CHANGED: #1471 CInterfaceExpr, CInterfaceExprNode and related classes are now in NELGUI and under NLGUI namespace.

This commit is contained in:
dfighter1985 2012-05-25 03:21:03 +02:00
parent 1067d4b491
commit 5b51fcfe84
39 changed files with 1607 additions and 1604 deletions

View file

@ -0,0 +1,239 @@
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef CL_INTERFACE_EXPR_H
#define CL_INTERFACE_EXPR_H
#include "nel/misc/ucstring.h"
#include "nel/misc/rgba.h"
namespace NLMISC{
class ICDBNode;
class CCDBNodeLeaf;
class CCDBNodeBranch;
}
namespace NLGUI
{
struct CInterfaceExprUserType;
class CInterfaceExprNode;
/** a value that can be returned by a CInterfaceExpr instance
* It supports basic type;
* It can be extended by user defined types
*/
class CInterfaceExprValue
{
public:
enum TType { Boolean = 0, Integer, Double, String, RGBA, UserType, NoType };
public:
// default ctor
CInterfaceExprValue() : _Type(NoType) {}
// copy ctor
CInterfaceExprValue(const CInterfaceExprValue &other);
// assignment operator
CInterfaceExprValue &operator = (const CInterfaceExprValue &other);
// dtor
~CInterfaceExprValue() { clean(); }
TType getType() const { return _Type; }
// get. Should be used only if the type is valid
bool getBool() const;
sint64 getInteger() const;
double getDouble() const;
std::string getString() const;
NLMISC::CRGBA getRGBA() const;
const ucstring &getUCString() const;
CInterfaceExprUserType *getUserType() const;
// set
void setBool(bool value) { clean(); _Type = Boolean; _BoolValue = value; }
void setInteger(sint64 value) { clean(); _Type = Integer; _IntegerValue = value; }
void setDouble(double value) { clean(); _Type = Double; _DoubleValue = value; }
void setString(const std::string &value) { clean(); _Type = String; _StringValue = value; }
void setUCString(const ucstring &value) { clean(); _Type = String; _StringValue = value; }
void setRGBA(NLMISC::CRGBA value) { clean(); _Type = RGBA; _RGBAValue = (uint32)(value.R+(value.G<<8)+(value.B<<16)+(value.A<<24)); }
void setUserType(CInterfaceExprUserType *value);
// reset this object to initial state (no type)
void clean();
// conversions. They return true if success
bool toBool();
bool toInteger();
bool toDouble();
bool toString();
bool toType(TType type);
bool toRGBA();
// test if the value if a bool, double, or integer
bool isNumerical() const;
/** evaluate a from a string
* \param expr : where to start the evaluation
* \return the position following the token, or NULL if the parsing failed
*/
const char *initFromString(const char *expr);
/////////////////////////////////////////////////////////////////////////////////////////////
private:
TType _Type;
union
{
bool _BoolValue;
sint64 _IntegerValue;
double _DoubleValue;
CInterfaceExprUserType *_UserTypeValue;
uint32 _RGBAValue;
};
ucstring _StringValue; // well, can't fit in union, unless we do some horrible hack..
private:
const char *evalBoolean(const char *expr);
const char *evalNumber(const char *expr);
const char *evalString(const char *expr);
};
/**
* Base class for user defined types that are use by the 'CInterfaceExprValue' class
* Derivers should include the 'clone' method
*
* CInterfaceExprValue instances have ownership of this object.
*
* \author Nicolas Vizerie
* \author Nevrax France
* \date 2003
*/
struct CInterfaceExprUserType
{
// cloning method
virtual CInterfaceExprUserType *clone() const = 0;
// dtor
virtual ~CInterfaceExprUserType() {}
};
/** Evaluate expressions used in interface.
* It can retrieve values from the database.
* It can also build a list of database values it depends of.
*
* An expression can be :
*
* - a string : 'toto', 'abcd', 'a\nbcd', 'a\\t', the escape sequences are the one of C
* - a integer 1, 2, 3
* - a double 1.1, 2.2
* - a database entry : @ui:interface:toto:truc. If the address is a leaf, it returns the leaf value and put an observer on it. If not a leaf, it returns 0, but put an observer on it.
* - a database indirection @db:value[db:index] is replaced by @db:value0 if db:index == 0 for example
* - a user function call : fct(expr0, epxr1, ...).
*
* NB : The lua language has been integrated since then (2005), and should be more suited
* for most of the tasks.
*
*
* \author Nicolas Vizerie
* \author Nevrax France
* \date 2002
*/
class CInterfaceExpr
{
public:
// list of argument for a function
typedef std::vector<CInterfaceExprValue> TArgList;
/** prototype of a user callable function
* It should return true if the result is meaningful. If not, the rest of the evaluation is stopped
*/
typedef bool (* TUserFct) (TArgList &args, CInterfaceExprValue &result);
public:
// release memory
static void release();
/** This try to eval the provided expression.
* - This returns a result
* - This eventually fill a vector with a set of database entries it has dependencies on
* \param expr The expression to evaluate
* \param result The result value
* \param nodes If not NULL, will be filled with the database nodes this expression depends on
* Node will only be inserted once, so we end up with a set of node (not ordered)
* \param noFctCalls when set to true, the terminal function calls will not be made, so the evaluation is only used to see which database entries the expression depends on.
*/
static bool eval(const std::string &expr, CInterfaceExprValue &result, std::vector<NLMISC::ICDBNode *> *nodes = NULL, bool noFctCalls = false);
/** Build a tree from the given expression so that it can be evaluated quickly.
* This is useful for a fixed expression that must be evaluated often
*/
static CInterfaceExprNode *buildExprTree(const std::string &expr);
/** Register a function that can have several arguments
* // NB : this is case sensitive
*/
static void registerUserFct(const char *name, TUserFct fct);
// Simple evaluations
static bool evalAsInt(const std::string &expr, sint64 &dest);
static bool evalAsDouble(const std::string &expr, double &dest);
static bool evalAsBool(const std::string &expr, bool &dest);
static bool evalAsString(const std::string &expr, std::string &dest);
/////////////////////////////////////////////////////////////////////////////////////////////
private:
// map of user functions
typedef std::map<std::string, TUserFct> TUserFctMap;
private:
static TUserFctMap *_UserFct;
private:
/** eval the value of a single expression
* \return position to the next valid character
*/
static const char *evalExpr(const char *expr, CInterfaceExprValue &result, std::vector<NLMISC::ICDBNode *> *nodes, bool noFctCalls);
static const char *evalFct(const char *expr,CInterfaceExprValue &result,std::vector<NLMISC::ICDBNode *> *nodes, bool noFctCalls);
static const char *evalDBEntry(const char *expr,CInterfaceExprValue &result,std::vector<NLMISC::ICDBNode *> *nodes);
public:
static const char *unpackDBentry(const char *expr, std::vector<NLMISC::ICDBNode *> *nodes, std::string &dest, bool *hasIndirections = NULL);
/** Build tree of a single expression
* \return position to the next valid character
*/
private:
static const char *buildExprTree(const char *expr, CInterfaceExprNode *&result);
static const char *buildFctNode(const char *expr, CInterfaceExprNode *&result);
static const char *buildDBEntryNode(const char *expr,CInterfaceExprNode *&result);
};
// helper macro to register user functions at startup
#define REGISTER_INTERFACE_USER_FCT(name, fct) \
const struct __InterUserFctRegister__##fct\
{\
__InterUserFctRegister__##fct() { CInterfaceExpr::registerUserFct(name, fct); }\
} __InterUserFctRegisterInstance__##fct;
// helper macro to declare a user function
// the code must follow
// arguments are available in 'args', result should be put in 'result'
#define DECLARE_INTERFACE_USER_FCT(name) \
bool name(CInterfaceExpr::TArgList &args, CInterfaceExprValue &result)
// helper macro to declare a C constant mirroring
#define DECLARE_INTERFACE_CONSTANT(_name, _cconst) \
static DECLARE_INTERFACE_USER_FCT(_name) \
{ \
result.setInteger(_cconst); \
return true; \
} \
REGISTER_INTERFACE_USER_FCT(#_name, _name)
}
#endif

View file

@ -0,0 +1,118 @@
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef CL_INTERFACE_EXPR_NODE_H
#define CL_INTERFACE_EXPR_NODE_H
#include "interface_expr.h"
namespace NLGUI
{
/** Base node of an interface expression parse tree
* \author Nicolas Vizerie
* \author Nevrax France
* \date 2003
*/
class CInterfaceExprNode
{
public:
virtual ~CInterfaceExprNode() {}
// eval result of expression, and eventually get the nodes the epression depends on
virtual void eval(CInterfaceExprValue &result) = 0;
// The same, but get db nodes the expression depends on (appended to vector)
virtual void evalWithDepends(CInterfaceExprValue &result, std::vector<NLMISC::ICDBNode *> &nodes) = 0;
// Get dependencies of the node (appended to vector)
virtual void getDepends(std::vector<NLMISC::ICDBNode *> &nodes) = 0;
};
// *******************************************************************************************************
/** A constant value already parsed by interface (in a interface expr parse tree)
*/
class CInterfaceExprNodeValue : public CInterfaceExprNode
{
public:
CInterfaceExprValue Value;
public:
virtual void eval(CInterfaceExprValue &result);
virtual void evalWithDepends(CInterfaceExprValue &result, std::vector<NLMISC::ICDBNode *> &nodes);
virtual void getDepends(std::vector<NLMISC::ICDBNode *> &nodes);
};
// *******************************************************************************************************
/** A fct call (in a interface expr parse tree)
*/
class CInterfaceExprNodeValueFnCall : public CInterfaceExprNode
{
public:
CInterfaceExpr::TUserFct Func;
// list of parameters
std::vector<CInterfaceExprNode *> Params;
public:
virtual void eval(CInterfaceExprValue &result);
virtual void evalWithDepends(CInterfaceExprValue &result, std::vector<NLMISC::ICDBNode *> &nodes);
virtual void getDepends(std::vector<NLMISC::ICDBNode *> &nodes);
virtual ~CInterfaceExprNodeValueFnCall();
};
// *******************************************************************************************************
/** A db leaf read (in a interface expr parse tree)
*/
class CInterfaceExprNodeDBLeaf : public CInterfaceExprNode
{
public:
class NLMISC::CCDBNodeLeaf *Leaf;
public:
virtual void eval(CInterfaceExprValue &result);
virtual void evalWithDepends(CInterfaceExprValue &result, std::vector<NLMISC::ICDBNode *> &nodes);
virtual void getDepends(std::vector<NLMISC::ICDBNode *> &nodes);
};
// *******************************************************************************************************
/** A db branch read (in a interface expr parse tree)
*/
class CInterfaceExprNodeDBBranch : public CInterfaceExprNode
{
public:
class NLMISC::CCDBNodeBranch *Branch;
public:
virtual void eval(CInterfaceExprValue &result);
virtual void evalWithDepends(CInterfaceExprValue &result, std::vector<NLMISC::ICDBNode *> &nodes);
virtual void getDepends(std::vector<NLMISC::ICDBNode *> &nodes);
};
// *******************************************************************************************************
/** A dependant db read (in a interface expr parse tree)
* This is rarely used so no real optim there..
*/
class CInterfaceExprNodeDependantDBRead : public CInterfaceExprNode
{
public:
std::string Expr;
public:
virtual void eval(CInterfaceExprValue &result);
virtual void evalWithDepends(CInterfaceExprValue &result, std::vector<NLMISC::ICDBNode *> &nodes);
virtual void getDepends(std::vector<NLMISC::ICDBNode *> &nodes);
};
}
#endif

View file

@ -326,6 +326,8 @@ public:
void buildFromHLS(float h, float l, float s); void buildFromHLS(float h, float l, float s);
//@} //@}
static CRGBA stringToRGBA( const char *ptr );
/// Swap the B and R components, to simulate a CBRGA /// Swap the B and R components, to simulate a CBRGA
void swapBR() void swapBR()

View file

@ -0,0 +1,939 @@
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "nel/misc/algo.h"
#include <algorithm>
#include "nel/gui/db_manager.h"
#include "nel/gui/interface_expr.h"
#include "nel/gui/interface_expr_node.h"
using namespace std;
using namespace NLMISC;
namespace NLGUI
{
// Yoyo: Act like a singleton, else registerUserFct may crash.
CInterfaceExpr::TUserFctMap *CInterfaceExpr::_UserFct= NULL;
static const std::string ExprLuaId="lua:";
//==================================================================
// release memory
void CInterfaceExpr::release()
{
delete _UserFct;
_UserFct = NULL;
}
//==================================================================
void formatLuaCall(const std::string &expr, std::string &tempStr)
{
/* Call the LUA interface exp fct, with the script as line, and resolve string definition conflicts:
eg: replace
lua:getSkillFromName('SM')
into
lua('getSkillFromName(\"SM\")')
*/
tempStr= expr.substr(ExprLuaId.size()); // eg: tempStr= getSkillFromName('SM')
while(strFindReplace(tempStr, "'", "\\\"")); // eg: tempStr= getSkillFromName(\"SM\")
tempStr= string("lua('") + tempStr + "')"; // eg: tempStr= lua('getSkillFromName(\"SM\")')
}
//==================================================================
bool CInterfaceExpr::eval(const std::string &expr, CInterfaceExprValue &result, std::vector<ICDBNode *> *nodes, bool noFctCalls /* = false */)
{
// Yoyo: Special InterfaceExpr Form to execute lua code?
if(expr.compare(0, ExprLuaId.size(), ExprLuaId) ==0 )
{
std::string tempStr;
formatLuaCall(expr, tempStr);
return evalExpr(tempStr.c_str(), result, nodes, noFctCalls) != NULL;
}
else
{
return evalExpr(expr.c_str(), result, nodes, noFctCalls) != NULL;
}
}
//==================================================================
CInterfaceExprNode *CInterfaceExpr::buildExprTree(const std::string &expr)
{
CInterfaceExprNode *node;
// Yoyo: Special InterfaceExpr Form to execute lua code?
if(expr.compare(0, ExprLuaId.size(), ExprLuaId) ==0 )
{
std::string tempStr;
formatLuaCall(expr, tempStr);
if (!buildExprTree(tempStr.c_str(), node)) return false;
}
else
{
if (!buildExprTree(expr.c_str(), node)) return false;
}
return node;
}
//==================================================================
void CInterfaceExpr::registerUserFct(const char *name,TUserFct fct)
{
if(!_UserFct) _UserFct= new TUserFctMap;
nlassert(fct != NULL);
(*_UserFct)[std::string(name)] = fct;
}
//==================================================================
/** tool fct : skip space, tab and carret-returns
*/
static const char *skipBlank(const char *start)
{
nlassert(start);
while (*start == ' ' || *start == '\t' || *start == '\r' || *start == '\n') ++start;
return start;
}
//==================================================================
const char *CInterfaceExpr::evalExpr(const char *expr, CInterfaceExprValue &result, std::vector<ICDBNode *> *nodes, bool noFctCalls)
{
nlassert(expr != NULL);
expr = skipBlank(expr);
if (isalpha(*expr)) // alpha character means this is a function name
{
return evalFct(expr, result, nodes, noFctCalls);
}
else if (*expr == '@') // is it a database entry ?
{
++ expr;
expr = skipBlank(expr);
return evalDBEntry(expr, result, nodes);
}
// try to parse a literal value
const char *newExpr = result.initFromString(expr);
if (!newExpr)
{
nlwarning("<CInterfaceExpr::evalExpr> : syntax error : %s", expr);
return NULL;
}
return newExpr;
}
//==================================================================
const char *CInterfaceExpr::buildExprTree(const char *expr, CInterfaceExprNode *&result)
{
nlassert(expr != NULL);
expr = skipBlank(expr);
if (isalpha(*expr)) // alpha character means this is a function name
{
return buildFctNode(expr, result);
}
else if (*expr == '@') // is it a database entry ?
{
++ expr;
expr = skipBlank(expr);
return buildDBEntryNode(expr, result);
}
else
{
CInterfaceExprValue value;
// try to parse a literal value
const char *newExpr = value.initFromString(expr);
if (!newExpr)
{
nlwarning("<CInterfaceExpr::buildExprTree> : syntax error : %s", expr);
return NULL;
}
CInterfaceExprNodeValue *node = new CInterfaceExprNodeValue;
node->Value = value;
result = node;
return newExpr;
}
return NULL;
}
//==================================================================
const char *CInterfaceExpr::evalFct(const char *expr, CInterfaceExprValue &result, std::vector<ICDBNode *> *nodes, bool noFctCalls)
{
if(!_UserFct) _UserFct= new TUserFctMap;
const char *start = expr;
while (isalnum(*expr)) ++ expr;
std::string fctName(start, expr - start);
// find entry in the map
TUserFctMap::iterator fctIt = _UserFct->find(fctName);
if (fctIt == _UserFct->end())
{
nlwarning("<CInterfaceExpr::evalFct> : Unknown function %s", fctName.c_str());
return NULL;
}
nlassert(fctIt->second != NULL);
// eval list of arguments
TArgList argList;
expr = skipBlank(expr);
if (*expr != '(')
{
nlwarning("<CInterfaceExpr::evalFct> : '(' expected for function %s", fctName.c_str());
return NULL;
}
++ expr;
expr = skipBlank(expr);
if (*expr != ')')
{
for(;;)
{
expr = skipBlank(expr);
// parse an argument
argList.push_back(CInterfaceExprValue());
expr = evalExpr(expr, argList.back(), nodes, noFctCalls);
if (expr == NULL) return NULL;
expr = skipBlank(expr);
if (*expr == ')') break;
// if it isn't the end of the expression, then we should find a ',' before next argument
if (*expr != ',')
{
nlwarning("<CInterfaceExpr::evalFct> : ',' expected in function %s", fctName.c_str());
return NULL;
}
++ expr;
}
}
++ expr;
// call the fct
if (!noFctCalls) // should we make terminal function calls ?
{
if (fctIt->second(argList, result)) return expr;
}
else
{
return expr;
}
return NULL;
}
//==================================================================
const char *CInterfaceExpr::buildFctNode(const char *expr, CInterfaceExprNode *&result)
{
if(!_UserFct) _UserFct= new TUserFctMap;
const char *start = expr;
while (isalnum(*expr)) ++ expr;
std::string fctName(start, expr - start);
// find entry in the map
TUserFctMap::iterator fctIt = _UserFct->find(fctName);
if (fctIt == _UserFct->end())
{
nlwarning("<CInterfaceExpr::buildFctNode> : Unknown function %s", fctName.c_str());
return NULL;
}
nlassert(fctIt->second != NULL);
// List of parameters
expr = skipBlank(expr);
if (*expr != '(')
{
nlwarning("<CInterfaceExpr::buildFctNode> : '(' expected for function %s", fctName.c_str());
return NULL;
}
++ expr;
expr = skipBlank(expr);
std::vector<CInterfaceExprNode *> Params;
if (*expr != ')')
{
for(;;)
{
expr = skipBlank(expr);
// parse an argument
CInterfaceExprNode *node = NULL;
expr = buildExprTree(expr, node);
if (expr == NULL)
{
for(uint k = 0; k < Params.size(); ++k)
{
delete Params[k];
}
return NULL;
}
Params.push_back(node);
expr = skipBlank(expr);
if (*expr == ')') break;
// if it isn't the end of the expression, then we should find a ',' before next argument
if (*expr != ',')
{
for(uint k = 0; k < Params.size(); ++k)
{
delete Params[k];
}
nlwarning("CInterfaceExpr::evalFct : ',' expected in function %s", fctName.c_str());
return NULL;
}
++ expr;
}
}
++ expr;
CInterfaceExprNodeValueFnCall *node = new CInterfaceExprNodeValueFnCall;
node->Params.swap(Params);
node->Func = fctIt->second;
result = node;
return expr;
}
//==================================================================
const char *CInterfaceExpr::evalDBEntry(const char *expr, CInterfaceExprValue &result, std::vector<ICDBNode *> *nodes)
{
std::string dbEntry;
expr = unpackDBentry(expr, nodes, dbEntry);
if (!expr) return NULL;
// TestYoyo
//nlassert(NLGUI::CDBManager::getInstance()->getDbProp(dbEntry, false) || CInterfaceManager::getInstance()->getDbBranch(dbEntry));
// get the db value
CCDBNodeLeaf *nl = NLGUI::CDBManager::getInstance()->getDbProp(dbEntry);
if (nl)
{
if (nodes)
{
// insert node if not already present
if (std::find(nodes->begin(), nodes->end(), nl) == nodes->end())
{
nodes->push_back(nl);
}
}
result.setInteger(nl->getValue64());
return expr;
}
else
{
CCDBNodeBranch *nb = NLGUI::CDBManager::getInstance()->getDbBranch(dbEntry);
if (nodes && nb)
{
if (std::find(nodes->begin(), nodes->end(), nb) == nodes->end())
{
nodes->push_back(nb);
}
}
if (!nb) return NULL;
result.setInteger(0);
return expr;
}
return NULL;
}
//==================================================================
const char *CInterfaceExpr::buildDBEntryNode(const char *expr, CInterfaceExprNode *&result)
{
std::string dbEntry;
bool indirection;
const char *startChar = expr;
expr = unpackDBentry(expr, NULL, dbEntry, &indirection);
if (!expr) return NULL;
if (indirection)
{
// special node with no optimisation
CInterfaceExprNodeDependantDBRead *node = new CInterfaceExprNodeDependantDBRead;
node->Expr.resize(expr - startChar + 1);
std::copy(startChar, expr, node->Expr.begin() + 1);
node->Expr[0] = '@';
result = node;
return expr;
}
else
{
// TestYoyo
//nlassert(NLGUI::CDBManager::getInstance()->getDbProp(dbEntry, false) || CInterfaceManager::getInstance()->getDbBranch(dbEntry));
CCDBNodeLeaf *nl = NLGUI::CDBManager::getInstance()->getDbProp(dbEntry);
if (nl)
{
CInterfaceExprNodeDBLeaf *node = new CInterfaceExprNodeDBLeaf;
node->Leaf = nl;
result = node;
return expr;
}
else
{
CCDBNodeBranch *nb = NLGUI::CDBManager::getInstance()->getDbBranch(dbEntry);
if (nb)
{
CInterfaceExprNodeDBBranch *node = new CInterfaceExprNodeDBBranch;
node->Branch = nb;
result = node;
return expr;
}
}
return NULL;
}
}
//==================================================================
const char *CInterfaceExpr::unpackDBentry(const char *expr, std::vector<ICDBNode *> *nodes, std::string &dest, bool *hasIndirections /* = NULL*/)
{
std::string entryName;
bool indirection = false;
for (;;)
{
if (*expr == '[')
{
indirection = true;
++ expr;
std::string subEntry;
expr = unpackDBentry(expr, nodes, subEntry);
if (!expr) return NULL;
// Read DB Index Offset.
sint32 indirectionOffset= 0;
if (*expr == '-' || *expr =='+' )
{
bool negative= *expr == '-';
std::string offsetString;
++ expr;
while(*expr!=0 && isdigit(*expr))
{
offsetString.push_back(*expr);
++ expr;
}
// get offset
fromString(offsetString, indirectionOffset);
if(negative)
indirectionOffset= -indirectionOffset;
}
// Test end of indirection
if (*expr != ']')
{
nlwarning("CInterfaceExpr::unpackDBentry: ']' expected");
return NULL;
}
++ expr;
// get the db value at sub entry
// TestYoyo
//nlassert(NLGUI::CDBManager::getInstance()->getDbProp(subEntry, false) || CInterfaceManager::getInstance()->getDbBranch(subEntry));
CCDBNodeLeaf *nl = NLGUI::CDBManager::getInstance()->getDbProp(subEntry);
if (nodes)
{
if (std::find(nodes->begin(), nodes->end(), nl) == nodes->end())
{
nodes->push_back(nl);
}
}
// compute indirection, (clamp).
sint32 indirectionValue= nl->getValue32() + indirectionOffset;
indirectionValue= std::max((sint32)0, indirectionValue);
// Append to entry name.
entryName += NLMISC::toString(indirectionValue);
}
else if (isalnum(*expr) || *expr == '_' || *expr == ':')
{
entryName += *expr;
++ expr;
}
else
{
break;
}
}
if (hasIndirections)
{
*hasIndirections = indirection;
}
dest = entryName;
return expr;
}
//==================================================================
bool CInterfaceExpr::evalAsInt(const std::string &expr, sint64 &dest)
{
CInterfaceExprValue result;
if (!eval(expr, result)) return false;
if (!result.toInteger())
{
nlwarning("<CInterfaceExpr::evalAsInt> Can't convert value to an integer, expr = %s", expr.c_str());
return false;
}
dest = result.getInteger();
return true;
}
//==================================================================
bool CInterfaceExpr::evalAsDouble(const std::string &expr, double &dest)
{
CInterfaceExprValue result;
if (!eval(expr, result)) return false;
if (!result.toDouble())
{
nlwarning("<CInterfaceExpr::evalAsDouble> Can't convert value to a double, expr = %s", expr.c_str());
return false;
}
dest = result.getDouble();
return true;
}
//==================================================================
bool CInterfaceExpr::evalAsBool(const std::string &expr, bool &dest)
{
CInterfaceExprValue result;
if (!eval(expr, result)) return false;
if (!result.toBool())
{
nlwarning("<CInterfaceExpr::evalAsBool> Can't convert value to a boolean, expr = %s", expr.c_str());
return false;
}
dest = result.getBool();
return true;
}
//==================================================================
bool CInterfaceExpr::evalAsString(const std::string &expr, std::string &dest)
{
CInterfaceExprValue result;
if (!eval(expr, result)) return false;
if (!result.toString())
{
nlwarning("<CInterfaceExpr::evalAsString> Can't convert value to a string, expr = %s", expr.c_str());
return false;
}
dest = result.getString();
return true;
}
//==================================================================
//==================================================================
//==================================================================
//==================================================================
//==================================================================
bool CInterfaceExprValue::toBool()
{
switch(_Type)
{
case Boolean: return true;
case Integer: setBool(_IntegerValue != 0); return true;
case Double: setBool(_DoubleValue != 0); return true;
case String: return evalBoolean(_StringValue.toString().c_str()) != NULL;
default: break;
}
return false;
}
//==================================================================
bool CInterfaceExprValue::toInteger()
{
switch(_Type)
{
case Boolean: setInteger(_BoolValue ? 1 : 0); return true;
case Integer: return true;
case Double: setInteger((sint64) _DoubleValue); return true;
case String:
if (evalNumber(_StringValue.toString().c_str())) return toInteger();
return false;
case RGBA: setInteger((sint64) _RGBAValue); return true;
default: break;
}
return false;
}
//==================================================================
bool CInterfaceExprValue::toDouble()
{
switch(_Type)
{
case Boolean: setDouble(_BoolValue ? 1 : 0); return true;
case Integer: setDouble((double) _IntegerValue); return true;
case Double: return true;
case String:
if (evalNumber(_StringValue.toString().c_str())) return toBool();
return false;
case RGBA: setDouble((double) _RGBAValue); return true;
default: break;
}
return false;
}
//==================================================================
bool CInterfaceExprValue::toString()
{
switch(_Type)
{
case Boolean: setString(_BoolValue ? "true" : "false"); return true;
case Integer: setString(NLMISC::toString(_IntegerValue)); return true;
case Double: setString(NLMISC::toString("%.2f", _DoubleValue)); return true;
case String: return true;
case RGBA:
{
uint r,g,b,a;
r= (_RGBAValue&0xff);
g= ((_RGBAValue>>8)&0xff);
b= ((_RGBAValue>>16)&0xff);
a= ((_RGBAValue>>24)&0xff);
setString(NLMISC::toString("%d %d %d %d", r, g, b, a));
return true;
}
default: break;
}
return false;
}
//==================================================================
bool CInterfaceExprValue::toRGBA()
{
switch(_Type)
{
case RGBA:
return true;
case Integer:
setRGBA(NLMISC::CRGBA((uint8)(_IntegerValue&0xff), (uint8)((_IntegerValue>>8)&0xff),
(uint8)((_IntegerValue>>16)&0xff), (uint8)((_IntegerValue>>24)&0xff)));
return true;
case String:
setRGBA( NLMISC::CRGBA::stringToRGBA(_StringValue.toString().c_str()));
return true;
default:
break;
}
return false;
}
//==================================================================
bool CInterfaceExprValue::isNumerical() const
{
return _Type == Boolean || _Type == Integer || _Type == Double;
}
//==================================================================
const char *CInterfaceExprValue::initFromString(const char *expr)
{
nlassert(expr);
expr = skipBlank(expr);
if (isdigit(*expr) || *expr == '.' || *expr == '-') return evalNumber(expr);
switch(*expr)
{
case 't':
case 'T':
case 'f':
case 'F':
return evalBoolean(expr);
case '\'':
return evalString(expr);
default:
return NULL;
}
}
//==================================================================
const char *CInterfaceExprValue::evalBoolean(const char *expr)
{
nlassert(expr);
expr = skipBlank(expr);
if (toupper(expr[0]) == 'T' &&
toupper(expr[1]) == 'R' &&
toupper(expr[2]) == 'U' &&
toupper(expr[3]) == 'E')
{
setBool(true);
return expr + 4;
}
//
if (toupper(expr[0]) == 'F' &&
toupper(expr[1]) == 'A' &&
toupper(expr[2]) == 'L' &&
toupper(expr[3]) == 'S' &&
toupper(expr[4]) == 'E')
{
setBool(false);
return expr + 5;
}
return NULL;
}
//==================================================================
const char *CInterfaceExprValue::evalNumber(const char *expr)
{
bool negative;
bool hasPoint = false;
expr = skipBlank(expr);
if (*expr == '-')
{
negative = true;
++ expr;
expr = skipBlank(expr);
}
else
{
negative = false;
}
const char *start = expr;
while (*expr == '.' || isdigit(*expr))
{
if (*expr == '.') hasPoint = true;
++ expr;
}
if (start == expr) return NULL;
if (!hasPoint)
{
sint64 value = 0;
// this is an integer
for (const char *nbPtr = start; nbPtr < expr; ++ nbPtr)
{
value *= 10;
value += (sint64) (*nbPtr - '0');
}
setInteger(negative ? - value : value);
return expr;
}
else // floating point value : use scanf
{
// well, for now, we only parse a float
float value;
std::string floatValue(start, expr - start);
if (fromString(floatValue, value))
{
setDouble(negative ? - value : value);
return expr;
}
else
{
return NULL;
}
}
}
//==================================================================
const char *CInterfaceExprValue::evalString(const char *expr)
{
expr = skipBlank(expr);
if (*expr != '\'') return NULL;
++expr;
std::string str;
for (;;)
{
if (expr == '\0')
{
nlwarning("CInterfaceExprValue::evalString : end of buffer encountered in a string");
return NULL;
}
else
if (*expr == '\'')
{
++ expr;
break;
}
if (*expr == '\\') // special char
{
++ expr;
switch (*expr)
{
case 't': str += '\t'; break;
case 'r': str += '\r'; break;
case 'n': str += '\n'; break;
case '\'': str += '\''; break;
case '"': str += '"'; break;
case '\\': str += '\\'; break;
case '\n':
case '\r':
// string continue on next line, so do nothing
break;
case '\0': continue;
default:
nlwarning("CInterfaceExprValue::evalString : unknown escape sequence : \\%c", *expr);
if (*expr) str += *expr;
break;
}
}
else if (*expr == '\n' || *expr == '\r')
{
nlwarning("CInterfaceExprValue::evalString : line break encountered in a string");
return NULL;
}
else
{
str += *expr;
}
++ expr;
}
setString(str);
return expr;
}
//==================================================================
bool CInterfaceExprValue::toType(TType type)
{
switch(type)
{
case Boolean: return toBool();
case Integer: return toInteger();
case Double: return toDouble();
case String: return toString();
case RGBA: return toRGBA();
default: return false;
}
}
//==================================================================
void CInterfaceExprValue::clean()
{
switch (_Type)
{
case String: _StringValue.clear(); break;
case UserType: delete _UserTypeValue; break;
default: break;
}
}
//==================================================================
void CInterfaceExprValue::setUserType(CInterfaceExprUserType *value)
{
if (_Type == UserType && value == _UserTypeValue) return;
clean();
_Type = UserType;
_UserTypeValue = value;
}
//==================================================================
bool CInterfaceExprValue::getBool() const
{
if (_Type != Boolean)
{
nlwarning("<CInterfaceExprValue::getBool> bad type!");
return false;
}
return _BoolValue;
}
//==================================================================
sint64 CInterfaceExprValue::getInteger() const
{
if (_Type != Integer)
{
nlwarning("<CInterfaceExprValue::getInteger> bad type!");
return 0;
}
return _IntegerValue;
}
//==================================================================
double CInterfaceExprValue::getDouble() const
{
if (_Type != Double)
{
nlwarning("<CInterfaceExprValue::getDouble> bad type!");
return 0;
}
return _DoubleValue;
}
//==================================================================
std::string CInterfaceExprValue::getString() const
{
if (_Type != String)
{
nlwarning("<CInterfaceExprValue::getString> bad type!");
return "";
}
return _StringValue.toString();
}
//==================================================================
NLMISC::CRGBA CInterfaceExprValue::getRGBA() const
{
if (_Type != RGBA)
{
nlwarning("<CInterfaceExprValue::getRGBA> bad type!");
return CRGBA::White;
}
NLMISC::CRGBA col;
col.R = (uint8)(_RGBAValue&0xff);
col.G = (uint8)((_RGBAValue>>8)&0xff);
col.B = (uint8)((_RGBAValue>>16)&0xff);
col.A = (uint8)((_RGBAValue>>24)&0xff);
return col;
}
//==================================================================
const ucstring &CInterfaceExprValue::getUCString() const
{
if (_Type != String)
{
nlwarning("<CInterfaceExprValue::getString> bad type!");
static ucstring emptyString;
return emptyString;
}
return _StringValue;
}
//==================================================================
CInterfaceExprUserType *CInterfaceExprValue::getUserType() const
{
if (_Type != UserType)
{
nlwarning("<CInterfaceExprValue::getUserType> bad type!");
return NULL;
}
return _UserTypeValue;
}
//==================================================================
CInterfaceExprValue::CInterfaceExprValue(const CInterfaceExprValue &other) : _Type(NoType)
{
*this = other;
}
//==================================================================
CInterfaceExprValue &CInterfaceExprValue::operator = (const CInterfaceExprValue &other)
{
if (this != &other)
{
clean();
switch(other._Type)
{
case Boolean: _BoolValue = other._BoolValue; break;
case Integer: _IntegerValue = other._IntegerValue; break;
case Double: _DoubleValue = other._DoubleValue; break;
case String: _StringValue = other._StringValue; break;
case RGBA: _RGBAValue = other._RGBAValue; break;
case UserType:
if (other._UserTypeValue != NULL)
{
_UserTypeValue = other._UserTypeValue->clone();
}
else
{
_UserTypeValue = NULL;
}
break;
case NoType: break;
default:
nlwarning("<CInterfaceExprValue::operator=> bad source type") ;
return *this;
break;
}
_Type = other._Type;
}
return *this;
}
}

View file

@ -0,0 +1,161 @@
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "nel/misc/cdb_leaf.h"
#include "nel/misc/cdb_branch.h"
#include "nel/gui/interface_expr_node.h"
using NLMISC::ICDBNode;
using NLMISC::CCDBNodeBranch;
using NLMISC::CCDBNodeLeaf;
namespace NLGUI
{
// *******************************************************************************************************
void CInterfaceExprNodeValue::eval(CInterfaceExprValue &result)
{
result = Value;
}
void CInterfaceExprNodeValue::evalWithDepends(CInterfaceExprValue &result, std::vector<ICDBNode *> &/* nodes */)
{
result = Value;
}
void CInterfaceExprNodeValue::getDepends(std::vector<ICDBNode *> &/* nodes */)
{
}
// *******************************************************************************************************
void CInterfaceExprNodeValueFnCall::eval(CInterfaceExprValue &result)
{
nlassert(Func);
uint numParams = (uint)Params.size();
std::vector<CInterfaceExprValue> params(numParams);
for(uint k = 0; k < numParams; ++k)
{
Params[k]->eval(params[k]);
}
Func(params, result); // do actual call
}
void CInterfaceExprNodeValueFnCall::evalWithDepends(CInterfaceExprValue &result, std::vector<ICDBNode *> &nodes)
{
nlassert(Func);
uint numParams = (uint)Params.size();
std::vector<CInterfaceExprValue> params(numParams);
for(uint k = 0; k < numParams; ++k)
{
Params[k]->evalWithDepends(params[k], nodes);
}
Func(params, result); // do actual call
}
void CInterfaceExprNodeValueFnCall::getDepends(std::vector<ICDBNode *> &nodes)
{
uint numParams = (uint)Params.size();
for(uint k = 0; k < numParams; ++k)
{
Params[k]->getDepends(nodes);
}
}
CInterfaceExprNodeValueFnCall::~CInterfaceExprNodeValueFnCall()
{
for(uint k = 0; k < Params.size(); ++k)
{
delete Params[k];
}
}
// *******************************************************************************************************
void CInterfaceExprNodeDBLeaf::eval(CInterfaceExprValue &result)
{
nlassert(Leaf);
result.setInteger(Leaf->getValue64());
}
void CInterfaceExprNodeDBLeaf::evalWithDepends(CInterfaceExprValue &result,std::vector<ICDBNode *> &nodes)
{
nlassert(Leaf);
result.setInteger(Leaf->getValue64());
if (std::find(nodes.begin(), nodes.end(), Leaf) == nodes.end())
{
nodes.push_back(Leaf);
}
}
void CInterfaceExprNodeDBLeaf::getDepends(std::vector<ICDBNode *> &nodes)
{
nlassert(Leaf);
if (std::find(nodes.begin(), nodes.end(), Leaf) == nodes.end())
{
nodes.push_back(Leaf);
}
}
// *******************************************************************************************************
void CInterfaceExprNodeDBBranch::eval(CInterfaceExprValue &result)
{
nlassert(Branch);
result.setInteger(0);
}
void CInterfaceExprNodeDBBranch::evalWithDepends(CInterfaceExprValue &result,std::vector<ICDBNode *> &nodes)
{
nlassert(Branch);
result.setInteger(0);
if (std::find(nodes.begin(), nodes.end(), Branch) == nodes.end())
{
nodes.push_back(Branch);
}
}
void CInterfaceExprNodeDBBranch::getDepends(std::vector<ICDBNode *> &nodes)
{
nlassert(Branch);
if (std::find(nodes.begin(), nodes.end(), Branch) == nodes.end())
{
nodes.push_back(Branch);
}
}
// *******************************************************************************************************
void CInterfaceExprNodeDependantDBRead::eval(CInterfaceExprValue &result)
{
// no gain there, but barely used
CInterfaceExpr::eval(Expr, result);
}
void CInterfaceExprNodeDependantDBRead::evalWithDepends(CInterfaceExprValue &result, std::vector<ICDBNode *> &nodes)
{
CInterfaceExpr::eval(Expr, result, &nodes);
}
void CInterfaceExprNodeDependantDBRead::getDepends(std::vector<ICDBNode *> &nodes)
{
CInterfaceExprValue dummyResult;
CInterfaceExpr::eval(Expr, dummyResult, &nodes, true);
}
}

View file

@ -728,6 +728,21 @@ void CRGBA::buildFromHLS(float h, float l, float s)
} }
} }
CRGBA CRGBA::stringToRGBA( const char *ptr )
{
if (!ptr)
return NLMISC::CRGBA::White;
int r = 255, g = 255, b = 255, a = 255;
sscanf( ptr, "%d %d %d %d", &r, &g, &b, &a );
clamp( r, 0, 255 );
clamp( g, 0, 255 );
clamp( b, 0, 255 );
clamp( a, 0, 255 );
return CRGBA( r,g,b,a );
}
// *************************************************************************** // ***************************************************************************
// *************************************************************************** // ***************************************************************************

View file

@ -1374,7 +1374,7 @@ void CClientConfig::setValues()
SPrintfCommand pcom; SPrintfCommand pcom;
pcom.X = pc->asInt(i); pcom.X = pc->asInt(i);
pcom.Y = pc->asInt(i+1); pcom.Y = pc->asInt(i+1);
pcom.Color = stringToRGBA( pc->asString(i+2).c_str() ); pcom.Color = CRGBA::stringToRGBA( pc->asString(i+2).c_str() );
pcom.FontSize = pc->asInt(i+3); pcom.FontSize = pc->asInt(i+3);
pcom.Text = pc->asString(i+4); pcom.Text = pc->asString(i+4);

View file

@ -67,7 +67,7 @@
#include "interface_v3/ctrl_button.h" #include "interface_v3/ctrl_button.h"
#include "interface_v3/input_handler_manager.h" #include "interface_v3/input_handler_manager.h"
#include "interface_v3/group_editbox.h" #include "interface_v3/group_editbox.h"
#include "interface_v3/interface_expr.h" #include "nel/gui/interface_expr.h"
#include "init_main_loop.h" #include "init_main_loop.h"
#include "continent_manager.h" #include "continent_manager.h"
#include "interface_v3/group_quick_help.h" #include "interface_v3/group_quick_help.h"
@ -1338,7 +1338,7 @@ void setTarget(CCtrlBase *ctrl, const string &targetName, ucstring &value)
CInterfaceExprValue exprValue; CInterfaceExprValue exprValue;
exprValue.setUCString(value); exprValue.setUCString(value);
CInterfaceParser::splitLinkTargets(targetName, ig, targets); CInterfaceLink::splitLinkTargets(targetName, ig, targets);
for(uint k = 0; k < targets.size(); ++k) for(uint k = 0; k < targets.size(); ++k)
{ {
if (targets[k].Elem) targets[k].affect(exprValue); if (targets[k].Elem) targets[k].affect(exprValue);
@ -1364,7 +1364,7 @@ void setTarget(CCtrlBase *ctrl, const string &targetName, uint32 value)
CInterfaceExprValue exprValue; CInterfaceExprValue exprValue;
exprValue.setInteger(value); exprValue.setInteger(value);
CInterfaceParser::splitLinkTargets(targetName, ig, targets); CInterfaceLink::splitLinkTargets(targetName, ig, targets);
for(uint k = 0; k < targets.size(); ++k) for(uint k = 0; k < targets.size(); ++k)
{ {
if (targets[k].Elem) targets[k].affect(exprValue); if (targets[k].Elem) targets[k].affect(exprValue);
@ -1813,7 +1813,7 @@ string getTarget(CCtrlBase * /* ctrl */, const string &targetName)
{ {
string sTmp = targetName; string sTmp = targetName;
std::vector<CInterfaceLink::CTargetInfo> targetsVector; std::vector<CInterfaceLink::CTargetInfo> targetsVector;
CInterfaceParser::splitLinkTargets(sTmp, NULL, targetsVector); CInterfaceLink::splitLinkTargets(sTmp, NULL, targetsVector);
CInterfaceLink::CTargetInfo &rTI = targetsVector[0]; CInterfaceLink::CTargetInfo &rTI = targetsVector[0];
@ -1835,7 +1835,7 @@ ucstring getUCTarget(CCtrlBase * /* ctrl */, const string &targetName)
{ {
string sTmp = targetName; string sTmp = targetName;
std::vector<CInterfaceLink::CTargetInfo> targetsVector; std::vector<CInterfaceLink::CTargetInfo> targetsVector;
CInterfaceParser::splitLinkTargets(sTmp, NULL, targetsVector); CInterfaceLink::splitLinkTargets(sTmp, NULL, targetsVector);
CInterfaceLink::CTargetInfo &rTI = targetsVector[0]; CInterfaceLink::CTargetInfo &rTI = targetsVector[0];

View file

@ -21,7 +21,7 @@
#include "action_handler.h" #include "action_handler.h"
#include "action_handler_misc.h" #include "action_handler_misc.h"
#include "interface_expr.h" #include "nel/gui/interface_expr.h"
#include "interface_manager.h" #include "interface_manager.h"
#include "group_container.h" #include "group_container.h"
@ -298,7 +298,7 @@ public:
if (ig != NULL) if (ig != NULL)
{ {
CInterfaceParser::splitLinkTargets(property, ig, targets); CInterfaceLink::splitLinkTargets(property, ig, targets);
for(uint k = 0; k < targets.size(); ++k) for(uint k = 0; k < targets.size(); ++k)
{ {
if (targets[k].Elem) targets[k].affect(value); if (targets[k].Elem) targets[k].affect(value);

View file

@ -35,7 +35,7 @@
#include "bot_chat_page_ring_sessions.h" #include "bot_chat_page_ring_sessions.h"
#include "dbctrl_sheet.h" #include "dbctrl_sheet.h"
#include "ctrl_sheet_selection.h" #include "ctrl_sheet_selection.h"
#include "interface_expr.h" #include "nel/gui/interface_expr.h"
#include "group_menu.h" #include "group_menu.h"
#include "group_container.h" #include "group_container.h"
#include "group_editbox.h" #include "group_editbox.h"
@ -3902,7 +3902,7 @@ public:
uint entity; uint entity;
fromString(getParam(sParams, "entity"), entity); fromString(getParam(sParams, "entity"), entity);
CRGBA color = stringToRGBA(getParam(sParams, "color").c_str()); CRGBA color = CRGBA::stringToRGBA(getParam(sParams, "color").c_str());
if (entity < 256) if (entity < 256)
EntitiesMngr.entity (entity)->addHPOutput (CI18N::get (text), color); EntitiesMngr.entity (entity)->addHPOutput (CI18N::get (text), color);
} }

View file

@ -25,7 +25,7 @@
#include "../sheet_manager.h" #include "../sheet_manager.h"
#include "skill_manager.h" #include "skill_manager.h"
#include "dbctrl_sheet.h" #include "dbctrl_sheet.h"
#include "interface_expr.h" #include "nel/gui/interface_expr.h"
#include "group_container.h" #include "group_container.h"
#include "group_editbox.h" #include "group_editbox.h"
#include "group_quick_help.h" #include "group_quick_help.h"

View file

@ -25,7 +25,7 @@
#include "dbctrl_sheet.h" #include "dbctrl_sheet.h"
#include "dbgroup_list_sheet.h" #include "dbgroup_list_sheet.h"
#include "group_editbox.h" #include "group_editbox.h"
#include "interface_expr.h" #include "nel/gui/interface_expr.h"
#include "player_trade.h" #include "player_trade.h"
#include "../user_entity.h" #include "../user_entity.h"
#include "../net_manager.h" #include "../net_manager.h"

View file

@ -22,7 +22,7 @@
#include "group_editbox.h" #include "group_editbox.h"
#include "people_interraction.h" #include "people_interraction.h"
#include "nel/misc/algo.h" #include "nel/misc/algo.h"
#include "interface_expr.h" #include "nel/gui/interface_expr.h"
#include "interface_link.h" #include "interface_link.h"
#include "../client_chat_manager.h" #include "../client_chat_manager.h"
#include "../motion/user_controls.h" #include "../motion/user_controls.h"
@ -427,7 +427,7 @@ class CActionHandlerAddLink : public IActionHandler
} }
std::vector<CInterfaceLink::CTargetInfo> targetsVect; std::vector<CInterfaceLink::CTargetInfo> targetsVect;
bool result = CInterfaceParser::splitLinkTargets(targets, parentGroup, targetsVect); bool result = CInterfaceLink::splitLinkTargets(targets, parentGroup, targetsVect);
if (!result) if (!result)
{ {
nlwarning("<CActionHandlerAddLink> Couldn't parse all links"); nlwarning("<CActionHandlerAddLink> Couldn't parse all links");

View file

@ -21,7 +21,7 @@
#include "action_handler.h" #include "action_handler.h"
#include "action_handler_tools.h" #include "action_handler_tools.h"
#include "game_share/outpost.h" #include "game_share/outpost.h"
#include "interface_expr.h" #include "nel/gui/interface_expr.h"
#include "group_map.h" #include "group_map.h"
#include "../sheet_manager.h" #include "../sheet_manager.h"
#include "../net_manager.h" #include "../net_manager.h"

View file

@ -18,7 +18,7 @@
#include "bar_manager.h" #include "bar_manager.h"
#include "interface_manager.h" #include "interface_manager.h"
#include "interface_expr.h" #include "nel/gui/interface_expr.h"
#include "../time_client.h" #include "../time_client.h"

View file

@ -554,7 +554,7 @@ void CChatGroupWindow::displayMessage(const ucstring &msg, NLMISC::CRGBA col, CC
// on a new message, change the Tab color // on a new message, change the Tab color
CInterfaceManager *pIM= CInterfaceManager::getInstance(); CInterfaceManager *pIM= CInterfaceManager::getInstance();
CRGBA newMsgColor= stringToRGBA(pIM->getDefine("chat_group_tab_color_newmsg").c_str()); CRGBA newMsgColor= CRGBA::stringToRGBA(pIM->getDefine("chat_group_tab_color_newmsg").c_str());
ucstring newmsg = msg; ucstring newmsg = msg;
ucstring prefix; ucstring prefix;

View file

@ -25,7 +25,7 @@
// client // client
#include "nel/gui/reflect.h" #include "nel/gui/reflect.h"
#include "ctrl_base.h" #include "ctrl_base.h"
#include "interface_expr.h" #include "nel/gui/interface_expr.h"
#include "action_handler.h" #include "action_handler.h"
#include "sphrase_manager.h" #include "sphrase_manager.h"
// game share // game share

View file

@ -19,7 +19,7 @@
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
#include "stdpch.h" #include "stdpch.h"
#include "interface_manager.h" #include "interface_manager.h"
#include "interface_expr.h" #include "nel/gui/interface_expr.h"
#include "group_menu.h" #include "group_menu.h"
#include "nel/misc/xml_auto_ptr.h" #include "nel/misc/xml_auto_ptr.h"
#include "view_bitmap.h" #include "view_bitmap.h"

View file

@ -20,7 +20,7 @@
#include "group_phrase_skill_filter.h" #include "group_phrase_skill_filter.h"
#include "interface_manager.h" #include "interface_manager.h"
#include "interface_expr.h" #include "nel/gui/interface_expr.h"
#include "view_text.h" #include "view_text.h"

View file

@ -21,7 +21,7 @@
#include "group_skills.h" #include "group_skills.h"
#include "interface_manager.h" #include "interface_manager.h"
#include "interface_expr.h" #include "nel/gui/interface_expr.h"
#include "view_text.h" #include "view_text.h"
#include "view_bitmap.h" #include "view_bitmap.h"

View file

@ -21,7 +21,7 @@
#include "interface_anim.h" #include "interface_anim.h"
#include "interface_manager.h" #include "interface_manager.h"
#include "interface_expr.h" #include "nel/gui/interface_expr.h"
#include "nel/misc/xml_auto_ptr.h" #include "nel/misc/xml_auto_ptr.h"
#include "action_handler.h" #include "action_handler.h"
#include "../time_client.h" #include "../time_client.h"
@ -75,7 +75,7 @@ bool CInterfaceTrack::parse (xmlNodePtr cur, CInterfaceGroup *parentGroup)
} }
// //
if (!CInterfaceParser::splitLinkTargets (ptr, parentGroup, _Targets)) if (!CInterfaceLink::splitLinkTargets (ptr, parentGroup, _Targets))
{ {
nlwarning ("no target for track"); nlwarning ("no target for track");
return false; return false;

View file

@ -761,7 +761,7 @@ void CInterfaceElement::convertHotSpotCouple (const char *ptr, THotSpot &parent
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
NLMISC::CRGBA CInterfaceElement::convertColor (const char *ptr) NLMISC::CRGBA CInterfaceElement::convertColor (const char *ptr)
{ {
return stringToRGBA(ptr); return NLMISC::CRGBA::stringToRGBA(ptr);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------

View file

@ -1,930 +0,0 @@
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "stdpch.h"
#include "interface_expr.h"
#include "interface_manager.h"
#include "interface_expr_node.h"
#include "../misc.h"
#include "nel/misc/algo.h"
#include <algorithm>
using namespace std;
using namespace NLMISC;
// Yoyo: Act like a singleton, else registerUserFct may crash.
CInterfaceExpr::TUserFctMap *CInterfaceExpr::_UserFct= NULL;
static const std::string ExprLuaId="lua:";
//==================================================================
// release memory
void CInterfaceExpr::release()
{
delete _UserFct;
_UserFct = NULL;
}
//==================================================================
void formatLuaCall(const std::string &expr, std::string &tempStr)
{
/* Call the LUA interface exp fct, with the script as line, and resolve string definition conflicts:
eg: replace
lua:getSkillFromName('SM')
into
lua('getSkillFromName(\"SM\")')
*/
tempStr= expr.substr(ExprLuaId.size()); // eg: tempStr= getSkillFromName('SM')
while(strFindReplace(tempStr, "'", "\\\"")); // eg: tempStr= getSkillFromName(\"SM\")
tempStr= string("lua('") + tempStr + "')"; // eg: tempStr= lua('getSkillFromName(\"SM\")')
}
//==================================================================
bool CInterfaceExpr::eval(const std::string &expr, CInterfaceExprValue &result, std::vector<ICDBNode *> *nodes, bool noFctCalls /* = false */)
{
// Yoyo: Special InterfaceExpr Form to execute lua code?
if(expr.compare(0, ExprLuaId.size(), ExprLuaId) ==0 )
{
std::string tempStr;
formatLuaCall(expr, tempStr);
return evalExpr(tempStr.c_str(), result, nodes, noFctCalls) != NULL;
}
else
{
return evalExpr(expr.c_str(), result, nodes, noFctCalls) != NULL;
}
}
//==================================================================
CInterfaceExprNode *CInterfaceExpr::buildExprTree(const std::string &expr)
{
CInterfaceExprNode *node;
// Yoyo: Special InterfaceExpr Form to execute lua code?
if(expr.compare(0, ExprLuaId.size(), ExprLuaId) ==0 )
{
std::string tempStr;
formatLuaCall(expr, tempStr);
if (!buildExprTree(tempStr.c_str(), node)) return false;
}
else
{
if (!buildExprTree(expr.c_str(), node)) return false;
}
return node;
}
//==================================================================
void CInterfaceExpr::registerUserFct(const char *name,TUserFct fct)
{
if(!_UserFct) _UserFct= new TUserFctMap;
nlassert(fct != NULL);
(*_UserFct)[std::string(name)] = fct;
}
//==================================================================
/** tool fct : skip space, tab and carret-returns
*/
static const char *skipBlank(const char *start)
{
nlassert(start);
while (*start == ' ' || *start == '\t' || *start == '\r' || *start == '\n') ++start;
return start;
}
//==================================================================
const char *CInterfaceExpr::evalExpr(const char *expr, CInterfaceExprValue &result, std::vector<ICDBNode *> *nodes, bool noFctCalls)
{
nlassert(expr != NULL);
expr = skipBlank(expr);
if (isalpha(*expr)) // alpha character means this is a function name
{
return evalFct(expr, result, nodes, noFctCalls);
}
else if (*expr == '@') // is it a database entry ?
{
++ expr;
expr = skipBlank(expr);
return evalDBEntry(expr, result, nodes);
}
// try to parse a literal value
const char *newExpr = result.initFromString(expr);
if (!newExpr)
{
nlwarning("<CInterfaceExpr::evalExpr> : syntax error : %s", expr);
return NULL;
}
return newExpr;
}
//==================================================================
const char *CInterfaceExpr::buildExprTree(const char *expr, CInterfaceExprNode *&result)
{
nlassert(expr != NULL);
expr = skipBlank(expr);
if (isalpha(*expr)) // alpha character means this is a function name
{
return buildFctNode(expr, result);
}
else if (*expr == '@') // is it a database entry ?
{
++ expr;
expr = skipBlank(expr);
return buildDBEntryNode(expr, result);
}
else
{
CInterfaceExprValue value;
// try to parse a literal value
const char *newExpr = value.initFromString(expr);
if (!newExpr)
{
nlwarning("<CInterfaceExpr::buildExprTree> : syntax error : %s", expr);
return NULL;
}
CInterfaceExprNodeValue *node = new CInterfaceExprNodeValue;
node->Value = value;
result = node;
return newExpr;
}
return NULL;
}
//==================================================================
const char *CInterfaceExpr::evalFct(const char *expr, CInterfaceExprValue &result, std::vector<ICDBNode *> *nodes, bool noFctCalls)
{
if(!_UserFct) _UserFct= new TUserFctMap;
const char *start = expr;
while (isalnum(*expr)) ++ expr;
std::string fctName(start, expr - start);
// find entry in the map
TUserFctMap::iterator fctIt = _UserFct->find(fctName);
if (fctIt == _UserFct->end())
{
nlwarning("<CInterfaceExpr::evalFct> : Unknown function %s", fctName.c_str());
return NULL;
}
nlassert(fctIt->second != NULL);
// eval list of arguments
TArgList argList;
expr = skipBlank(expr);
if (*expr != '(')
{
nlwarning("<CInterfaceExpr::evalFct> : '(' expected for function %s", fctName.c_str());
return NULL;
}
++ expr;
expr = skipBlank(expr);
if (*expr != ')')
{
for(;;)
{
expr = skipBlank(expr);
// parse an argument
argList.push_back(CInterfaceExprValue());
expr = evalExpr(expr, argList.back(), nodes, noFctCalls);
if (expr == NULL) return NULL;
expr = skipBlank(expr);
if (*expr == ')') break;
// if it isn't the end of the expression, then we should find a ',' before next argument
if (*expr != ',')
{
nlwarning("<CInterfaceExpr::evalFct> : ',' expected in function %s", fctName.c_str());
return NULL;
}
++ expr;
}
}
++ expr;
// call the fct
if (!noFctCalls) // should we make terminal function calls ?
{
if (fctIt->second(argList, result)) return expr;
}
else
{
return expr;
}
return NULL;
}
//==================================================================
const char *CInterfaceExpr::buildFctNode(const char *expr, CInterfaceExprNode *&result)
{
if(!_UserFct) _UserFct= new TUserFctMap;
const char *start = expr;
while (isalnum(*expr)) ++ expr;
std::string fctName(start, expr - start);
// find entry in the map
TUserFctMap::iterator fctIt = _UserFct->find(fctName);
if (fctIt == _UserFct->end())
{
nlwarning("<CInterfaceExpr::buildFctNode> : Unknown function %s", fctName.c_str());
return NULL;
}
nlassert(fctIt->second != NULL);
// List of parameters
expr = skipBlank(expr);
if (*expr != '(')
{
nlwarning("<CInterfaceExpr::buildFctNode> : '(' expected for function %s", fctName.c_str());
return NULL;
}
++ expr;
expr = skipBlank(expr);
std::vector<CInterfaceExprNode *> Params;
if (*expr != ')')
{
for(;;)
{
expr = skipBlank(expr);
// parse an argument
CInterfaceExprNode *node = NULL;
expr = buildExprTree(expr, node);
if (expr == NULL)
{
for(uint k = 0; k < Params.size(); ++k)
{
delete Params[k];
}
return NULL;
}
Params.push_back(node);
expr = skipBlank(expr);
if (*expr == ')') break;
// if it isn't the end of the expression, then we should find a ',' before next argument
if (*expr != ',')
{
for(uint k = 0; k < Params.size(); ++k)
{
delete Params[k];
}
nlwarning("CInterfaceExpr::evalFct : ',' expected in function %s", fctName.c_str());
return NULL;
}
++ expr;
}
}
++ expr;
CInterfaceExprNodeValueFnCall *node = new CInterfaceExprNodeValueFnCall;
node->Params.swap(Params);
node->Func = fctIt->second;
result = node;
return expr;
}
//==================================================================
const char *CInterfaceExpr::evalDBEntry(const char *expr, CInterfaceExprValue &result, std::vector<ICDBNode *> *nodes)
{
std::string dbEntry;
expr = unpackDBentry(expr, nodes, dbEntry);
if (!expr) return NULL;
// TestYoyo
//nlassert(NLGUI::CDBManager::getInstance()->getDbProp(dbEntry, false) || CInterfaceManager::getInstance()->getDbBranch(dbEntry));
// get the db value
CCDBNodeLeaf *nl = NLGUI::CDBManager::getInstance()->getDbProp(dbEntry);
if (nl)
{
if (nodes)
{
// insert node if not already present
if (std::find(nodes->begin(), nodes->end(), nl) == nodes->end())
{
nodes->push_back(nl);
}
}
result.setInteger(nl->getValue64());
return expr;
}
else
{
CCDBNodeBranch *nb = NLGUI::CDBManager::getInstance()->getDbBranch(dbEntry);
if (nodes && nb)
{
if (std::find(nodes->begin(), nodes->end(), nb) == nodes->end())
{
nodes->push_back(nb);
}
}
if (!nb) return NULL;
result.setInteger(0);
return expr;
}
return NULL;
}
//==================================================================
const char *CInterfaceExpr::buildDBEntryNode(const char *expr, CInterfaceExprNode *&result)
{
std::string dbEntry;
bool indirection;
const char *startChar = expr;
expr = unpackDBentry(expr, NULL, dbEntry, &indirection);
if (!expr) return NULL;
if (indirection)
{
// special node with no optimisation
CInterfaceExprNodeDependantDBRead *node = new CInterfaceExprNodeDependantDBRead;
node->Expr.resize(expr - startChar + 1);
std::copy(startChar, expr, node->Expr.begin() + 1);
node->Expr[0] = '@';
result = node;
return expr;
}
else
{
// TestYoyo
//nlassert(NLGUI::CDBManager::getInstance()->getDbProp(dbEntry, false) || CInterfaceManager::getInstance()->getDbBranch(dbEntry));
CCDBNodeLeaf *nl = NLGUI::CDBManager::getInstance()->getDbProp(dbEntry);
if (nl)
{
CInterfaceExprNodeDBLeaf *node = new CInterfaceExprNodeDBLeaf;
node->Leaf = nl;
result = node;
return expr;
}
else
{
CCDBNodeBranch *nb = NLGUI::CDBManager::getInstance()->getDbBranch(dbEntry);
if (nb)
{
CInterfaceExprNodeDBBranch *node = new CInterfaceExprNodeDBBranch;
node->Branch = nb;
result = node;
return expr;
}
}
return NULL;
}
}
//==================================================================
const char *CInterfaceExpr::unpackDBentry(const char *expr, std::vector<ICDBNode *> *nodes, std::string &dest, bool *hasIndirections /* = NULL*/)
{
std::string entryName;
bool indirection = false;
for (;;)
{
if (*expr == '[')
{
indirection = true;
++ expr;
std::string subEntry;
expr = unpackDBentry(expr, nodes, subEntry);
if (!expr) return NULL;
// Read DB Index Offset.
sint32 indirectionOffset= 0;
if (*expr == '-' || *expr =='+' )
{
bool negative= *expr == '-';
std::string offsetString;
++ expr;
while(*expr!=0 && isdigit(*expr))
{
offsetString.push_back(*expr);
++ expr;
}
// get offset
fromString(offsetString, indirectionOffset);
if(negative)
indirectionOffset= -indirectionOffset;
}
// Test end of indirection
if (*expr != ']')
{
nlwarning("CInterfaceExpr::unpackDBentry: ']' expected");
return NULL;
}
++ expr;
// get the db value at sub entry
// TestYoyo
//nlassert(NLGUI::CDBManager::getInstance()->getDbProp(subEntry, false) || CInterfaceManager::getInstance()->getDbBranch(subEntry));
CCDBNodeLeaf *nl = NLGUI::CDBManager::getInstance()->getDbProp(subEntry);
if (nodes)
{
if (std::find(nodes->begin(), nodes->end(), nl) == nodes->end())
{
nodes->push_back(nl);
}
}
// compute indirection, (clamp).
sint32 indirectionValue= nl->getValue32() + indirectionOffset;
indirectionValue= std::max((sint32)0, indirectionValue);
// Append to entry name.
entryName += NLMISC::toString(indirectionValue);
}
else if (isalnum(*expr) || *expr == '_' || *expr == ':')
{
entryName += *expr;
++ expr;
}
else
{
break;
}
}
if (hasIndirections)
{
*hasIndirections = indirection;
}
dest = entryName;
return expr;
}
//==================================================================
bool CInterfaceExpr::evalAsInt(const std::string &expr, sint64 &dest)
{
CInterfaceExprValue result;
if (!eval(expr, result)) return false;
if (!result.toInteger())
{
nlwarning("<CInterfaceExpr::evalAsInt> Can't convert value to an integer, expr = %s", expr.c_str());
return false;
}
dest = result.getInteger();
return true;
}
//==================================================================
bool CInterfaceExpr::evalAsDouble(const std::string &expr, double &dest)
{
CInterfaceExprValue result;
if (!eval(expr, result)) return false;
if (!result.toDouble())
{
nlwarning("<CInterfaceExpr::evalAsDouble> Can't convert value to a double, expr = %s", expr.c_str());
return false;
}
dest = result.getDouble();
return true;
}
//==================================================================
bool CInterfaceExpr::evalAsBool(const std::string &expr, bool &dest)
{
CInterfaceExprValue result;
if (!eval(expr, result)) return false;
if (!result.toBool())
{
nlwarning("<CInterfaceExpr::evalAsBool> Can't convert value to a boolean, expr = %s", expr.c_str());
return false;
}
dest = result.getBool();
return true;
}
//==================================================================
bool CInterfaceExpr::evalAsString(const std::string &expr, std::string &dest)
{
CInterfaceExprValue result;
if (!eval(expr, result)) return false;
if (!result.toString())
{
nlwarning("<CInterfaceExpr::evalAsString> Can't convert value to a string, expr = %s", expr.c_str());
return false;
}
dest = result.getString();
return true;
}
//==================================================================
//==================================================================
//==================================================================
//==================================================================
//==================================================================
bool CInterfaceExprValue::toBool()
{
switch(_Type)
{
case Boolean: return true;
case Integer: setBool(_IntegerValue != 0); return true;
case Double: setBool(_DoubleValue != 0); return true;
case String: return evalBoolean(_StringValue.toString().c_str()) != NULL;
default: break;
}
return false;
}
//==================================================================
bool CInterfaceExprValue::toInteger()
{
switch(_Type)
{
case Boolean: setInteger(_BoolValue ? 1 : 0); return true;
case Integer: return true;
case Double: setInteger((sint64) _DoubleValue); return true;
case String:
if (evalNumber(_StringValue.toString().c_str())) return toInteger();
return false;
case RGBA: setInteger((sint64) _RGBAValue); return true;
default: break;
}
return false;
}
//==================================================================
bool CInterfaceExprValue::toDouble()
{
switch(_Type)
{
case Boolean: setDouble(_BoolValue ? 1 : 0); return true;
case Integer: setDouble((double) _IntegerValue); return true;
case Double: return true;
case String:
if (evalNumber(_StringValue.toString().c_str())) return toBool();
return false;
case RGBA: setDouble((double) _RGBAValue); return true;
default: break;
}
return false;
}
//==================================================================
bool CInterfaceExprValue::toString()
{
switch(_Type)
{
case Boolean: setString(_BoolValue ? "true" : "false"); return true;
case Integer: setString(NLMISC::toString(_IntegerValue)); return true;
case Double: setString(NLMISC::toString("%.2f", _DoubleValue)); return true;
case String: return true;
case RGBA:
{
uint r,g,b,a;
r= (_RGBAValue&0xff);
g= ((_RGBAValue>>8)&0xff);
b= ((_RGBAValue>>16)&0xff);
a= ((_RGBAValue>>24)&0xff);
setString(NLMISC::toString("%d %d %d %d", r, g, b, a));
return true;
}
default: break;
}
return false;
}
//==================================================================
bool CInterfaceExprValue::toRGBA()
{
switch(_Type)
{
case RGBA: return true;
case Integer: setRGBA(NLMISC::CRGBA((uint8)(_IntegerValue&0xff), (uint8)((_IntegerValue>>8)&0xff),
(uint8)((_IntegerValue>>16)&0xff), (uint8)((_IntegerValue>>24)&0xff))); return true;
case String:
setRGBA(stringToRGBA(_StringValue.toString().c_str())); return true;
default: break;
}
return false;
}
//==================================================================
bool CInterfaceExprValue::isNumerical() const
{
return _Type == Boolean || _Type == Integer || _Type == Double;
}
//==================================================================
const char *CInterfaceExprValue::initFromString(const char *expr)
{
nlassert(expr);
expr = skipBlank(expr);
if (isdigit(*expr) || *expr == '.' || *expr == '-') return evalNumber(expr);
switch(*expr)
{
case 't':
case 'T':
case 'f':
case 'F':
return evalBoolean(expr);
case '\'':
return evalString(expr);
default:
return NULL;
}
}
//==================================================================
const char *CInterfaceExprValue::evalBoolean(const char *expr)
{
nlassert(expr);
expr = skipBlank(expr);
if (toupper(expr[0]) == 'T' &&
toupper(expr[1]) == 'R' &&
toupper(expr[2]) == 'U' &&
toupper(expr[3]) == 'E')
{
setBool(true);
return expr + 4;
}
//
if (toupper(expr[0]) == 'F' &&
toupper(expr[1]) == 'A' &&
toupper(expr[2]) == 'L' &&
toupper(expr[3]) == 'S' &&
toupper(expr[4]) == 'E')
{
setBool(false);
return expr + 5;
}
return NULL;
}
//==================================================================
const char *CInterfaceExprValue::evalNumber(const char *expr)
{
bool negative;
bool hasPoint = false;
expr = skipBlank(expr);
if (*expr == '-')
{
negative = true;
++ expr;
expr = skipBlank(expr);
}
else
{
negative = false;
}
const char *start = expr;
while (*expr == '.' || isdigit(*expr))
{
if (*expr == '.') hasPoint = true;
++ expr;
}
if (start == expr) return NULL;
if (!hasPoint)
{
sint64 value = 0;
// this is an integer
for (const char *nbPtr = start; nbPtr < expr; ++ nbPtr)
{
value *= 10;
value += (sint64) (*nbPtr - '0');
}
setInteger(negative ? - value : value);
return expr;
}
else // floating point value : use scanf
{
// well, for now, we only parse a float
float value;
std::string floatValue(start, expr - start);
if (fromString(floatValue, value))
{
setDouble(negative ? - value : value);
return expr;
}
else
{
return NULL;
}
}
}
//==================================================================
const char *CInterfaceExprValue::evalString(const char *expr)
{
expr = skipBlank(expr);
if (*expr != '\'') return NULL;
++expr;
std::string str;
for (;;)
{
if (expr == '\0')
{
nlwarning("CInterfaceExprValue::evalString : end of buffer encountered in a string");
return NULL;
}
else
if (*expr == '\'')
{
++ expr;
break;
}
if (*expr == '\\') // special char
{
++ expr;
switch (*expr)
{
case 't': str += '\t'; break;
case 'r': str += '\r'; break;
case 'n': str += '\n'; break;
case '\'': str += '\''; break;
case '"': str += '"'; break;
case '\\': str += '\\'; break;
case '\n':
case '\r':
// string continue on next line, so do nothing
break;
case '\0': continue;
default:
nlwarning("CInterfaceExprValue::evalString : unknown escape sequence : \\%c", *expr);
if (*expr) str += *expr;
break;
}
}
else if (*expr == '\n' || *expr == '\r')
{
nlwarning("CInterfaceExprValue::evalString : line break encountered in a string");
return NULL;
}
else
{
str += *expr;
}
++ expr;
}
setString(str);
return expr;
}
//==================================================================
bool CInterfaceExprValue::toType(TType type)
{
switch(type)
{
case Boolean: return toBool();
case Integer: return toInteger();
case Double: return toDouble();
case String: return toString();
case RGBA: return toRGBA();
default: return false;
}
}
//==================================================================
void CInterfaceExprValue::clean()
{
switch (_Type)
{
case String: _StringValue.clear(); break;
case UserType: delete _UserTypeValue; break;
default: break;
}
}
//==================================================================
void CInterfaceExprValue::setUserType(CInterfaceExprUserType *value)
{
if (_Type == UserType && value == _UserTypeValue) return;
clean();
_Type = UserType;
_UserTypeValue = value;
}
//==================================================================
bool CInterfaceExprValue::getBool() const
{
if (_Type != Boolean)
{
nlwarning("<CInterfaceExprValue::getBool> bad type!");
return false;
}
return _BoolValue;
}
//==================================================================
sint64 CInterfaceExprValue::getInteger() const
{
if (_Type != Integer)
{
nlwarning("<CInterfaceExprValue::getInteger> bad type!");
return 0;
}
return _IntegerValue;
}
//==================================================================
double CInterfaceExprValue::getDouble() const
{
if (_Type != Double)
{
nlwarning("<CInterfaceExprValue::getDouble> bad type!");
return 0;
}
return _DoubleValue;
}
//==================================================================
std::string CInterfaceExprValue::getString() const
{
if (_Type != String)
{
nlwarning("<CInterfaceExprValue::getString> bad type!");
return "";
}
return _StringValue.toString();
}
//==================================================================
NLMISC::CRGBA CInterfaceExprValue::getRGBA() const
{
if (_Type != RGBA)
{
nlwarning("<CInterfaceExprValue::getRGBA> bad type!");
return CRGBA::White;
}
NLMISC::CRGBA col;
col.R = (uint8)(_RGBAValue&0xff);
col.G = (uint8)((_RGBAValue>>8)&0xff);
col.B = (uint8)((_RGBAValue>>16)&0xff);
col.A = (uint8)((_RGBAValue>>24)&0xff);
return col;
}
//==================================================================
const ucstring &CInterfaceExprValue::getUCString() const
{
if (_Type != String)
{
nlwarning("<CInterfaceExprValue::getString> bad type!");
static ucstring emptyString;
return emptyString;
}
return _StringValue;
}
//==================================================================
CInterfaceExprUserType *CInterfaceExprValue::getUserType() const
{
if (_Type != UserType)
{
nlwarning("<CInterfaceExprValue::getUserType> bad type!");
return NULL;
}
return _UserTypeValue;
}
//==================================================================
CInterfaceExprValue::CInterfaceExprValue(const CInterfaceExprValue &other) : _Type(NoType)
{
*this = other;
}
//==================================================================
CInterfaceExprValue &CInterfaceExprValue::operator = (const CInterfaceExprValue &other)
{
if (this != &other)
{
clean();
switch(other._Type)
{
case Boolean: _BoolValue = other._BoolValue; break;
case Integer: _IntegerValue = other._IntegerValue; break;
case Double: _DoubleValue = other._DoubleValue; break;
case String: _StringValue = other._StringValue; break;
case RGBA: _RGBAValue = other._RGBAValue; break;
case UserType:
if (other._UserTypeValue != NULL)
{
_UserTypeValue = other._UserTypeValue->clone();
}
else
{
_UserTypeValue = NULL;
}
break;
case NoType: break;
default:
nlwarning("<CInterfaceExprValue::operator=> bad source type") ;
return *this;
break;
}
_Type = other._Type;
}
return *this;
}

View file

@ -1,242 +0,0 @@
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef CL_INTERFACE_EXPR_H
#define CL_INTERFACE_EXPR_H
#include "nel/misc/ucstring.h"
#include "nel/misc/rgba.h"
namespace NLMISC{
class ICDBNode;
class CCDBNodeLeaf;
class CCDBNodeBranch;
}
struct CInterfaceExprUserType;
class CInterfaceExprNode;
/** a value that can be returned by a CInterfaceExpr instance
* It supports basic type;
* It can be extended by user defined types
*/
class CInterfaceExprValue
{
public:
enum TType { Boolean = 0, Integer, Double, String, RGBA, UserType, NoType };
public:
// default ctor
CInterfaceExprValue() : _Type(NoType) {}
// copy ctor
CInterfaceExprValue(const CInterfaceExprValue &other);
// assignment operator
CInterfaceExprValue &operator = (const CInterfaceExprValue &other);
// dtor
~CInterfaceExprValue() { clean(); }
TType getType() const { return _Type; }
// get. Should be used only if the type is valid
bool getBool() const;
sint64 getInteger() const;
double getDouble() const;
std::string getString() const;
NLMISC::CRGBA getRGBA() const;
const ucstring &getUCString() const;
CInterfaceExprUserType *getUserType() const;
// set
void setBool(bool value) { clean(); _Type = Boolean; _BoolValue = value; }
void setInteger(sint64 value) { clean(); _Type = Integer; _IntegerValue = value; }
void setDouble(double value) { clean(); _Type = Double; _DoubleValue = value; }
void setString(const std::string &value) { clean(); _Type = String; _StringValue = value; }
void setUCString(const ucstring &value) { clean(); _Type = String; _StringValue = value; }
void setRGBA(NLMISC::CRGBA value) { clean(); _Type = RGBA; _RGBAValue = (uint32)(value.R+(value.G<<8)+(value.B<<16)+(value.A<<24)); }
void setUserType(CInterfaceExprUserType *value);
// reset this object to initial state (no type)
void clean();
// conversions. They return true if success
bool toBool();
bool toInteger();
bool toDouble();
bool toString();
bool toType(TType type);
bool toRGBA();
// test if the value if a bool, double, or integer
bool isNumerical() const;
/** evaluate a from a string
* \param expr : where to start the evaluation
* \return the position following the token, or NULL if the parsing failed
*/
const char *initFromString(const char *expr);
/////////////////////////////////////////////////////////////////////////////////////////////
private:
TType _Type;
union
{
bool _BoolValue;
sint64 _IntegerValue;
double _DoubleValue;
CInterfaceExprUserType *_UserTypeValue;
uint32 _RGBAValue;
};
ucstring _StringValue; // well, can't fit in union, unless we do some horrible hack..
private:
const char *evalBoolean(const char *expr);
const char *evalNumber(const char *expr);
const char *evalString(const char *expr);
};
/**
* Base class for user defined types that are use by the 'CInterfaceExprValue' class
* Derivers should include the 'clone' method
*
* CInterfaceExprValue instances have ownership of this object.
*
* \author Nicolas Vizerie
* \author Nevrax France
* \date 2003
*/
struct CInterfaceExprUserType
{
// cloning method
virtual CInterfaceExprUserType *clone() const = 0;
// dtor
virtual ~CInterfaceExprUserType() {}
};
/** Evaluate expressions used in interface.
* It can retrieve values from the database.
* It can also build a list of database values it depends of.
*
* An expression can be :
*
* - a string : 'toto', 'abcd', 'a\nbcd', 'a\\t', the escape sequences are the one of C
* - a integer 1, 2, 3
* - a double 1.1, 2.2
* - a database entry : @ui:interface:toto:truc. If the address is a leaf, it returns the leaf value and put an observer on it. If not a leaf, it returns 0, but put an observer on it.
* - a database indirection @db:value[db:index] is replaced by @db:value0 if db:index == 0 for example
* - a user function call : fct(expr0, epxr1, ...).
*
* NB : The lua language has been integrated since then (2005), and should be more suited
* for most of the tasks.
*
*
* \author Nicolas Vizerie
* \author Nevrax France
* \date 2002
*/
class CInterfaceExpr
{
public:
// list of argument for a function
typedef std::vector<CInterfaceExprValue> TArgList;
/** prototype of a user callable function
* It should return true if the result is meaningful. If not, the rest of the evaluation is stopped
*/
typedef bool (* TUserFct) (TArgList &args, CInterfaceExprValue &result);
public:
// release memory
static void release();
/** This try to eval the provided expression.
* - This returns a result
* - This eventually fill a vector with a set of database entries it has dependencies on
* \param expr The expression to evaluate
* \param result The result value
* \param nodes If not NULL, will be filled with the database nodes this expression depends on
* Node will only be inserted once, so we end up with a set of node (not ordered)
* \param noFctCalls when set to true, the terminal function calls will not be made, so the evaluation is only used to see which database entries the expression depends on.
*/
static bool eval(const std::string &expr, CInterfaceExprValue &result, std::vector<NLMISC::ICDBNode *> *nodes = NULL, bool noFctCalls = false);
/** Build a tree from the given expression so that it can be evaluated quickly.
* This is useful for a fixed expression that must be evaluated often
*/
static CInterfaceExprNode *buildExprTree(const std::string &expr);
/** Register a function that can have several arguments
* // NB : this is case sensitive
*/
static void registerUserFct(const char *name, TUserFct fct);
// Simple evaluations
static bool evalAsInt(const std::string &expr, sint64 &dest);
static bool evalAsDouble(const std::string &expr, double &dest);
static bool evalAsBool(const std::string &expr, bool &dest);
static bool evalAsString(const std::string &expr, std::string &dest);
/////////////////////////////////////////////////////////////////////////////////////////////
private:
// map of user functions
typedef std::map<std::string, TUserFct> TUserFctMap;
private:
static TUserFctMap *_UserFct;
private:
/** eval the value of a single expression
* \return position to the next valid character
*/
static const char *evalExpr(const char *expr, CInterfaceExprValue &result, std::vector<NLMISC::ICDBNode *> *nodes, bool noFctCalls);
static const char *evalFct(const char *expr,CInterfaceExprValue &result,std::vector<NLMISC::ICDBNode *> *nodes, bool noFctCalls);
static const char *evalDBEntry(const char *expr,CInterfaceExprValue &result,std::vector<NLMISC::ICDBNode *> *nodes);
public:
static const char *unpackDBentry(const char *expr, std::vector<NLMISC::ICDBNode *> *nodes, std::string &dest, bool *hasIndirections = NULL);
/** Build tree of a single expression
* \return position to the next valid character
*/
private:
static const char *buildExprTree(const char *expr, CInterfaceExprNode *&result);
static const char *buildFctNode(const char *expr, CInterfaceExprNode *&result);
static const char *buildDBEntryNode(const char *expr,CInterfaceExprNode *&result);
};
// helper macro to register user functions at startup
#define REGISTER_INTERFACE_USER_FCT(name, fct) \
const struct __InterUserFctRegister__##fct\
{\
__InterUserFctRegister__##fct() { CInterfaceExpr::registerUserFct(name, fct); }\
} __InterUserFctRegisterInstance__##fct;
// helper macro to declare a user function
// the code must follow
// arguments are available in 'args', result should be put in 'result'
#define DECLARE_INTERFACE_USER_FCT(name) \
bool name(CInterfaceExpr::TArgList &args, CInterfaceExprValue &result)
// helper macro to declare a C constant mirroring
#define DECLARE_INTERFACE_CONSTANT(_name, _cconst) \
static DECLARE_INTERFACE_USER_FCT(_name) \
{ \
result.setInteger(_cconst); \
return true; \
} \
REGISTER_INTERFACE_USER_FCT(#_name, _name)
#endif

View file

@ -1,159 +0,0 @@
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "stdpch.h"
#include "interface_expr_node.h"
#include "nel/misc/cdb_leaf.h"
#include "nel/misc/cdb_branch.h"
using NLMISC::ICDBNode;
using NLMISC::CCDBNodeBranch;
using NLMISC::CCDBNodeLeaf;
// *******************************************************************************************************
void CInterfaceExprNodeValue::eval(CInterfaceExprValue &result)
{
result = Value;
}
void CInterfaceExprNodeValue::evalWithDepends(CInterfaceExprValue &result, std::vector<ICDBNode *> &/* nodes */)
{
result = Value;
}
void CInterfaceExprNodeValue::getDepends(std::vector<ICDBNode *> &/* nodes */)
{
}
// *******************************************************************************************************
void CInterfaceExprNodeValueFnCall::eval(CInterfaceExprValue &result)
{
nlassert(Func);
uint numParams = (uint)Params.size();
std::vector<CInterfaceExprValue> params(numParams);
for(uint k = 0; k < numParams; ++k)
{
Params[k]->eval(params[k]);
}
Func(params, result); // do actual call
}
void CInterfaceExprNodeValueFnCall::evalWithDepends(CInterfaceExprValue &result, std::vector<ICDBNode *> &nodes)
{
nlassert(Func);
uint numParams = (uint)Params.size();
std::vector<CInterfaceExprValue> params(numParams);
for(uint k = 0; k < numParams; ++k)
{
Params[k]->evalWithDepends(params[k], nodes);
}
Func(params, result); // do actual call
}
void CInterfaceExprNodeValueFnCall::getDepends(std::vector<ICDBNode *> &nodes)
{
uint numParams = (uint)Params.size();
for(uint k = 0; k < numParams; ++k)
{
Params[k]->getDepends(nodes);
}
}
CInterfaceExprNodeValueFnCall::~CInterfaceExprNodeValueFnCall()
{
for(uint k = 0; k < Params.size(); ++k)
{
delete Params[k];
}
}
// *******************************************************************************************************
void CInterfaceExprNodeDBLeaf::eval(CInterfaceExprValue &result)
{
nlassert(Leaf);
result.setInteger(Leaf->getValue64());
}
void CInterfaceExprNodeDBLeaf::evalWithDepends(CInterfaceExprValue &result,std::vector<ICDBNode *> &nodes)
{
nlassert(Leaf);
result.setInteger(Leaf->getValue64());
if (std::find(nodes.begin(), nodes.end(), Leaf) == nodes.end())
{
nodes.push_back(Leaf);
}
}
void CInterfaceExprNodeDBLeaf::getDepends(std::vector<ICDBNode *> &nodes)
{
nlassert(Leaf);
if (std::find(nodes.begin(), nodes.end(), Leaf) == nodes.end())
{
nodes.push_back(Leaf);
}
}
// *******************************************************************************************************
void CInterfaceExprNodeDBBranch::eval(CInterfaceExprValue &result)
{
nlassert(Branch);
result.setInteger(0);
}
void CInterfaceExprNodeDBBranch::evalWithDepends(CInterfaceExprValue &result,std::vector<ICDBNode *> &nodes)
{
nlassert(Branch);
result.setInteger(0);
if (std::find(nodes.begin(), nodes.end(), Branch) == nodes.end())
{
nodes.push_back(Branch);
}
}
void CInterfaceExprNodeDBBranch::getDepends(std::vector<ICDBNode *> &nodes)
{
nlassert(Branch);
if (std::find(nodes.begin(), nodes.end(), Branch) == nodes.end())
{
nodes.push_back(Branch);
}
}
// *******************************************************************************************************
void CInterfaceExprNodeDependantDBRead::eval(CInterfaceExprValue &result)
{
// no gain there, but barely used
CInterfaceExpr::eval(Expr, result);
}
void CInterfaceExprNodeDependantDBRead::evalWithDepends(CInterfaceExprValue &result, std::vector<ICDBNode *> &nodes)
{
CInterfaceExpr::eval(Expr, result, &nodes);
}
void CInterfaceExprNodeDependantDBRead::getDepends(std::vector<ICDBNode *> &nodes)
{
CInterfaceExprValue dummyResult;
CInterfaceExpr::eval(Expr, dummyResult, &nodes, true);
}

View file

@ -1,123 +0,0 @@
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef CL_INTERFACE_EXPR_NODE_H
#define CL_INTERFACE_EXPR_NODE_H
#include "interface_expr.h"
/** Base node of an interface expression parse tree
* \author Nicolas Vizerie
* \author Nevrax France
* \date 2003
*/
class CInterfaceExprNode
{
public:
virtual ~CInterfaceExprNode() {}
// eval result of expression, and eventually get the nodes the epression depends on
virtual void eval(CInterfaceExprValue &result) = 0;
// The same, but get db nodes the expression depends on (appended to vector)
virtual void evalWithDepends(CInterfaceExprValue &result, std::vector<NLMISC::ICDBNode *> &nodes) = 0;
// Get dependencies of the node (appended to vector)
virtual void getDepends(std::vector<NLMISC::ICDBNode *> &nodes) = 0;
};
// *******************************************************************************************************
/** A constant value already parsed by interface (in a interface expr parse tree)
*/
class CInterfaceExprNodeValue : public CInterfaceExprNode
{
public:
CInterfaceExprValue Value;
public:
virtual void eval(CInterfaceExprValue &result);
virtual void evalWithDepends(CInterfaceExprValue &result, std::vector<NLMISC::ICDBNode *> &nodes);
virtual void getDepends(std::vector<NLMISC::ICDBNode *> &nodes);
};
// *******************************************************************************************************
/** A fct call (in a interface expr parse tree)
*/
class CInterfaceExprNodeValueFnCall : public CInterfaceExprNode
{
public:
CInterfaceExpr::TUserFct Func;
// list of parameters
std::vector<CInterfaceExprNode *> Params;
public:
virtual void eval(CInterfaceExprValue &result);
virtual void evalWithDepends(CInterfaceExprValue &result, std::vector<NLMISC::ICDBNode *> &nodes);
virtual void getDepends(std::vector<NLMISC::ICDBNode *> &nodes);
virtual ~CInterfaceExprNodeValueFnCall();
};
// *******************************************************************************************************
/** A db leaf read (in a interface expr parse tree)
*/
class CInterfaceExprNodeDBLeaf : public CInterfaceExprNode
{
public:
class NLMISC::CCDBNodeLeaf *Leaf;
public:
virtual void eval(CInterfaceExprValue &result);
virtual void evalWithDepends(CInterfaceExprValue &result, std::vector<NLMISC::ICDBNode *> &nodes);
virtual void getDepends(std::vector<NLMISC::ICDBNode *> &nodes);
};
// *******************************************************************************************************
/** A db branch read (in a interface expr parse tree)
*/
class CInterfaceExprNodeDBBranch : public CInterfaceExprNode
{
public:
class NLMISC::CCDBNodeBranch *Branch;
public:
virtual void eval(CInterfaceExprValue &result);
virtual void evalWithDepends(CInterfaceExprValue &result, std::vector<NLMISC::ICDBNode *> &nodes);
virtual void getDepends(std::vector<NLMISC::ICDBNode *> &nodes);
};
// *******************************************************************************************************
/** A dependant db read (in a interface expr parse tree)
* This is rarely used so no real optim there..
*/
class CInterfaceExprNodeDependantDBRead : public CInterfaceExprNode
{
public:
std::string Expr;
public:
virtual void eval(CInterfaceExprValue &result);
virtual void evalWithDepends(CInterfaceExprValue &result, std::vector<NLMISC::ICDBNode *> &nodes);
virtual void getDepends(std::vector<NLMISC::ICDBNode *> &nodes);
};
#endif

View file

@ -20,7 +20,7 @@
#include "stdpch.h" #include "stdpch.h"
// client // client
#include "interface_expr.h" #include "nel/gui/interface_expr.h"
#include "ctrl_sheet_selection.h" #include "ctrl_sheet_selection.h"
#include "interface_manager.h" #include "interface_manager.h"
// game_share // game_share
@ -519,7 +519,7 @@ static DECLARE_INTERFACE_USER_FCT(userFctGetProp)
string sTmp = args[0].getString(); string sTmp = args[0].getString();
std::vector<CInterfaceLink::CTargetInfo> targetsVector; std::vector<CInterfaceLink::CTargetInfo> targetsVector;
CInterfaceParser::splitLinkTargets(sTmp, NULL, targetsVector); CInterfaceLink::splitLinkTargets(sTmp, NULL, targetsVector);
if (targetsVector.empty()) if (targetsVector.empty())
{ {

View file

@ -18,7 +18,7 @@
#include "stdpch.h" #include "stdpch.h"
// Interface // Interface
#include "interface_expr.h" #include "nel/gui/interface_expr.h"
#include "interface_manager.h" #include "interface_manager.h"
#include "interface_element.h" #include "interface_element.h"
#include "chat_window.h" #include "chat_window.h"

View file

@ -20,7 +20,7 @@
// client // client
#include "../sheet_manager.h" #include "../sheet_manager.h"
#include "interface_expr.h" #include "nel/gui/interface_expr.h"
#include "dbctrl_sheet.h" #include "dbctrl_sheet.h"
#include "ctrl_sheet_selection.h" #include "ctrl_sheet_selection.h"
#include "dbgroup_list_sheet.h" #include "dbgroup_list_sheet.h"

View file

@ -19,10 +19,10 @@
#include "stdpch.h" #include "stdpch.h"
#include "interface_link.h" #include "interface_link.h"
#include "interface_expr.h"
#include "interface_element.h" #include "interface_element.h"
#include "interface_manager.h" #include "interface_manager.h"
#include "interface_expr_node.h" #include "nel/gui/interface_expr.h"
#include "nel/gui/interface_expr_node.h"
#include "nel/gui/reflect.h" #include "nel/gui/reflect.h"
#include "nel/gui/db_manager.h" #include "nel/gui/db_manager.h"
#include "nel/misc/cdb_branch.h" #include "nel/misc/cdb_branch.h"
@ -444,6 +444,88 @@ void CInterfaceLink::removeAllLinks()
nlassert(_LinkList.empty()); nlassert(_LinkList.empty());
} }
// ***************************************************************************
bool CInterfaceLink::splitLinkTarget(const std::string &target, CInterfaceGroup *parentGroup, std::string &propertyName, CInterfaceElement *&targetElm)
{
// the last token of the target gives the name of the property
std::string::size_type lastPos = target.find_last_of(':');
if (lastPos == (target.length() - 1))
{
// todo hulud interface syntax error
nlwarning("The target should at least contains a path and a property as follow 'path:property'");
return false;
}
std::string elmPath;
std::string elmProp;
CInterfaceElement *elm = NULL;
if (parentGroup)
{
if (lastPos == std::string::npos)
{
elmProp = target;
elm = parentGroup;
elmPath = "current";
}
else
{
elmProp = target.substr(lastPos + 1);
elmPath = parentGroup->getId() + ":" + target.substr(0, lastPos);
elm = parentGroup->getElement(elmPath);
}
}
if (!elm)
{
// try the absolute adress of the element
elmPath = target.substr(0, lastPos);
elm = CInterfaceManager::getInstance()->getElementFromId(elmPath);
elmProp = target.substr(lastPos + 1);
}
if (!elm)
{
// todo hulud interface syntax error
nlwarning("<splitLinkTarget> can't find target link %s", elmPath.c_str());
return false;
}
targetElm = elm;
propertyName = elmProp;
return true;
}
// ***************************************************************************
bool CInterfaceLink::splitLinkTargets(const std::string &targets, CInterfaceGroup *parentGroup,std::vector<CInterfaceLink::CTargetInfo> &targetsVect)
{
std::vector<std::string> targetNames;
NLMISC::splitString(targets, ",", targetNames);
targetsVect.clear();
targetsVect.reserve(targetNames.size());
bool everythingOk = true;
for (uint k = 0; k < targetNames.size(); ++k)
{
CInterfaceLink::CTargetInfo ti;
std::string::size_type startPos = targetNames[k].find_first_not_of(" ");
if(startPos == std::string::npos)
{
// todo hulud interface syntax error
nlwarning("<splitLinkTargets> empty target encountered");
continue;
}
std::string::size_type lastPos = targetNames[k].find_last_not_of(" ");
if (!splitLinkTarget(targetNames[k].substr(startPos, lastPos - startPos+1), parentGroup, ti.PropertyName, ti.Elem))
{
// todo hulud interface syntax error
nlwarning("<splitLinkTargets> Can't get link target");
everythingOk = false;
continue;
}
targetsVect.push_back(ti);
}
return everythingOk;
}
//=========================================================== //===========================================================
void CInterfaceLink::checkNbRefs() void CInterfaceLink::checkNbRefs()
{ {
@ -470,7 +552,7 @@ void CInterfaceLink::setTargetProperty (const std::string &Target, const CInt
if (pIG != NULL) if (pIG != NULL)
{ {
std::vector<CTargetInfo> vTargets; std::vector<CTargetInfo> vTargets;
CInterfaceParser::splitLinkTargets(Target, pIG, vTargets); splitLinkTargets(Target, pIG, vTargets);
if ((vTargets.size() > 0) && (vTargets[0].Elem)) if ((vTargets.size() > 0) && (vTargets[0].Elem))
{ {
vTargets[0].affect(val); vTargets[0].affect(val);

View file

@ -25,13 +25,14 @@
namespace NLGUI namespace NLGUI
{ {
class CReflectedProperty; class CReflectedProperty;
class CInterfaceExprValue;
class CInterfaceExprNode;
} }
class CInterfaceElement; class CInterfaceElement;
class CInterfaceExprValue;
class CInterfaceGroup; class CInterfaceGroup;
class CInterfaceExprNode;
using namespace NLGUI; using namespace NLGUI;
@ -115,6 +116,16 @@ public:
static void setTargetProperty (const std::string & Target, const CInterfaceExprValue &val); static void setTargetProperty (const std::string & Target, const CInterfaceExprValue &val);
static bool isUpdatingAllLinks() { return _UpdateAllLinks; } static bool isUpdatingAllLinks() { return _UpdateAllLinks; }
/** From a target name of a link, retrieve the target element and its target target property
* \return true if the target is valid
*/
static bool splitLinkTarget(const std::string &target, CInterfaceGroup *parentGroup, std::string &propertyName, CInterfaceElement *&targetElm);
/** From several target names of a link (seprated by ','), retrieve the target elements and their target properties
* \return true if all targets are valid
*/
static bool splitLinkTargets(const std::string &targets, CInterfaceGroup *parentGroup, std::vector<CInterfaceLink::CTargetInfo> &targetsVect);
//////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////
private: private:
friend struct CRemoveTargetPred; friend struct CRemoveTargetPred;

View file

@ -35,7 +35,7 @@
#include "../client_cfg.h" #include "../client_cfg.h"
#include "encyclopedia_manager.h" #include "encyclopedia_manager.h"
// Expr // Expr
#include "interface_expr.h" #include "nel/gui/interface_expr.h"
#include "register_interface_elements.h" #include "register_interface_elements.h"
// Action / Observers // Action / Observers
#include "action_handler.h" #include "action_handler.h"

View file

@ -1403,7 +1403,7 @@ bool CInterfaceParser::parseLink(xmlNodePtr cur, CInterfaceGroup * parentGroup)
ptr = (char*) xmlGetProp (cur, (xmlChar*)"target"); ptr = (char*) xmlGetProp (cur, (xmlChar*)"target");
if (ptr) if (ptr)
{ {
splitLinkTargets(std::string((const char*)ptr), parentGroup, targets); CInterfaceLink::splitLinkTargets(std::string((const char*)ptr), parentGroup, targets);
} }
// optional action handler // optional action handler
std::string action; std::string action;
@ -2925,88 +2925,6 @@ bool CInterfaceParser::parseSheetSelection(xmlNodePtr cur)
return true; return true;
} }
// ***************************************************************************
bool CInterfaceParser::splitLinkTarget(const std::string &target, CInterfaceGroup *parentGroup, std::string &propertyName, CInterfaceElement *&targetElm)
{
// the last token of the target gives the name of the property
std::string::size_type lastPos = target.find_last_of(':');
if (lastPos == (target.length() - 1))
{
// todo hulud interface syntax error
nlwarning("The target should at least contains a path and a property as follow 'path:property'");
return false;
}
std::string elmPath;
std::string elmProp;
CInterfaceElement *elm = NULL;
if (parentGroup)
{
if (lastPos == std::string::npos)
{
elmProp = target;
elm = parentGroup;
elmPath = "current";
}
else
{
elmProp = target.substr(lastPos + 1);
elmPath = parentGroup->getId() + ":" + target.substr(0, lastPos);
elm = parentGroup->getElement(elmPath);
}
}
if (!elm)
{
// try the absolute adress of the element
elmPath = target.substr(0, lastPos);
elm = CInterfaceManager::getInstance()->getElementFromId(elmPath);
elmProp = target.substr(lastPos + 1);
}
if (!elm)
{
// todo hulud interface syntax error
nlwarning("<CInterfaceParser::splitLinkTarget> can't find target link %s", elmPath.c_str());
return false;
}
targetElm = elm;
propertyName = elmProp;
return true;
}
// ***************************************************************************
bool CInterfaceParser::splitLinkTargets(const std::string &targets, CInterfaceGroup *parentGroup,std::vector<CInterfaceLink::CTargetInfo> &targetsVect)
{
std::vector<std::string> targetNames;
NLMISC::splitString(targets, ",", targetNames);
targetsVect.clear();
targetsVect.reserve(targetNames.size());
bool everythingOk = true;
for (uint k = 0; k < targetNames.size(); ++k)
{
CInterfaceLink::CTargetInfo ti;
std::string::size_type startPos = targetNames[k].find_first_not_of(" ");
if(startPos == std::string::npos)
{
// todo hulud interface syntax error
nlwarning("<CInterfaceParser::splitLinkTargets> empty target encountered");
continue;
}
std::string::size_type lastPos = targetNames[k].find_last_not_of(" ");
if (!splitLinkTarget(targetNames[k].substr(startPos, lastPos - startPos+1), parentGroup, ti.PropertyName, ti.Elem))
{
// todo hulud interface syntax error
nlwarning("<CInterfaceParser::splitLinkTargets> Can't get link target");
everythingOk = false;
continue;
}
targetsVect.push_back(ti);
}
return everythingOk;
}
// *************************************************************************** // ***************************************************************************
bool CInterfaceParser::addLink(CInterfaceLink *link, const std::string &id) bool CInterfaceParser::addLink(CInterfaceLink *link, const std::string &id)
{ {

View file

@ -214,16 +214,6 @@ public:
void setDefine(const std::string &id, const std::string &value); void setDefine(const std::string &id, const std::string &value);
// @} // @}
/** From a target name of a link, retrieve the target element and its target target property
* \return true if the target is valid
*/
static bool splitLinkTarget(const std::string &target, CInterfaceGroup *parentGroup, std::string &propertyName, CInterfaceElement *&targetElm);
/** From several target names of a link (seprated by ','), retrieve the target elements and their target properties
* \return true if all targets are valid
*/
static bool splitLinkTargets(const std::string &targets, CInterfaceGroup *parentGroup, std::vector<CInterfaceLink::CTargetInfo> &targetsVect);
/// \name Dynamic links mgt /// \name Dynamic links mgt
// @{ // @{
/** Associate the given dynamic link with an ID /** Associate the given dynamic link with an ID

View file

@ -53,7 +53,7 @@
#include "game_share/people_pd.h" #include "game_share/people_pd.h"
#include "group_tree.h" #include "group_tree.h"
#include "interface_link.h" #include "interface_link.h"
#include "interface_expr.h" #include "nel/gui/interface_expr.h"
#include "people_interraction.h" #include "people_interraction.h"
#include "nel/misc/algo.h" #include "nel/misc/algo.h"
#include "nel/misc/file.h" #include "nel/misc/file.h"

View file

@ -30,7 +30,7 @@
#include "dbgroup_combo_box.h" #include "dbgroup_combo_box.h"
#include "group_container.h" #include "group_container.h"
#include "group_modal_get_key.h" #include "group_modal_get_key.h"
#include "interface_expr.h" #include "nel/gui/interface_expr.h"
// tmp // tmp
#include "../r2/editor.h" #include "../r2/editor.h"

View file

@ -20,7 +20,7 @@
// client // client
#include "../string_manager_client.h" #include "../string_manager_client.h"
#include "people_interraction.h" #include "people_interraction.h"
#include "interface_expr.h" #include "nel/gui/interface_expr.h"
#include "interface_manager.h" #include "interface_manager.h"
#include "action_handler.h" #include "action_handler.h"
#include "action_handler_misc.h" #include "action_handler_misc.h"
@ -30,7 +30,7 @@
#include "group_menu.h" #include "group_menu.h"
#include "../client_chat_manager.h" #include "../client_chat_manager.h"
#include "../string_manager_client.h" #include "../string_manager_client.h"
#include "interface_expr.h" #include "nel/gui/interface_expr.h"
#include "ctrl_button.h" #include "ctrl_button.h"
#include "ctrl_text_button.h" #include "ctrl_text_button.h"
#include "filtered_chat_summary.h" #include "filtered_chat_summary.h"
@ -1027,7 +1027,7 @@ class CHandlerChatGroupFilter : public IActionHandler
CCtrlTabButton *pTabButton= dynamic_cast<CCtrlTabButton*>(pCaller); CCtrlTabButton *pTabButton= dynamic_cast<CCtrlTabButton*>(pCaller);
if(pTabButton) if(pTabButton)
{ {
CRGBA stdColor= stringToRGBA(pIM->getDefine("chat_group_tab_color_normal").c_str()); CRGBA stdColor= CRGBA::stringToRGBA(pIM->getDefine("chat_group_tab_color_normal").c_str());
pTabButton->setTextColorNormal(stdColor); pTabButton->setTextColorNormal(stdColor);
} }
} }

View file

@ -976,21 +976,6 @@ std::string getStringCategoryIfAny(const ucstring &src, ucstring &dest)
} }
NLMISC::CRGBA stringToRGBA(const char *ptr)
{
if (!ptr) return NLMISC::CRGBA::White;
int r = 255, g = 255, b = 255, a = 255;
sscanf (ptr, "%d %d %d %d", &r, &g, &b, &a);
NLMISC::clamp (r, 0, 255);
NLMISC::clamp (g, 0, 255);
NLMISC::clamp (b, 0, 255);
NLMISC::clamp (a, 0, 255);
return CRGBA(r,g,b,a);
}
// *************************************************************************** // ***************************************************************************
inline bool isSeparator (ucchar c) inline bool isSeparator (ucchar c)

View file

@ -166,9 +166,6 @@ std::string getStringCategory(const ucstring &src, ucstring &dest, bool alwaysAd
// Get the category from the string (src="&SYS&Who are you?" and dest="Who are you?" and return "SYS"), if no category, return "" // Get the category from the string (src="&SYS&Who are you?" and dest="Who are you?" and return "SYS"), if no category, return ""
std::string getStringCategoryIfAny(const ucstring &src, ucstring &dest); std::string getStringCategoryIfAny(const ucstring &src, ucstring &dest);
NLMISC::CRGBA stringToRGBA(const char *ptr);
// Number of shortcut // Number of shortcut
#define RYZOM_MAX_SHORTCUT 20 #define RYZOM_MAX_SHORTCUT 20