| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292 | 
							- /*
 
-  * CCursorHandler.cpp, part of VCMI engine
 
-  *
 
-  * Authors: listed in file AUTHORS in main folder
 
-  *
 
-  * License: GNU General Public License v2.0 or later
 
-  * Full text of license available in license.txt file, in main folder
 
-  *
 
-  */
 
- #include "StdInc.h"
 
- #include "CursorHandler.h"
 
- #include "CGuiHandler.h"
 
- #include "FramerateManager.h"
 
- #include "../renderSDL/CursorSoftware.h"
 
- #include "../renderSDL/CursorHardware.h"
 
- #include "../render/CAnimation.h"
 
- #include "../render/IImage.h"
 
- #include "../render/IRenderHandler.h"
 
- #include "../../lib/CConfigHandler.h"
 
- std::unique_ptr<ICursor> CursorHandler::createCursor()
 
- {
 
- #if defined(VCMI_MOBILE)
 
- 	if (settings["general"]["userRelativePointer"].Bool())
 
- 		return std::make_unique<CursorSoftware>();
 
- #endif
 
- 	if (settings["video"]["cursor"].String() == "hardware")
 
- 		return std::make_unique<CursorHardware>();
 
- 	assert(settings["video"]["cursor"].String() == "software");
 
- 	return std::make_unique<CursorSoftware>();
 
- }
 
- CursorHandler::CursorHandler()
 
- 	: cursor(createCursor())
 
- 	, frameTime(0.f)
 
- 	, showing(false)
 
- 	, pos(0,0)
 
- {
 
- 	type = Cursor::Type::DEFAULT;
 
- 	dndObject = nullptr;
 
- 	cursors =
 
- 	{
 
- 		GH.renderHandler().loadAnimation(AnimationPath::builtin("CRADVNTR")),
 
- 		GH.renderHandler().loadAnimation(AnimationPath::builtin("CRCOMBAT")),
 
- 		GH.renderHandler().loadAnimation(AnimationPath::builtin("CRDEFLT")),
 
- 		GH.renderHandler().loadAnimation(AnimationPath::builtin("CRSPELL"))
 
- 	};
 
- 	for (auto & cursor : cursors)
 
- 		cursor->preload();
 
- 	set(Cursor::Map::POINTER);
 
- }
 
- CursorHandler::~CursorHandler() = default;
 
- 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<size_t>(index));
 
- }
 
- void CursorHandler::set(Cursor::Map index)
 
- {
 
- 	changeGraphic(Cursor::Type::ADVENTURE, static_cast<size_t>(index));
 
- }
 
- void CursorHandler::set(Cursor::Combat index)
 
- {
 
- 	changeGraphic(Cursor::Type::COMBAT, static_cast<size_t>(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<IImage> image)
 
- {
 
- 	dndObject = image;
 
- 	cursor->setImage(getCurrentImage(), getPivotOffset());
 
- }
 
- void CursorHandler::dragAndDropCursor (const AnimationPath & path, size_t index)
 
- {
 
- 	auto anim = GH.renderHandler().loadAnimation(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<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,
 
- 		{ 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<Point, 20> 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<IImage> CursorHandler::getCurrentImage()
 
- {
 
- 	if (dndObject)
 
- 		return dndObject;
 
- 	return cursors[static_cast<size_t>(type)]->getImage(frame);
 
- }
 
- void CursorHandler::updateSpellcastCursor()
 
- {
 
- 	static const float frameDisplayDuration = 0.1f; // H3 uses 100 ms per frame
 
- 	frameTime += GH.framerate().getElapsedMilliseconds() / 1000.f;
 
- 	size_t newFrame = frame;
 
- 	while (frameTime >= frameDisplayDuration)
 
- 	{
 
- 		frameTime -= frameDisplayDuration;
 
- 		newFrame++;
 
- 	}
 
- 	auto & animation = cursors.at(static_cast<size_t>(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);
 
- }
 
 
  |