Merge branch '138-toggle-free-look-with-hotkey' into 'main/atys-live'
[ryzomcore.git] / nel / src / gui / interface_expr.cpp
blobc10627e02179ca3faf793b7f912dcfcfc45c99c0
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2013 Laszlo KIS-ADAM (dfighter) <dfighter1985@gmail.com>
6 // Copyright (C) 2020 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
7 //
8 // This program is free software: you can redistribute it and/or modify
9 // it under the terms of the GNU Affero General Public License as
10 // published by the Free Software Foundation, either version 3 of the
11 // License, or (at your option) any later version.
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU Affero General Public License for more details.
18 // You should have received a copy of the GNU Affero General Public License
19 // along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "stdpch.h"
23 #include "nel/misc/algo.h"
24 #include <algorithm>
25 #include "nel/gui/db_manager.h"
26 #include "nel/gui/interface_expr.h"
27 #include "nel/gui/interface_expr_node.h"
29 using namespace std;
30 using namespace NLMISC;
32 #ifdef DEBUG_NEW
33 #define new DEBUG_NEW
34 #endif
36 namespace NLGUI
39 void ifexprufct_forcelink();
41 // Needed because otherwise GCC and co. omit the code in interface_expr_user_fct.cpp code
42 // causing the GUI not to work.
43 // It all happens because no function is called *directly* from that module.
44 struct LinkTrickster
46 LinkTrickster()
48 ifexprufct_forcelink();
52 LinkTrickster linkTrickster;
54 // Yoyo: Act like a singleton, else registerUserFct may crash.
55 CInterfaceExpr::TUserFctMap *CInterfaceExpr::_UserFct= NULL;
57 static const std::string ExprLuaId="lua:";
59 //==================================================================
60 // release memory
61 void CInterfaceExpr::release()
63 delete _UserFct;
64 _UserFct = NULL;
67 //==================================================================
68 void formatLuaCall(const std::string &expr, std::string &tempStr)
70 /* Call the LUA interface exp fct, with the script as line, and resolve string definition conflicts:
71 eg: replace
72 lua:getSkillFromName('SM')
73 into
74 lua('getSkillFromName(\"SM\")')
76 tempStr= expr.substr(ExprLuaId.size()); // eg: tempStr= getSkillFromName('SM')
77 while(strFindReplace(tempStr, "'", "\\\"")); // eg: tempStr= getSkillFromName(\"SM\")
78 tempStr= string("lua('") + tempStr + "')"; // eg: tempStr= lua('getSkillFromName(\"SM\")')
81 //==================================================================
82 bool CInterfaceExpr::eval(const std::string &expr, CInterfaceExprValue &result, std::vector<ICDBNode *> *nodes, bool noFctCalls /* = false */)
84 // Yoyo: Special InterfaceExpr Form to execute lua code?
85 if(expr.compare(0, ExprLuaId.size(), ExprLuaId) ==0 )
87 std::string tempStr;
88 formatLuaCall(expr, tempStr);
89 return evalExpr(tempStr.c_str(), result, nodes, noFctCalls) != NULL;
91 else
93 return evalExpr(expr.c_str(), result, nodes, noFctCalls) != NULL;
97 //==================================================================
98 CInterfaceExprNode *CInterfaceExpr::buildExprTree(const std::string &expr)
100 CInterfaceExprNode *node;
102 // Yoyo: Special InterfaceExpr Form to execute lua code?
103 if(expr.compare(0, ExprLuaId.size(), ExprLuaId) ==0 )
105 std::string tempStr;
106 formatLuaCall(expr, tempStr);
107 if (!buildExprTree(tempStr.c_str(), node)) return NULL;
109 else
111 if (!buildExprTree(expr.c_str(), node)) return NULL;
114 return node;
118 //==================================================================
119 void CInterfaceExpr::registerUserFct(const char *name,TUserFct fct)
121 if(!_UserFct) _UserFct= new TUserFctMap;
123 nlassert(fct != NULL);
124 (*_UserFct)[std::string(name)] = fct;
127 //==================================================================
128 /** tool fct : skip space, tab and carret-returns
130 static const char *skipBlank(const char *start)
132 nlassert(start);
133 while (*start == ' ' || *start == '\t' || *start == '\r' || *start == '\n') ++start;
134 return start;
137 //==================================================================
138 const char *CInterfaceExpr::evalExpr(const char *expr, CInterfaceExprValue &result, std::vector<ICDBNode *> *nodes, bool noFctCalls)
140 nlassert(expr != NULL);
141 expr = skipBlank(expr);
142 if (isalpha(*expr)) // alpha character means this is a function name
144 return evalFct(expr, result, nodes, noFctCalls);
146 else if (*expr == '@') // is it a database entry ?
148 ++ expr;
149 expr = skipBlank(expr);
150 return evalDBEntry(expr, result, nodes);
153 // try to parse a literal value
154 const char *newExpr = result.initFromString(expr);
155 if (!newExpr)
157 nlwarning("<CInterfaceExpr::evalExpr> : syntax error : %s", expr);
158 return NULL;
160 return newExpr;
163 //==================================================================
164 const char *CInterfaceExpr::buildExprTree(const char *expr, CInterfaceExprNode *&result)
166 nlassert(expr != NULL);
167 expr = skipBlank(expr);
168 if (isalpha(*expr)) // alpha character means this is a function name
170 return buildFctNode(expr, result);
172 else if (*expr == '@') // is it a database entry ?
174 ++ expr;
175 expr = skipBlank(expr);
176 return buildDBEntryNode(expr, result);
178 else
180 CInterfaceExprValue value;
181 // try to parse a literal value
182 const char *newExpr = value.initFromString(expr);
183 if (!newExpr)
185 nlwarning("<CInterfaceExpr::buildExprTree> : syntax error : %s", expr);
186 return NULL;
188 CInterfaceExprNodeValue *node = new CInterfaceExprNodeValue;
189 node->Value = value;
190 result = node;
191 return newExpr;
193 return NULL;
197 //==================================================================
198 const char *CInterfaceExpr::evalFct(const char *expr, CInterfaceExprValue &result, std::vector<ICDBNode *> *nodes, bool noFctCalls)
200 if(!_UserFct) _UserFct= new TUserFctMap;
202 const char *start = expr;
203 while (isalnum(*expr)) ++ expr;
204 std::string fctName(start, expr - start);
205 // find entry in the map
206 TUserFctMap::iterator fctIt = _UserFct->find(fctName);
207 if (fctIt == _UserFct->end())
209 nlwarning("<CInterfaceExpr::evalFct> : Unknown function %s", fctName.c_str());
210 return NULL;
212 nlassert(fctIt->second != NULL);
213 // eval list of arguments
214 TArgList argList;
215 expr = skipBlank(expr);
216 if (*expr != '(')
218 nlwarning("<CInterfaceExpr::evalFct> : '(' expected for function %s", fctName.c_str());
219 return NULL;
221 ++ expr;
222 expr = skipBlank(expr);
223 if (*expr != ')')
225 for(;;)
227 expr = skipBlank(expr);
228 // parse an argument
229 argList.push_back(CInterfaceExprValue());
230 expr = evalExpr(expr, argList.back(), nodes, noFctCalls);
231 if (expr == NULL) return NULL;
232 expr = skipBlank(expr);
233 if (*expr == ')') break;
234 // if it isn't the end of the expression, then we should find a ',' before next argument
235 if (*expr != ',')
237 nlwarning("<CInterfaceExpr::evalFct> : ',' expected in function %s", fctName.c_str());
238 return NULL;
240 ++ expr;
243 ++ expr;
244 // call the fct
245 if (!noFctCalls) // should we make terminal function calls ?
247 if (fctIt->second(argList, result)) return expr;
249 else
251 return expr;
253 return NULL;
256 //==================================================================
257 const char *CInterfaceExpr::buildFctNode(const char *expr, CInterfaceExprNode *&result)
259 if(!_UserFct) _UserFct= new TUserFctMap;
261 const char *start = expr;
262 while (isalnum(*expr)) ++ expr;
263 std::string fctName(start, expr - start);
264 // find entry in the map
265 TUserFctMap::iterator fctIt = _UserFct->find(fctName);
266 if (fctIt == _UserFct->end())
268 nlwarning("<CInterfaceExpr::buildFctNode> : Unknown function %s", fctName.c_str());
269 return NULL;
271 nlassert(fctIt->second != NULL);
272 // List of parameters
273 expr = skipBlank(expr);
274 if (*expr != '(')
276 nlwarning("<CInterfaceExpr::buildFctNode> : '(' expected for function %s", fctName.c_str());
277 return NULL;
279 ++ expr;
280 expr = skipBlank(expr);
281 std::vector<CInterfaceExprNode *> Params;
282 if (*expr != ')')
284 for(;;)
286 expr = skipBlank(expr);
287 // parse an argument
288 CInterfaceExprNode *node = NULL;
289 expr = buildExprTree(expr, node);
290 if (expr == NULL)
292 for(uint k = 0; k < Params.size(); ++k)
294 delete Params[k];
296 return NULL;
298 Params.push_back(node);
299 expr = skipBlank(expr);
300 if (*expr == ')') break;
301 // if it isn't the end of the expression, then we should find a ',' before next argument
302 if (*expr != ',')
304 for(uint k = 0; k < Params.size(); ++k)
306 delete Params[k];
308 nlwarning("CInterfaceExpr::evalFct : ',' expected in function %s", fctName.c_str());
309 return NULL;
311 ++ expr;
314 ++ expr;
315 CInterfaceExprNodeValueFnCall *node = new CInterfaceExprNodeValueFnCall;
316 node->Params.swap(Params);
317 node->Func = fctIt->second;
318 result = node;
319 return expr;
322 //==================================================================
323 const char *CInterfaceExpr::evalDBEntry(const char *expr, CInterfaceExprValue &result, std::vector<ICDBNode *> *nodes)
325 std::string dbEntry;
326 expr = unpackDBentry(expr, nodes, dbEntry);
327 if (!expr) return NULL;
328 // TestYoyo
329 //nlassert(NLGUI::CDBManager::getInstance()->getDbProp(dbEntry, false) || CInterfaceManager::getInstance()->getDbBranch(dbEntry));
330 // get the db value
331 CCDBNodeLeaf *nl = NLGUI::CDBManager::getInstance()->getDbProp(dbEntry);
332 if (nl)
334 if (nodes)
336 // insert node if not already present
337 if (std::find(nodes->begin(), nodes->end(), nl) == nodes->end())
339 nodes->push_back(nl);
342 result.setInteger(nl->getValue64());
343 return expr;
345 else
347 CCDBNodeBranch *nb = NLGUI::CDBManager::getInstance()->getDbBranch(dbEntry);
348 if (nodes && nb)
350 if (std::find(nodes->begin(), nodes->end(), nb) == nodes->end())
352 nodes->push_back(nb);
355 if (!nb) return NULL;
356 result.setInteger(0);
357 return expr;
359 return NULL;
362 //==================================================================
363 const char *CInterfaceExpr::buildDBEntryNode(const char *expr, CInterfaceExprNode *&result)
365 std::string dbEntry;
366 bool indirection;
367 const char *startChar = expr;
368 expr = unpackDBentry(expr, NULL, dbEntry, &indirection);
369 if (!expr) return NULL;
370 if (indirection)
372 // special node with no optimisation
373 CInterfaceExprNodeDependantDBRead *node = new CInterfaceExprNodeDependantDBRead;
374 node->Expr.resize(expr - startChar + 1);
375 std::copy(startChar, expr, node->Expr.begin() + 1);
376 node->Expr[0] = '@';
377 result = node;
378 return expr;
380 else
382 // TestYoyo
383 //nlassert(NLGUI::CDBManager::getInstance()->getDbProp(dbEntry, false) || CInterfaceManager::getInstance()->getDbBranch(dbEntry));
384 CCDBNodeLeaf *nl = NLGUI::CDBManager::getInstance()->getDbProp(dbEntry);
385 if (nl)
387 CInterfaceExprNodeDBLeaf *node = new CInterfaceExprNodeDBLeaf;
388 node->Leaf = nl;
389 result = node;
390 return expr;
392 else
394 CCDBNodeBranch *nb = NLGUI::CDBManager::getInstance()->getDbBranch(dbEntry);
395 if (nb)
397 CInterfaceExprNodeDBBranch *node = new CInterfaceExprNodeDBBranch;
398 node->Branch = nb;
399 result = node;
400 return expr;
403 return NULL;
407 //==================================================================
408 const char *CInterfaceExpr::unpackDBentry(const char *expr, std::vector<ICDBNode *> *nodes, std::string &dest, bool *hasIndirections /* = NULL*/)
410 std::string entryName;
411 bool indirection = false;
412 for (;;)
414 if (*expr == '[')
416 indirection = true;
417 ++ expr;
418 std::string subEntry;
419 expr = unpackDBentry(expr, nodes, subEntry);
420 if (!expr) return NULL;
421 // Read DB Index Offset.
422 sint32 indirectionOffset= 0;
423 if (*expr == '-' || *expr =='+' )
425 bool negative= *expr == '-';
426 std::string offsetString;
427 ++ expr;
428 while(*expr!=0 && isdigit(*expr))
430 offsetString.push_back(*expr);
431 ++ expr;
433 // get offset
434 fromString(offsetString, indirectionOffset);
435 if(negative)
436 indirectionOffset= -indirectionOffset;
438 // Test end of indirection
439 if (*expr != ']')
441 nlwarning("CInterfaceExpr::unpackDBentry: ']' expected");
442 return NULL;
444 ++ expr;
445 // get the db value at sub entry
446 // TestYoyo
447 //nlassert(NLGUI::CDBManager::getInstance()->getDbProp(subEntry, false) || CInterfaceManager::getInstance()->getDbBranch(subEntry));
448 CCDBNodeLeaf *nl = NLGUI::CDBManager::getInstance()->getDbProp(subEntry);
449 if (nodes)
451 if (std::find(nodes->begin(), nodes->end(), nl) == nodes->end())
453 nodes->push_back(nl);
456 // compute indirection, (clamp).
457 sint32 indirectionValue= nl->getValue32() + indirectionOffset;
458 indirectionValue= std::max((sint32)0, indirectionValue);
460 // Append to entry name.
461 entryName += NLMISC::toString(indirectionValue);
463 else if (isalnum(*expr) || *expr == '_' || *expr == ':')
465 entryName += *expr;
466 ++ expr;
468 else
470 break;
473 if (hasIndirections)
475 *hasIndirections = indirection;
477 dest = entryName;
478 return expr;
482 //==================================================================
483 bool CInterfaceExpr::evalAsInt(const std::string &expr, sint64 &dest)
485 CInterfaceExprValue result;
486 if (!eval(expr, result)) return false;
487 if (!result.toInteger())
489 nlwarning("<CInterfaceExpr::evalAsInt> Can't convert value to an integer, expr = %s", expr.c_str());
490 return false;
492 dest = result.getInteger();
493 return true;
496 //==================================================================
497 bool CInterfaceExpr::evalAsDouble(const std::string &expr, double &dest)
499 CInterfaceExprValue result;
500 if (!eval(expr, result)) return false;
501 if (!result.toDouble())
503 nlwarning("<CInterfaceExpr::evalAsDouble> Can't convert value to a double, expr = %s", expr.c_str());
504 return false;
506 dest = result.getDouble();
507 return true;
510 //==================================================================
511 bool CInterfaceExpr::evalAsBool(const std::string &expr, bool &dest)
513 CInterfaceExprValue result;
514 if (!eval(expr, result)) return false;
515 if (!result.toBool())
517 nlwarning("<CInterfaceExpr::evalAsBool> Can't convert value to a boolean, expr = %s", expr.c_str());
518 return false;
520 dest = result.getBool();
521 return true;
524 //==================================================================
525 bool CInterfaceExpr::evalAsString(const std::string &expr, std::string &dest)
527 CInterfaceExprValue result;
528 if (!eval(expr, result)) return false;
529 if (!result.toString())
531 nlwarning("<CInterfaceExpr::evalAsString> Can't convert value to a string, expr = %s", expr.c_str());
532 return false;
534 dest = result.getString();
535 return true;
538 //==================================================================
539 //==================================================================
540 //==================================================================
541 //==================================================================
544 //==================================================================
545 bool CInterfaceExprValue::toBool()
547 switch(_Type)
549 case Boolean: return true;
550 case Integer: setBool(_IntegerValue != 0); return true;
551 case Double: setBool(_DoubleValue != 0); return true;
552 case String: return evalBoolean(_StringValue.c_str()) != NULL;
553 default: break;
555 return false;
559 //==================================================================
560 bool CInterfaceExprValue::toInteger()
562 switch(_Type)
564 case Boolean: setInteger(_BoolValue ? 1 : 0); return true;
565 case Integer: return true;
566 case Double: setInteger((sint64) _DoubleValue); return true;
567 case String:
568 if (evalNumber(_StringValue.c_str())) return toInteger();
569 return false;
570 case RGBA: setInteger((sint64) _RGBAValue); return true;
571 default: break;
573 return false;
576 //==================================================================
577 bool CInterfaceExprValue::toDouble()
579 switch(_Type)
581 case Boolean: setDouble(_BoolValue ? 1 : 0); return true;
582 case Integer: setDouble((double) _IntegerValue); return true;
583 case Double: return true;
584 case String:
585 if (evalNumber(_StringValue.c_str())) return toBool();
586 return false;
587 case RGBA: setDouble((double) _RGBAValue); return true;
588 default: break;
590 return false;
593 //==================================================================
594 bool CInterfaceExprValue::toString()
596 switch(_Type)
598 case Boolean: setString(_BoolValue ? "true" : "false"); return true;
599 case Integer: setString(NLMISC::toString(_IntegerValue)); return true;
600 case Double: setString(NLMISC::toString("%.2f", _DoubleValue)); return true;
601 case String: return true;
602 case RGBA:
604 uint r,g,b,a;
605 r= (_RGBAValue&0xff);
606 g= ((_RGBAValue>>8)&0xff);
607 b= ((_RGBAValue>>16)&0xff);
608 a= ((_RGBAValue>>24)&0xff);
609 setString(NLMISC::toString("%d %d %d %d", r, g, b, a));
610 return true;
612 default: break;
614 return false;
617 //==================================================================
618 bool CInterfaceExprValue::toRGBA()
620 switch(_Type)
622 case RGBA:
623 return true;
625 case Integer:
626 setRGBA(NLMISC::CRGBA((uint8)(_IntegerValue&0xff), (uint8)((_IntegerValue>>8)&0xff),
627 (uint8)((_IntegerValue>>16)&0xff), (uint8)((_IntegerValue>>24)&0xff)));
628 return true;
630 case String:
631 setRGBA( NLMISC::CRGBA::stringToRGBA(_StringValue.c_str()));
632 return true;
634 default:
635 break;
637 return false;
640 //==================================================================
641 bool CInterfaceExprValue::isNumerical() const
643 return _Type == Boolean || _Type == Integer || _Type == Double;
646 //==================================================================
647 const char *CInterfaceExprValue::initFromString(const char *expr)
649 nlassert(expr);
650 expr = skipBlank(expr);
651 if (isdigit(*expr) || *expr == '.' || *expr == '-') return evalNumber(expr);
652 switch(*expr)
654 case 't':
655 case 'T':
656 case 'f':
657 case 'F':
658 return evalBoolean(expr);
659 case '\'':
660 return evalString(expr);
661 default:
662 return NULL;
666 //==================================================================
667 const char *CInterfaceExprValue::evalBoolean(const char *expr)
669 nlassert(expr);
670 expr = skipBlank(expr);
671 if (toupper(expr[0]) == 'T' &&
672 toupper(expr[1]) == 'R' &&
673 toupper(expr[2]) == 'U' &&
674 toupper(expr[3]) == 'E')
676 setBool(true);
677 return expr + 4;
680 if (toupper(expr[0]) == 'F' &&
681 toupper(expr[1]) == 'A' &&
682 toupper(expr[2]) == 'L' &&
683 toupper(expr[3]) == 'S' &&
684 toupper(expr[4]) == 'E')
686 setBool(false);
687 return expr + 5;
689 return NULL;
692 //==================================================================
693 const char *CInterfaceExprValue::evalNumber(const char *expr)
695 bool negative;
696 bool hasPoint = false;
698 expr = skipBlank(expr);
700 if (*expr == '-')
702 negative = true;
703 ++ expr;
704 expr = skipBlank(expr);
706 else
708 negative = false;
711 const char *start = expr;
712 while (*expr == '.' || isdigit(*expr))
714 if (*expr == '.') hasPoint = true;
715 ++ expr;
717 if (start == expr) return NULL;
718 if (!hasPoint)
720 sint64 value = 0;
721 // this is an integer
722 for (const char *nbPtr = start; nbPtr < expr; ++ nbPtr)
724 value *= 10;
725 value += (sint64) (*nbPtr - '0');
727 setInteger(negative ? - value : value);
728 return expr;
730 else // floating point value : use scanf
732 // well, for now, we only parse a float
733 float value;
734 std::string floatValue(start, expr - start);
735 if (fromString(floatValue, value))
737 setDouble(negative ? - value : value);
738 return expr;
740 else
742 return NULL;
747 //==================================================================
748 const char *CInterfaceExprValue::evalString(const char *expr)
750 expr = skipBlank(expr);
751 if (*expr != '\'') return NULL;
752 ++expr;
753 std::string str;
754 for (;;)
756 if (*expr == '\0')
758 nlwarning("CInterfaceExprValue::evalString : end of buffer encountered in a string");
759 return NULL;
761 else
762 if (*expr == '\'')
764 ++ expr;
765 break;
767 if (*expr == '\\') // special char
769 ++ expr;
770 switch (*expr)
772 case 't': str += '\t'; break;
773 case 'r': str += '\r'; break;
774 case 'n': str += '\n'; break;
775 case '\'': str += '\''; break;
776 case '"': str += '"'; break;
777 case '\\': str += '\\'; break;
778 case '\n':
779 case '\r':
780 // string continue on next line, so do nothing
781 break;
782 case '\0': continue;
783 default:
784 nlwarning("CInterfaceExprValue::evalString : unknown escape sequence : \\%c", *expr);
785 if (*expr) str += *expr;
786 break;
789 else if (*expr == '\n' || *expr == '\r')
791 nlwarning("CInterfaceExprValue::evalString : line break encountered in a string");
792 return NULL;
794 else
796 str += *expr;
798 ++ expr;
800 setString(str);
801 return expr;
804 //==================================================================
805 bool CInterfaceExprValue::toType(TType type)
807 switch(type)
809 case Boolean: return toBool();
810 case Integer: return toInteger();
811 case Double: return toDouble();
812 case String: return toString();
813 case RGBA: return toRGBA();
814 default: return false;
819 //==================================================================
820 void CInterfaceExprValue::clean()
822 switch (_Type)
824 case String: _StringValue.clear(); break;
825 case UserType: delete _UserTypeValue; break;
826 default: break;
830 //==================================================================
831 void CInterfaceExprValue::setUserType(CInterfaceExprUserType *value)
833 if (_Type == UserType && value == _UserTypeValue) return;
834 clean();
835 _Type = UserType;
836 _UserTypeValue = value;
839 //==================================================================
840 bool CInterfaceExprValue::getBool() const
842 if (_Type != Boolean)
844 nlwarning("<CInterfaceExprValue::getBool> bad type!");
845 return false;
847 return _BoolValue;
850 //==================================================================
851 sint64 CInterfaceExprValue::getInteger() const
853 if (_Type != Integer)
855 nlwarning("<CInterfaceExprValue::getInteger> bad type!");
856 return 0;
858 return _IntegerValue;
861 //==================================================================
862 double CInterfaceExprValue::getDouble() const
864 if (_Type != Double)
866 nlwarning("<CInterfaceExprValue::getDouble> bad type!");
867 return 0;
869 return _DoubleValue;
872 //==================================================================
873 const std::string &CInterfaceExprValue::getString() const
875 if (_Type != String)
877 nlwarning("<CInterfaceExprValue::getString> bad type!");
878 static const std::string empty;
879 return empty;
881 return _StringValue;
884 //==================================================================
885 NLMISC::CRGBA CInterfaceExprValue::getRGBA() const
887 if (_Type != RGBA)
889 nlwarning("<CInterfaceExprValue::getRGBA> bad type!");
890 return CRGBA::White;
892 NLMISC::CRGBA col;
893 col.R = (uint8)(_RGBAValue&0xff);
894 col.G = (uint8)((_RGBAValue>>8)&0xff);
895 col.B = (uint8)((_RGBAValue>>16)&0xff);
896 col.A = (uint8)((_RGBAValue>>24)&0xff);
897 return col;
900 //==================================================================
901 CInterfaceExprUserType *CInterfaceExprValue::getUserType() const
903 if (_Type != UserType)
905 nlwarning("<CInterfaceExprValue::getUserType> bad type!");
906 return NULL;
908 return _UserTypeValue;
911 //==================================================================
912 CInterfaceExprValue::CInterfaceExprValue(const CInterfaceExprValue &other) : _Type(NoType)
914 *this = other;
917 //==================================================================
918 CInterfaceExprValue &CInterfaceExprValue::operator = (const CInterfaceExprValue &other)
920 if (this != &other)
922 clean();
923 switch(other._Type)
925 case Boolean: _BoolValue = other._BoolValue; break;
926 case Integer: _IntegerValue = other._IntegerValue; break;
927 case Double: _DoubleValue = other._DoubleValue; break;
928 case String: _StringValue = other._StringValue; break;
929 case RGBA: _RGBAValue = other._RGBAValue; break;
930 case UserType:
931 if (other._UserTypeValue != NULL)
933 _UserTypeValue = other._UserTypeValue->clone();
935 else
937 _UserTypeValue = NULL;
939 break;
940 case NoType: break;
941 default:
942 nlwarning("<CInterfaceExprValue::operator=> bad source type") ;
943 return *this;
944 break;
946 _Type = other._Type;
948 return *this;