1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-06-08 23:36:33 +02:00

Refactoring of CursorHandler, in preparation for HW cursor routines

This commit is contained in:
Ivan Savenko 2023-01-05 19:03:27 +02:00
parent 246281e62a
commit d44e809369
2 changed files with 161 additions and 145 deletions

View File

@ -44,11 +44,11 @@ CCursorHandler::CCursorHandler()
, cursorLayer(nullptr) , cursorLayer(nullptr)
, frameTime(0.f) , frameTime(0.f)
, showing(false) , showing(false)
, pos(0,0)
{ {
cursorLayer = SDL_CreateTexture(mainRenderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, 40, 40); cursorLayer = SDL_CreateTexture(mainRenderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, 40, 40);
SDL_SetTextureBlendMode(cursorLayer, SDL_BLENDMODE_BLEND); SDL_SetTextureBlendMode(cursorLayer, SDL_BLENDMODE_BLEND);
xpos = ypos = 0;
type = Cursor::Type::DEFAULT; type = Cursor::Type::DEFAULT;
dndObject = nullptr; dndObject = nullptr;
@ -72,7 +72,7 @@ CCursorHandler::CCursorHandler()
Point CCursorHandler::position() const Point CCursorHandler::position() const
{ {
return Point(xpos, ypos); return pos;
} }
void CCursorHandler::changeGraphic(Cursor::Type type, size_t index) void CCursorHandler::changeGraphic(Cursor::Type type, size_t index)
@ -127,136 +127,134 @@ void CCursorHandler::dragAndDropCursor(std::unique_ptr<CAnimImage> object)
void CCursorHandler::cursorMove(const int & x, const int & y) void CCursorHandler::cursorMove(const int & x, const int & y)
{ {
xpos = x; pos.x = x;
ypos = y; pos.y = y;
} }
void CCursorHandler::shiftPos( int &x, int &y ) Point CCursorHandler::getPivotOffsetDefault(size_t index)
{ {
if(( type == Cursor::Type::COMBAT && frame != static_cast<size_t>(Cursor::Combat::POINTER)) || type == Cursor::Type::SPELLBOOK) return {0, 0};
{ }
x-=16;
y-=16;
// Properly align the melee attack cursors. Point CCursorHandler::getPivotOffsetMap(size_t index)
if (type == Cursor::Type::COMBAT) {
{ static const std::array<Point, 43> offsets = {{
switch (static_cast<Cursor::Combat>(frame)) { 0, 0}, // POINTER = 0,
{ { 0, 0}, // HOURGLASS = 1,
case Cursor::Combat::HIT_NORTHEAST: { 12, 10}, // HERO = 2,
x -= 6; { 12, 12}, // TOWN = 3,
y += 16;
break; { 15, 13}, // T1_MOVE = 4,
case Cursor::Combat::HIT_EAST: { 13, 13}, // T1_ATTACK = 5,
x -= 16; { 20, 20}, // T1_SAIL = 6,
y += 10; { 13, 16}, // T1_DISEMBARK = 7,
break; { 8, 9}, // T1_EXCHANGE = 8,
case Cursor::Combat::HIT_SOUTHEAST: { 14, 16}, // T1_VISIT = 9,
x -= 6;
y -= 6; { 15, 13}, // T2_MOVE = 10,
break; { 13, 13}, // T2_ATTACK = 11,
case Cursor::Combat::HIT_SOUTHWEST: { 20, 20}, // T2_SAIL = 12,
x += 16; { 13, 16}, // T2_DISEMBARK = 13,
y -= 6; { 8, 9}, // T2_EXCHANGE = 14,
break; { 14, 16}, // T2_VISIT = 15,
case Cursor::Combat::HIT_WEST:
x += 16; { 15, 13}, // T3_MOVE = 16,
y += 11; { 13, 13}, // T3_ATTACK = 17,
break; { 20, 20}, // T3_SAIL = 18,
case Cursor::Combat::HIT_NORTHWEST: { 13, 16}, // T3_DISEMBARK = 19,
x += 16; { 8, 9}, // T3_EXCHANGE = 20,
y += 16; { 14, 16}, // T3_VISIT = 21,
break;
case Cursor::Combat::HIT_NORTH: { 15, 13}, // T4_MOVE = 22,
x += 9; { 13, 13}, // T4_ATTACK = 23,
y += 16; { 20, 20}, // T4_SAIL = 24,
break; { 13, 16}, // T4_DISEMBARK = 25,
case Cursor::Combat::HIT_SOUTH: { 8, 9}, // T4_EXCHANGE = 26,
x += 9; { 14, 16}, // T4_VISIT = 27,
y -= 15;
break; { 20, 20}, // T1_SAIL_VISIT = 28,
} { 20, 20}, // T2_SAIL_VISIT = 29,
} { 20, 20}, // T3_SAIL_VISIT = 30,
} { 20, 20}, // T4_SAIL_VISIT = 31,
else if(type == Cursor::Type::ADVENTURE)
{ { 6, 1}, // SCROLL_NORTH = 32,
if (frame == 0) { 16, 2}, // SCROLL_NORTHEAST = 33,
{ { 21, 6}, // SCROLL_EAST = 34,
//no-op { 16, 16}, // SCROLL_SOUTHEAST = 35,
} { 6, 21}, // SCROLL_SOUTH = 36,
else if(frame == 2) { 1, 16}, // SCROLL_SOUTHWEST = 37,
{ { 1, 5}, // SCROLL_WEST = 38,
x -= 12; { 2, 1}, // SCROLL_NORTHWEST = 39,
y -= 10;
} { 0, 0}, // POINTER_COPY = 40,
else if(frame == 3) { 14, 16}, // TELEPORT = 41,
{ { 20, 20}, // SCUTTLE_BOAT = 42
x -= 12; }};
y -= 12;
} static_assert (offsets.size() == size_t(Cursor::Map::COUNT), "Invalid number of pivot offsets for cursor" );
else if(frame < 27) assert(index < offsets.size());
{ return offsets[index];
int hlpNum = (frame - 4)%6; }
if(hlpNum == 0)
{ Point CCursorHandler::getPivotOffsetCombat(size_t index)
x -= 15; {
y -= 13; static const std::array<Point, 20> offsets = {{
} { 12, 12 }, // BLOCKED = 0,
else if(hlpNum == 1) { 10, 14 }, // MOVE = 1,
{ { 14, 14 }, // FLY = 2,
x -= 13; { 12, 12 }, // SHOOT = 3,
y -= 13; { 12, 12 }, // HERO = 4,
} { 8, 12 }, // QUERY = 5,
else if(hlpNum == 2) { 0, 0 }, // POINTER = 6,
{ { 21, 0 }, // HIT_NORTHEAST = 7,
x -= 20; { 31, 5 }, // HIT_EAST = 8,
y -= 20; { 21, 21 }, // HIT_SOUTHEAST = 9,
} { 0, 21 }, // HIT_SOUTHWEST = 10,
else if(hlpNum == 3) { 0, 5 }, // HIT_WEST = 11,
{ { 0, 0 }, // HIT_NORTHWEST = 12,
x -= 13; { 6, 0 }, // HIT_NORTH = 13,
y -= 16; { 6, 31 }, // HIT_SOUTH = 14,
} { 14, 0 }, // SHOOT_PENALTY = 15,
else if(hlpNum == 4) { 12, 12 }, // SHOOT_CATAPULT = 16,
{ { 12, 12 }, // HEAL = 17,
x -= 8; { 12, 12 }, // SACRIFICE = 18,
y -= 9; { 14, 20 }, // TELEPORT = 19
} }};
else if(hlpNum == 5)
{ static_assert (offsets.size() == size_t(Cursor::Combat::COUNT), "Invalid number of pivot offsets for cursor" );
x -= 14; assert(index < offsets.size());
y -= 16; return offsets[index];
} }
}
else if(frame == 41) Point CCursorHandler::getPivotOffsetSpellcast()
{ {
x -= 14; return { 18, 28};
y -= 16; }
}
else if(frame < 31 || frame == 42) Point CCursorHandler::getPivotOffset()
{ {
x -= 20; switch (type) {
y -= 20; 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};
} }
void CCursorHandler::centerCursor() void CCursorHandler::centerCursor()
{ {
this->xpos = static_cast<int>((screen->w / 2.) - (currentCursor->pos.w / 2.)); pos.x = static_cast<int>((screen->w / 2.) - (currentCursor->pos.w / 2.));
this->ypos = static_cast<int>((screen->h / 2.) - (currentCursor->pos.h / 2.)); pos.y = static_cast<int>((screen->h / 2.) - (currentCursor->pos.h / 2.));
SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE); SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);
SDL_WarpMouse(this->xpos, this->ypos); SDL_WarpMouse(pos.x, pos.y);
SDL_EventState(SDL_MOUSEMOTION, SDL_ENABLE); SDL_EventState(SDL_MOUSEMOTION, SDL_ENABLE);
} }
void CCursorHandler::render() void CCursorHandler::updateSpellcastCursor()
{ {
if(!showing)
return;
if (type == Cursor::Type::SPELLBOOK)
{
static const float frameDisplayDuration = 0.1f; static const float frameDisplayDuration = 0.1f;
frameTime += GH.mainFPSmng->getElapsedMilliseconds() / 1000.f; frameTime += GH.mainFPSmng->getElapsedMilliseconds() / 1000.f;
@ -274,24 +272,30 @@ void CCursorHandler::render()
newFrame -= animation->size(); newFrame -= animation->size();
changeGraphic(Cursor::Type::SPELLBOOK, newFrame); changeGraphic(Cursor::Type::SPELLBOOK, newFrame);
} }
void CCursorHandler::render()
{
if(!showing)
return;
if (type == Cursor::Type::SPELLBOOK)
updateSpellcastCursor();
//the must update texture in the main (renderer) thread, but changes to cursor type may come from other threads //the must update texture in the main (renderer) thread, but changes to cursor type may come from other threads
updateTexture(); updateTexture();
int x = xpos; Point renderPos = pos;
int y = ypos;
shiftPos(x, y);
if(dndObject) if(dndObject)
{ renderPos -= dndObject->pos.dimensions() / 2;
x -= dndObject->pos.w/2; else
y -= dndObject->pos.h/2; renderPos -= getPivotOffset();
}
SDL_Rect destRect; SDL_Rect destRect;
destRect.x = x; destRect.x = renderPos.x;
destRect.y = y; destRect.y = renderPos.y;
destRect.w = 40; destRect.w = 40;
destRect.h = 40; destRect.h = 40;

View File

@ -8,11 +8,13 @@
* *
*/ */
#pragma once #pragma once
class CIntObject; class CIntObject;
class CAnimImage; class CAnimImage;
struct SDL_Surface; struct SDL_Surface;
struct SDL_Texture; struct SDL_Texture;
struct Point;
#include "Geometries.h"
namespace Cursor namespace Cursor
{ {
@ -51,7 +53,9 @@ namespace Cursor
SHOOT_CATAPULT = 16, SHOOT_CATAPULT = 16,
HEAL = 17, HEAL = 17,
SACRIFICE = 18, SACRIFICE = 18,
TELEPORT = 19 TELEPORT = 19,
COUNT
}; };
enum class Map { enum class Map {
@ -97,7 +101,9 @@ namespace Cursor
SCROLL_NORTHWEST = 39, SCROLL_NORTHWEST = 39,
//POINTER_COPY = 40, // probably unused //POINTER_COPY = 40, // probably unused
TELEPORT = 41, TELEPORT = 41,
SCUTTLE_BOAT = 42 SCUTTLE_BOAT = 42,
COUNT
}; };
enum class Spellcast { enum class Spellcast {
@ -123,7 +129,6 @@ class CCursorHandler final
void clearBuffer(); void clearBuffer();
void updateBuffer(CIntObject * payload); void updateBuffer(CIntObject * payload);
void replaceBuffer(CIntObject * payload); void replaceBuffer(CIntObject * payload);
void shiftPos( int &x, int &y );
void updateTexture(); void updateTexture();
@ -135,8 +140,15 @@ class CCursorHandler final
void changeGraphic(Cursor::Type type, size_t index); void changeGraphic(Cursor::Type type, size_t index);
/// position of cursor /// position of cursor
int xpos, ypos; Point pos;
Point getPivotOffsetDefault(size_t index);
Point getPivotOffsetMap(size_t index);
Point getPivotOffsetCombat(size_t index);
Point getPivotOffsetSpellcast();
Point getPivotOffset();
void updateSpellcastCursor();
public: public:
CCursorHandler(); CCursorHandler();
~CCursorHandler(); ~CCursorHandler();