diff --git a/doc/changelog.html b/doc/changelog.html
index 783a5c906..d6309dd4b 100644
--- a/doc/changelog.html
+++ b/doc/changelog.html
@@ -40,7 +40,13 @@
-- 2.4.2 Released
+- 2.4.3 Released
+
+ -
+ Allow specifying colors, percentages, and border for the LifeBar.
+
+
+- 2.4.2 Released
-
Force load progress to screen only every 500ms. On modern machines, loading
diff --git a/doc/scripts/ui.html b/doc/scripts/ui.html
index e7c23f3f9..a4c80912e 100644
--- a/doc/scripts/ui.html
+++ b/doc/scripts/ui.html
@@ -918,6 +918,15 @@ Define panel content when an unit is selected.
- Height of the bar.
- Width = value
- width of the bar.
+ - Border = boolean
+ - if true then add a border to the bar. Default is true.
+ - Colors = list
+ - A list of {percentage, color-name} pairs. The default is equivalent
+ to {{75, "dark-green"}, {50, "yellow"}, {25, "orange"}, {0,
+ "red"}}. The last element must start with "0". The meaning of the
+ number is the percentage above which the associated color takes
+ effect.
+
- "CompleteBar", {flag = value, ...}
- Draw a bar which represent the variable.
diff --git a/src/include/ui/contenttype.h b/src/include/ui/contenttype.h
index e909fc9ac..1a59e9628 100644
--- a/src/include/ui/contenttype.h
+++ b/src/include/ui/contenttype.h
@@ -149,19 +149,23 @@ private:
class CContentTypeLifeBar : public CContentType
{
public:
- CContentTypeLifeBar() : Index(-1), Width(0), Height(0) {}
+ CContentTypeLifeBar() : Index(-1), Width(0), Height(0), hasBorder(true), colors(NULL), values(NULL) {}
+ virtual ~CContentTypeLifeBar()
+ {
+ delete[] colors;
+ delete[] values;
+ }
virtual void Draw(const CUnit &unit, CFont *defaultfont) const;
virtual void Parse(lua_State *l);
private:
- int Index; /// Index of the variable to show, -1 if not.
- int Width; /// Width of the bar.
- int Height; /// Height of the bar.
-#if 0 // FIXME : something for color and value parametrisation (not implemented)
- Color *colors; /// array of color to show (depend of value)
- int *values; /// list of percentage to change color.
-#endif
+ int Index; /// Index of the variable to show, -1 if not.
+ int Width; /// Width of the bar.
+ int Height; /// Height of the bar.
+ bool hasBorder; /// True for additional border.
+ unsigned int *colors; /// array of color to show (depend of value)
+ unsigned int *values; /// list of percentage to change color.
};
/**
diff --git a/src/ui/contenttype.cpp b/src/ui/contenttype.cpp
index 43fd15d7d..fa50aec0e 100644
--- a/src/ui/contenttype.cpp
+++ b/src/ui/contenttype.cpp
@@ -262,6 +262,30 @@ static const CUnit *GetUnitRef(const CUnit &unit, EnumUnit e)
}
}
+static inline Uint32 IndexToColor(unsigned int index) {
+ // FIXME: this only works after video was initialized, so we do it dynamically
+ static const Uint32 ColorValues[] = {ColorRed, ColorYellow, ColorGreen, ColorLightGray,
+ ColorGray, ColorDarkGray, ColorWhite, ColorOrange,
+ ColorLightBlue, ColorBlue, ColorDarkGreen, ColorBlack};
+ return ColorValues[index];
+}
+
+static const char *ColorNames[] = {"red", "yellow", "green", "light-gray",
+ "gray", "dark-gray", "white", "orange",
+ "light-blue", "blue", "dark-green", "black", NULL};
+
+static int GetColorIndexByName(const char *colorName)
+{
+ int i = 0;
+ while (ColorNames[i] != NULL) {
+ if (!strcmp(colorName, ColorNames[i])) {
+ return i;
+ }
+ i++;
+ }
+ return -1;
+}
+
/**
** Draw life bar of a unit using selected variable.
** Placed under icons on top-panel.
@@ -280,20 +304,19 @@ static const CUnit *GetUnitRef(const CUnit &unit, EnumUnit e)
Uint32 color;
int f = (100 * unit.Variable[this->Index].Value) / unit.Variable[this->Index].Max;
+ int i = 0;
- if (f > 75) {
- color = ColorDarkGreen;
- } else if (f > 50) {
- color = ColorYellow;
- } else if (f > 25) {
- color = ColorOrange;
- } else {
- color = ColorRed;
+ // get to right color
+ while (f < this->values[i]) {
+ i++;
}
+ color = IndexToColor(this->colors[i]);
- // Border
- Video.FillRectangleClip(ColorBlack, this->Pos.x - 2, this->Pos.y - 2,
- this->Width + 3, this->Height + 3);
+ if (this->hasBorder) {
+ // Border
+ Video.FillRectangleClip(ColorBlack, this->Pos.x - 2, this->Pos.y - 2,
+ this->Width + 3, this->Height + 3);
+ }
Video.FillRectangleClip(color, this->Pos.x - 1, this->Pos.y - 1,
(f * this->Width) / 100, this->Height);
@@ -320,11 +343,7 @@ static const CUnit *GetUnitRef(const CUnit &unit, EnumUnit e)
int h = this->height;
Assert(w > 0);
Assert(h > 4);
- const Uint32 colors[] = {ColorRed, ColorYellow, ColorGreen, ColorLightGray,
- ColorGray, ColorDarkGray, ColorWhite, ColorOrange,
- ColorLightBlue, ColorBlue, ColorDarkGreen, ColorBlack
- };
- const Uint32 color = (colorIndex != -1) ? colors[colorIndex] : UI.CompletedBarColor;
+ const Uint32 color = (colorIndex != -1) ? IndexToColor(colorIndex) : UI.CompletedBarColor;
const int f = (100 * unit.Variable[this->varIndex].Value) / unit.Variable[this->varIndex].Max;
if (!this->hasBorder) {
@@ -508,6 +527,34 @@ static EnumUnit Str2EnumUnit(lua_State *l, const char *s)
this->Height = LuaToNumber(l, -1);
} else if (!strcmp(key, "Width")) {
this->Width = LuaToNumber(l, -1);
+ } else if (!strcmp(key, "Colors")) {
+ if (!lua_istable(l, -1)) {
+ LuaError(l, "incorrect argument, need list");
+ }
+ const int color_len = lua_rawlen(l, -1);
+ if (color_len == 0) {
+ LuaError(l, "need at least one {percentage, color} pair, got 0");
+ }
+ this->colors = new unsigned int[color_len];
+ this->values = new unsigned int[color_len];
+ int i = 0;
+ for (lua_pushnil(l); lua_next(l, -2); lua_pop(l, 1)) {
+ if (!lua_istable(l, -1) || lua_rawlen(l, -1) != 2) {
+ LuaError(l, "incorrect argument, need list of size 2 with {percentage, color}");
+ }
+ this->values[i] = LuaToNumber(l, -1, 1);
+ const char *const colorName = LuaToString(l, -1, 2);
+ this->colors[i] = GetColorIndexByName(colorName);
+ if (this->colors[i] == -1) {
+ LuaError(l, "incorrect color: '%s' " _C_ colorName);
+ }
+ i++;
+ }
+ if (this->values[color_len - 1] != 0) {
+ LuaError(l, "the last {percentage, color} pair must be for 0%%");
+ }
+ } else if (!strcmp(key, "Border")) {
+ this->hasBorder = LuaToBoolean(l, -1);
} else {
LuaError(l, "'%s' invalid for method 'LifeBar' in DefinePanelContents" _C_ key);
}
@@ -522,22 +569,20 @@ static EnumUnit Str2EnumUnit(lua_State *l, const char *s)
if (this->Index == -1) {
LuaError(l, "variable undefined for LifeBar");
}
-}
+ if (this->colors == NULL || this->values == NULL) {
+ this->colors = new unsigned int[4];
+ this->values = new unsigned int[4];
-static int GetColorIndexByName(const char *colorName)
-{
- //FIXME: need more general way
- const char *names[] = {
- "red", "yellow", "green", "light-gray", "gray", "dark-gray",
- "white", "orange", "light-blue", "blue", "dark-green", "black"
- };
+ this->values[0] = 75;
+ this->values[1] = 50;
+ this->values[2] = 25;
+ this->values[3] = 0;
- for (unsigned int i = 0; i != sizeof(names) / sizeof(names[0]); ++i) {
- if (!strcmp(colorName, names[i])) {
- return i;
- }
+ this->colors[0] = GetColorIndexByName("dark-green");
+ this->colors[1] = GetColorIndexByName("yellow");
+ this->colors[2] = GetColorIndexByName("orange");;
+ this->colors[3] = GetColorIndexByName("red");
}
- return -1;
}
/* virtual */ void CContentTypeCompleteBar::Parse(lua_State *l)