Resolve "Toggle Free Look with Hotkey"
[ryzomcore.git] / ryzom / server / src / ai_service / fx_entity_manager.cpp
blob2fbe072c4c18dd5806f562b11d6b513a61a5d48b
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
17 #include "stdpch.h"
19 #include <queue>
20 #include "fx_entity_manager.h"
22 CFxEntityManager* CFxEntityManager::_Instance = NULL;
24 CFxEntityManager* CFxEntityManager::getInstance()
26 if (!_Instance)
27 _Instance = new CFxEntityManager();
28 return _Instance;
31 void CFxEntityManager::destroyInstance()
33 delete _Instance;
34 _Instance = NULL;
37 CFxEntityPtr CFxEntityManager::create(CAIPos const& pos, NLMISC::CSheetId const& sheet)
39 CFxEntityPtr entity(new CFxEntity(pos, sheet));
40 _Entities.insert(entity);
41 return entity;
44 void CFxEntityManager::registerEntity(CFxEntityPtr const& entity)
46 _IdIndex.insert(std::make_pair(entity->id(), entity));
49 void CFxEntityManager::unregisterEntity(CFxEntityPtr const& entity)
51 _IdIndex.erase(entity->id());
54 void CFxEntityManager::destroy(CFxEntityPtr const& entity)
56 _Entities.erase(entity);
59 CFxEntityPtr CFxEntityManager::get(NLMISC::CEntityId const& id)
61 TEntityIdContainer::iterator it = _IdIndex.find(id);
62 if (it!=_IdIndex.end())
63 return it->second;
64 else
65 return NULL;
68 void CFxEntityManager::init(TDataSetIndex baseRowIndex, TDataSetIndex size)
72 void CFxEntityManager::tickUpdate()
75 // The following loop is there to allow entities to destroy themselves
76 FOREACH(itEntity, TFxEntityContainer, _Entities)
78 CFxEntityPtr entity = (*itEntity);
79 if (entity.isNull())
80 continue;
82 if (!entity->update())
84 entity->despawn();
85 (*itEntity) = NULL;
86 --_NbEntities;
92 bool CFxEntityManager::exists(NLMISC::CEntityId const& id)
94 return _IdIndex.find(id) != _IdIndex.end();
97 /// Valid format for request string is:
98 /// - * Select all entities
99 /// - <entity id> Select the specified entity using his eid (format is "(id:type:crea:dyn)")
100 /// - <name> Select an entity with its name (any name allowed for a fx entity)
101 void CFxEntityManager::select(std::string const& request, std::vector<NLMISC::CEntityId>& entities)
103 if (request.empty())
104 return;
106 if (request == "*")
108 // we want all entities
109 FOREACHC(it, TEntityIdContainer, _IdIndex)
111 entities.push_back(it->first);
114 else if (request[0] == '(')
116 // we want a specific entity id
117 NLMISC::CEntityId id(request);
118 if (exists(id))
119 entities.push_back(id);
121 else
123 // try with the name (when we add a name to these entities)
127 #define ENTITY_VARIABLE(__name,__help) \
128 struct __name##Class : public NLMISC::ICommand \
130 __name##Class () : NLMISC::ICommand("variables",#__name, __help, "<entity> [<value>]") { Type = Variable; } \
131 virtual bool execute(const std::string &rawCommandString, const std::vector<std::string> &args, NLMISC::CLog &log, bool quiet, bool human) \
133 if (args.size() != 1 && args.size() != 2) \
134 return false; \
136 std::vector<NLMISC::CEntityId> entities; \
137 CFxEntityManager::getInstance()->select(args[0], entities); \
139 for (uint i = 0; i < entities.size(); i++) \
141 std::string value; \
142 if (args.size()==2) \
143 value = args[1]; \
144 else \
145 value = "???"; \
146 pointer(entities[i], (args.size()==1), value); \
147 if (quiet) \
148 log.displayNL("%s %s", entities[i].toString().c_str(), value.c_str()); \
149 else \
150 log.displayNL("Entity %s Variable %s = %s", entities[i].toString().c_str(), _CommandName.c_str(), value.c_str()); \
152 return true; \
154 void pointer(NLMISC::CEntityId entity, bool get, std::string &value); \
155 }; \
156 __name##Class __name##Instance; \
157 void __name##Class::pointer(NLMISC::CEntityId entity, bool get, std::string &value)
159 #define ENTITY_GET_FXENTITY \
160 CFxEntity* fxEntity = CFxEntityManager::getInstance()->get(entity); \
161 if(fxEntity == 0) \
163 nlwarning("Unknown entity '%s'", entity.toString().c_str()); \
164 if (get) value = "UnknownEntity"; \
165 return; \
169 struct FxEntityChange
171 FxEntityChange(NLMISC::CEntityId _id, std::string _prop, std::string _value)
172 : id(_id), prop(_prop), value(_value) { }
173 NLMISC::CEntityId id;
174 std::string prop;
175 std::string value;
177 std::queue<FxEntityChange> fxEntityChangeQueue;
179 void execFxEntityChanges()
181 CFxEntityManager* manager = CFxEntityManager::getInstance();
182 while (!fxEntityChangeQueue.empty())
184 FxEntityChange& fxEntityChange = fxEntityChangeQueue.front();
185 CFxEntityPtr fxEntity = manager->get(fxEntityChange.id);
186 if(fxEntity != 0)
188 fxEntity->set(fxEntityChange.prop, fxEntityChange.value, true);
190 fxEntityChangeQueue.pop();
196 ENTITY_VARIABLE(FxEntitySheet, "Sheet of a fx entity")
198 ENTITY_GET_FXENTITY
200 if (get)
201 value = fxEntity->get("sheet");
202 else
203 nlwarning("Trying to change a fx entity's sheet: '%s' to '%s'", fxEntity->get("sheet").c_str(), value.c_str());
206 ENTITY_VARIABLE(FxEntityPosition, "Position of a fx entity")
208 ENTITY_GET_FXENTITY
210 if (get)
211 value = fxEntity->get("position");
212 else
213 nlwarning("Trying to change a fx entity's position: '%s' to '%s'", fxEntity->get("position").c_str(), value.c_str());
216 NLMISC_COMMAND(fxCreateEntity, "Create an fx entity", "<sheet> <x> <y>")
218 if (args.size()<3)
219 return false;
220 NLMISC::CSheetId sheetId(args[0]);
221 if (sheetId==NLMISC::CSheetId::Unknown)
223 log.displayNL("'%s' is not a valid fx sheet id", args[0].c_str());
224 return true;
226 nldebug("Using sheet %s (%d 0x%08x)", sheetId.toString().c_str(), sheetId.asInt(), sheetId.asInt());
227 double x = 0;
228 double y = 0;
229 NLMISC::fromString(args[1], x);
230 NLMISC::fromString(args[2], y);
231 CFxEntityPtr fx = CFxEntityManager::getInstance()->create(CAIPos(x, y, 0, 0.f), sheetId);
232 if (fx->spawn())
233 log.displayNL("Created entity %s", fx->id().toString().c_str());
234 else
235 log.displayNL("Unable to spawn fx entity (mirror range full?)");
236 return true;
239 NLMISC_COMMAND(fxDestroyEntity, "Create an fx entity", "<entity id>")
241 if (args.size()<1)
242 return false;
243 NLMISC::CEntityId entityId(args[0]);
244 if (entityId==NLMISC::CEntityId::Unknown)
246 log.displayNL("'%s' is not a valid entity id", args[0].c_str());
247 return true;
250 CFxEntityPtr fx = CFxEntityManager::getInstance()->get(entityId);
251 if (fx.isNull())
253 log.displayNL("'%s' is not a valid fx entity", entityId.toString().c_str());
254 return true;
256 fx->despawn();
257 CFxEntityManager::getInstance()->destroy(fx);
258 return true;
261 NLMISC_COMMAND(fxManagerDumpIndex, "", "")
263 CFxEntityManager::getInstance()->dumpIndex();
264 return true;