1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2013 Laszlo KIS-ADAM (dfighter) <dfighter1985@gmail.com>
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/>.
22 #include "nel/gui/reflect.h"
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 //===================================================================================
46 void CReflectSystem::release()
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
;
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());
95 const CClassInfo
*ci
= &it
->second
;
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
]);
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 ...
115 nlwarning("CReflectSystem::getProperty : %s is not a property of class : %s", propertyName
.c_str(), className
.c_str());
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())
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"
147 CReflectableRefPtrTarget::~CReflectableRefPtrTarget()
149 CLuaState
*lua
= CLuaManager::getInstance().getLuaState();
152 CLuaStackChecker
lsc(lua
);
153 // remove from the lua registry if i'm in
154 lua
->pushLightUserData((void *) this);
155 lua
->getTable(LUA_REGISTRYINDEX
);
159 lua
->pushLightUserData((void *) this);
161 lua
->setTable(LUA_REGISTRYINDEX
);
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
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();
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
202 ci
.LuaStrToProp
[luaStringPtr
] = lip
;