mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	vcmi: actually implement AUTO for CInfoWindow
This is possible to use infobar interactions now.
This commit is contained in:
		| @@ -47,6 +47,8 @@ | ||||
| 	"vcmi.systemOptions.framerateButton.hover"  : "Show FPS", | ||||
| 	"vcmi.systemOptions.framerateButton.help"   : "{Show FPS}\n\n Toggles visibility of Frames Per Second counter in corner of game window.", | ||||
|  | ||||
| 	"vcmi.adventureOptions.infoBarPick.hover" : "Show Messages in Info Panel", | ||||
| 	"vcmi.adventureOptions.infoBarPick.help" : "{Show Messages in Info Panel}\n\nWhenever possible, game messages from visiting map objects will be shown in info bar instead of showing up as popup windows", | ||||
| 	"vcmi.adventureOptions.numericQuantities.hover" : "Numeric Creature Quantities", | ||||
| 	"vcmi.adventureOptions.numericQuantities.help" : "{Numeric Creature Quantities}\n\n Shows approximate enemy creatures quantities in numeric A-B format.", | ||||
| 	"vcmi.adventureOptions.forceMovementInfo.hover" : "Always Show Movement Cost", | ||||
|   | ||||
| @@ -47,6 +47,8 @@ | ||||
| 	"vcmi.systemOptions.framerateButton.hover"  : "Показывать частоту кадров", | ||||
| 	"vcmi.systemOptions.framerateButton.help"   : "{Показывать частоту кадров}\n\n Включить счетчик частоты кадров в углу игрового клиента", | ||||
|  | ||||
| 	"vcmi.adventureOptions.infoBarPick.hover" : "Сообщения в информационной панели", | ||||
| 	"vcmi.adventureOptions.infoBarPick.help" : "{Сообщения в информационной панели}\n\n Если сообщения помещаются, то показывать их в информационной панели (только на интерфейсе карты).", | ||||
| 	"vcmi.adventureOptions.numericQuantities.hover" : "Приблизительное число существ", | ||||
| 	"vcmi.adventureOptions.numericQuantities.help" : "{Приблизительное число существ}\n\n Показывать приблизительное число существ в формате A-B вместо словесный обозначений", | ||||
| 	"vcmi.adventureOptions.forceMovementInfo.hover" : "Всегда показывать стоимость перемещения", | ||||
|   | ||||
| @@ -1034,11 +1034,18 @@ void CPlayerInterface::yourTacticPhase(int distance) | ||||
| void CPlayerInterface::showInfoDialog(EInfoWindowMode type, const std::string &text, const std::vector<Component> & components, int soundID) | ||||
| { | ||||
| 	EVENT_HANDLER_CALLED_BY_CLIENT; | ||||
| 	if(type == InfoWindow::INFO) { | ||||
| 		adventureInt->infoBar->showComponents(components, text); | ||||
| 		if (makingTurn && GH.listInt.size() && LOCPLINT == this) | ||||
| 			CCS->soundh->playSound(static_cast<soundBase::soundID>(soundID)); | ||||
| 		return; | ||||
|  | ||||
| 	bool autoTryHover = settings["gameTweaks"]["infoBarPick"].Bool() && type == EInfoWindowMode::AUTO; | ||||
| 	auto timer = type == EInfoWindowMode::INFO ? 3000 : 4500; //Implement long info windows like in HD mod | ||||
|  | ||||
| 	if(autoTryHover || type == EInfoWindowMode::INFO) | ||||
| 	{ | ||||
| 		if(adventureInt->infoBar->tryShowComponents(components, text, timer)) | ||||
| 		{ | ||||
| 			if (makingTurn && GH.listInt.size() && LOCPLINT == this) | ||||
| 				CCS->soundh->playSound(static_cast<soundBase::soundID>(soundID)); | ||||
| 			return; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if (settings["session"]["autoSkip"].Bool() && !GH.isKeyboardShiftDown()) | ||||
|   | ||||
| @@ -15,6 +15,7 @@ | ||||
|  | ||||
| #include "../widgets/CComponent.h" | ||||
| #include "../widgets/Images.h" | ||||
| #include "../windows/CMessage.h" | ||||
| #include "../widgets/TextControls.h" | ||||
| #include "../widgets/MiscWidgets.h" | ||||
| #include "../windows/InfoWindows.h" | ||||
| @@ -29,7 +30,7 @@ | ||||
| #include "../../lib/mapObjects/CGTownInstance.h" | ||||
|  | ||||
| CInfoBar::CVisibleInfo::CVisibleInfo() | ||||
| 	: CIntObject(0, Point(8, 12)) | ||||
| 	: CIntObject(0, Point(offset_x, offset_y)) | ||||
| { | ||||
| } | ||||
|  | ||||
| @@ -163,24 +164,31 @@ CInfoBar::VisibleGameStatusInfo::VisibleGameStatusInfo() | ||||
| 	} | ||||
| } | ||||
|  | ||||
| CInfoBar::VisibleComponentInfo::VisibleComponentInfo(const std::vector<Component> & compsToDisplay, std::string message) | ||||
| CInfoBar::VisibleComponentInfo::VisibleComponentInfo(const std::vector<Component> & compsToDisplay, std::string message, int textH, bool tiny) | ||||
| { | ||||
| 	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); | ||||
|  | ||||
| 	background = std::make_shared<CPicture>("ADSTATOT", 1, 0); | ||||
| 	auto fullRect = Rect(4, 4, 171, 171); | ||||
| 	auto fullRect = Rect(0, 0, data_width, data_height); | ||||
| 	auto textRect = fullRect; | ||||
| 	auto imageRect = fullRect; | ||||
| 	auto font = FONT_SMALL; | ||||
|  | ||||
| 	if(!compsToDisplay.empty()) | ||||
| 	{ | ||||
| 		auto size = CComponent::large; | ||||
| 		if(compsToDisplay.size() > 2) | ||||
| 			size = CComponent::small; | ||||
| 		if(message != "") | ||||
| 		if(!message.empty()) | ||||
| 		{ | ||||
| 			textRect = Rect(4, 4, 171, 42); | ||||
| 			imageRect = Rect(4, 42, 171, 121); | ||||
| 			textRect = Rect(CInfoBar::offset, | ||||
| 							CInfoBar::offset, | ||||
| 							data_width - 2 * CInfoBar::offset, | ||||
| 							textH); | ||||
| 			imageRect = Rect(CInfoBar::offset, | ||||
| 							 textH + CInfoBar::offset, | ||||
| 							 data_width - 2 * CInfoBar::offset, | ||||
| 							 CInfoBar::data_height - 2* CInfoBar::offset - textH); | ||||
| 			if(compsToDisplay.size() > 4) | ||||
| 				size = CComponent::tiny; | ||||
| 		} | ||||
| @@ -194,8 +202,24 @@ CInfoBar::VisibleComponentInfo::VisibleComponentInfo(const std::vector<Component | ||||
|  | ||||
| 		comps = std::make_shared<CComponentBox>(vect, imageRect, 4, 4, 1); | ||||
| 	} | ||||
| 	else | ||||
| 		font = tiny ? FONT_TINY : font; | ||||
|  | ||||
| 	text = std::make_shared<CTextBox>(message, textRect, 0, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE); | ||||
| 	if(!message.empty()) | ||||
| 		text = std::make_shared<CTextBox>(message, textRect, 0, font, ETextAlignment::CENTER, Colors::WHITE); | ||||
| } | ||||
|  | ||||
| int CInfoBar::getEstimatedComponentHeight(int numComps) const | ||||
| { | ||||
| 	if (numComps > 8) //Bigger than 8 components - return invalid value | ||||
| 		return std::numeric_limits<int>::max(); | ||||
| 	else if (numComps > 4) | ||||
| 		return 48 + 20; // 24px * 2 rows + 20 to offset | ||||
| 	else if (numComps > 2) | ||||
| 		return 32 + 20; // 32px * 1 row + 20 to offset | ||||
| 	else if (numComps) | ||||
| 		return 128; // 128 px to offset | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| void CInfoBar::playNewDaySound() | ||||
| @@ -293,13 +317,36 @@ void CInfoBar::showDate() | ||||
| 	redraw(); | ||||
| } | ||||
|  | ||||
| void CInfoBar::showComponents(const std::vector<Component> & comps, std::string message) | ||||
| bool CInfoBar::tryShowComponents(const std::vector<Component> & components, std::string message, int timer) | ||||
| { | ||||
| 	auto imageH = getEstimatedComponentHeight(components.size()) + (components.empty() ? 0 : 2 * CInfoBar::offset); | ||||
| 	auto textH = CMessage::guessHeight(message,CInfoBar::data_width - 2 * CInfoBar::offset, FONT_SMALL); | ||||
| 	auto tinyH = CMessage::guessHeight(message,CInfoBar::data_width - 2 * CInfoBar::offset, FONT_TINY); | ||||
| 	auto header = CMessage::guessHeader(message); | ||||
| 	auto headerH = CMessage::guessHeight(header, CInfoBar::data_width - 2 * CInfoBar::offset, FONT_SMALL); | ||||
|  | ||||
| 	// Order matters - priority form should be chosen first | ||||
| 	if(imageH + textH < CInfoBar::data_height) | ||||
| 		showComponents(components, message, textH, false, timer); | ||||
| 	else if(!imageH && tinyH < CInfoBar::data_height) | ||||
| 		showComponents(components, message, tinyH, true, timer); | ||||
| 	else if(imageH + headerH < CInfoBar::data_height) | ||||
| 		showComponents(components, header, headerH, false, timer); | ||||
| 	else if(imageH < CInfoBar::data_height) | ||||
| 		showComponents(components, "", 0, false, timer); | ||||
| 	else | ||||
| 		return false; //We cannot fit message to infobar, fallback to window | ||||
|  | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| void CInfoBar::showComponents(const std::vector<Component> & comps, std::string message, int textH, bool tiny, int timer) | ||||
| { | ||||
| 	OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE); | ||||
| 	state = COMPONENT; | ||||
| 	visibleInfo = std::make_shared<VisibleComponentInfo>(comps, message); | ||||
| 	visibleInfo = std::make_shared<VisibleComponentInfo>(comps, message, textH, tiny); | ||||
|  | ||||
| 	setTimer(3000); | ||||
| 	setTimer(timer); | ||||
| 	redraw(); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -37,12 +37,15 @@ private: | ||||
| 	/// Declare before to compute correct size of widgets | ||||
| 	static constexpr int width = 192; | ||||
| 	static constexpr int height = 192; | ||||
| 	static constexpr int component_offset = 8; | ||||
| 	static constexpr int offset = 4; | ||||
|  | ||||
| 	//all visible information located in one object - for ease of replacing | ||||
| 	class CVisibleInfo : public CIntObject | ||||
| 	{ | ||||
| 	public: | ||||
| 		static constexpr int offset_x = 8; | ||||
| 		static constexpr int offset_y = 12; | ||||
|  | ||||
| 		void show(SDL_Surface * to) override; | ||||
|  | ||||
| 	protected: | ||||
| @@ -52,6 +55,9 @@ private: | ||||
| 		CVisibleInfo(); | ||||
| 	}; | ||||
|  | ||||
| 	static constexpr int data_width = width - 2 * CVisibleInfo::offset_x; | ||||
| 	static constexpr int data_height = height - 2 * CVisibleInfo::offset_y + 4; //yes, +4 is required | ||||
|  | ||||
| 	class EmptyVisibleInfo : public CVisibleInfo | ||||
| 	{ | ||||
| 	public: | ||||
| @@ -108,7 +114,7 @@ private: | ||||
| 		std::shared_ptr<CComponentBox> comps; | ||||
| 		std::shared_ptr<CTextBox> text; | ||||
| 	public: | ||||
| 		VisibleComponentInfo(const std::vector<Component> & compsToDisplay, std::string message); | ||||
| 		VisibleComponentInfo(const std::vector<Component> & compsToDisplay, std::string message, int textH, bool tiny); | ||||
| 	}; | ||||
|  | ||||
| 	enum EState | ||||
| @@ -119,6 +125,9 @@ private: | ||||
| 	std::shared_ptr<CVisibleInfo> visibleInfo; | ||||
| 	EState state; | ||||
|  | ||||
| 	//private helper for showing components | ||||
| 	void showComponents(const std::vector<Component> & comps, std::string message, int textH, bool tiny = false, int timer = 3000); | ||||
|  | ||||
| 	//removes all information about current state, deactivates timer (if any) | ||||
| 	void reset(); | ||||
|  | ||||
| @@ -137,7 +146,7 @@ public: | ||||
| 	void showDate(); | ||||
|  | ||||
| 	/// show components for 3 seconds. Used to display picked up resources. Can display up to 8 components | ||||
| 	void showComponents(const std::vector<Component> & comps, std::string message); | ||||
| 	bool tryShowComponents(const std::vector<Component> & comps, std::string message, int timer = 3000); | ||||
|  | ||||
| 	/// print enemy turn progress | ||||
| 	void startEnemyTurn(PlayerColor color); | ||||
| @@ -154,5 +163,8 @@ public: | ||||
|  | ||||
| 	/// check if infobar is showed something about pickups | ||||
| 	bool showingComponents(); | ||||
|  | ||||
| 	/// get estimated component height for InfoBar | ||||
| 	int getEstimatedComponentHeight(int numComps) const; | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -202,6 +202,25 @@ std::vector<std::string> CMessage::breakText( std::string text, size_t maxLineWi | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
| std::string CMessage::guessHeader(const std::string & msg) | ||||
| { | ||||
| 	size_t begin = 0; | ||||
| 	std::string delimeters = "{}"; | ||||
| 	size_t start = msg.find_first_of(delimeters[0], begin); | ||||
| 	size_t end = msg.find_first_of(delimeters[1], start); | ||||
| 	if(start > msg.size() || end > msg.size()) | ||||
| 		return ""; | ||||
| 	return msg.substr(begin, end); | ||||
| } | ||||
|  | ||||
| int CMessage::guessHeight(const std::string & txt, int width, EFonts font) | ||||
| { | ||||
| 	const auto f = graphics->fonts[font]; | ||||
| 	auto lines = CMessage::breakText(txt, width, font); | ||||
| 	int lineHeight = static_cast<int>(f->getLineHeight()); | ||||
| 	return lineHeight * (int)lines.size(); | ||||
| } | ||||
|  | ||||
| void CMessage::drawIWindow(CInfoWindow * ret, std::string text, PlayerColor player) | ||||
| { | ||||
| 	bool blitOr = false; | ||||
|   | ||||
| @@ -32,6 +32,12 @@ public: | ||||
| 	/// split text in lines | ||||
| 	static std::vector<std::string> breakText(std::string text, size_t maxLineWidth, EFonts font); | ||||
|  | ||||
| 	/// Try to guess a header of a message | ||||
| 	static std::string guessHeader(const std::string & msg); | ||||
|  | ||||
| 	/// For convenience | ||||
| 	static int guessHeight(const std::string & string, int width, EFonts fnt); | ||||
|  | ||||
| 	/// constructor | ||||
| 	static void init(); | ||||
| 	/// destructor | ||||
|   | ||||
| @@ -105,11 +105,15 @@ AdventureOptionsTab::AdventureOptionsTab() | ||||
| 	addCallback("mapSwipeChanged", [](bool value) | ||||
| 	{ | ||||
| #if defined(VCMI_MOBILE) | ||||
| 		setBoolSetting("general", "swipe", value); | ||||
| 		return setBoolSetting("general", "swipe", value); | ||||
| #else | ||||
| 		setBoolSetting("general", "swipeDesktop", value); | ||||
| 		return setBoolSetting("general", "swipeDesktop", value); | ||||
| #endif | ||||
| 	}); | ||||
| 	addCallback("infoBarPickChanged", [](bool value) | ||||
| 	{ | ||||
| 		return setBoolSetting("gameTweaks", "infoBarPick", value); | ||||
| 	}); | ||||
| 	build(config); | ||||
|  | ||||
| 	std::shared_ptr<CToggleGroup> playerHeroSpeedToggle = widget<CToggleGroup>("heroMovementSpeedPicker"); | ||||
| @@ -142,4 +146,6 @@ AdventureOptionsTab::AdventureOptionsTab() | ||||
| #else | ||||
| 	mapSwipeCheckbox->setSelected(settings["general"]["swipeDesktop"].Bool()); | ||||
| #endif | ||||
| 	std::shared_ptr<CToggleButton> infoBarPickCheckbox = widget<CToggleButton>("infoBarPickCheckbox"); | ||||
| 	infoBarPickCheckbox->setSelected(settings["gameTweaks"]["infoBarPick"].Bool()); | ||||
| } | ||||
|   | ||||
| @@ -503,6 +503,7 @@ | ||||
| 				"numericCreaturesQuantities", | ||||
| 				"availableCreaturesAsDwellingLabel", | ||||
| 				"compactTownCreatureInfo", | ||||
| 				"infoBarPick", | ||||
| 				"skipBattleIntroMusic" | ||||
| 			], | ||||
| 			"properties": { | ||||
| @@ -526,6 +527,10 @@ | ||||
| 					"type" : "boolean", | ||||
| 					"default" : false | ||||
| 				}, | ||||
| 				"infoBarPick" : { | ||||
| 					"type" : "boolean", | ||||
| 					"default" : false | ||||
| 				}, | ||||
| 				"skipBattleIntroMusic" : { | ||||
| 					"type" : "boolean", | ||||
| 					"default" : false | ||||
|   | ||||
| @@ -364,6 +364,10 @@ | ||||
| 				{ | ||||
| 					"position": {"x": 45, "y": 385}, | ||||
| 					"text": "vcmi.adventureOptions.mapSwipe.hover" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"position": {"x": 45, "y": 415}, | ||||
| 					"text": "vcmi.adventureOptions.infoBarPick.hover" | ||||
| 				} | ||||
| 			] | ||||
| 		}, | ||||
| @@ -399,6 +403,13 @@ | ||||
| 			"position": {"x": 10, "y": 383}, | ||||
| 			"callback": "mapSwipeChanged" | ||||
| 		}, | ||||
|  | ||||
| 		{ | ||||
| 			"name": "infoBarPickCheckbox", | ||||
| 			"type": "toggleButton", | ||||
| 			"image": "sysopchk.def", | ||||
| 			"help": "vcmi.adventureOptions.infoBarPick", | ||||
| 			"position": {"x": 10, "y": 413}, | ||||
| 			"callback": "infoBarPickChanged" | ||||
| 		} | ||||
| 	] | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user