1 // _________ __ __
2 // / _____// |_____________ _/ |______ ____ __ __ ______
3 // \_____ \\ __\_ __ \__ \\ __\__ \ / ___\| | \/ ___/
4 // / \| | | | \// __ \| | / __ \_/ /_/ > | /\___ |
5 // /_______ /|__| |__| (____ /__| (____ /\___ /|____//____ >
6 // \/ \/ \//_____/ \/
7 // ______________________ ______________________
8 // T H E W A R B E G I N S
9 // Stratagus - A free fantasy real time strategy game engine
10 //
11 /**@name contenttype.cpp - . */
12 //
13 // (c) Copyright 1999-2015 by Joris Dauphin and Andrettin
14 //
15 // This program is free software; you can redistribute it and/or modify
16 // it under the terms of the GNU General Public License as published by
17 // the Free Software Foundation; only version 2 of the License.
18 //
19 // This program is distributed in the hope that it will be useful,
20 // but WITHOUT ANY WARRANTY; without even the implied warranty of
21 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 // GNU General Public License for more details.
23 //
24 // You should have received a copy of the GNU General Public License
25 // along with this program; if not, write to the Free Software
26 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
27 // 02111-1307, USA.
28 //
29
30 //@{
31
32 /*----------------------------------------------------------------------------
33 -- Includes
34 ----------------------------------------------------------------------------*/
35
36 #include "stratagus.h"
37
38 #include "ui/contenttype.h"
39
40 #include "actions.h"
41 #include "action/action_built.h"
42 #include "font.h"
43 #include "translate.h"
44 #include "unit.h"
45 #include "ui.h"
46 #include "video.h"
47
48 enum UStrIntType {
49 USTRINT_STR, USTRINT_INT
50 };
51 struct UStrInt {
52 union {const char *s; int i;};
53 UStrIntType type;
54 };
55
56 extern UStrInt GetComponent(const CUnit &unit, int index, EnumVariable e, int t);
57 extern UStrInt GetComponent(const CUnitType &type, int index, EnumVariable e);
58
~CContentType()59 /* virtual */ CContentType::~CContentType()
60 {
61 delete Condition;
62 }
63
64 /**
65 ** Draw text with variable.
66 **
67 ** @param unit unit with variable to show.
68 ** @param defaultfont default font if no specific font in extra data.
69 */
Draw(const CUnit & unit,CFont * defaultfont) const70 /* virtual */ void CContentTypeText::Draw(const CUnit &unit, CFont *defaultfont) const
71 {
72 std::string text; // Optional text to display.
73 int x = this->Pos.x;
74 int y = this->Pos.y;
75 CFont &font = this->Font ? *this->Font : *defaultfont;
76
77 Assert(&font);
78 Assert(this->Index == -1 || ((unsigned int) this->Index < UnitTypeVar.GetNumberVariable()));
79
80 CLabel label(font);
81
82 if (this->Text) {
83 text = EvalString(this->Text);
84 std::string::size_type pos;
85 if ((pos = text.find("~|")) != std::string::npos) {
86 x += (label.Draw(x - font.getWidth(text.substr(0, pos)), y, text) - font.getWidth(text.substr(0, pos)));
87 } else if (this->Centered) {
88 x += (label.DrawCentered(x, y, text) * 2);
89 } else {
90 x += label.Draw(x, y, text);
91 }
92 }
93
94 if (this->ShowName) {
95 label.DrawCentered(x, y, unit.Type->Name);
96 return;
97 }
98
99 if (this->Index != -1) {
100 if (!this->Stat) {
101 EnumVariable component = this->Component;
102 switch (component) {
103 case VariableValue:
104 case VariableMax:
105 case VariableIncrease:
106 case VariableDiff:
107 case VariablePercent:
108 label.Draw(x, y, GetComponent(unit, this->Index, component, 0).i);
109 break;
110 case VariableName:
111 label.Draw(x, y, GetComponent(unit, this->Index, component, 0).s);
112 break;
113 default:
114 Assert(0);
115 }
116 } else {
117 int value = unit.Type->MapDefaultStat.Variables[this->Index].Value;
118 int diff = unit.Stats->Variables[this->Index].Value - value;
119
120 if (!diff) {
121 label.Draw(x, y, value);
122 } else {
123 char buf[64];
124 snprintf(buf, sizeof(buf), diff > 0 ? "%d~<+%d~>" : "%d~<-%d~>", value, diff);
125 label.Draw(x, y, buf);
126 }
127 }
128 }
129 }
130
131 /**
132 ** Draw formatted text with variable value.
133 **
134 ** @param unit unit with variable to show.
135 ** @param defaultfont default font if no specific font in extra data.
136 **
137 ** @note text is limited to 256 chars. (enough?)
138 ** @note text must have exactly 1 %d.
139 ** @bug if text format is incorrect.
140 */
Draw(const CUnit & unit,CFont * defaultfont) const141 /* virtual */ void CContentTypeFormattedText::Draw(const CUnit &unit, CFont *defaultfont) const
142 {
143 char buf[256];
144 UStrInt usi1;
145
146 CFont &font = this->Font ? *this->Font : *defaultfont;
147 Assert(&font);
148
149 CLabel label(font);
150
151 Assert((unsigned int) this->Index < UnitTypeVar.GetNumberVariable());
152 usi1 = GetComponent(unit, this->Index, this->Component, 0);
153 if (usi1.type == USTRINT_STR) {
154 snprintf(buf, sizeof(buf), this->Format.c_str(), _(usi1.s));
155 } else {
156 snprintf(buf, sizeof(buf), this->Format.c_str(), usi1.i);
157 }
158
159 char *pos;
160 if ((pos = strstr(buf, "~|")) != NULL) {
161 std::string buf2(buf);
162 label.Draw(this->Pos.x - font.getWidth(buf2.substr(0, pos - buf)), this->Pos.y, buf);
163 } else if (this->Centered) {
164 label.DrawCentered(this->Pos.x, this->Pos.y, buf);
165 } else {
166 label.Draw(this->Pos.x, this->Pos.y, buf);
167 }
168 }
169
170 /**
171 ** Draw formatted text with variable value.
172 **
173 ** @param unit unit with variable to show.
174 ** @param defaultfont default font if no specific font in extra data.
175 **
176 ** @note text is limited to 256 chars. (enough?)
177 ** @note text must have exactly 2 %d.
178 ** @bug if text format is incorrect.
179 */
Draw(const CUnit & unit,CFont * defaultfont) const180 /* virtual */ void CContentTypeFormattedText2::Draw(const CUnit &unit, CFont *defaultfont) const
181 {
182 char buf[256];
183 UStrInt usi1, usi2;
184
185 CFont &font = this->Font ? *this->Font : *defaultfont;
186 Assert(&font);
187 CLabel label(font);
188
189 usi1 = GetComponent(unit, this->Index1, this->Component1, 0);
190 usi2 = GetComponent(unit, this->Index2, this->Component2, 0);
191 if (usi1.type == USTRINT_STR) {
192 if (usi2.type == USTRINT_STR) {
193 snprintf(buf, sizeof(buf), this->Format.c_str(), _(usi1.s), _(usi2.s));
194 } else {
195 snprintf(buf, sizeof(buf), this->Format.c_str(), _(usi1.s), usi2.i);
196 }
197 } else {
198 if (usi2.type == USTRINT_STR) {
199 snprintf(buf, sizeof(buf), this->Format.c_str(), usi1.i, _(usi2.s));
200 } else {
201 snprintf(buf, sizeof(buf), this->Format.c_str(), usi1.i, usi2.i);
202 }
203 }
204 char *pos;
205 if ((pos = strstr(buf, "~|")) != NULL) {
206 std::string buf2(buf);
207 label.Draw(this->Pos.x - font.getWidth(buf2.substr(0, pos - buf)), this->Pos.y, buf);
208 } else if (this->Centered) {
209 label.DrawCentered(this->Pos.x, this->Pos.y, buf);
210 } else {
211 label.Draw(this->Pos.x, this->Pos.y, buf);
212 }
213 }
214
215
216 /**
217 ** Get unit from a unit depending of the relation.
218 **
219 ** @param unit unit reference.
220 ** @param e relation with unit.
221 **
222 ** @return The desired unit.
223 */
GetUnitRef(const CUnit & unit,EnumUnit e)224 static const CUnit *GetUnitRef(const CUnit &unit, EnumUnit e)
225 {
226 switch (e) {
227 case UnitRefItSelf:
228 return &unit;
229 case UnitRefInside:
230 return unit.UnitInside;
231 case UnitRefContainer:
232 return unit.Container;
233 case UnitRefWorker :
234 if (unit.CurrentAction() == UnitActionBuilt) {
235 COrder_Built &order = *static_cast<COrder_Built *>(unit.CurrentOrder());
236
237 return order.GetWorkerPtr();
238 } else {
239 return NULL;
240 }
241 case UnitRefGoal:
242 return unit.Goal;
243 default:
244 Assert(0);
245 }
246 return NULL;
247 }
248
249 /**
250 ** Draw icon for unit.
251 **
252 ** @param unit unit with icon to show.
253 ** @param defaultfont unused.
254 */
Draw(const CUnit & unit,CFont *) const255 /* virtual */ void CContentTypeIcon::Draw(const CUnit &unit, CFont *) const
256 {
257 const CUnit *unitToDraw = GetUnitRef(unit, this->UnitRef);
258
259 if (unitToDraw && unitToDraw->Type->Icon.Icon) {
260 unitToDraw->Type->Icon.Icon->DrawUnitIcon(*UI.SingleSelectedButton->Style, 0, this->Pos, "",
261 unitToDraw->RescuedFrom ? unitToDraw->RescuedFrom->Index : unitToDraw->Player->Index);
262 }
263 }
264
265 /**
266 ** Draw life bar of a unit using selected variable.
267 ** Placed under icons on top-panel.
268 **
269 ** @param unit Pointer to unit.
270 ** @param defaultfont FIXME: docu
271 **
272 ** @todo Color and percent value Parametrisation.
273 */
Draw(const CUnit & unit,CFont *) const274 /* virtual */ void CContentTypeLifeBar::Draw(const CUnit &unit, CFont *) const
275 {
276 Uint32 color;
277 int f;
278 if (this->Index != -1) {
279 Assert((unsigned int) this->Index < UnitTypeVar.GetNumberVariable());
280 if (!unit.Variable[this->Index].Max) {
281 return;
282 }
283 f = (100 * unit.Variable[this->Index].Value) / unit.Variable[this->Index].Max;
284 } else {
285 f = (100 * EvalNumber(this->ValueFunc)) / this->ValueMax;
286 f = f > 100 ? 100 : f;
287 if (f < 0) {
288 return;
289 }
290 }
291 int i = 0;
292
293 // get to right color
294 while (f < this->values[i]) {
295 i++;
296 }
297 color = IndexToColor(this->colors[i]);
298
299 if (this->hasBorder) {
300 // Border. We have a simple heuristic to determine how big it is...
301 // TODO: make configurable?
302 if (this->Height <= 6) {
303 Video.FillRectangleClip(this->hasBorder, this->Pos.x - 2, this->Pos.y - 2,
304 this->Width + 2, this->Height + 2);
305 } else {
306 Video.FillRectangleClip(this->hasBorder, this->Pos.x - 2, this->Pos.y - 2,
307 this->Width + 3, this->Height + 3);
308 }
309 }
310
311 Video.FillRectangleClip(color, this->Pos.x - 1, this->Pos.y - 1,
312 (f * this->Width) / 100, this->Height);
313 }
314
315 /**
316 ** Draw life bar of a unit using selected variable.
317 ** Placed under icons on top-panel.
318 **
319 ** @param unit Pointer to unit.
320 ** @param defaultfont FIXME: docu
321 **
322 ** @todo Color and percent value Parametrisation.
323 */
Draw(const CUnit & unit,CFont *) const324 /* virtual */ void CContentTypeCompleteBar::Draw(const CUnit &unit, CFont *) const
325 {
326 Assert((unsigned int) this->varIndex < UnitTypeVar.GetNumberVariable());
327 if (!unit.Variable[this->varIndex].Max) {
328 return;
329 }
330 int x = this->Pos.x;
331 int y = this->Pos.y;
332 int w = this->width;
333 int h = this->height;
334 Assert(w > 0);
335 Assert(h > 4);
336 const Uint32 color = (colorIndex != -1) ? IndexToColor(colorIndex) : UI.CompletedBarColor;
337 const int f = (100 * unit.Variable[this->varIndex].Value) / unit.Variable[this->varIndex].Max;
338
339 if (!this->hasBorder) {
340 Video.FillRectangleClip(color, x, y, f * w / 100, h);
341 if (UI.CompletedBarShadow) {
342 // Shadow
343 Video.DrawVLine(ColorGray, x + f * w / 100, y, h);
344 Video.DrawHLine(ColorGray, x, y + h, f * w / 100);
345
346 // |~ Light
347 Video.DrawVLine(ColorWhite, x, y, h);
348 Video.DrawHLine(ColorWhite, x, y, f * w / 100);
349 }
350 } else {
351 Video.DrawRectangleClip(ColorWhite, x, y, w + 4, h);
352 Video.DrawRectangleClip(ColorBlack, x + 1, y + 1, w + 2, h - 2);
353 Video.FillRectangleClip(color, x + 2, y + 2, f * w / 100, h - 4);
354 }
355 }
356
Parse(lua_State * l)357 /* virtual */ void CContentTypeText::Parse(lua_State *l)
358 {
359 Assert(lua_istable(l, -1) || lua_isstring(l, -1));
360
361 if (lua_isstring(l, -1)) {
362 this->Text = CclParseStringDesc(l);
363 lua_pushnil(l); // ParseStringDesc eat token
364 } else {
365 for (lua_pushnil(l); lua_next(l, -2); lua_pop(l, 1)) {
366 const char *key = LuaToString(l, -2);
367 if (!strcmp(key, "Text")) {
368 this->Text = CclParseStringDesc(l);
369 lua_pushnil(l); // ParseStringDesc eat token
370 } else if (!strcmp(key, "Font")) {
371 this->Font = CFont::Get(LuaToString(l, -1));
372 } else if (!strcmp(key, "Centered")) {
373 this->Centered = LuaToBoolean(l, -1);
374 } else if (!strcmp(key, "Variable")) {
375 const char *const name = LuaToString(l, -1);
376 this->Index = UnitTypeVar.VariableNameLookup[name];
377 if (this->Index == -1) {
378 LuaError(l, "unknown variable '%s'" _C_ LuaToString(l, -1));
379 }
380 } else if (!strcmp(key, "Component")) {
381 this->Component = Str2EnumVariable(l, LuaToString(l, -1));
382 } else if (!strcmp(key, "Stat")) {
383 this->Stat = LuaToBoolean(l, -1);
384 } else if (!strcmp(key, "ShowName")) {
385 this->ShowName = LuaToBoolean(l, -1);
386 } else {
387 LuaError(l, "'%s' invalid for method 'Text' in DefinePanelContents" _C_ key);
388 }
389 }
390 }
391 }
392
Parse(lua_State * l)393 /* virtual */ void CContentTypeFormattedText::Parse(lua_State *l)
394 {
395 Assert(lua_istable(l, -1));
396
397 for (lua_pushnil(l); lua_next(l, -2); lua_pop(l, 1)) {
398 const char *key = LuaToString(l, -2);
399 if (!strcmp(key, "Format")) {
400 this->Format = LuaToString(l, -1);
401 } else if (!strcmp(key, "Font")) {
402 this->Font = CFont::Get(LuaToString(l, -1));
403 } else if (!strcmp(key, "Variable")) {
404 const char *const name = LuaToString(l, -1);
405 this->Index = UnitTypeVar.VariableNameLookup[name];
406 if (this->Index == -1) {
407 LuaError(l, "unknown variable '%s'" _C_ name);
408 }
409 } else if (!strcmp(key, "Component")) {
410 this->Component = Str2EnumVariable(l, LuaToString(l, -1));
411 } else if (!strcmp(key, "Centered")) {
412 this->Centered = LuaToBoolean(l, -1);
413 } else {
414 LuaError(l, "'%s' invalid for method 'FormattedText' in DefinePanelContents" _C_ key);
415 }
416 }
417 }
418
Parse(lua_State * l)419 /* virtual */ void CContentTypeFormattedText2::Parse(lua_State *l)
420 {
421 Assert(lua_istable(l, -1));
422 for (lua_pushnil(l); lua_next(l, -2); lua_pop(l, 1)) {
423 const char *key = LuaToString(l, -2);
424 if (!strcmp(key, "Format")) {
425 this->Format = LuaToString(l, -1);
426 } else if (!strcmp(key, "Font")) {
427 this->Font = CFont::Get(LuaToString(l, -1));
428 } else if (!strcmp(key, "Variable")) {
429 const char *const name = LuaToString(l, -1);
430 this->Index1 = UnitTypeVar.VariableNameLookup[name];
431 this->Index2 = this->Index1;
432 if (this->Index1 == -1) {
433 LuaError(l, "unknown variable '%s'" _C_ name);
434 }
435 } else if (!strcmp(key, "Component")) {
436 this->Component1 = Str2EnumVariable(l, LuaToString(l, -1));
437 this->Component2 = Str2EnumVariable(l, LuaToString(l, -1));
438 } else if (!strcmp(key, "Variable1")) {
439 const char *const name = LuaToString(l, -1);
440 this->Index1 = UnitTypeVar.VariableNameLookup[name];
441 if (this->Index1 == -1) {
442 LuaError(l, "unknown variable '%s'" _C_ name);
443 }
444 } else if (!strcmp(key, "Component1")) {
445 this->Component1 = Str2EnumVariable(l, LuaToString(l, -1));
446 } else if (!strcmp(key, "Variable2")) {
447 const char *const name = LuaToString(l, -1);
448 this->Index2 = UnitTypeVar.VariableNameLookup[name];
449 if (this->Index2 == -1) {
450 LuaError(l, "unknown variable '%s'" _C_ LuaToString(l, -1));
451 }
452 } else if (!strcmp(key, "Component2")) {
453 this->Component2 = Str2EnumVariable(l, LuaToString(l, -1));
454 } else if (!strcmp(key, "Centered")) {
455 this->Centered = LuaToBoolean(l, -1);
456 } else {
457 LuaError(l, "'%s' invalid for method 'FormattedText2' in DefinePanelContents" _C_ key);
458 }
459 }
460 }
461
462 /**
463 ** Return enum from string about variable component.
464 **
465 ** @param l Lua State.
466 ** @param s string to convert.
467 **
468 ** @return Corresponding value.
469 ** @note Stop on error.
470 */
Str2EnumUnit(lua_State * l,const char * s)471 static EnumUnit Str2EnumUnit(lua_State *l, const char *s)
472 {
473 static struct {
474 const char *s;
475 EnumUnit e;
476 } list[] = {
477 {"ItSelf", UnitRefItSelf},
478 {"Inside", UnitRefInside},
479 {"Container", UnitRefContainer},
480 {"Worker", UnitRefWorker},
481 {"Goal", UnitRefGoal},
482 {0, UnitRefItSelf}
483 }; // List of possible values.
484
485 for (int i = 0; list[i].s; ++i) {
486 if (!strcmp(s, list[i].s)) {
487 return list[i].e;
488 }
489 }
490 LuaError(l, "'%s' is a invalid Unit reference" _C_ s);
491 return UnitRefItSelf;
492 }
493
Parse(lua_State * l)494 /* virtual */ void CContentTypeIcon::Parse(lua_State *l)
495 {
496 for (lua_pushnil(l); lua_next(l, -2); lua_pop(l, 1)) {
497 const char *key = LuaToString(l, -2);
498 if (!strcmp(key, "Unit")) {
499 this->UnitRef = Str2EnumUnit(l, LuaToString(l, -1));
500 } else {
501 LuaError(l, "'%s' invalid for method 'Icon' in DefinePanelContents" _C_ key);
502 }
503 }
504 }
505
Parse(lua_State * l)506 /* virtual */ void CContentTypeLifeBar::Parse(lua_State *l)
507 {
508 for (lua_pushnil(l); lua_next(l, -2); lua_pop(l, 1)) {
509 const char *key = LuaToString(l, -2);
510 if (!strcmp(key, "Variable")) {
511 if (lua_isstring(l, -1)) {
512 const char *const name = LuaToString(l, -1);
513 this->Index = UnitTypeVar.VariableNameLookup[name];
514 if (this->Index == -1) {
515 LuaError(l, "unknown variable '%s'" _C_ name);
516 }
517 } else {
518 if (!lua_istable(l, -1)) {
519 LuaError(l, "incorrect argument, need list of size 2 with {function, max} or a string with the name of a unit variable");
520 }
521 for (lua_pushnil(l); lua_next(l, -2); lua_pop(l, 1)) {
522 const char *key = LuaToString(l, -2);
523 if (!strcmp(key, "Max")) {
524 this->ValueMax = LuaToNumber(l, -1);
525 } else if (!strcmp(key, "Value")) {
526 this->ValueFunc = CclParseNumberDesc(l);
527 lua_pushnil(l); // ParseStringDesc eat token
528 } else {
529 lua_pop(l, 1);
530 LuaError(l, "unknow value '%s'" _C_ key);
531 }
532 }
533 if (this->ValueMax == -1) {
534 this->ValueMax = 100;
535 }
536 if (this->ValueFunc == NULL) {
537 LuaError(l, "didn't set a value function");
538 }
539 }
540 } else if (!strcmp(key, "Height")) {
541 this->Height = LuaToNumber(l, -1);
542 } else if (!strcmp(key, "Width")) {
543 this->Width = LuaToNumber(l, -1);
544 } else if (!strcmp(key, "Colors")) {
545 if (!lua_istable(l, -1)) {
546 LuaError(l, "incorrect argument, need list");
547 }
548 const int color_len = lua_rawlen(l, -1);
549 if (color_len == 0) {
550 LuaError(l, "need at least one {percentage, color} pair, got 0");
551 }
552 this->colors = new unsigned int[color_len];
553 this->values = new unsigned int[color_len];
554 int i = 0;
555 for (lua_pushnil(l); lua_next(l, -2); lua_pop(l, 1)) {
556 if (!lua_istable(l, -1) || lua_rawlen(l, -1) != 2) {
557 LuaError(l, "incorrect argument, need list of size 2 with {percentage, color}");
558 }
559 this->values[i] = LuaToNumber(l, -1, 1);
560 const char *const colorName = LuaToString(l, -1, 2);
561 this->colors[i] = GetColorIndexByName(colorName);
562 if (this->colors[i] == -1) {
563 LuaError(l, "incorrect color: '%s' " _C_ colorName);
564 }
565 i++;
566 }
567 if (this->values[color_len - 1] != 0) {
568 LuaError(l, "the last {percentage, color} pair must be for 0%%");
569 }
570 } else if (!strcmp(key, "Border")) {
571 if (lua_isboolean(l, -1)) {
572 if (LuaToBoolean(l, -1)) {
573 this->hasBorder = 1;
574 } else {
575 this->hasBorder = 0;
576 }
577 } else {
578 this->hasBorder = LuaToUnsignedNumber(l, -1);
579 if (this->hasBorder == 0) {
580 this->hasBorder = 1; // complete black is set to 1
581 }
582 }
583 } else {
584 LuaError(l, "'%s' invalid for method 'LifeBar' in DefinePanelContents" _C_ key);
585 }
586 }
587 // Default value and checking errors.
588 if (this->Height <= 0) {
589 this->Height = 5; // Default value.
590 }
591 if (this->Width <= 0) {
592 this->Width = 50; // Default value.
593 }
594 if (this->Index == -1 && this->ValueFunc == NULL) {
595 LuaError(l, "variable undefined for LifeBar");
596 }
597 if (this->colors == NULL || this->values == NULL) {
598 this->colors = new unsigned int[4];
599 this->values = new unsigned int[4];
600
601 this->values[0] = 75;
602 this->values[1] = 50;
603 this->values[2] = 25;
604 this->values[3] = 0;
605
606 this->colors[0] = GetColorIndexByName("dark-green");
607 this->colors[1] = GetColorIndexByName("yellow");
608 this->colors[2] = GetColorIndexByName("orange");;
609 this->colors[3] = GetColorIndexByName("red");
610 }
611 }
612
Parse(lua_State * l)613 /* virtual */ void CContentTypeCompleteBar::Parse(lua_State *l)
614 {
615 for (lua_pushnil(l); lua_next(l, -2); lua_pop(l, 1)) {
616 const char *key = LuaToString(l, -2);
617
618 if (!strcmp(key, "Variable")) {
619 const char *const name = LuaToString(l, -1);
620 this->varIndex = UnitTypeVar.VariableNameLookup[name];
621 if (this->varIndex == -1) {
622 LuaError(l, "unknown variable '%s'" _C_ name);
623 }
624 } else if (!strcmp(key, "Height")) {
625 this->height = LuaToNumber(l, -1);
626 } else if (!strcmp(key, "Width")) {
627 this->width = LuaToNumber(l, -1);
628 } else if (!strcmp(key, "Border")) {
629 this->hasBorder = LuaToBoolean(l, -1);
630 } else if (!strcmp(key, "Color")) {
631 const char *const colorName = LuaToString(l, -1);
632 this->colorIndex = GetColorIndexByName(colorName);
633 if (colorIndex == -1) {
634 LuaError(l, "incorrect color: '%s' " _C_ colorName);
635 }
636 } else {
637 LuaError(l, "'%s' invalid for method 'CompleteBar' in DefinePanelContents" _C_ key);
638 }
639 }
640 // Default value and checking errors.
641 if (this->height <= 0) {
642 this->height = 5; // Default value.
643 }
644 if (this->width <= 0) {
645 this->width = 50; // Default value.
646 }
647 if (this->varIndex == -1) {
648 LuaError(l, "variable undefined for CompleteBar");
649 }
650 }
651
652 //@}
653