1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-06-12 23:57: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,135 +127,133 @@ 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)
{ {
switch (static_cast<Cursor::Combat>(frame)) static const std::array<Point, 43> 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,
{ 20, 20}, // T1_SAIL = 6,
{ 13, 16}, // T1_DISEMBARK = 7,
{ 8, 9}, // T1_EXCHANGE = 8,
{ 14, 16}, // T1_VISIT = 9,
{ 15, 13}, // T2_MOVE = 10,
{ 13, 13}, // T2_ATTACK = 11,
{ 20, 20}, // T2_SAIL = 12,
{ 13, 16}, // T2_DISEMBARK = 13,
{ 8, 9}, // T2_EXCHANGE = 14,
{ 14, 16}, // T2_VISIT = 15,
{ 15, 13}, // T3_MOVE = 16,
{ 13, 13}, // T3_ATTACK = 17,
{ 20, 20}, // T3_SAIL = 18,
{ 13, 16}, // T3_DISEMBARK = 19,
{ 8, 9}, // T3_EXCHANGE = 20,
{ 14, 16}, // T3_VISIT = 21,
{ 15, 13}, // T4_MOVE = 22,
{ 13, 13}, // T4_ATTACK = 23,
{ 20, 20}, // T4_SAIL = 24,
{ 13, 16}, // T4_DISEMBARK = 25,
{ 8, 9}, // T4_EXCHANGE = 26,
{ 14, 16}, // T4_VISIT = 27,
{ 20, 20}, // T1_SAIL_VISIT = 28,
{ 20, 20}, // T2_SAIL_VISIT = 29,
{ 20, 20}, // T3_SAIL_VISIT = 30,
{ 20, 20}, // 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
}};
static_assert (offsets.size() == size_t(Cursor::Map::COUNT), "Invalid number of pivot offsets for cursor" );
assert(index < offsets.size());
return offsets[index];
}
Point CCursorHandler::getPivotOffsetCombat(size_t index)
{ {
case Cursor::Combat::HIT_NORTHEAST: static const std::array<Point, 20> offsets = {{
x -= 6; { 12, 12 }, // BLOCKED = 0,
y += 16; { 10, 14 }, // MOVE = 1,
break; { 14, 14 }, // FLY = 2,
case Cursor::Combat::HIT_EAST: { 12, 12 }, // SHOOT = 3,
x -= 16; { 12, 12 }, // HERO = 4,
y += 10; { 8, 12 }, // QUERY = 5,
break; { 0, 0 }, // POINTER = 6,
case Cursor::Combat::HIT_SOUTHEAST: { 21, 0 }, // HIT_NORTHEAST = 7,
x -= 6; { 31, 5 }, // HIT_EAST = 8,
y -= 6; { 21, 21 }, // HIT_SOUTHEAST = 9,
break; { 0, 21 }, // HIT_SOUTHWEST = 10,
case Cursor::Combat::HIT_SOUTHWEST: { 0, 5 }, // HIT_WEST = 11,
x += 16; { 0, 0 }, // HIT_NORTHWEST = 12,
y -= 6; { 6, 0 }, // HIT_NORTH = 13,
break; { 6, 31 }, // HIT_SOUTH = 14,
case Cursor::Combat::HIT_WEST: { 14, 0 }, // SHOOT_PENALTY = 15,
x += 16; { 12, 12 }, // SHOOT_CATAPULT = 16,
y += 11; { 12, 12 }, // HEAL = 17,
break; { 12, 12 }, // SACRIFICE = 18,
case Cursor::Combat::HIT_NORTHWEST: { 14, 20 }, // TELEPORT = 19
x += 16; }};
y += 16;
break; static_assert (offsets.size() == size_t(Cursor::Combat::COUNT), "Invalid number of pivot offsets for cursor" );
case Cursor::Combat::HIT_NORTH: assert(index < offsets.size());
x += 9; return offsets[index];
y += 16;
break;
case Cursor::Combat::HIT_SOUTH:
x += 9;
y -= 15;
break;
} }
}
} Point CCursorHandler::getPivotOffsetSpellcast()
else if(type == Cursor::Type::ADVENTURE)
{ {
if (frame == 0) return { 18, 28};
}
Point CCursorHandler::getPivotOffset()
{ {
//no-op switch (type) {
} case Cursor::Type::ADVENTURE: return getPivotOffsetMap(frame);
else if(frame == 2) case Cursor::Type::COMBAT: return getPivotOffsetCombat(frame);
{ case Cursor::Type::DEFAULT: return getPivotOffsetDefault(frame);
x -= 12; case Cursor::Type::SPELLBOOK: return getPivotOffsetSpellcast();
y -= 10; };
}
else if(frame == 3) assert(0);
{ return {0, 0};
x -= 12;
y -= 12;
}
else if(frame < 27)
{
int hlpNum = (frame - 4)%6;
if(hlpNum == 0)
{
x -= 15;
y -= 13;
}
else if(hlpNum == 1)
{
x -= 13;
y -= 13;
}
else if(hlpNum == 2)
{
x -= 20;
y -= 20;
}
else if(hlpNum == 3)
{
x -= 13;
y -= 16;
}
else if(hlpNum == 4)
{
x -= 8;
y -= 9;
}
else if(hlpNum == 5)
{
x -= 14;
y -= 16;
}
}
else if(frame == 41)
{
x -= 14;
y -= 16;
}
else if(frame < 31 || frame == 42)
{
x -= 20;
y -= 20;
}
}
} }
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;
@ -276,22 +274,28 @@ void CCursorHandler::render()
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();