From dfbcfb7b3c5f85995cac0f5d1d54cdf992a0827f Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Wed, 1 Feb 2023 15:56:44 +0200 Subject: [PATCH] Remove duplicated code from new files --- client/gui/CursorHandlerBase.cpp | 145 ------------ client/gui/CursorHandlerBase.h | 51 ----- client/gui/CursorHardware.cpp | 371 ------------------------------- client/gui/CursorHardware.h | 202 ----------------- client/gui/CursorSoftware.cpp | 350 ----------------------------- client/gui/CursorSoftware.h | 194 ---------------- client/gui/ICursor.h | 207 ----------------- 7 files changed, 1520 deletions(-) diff --git a/client/gui/CursorHandlerBase.cpp b/client/gui/CursorHandlerBase.cpp index b44cb3040..4d1760f7a 100644 --- a/client/gui/CursorHandlerBase.cpp +++ b/client/gui/CursorHandlerBase.cpp @@ -311,148 +311,3 @@ void CursorHandler::show() cursor->setVisible(true); } -void CursorSoftware::render() -{ - //texture must be updated in the main (renderer) thread, but changes to cursor type may come from other threads - if (needUpdate) - updateTexture(); - - Point renderPos = pos - pivot; - - SDL_Rect destRect; - destRect.x = renderPos.x; - destRect.y = renderPos.y; - destRect.w = 40; - destRect.h = 40; - - SDL_RenderCopy(mainRenderer, cursorTexture, nullptr, &destRect); -} - -void CursorSoftware::createTexture(const Point & dimensions) -{ - if(cursorTexture) - SDL_DestroyTexture(cursorTexture); - - if (cursorSurface) - SDL_FreeSurface(cursorSurface); - - cursorSurface = CSDL_Ext::newSurface(dimensions.x, dimensions.y); - cursorTexture = SDL_CreateTexture(mainRenderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, dimensions.x, dimensions.y); - - SDL_SetSurfaceBlendMode(cursorSurface, SDL_BLENDMODE_NONE); - SDL_SetTextureBlendMode(cursorTexture, SDL_BLENDMODE_BLEND); -} - -void CursorSoftware::updateTexture() -{ - Point dimensions(-1, -1); - - if (!cursorSurface || Point(cursorSurface->w, cursorSurface->h) != cursorImage->dimensions()) - createTexture(cursorImage->dimensions()); - - CSDL_Ext::fillSurface(cursorSurface, Colors::TRANSPARENCY); - - cursorImage->draw(cursorSurface); - SDL_UpdateTexture(cursorTexture, NULL, cursorSurface->pixels, cursorSurface->pitch); - needUpdate = false; -} - -void CursorSoftware::setImage(std::shared_ptr image, const Point & pivotOffset) -{ - assert(image != nullptr); - cursorImage = image; - pivot = pivotOffset; - needUpdate = true; -} - -void CursorSoftware::setCursorPosition( const Point & newPos ) -{ - pos = newPos; -} - -void CursorSoftware::setVisible(bool on) -{ - visible = on; -} - -CursorSoftware::CursorSoftware(): - cursorTexture(nullptr), - cursorSurface(nullptr), - needUpdate(false), - visible(false), - pivot(0,0) -{ - SDL_ShowCursor(SDL_DISABLE); -} - -CursorSoftware::~CursorSoftware() -{ - if(cursorTexture) - SDL_DestroyTexture(cursorTexture); - - if (cursorSurface) - SDL_FreeSurface(cursorSurface); -} - -CursorHardware::CursorHardware(): - cursor(nullptr) -{ - SDL_ShowCursor(SDL_DISABLE); -} - -CursorHardware::~CursorHardware() -{ - if(cursor) - SDL_FreeCursor(cursor); -} - -void CursorHardware::setVisible(bool on) -{ -#ifdef VCMI_APPLE - dispatch_async(dispatch_get_main_queue(), ^{ -#endif - if (on) - SDL_ShowCursor(SDL_ENABLE); - else - SDL_ShowCursor(SDL_DISABLE); -#ifdef VCMI_APPLE - }); -#endif -} - -void CursorHardware::setImage(std::shared_ptr image, const Point & pivotOffset) -{ - auto cursorSurface = CSDL_Ext::newSurface(image->dimensions().x, image->dimensions().y); - - CSDL_Ext::fillSurface(cursorSurface, Colors::TRANSPARENCY); - - image->draw(cursorSurface); - - auto oldCursor = cursor; - cursor = SDL_CreateColorCursor(cursorSurface, pivotOffset.x, pivotOffset.y); - - if (!cursor) - logGlobal->error("Failed to set cursor! SDL says %s", SDL_GetError()); - - SDL_FreeSurface(cursorSurface); -#ifdef VCMI_APPLE - dispatch_async(dispatch_get_main_queue(), ^{ -#endif - SDL_SetCursor(cursor); - - if (oldCursor) - SDL_FreeCursor(oldCursor); -#ifdef VCMI_APPLE - }); -#endif -} - -void CursorHardware::setCursorPosition( const Point & newPos ) -{ - //no-op -} - -void CursorHardware::render() -{ - //no-op -} diff --git a/client/gui/CursorHandlerBase.h b/client/gui/CursorHandlerBase.h index b66bfb92b..807f90164 100644 --- a/client/gui/CursorHandlerBase.h +++ b/client/gui/CursorHandlerBase.h @@ -112,57 +112,6 @@ namespace Cursor }; } -class ICursor -{ -public: - virtual ~ICursor() = default; - - virtual void setImage(std::shared_ptr image, const Point & pivotOffset) = 0; - virtual void setCursorPosition( const Point & newPos ) = 0; - virtual void render() = 0; - virtual void setVisible( bool on) = 0; -}; - -class CursorHardware : public ICursor -{ - std::shared_ptr cursorImage; - - SDL_Cursor * cursor; - -public: - CursorHardware(); - ~CursorHardware(); - - void setImage(std::shared_ptr image, const Point & pivotOffset) override; - void setCursorPosition( const Point & newPos ) override; - void render() override; - void setVisible( bool on) override; -}; - -class CursorSoftware : public ICursor -{ - std::shared_ptr cursorImage; - - SDL_Texture * cursorTexture; - SDL_Surface * cursorSurface; - - Point pos; - Point pivot; - bool needUpdate; - bool visible; - - void createTexture(const Point & dimensions); - void updateTexture(); -public: - CursorSoftware(); - ~CursorSoftware(); - - void setImage(std::shared_ptr image, const Point & pivotOffset) override; - void setCursorPosition( const Point & newPos ) override; - void render() override; - void setVisible( bool on) override; -}; - /// handles mouse cursor class CursorHandler final { diff --git a/client/gui/CursorHardware.cpp b/client/gui/CursorHardware.cpp index b44cb3040..a426f06a7 100644 --- a/client/gui/CursorHardware.cpp +++ b/client/gui/CursorHardware.cpp @@ -23,377 +23,6 @@ #include #endif -std::unique_ptr CursorHandler::createCursor() -{ - if (settings["video"]["cursor"].String() == "auto") - { -#if defined(VCMI_ANDROID) || defined(VCMI_IOS) - return std::make_unique(); -#else - return std::make_unique(); -#endif - } - - if (settings["video"]["cursor"].String() == "hardware") - return std::make_unique(); - - assert(settings["video"]["cursor"].String() == "software"); - return std::make_unique(); -} - -CursorHandler::CursorHandler() - : cursor(createCursor()) - , frameTime(0.f) - , showing(false) - , pos(0,0) -{ - - type = Cursor::Type::DEFAULT; - dndObject = nullptr; - - cursors = - { - std::make_unique("CRADVNTR"), - std::make_unique("CRCOMBAT"), - std::make_unique("CRDEFLT"), - std::make_unique("CRSPELL") - }; - - for (auto & cursor : cursors) - cursor->preload(); - - set(Cursor::Map::POINTER); -} - -Point CursorHandler::position() const -{ - return pos; -} - -void CursorHandler::changeGraphic(Cursor::Type type, size_t index) -{ - assert(dndObject == nullptr); - - if (type == this->type && index == this->frame) - return; - - this->type = type; - this->frame = index; - - cursor->setImage(getCurrentImage(), getPivotOffset()); -} - -void CursorHandler::set(Cursor::Default index) -{ - changeGraphic(Cursor::Type::DEFAULT, static_cast(index)); -} - -void CursorHandler::set(Cursor::Map index) -{ - changeGraphic(Cursor::Type::ADVENTURE, static_cast(index)); -} - -void CursorHandler::set(Cursor::Combat index) -{ - changeGraphic(Cursor::Type::COMBAT, static_cast(index)); -} - -void CursorHandler::set(Cursor::Spellcast index) -{ - //Note: this is animated cursor, ignore specified frame and only change type - changeGraphic(Cursor::Type::SPELLBOOK, frame); -} - -void CursorHandler::dragAndDropCursor(std::shared_ptr image) -{ - dndObject = image; - cursor->setImage(getCurrentImage(), getPivotOffset()); -} - -void CursorHandler::dragAndDropCursor (std::string path, size_t index) -{ - CAnimation anim(path); - anim.load(index); - dragAndDropCursor(anim.getImage(index)); -} - -void CursorHandler::cursorMove(const int & x, const int & y) -{ - pos.x = x; - pos.y = y; - - cursor->setCursorPosition(pos); -} - -Point CursorHandler::getPivotOffsetDefault(size_t index) -{ - return {0, 0}; -} - -Point CursorHandler::getPivotOffsetMap(size_t index) -{ - static const std::array offsets = {{ - { 0, 0}, // POINTER = 0, - { 0, 0}, // HOURGLASS = 1, - { 12, 10}, // HERO = 2, - { 12, 12}, // TOWN = 3, - - { 15, 13}, // T1_MOVE = 4, - { 13, 13}, // T1_ATTACK = 5, - { 16, 32}, // T1_SAIL = 6, - { 13, 20}, // T1_DISEMBARK = 7, - { 8, 9}, // T1_EXCHANGE = 8, - { 14, 16}, // T1_VISIT = 9, - - { 15, 13}, // T2_MOVE = 10, - { 13, 13}, // T2_ATTACK = 11, - { 16, 32}, // T2_SAIL = 12, - { 13, 20}, // T2_DISEMBARK = 13, - { 8, 9}, // T2_EXCHANGE = 14, - { 14, 16}, // T2_VISIT = 15, - - { 15, 13}, // T3_MOVE = 16, - { 13, 13}, // T3_ATTACK = 17, - { 16, 32}, // T3_SAIL = 18, - { 13, 20}, // T3_DISEMBARK = 19, - { 8, 9}, // T3_EXCHANGE = 20, - { 14, 16}, // T3_VISIT = 21, - - { 15, 13}, // T4_MOVE = 22, - { 13, 13}, // T4_ATTACK = 23, - { 16, 32}, // T4_SAIL = 24, - { 13, 20}, // T4_DISEMBARK = 25, - { 8, 9}, // T4_EXCHANGE = 26, - { 14, 16}, // T4_VISIT = 27, - - { 16, 32}, // T1_SAIL_VISIT = 28, - { 16, 32}, // T2_SAIL_VISIT = 29, - { 16, 32}, // T3_SAIL_VISIT = 30, - { 16, 32}, // T4_SAIL_VISIT = 31, - - { 6, 1}, // SCROLL_NORTH = 32, - { 16, 2}, // SCROLL_NORTHEAST = 33, - { 21, 6}, // SCROLL_EAST = 34, - { 16, 16}, // SCROLL_SOUTHEAST = 35, - { 6, 21}, // SCROLL_SOUTH = 36, - { 1, 16}, // SCROLL_SOUTHWEST = 37, - { 1, 5}, // SCROLL_WEST = 38, - { 2, 1}, // SCROLL_NORTHWEST = 39, - - { 0, 0}, // POINTER_COPY = 40, - { 14, 16}, // TELEPORT = 41, - { 20, 20}, // SCUTTLE_BOAT = 42 - }}; - - assert(offsets.size() == size_t(Cursor::Map::COUNT)); //Invalid number of pivot offsets for cursor - assert(index < offsets.size()); - return offsets[index]; -} - -Point CursorHandler::getPivotOffsetCombat(size_t index) -{ - static const std::array offsets = {{ - { 12, 12 }, // BLOCKED = 0, - { 10, 14 }, // MOVE = 1, - { 14, 14 }, // FLY = 2, - { 12, 12 }, // SHOOT = 3, - { 12, 12 }, // HERO = 4, - { 8, 12 }, // QUERY = 5, - { 0, 0 }, // POINTER = 6, - { 21, 0 }, // HIT_NORTHEAST = 7, - { 31, 5 }, // HIT_EAST = 8, - { 21, 21 }, // HIT_SOUTHEAST = 9, - { 0, 21 }, // HIT_SOUTHWEST = 10, - { 0, 5 }, // HIT_WEST = 11, - { 0, 0 }, // HIT_NORTHWEST = 12, - { 6, 0 }, // HIT_NORTH = 13, - { 6, 31 }, // HIT_SOUTH = 14, - { 14, 0 }, // SHOOT_PENALTY = 15, - { 12, 12 }, // SHOOT_CATAPULT = 16, - { 12, 12 }, // HEAL = 17, - { 12, 12 }, // SACRIFICE = 18, - { 14, 20 }, // TELEPORT = 19 - }}; - - assert(offsets.size() == size_t(Cursor::Combat::COUNT)); //Invalid number of pivot offsets for cursor - assert(index < offsets.size()); - return offsets[index]; -} - -Point CursorHandler::getPivotOffsetSpellcast() -{ - return { 18, 28}; -} - -Point CursorHandler::getPivotOffset() -{ - if (dndObject) - return dndObject->dimensions() / 2; - - switch (type) { - case Cursor::Type::ADVENTURE: return getPivotOffsetMap(frame); - case Cursor::Type::COMBAT: return getPivotOffsetCombat(frame); - case Cursor::Type::DEFAULT: return getPivotOffsetDefault(frame); - case Cursor::Type::SPELLBOOK: return getPivotOffsetSpellcast(); - }; - - assert(0); - return {0, 0}; -} - -std::shared_ptr CursorHandler::getCurrentImage() -{ - if (dndObject) - return dndObject; - - return cursors[static_cast(type)]->getImage(frame); -} - -void CursorHandler::centerCursor() -{ - Point screenSize {screen->w, screen->h}; - pos = screenSize / 2 - getPivotOffset(); - - SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE); - CSDL_Ext::warpMouse(pos.x, pos.y); - SDL_EventState(SDL_MOUSEMOTION, SDL_ENABLE); - - cursor->setCursorPosition(pos); -} - -void CursorHandler::updateSpellcastCursor() -{ - static const float frameDisplayDuration = 0.1f; // H3 uses 100 ms per frame - - frameTime += GH.mainFPSmng->getElapsedMilliseconds() / 1000.f; - size_t newFrame = frame; - - while (frameTime >= frameDisplayDuration) - { - frameTime -= frameDisplayDuration; - newFrame++; - } - - auto & animation = cursors.at(static_cast(type)); - - while (newFrame >= animation->size()) - newFrame -= animation->size(); - - changeGraphic(Cursor::Type::SPELLBOOK, newFrame); -} - -void CursorHandler::render() -{ - if(!showing) - return; - - if (type == Cursor::Type::SPELLBOOK) - updateSpellcastCursor(); - - cursor->render(); -} - -void CursorHandler::hide() -{ - if (!showing) - return; - - showing = false; - cursor->setVisible(false); -} - -void CursorHandler::show() -{ - if (showing) - return; - - showing = true; - cursor->setVisible(true); -} - -void CursorSoftware::render() -{ - //texture must be updated in the main (renderer) thread, but changes to cursor type may come from other threads - if (needUpdate) - updateTexture(); - - Point renderPos = pos - pivot; - - SDL_Rect destRect; - destRect.x = renderPos.x; - destRect.y = renderPos.y; - destRect.w = 40; - destRect.h = 40; - - SDL_RenderCopy(mainRenderer, cursorTexture, nullptr, &destRect); -} - -void CursorSoftware::createTexture(const Point & dimensions) -{ - if(cursorTexture) - SDL_DestroyTexture(cursorTexture); - - if (cursorSurface) - SDL_FreeSurface(cursorSurface); - - cursorSurface = CSDL_Ext::newSurface(dimensions.x, dimensions.y); - cursorTexture = SDL_CreateTexture(mainRenderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, dimensions.x, dimensions.y); - - SDL_SetSurfaceBlendMode(cursorSurface, SDL_BLENDMODE_NONE); - SDL_SetTextureBlendMode(cursorTexture, SDL_BLENDMODE_BLEND); -} - -void CursorSoftware::updateTexture() -{ - Point dimensions(-1, -1); - - if (!cursorSurface || Point(cursorSurface->w, cursorSurface->h) != cursorImage->dimensions()) - createTexture(cursorImage->dimensions()); - - CSDL_Ext::fillSurface(cursorSurface, Colors::TRANSPARENCY); - - cursorImage->draw(cursorSurface); - SDL_UpdateTexture(cursorTexture, NULL, cursorSurface->pixels, cursorSurface->pitch); - needUpdate = false; -} - -void CursorSoftware::setImage(std::shared_ptr image, const Point & pivotOffset) -{ - assert(image != nullptr); - cursorImage = image; - pivot = pivotOffset; - needUpdate = true; -} - -void CursorSoftware::setCursorPosition( const Point & newPos ) -{ - pos = newPos; -} - -void CursorSoftware::setVisible(bool on) -{ - visible = on; -} - -CursorSoftware::CursorSoftware(): - cursorTexture(nullptr), - cursorSurface(nullptr), - needUpdate(false), - visible(false), - pivot(0,0) -{ - SDL_ShowCursor(SDL_DISABLE); -} - -CursorSoftware::~CursorSoftware() -{ - if(cursorTexture) - SDL_DestroyTexture(cursorTexture); - - if (cursorSurface) - SDL_FreeSurface(cursorSurface); -} - CursorHardware::CursorHardware(): cursor(nullptr) { diff --git a/client/gui/CursorHardware.h b/client/gui/CursorHardware.h index b66bfb92b..7e299130a 100644 --- a/client/gui/CursorHardware.h +++ b/client/gui/CursorHardware.h @@ -17,112 +17,6 @@ struct SDL_Cursor; #include "../../lib/Point.h" -namespace Cursor -{ - enum class Type { - ADVENTURE, // set of various cursors for adventure map - COMBAT, // set of various cursors for combat - DEFAULT, // default arrow and hourglass cursors - SPELLBOOK // animated cursor for spellcasting - }; - - enum class Default { - POINTER = 0, - //ARROW_COPY = 1, // probably unused - HOURGLASS = 2, - }; - - enum class Combat { - INVALID = -1, - - BLOCKED = 0, - MOVE = 1, - FLY = 2, - SHOOT = 3, - HERO = 4, - QUERY = 5, - POINTER = 6, - HIT_NORTHEAST = 7, - HIT_EAST = 8, - HIT_SOUTHEAST = 9, - HIT_SOUTHWEST = 10, - HIT_WEST = 11, - HIT_NORTHWEST = 12, - HIT_NORTH = 13, - HIT_SOUTH = 14, - SHOOT_PENALTY = 15, - SHOOT_CATAPULT = 16, - HEAL = 17, - SACRIFICE = 18, - TELEPORT = 19, - - COUNT - }; - - enum class Map { - POINTER = 0, - HOURGLASS = 1, - HERO = 2, - TOWN = 3, - T1_MOVE = 4, - T1_ATTACK = 5, - T1_SAIL = 6, - T1_DISEMBARK = 7, - T1_EXCHANGE = 8, - T1_VISIT = 9, - T2_MOVE = 10, - T2_ATTACK = 11, - T2_SAIL = 12, - T2_DISEMBARK = 13, - T2_EXCHANGE = 14, - T2_VISIT = 15, - T3_MOVE = 16, - T3_ATTACK = 17, - T3_SAIL = 18, - T3_DISEMBARK = 19, - T3_EXCHANGE = 20, - T3_VISIT = 21, - T4_MOVE = 22, - T4_ATTACK = 23, - T4_SAIL = 24, - T4_DISEMBARK = 25, - T4_EXCHANGE = 26, - T4_VISIT = 27, - T1_SAIL_VISIT = 28, - T2_SAIL_VISIT = 29, - T3_SAIL_VISIT = 30, - T4_SAIL_VISIT = 31, - SCROLL_NORTH = 32, - SCROLL_NORTHEAST = 33, - SCROLL_EAST = 34, - SCROLL_SOUTHEAST = 35, - SCROLL_SOUTH = 36, - SCROLL_SOUTHWEST = 37, - SCROLL_WEST = 38, - SCROLL_NORTHWEST = 39, - //POINTER_COPY = 40, // probably unused - TELEPORT = 41, - SCUTTLE_BOAT = 42, - - COUNT - }; - - enum class Spellcast { - SPELL = 0, - }; -} - -class ICursor -{ -public: - virtual ~ICursor() = default; - - virtual void setImage(std::shared_ptr image, const Point & pivotOffset) = 0; - virtual void setCursorPosition( const Point & newPos ) = 0; - virtual void render() = 0; - virtual void setVisible( bool on) = 0; -}; - class CursorHardware : public ICursor { std::shared_ptr cursorImage; @@ -139,99 +33,3 @@ public: void setVisible( bool on) override; }; -class CursorSoftware : public ICursor -{ - std::shared_ptr cursorImage; - - SDL_Texture * cursorTexture; - SDL_Surface * cursorSurface; - - Point pos; - Point pivot; - bool needUpdate; - bool visible; - - void createTexture(const Point & dimensions); - void updateTexture(); -public: - CursorSoftware(); - ~CursorSoftware(); - - void setImage(std::shared_ptr image, const Point & pivotOffset) override; - void setCursorPosition( const Point & newPos ) override; - void render() override; - void setVisible( bool on) override; -}; - -/// handles mouse cursor -class CursorHandler final -{ - std::shared_ptr dndObject; //if set, overrides currentCursor - - std::array, 4> cursors; - - bool showing; - - /// Current cursor - Cursor::Type type; - size_t frame; - float frameTime; - Point pos; - - void changeGraphic(Cursor::Type type, size_t index); - - Point getPivotOffsetDefault(size_t index); - Point getPivotOffsetMap(size_t index); - Point getPivotOffsetCombat(size_t index); - Point getPivotOffsetSpellcast(); - Point getPivotOffset(); - - void updateSpellcastCursor(); - - std::shared_ptr getCurrentImage(); - - std::unique_ptr cursor; - - static std::unique_ptr createCursor(); -public: - CursorHandler(); - ~CursorHandler(); - - /// Replaces the cursor with a custom image. - /// @param image Image to replace cursor with or nullptr to use the normal cursor. - void dragAndDropCursor(std::shared_ptr image); - - void dragAndDropCursor(std::string path, size_t index); - - /// Returns current position of the cursor - Point position() const; - - /// Changes cursor to specified index - void set(Cursor::Default index); - void set(Cursor::Map index); - void set(Cursor::Combat index); - void set(Cursor::Spellcast index); - - /// Returns current index of cursor - template - Index get() - { - assert((std::is_same::value )|| type != Cursor::Type::DEFAULT ); - assert((std::is_same::value )|| type != Cursor::Type::ADVENTURE ); - assert((std::is_same::value )|| type != Cursor::Type::COMBAT ); - assert((std::is_same::value )|| type != Cursor::Type::SPELLBOOK ); - - return static_cast(frame); - } - - void render(); - - void hide(); - void show(); - - /// change cursor's positions to (x, y) - void cursorMove(const int & x, const int & y); - /// Move cursor to screen center - void centerCursor(); - -}; diff --git a/client/gui/CursorSoftware.cpp b/client/gui/CursorSoftware.cpp index b44cb3040..f6ee7f9ac 100644 --- a/client/gui/CursorSoftware.cpp +++ b/client/gui/CursorSoftware.cpp @@ -23,294 +23,6 @@ #include #endif -std::unique_ptr CursorHandler::createCursor() -{ - if (settings["video"]["cursor"].String() == "auto") - { -#if defined(VCMI_ANDROID) || defined(VCMI_IOS) - return std::make_unique(); -#else - return std::make_unique(); -#endif - } - - if (settings["video"]["cursor"].String() == "hardware") - return std::make_unique(); - - assert(settings["video"]["cursor"].String() == "software"); - return std::make_unique(); -} - -CursorHandler::CursorHandler() - : cursor(createCursor()) - , frameTime(0.f) - , showing(false) - , pos(0,0) -{ - - type = Cursor::Type::DEFAULT; - dndObject = nullptr; - - cursors = - { - std::make_unique("CRADVNTR"), - std::make_unique("CRCOMBAT"), - std::make_unique("CRDEFLT"), - std::make_unique("CRSPELL") - }; - - for (auto & cursor : cursors) - cursor->preload(); - - set(Cursor::Map::POINTER); -} - -Point CursorHandler::position() const -{ - return pos; -} - -void CursorHandler::changeGraphic(Cursor::Type type, size_t index) -{ - assert(dndObject == nullptr); - - if (type == this->type && index == this->frame) - return; - - this->type = type; - this->frame = index; - - cursor->setImage(getCurrentImage(), getPivotOffset()); -} - -void CursorHandler::set(Cursor::Default index) -{ - changeGraphic(Cursor::Type::DEFAULT, static_cast(index)); -} - -void CursorHandler::set(Cursor::Map index) -{ - changeGraphic(Cursor::Type::ADVENTURE, static_cast(index)); -} - -void CursorHandler::set(Cursor::Combat index) -{ - changeGraphic(Cursor::Type::COMBAT, static_cast(index)); -} - -void CursorHandler::set(Cursor::Spellcast index) -{ - //Note: this is animated cursor, ignore specified frame and only change type - changeGraphic(Cursor::Type::SPELLBOOK, frame); -} - -void CursorHandler::dragAndDropCursor(std::shared_ptr image) -{ - dndObject = image; - cursor->setImage(getCurrentImage(), getPivotOffset()); -} - -void CursorHandler::dragAndDropCursor (std::string path, size_t index) -{ - CAnimation anim(path); - anim.load(index); - dragAndDropCursor(anim.getImage(index)); -} - -void CursorHandler::cursorMove(const int & x, const int & y) -{ - pos.x = x; - pos.y = y; - - cursor->setCursorPosition(pos); -} - -Point CursorHandler::getPivotOffsetDefault(size_t index) -{ - return {0, 0}; -} - -Point CursorHandler::getPivotOffsetMap(size_t index) -{ - static const std::array offsets = {{ - { 0, 0}, // POINTER = 0, - { 0, 0}, // HOURGLASS = 1, - { 12, 10}, // HERO = 2, - { 12, 12}, // TOWN = 3, - - { 15, 13}, // T1_MOVE = 4, - { 13, 13}, // T1_ATTACK = 5, - { 16, 32}, // T1_SAIL = 6, - { 13, 20}, // T1_DISEMBARK = 7, - { 8, 9}, // T1_EXCHANGE = 8, - { 14, 16}, // T1_VISIT = 9, - - { 15, 13}, // T2_MOVE = 10, - { 13, 13}, // T2_ATTACK = 11, - { 16, 32}, // T2_SAIL = 12, - { 13, 20}, // T2_DISEMBARK = 13, - { 8, 9}, // T2_EXCHANGE = 14, - { 14, 16}, // T2_VISIT = 15, - - { 15, 13}, // T3_MOVE = 16, - { 13, 13}, // T3_ATTACK = 17, - { 16, 32}, // T3_SAIL = 18, - { 13, 20}, // T3_DISEMBARK = 19, - { 8, 9}, // T3_EXCHANGE = 20, - { 14, 16}, // T3_VISIT = 21, - - { 15, 13}, // T4_MOVE = 22, - { 13, 13}, // T4_ATTACK = 23, - { 16, 32}, // T4_SAIL = 24, - { 13, 20}, // T4_DISEMBARK = 25, - { 8, 9}, // T4_EXCHANGE = 26, - { 14, 16}, // T4_VISIT = 27, - - { 16, 32}, // T1_SAIL_VISIT = 28, - { 16, 32}, // T2_SAIL_VISIT = 29, - { 16, 32}, // T3_SAIL_VISIT = 30, - { 16, 32}, // T4_SAIL_VISIT = 31, - - { 6, 1}, // SCROLL_NORTH = 32, - { 16, 2}, // SCROLL_NORTHEAST = 33, - { 21, 6}, // SCROLL_EAST = 34, - { 16, 16}, // SCROLL_SOUTHEAST = 35, - { 6, 21}, // SCROLL_SOUTH = 36, - { 1, 16}, // SCROLL_SOUTHWEST = 37, - { 1, 5}, // SCROLL_WEST = 38, - { 2, 1}, // SCROLL_NORTHWEST = 39, - - { 0, 0}, // POINTER_COPY = 40, - { 14, 16}, // TELEPORT = 41, - { 20, 20}, // SCUTTLE_BOAT = 42 - }}; - - assert(offsets.size() == size_t(Cursor::Map::COUNT)); //Invalid number of pivot offsets for cursor - assert(index < offsets.size()); - return offsets[index]; -} - -Point CursorHandler::getPivotOffsetCombat(size_t index) -{ - static const std::array offsets = {{ - { 12, 12 }, // BLOCKED = 0, - { 10, 14 }, // MOVE = 1, - { 14, 14 }, // FLY = 2, - { 12, 12 }, // SHOOT = 3, - { 12, 12 }, // HERO = 4, - { 8, 12 }, // QUERY = 5, - { 0, 0 }, // POINTER = 6, - { 21, 0 }, // HIT_NORTHEAST = 7, - { 31, 5 }, // HIT_EAST = 8, - { 21, 21 }, // HIT_SOUTHEAST = 9, - { 0, 21 }, // HIT_SOUTHWEST = 10, - { 0, 5 }, // HIT_WEST = 11, - { 0, 0 }, // HIT_NORTHWEST = 12, - { 6, 0 }, // HIT_NORTH = 13, - { 6, 31 }, // HIT_SOUTH = 14, - { 14, 0 }, // SHOOT_PENALTY = 15, - { 12, 12 }, // SHOOT_CATAPULT = 16, - { 12, 12 }, // HEAL = 17, - { 12, 12 }, // SACRIFICE = 18, - { 14, 20 }, // TELEPORT = 19 - }}; - - assert(offsets.size() == size_t(Cursor::Combat::COUNT)); //Invalid number of pivot offsets for cursor - assert(index < offsets.size()); - return offsets[index]; -} - -Point CursorHandler::getPivotOffsetSpellcast() -{ - return { 18, 28}; -} - -Point CursorHandler::getPivotOffset() -{ - if (dndObject) - return dndObject->dimensions() / 2; - - switch (type) { - case Cursor::Type::ADVENTURE: return getPivotOffsetMap(frame); - case Cursor::Type::COMBAT: return getPivotOffsetCombat(frame); - case Cursor::Type::DEFAULT: return getPivotOffsetDefault(frame); - case Cursor::Type::SPELLBOOK: return getPivotOffsetSpellcast(); - }; - - assert(0); - return {0, 0}; -} - -std::shared_ptr CursorHandler::getCurrentImage() -{ - if (dndObject) - return dndObject; - - return cursors[static_cast(type)]->getImage(frame); -} - -void CursorHandler::centerCursor() -{ - Point screenSize {screen->w, screen->h}; - pos = screenSize / 2 - getPivotOffset(); - - SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE); - CSDL_Ext::warpMouse(pos.x, pos.y); - SDL_EventState(SDL_MOUSEMOTION, SDL_ENABLE); - - cursor->setCursorPosition(pos); -} - -void CursorHandler::updateSpellcastCursor() -{ - static const float frameDisplayDuration = 0.1f; // H3 uses 100 ms per frame - - frameTime += GH.mainFPSmng->getElapsedMilliseconds() / 1000.f; - size_t newFrame = frame; - - while (frameTime >= frameDisplayDuration) - { - frameTime -= frameDisplayDuration; - newFrame++; - } - - auto & animation = cursors.at(static_cast(type)); - - while (newFrame >= animation->size()) - newFrame -= animation->size(); - - changeGraphic(Cursor::Type::SPELLBOOK, newFrame); -} - -void CursorHandler::render() -{ - if(!showing) - return; - - if (type == Cursor::Type::SPELLBOOK) - updateSpellcastCursor(); - - cursor->render(); -} - -void CursorHandler::hide() -{ - if (!showing) - return; - - showing = false; - cursor->setVisible(false); -} - -void CursorHandler::show() -{ - if (showing) - return; - - showing = true; - cursor->setVisible(true); -} - void CursorSoftware::render() { //texture must be updated in the main (renderer) thread, but changes to cursor type may come from other threads @@ -394,65 +106,3 @@ CursorSoftware::~CursorSoftware() SDL_FreeSurface(cursorSurface); } -CursorHardware::CursorHardware(): - cursor(nullptr) -{ - SDL_ShowCursor(SDL_DISABLE); -} - -CursorHardware::~CursorHardware() -{ - if(cursor) - SDL_FreeCursor(cursor); -} - -void CursorHardware::setVisible(bool on) -{ -#ifdef VCMI_APPLE - dispatch_async(dispatch_get_main_queue(), ^{ -#endif - if (on) - SDL_ShowCursor(SDL_ENABLE); - else - SDL_ShowCursor(SDL_DISABLE); -#ifdef VCMI_APPLE - }); -#endif -} - -void CursorHardware::setImage(std::shared_ptr image, const Point & pivotOffset) -{ - auto cursorSurface = CSDL_Ext::newSurface(image->dimensions().x, image->dimensions().y); - - CSDL_Ext::fillSurface(cursorSurface, Colors::TRANSPARENCY); - - image->draw(cursorSurface); - - auto oldCursor = cursor; - cursor = SDL_CreateColorCursor(cursorSurface, pivotOffset.x, pivotOffset.y); - - if (!cursor) - logGlobal->error("Failed to set cursor! SDL says %s", SDL_GetError()); - - SDL_FreeSurface(cursorSurface); -#ifdef VCMI_APPLE - dispatch_async(dispatch_get_main_queue(), ^{ -#endif - SDL_SetCursor(cursor); - - if (oldCursor) - SDL_FreeCursor(oldCursor); -#ifdef VCMI_APPLE - }); -#endif -} - -void CursorHardware::setCursorPosition( const Point & newPos ) -{ - //no-op -} - -void CursorHardware::render() -{ - //no-op -} diff --git a/client/gui/CursorSoftware.h b/client/gui/CursorSoftware.h index b66bfb92b..f61b5139c 100644 --- a/client/gui/CursorSoftware.h +++ b/client/gui/CursorSoftware.h @@ -17,128 +17,6 @@ struct SDL_Cursor; #include "../../lib/Point.h" -namespace Cursor -{ - enum class Type { - ADVENTURE, // set of various cursors for adventure map - COMBAT, // set of various cursors for combat - DEFAULT, // default arrow and hourglass cursors - SPELLBOOK // animated cursor for spellcasting - }; - - enum class Default { - POINTER = 0, - //ARROW_COPY = 1, // probably unused - HOURGLASS = 2, - }; - - enum class Combat { - INVALID = -1, - - BLOCKED = 0, - MOVE = 1, - FLY = 2, - SHOOT = 3, - HERO = 4, - QUERY = 5, - POINTER = 6, - HIT_NORTHEAST = 7, - HIT_EAST = 8, - HIT_SOUTHEAST = 9, - HIT_SOUTHWEST = 10, - HIT_WEST = 11, - HIT_NORTHWEST = 12, - HIT_NORTH = 13, - HIT_SOUTH = 14, - SHOOT_PENALTY = 15, - SHOOT_CATAPULT = 16, - HEAL = 17, - SACRIFICE = 18, - TELEPORT = 19, - - COUNT - }; - - enum class Map { - POINTER = 0, - HOURGLASS = 1, - HERO = 2, - TOWN = 3, - T1_MOVE = 4, - T1_ATTACK = 5, - T1_SAIL = 6, - T1_DISEMBARK = 7, - T1_EXCHANGE = 8, - T1_VISIT = 9, - T2_MOVE = 10, - T2_ATTACK = 11, - T2_SAIL = 12, - T2_DISEMBARK = 13, - T2_EXCHANGE = 14, - T2_VISIT = 15, - T3_MOVE = 16, - T3_ATTACK = 17, - T3_SAIL = 18, - T3_DISEMBARK = 19, - T3_EXCHANGE = 20, - T3_VISIT = 21, - T4_MOVE = 22, - T4_ATTACK = 23, - T4_SAIL = 24, - T4_DISEMBARK = 25, - T4_EXCHANGE = 26, - T4_VISIT = 27, - T1_SAIL_VISIT = 28, - T2_SAIL_VISIT = 29, - T3_SAIL_VISIT = 30, - T4_SAIL_VISIT = 31, - SCROLL_NORTH = 32, - SCROLL_NORTHEAST = 33, - SCROLL_EAST = 34, - SCROLL_SOUTHEAST = 35, - SCROLL_SOUTH = 36, - SCROLL_SOUTHWEST = 37, - SCROLL_WEST = 38, - SCROLL_NORTHWEST = 39, - //POINTER_COPY = 40, // probably unused - TELEPORT = 41, - SCUTTLE_BOAT = 42, - - COUNT - }; - - enum class Spellcast { - SPELL = 0, - }; -} - -class ICursor -{ -public: - virtual ~ICursor() = default; - - virtual void setImage(std::shared_ptr image, const Point & pivotOffset) = 0; - virtual void setCursorPosition( const Point & newPos ) = 0; - virtual void render() = 0; - virtual void setVisible( bool on) = 0; -}; - -class CursorHardware : public ICursor -{ - std::shared_ptr cursorImage; - - SDL_Cursor * cursor; - -public: - CursorHardware(); - ~CursorHardware(); - - void setImage(std::shared_ptr image, const Point & pivotOffset) override; - void setCursorPosition( const Point & newPos ) override; - void render() override; - void setVisible( bool on) override; -}; - class CursorSoftware : public ICursor { std::shared_ptr cursorImage; @@ -163,75 +41,3 @@ public: void setVisible( bool on) override; }; -/// handles mouse cursor -class CursorHandler final -{ - std::shared_ptr dndObject; //if set, overrides currentCursor - - std::array, 4> cursors; - - bool showing; - - /// Current cursor - Cursor::Type type; - size_t frame; - float frameTime; - Point pos; - - void changeGraphic(Cursor::Type type, size_t index); - - Point getPivotOffsetDefault(size_t index); - Point getPivotOffsetMap(size_t index); - Point getPivotOffsetCombat(size_t index); - Point getPivotOffsetSpellcast(); - Point getPivotOffset(); - - void updateSpellcastCursor(); - - std::shared_ptr getCurrentImage(); - - std::unique_ptr cursor; - - static std::unique_ptr createCursor(); -public: - CursorHandler(); - ~CursorHandler(); - - /// Replaces the cursor with a custom image. - /// @param image Image to replace cursor with or nullptr to use the normal cursor. - void dragAndDropCursor(std::shared_ptr image); - - void dragAndDropCursor(std::string path, size_t index); - - /// Returns current position of the cursor - Point position() const; - - /// Changes cursor to specified index - void set(Cursor::Default index); - void set(Cursor::Map index); - void set(Cursor::Combat index); - void set(Cursor::Spellcast index); - - /// Returns current index of cursor - template - Index get() - { - assert((std::is_same::value )|| type != Cursor::Type::DEFAULT ); - assert((std::is_same::value )|| type != Cursor::Type::ADVENTURE ); - assert((std::is_same::value )|| type != Cursor::Type::COMBAT ); - assert((std::is_same::value )|| type != Cursor::Type::SPELLBOOK ); - - return static_cast(frame); - } - - void render(); - - void hide(); - void show(); - - /// change cursor's positions to (x, y) - void cursorMove(const int & x, const int & y); - /// Move cursor to screen center - void centerCursor(); - -}; diff --git a/client/gui/ICursor.h b/client/gui/ICursor.h index b66bfb92b..8951a18b6 100644 --- a/client/gui/ICursor.h +++ b/client/gui/ICursor.h @@ -17,101 +17,6 @@ struct SDL_Cursor; #include "../../lib/Point.h" -namespace Cursor -{ - enum class Type { - ADVENTURE, // set of various cursors for adventure map - COMBAT, // set of various cursors for combat - DEFAULT, // default arrow and hourglass cursors - SPELLBOOK // animated cursor for spellcasting - }; - - enum class Default { - POINTER = 0, - //ARROW_COPY = 1, // probably unused - HOURGLASS = 2, - }; - - enum class Combat { - INVALID = -1, - - BLOCKED = 0, - MOVE = 1, - FLY = 2, - SHOOT = 3, - HERO = 4, - QUERY = 5, - POINTER = 6, - HIT_NORTHEAST = 7, - HIT_EAST = 8, - HIT_SOUTHEAST = 9, - HIT_SOUTHWEST = 10, - HIT_WEST = 11, - HIT_NORTHWEST = 12, - HIT_NORTH = 13, - HIT_SOUTH = 14, - SHOOT_PENALTY = 15, - SHOOT_CATAPULT = 16, - HEAL = 17, - SACRIFICE = 18, - TELEPORT = 19, - - COUNT - }; - - enum class Map { - POINTER = 0, - HOURGLASS = 1, - HERO = 2, - TOWN = 3, - T1_MOVE = 4, - T1_ATTACK = 5, - T1_SAIL = 6, - T1_DISEMBARK = 7, - T1_EXCHANGE = 8, - T1_VISIT = 9, - T2_MOVE = 10, - T2_ATTACK = 11, - T2_SAIL = 12, - T2_DISEMBARK = 13, - T2_EXCHANGE = 14, - T2_VISIT = 15, - T3_MOVE = 16, - T3_ATTACK = 17, - T3_SAIL = 18, - T3_DISEMBARK = 19, - T3_EXCHANGE = 20, - T3_VISIT = 21, - T4_MOVE = 22, - T4_ATTACK = 23, - T4_SAIL = 24, - T4_DISEMBARK = 25, - T4_EXCHANGE = 26, - T4_VISIT = 27, - T1_SAIL_VISIT = 28, - T2_SAIL_VISIT = 29, - T3_SAIL_VISIT = 30, - T4_SAIL_VISIT = 31, - SCROLL_NORTH = 32, - SCROLL_NORTHEAST = 33, - SCROLL_EAST = 34, - SCROLL_SOUTHEAST = 35, - SCROLL_SOUTH = 36, - SCROLL_SOUTHWEST = 37, - SCROLL_WEST = 38, - SCROLL_NORTHWEST = 39, - //POINTER_COPY = 40, // probably unused - TELEPORT = 41, - SCUTTLE_BOAT = 42, - - COUNT - }; - - enum class Spellcast { - SPELL = 0, - }; -} - class ICursor { public: @@ -123,115 +28,3 @@ public: virtual void setVisible( bool on) = 0; }; -class CursorHardware : public ICursor -{ - std::shared_ptr cursorImage; - - SDL_Cursor * cursor; - -public: - CursorHardware(); - ~CursorHardware(); - - void setImage(std::shared_ptr image, const Point & pivotOffset) override; - void setCursorPosition( const Point & newPos ) override; - void render() override; - void setVisible( bool on) override; -}; - -class CursorSoftware : public ICursor -{ - std::shared_ptr cursorImage; - - SDL_Texture * cursorTexture; - SDL_Surface * cursorSurface; - - Point pos; - Point pivot; - bool needUpdate; - bool visible; - - void createTexture(const Point & dimensions); - void updateTexture(); -public: - CursorSoftware(); - ~CursorSoftware(); - - void setImage(std::shared_ptr image, const Point & pivotOffset) override; - void setCursorPosition( const Point & newPos ) override; - void render() override; - void setVisible( bool on) override; -}; - -/// handles mouse cursor -class CursorHandler final -{ - std::shared_ptr dndObject; //if set, overrides currentCursor - - std::array, 4> cursors; - - bool showing; - - /// Current cursor - Cursor::Type type; - size_t frame; - float frameTime; - Point pos; - - void changeGraphic(Cursor::Type type, size_t index); - - Point getPivotOffsetDefault(size_t index); - Point getPivotOffsetMap(size_t index); - Point getPivotOffsetCombat(size_t index); - Point getPivotOffsetSpellcast(); - Point getPivotOffset(); - - void updateSpellcastCursor(); - - std::shared_ptr getCurrentImage(); - - std::unique_ptr cursor; - - static std::unique_ptr createCursor(); -public: - CursorHandler(); - ~CursorHandler(); - - /// Replaces the cursor with a custom image. - /// @param image Image to replace cursor with or nullptr to use the normal cursor. - void dragAndDropCursor(std::shared_ptr image); - - void dragAndDropCursor(std::string path, size_t index); - - /// Returns current position of the cursor - Point position() const; - - /// Changes cursor to specified index - void set(Cursor::Default index); - void set(Cursor::Map index); - void set(Cursor::Combat index); - void set(Cursor::Spellcast index); - - /// Returns current index of cursor - template - Index get() - { - assert((std::is_same::value )|| type != Cursor::Type::DEFAULT ); - assert((std::is_same::value )|| type != Cursor::Type::ADVENTURE ); - assert((std::is_same::value )|| type != Cursor::Type::COMBAT ); - assert((std::is_same::value )|| type != Cursor::Type::SPELLBOOK ); - - return static_cast(frame); - } - - void render(); - - void hide(); - void show(); - - /// change cursor's positions to (x, y) - void cursorMove(const int & x, const int & y); - /// Move cursor to screen center - void centerCursor(); - -};