| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 | 
							- /*
 
-  * RadialMenu.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 "RadialMenu.h"
 
- #include "Images.h"
 
- #include "TextControls.h"
 
- #include "../eventsSDL/InputHandler.h"
 
- #include "../gui/CGuiHandler.h"
 
- #include "../gui/WindowHandler.h"
 
- #include "../render/IImage.h"
 
- #include "../CGameInfo.h"
 
- #include "../../lib/texts/CGeneralTextHandler.h"
 
- RadialMenuItem::RadialMenuItem(const std::string & imageName, const std::string & hoverText, const std::function<void()> & callback, bool alternativeLayout)
 
- 	: callback(callback)
 
- 	, hoverText(hoverText)
 
- {
 
- 	OBJECT_CONSTRUCTION;
 
- 	inactiveImage = std::make_shared<CPicture>(ImagePath::builtin(alternativeLayout ? "radialMenu/itemInactiveAlt" : "radialMenu/itemInactive"), Point(0, 0));
 
- 	selectedImage = std::make_shared<CPicture>(ImagePath::builtin(alternativeLayout ? "radialMenu/itemEmptyAlt" : "radialMenu/itemEmpty"), Point(0, 0));
 
- 	iconImage = std::make_shared<CPicture>(ImagePath::builtin("radialMenu/" + imageName), Point(0, 0));
 
- 	pos = selectedImage->pos;
 
- 	selectedImage->setEnabled(false);
 
- }
 
- void RadialMenuItem::setSelected(bool selected)
 
- {
 
- 	selectedImage->setEnabled(selected);
 
- 	inactiveImage->setEnabled(!selected);
 
- }
 
- RadialMenu::RadialMenu(const Point & positionToCenter, const std::vector<RadialMenuConfig> & menuConfig, bool alternativeLayout):
 
- 	centerPosition(positionToCenter), alternativeLayout(alternativeLayout)
 
- {
 
- 	OBJECT_CONSTRUCTION;
 
- 	pos += positionToCenter;
 
- 	Point itemSize = alternativeLayout ? Point(80, 70) : Point(70, 80);
 
- 	moveBy(-itemSize / 2);
 
- 	pos.w = itemSize.x;
 
- 	pos.h = itemSize.y;
 
- 	for (auto const & item : menuConfig)
 
- 		addItem(item.itemPosition, item.enabled, item.imageName, item.hoverText, item.callback);
 
- 	statusBar = CGStatusBar::create(-80, -100, ImagePath::builtin("radialMenu/statusBar"));
 
- 	for(const auto & item : items)
 
- 		pos = pos.include(item->pos);
 
- 	pos = pos.include(statusBar->pos);
 
- 	fitToScreen(10);
 
- 	addUsedEvents(GESTURE);
 
- }
 
- void RadialMenu::addItem(const Point & offset, bool enabled, const std::string & path, const std::string & hoverText, const std::function<void()>& callback )
 
- {
 
- 	if (!enabled)
 
- 		return;
 
- 	auto item = std::make_shared<RadialMenuItem>(path, CGI->generaltexth->translate(hoverText), callback, alternativeLayout);
 
- 	item->moveBy(offset);
 
- 	items.push_back(item);
 
- }
 
- std::shared_ptr<RadialMenuItem> RadialMenu::findNearestItem(const Point & cursorPosition) const
 
- {
 
- 	static const int requiredDistanceFromCenter = 45;
 
- 	// cursor is inside centeral area -> no selection
 
- 	if ((centerPosition - cursorPosition).length() < requiredDistanceFromCenter)
 
- 		return nullptr;
 
- 	int bestDistance = std::numeric_limits<int>::max();
 
- 	std::shared_ptr<RadialMenuItem> bestItem;
 
- 	for(const auto & item : items)
 
- 	{
 
- 		Point vector = item->pos.center() - cursorPosition;
 
- 		if (vector.length() < bestDistance)
 
- 		{
 
- 			bestDistance = vector.length();
 
- 			bestItem = item;
 
- 		}
 
- 	}
 
- 	assert(bestItem);
 
- 	return bestItem;
 
- }
 
- void RadialMenu::gesturePanning(const Point & initialPosition, const Point & currentPosition, const Point & lastUpdateDistance)
 
- {
 
- 	auto newSelection = findNearestItem(currentPosition);
 
- 	if (newSelection != selectedItem)
 
- 	{
 
- 		if (selectedItem)
 
- 			selectedItem->setSelected(false);
 
- 		if (newSelection)
 
- 		{
 
- 			GH.statusbar()->write(newSelection->hoverText);
 
- 			newSelection->setSelected(true);
 
- 		}
 
- 		else
 
- 			GH.statusbar()->clear();
 
- 		selectedItem = newSelection;
 
- 		GH.windows().totalRedraw();
 
- 	}
 
- }
 
- void RadialMenu::gesture(bool on, const Point & initialPosition, const Point & finalPosition)
 
- {
 
- 	if (on)
 
- 		return;
 
- 	auto item = findNearestItem(finalPosition);
 
- 	// we need to close this window first so if action spawns a new window it won't be closed instead
 
- 	GH.windows().popWindows(1);
 
- 	if (item)
 
- 	{
 
- 		GH.input().hapticFeedback();
 
- 		item->callback();
 
- 	}
 
- }
 
 
  |