simSet.cc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2013 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "platform/platform.h"
  23. #include "sim/simBase.h"
  24. #include "string/stringTable.h"
  25. #include "console/console.h"
  26. #include "io/fileStream.h"
  27. #include "input/actionMap.h"
  28. #include "io/resource/resourceManager.h"
  29. #include "io/fileObject.h"
  30. #include "console/consoleInternal.h"
  31. #include "debug/profiler.h"
  32. #include "console/ConsoleTypeValidators.h"
  33. #include "memory/frameAllocator.h"
  34. #include "simSet_ScriptBinding.h"
  35. //////////////////////////////////////////////////////////////////////////
  36. // Sim Set
  37. //////////////////////////////////////////////////////////////////////////
  38. void SimSet::addObject(SimObject* obj)
  39. {
  40. lock();
  41. objectList.pushBack(obj);
  42. deleteNotify(obj);
  43. unlock();
  44. }
  45. void SimSet::removeObject(SimObject* obj)
  46. {
  47. lock();
  48. objectList.remove(obj);
  49. clearNotify(obj);
  50. unlock();
  51. }
  52. void SimSet::pushObject(SimObject* pObj)
  53. {
  54. lock();
  55. objectList.pushBackForce(pObj);
  56. deleteNotify(pObj);
  57. unlock();
  58. }
  59. void SimSet::popObject()
  60. {
  61. MutexHandle handle;
  62. handle.lock(mMutex);
  63. if (objectList.size() == 0)
  64. {
  65. AssertWarn(false, "Stack underflow in SimSet::popObject");
  66. return;
  67. }
  68. SimObject* pObject = objectList[objectList.size() - 1];
  69. objectList.removeStable(pObject);
  70. clearNotify(pObject);
  71. }
  72. //-----------------------------------------------------------------------------
  73. void SimSet::callOnChildren( const char * method, S32 argc, const char *argv[], bool executeOnChildGroups )
  74. {
  75. // Prep the arguments for the console exec...
  76. // Make sure and leave args[1] empty.
  77. const char* args[21];
  78. args[0] = method;
  79. for (S32 i = 0; i < argc; i++)
  80. args[i + 2] = argv[i];
  81. for( iterator i = begin(); i != end(); i++ )
  82. {
  83. SimObject *childObj = static_cast<SimObject*>(*i);
  84. if( childObj->isMethod( method ) )
  85. Con::execute(childObj, argc + 2, args);
  86. if( executeOnChildGroups )
  87. {
  88. SimSet* childSet = dynamic_cast<SimSet*>(*i);
  89. if ( childSet )
  90. childSet->callOnChildren( method, argc, argv, executeOnChildGroups );
  91. }
  92. }
  93. }
  94. bool SimSet::isMember(SimObject* obj)
  95. {
  96. lock();
  97. for (SimSet::iterator i = begin(); i != end(); i++)
  98. {
  99. if (*i == obj)
  100. {
  101. unlock();
  102. return true;
  103. }
  104. }
  105. unlock();
  106. return false;
  107. }
  108. bool SimSet::reOrder( SimObject *obj, SimObject *target )
  109. {
  110. MutexHandle handle;
  111. handle.lock(mMutex);
  112. iterator itrS, itrD;
  113. if ( (itrS = find(begin(),end(),obj)) == end() )
  114. {
  115. return false; // object must be in list
  116. }
  117. if ( obj == target )
  118. {
  119. return true; // don't reorder same object but don't indicate error
  120. }
  121. if ( !target ) // if no target, then put to back of list
  122. {
  123. if ( itrS != (end()-1) ) // don't move if already last object
  124. {
  125. objectList.erase(itrS); // remove object from its current location
  126. objectList.push_back(obj); // push it to the back of the list
  127. }
  128. }
  129. else // if target, insert object in front of target
  130. {
  131. if ( (itrD = find(begin(),end(),target)) == end() )
  132. return false; // target must be in list
  133. objectList.erase(itrS);
  134. //Tinman - once itrS has been erased, itrD won't be pointing at the same place anymore - re-find...
  135. itrD = find(begin(),end(),target);
  136. objectList.insert(itrD,obj);
  137. }
  138. return true;
  139. }
  140. void SimSet::onDeleteNotify(SimObject *object)
  141. {
  142. removeObject(object);
  143. Parent::onDeleteNotify(object);
  144. }
  145. void SimSet::onRemove()
  146. {
  147. MutexHandle handle;
  148. handle.lock(mMutex);
  149. objectList.sortId();
  150. if (objectList.size())
  151. {
  152. // This backwards iterator loop doesn't work if the
  153. // list is empty, check the size first.
  154. for (SimObjectList::iterator ptr = objectList.end() - 1;
  155. ptr >= objectList.begin(); ptr--)
  156. {
  157. clearNotify(*ptr);
  158. }
  159. }
  160. handle.unlock();
  161. Parent::onRemove();
  162. }
  163. void SimSet::write(Stream &stream, U32 tabStop, U32 flags)
  164. {
  165. MutexHandle handle;
  166. handle.lock(mMutex);
  167. // export selected only?
  168. if((flags & SelectedOnly) && !isSelected())
  169. {
  170. for(U32 i = 0; i < (U32)size(); i++)
  171. (*this)[i]->write(stream, tabStop, flags);
  172. return;
  173. }
  174. stream.writeTabs(tabStop);
  175. char buffer[1024];
  176. dSprintf(buffer, sizeof(buffer), "new %s(%s) {\r\n", getClassName(), getName() ? getName() : "");
  177. stream.write(dStrlen(buffer), buffer);
  178. writeFields(stream, tabStop + 1);
  179. if(size())
  180. {
  181. stream.write(2, "\r\n");
  182. for(U32 i = 0; i < (U32)size(); i++)
  183. (*this)[i]->write(stream, tabStop + 1, flags);
  184. }
  185. stream.writeTabs(tabStop);
  186. stream.write(4, "};\r\n");
  187. }
  188. void SimSet::deleteObjects( void )
  189. {
  190. lock();
  191. while(size() > 0 )
  192. {
  193. objectList[0]->deleteObject();
  194. }
  195. unlock();
  196. }
  197. void SimSet::clear()
  198. {
  199. lock();
  200. while (size() > 0)
  201. removeObject(objectList.last());
  202. unlock();
  203. }
  204. SimObject* SimSet::findObjectByInternalName(const char* internalName, bool searchChildren)
  205. {
  206. iterator i;
  207. for (i = begin(); i != end(); i++)
  208. {
  209. SimObject *childObj = static_cast<SimObject*>(*i);
  210. if(childObj->getInternalName() == internalName)
  211. return childObj;
  212. else if (searchChildren)
  213. {
  214. SimSet* childSet = dynamic_cast<SimSet*>(*i);
  215. if (childSet)
  216. {
  217. SimObject* found = childSet->findObjectByInternalName(internalName, searchChildren);
  218. if (found) return found;
  219. }
  220. }
  221. }
  222. return NULL;
  223. }
  224. //////////////////////////////////////////////////////////////////////////
  225. IMPLEMENT_CONOBJECT_CHILDREN(SimSet);
  226. inline void SimSetIterator::Stack::push_back(SimSet* set)
  227. {
  228. increment();
  229. last().set = set;
  230. last().itr = set->begin();
  231. }
  232. //-----------------------------------------------------------------------------
  233. SimSetIterator::SimSetIterator(SimSet* set)
  234. {
  235. VECTOR_SET_ASSOCIATION(stack);
  236. if (!set->empty())
  237. stack.push_back(set);
  238. }
  239. //-----------------------------------------------------------------------------
  240. SimObject* SimSetIterator::operator++()
  241. {
  242. SimSet* set;
  243. if ((set = dynamic_cast<SimSet*>(*stack.last().itr)) != 0)
  244. {
  245. if (!set->empty())
  246. {
  247. stack.push_back(set);
  248. return *stack.last().itr;
  249. }
  250. }
  251. while (++stack.last().itr == stack.last().set->end())
  252. {
  253. stack.pop_back();
  254. if (stack.empty())
  255. return 0;
  256. }
  257. return *stack.last().itr;
  258. }
  259. SimObject* SimGroupIterator::operator++()
  260. {
  261. SimGroup* set;
  262. if ((set = dynamic_cast<SimGroup*>(*stack.last().itr)) != 0)
  263. {
  264. if (!set->empty())
  265. {
  266. stack.push_back(set);
  267. return *stack.last().itr;
  268. }
  269. }
  270. while (++stack.last().itr == stack.last().set->end())
  271. {
  272. stack.pop_back();
  273. if (stack.empty())
  274. return 0;
  275. }
  276. return *stack.last().itr;
  277. }
  278. //////////////////////////////////////////////////////////////////////////
  279. // SimGroup
  280. //////////////////////////////////////////////////////////////////////////
  281. SimGroup::~SimGroup()
  282. {
  283. lock();
  284. for (iterator itr = begin(); itr != end(); itr++)
  285. nameDictionary.remove(*itr);
  286. // XXX Move this later into Group Class
  287. // If we have any objects at this point, they should
  288. // already have been removed from the manager, so we
  289. // can just delete them directly.
  290. objectList.sortId();
  291. while (!objectList.empty())
  292. {
  293. delete objectList.last();
  294. objectList.decrement();
  295. }
  296. unlock();
  297. }
  298. //////////////////////////////////////////////////////////////////////////
  299. void SimGroup::addObject(SimObject* obj)
  300. {
  301. lock();
  302. // Make sure we aren't adding ourself. This isn't the most robust check
  303. // but it should be good enough to prevent some self-foot-shooting.
  304. if(obj == this)
  305. {
  306. Con::errorf("SimGroup::addObject - (%d) can't add self!", getIdString());
  307. unlock();
  308. return;
  309. }
  310. if (obj->mGroup != this)
  311. {
  312. if (obj->mGroup)
  313. obj->mGroup->removeObject(obj);
  314. nameDictionary.insert(obj);
  315. obj->mGroup = this;
  316. objectList.push_back(obj); // force it into the object list
  317. // doesn't get a delete notify
  318. obj->onGroupAdd();
  319. }
  320. unlock();
  321. }
  322. void SimGroup::removeObject(SimObject* obj)
  323. {
  324. lock();
  325. if (obj->mGroup == this)
  326. {
  327. obj->onGroupRemove();
  328. nameDictionary.remove(obj);
  329. objectList.remove(obj);
  330. obj->mGroup = 0;
  331. onChildRemoved(obj);
  332. }
  333. unlock();
  334. }
  335. void SimGroup::onChildRemoved(SimObject* obj)
  336. {
  337. //Left blank...
  338. }
  339. //////////////////////////////////////////////////////////////////////////
  340. void SimGroup::onRemove()
  341. {
  342. lock();
  343. objectList.sortId();
  344. if (objectList.size())
  345. {
  346. // This backwards iterator loop doesn't work if the
  347. // list is empty, check the size first.
  348. for (SimObjectList::iterator ptr = objectList.end() - 1;
  349. ptr >= objectList.begin(); ptr--)
  350. {
  351. if ( (*ptr)->isProperlyAdded() )
  352. {
  353. (*ptr)->onGroupRemove();
  354. (*ptr)->mGroup = NULL;
  355. (*ptr)->unregisterObject();
  356. (*ptr)->mGroup = this;
  357. }
  358. }
  359. }
  360. SimObject::onRemove();
  361. unlock();
  362. }
  363. //////////////////////////////////////////////////////////////////////////
  364. SimObject *SimGroup::findObject(const char *namePath)
  365. {
  366. // find the end of the object name
  367. S32 len;
  368. for(len = 0; namePath[len] != 0 && namePath[len] != '/'; len++)
  369. ;
  370. StringTableEntry stName = StringTable->lookupn(namePath, len);
  371. if(!stName)
  372. return NULL;
  373. SimObject *root = nameDictionary.find(stName);
  374. if(!root)
  375. return NULL;
  376. if(namePath[len] == 0)
  377. return root;
  378. return root->findObject(namePath + len + 1);
  379. }
  380. SimObject *SimSet::findObject(const char *namePath)
  381. {
  382. // find the end of the object name
  383. S32 len;
  384. for(len = 0; namePath[len] != 0 && namePath[len] != '/'; len++)
  385. ;
  386. StringTableEntry stName = StringTable->lookupn(namePath, len);
  387. if(!stName)
  388. return NULL;
  389. lock();
  390. for(SimSet::iterator i = begin(); i != end(); i++)
  391. {
  392. if((*i)->getName() == stName)
  393. {
  394. unlock();
  395. if(namePath[len] == 0)
  396. return *i;
  397. return (*i)->findObject(namePath + len + 1);
  398. }
  399. }
  400. unlock();
  401. return NULL;
  402. }
  403. SimObject* SimObject::findObject(const char* )
  404. {
  405. return NULL;
  406. }
  407. //////////////////////////////////////////////////////////////////////////
  408. bool SimGroup::processArguments(S32, const char **)
  409. {
  410. return true;
  411. }
  412. //////////////////////////////////////////////////////////////////////////
  413. IMPLEMENT_CONOBJECT(SimGroup);