From 99579eea945d64921b4f359e00db91969db321d6 Mon Sep 17 00:00:00 2001
From: Tim Felgentreff <timfelgentreff@gmail.com>
Date: Fri, 1 Apr 2022 20:12:39 +0200
Subject: [PATCH] add some more flexibility for live reloading of ui, allow
 using frames in panel graphics

---
 src/include/ui/contenttype.h |  1 +
 src/spell/script_spell.cpp   | 12 ++++++++++++
 src/tolua/ui.pkg             |  5 +++++
 src/ui/contenttype.cpp       | 20 ++++++++++++++++++--
 src/ui/interface.cpp         |  2 +-
 src/ui/mainscr.cpp           | 21 +++++++++++++++++++--
 src/ui/ui.cpp                |  5 +++++
 src/video/sdl.cpp            |  4 ----
 8 files changed, 61 insertions(+), 9 deletions(-)

diff --git a/src/include/ui/contenttype.h b/src/include/ui/contenttype.h
index 22a9f937f..0b5898a5b 100644
--- a/src/include/ui/contenttype.h
+++ b/src/include/ui/contenttype.h
@@ -155,6 +155,7 @@ public:
 
 private:
 	std::string graphic;
+	int frame;
 };
 
 /**
diff --git a/src/spell/script_spell.cpp b/src/spell/script_spell.cpp
index 381d8dd71..1c8494cbd 100644
--- a/src/spell/script_spell.cpp
+++ b/src/spell/script_spell.cpp
@@ -123,6 +123,18 @@ char Ccl2Condition(lua_State *l, const char *value)
 		return CONDITION_FALSE;
 	} else if (!strcmp(value, "only")) {
 		return CONDITION_ONLY;
+	} else if (value[0] == '<') {
+		int v = atoi(value + 1);
+		if (v > 100) {
+			LuaError(l, "Can only encode condition '<' up to 100%%, got %d" _C_ v);
+		}
+		return -v;
+	} else if (value[0] == '>') {
+		int v = atoi(value + 1);
+		if (v > 100) {
+			LuaError(l, "Can only encode condition '<' up to 100%%, got %d" _C_ v);
+		}
+		return v + CONDITION_ONLY;
 	} else {
 		LuaError(l, "Bad condition result: %s" _C_ value);
 		return -1;
diff --git a/src/tolua/ui.pkg b/src/tolua/ui.pkg
index 04c39b8c2..6196658c3 100644
--- a/src/tolua/ui.pkg
+++ b/src/tolua/ui.pkg
@@ -205,6 +205,8 @@ class CUserInterface
 	Vec2i EditorSettingsAreaBottomRight;
 	Vec2i EditorButtonAreaTopLeft;
 	Vec2i EditorButtonAreaBottomRight;
+
+	void Load();
 };
 
 extern CUserInterface UI;
@@ -688,3 +690,6 @@ void UiTrackUnit();
 void SetNewViewportMode(ViewportModeType new_mode);
 
 void SetDefaultTextColors(const std::string &normal, const std::string &reverse);
+
+void LoadDecorations();
+void InitUserInterface();
diff --git a/src/ui/contenttype.cpp b/src/ui/contenttype.cpp
index 2668c489b..ebc1e71a2 100644
--- a/src/ui/contenttype.cpp
+++ b/src/ui/contenttype.cpp
@@ -269,7 +269,11 @@ static const CUnit *GetUnitRef(const CUnit &unit, EnumUnit e)
 {
 	CGraphic *g = CGraphic::Get(this->graphic);
 	if (g) {
-		g->DrawClip(this->Pos.x, this->Pos.y);
+		if (this->frame) {
+			g->DrawFrameClip(this->frame, this->Pos.x, this->Pos.y);
+		} else {
+			g->DrawClip(this->Pos.x, this->Pos.y);
+		}
 	}
 }
 
@@ -516,7 +520,19 @@ static EnumUnit Str2EnumUnit(lua_State *l, const char *s)
 
 /* virtual */ void CContentTypeGraphic::Parse(lua_State *l)
 {
-	this->graphic = LuaToString(l, -1);
+	if (lua_isstring(l, -1)) {
+		this->graphic = LuaToString(l, -1);
+		this->frame = 0;
+	} else if (lua_istable(l, -1)) {
+		for (lua_pushnil(l); lua_next(l, -2); lua_pop(l, 1)) {
+			const char *key = LuaToString(l, -2);
+			if (!strcmp(key, "Graphic")) {
+				this->graphic = LuaToString(l, -1);
+			} else if (!strcmp(key, "Frame")) {
+				this->frame = LuaToNumber(l, -1);
+			}
+		}
+	}
 }
 
 /* virtual */ void CContentTypeLifeBar::Parse(lua_State *l)
diff --git a/src/ui/interface.cpp b/src/ui/interface.cpp
index 67fa328e8..628a0d2a1 100644
--- a/src/ui/interface.cpp
+++ b/src/ui/interface.cpp
@@ -866,7 +866,7 @@ static void InputKey(int key)
 			} else
 #endif
 				if (!IsNetworkGame()) {
-					if (!GameObserve && !GamePaused && !GameEstablishing) {
+					if (!GameObserve && !GameEstablishing) {
 						if (HandleCheats(Input)) {
 							CommandLog("input", NoUnitP, FlushCommands, -1, -1, NoUnitP, Input, -1);
 						}
diff --git a/src/ui/mainscr.cpp b/src/ui/mainscr.cpp
index 47d008db7..2b462922d 100644
--- a/src/ui/mainscr.cpp
+++ b/src/ui/mainscr.cpp
@@ -229,8 +229,25 @@ static bool CanShowContent(const ConditionPanel *condition, const CUnit &unit)
 	}
 	if (condition->Variables) {
 		for (unsigned int i = 0; i < UnitTypeVar.GetNumberVariable(); ++i) {
-			if (condition->Variables[i] != CONDITION_TRUE) {
-				if ((condition->Variables[i] == CONDITION_ONLY) ^ unit.Variable[i].Enable) {
+			char v = condition->Variables[i];
+			if (v < 0) {
+				// only show for less than -v%
+				if (unit.Variable[i].Enable) {
+					const int f = (100 * unit.Variable[i].Value) / unit.Variable[i].Max;
+					if (f >= -v) {
+						return false;
+					}
+				}
+			} else if (v > CONDITION_ONLY) {
+				// only show for more than (v-CONDITION_ONLY)%
+				if (unit.Variable[i].Enable) {
+					const int f = (100 * unit.Variable[i].Value) / unit.Variable[i].Max;
+					if (f <= v - CONDITION_ONLY) {
+						return false;
+					}
+				}
+			} else if (v != CONDITION_TRUE) {
+				if ((v == CONDITION_ONLY) ^ unit.Variable[i].Enable) {
 					return false;
 				}
 			}
diff --git a/src/ui/ui.cpp b/src/ui/ui.cpp
index 3669623c3..eb3639960 100644
--- a/src/ui/ui.cpp
+++ b/src/ui/ui.cpp
@@ -205,6 +205,11 @@ void InitUserInterface()
 	UI.Offset640X = (Video.Width - 640) / 2;
 	UI.Offset480Y = (Video.Height - 480) / 2;
 
+	UI.LifeBarColorsInt.clear();
+	for(std::vector<std::string>::iterator it = UI.LifeBarColorNames.begin(); it != UI.LifeBarColorNames.end(); ++it) {
+		UI.LifeBarColorsInt.push_back(IndexToColor(GetColorIndexByName((*it).c_str())));
+	}
+
 	//
 	// Calculations
 	//
diff --git a/src/video/sdl.cpp b/src/video/sdl.cpp
index 273233590..edd80fb92 100644
--- a/src/video/sdl.cpp
+++ b/src/video/sdl.cpp
@@ -497,10 +497,6 @@ void InitVideoSdl()
 	ColorGreen = Video.MapRGB(TheScreen->format, 0, 252, 0);
 	ColorYellow = Video.MapRGB(TheScreen->format, 252, 252, 0);
 
-	for(std::vector<std::string>::iterator it = UI.LifeBarColorNames.begin(); it != UI.LifeBarColorNames.end(); ++it) {
-		UI.LifeBarColorsInt.push_back(IndexToColor(GetColorIndexByName((*it).c_str())));
-	}
-
 	UI.MouseWarpPos.x = UI.MouseWarpPos.y = -1;
 }