Merge branch 'main/rendor-staging' into fixes
[ryzomcore.git] / nel / src / gui / reflect.cpp
blob994df9c3a40664994b622baad5dac22ea8b9d398
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2013 Laszlo KIS-ADAM (dfighter) <dfighter1985@gmail.com>
6 //
7 // This program is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU Affero General Public License as
9 // published by the Free Software Foundation, either version 3 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU Affero General Public License for more details.
17 // You should have received a copy of the GNU Affero General Public License
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "stdpch.h"
22 #include "nel/gui/reflect.h"
24 #ifdef DEBUG_NEW
25 #define new DEBUG_NEW
26 #endif
28 namespace NLGUI
30 // Yoyo: Act like a singleton, else registerClass may crash.
31 CReflectSystem::TClassMap *CReflectSystem::_ClassMap= NULL;
33 // hack to register the root class at startup
34 static const struct CRootReflectableClassRegister
36 CRootReflectableClassRegister()
38 TReflectedProperties props;
39 CReflectSystem::registerClass("CReflectable", "", props);
41 } _RootReflectableClassRegisterInstance;
44 //===================================================================================
45 // release memory
46 void CReflectSystem::release()
48 delete _ClassMap;
49 _ClassMap = NULL;
52 //===================================================================================
53 void CReflectSystem::registerClass(const std::string &className, const std::string &parentName, const TReflectedProperties properties)
55 if(!_ClassMap) _ClassMap= new TClassMap;
57 TClassMap::const_iterator it = _ClassMap->find(className);
58 if (it != _ClassMap->end())
60 nlerror("CReflectSystem::registerClass : Class registered twice : %s!", className.c_str());
62 CClassInfo &ci = (*_ClassMap)[className];
63 ci.Properties = properties;
64 ci.ClassName = className;
65 for(uint k = 0; k < ci.Properties.size(); ++k)
67 ci.Properties[k].ParentClass = &ci;
69 if (parentName.empty())
71 ci.ParentClass = NULL;
73 else
75 it = _ClassMap->find(parentName);
76 if (it == _ClassMap->end())
78 nlerror("CReflectSystem::registerClass : Parent class %s not found", parentName.c_str());
80 ci.ParentClass = &(it->second);
84 //===================================================================================
85 const CReflectedProperty *CReflectSystem::getProperty(const std::string &className, const std::string &propertyName, bool dspWarning)
87 if(!_ClassMap) _ClassMap= new TClassMap;
89 TClassMap::const_iterator it = _ClassMap->find(className);
90 if (it == _ClassMap->end())
92 nlwarning("CReflectSystem::getProperty : Unkwown class : %s", className.c_str());
93 return NULL;
95 const CClassInfo *ci = &it->second;
96 while (ci)
98 // Linear search should suffice for now
99 for(uint k = 0; k < ci->Properties.size(); ++k)
101 if (ci->Properties[k].Name == propertyName)
103 return &(ci->Properties[k]);
106 // search in parent
107 ci = ci->ParentClass;
109 //\ TODO nico : possible optimization : instead of going up in the parents when
110 // searching for a property, it would be simpler to concatenate properties
111 // from parent class at registration.
112 // All that would be left at the end would be a hash_map of properties ...
114 if(dspWarning)
115 nlwarning("CReflectSystem::getProperty : %s is not a property of class : %s", propertyName.c_str(), className.c_str());
116 return NULL;
120 //===================================================================================
121 const CClassInfo *CReflectable::getClassInfo()
123 if (!CReflectSystem::getClassMap()) return NULL;
124 // TODO nico : a possible optimization would be to use the address of the static function
125 // 'getReflectedProperties' as a key into the CClassInfo map. This pointer uniquely identify
126 // classes that export properties
127 CReflectSystem::TClassMap::const_iterator it = CReflectSystem::getClassMap()->find(this->getReflectedClassName());
128 if (it == CReflectSystem::getClassMap()->end())
130 return NULL;
132 return &(it->second);
135 //===================================================================================
136 const CReflectedProperty *CReflectable::getReflectedProperty(const std::string &propertyName, bool dspWarning) const
138 return CReflectSystem::getProperty(this->getReflectedClassName(), propertyName, dspWarning);
143 #include "nel/gui/lua_manager.h"
145 namespace NLGUI
147 CReflectableRefPtrTarget::~CReflectableRefPtrTarget()
149 CLuaState *lua= CLuaManager::getInstance().getLuaState();
150 if(!lua)
151 return;
152 CLuaStackChecker lsc(lua);
153 // remove from the lua registry if i'm in
154 lua->pushLightUserData((void *) this);
155 lua->getTable(LUA_REGISTRYINDEX);
156 if (!lua->isNil(-1))
158 lua->pop();
159 lua->pushLightUserData((void *) this);
160 lua->pushNil();
161 lua->setTable(LUA_REGISTRYINDEX);
163 else
165 lua->pop();
170 * Data structure pushed in lua (a userdata) to access CReflectableRefPtrTarget derived objects
171 * These includes element of the GUI.
172 * if holds a pointer to the reflectable object, and
173 * a cache to its CClassInfo for fast access to exported properties
174 * \see reflect.h
179 inline const CClassInfo &CReflectableLuaRef::getClassInfo() const
181 nlassert(Ptr); // class info should not be accessed for a null ptr
182 if (_ClassInfo) return *_ClassInfo;
183 _ClassInfo = Ptr->getClassInfo();
184 return *_ClassInfo;
187 const CReflectedProperty *CReflectableLuaRef::getProp(const char *luaStringPtr) const
189 const CClassInfo &ci = getClassInfo();
190 CClassInfo::TLuaStrToPropMap::const_iterator it = ci.LuaStrToProp.find(luaStringPtr);
191 if (it != ci.LuaStrToProp.end())
193 return it->second.Prop;
195 // slowly retrieve property, and store in cache
196 // NB nico : this could also be done at startup...
197 const CReflectedProperty *prop = CReflectSystem::getProperty(ci.ClassName, luaStringPtr, false);
198 if (!prop) return NULL;
199 CLuaIndexedProperty lip;
200 lip.Id = CLuaString(luaStringPtr); // keep a ref on the lua string to ensure that its pointer always remains valid
201 lip.Prop = prop;
202 ci.LuaStrToProp[luaStringPtr] = lip;
203 return prop;