simObject.h 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737
  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. #ifndef _SIM_OBJECT_H_
  23. #define _SIM_OBJECT_H_
  24. #ifndef _CONSOLEOBJECT_H_
  25. #include "console/consoleObject.h"
  26. #endif
  27. #ifndef _SIM_FIELD_DICTIONARY_H_
  28. #include "sim/simFieldDictionary.h"
  29. #endif
  30. #ifndef _TAML_CALLBACKS_H_
  31. #include "persistence/taml/tamlCallbacks.h"
  32. #endif
  33. //-----------------------------------------------------------------------------
  34. typedef U32 SimObjectId;
  35. class SimGroup;
  36. //---------------------------------------------------------------------------
  37. /// Base class for objects involved in the simulation.
  38. ///
  39. /// @section simobject_intro Introduction
  40. ///
  41. /// SimObject is a base class for most of the classes you'll encounter
  42. /// working in Torque. It provides fundamental services allowing "smart"
  43. /// object referencing, creation, destruction, organization, and location.
  44. /// Along with SimEvent, it gives you a flexible event-scheduling system,
  45. /// as well as laying the foundation for the in-game editors, GUI system,
  46. /// and other vital subsystems.
  47. ///
  48. /// @section simobject_subclassing Subclassing
  49. ///
  50. /// You will spend a lot of your time in Torque subclassing, or working
  51. /// with subclasses of, SimObject. SimObject is designed to be easy to
  52. /// subclass.
  53. ///
  54. /// You should not need to override anything in a subclass except:
  55. /// - The constructor/destructor.
  56. /// - processArguments()
  57. /// - onAdd()/onRemove()
  58. /// - onGroupAdd()/onGroupRemove()
  59. /// - onNameChange()
  60. /// - onStaticModified()
  61. /// - onDeleteNotify()
  62. /// - onEditorEnable()/onEditorDisable()
  63. /// - inspectPreApply()/inspectPostApply()
  64. /// - things from ConsoleObject (see ConsoleObject docs for specifics)
  65. ///
  66. /// Of course, if you know what you're doing, go nuts! But in most cases, you
  67. /// shouldn't need to touch things not on that list.
  68. ///
  69. /// When you subclass, you should define a typedef in the class, called Parent,
  70. /// that references the class you're inheriting from.
  71. ///
  72. /// @code
  73. /// class mySubClass : public SimObject {
  74. /// typedef SimObject Parent;
  75. /// ...
  76. /// @endcode
  77. ///
  78. /// Then, when you override a method, put in:
  79. ///
  80. /// @code
  81. /// bool mySubClass::onAdd()
  82. /// {
  83. /// if(!Parent::onAdd())
  84. /// return false;
  85. ///
  86. /// // ... do other things ...
  87. /// }
  88. /// @endcode
  89. ///
  90. /// Of course, you want to replace onAdd with the appropriate method call.
  91. ///
  92. /// @section simobject_lifecycle A SimObject's Life Cycle
  93. ///
  94. /// SimObjects do not live apart. One of the primary benefits of using a
  95. /// SimObject is that you can uniquely identify it and easily find it (using
  96. /// its ID). Torque does this by keeping a global hierarchy of SimGroups -
  97. /// a tree - containing every registered SimObject. You can then query
  98. /// for a given object using Sim::findObject() (or SimSet::findObject() if
  99. /// you want to search only a specific set).
  100. ///
  101. /// @code
  102. /// // Three examples of registering an object.
  103. ///
  104. /// // Method 1:
  105. /// AIClient *aiPlayer = new AIClient();
  106. /// aiPlayer->registerObject();
  107. ///
  108. /// // Method 2:
  109. /// ActionMap* globalMap = new ActionMap;
  110. /// globalMap->registerObject("GlobalActionMap");
  111. ///
  112. /// // Method 3:
  113. /// bool reg = mObj->registerObject(id);
  114. /// @endcode
  115. ///
  116. /// Registering a SimObject performs these tasks:
  117. /// - Marks the object as not cleared and not removed.
  118. /// - Assigns the object a unique SimObjectID if it does not have one already.
  119. /// - Adds the object to the global name and ID dictionaries so it can be found
  120. /// again.
  121. /// - Calls the object's onAdd() method. <b>Note:</b> SimObject::onAdd() performs
  122. /// some important initialization steps. See @ref simobject_subclassing "here
  123. /// for details" on how to properly subclass SimObject.
  124. /// - If onAdd() fails (returns false), it calls unregisterObject().
  125. /// - Checks to make sure that the SimObject was properly initialized (and asserts
  126. /// if not).
  127. ///
  128. /// Calling registerObject() and passing an ID or a name will cause the object to be
  129. /// assigned that name and/or ID before it is registered.
  130. ///
  131. /// Congratulations, you have now registered your object! What now?
  132. ///
  133. /// Well, hopefully, the SimObject will have a long, useful life. But eventually,
  134. /// it must die.
  135. ///
  136. /// There are a two ways a SimObject can die.
  137. /// - First, the game can be shut down. This causes the root SimGroup
  138. /// to be unregistered and deleted. When a SimGroup is unregistered,
  139. /// it unregisters all of its member SimObjects; this results in everything
  140. /// that has been registered with Sim being unregistered, as everything
  141. /// registered with Sim is in the root group.
  142. /// - Second, you can manually kill it off, either by calling unregisterObject()
  143. /// or by calling deleteObject().
  144. ///
  145. /// When you unregister a SimObject, the following tasks are performed:
  146. /// - The object is flagged as removed.
  147. /// - Notifications are cleaned up.
  148. /// - If the object is in a group, then it removes itself from the group.
  149. /// - Delete notifications are sent out.
  150. /// - Finally, the object removes itself from the Sim globals, and tells
  151. /// Sim to get rid of any pending events for it.
  152. ///
  153. /// If you call deleteObject(), all of the above tasks are performed, in addition
  154. /// to some sanity checking to make sure the object was previously added properly,
  155. /// and isn't in the process of being deleted. After the object is unregistered, it
  156. /// de-allocates itself.
  157. ///
  158. /// @section simobject_editor Torque Editors
  159. ///
  160. /// SimObjects are one of the building blocks for the in-game editors. They
  161. /// provide a basic interface for the editor to be able to list the fields
  162. /// of the object, update them safely and reliably, and inform the object
  163. /// things have changed.
  164. ///
  165. /// This interface is implemented in the following areas:
  166. /// - onNameChange() is called when the object is renamed.
  167. /// - onStaticModified() is called whenever a static field is modified.
  168. /// - inspectPreApply() is called before the object's fields are updated,
  169. /// when changes are being applied.
  170. /// - inspectPostApply() is called after the object's fields are updated.
  171. /// - onEditorEnable() is called whenever an editor is enabled (for instance,
  172. /// when you hit F11 to bring up the world editor).
  173. /// - onEditorDisable() is called whenever the editor is disabled (for instance,
  174. /// when you hit F11 again to close the world editor).
  175. ///
  176. /// (Note: you can check the variable gEditingMission to see if the mission editor
  177. /// is running; if so, you may want to render special indicators. For instance, the
  178. /// fxFoliageReplicator renders inner and outer radii when the mission editor is
  179. /// running.)
  180. ///
  181. /// @section simobject_console The Console
  182. ///
  183. /// SimObject extends ConsoleObject by allowing you to
  184. /// to set arbitrary dynamic fields on the object, as well as
  185. /// statically defined fields. This is done through two methods,
  186. /// setDataField and getDataField, which deal with the complexities of
  187. /// allowing access to two different types of object fields.
  188. ///
  189. /// Static fields take priority over dynamic fields. This is to be
  190. /// expected, as the role of dynamic fields is to allow data to be
  191. /// stored in addition to the predefined fields.
  192. ///
  193. /// The fields in a SimObject are like properties (or fields) in a class.
  194. ///
  195. /// Some fields may be arrays, which is what the array parameter is for; if it's non-null,
  196. /// then it is parsed with dAtoI and used as an index into the array. If you access something
  197. /// as an array which isn't, then you get an empty string.
  198. ///
  199. /// <b>You don't need to read any further than this.</b> Right now,
  200. /// set/getDataField are called a total of 6 times through the entire
  201. /// Torque codebase. Therefore, you probably don't need to be familiar
  202. /// with the details of accessing them. You may want to look at Con::setData
  203. /// instead. Most of the time you will probably be accessing fields directly,
  204. /// or using the scripting language, which in either case means you don't
  205. /// need to do anything special.
  206. ///
  207. /// The functions to get/set these fields are very straightforward:
  208. ///
  209. /// @code
  210. /// setDataField(StringTable->insert("locked", false), NULL, b ? "true" : "false" );
  211. /// curObject->setDataField(curField, curFieldArray, STR.getStringValue());
  212. /// setDataField(slotName, array, value);
  213. /// @endcode
  214. ///
  215. /// <i>For advanced users:</i> There are two flags which control the behavior
  216. /// of these functions. The first is ModStaticFields, which controls whether
  217. /// or not the DataField functions look through the static fields (defined
  218. /// with addField; see ConsoleObject for details) of the class. The second
  219. /// is ModDynamicFields, which controls dynamically defined fields. They are
  220. /// set automatically by the console constructor code.
  221. ///
  222. /// @nosubgrouping
  223. class SimObject: public ConsoleObject, public TamlCallbacks
  224. {
  225. typedef ConsoleObject Parent;
  226. friend class SimManager;
  227. friend class SimGroup;
  228. friend class SimNameDictionary;
  229. friend class SimManagerNameDictionary;
  230. friend class SimIdDictionary;
  231. //-------------------------------------- Structures and enumerations
  232. private:
  233. /// Flags for use in mFlags
  234. enum {
  235. Deleted = BIT(0), ///< This object is marked for deletion.
  236. Removed = BIT(1), ///< This object has been unregistered from the object system.
  237. Added = BIT(3), ///< This object has been registered with the object system.
  238. Selected = BIT(4), ///< This object has been marked as selected. (in editor)
  239. Expanded = BIT(5), ///< This object has been marked as expanded. (in editor)
  240. ModStaticFields = BIT(6), ///< The object allows you to read/modify static fields
  241. ModDynamicFields = BIT(7) ///< The object allows you to read/modify dynamic fields
  242. };
  243. public:
  244. /// @name Notification
  245. /// @{
  246. struct Notify {
  247. enum Type {
  248. ClearNotify, ///< Notified when the object is cleared.
  249. DeleteNotify, ///< Notified when the object is deleted.
  250. ObjectRef, ///< Cleverness to allow tracking of references.
  251. Invalid ///< Mark this notification as unused (used in freeNotify).
  252. } type;
  253. void *ptr; ///< Data (typically referencing or interested object).
  254. Notify *next; ///< Next notification in the linked list.
  255. };
  256. /// @}
  257. enum WriteFlags {
  258. SelectedOnly = BIT(0) ///< Passed to SimObject::write to indicate that only objects
  259. /// marked as selected should be outputted. Used in SimSet.
  260. };
  261. private:
  262. // dictionary information stored on the object
  263. StringTableEntry objectName;
  264. SimObject* nextNameObject;
  265. SimObject* nextManagerNameObject;
  266. SimObject* nextIdObject;
  267. SimGroup* mGroup; ///< SimGroup we're contained in, if any.
  268. BitSet32 mFlags;
  269. StringTableEntry mProgenitorFile;
  270. S32 mPeriodicTimerID;
  271. /// @name Notification
  272. /// @{
  273. Notify* mNotifyList;
  274. /// @}
  275. Vector<StringTableEntry> mFieldFilter;
  276. protected:
  277. SimObjectId mId; ///< Id number for this object.
  278. StringTableEntry mIdString;
  279. Namespace* mNameSpace;
  280. U32 mTypeMask;
  281. S32 mScriptCallbackGuard; ///< Whether the object is executing a script callback.
  282. protected:
  283. /// @name Notification
  284. /// Helper functions for notification code.
  285. /// @{
  286. static SimObject::Notify *mNotifyFreeList;
  287. static SimObject::Notify *allocNotify(); ///< Get a free Notify structure.
  288. static void freeNotify(SimObject::Notify*); ///< Mark a Notify structure as free.
  289. /// @}
  290. private:
  291. SimFieldDictionary *mFieldDictionary; ///< Storage for dynamic fields.
  292. protected:
  293. /// Taml callbacks.
  294. virtual void onTamlPreWrite( void ) {}
  295. virtual void onTamlPostWrite( void ) {}
  296. virtual void onTamlPreRead( void ) {}
  297. virtual void onTamlPostRead( const TamlCustomNodes& customNodes ) {}
  298. virtual void onTamlAddParent( SimObject* pParentObject ) {}
  299. virtual void onTamlCustomWrite( TamlCustomNodes& customNodes ) {}
  300. virtual void onTamlCustomRead( const TamlCustomNodes& customNodes ) {}
  301. protected:
  302. bool mCanSaveFieldDictionary; ///< true if dynamic fields (added at runtime) should be saved, defaults to true
  303. StringTableEntry mInternalName; ///< Stores object Internal Name
  304. // Namespace linking
  305. StringTableEntry mClassName; ///< Stores the class name to link script class namespaces
  306. StringTableEntry mSuperClassName; ///< Stores super class name to link script class namespaces
  307. static bool setClass(void* obj, const char* data) { static_cast<SimObject*>(obj)->setClassNamespace(data); return false; };
  308. static bool setSuperClass(void* obj, const char* data) { static_cast<SimObject*>(obj)->setSuperClassNamespace(data); return false; };
  309. static bool writeCanSaveDynamicFields( void* obj, StringTableEntry pFieldName ) { return static_cast<SimObject*>(obj)->mCanSaveFieldDictionary == false; }
  310. static bool writeInternalName( void* obj, StringTableEntry pFieldName ) { SimObject* simObject = static_cast<SimObject*>(obj); return simObject->mInternalName != NULL && simObject->mInternalName != StringTable->EmptyString; }
  311. static bool setParentGroup(void* obj, const char* data);
  312. static bool writeParentGroup( void* obj, StringTableEntry pFieldName ) { return static_cast<SimObject*>(obj)->mGroup != NULL; }
  313. static bool writeSuperclass( void* obj, StringTableEntry pFieldName ) { SimObject* simObject = static_cast<SimObject*>(obj); return simObject->mSuperClassName != NULL && simObject->mSuperClassName != StringTable->EmptyString; }
  314. static bool writeClass( void* obj, StringTableEntry pFieldName ) { SimObject* simObject = static_cast<SimObject*>(obj); return simObject->mClassName != NULL && simObject->mClassName != StringTable->EmptyString; }
  315. // Accessors
  316. public:
  317. StringTableEntry getClassNamespace() const { return mClassName; };
  318. StringTableEntry getSuperClassNamespace() const { return mSuperClassName; };
  319. void setClassNamespace( const char* classNamespace );
  320. void setSuperClassNamespace( const char* superClassNamespace );
  321. // Script callback deletion guard.
  322. inline void pushScriptCallbackGuard( void ) { mScriptCallbackGuard++; }
  323. inline void popScriptCallbackGuard( void ) { mScriptCallbackGuard--; AssertFatal( mScriptCallbackGuard >= 0, "Invalid script callback guard." ); }
  324. inline S32 getScriptCallbackGuard( void ) { return mScriptCallbackGuard; }
  325. protected:
  326. // By setting the value of mNSLinkMask in the constructor of a class that
  327. // inherits from SimObject, you can specify how the namespaces are linked
  328. // for that class. An easy way to think about this change, if you have worked
  329. // with this in the past is that ScriptObject uses:
  330. // mNSLinkMask = LinkSuperClassName | LinkClassName;
  331. // which will attempt to do a full namespace link checking mClassName and mSuperClassName
  332. //
  333. // and BehaviorTemplate does not set the value of NSLinkMask, which means that
  334. // only the default link will be made, which is: ObjectName -> ClassName
  335. enum SimObjectNSLinkType
  336. {
  337. LinkClassName = BIT(0),
  338. LinkSuperClassName = BIT(1)
  339. };
  340. U8 mNSLinkMask;
  341. void linkNamespaces();
  342. void unlinkNamespaces();
  343. public:
  344. /// @name Accessors
  345. /// @{
  346. /// Get the value of a field on the object.
  347. ///
  348. /// See @ref simobject_console "here" for a detailed discussion of what this
  349. /// function does.
  350. ///
  351. /// @param slotName Field to access.
  352. /// @param array String containing index into array
  353. /// (if field is an array); if NULL, it is ignored.
  354. const char *getDataField(StringTableEntry slotName, const char *array);
  355. /// Set the value of a field on the object.
  356. ///
  357. /// See @ref simobject_console "here" for a detailed discussion of what this
  358. /// function does.
  359. ///
  360. /// @param slotName Field to access.
  361. /// @param array String containing index into array; if NULL, it is ignored.
  362. /// @param value Value to store.
  363. void setDataField(StringTableEntry slotName, const char *array, const char *value);
  364. const char *getPrefixedDataField(StringTableEntry fieldName, const char *array);
  365. void setPrefixedDataField(StringTableEntry fieldName, const char *array, const char *value);
  366. const char *getPrefixedDynamicDataField(StringTableEntry fieldName, const char *array, const S32 fieldType = -1);
  367. void setPrefixedDynamicDataField(StringTableEntry fieldName, const char *array, const char *value, const S32 fieldType = -1);
  368. StringTableEntry getDataFieldPrefix( StringTableEntry fieldName );
  369. /// Get the type of a field on the object.
  370. ///
  371. /// @param slotName Field to access.
  372. /// @param array String containing index into array
  373. /// (if field is an array); if NULL, it is ignored.
  374. U32 getDataFieldType(StringTableEntry slotName, const char *array);
  375. /// Get reference to the dictionary containing dynamic fields.
  376. ///
  377. /// See @ref simobject_console "here" for a detailed discussion of what this
  378. /// function does.
  379. ///
  380. /// This dictionary can be iterated over using a SimFieldDictionaryIterator.
  381. SimFieldDictionary * getFieldDictionary() {return(mFieldDictionary);}
  382. /// Clear all dynamic fields.
  383. inline void clearDynamicFields( void ) { if ( mFieldDictionary != NULL ) { delete mFieldDictionary; mFieldDictionary = new SimFieldDictionary; } }
  384. /// Set whether fields created at runtime should be saved. Default is true.
  385. void setCanSaveDynamicFields(bool bCanSave){ mCanSaveFieldDictionary = bCanSave;}
  386. /// Get whether fields created at runtime should be saved. Default is true.
  387. inline bool getCanSaveDynamicFields(void) const { return mCanSaveFieldDictionary;}
  388. /// These functions support internal naming that is not namespace
  389. /// bound for locating child controls in a generic way.
  390. ///
  391. /// Set the internal name of this control (Not linked to a namespace)
  392. void setInternalName(const char* newname);
  393. /// Get the internal of of this control
  394. StringTableEntry getInternalName();
  395. /// Save object as a TorqueScript File.
  396. virtual bool save(const char* pcFilePath, bool bOnlySelected=false);
  397. /// Check if a method exists in the objects current namespace.
  398. virtual bool isMethod( const char* methodName );
  399. /// @}
  400. /// @name Initialization
  401. /// @{
  402. ///
  403. SimObject( const U8 namespaceLinkMask = LinkSuperClassName | LinkClassName );
  404. virtual ~SimObject();
  405. virtual bool processArguments(S32 argc, const char **argv); ///< Process constructor options. (ie, new SimObject(1,2,3))
  406. /// @}
  407. /// @name Events
  408. /// @{
  409. virtual bool onAdd(); ///< Called when the object is added to the sim.
  410. virtual void onRemove(); ///< Called when the object is removed from the sim.
  411. virtual void onGroupAdd(); ///< Called when the object is added to a SimGroup.
  412. virtual void onGroupRemove(); ///< Called when the object is removed from a SimGroup.
  413. virtual void onNameChange(const char *name); ///< Called when the object's name is changed.
  414. virtual void onStaticModified(const char* slotName, const char*newValue = NULL); ///< Called when a static field is modified.
  415. ///
  416. /// Specifically, this is called by setDataField
  417. /// when a static field is modified, see
  418. /// @ref simobject_console "the console details".
  419. /// Called before any property of the object is changed in the world editor.
  420. ///
  421. /// The calling order here is:
  422. /// - inspectPreApply()
  423. /// - ...
  424. /// - calls to setDataField()
  425. /// - ...
  426. /// - inspectPostApply()
  427. virtual void inspectPreApply();
  428. /// Called after any property of the object is changed in the world editor.
  429. ///
  430. /// @see inspectPreApply
  431. virtual void inspectPostApply();
  432. /// Called when a SimObject is deleted.
  433. ///
  434. /// When you are on the notification list for another object
  435. /// and it is deleted, this method is called.
  436. virtual void onDeleteNotify(SimObject *object);
  437. /// Called when the editor is activated.
  438. virtual void onEditorEnable(){};
  439. /// Called when the editor is deactivated.
  440. virtual void onEditorDisable(){};
  441. /// @}
  442. /// Find a named sub-object of this object.
  443. ///
  444. /// This is subclassed in the SimGroup and SimSet classes.
  445. ///
  446. /// For a single object, it just returns NULL, as normal objects cannot have children.
  447. virtual SimObject *findObject(const char *name);
  448. /// @name Notification
  449. /// @{
  450. Notify *removeNotify(void *ptr, Notify::Type); ///< Remove a notification from the list.
  451. void deleteNotify(SimObject* obj); ///< Notify an object when we are deleted.
  452. void clearNotify(SimObject* obj); ///< Notify an object when we are cleared.
  453. void clearAllNotifications(); ///< Remove all notifications for this object.
  454. void processDeleteNotifies(); ///< Send out deletion notifications.
  455. /// Register a reference to this object.
  456. ///
  457. /// You pass a pointer to your reference to this object.
  458. ///
  459. /// When the object is deleted, it will null your
  460. /// pointer, ensuring you don't access old memory.
  461. ///
  462. /// @param obj Pointer to your reference to the object.
  463. void registerReference(SimObject **obj);
  464. /// Unregister a reference to this object.
  465. ///
  466. /// Remove a reference from the list, so that it won't
  467. /// get nulled inappropriately.
  468. ///
  469. /// Call this when you're done with your reference to
  470. /// the object, especially if you're going to free the
  471. /// memory. Otherwise, you may erroneously get something
  472. /// overwritten.
  473. ///
  474. /// @see registerReference
  475. void unregisterReference(SimObject **obj);
  476. /// @}
  477. /// @name Registration
  478. ///
  479. /// SimObjects must be registered with the object system.
  480. /// @{
  481. /// Register an object with the object system.
  482. ///
  483. /// This must be called if you want to keep the object around.
  484. /// In the rare case that you will delete the object immediately, or
  485. /// don't want to be able to use Sim::findObject to locate it, then
  486. /// you don't need to register it.
  487. ///
  488. /// registerObject adds the object to the global ID and name dictionaries,
  489. /// after first assigning it a new ID number. It calls onAdd(). If onAdd fails,
  490. /// it unregisters the object and returns false.
  491. ///
  492. /// If a subclass's onAdd doesn't eventually call SimObject::onAdd(), it will
  493. /// cause an assertion.
  494. bool registerObject();
  495. /// Register the object, forcing the id.
  496. ///
  497. /// @see registerObject()
  498. /// @param id ID to assign to the object.
  499. bool registerObject(U32 id);
  500. /// Register the object, assigning the name.
  501. ///
  502. /// @see registerObject()
  503. /// @param name Name to assign to the object.
  504. bool registerObject(const char *name);
  505. /// Register the object, assigning a name and ID.
  506. ///
  507. /// @see registerObject()
  508. /// @param name Name to assign to the object.
  509. /// @param id ID to assign to the object.
  510. bool registerObject(const char *name, U32 id);
  511. /// Unregister the object from Sim.
  512. ///
  513. /// This performs several operations:
  514. /// - Sets the removed flag.
  515. /// - Call onRemove()
  516. /// - Clear out notifications.
  517. /// - Remove the object from...
  518. /// - its group, if any. (via getGroup)
  519. /// - Sim::gNameDictionary
  520. /// - Sim::gIDDictionary
  521. /// - Finally, cancel any pending events for this object (as it can't receive them now).
  522. void unregisterObject();
  523. void deleteObject(); ///< Unregister, mark as deleted, and free the object.
  524. ///
  525. /// This helper function can be used when you're done with the object
  526. /// and don't want to be bothered with the details of cleaning it up.
  527. /// @}
  528. /// @name Accessors
  529. /// @{
  530. inline SimObjectId getId( void ) const { return mId; }
  531. inline StringTableEntry getIdString( void ) const { return mIdString; }
  532. U32 getType() const { return mTypeMask; }
  533. const StringTableEntry getName( void ) const { return objectName; };
  534. void setId(SimObjectId id);
  535. void assignName(const char* name);
  536. SimGroup* getGroup() const { return mGroup; }
  537. bool isChildOfGroup(SimGroup* pGroup);
  538. bool isProperlyAdded() const { return mFlags.test(Added); }
  539. bool isDeleted() const { return mFlags.test(Deleted); }
  540. bool isRemoved() const { return mFlags.test(Deleted | Removed); }
  541. bool isLocked();
  542. void setLocked( bool b );
  543. bool isHidden();
  544. void setHidden(bool b);
  545. inline void setProgenitorFile( const char* pFile ) { mProgenitorFile = StringTable->insert( pFile ); }
  546. inline StringTableEntry getProgenitorFile( void ) const { return mProgenitorFile; }
  547. inline void setPeriodicTimerID( const S32 timerID ) { mPeriodicTimerID = timerID; }
  548. inline S32 getPeriodicTimerID( void ) const { return mPeriodicTimerID; }
  549. inline bool isPeriodicTimerActive( void ) const { return mPeriodicTimerID != 0; }
  550. /// @}
  551. /// @name Sets
  552. ///
  553. /// The object must be properly registered before you can add/remove it to/from a set.
  554. ///
  555. /// All these functions accept either a name or ID to identify the set you wish
  556. /// to operate on. Then they call addObject or removeObject on the set, which
  557. /// sets up appropriate notifications.
  558. ///
  559. /// An object may be in multiple sets at a time.
  560. /// @{
  561. bool addToSet(SimObjectId);
  562. bool addToSet(const char *);
  563. bool removeFromSet(SimObjectId);
  564. bool removeFromSet(const char *);
  565. /// @}
  566. /// @name Serialization
  567. /// @{
  568. /// Determine whether or not a field should be written.
  569. ///
  570. /// @param fieldname The name of the field being written.
  571. /// @param value The value of the field.
  572. virtual bool writeField(StringTableEntry fieldname, const char* value);
  573. /// Output the TorqueScript to recreate this object.
  574. ///
  575. /// This calls writeFields internally.
  576. /// @param stream Stream to output to.
  577. /// @param tabStop Indentation level for this object.
  578. /// @param flags If SelectedOnly is passed here, then
  579. /// only objects marked as selected (using setSelected)
  580. /// will output themselves.
  581. virtual void write(Stream &stream, U32 tabStop, U32 flags = 0);
  582. /// Write the fields of this object in TorqueScript.
  583. ///
  584. /// @param stream Stream for output.
  585. /// @param tabStop Indentation level for the fields.
  586. virtual void writeFields(Stream &stream, U32 tabStop);
  587. virtual bool writeObject(Stream *stream);
  588. virtual bool readObject(Stream *stream);
  589. virtual void buildFilterList();
  590. void addFieldFilter(const char *fieldName);
  591. void removeFieldFilter(const char *fieldName);
  592. void clearFieldFilters();
  593. bool isFiltered(const char *fieldName);
  594. /// Copy fields from another object onto this one.
  595. ///
  596. /// Objects must be of same type. Everything from obj
  597. /// will overwrite what's in this object; extra fields
  598. /// in this object will remain. This includes dynamic
  599. /// fields.
  600. ///
  601. /// @param obj Object to copy from.
  602. void assignFieldsFrom(SimObject *obj);
  603. /// Copy dynamic fields from another object onto this one.
  604. ///
  605. /// Everything from obj will overwrite what's in this
  606. /// object.
  607. ///
  608. /// @param obj Object to copy from.
  609. void assignDynamicFieldsFrom(SimObject *obj);
  610. /// @}
  611. /// Return the object's namespace.
  612. Namespace* getNamespace() { return mNameSpace; }
  613. /// Get next matching item in namespace.
  614. ///
  615. /// This wraps a call to Namespace::tabComplete; it gets the
  616. /// next thing in the namespace, given a starting value
  617. /// and a base length of the string. See
  618. /// Namespace::tabComplete for details.
  619. const char *tabComplete(const char *prevText, S32 baseLen, bool);
  620. /// @name Accessors
  621. /// @{
  622. bool isSelected() const { return mFlags.test(Selected); }
  623. bool isExpanded() const { return mFlags.test(Expanded); }
  624. void setSelected(bool sel) { if(sel) mFlags.set(Selected); else mFlags.clear(Selected); }
  625. void setExpanded(bool exp) { if(exp) mFlags.set(Expanded); else mFlags.clear(Expanded); }
  626. void setModDynamicFields(bool dyn) { if(dyn) mFlags.set(ModDynamicFields); else mFlags.clear(ModDynamicFields); }
  627. void setModStaticFields(bool sta) { if(sta) mFlags.set(ModStaticFields); else mFlags.clear(ModStaticFields); }
  628. /// @}
  629. virtual void dump();
  630. virtual void dumpClassHierarchy();
  631. static void initPersistFields();
  632. SimObject* clone( const bool copyDynamicFields );
  633. virtual void copyTo(SimObject* object);
  634. template<typename T> bool isType(void) { return dynamic_cast<T>(this) != NULL; }
  635. // Component Console Overrides
  636. virtual bool handlesConsoleMethod(const char * fname, S32 * routingId) { return false; }
  637. DECLARE_CONOBJECT(SimObject);
  638. };
  639. #endif // _SIM_OBJECT_H_