simObject.h 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 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. //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
  23. // Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
  24. // Copyright (C) 2015 Faust Logic, Inc.
  25. //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
  26. #ifndef _SIMOBJECT_H_
  27. #define _SIMOBJECT_H_
  28. #ifndef _SIM_H_
  29. #include "console/sim.h"
  30. #endif
  31. #ifndef _CONSOLEOBJECT_H_
  32. #include "console/consoleObject.h"
  33. #endif
  34. #ifndef _BITSET_H_
  35. #include "core/bitSet.h"
  36. #endif
  37. #ifndef _TAML_CALLBACKS_H_
  38. #include "persistence/taml/tamlCallbacks.h"
  39. #endif
  40. class Stream;
  41. class LightManager;
  42. class SimFieldDictionary;
  43. class SimPersistID;
  44. /// Base class for objects involved in the simulation.
  45. ///
  46. /// @section simobject_intro Introduction
  47. ///
  48. /// SimObject is a base class for most of the classes you'll encounter
  49. /// working in Torque. It provides fundamental services allowing "smart"
  50. /// object referencing, creation, destruction, organization, and location.
  51. /// Along with SimEvent, it gives you a flexible event-scheduling system,
  52. /// as well as laying the foundation for the in-game editors, GUI system,
  53. /// and other vital subsystems.
  54. ///
  55. /// @section simobject_subclassing Subclassing
  56. ///
  57. /// You will spend a lot of your time in Torque subclassing, or working
  58. /// with subclasses of, SimObject. SimObject is designed to be easy to
  59. /// subclass.
  60. ///
  61. /// You should not need to override anything in a subclass except:
  62. /// - The constructor/destructor.
  63. /// - processArguments()
  64. /// - onAdd()/onRemove()
  65. /// - onGroupAdd()/onGroupRemove()
  66. /// - onNameChange()
  67. /// - onStaticModified()
  68. /// - onDeleteNotify()
  69. /// - onEditorEnable()/onEditorDisable()
  70. /// - inspectPreApply()/inspectPostApply()
  71. /// - things from ConsoleObject (see ConsoleObject docs for specifics)
  72. ///
  73. /// Of course, if you know what you're doing, go nuts! But in most cases, you
  74. /// shouldn't need to touch things not on that list.
  75. ///
  76. /// When you subclass, you should define a typedef in the class, called Parent,
  77. /// that references the class you're inheriting from.
  78. ///
  79. /// @code
  80. /// class mySubClass : public SimObject {
  81. /// typedef SimObject Parent;
  82. /// ...
  83. /// @endcode
  84. ///
  85. /// Then, when you override a method, put in:
  86. ///
  87. /// @code
  88. /// bool mySubClass::onAdd()
  89. /// {
  90. /// if(!Parent::onAdd())
  91. /// return false;
  92. ///
  93. /// // ... do other things ...
  94. /// }
  95. /// @endcode
  96. ///
  97. /// Of course, you want to replace onAdd with the appropriate method call.
  98. ///
  99. /// @section simobject_lifecycle A SimObject's Life Cycle
  100. ///
  101. /// SimObjects do not live apart. One of the primary benefits of using a
  102. /// SimObject is that you can uniquely identify it and easily find it (using
  103. /// its ID). Torque does this by keeping a global hierarchy of SimGroups -
  104. /// a tree - containing every registered SimObject. You can then query
  105. /// for a given object using Sim::findObject() (or SimSet::findObject() if
  106. /// you want to search only a specific set).
  107. ///
  108. /// @code
  109. /// // Three examples of registering an object.
  110. ///
  111. /// // Method 1:
  112. /// AIClient *aiPlayer = new AIClient();
  113. /// aiPlayer->registerObject();
  114. ///
  115. /// // Method 2:
  116. /// ActionMap* globalMap = new ActionMap;
  117. /// globalMap->registerObject("GlobalActionMap");
  118. ///
  119. /// // Method 3:
  120. /// bool reg = mObj->registerObject(id);
  121. /// @endcode
  122. ///
  123. /// Registering a SimObject performs these tasks:
  124. /// - Marks the object as not cleared and not removed.
  125. /// - Assigns the object a unique SimObjectID if it does not have one already.
  126. /// - Adds the object to the global name and ID dictionaries so it can be found
  127. /// again.
  128. /// - Calls the object's onAdd() method. <b>Note:</b> SimObject::onAdd() performs
  129. /// some important initialization steps. See @ref simobject_subclassing "here
  130. /// for details" on how to properly subclass SimObject.
  131. /// - If onAdd() fails (returns false), it calls unregisterObject().
  132. /// - Checks to make sure that the SimObject was properly initialized (and asserts
  133. /// if not).
  134. ///
  135. /// Calling registerObject() and passing an ID or a name will cause the object to be
  136. /// assigned that name and/or ID before it is registered.
  137. ///
  138. /// Congratulations, you have now registered your object! What now?
  139. ///
  140. /// Well, hopefully, the SimObject will have a long, useful life. But eventually,
  141. /// it must die.
  142. ///
  143. /// There are a two ways a SimObject can die.
  144. /// - First, the game can be shut down. This causes the root SimGroup
  145. /// to be unregistered and deleted. When a SimGroup is unregistered,
  146. /// it unregisters all of its member SimObjects; this results in everything
  147. /// that has been registered with Sim being unregistered, as everything
  148. /// registered with Sim is in the root group.
  149. /// - Second, you can manually kill it off, either by calling unregisterObject()
  150. /// or by calling deleteObject().
  151. ///
  152. /// When you unregister a SimObject, the following tasks are performed:
  153. /// - The object is flagged as removed.
  154. /// - Notifications are cleaned up.
  155. /// - If the object is in a group, then it removes itself from the group.
  156. /// - Delete notifications are sent out.
  157. /// - Finally, the object removes itself from the Sim globals, and tells
  158. /// Sim to get rid of any pending events for it.
  159. ///
  160. /// If you call deleteObject(), all of the above tasks are performed, in addition
  161. /// to some sanity checking to make sure the object was previously added properly,
  162. /// and isn't in the process of being deleted. After the object is unregistered, it
  163. /// deallocates itself.
  164. ///
  165. /// @section simobject_editor Torque Editors
  166. ///
  167. /// SimObjects are one of the building blocks for the in-game editors. They
  168. /// provide a basic interface for the editor to be able to list the fields
  169. /// of the object, update them safely and reliably, and inform the object
  170. /// things have changed.
  171. ///
  172. /// This interface is implemented in the following areas:
  173. /// - onNameChange() is called when the object is renamed.
  174. /// - onStaticModified() is called whenever a static field is modified.
  175. /// - inspectPreApply() is called before the object's fields are updated,
  176. /// when changes are being applied.
  177. /// - inspectPostApply() is called after the object's fields are updated.
  178. /// - onEditorEnable() is called whenever an editor is enabled (for instance,
  179. /// when you hit F11 to bring up the world editor).
  180. /// - onEditorDisable() is called whenever the editor is disabled (for instance,
  181. /// when you hit F11 again to close the world editor).
  182. ///
  183. /// (Note: you can check the variable gEditingMission to see if the mission editor
  184. /// is running; if so, you may want to render special indicators. For instance, the
  185. /// fxFoliageReplicator renders inner and outer radii when the mission editor is
  186. /// runnning.)
  187. ///
  188. /// @section simobject_console The Console
  189. ///
  190. /// SimObject extends ConsoleObject by allowing you to
  191. /// to set arbitrary dynamic fields on the object, as well as
  192. /// statically defined fields. This is done through two methods,
  193. /// setDataField and getDataField, which deal with the complexities of
  194. /// allowing access to two different types of object fields.
  195. ///
  196. /// Static fields take priority over dynamic fields. This is to be
  197. /// expected, as the role of dynamic fields is to allow data to be
  198. /// stored in addition to the predefined fields.
  199. ///
  200. /// The fields in a SimObject are like properties (or fields) in a class.
  201. ///
  202. /// Some fields may be arrays, which is what the array parameter is for; if it's non-null,
  203. /// then it is parsed with dAtoI and used as an index into the array. If you access something
  204. /// as an array which isn't, then you get an empty string.
  205. ///
  206. /// <b>You don't need to read any further than this.</b> Right now,
  207. /// set/getDataField are called a total of 6 times through the entire
  208. /// Torque codebase. Therefore, you probably don't need to be familiar
  209. /// with the details of accessing them. You may want to look at Con::setData
  210. /// instead. Most of the time you will probably be accessing fields directly,
  211. /// or using the scripting language, which in either case means you don't
  212. /// need to do anything special.
  213. ///
  214. /// The functions to get/set these fields are very straightforward:
  215. ///
  216. /// @code
  217. /// setDataField(StringTable->insert("locked", false), NULL, b ? "true" : "false" );
  218. /// curObject->setDataField(curField, curFieldArray, STR.getStringValue());
  219. /// setDataField(slotName, array, value);
  220. /// @endcode
  221. ///
  222. /// <i>For advanced users:</i> There are two flags which control the behavior
  223. /// of these functions. The first is ModStaticFields, which controls whether
  224. /// or not the DataField functions look through the static fields (defined
  225. /// with addField; see ConsoleObject for details) of the class. The second
  226. /// is ModDynamicFields, which controls dynamically defined fields. They are
  227. /// set automatically by the console constructor code.
  228. ///
  229. /// @nosubgrouping
  230. class SimObject: public ConsoleObject, public TamlCallbacks
  231. {
  232. public:
  233. typedef ConsoleObject Parent;
  234. friend class SimManager;
  235. friend class SimGroup;
  236. friend class SimNameDictionary;
  237. friend class SimManagerNameDictionary;
  238. friend class SimIdDictionary;
  239. /// @name Notification
  240. /// @{
  241. struct Notify
  242. {
  243. enum Type
  244. {
  245. ClearNotify, ///< Notified when the object is cleared.
  246. DeleteNotify, ///< Notified when the object is deleted.
  247. ObjectRef, ///< Cleverness to allow tracking of references.
  248. Invalid ///< Mark this notification as unused (used in freeNotify).
  249. } type;
  250. void *ptr; ///< Data (typically referencing or interested object).
  251. Notify *next; ///< Next notification in the linked list.
  252. };
  253. /// @}
  254. /// Flags passed to SimObject::write
  255. enum WriteFlags
  256. {
  257. SelectedOnly = BIT( 0 ), ///< Indicates that only objects marked as selected should be outputted. Used in SimSet.
  258. NoName = BIT( 1 ), ///< Indicates that the object name should not be saved.
  259. IgnoreCanSave = BIT( 2 ), ///< Write out even if CannotSave=true.
  260. };
  261. private:
  262. /// Flags for use in mFlags
  263. enum
  264. {
  265. Deleted = BIT( 0 ), ///< This object is marked for deletion.
  266. Removed = BIT( 1 ), ///< This object has been unregistered from the object system.
  267. Added = BIT( 3 ), ///< This object has been registered with the object system.
  268. Selected = BIT( 4 ), ///< This object has been marked as selected. (in editor)
  269. Expanded = BIT( 5 ), ///< This object has been marked as expanded. (in editor)
  270. ModStaticFields = BIT( 6 ), ///< The object allows you to read/modify static fields
  271. ModDynamicFields = BIT( 7 ), ///< The object allows you to read/modify dynamic fields
  272. AutoDelete = BIT( 8 ), ///< Delete this object when the last ObjectRef is gone.
  273. CannotSave = BIT( 9 ), ///< Object should not be saved.
  274. EditorOnly = BIT( 10 ), ///< This object is for use by the editor only.
  275. NoNameChange = BIT( 11 ), ///< Whether changing the name of this object is allowed.
  276. Hidden = BIT( 12 ), ///< Object is hidden in editors.
  277. Locked = BIT( 13 ), ///< Object is locked in editors.
  278. };
  279. // dictionary information stored on the object
  280. StringTableEntry mObjectName;
  281. StringTableEntry mOriginalName;
  282. SimObject* nextNameObject;
  283. SimObject* nextManagerNameObject;
  284. SimObject* nextIdObject;
  285. /// SimGroup we're contained in, if any.
  286. SimGroup* mGroup;
  287. /// Flags internal to the object management system.
  288. BitSet32 mFlags;
  289. StringTableEntry mProgenitorFile;
  290. /// Object we are copying fields from.
  291. SimObject* mCopySource;
  292. /// Table of dynamic fields assigned to this object.
  293. SimFieldDictionary *mFieldDictionary;
  294. /// Buffer to store textual representation of this object's numeric ID in.
  295. char mIdString[ 11 ];
  296. /// @name Serialization
  297. /// @{
  298. /// Path to file this SimObject was loaded from.
  299. StringTableEntry mFilename;
  300. /// The line number that the object was declared on if it was loaded from a file.
  301. S32 mDeclarationLine;
  302. /// @}
  303. /// @name Notification
  304. /// @{
  305. /// List of notifications added to this object.
  306. Notify* mNotifyList;
  307. static SimObject::Notify *mNotifyFreeList;
  308. static SimObject::Notify *allocNotify(); ///< Get a free Notify structure.
  309. static void freeNotify(SimObject::Notify*); ///< Mark a Notify structure as free.
  310. /// @}
  311. static bool _setCanSave( void* object, const char* index, const char* data );
  312. static const char* _getCanSave( void* object, const char* data );
  313. static const char* _getHidden( void* object, const char* data )
  314. { if( static_cast< SimObject* >( object )->isHidden() ) return "1"; return "0"; }
  315. static const char* _getLocked( void* object, const char* data )
  316. { if( static_cast< SimObject* >( object )->isLocked() ) return "1"; return "0"; }
  317. static bool _setHidden( void* object, const char* index, const char* data )
  318. { static_cast< SimObject* >( object )->setHidden( dAtob( data ) ); return false; }
  319. static bool _setLocked( void* object, const char* index, const char* data )
  320. { static_cast< SimObject* >( object )->setLocked( dAtob( data ) ); return false; }
  321. // Namespace protected set methods
  322. static bool setClass( void *object, const char *index, const char *data )
  323. { static_cast<SimObject*>(object)->setClassNamespace(data); return false; };
  324. static bool setSuperClass(void *object, const char *index, const char *data)
  325. { static_cast<SimObject*>(object)->setSuperClassNamespace(data); return false; };
  326. static bool writeObjectName(void* obj, StringTableEntry pFieldName)
  327. { SimObject* simObject = static_cast<SimObject*>(obj); return simObject->mObjectName != NULL && simObject->mObjectName != StringTable->EmptyString(); }
  328. static bool writeCanSaveDynamicFields(void* obj, StringTableEntry pFieldName)
  329. { return static_cast<SimObject*>(obj)->mCanSaveFieldDictionary == false; }
  330. static bool writeInternalName(void* obj, StringTableEntry pFieldName)
  331. { SimObject* simObject = static_cast<SimObject*>(obj); return simObject->mInternalName != NULL && simObject->mInternalName != StringTable->EmptyString(); }
  332. static bool setParentGroup(void* obj, const char* data);
  333. static bool writeParentGroup(void* obj, StringTableEntry pFieldName)
  334. { return static_cast<SimObject*>(obj)->mGroup != NULL; }
  335. static bool writeSuperclass(void* obj, StringTableEntry pFieldName)
  336. { SimObject* simObject = static_cast<SimObject*>(obj); return simObject->mSuperClassName != NULL && simObject->mSuperClassName != StringTable->EmptyString(); }
  337. static bool writeClass(void* obj, StringTableEntry pFieldName)
  338. { SimObject* simObject = static_cast<SimObject*>(obj); return simObject->mClassName != NULL && simObject->mClassName != StringTable->EmptyString(); }
  339. static bool writeClassName(void* obj, StringTableEntry pFieldName)
  340. { SimObject* simObject = static_cast<SimObject*>(obj); return simObject->mClassName != NULL && simObject->mClassName != StringTable->EmptyString(); }
  341. // Group hierarchy protected set method
  342. static bool setProtectedParent(void *object, const char *index, const char *data);
  343. // Object name protected set method
  344. static bool setProtectedName(void *object, const char *index, const char *data);
  345. public:
  346. inline void setProgenitorFile(const char* pFile) { mProgenitorFile = StringTable->insert(pFile); }
  347. inline StringTableEntry getProgenitorFile(void) const { return mProgenitorFile; }
  348. protected:
  349. /// Taml callbacks.
  350. virtual void onTamlPreWrite(void) {}
  351. virtual void onTamlPostWrite(void) {}
  352. virtual void onTamlPreRead(void) {}
  353. virtual void onTamlPostRead(const TamlCustomNodes& customNodes) {}
  354. virtual void onTamlAddParent(SimObject* pParentObject) {}
  355. virtual void onTamlCustomWrite(TamlCustomNodes& customNodes) {}
  356. virtual void onTamlCustomRead(const TamlCustomNodes& customNodes);
  357. /// Id number for this object.
  358. SimObjectId mId;
  359. /// Internal name assigned to the object. Not set by default.
  360. StringTableEntry mInternalName;
  361. static bool smForceId; ///< Force a registered object to use the given Id. Cleared upon use.
  362. static SimObjectId smForcedId; ///< The Id to force upon the object. Poor object.
  363. /// @name Serialization
  364. /// @{
  365. /// Whether dynamic fields should be saved out in serialization. Defaults to true.
  366. bool mCanSaveFieldDictionary;
  367. /// @}
  368. /// @name Persistent IDs
  369. /// @{
  370. /// Persistent ID assigned to this object. Allows to unambiguously refer to this
  371. /// object in serializations regardless of stream object ordering.
  372. SimPersistID* mPersistentId;
  373. static bool _setPersistentID( void* object, const char* index, const char* data );
  374. /// @}
  375. /// @name Namespace management
  376. /// @{
  377. /// The namespace in which method lookup for this object begins.
  378. Namespace* mNameSpace;
  379. /// Name of namespace to use as class namespace.
  380. StringTableEntry mClassName;
  381. /// Name of namespace to use as class super namespace.
  382. StringTableEntry mSuperClassName;
  383. /// Perform namespace linking on this object.
  384. void linkNamespaces();
  385. /// Undo namespace linking on this object.
  386. void unlinkNamespaces();
  387. /// @}
  388. /// Called when the object is selected in the editor.
  389. virtual void _onSelected() {}
  390. /// Called when the object is unselected in the editor.
  391. virtual void _onUnselected() {}
  392. /// We can provide more detail, like object name and id.
  393. virtual String _getLogMessage(const char* fmt, va_list args) const;
  394. DEFINE_CREATE_METHOD
  395. {
  396. T* object = new T;
  397. object->incRefCount();
  398. object->registerObject();
  399. return object;
  400. }
  401. // EngineObject.
  402. virtual void _destroySelf();
  403. public:
  404. /// @name Cloning
  405. /// @{
  406. /// Return a shallow copy of this object.
  407. virtual SimObject* clone();
  408. /// Return a deep copy of this object.
  409. virtual SimObject* deepClone();
  410. /// @}
  411. /// @name Accessors
  412. /// @{
  413. /// Get the value of a field on the object.
  414. ///
  415. /// See @ref simobject_console "here" for a detailed discussion of what this
  416. /// function does.
  417. ///
  418. /// @param slotName Field to access.
  419. /// @param array String containing index into array
  420. /// (if field is an array); if NULL, it is ignored.
  421. const char *getDataField(StringTableEntry slotName, const char *array);
  422. /// Set the value of a field on the object.
  423. ///
  424. /// See @ref simobject_console "here" for a detailed discussion of what this
  425. /// function does.
  426. ///
  427. /// @param slotName Field to access.
  428. /// @param array String containing index into array; if NULL, it is ignored.
  429. /// @param value Value to store.
  430. void setDataField(StringTableEntry slotName, const char *array, const char *value);
  431. const char *getPrefixedDataField(StringTableEntry fieldName, const char *array);
  432. void setPrefixedDataField(StringTableEntry fieldName, const char *array, const char *value);
  433. const char *getPrefixedDynamicDataField(StringTableEntry fieldName, const char *array, const S32 fieldType = -1);
  434. void setPrefixedDynamicDataField(StringTableEntry fieldName, const char *array, const char *value, const S32 fieldType = -1);
  435. StringTableEntry getDataFieldPrefix(StringTableEntry fieldName);
  436. /// Get the type of a field on the object.
  437. ///
  438. /// @param slotName Field to access.
  439. /// @param array String containing index into array
  440. /// (if field is an array); if NULL, it is ignored.
  441. U32 getDataFieldType(StringTableEntry slotName, const char *array);
  442. /// Set the type of a *dynamic* field on the object.
  443. ///
  444. /// @param typeName/Id Console base type name/id to assign to a dynamic field.
  445. /// @param slotName Field to access.
  446. /// @param array String containing index into array
  447. /// (if field is an array); if NULL, it is ignored.
  448. void setDataFieldType(const U32 fieldTypeId, StringTableEntry slotName, const char *array);
  449. void setDataFieldType(const char *typeName, StringTableEntry slotName, const char *array);
  450. /// Get reference to the dictionary containing dynamic fields.
  451. ///
  452. /// See @ref simobject_console "here" for a detailed discussion of what this
  453. /// function does.
  454. ///
  455. /// This dictionary can be iterated over using a SimFieldDictionaryIterator.
  456. SimFieldDictionary * getFieldDictionary() {return(mFieldDictionary);}
  457. // Component Information
  458. inline virtual StringTableEntry getComponentName() { return StringTable->insert( getClassName() ); };
  459. /// These functions support internal naming that is not namespace
  460. /// bound for locating child controls in a generic way.
  461. ///
  462. /// Set the internal name of this control (Not linked to a namespace)
  463. void setInternalName(const char* newname);
  464. /// Get the internal name of this control
  465. StringTableEntry getInternalName() const { return mInternalName; }
  466. /// Set the original name of this control
  467. void setOriginalName(const char* originalName);
  468. /// Get the original name of this control
  469. StringTableEntry getOriginalName() const { return mOriginalName; }
  470. /// These functions allow you to set and access the filename
  471. /// where this object was created.
  472. ///
  473. /// Set the filename
  474. void setFilename(const char* file);
  475. /// Get the filename
  476. StringTableEntry getFilename() const { return mFilename; }
  477. /// These functions are used to track the line number (1-based)
  478. /// on which the object was created if it was loaded from script
  479. ///
  480. /// Set the declaration line number
  481. void setDeclarationLine(U32 lineNumber);
  482. /// Get the declaration line number
  483. S32 getDeclarationLine() const { return mDeclarationLine; }
  484. /// Save object as a TorqueScript File.
  485. virtual bool save( const char* pcFilePath, bool bOnlySelected = false, const char *preappend = NULL );
  486. /// Check if a method exists in the objects current namespace.
  487. virtual bool isMethod( const char* methodName );
  488. /// Return true if the field is defined on the object
  489. virtual bool isField( const char* fieldName, bool includeStatic = true, bool includeDynamic = true );
  490. /// @}
  491. /// @name Initialization
  492. /// @{
  493. ///
  494. SimObject();
  495. virtual ~SimObject();
  496. virtual bool processArguments(S32 argc, ConsoleValueRef *argv); ///< Process constructor options. (ie, new SimObject(1,2,3))
  497. /// @}
  498. /// @name Events
  499. /// @{
  500. /// Called when the object is added to the sim.
  501. virtual bool onAdd();
  502. /// Called when the object is removed from the sim.
  503. virtual void onRemove();
  504. /// Called when the object is added to a SimGroup.
  505. virtual void onGroupAdd();
  506. /// Called when the object is removed from a SimGroup.
  507. virtual void onGroupRemove();
  508. /// Called when the object's name is changed.
  509. virtual void onNameChange(const char *name);
  510. /// Called when the adding of the object to the sim is complete, all sub-objects have been processed as well
  511. // This is a special-case function that only really gets used with Entities/BehaviorObjects.
  512. virtual void onPostAdd() {}
  513. ///
  514. /// Specifically, these are called by setDataField
  515. /// when a static or dynamic field is modified, see
  516. /// @ref simobject_console "the console details".
  517. virtual void onStaticModified(const char* slotName, const char*newValue = NULL); ///< Called when a static field is modified.
  518. virtual void onDynamicModified(const char* slotName, const char*newValue = NULL); ///< Called when a dynamic field is modified.
  519. /// Called before any property of the object is changed in the world editor.
  520. ///
  521. /// The calling order here is:
  522. /// - inspectPreApply()
  523. /// - ...
  524. /// - calls to setDataField()
  525. /// - ...
  526. /// - inspectPostApply()
  527. virtual void inspectPreApply();
  528. /// Called after any property of the object is changed in the world editor.
  529. ///
  530. /// @see inspectPreApply
  531. virtual void inspectPostApply();
  532. /// Called when a SimObject is deleted.
  533. ///
  534. /// When you are on the notification list for another object
  535. /// and it is deleted, this method is called.
  536. virtual void onDeleteNotify(SimObject *object);
  537. /// Called when the editor is activated.
  538. virtual void onEditorEnable(){};
  539. /// Called when the editor is deactivated.
  540. virtual void onEditorDisable(){};
  541. /// @}
  542. /// Find a named sub-object of this object.
  543. ///
  544. /// This is subclassed in the SimGroup and SimSet classes.
  545. ///
  546. /// For a single object, it just returns NULL, as normal objects cannot have children.
  547. virtual SimObject *findObject(const char *name);
  548. /// @name Notification
  549. /// @{
  550. Notify *removeNotify(void *ptr, Notify::Type); ///< Remove a notification from the list.
  551. void deleteNotify(SimObject* obj); ///< Notify an object when we are deleted.
  552. void clearNotify(SimObject* obj); ///< Notify an object when we are cleared.
  553. void clearAllNotifications(); ///< Remove all notifications for this object.
  554. void processDeleteNotifies(); ///< Send out deletion notifications.
  555. /// Register a reference to this object.
  556. ///
  557. /// You pass a pointer to your reference to this object.
  558. ///
  559. /// When the object is deleted, it will null your
  560. /// pointer, ensuring you don't access old memory.
  561. ///
  562. /// @param obj Pointer to your reference to the object.
  563. void registerReference(SimObject **obj);
  564. /// Unregister a reference to this object.
  565. ///
  566. /// Remove a reference from the list, so that it won't
  567. /// get nulled inappropriately.
  568. ///
  569. /// Call this when you're done with your reference to
  570. /// the object, especially if you're going to free the
  571. /// memory. Otherwise, you may erroneously get something
  572. /// overwritten.
  573. ///
  574. /// @see registerReference
  575. void unregisterReference(SimObject **obj);
  576. /// @}
  577. /// @name Registration
  578. ///
  579. /// SimObjects must be registered with the object system.
  580. /// @{
  581. /// Register an object with the object system.
  582. ///
  583. /// This must be called if you want to keep the object around.
  584. /// In the rare case that you will delete the object immediately, or
  585. /// don't want to be able to use Sim::findObject to locate it, then
  586. /// you don't need to register it.
  587. ///
  588. /// registerObject adds the object to the global ID and name dictionaries,
  589. /// after first assigning it a new ID number. It calls onAdd(). If onAdd fails,
  590. /// it unregisters the object and returns false.
  591. ///
  592. /// If a subclass's onAdd doesn't eventually call SimObject::onAdd(), it will
  593. /// cause an assertion.
  594. bool registerObject();
  595. /// Register the object, forcing the id.
  596. ///
  597. /// @see registerObject()
  598. /// @param id ID to assign to the object.
  599. bool registerObject(U32 id);
  600. /// Register the object, assigning the name.
  601. ///
  602. /// @see registerObject()
  603. /// @param name Name to assign to the object.
  604. bool registerObject(const char *name);
  605. /// Register the object, assigning a name and ID.
  606. ///
  607. /// @see registerObject()
  608. /// @param name Name to assign to the object.
  609. /// @param id ID to assign to the object.
  610. bool registerObject(const char *name, U32 id);
  611. /// Unregister the object from Sim.
  612. ///
  613. /// This performs several operations:
  614. /// - Sets the removed flag.
  615. /// - Call onRemove()
  616. /// - Clear out notifications.
  617. /// - Remove the object from...
  618. /// - its group, if any. (via getGroup)
  619. /// - Sim::gNameDictionary
  620. /// - Sim::gIDDictionary
  621. /// - Finally, cancel any pending events for this object (as it can't receive them now).
  622. void unregisterObject();
  623. /// Unregister, mark as deleted, and free the object.
  624. virtual void deleteObject();
  625. /// Performs a safe delayed delete of the object using a sim event.
  626. void safeDeleteObject();
  627. /// @}
  628. /// @name Accessors
  629. /// @{
  630. /// Return the unique numeric object ID.
  631. SimObjectId getId() const { return mId; }
  632. /// Return the object ID as a string.
  633. const char* getIdString() const { return mIdString; }
  634. /// Return the name of this object.
  635. StringTableEntry getName() const { return mObjectName; }
  636. /// Return the SimGroup that this object is contained in. Never NULL except for
  637. /// RootGroup and unregistered objects.
  638. SimGroup* getGroup() const { return mGroup; }
  639. /// Assign the given name to this object.
  640. void assignName( const char* name );
  641. void setId(SimObjectId id);
  642. static void setForcedId(SimObjectId id) { smForceId = true; smForcedId = id; } ///< Force an Id on the next registered object.
  643. bool isChildOfGroup(SimGroup* pGroup);
  644. bool isProperlyAdded() const { return mFlags.test(Added); }
  645. bool isDeleted() const { return mFlags.test(Deleted); }
  646. bool isRemoved() const { return mFlags.test(Deleted | Removed); }
  647. virtual bool isLocked() const { return mFlags.test( Locked ); }
  648. virtual void setLocked( bool b );
  649. virtual bool isHidden() const { return mFlags.test( Hidden ); }
  650. virtual void setHidden(bool b);
  651. /// @}
  652. /// @name Sets
  653. ///
  654. /// The object must be properly registered before you can add/remove it to/from a set.
  655. ///
  656. /// All these functions accept either a name or ID to identify the set you wish
  657. /// to operate on. Then they call addObject or removeObject on the set, which
  658. /// sets up appropriate notifications.
  659. ///
  660. /// An object may be in multiple sets at a time.
  661. /// @{
  662. bool addToSet(SimObjectId);
  663. bool addToSet(const char *);
  664. bool removeFromSet(SimObjectId);
  665. bool removeFromSet(const char *);
  666. /// @}
  667. /// @name Serialization
  668. /// @{
  669. /// Determine whether or not a field should be written.
  670. ///
  671. /// @param fiedname The name of the field being written.
  672. /// @param value The value of the field.
  673. virtual bool writeField(StringTableEntry fieldname, const char* value);
  674. /// Output the TorqueScript to recreate this object.
  675. ///
  676. /// This calls writeFields internally.
  677. /// @param stream Stream to output to.
  678. /// @param tabStop Indentation level for this object.
  679. /// @param flags If SelectedOnly is passed here, then
  680. /// only objects marked as selected (using setSelected)
  681. /// will output themselves.
  682. virtual void write(Stream &stream, U32 tabStop, U32 flags = 0);
  683. /// Write the fields of this object in TorqueScript.
  684. ///
  685. /// @param stream Stream for output.
  686. /// @param tabStop Indentation level for the fields.
  687. virtual void writeFields(Stream &stream, U32 tabStop);
  688. virtual bool writeObject(Stream *stream);
  689. virtual bool readObject(Stream *stream);
  690. /// Set whether fields created at runtime should be saved. Default is true.
  691. void setCanSaveDynamicFields( bool bCanSave ) { mCanSaveFieldDictionary = bCanSave; }
  692. /// Get whether fields created at runtime should be saved. Default is true.
  693. bool getCanSaveDynamicFields( ) { return mCanSaveFieldDictionary;}
  694. /// Return the object that this object is copying fields from.
  695. SimObject* getCopySource() const { return mCopySource; }
  696. /// Set the object that this object should be copying fields from.
  697. void setCopySource( SimObject* object );
  698. /// Copy fields from another object onto this one.
  699. ///
  700. /// Objects must be of same type. Everything from obj
  701. /// will overwrite what's in this object; extra fields
  702. /// in this object will remain. This includes dynamic
  703. /// fields.
  704. ///
  705. /// @param obj Object to copy from.
  706. void assignFieldsFrom(SimObject *obj);
  707. /// Copy dynamic fields from another object onto this one.
  708. ///
  709. /// Everything from obj will overwrite what's in this
  710. /// object.
  711. ///
  712. /// @param obj Object to copy from.
  713. void assignDynamicFieldsFrom(SimObject *obj);
  714. /// @}
  715. /// Return the object's namespace.
  716. Namespace* getNamespace() { return mNameSpace; }
  717. /// Get next matching item in namespace.
  718. ///
  719. /// This wraps a call to Namespace::tabComplete; it gets the
  720. /// next thing in the namespace, given a starting value
  721. /// and a base length of the string. See
  722. /// Namespace::tabComplete for details.
  723. const char *tabComplete(const char *prevText, S32 baseLen, bool);
  724. /// @name Accessors
  725. /// @{
  726. bool isSelected() const { return mFlags.test(Selected); }
  727. bool isExpanded() const { return mFlags.test(Expanded); }
  728. bool isEditorOnly() const { return mFlags.test( EditorOnly ); }
  729. bool isNameChangeAllowed() const { return !mFlags.test( NoNameChange ); }
  730. bool isAutoDeleted() const { return mFlags.test( AutoDelete ); }
  731. void setSelected(bool sel);
  732. void setExpanded(bool exp) { if(exp) mFlags.set(Expanded); else mFlags.clear(Expanded); }
  733. void setModDynamicFields(bool dyn) { if(dyn) mFlags.set(ModDynamicFields); else mFlags.clear(ModDynamicFields); }
  734. void setModStaticFields(bool sta) { if(sta) mFlags.set(ModStaticFields); else mFlags.clear(ModStaticFields); }
  735. bool canModDynamicFields() { return mFlags.test(ModDynamicFields); }
  736. bool canModStaticFields() { return mFlags.test(ModStaticFields); }
  737. void setAutoDelete( bool val ) { if( val ) mFlags.set( AutoDelete ); else mFlags.clear( AutoDelete ); }
  738. void setEditorOnly( bool val ) { if( val ) mFlags.set( EditorOnly ); else mFlags.clear( EditorOnly ); }
  739. void setNameChangeAllowed( bool val ) { if( val ) mFlags.clear( NoNameChange ); else mFlags.set( NoNameChange ); }
  740. /// Returns boolean specifying if the object can be serialized.
  741. bool getCanSave() const { return !mFlags.test( CannotSave ); }
  742. /// Set serialization flag.
  743. virtual void setCanSave( bool val ) { if( !val ) mFlags.set( CannotSave ); else mFlags.clear( CannotSave ); }
  744. /// Returns true if this object is selected or any group it is a member of is.
  745. bool isSelectedRecursive() const;
  746. /// @}
  747. /// @name Namespace management
  748. /// @{
  749. /// Return name of class namespace set on this object.
  750. StringTableEntry getClassNamespace() const { return mClassName; };
  751. /// Return name of superclass namespace set on this object.
  752. StringTableEntry getSuperClassNamespace() const { return mSuperClassName; };
  753. ///
  754. void setClassNamespace( const char* classNamespace );
  755. ///
  756. void setSuperClassNamespace( const char* superClassNamespace );
  757. /// @}
  758. /// @name Persistent IDs
  759. /// @{
  760. /// Return the persistent ID assigned to this object or NULL.
  761. SimPersistID* getPersistentId() const { return mPersistentId; }
  762. /// Return the persistent ID assigned to this object or assign one to it if it has none.
  763. SimPersistID* getOrCreatePersistentId();
  764. /// @}
  765. /// @name Debugging
  766. /// @{
  767. /// Return a textual description of the object.
  768. virtual String describeSelf() const;
  769. /// Dump the contents of this object to the console. Use the Torque Script dump() and dumpF() functions to
  770. /// call this.
  771. void dumpToConsole( bool includeFunctions=true );
  772. ///added this so that you can print the entire class hierarchy, including script objects,
  773. //from the console or C++.
  774. /// Print the AbstractClassRep hierarchy of this object to the console.
  775. virtual void dumpClassHierarchy();
  776. /// Print the SimGroup hierarchy of this object to the console.
  777. virtual void dumpGroupHierarchy();
  778. /// @}
  779. static void initPersistFields();
  780. /// Copy SimObject to another SimObject (Originally designed for T2D).
  781. virtual void copyTo(SimObject* object);
  782. // Component Console Overrides
  783. virtual bool handlesConsoleMethod(const char * fname, S32 * routingId) { return false; }
  784. virtual void getConsoleMethodData(const char * fname, S32 routingId, S32 * type, S32 * minArgs, S32 * maxArgs, void ** callback, const char ** usage) {}
  785. DECLARE_CONOBJECT( SimObject );
  786. static SimObject* __findObject( const char* id ) { return Sim::findObject( id ); }
  787. static const char* __getObjectId( ConsoleObject* object )
  788. {
  789. SimObject* simObject = static_cast< SimObject* >( object );
  790. if( !simObject )
  791. return "";
  792. else if( simObject->getName() )
  793. return simObject->getName();
  794. return simObject->getIdString();
  795. }
  796. // EngineObject.
  797. virtual void destroySelf();
  798. protected:
  799. bool is_temp_clone;
  800. public:
  801. /*C*/ SimObject(const SimObject&, bool = false);
  802. bool isTempClone() const { return is_temp_clone; }
  803. virtual bool allowSubstitutions() const { return false; }
  804. public:
  805. static bool preventNameChanging;
  806. void assignDynamicFieldsFrom(SimObject*, const char* filter, bool no_replace=false);
  807. public:
  808. virtual void reloadReset() { }
  809. };
  810. /// Smart SimObject pointer.
  811. ///
  812. /// This class keeps track of the book-keeping necessary
  813. /// to keep a registered reference to a SimObject or subclass
  814. /// thereof.
  815. ///
  816. /// Normally, if you want the SimObject to be aware that you
  817. /// have a reference to it, you must call SimObject::registerReference()
  818. /// when you create the reference, and SimObject::unregisterReference() when
  819. /// you're done. If you change the reference, you must also register/unregister
  820. /// it. This is a big headache, so this class exists to automatically
  821. /// keep track of things for you.
  822. ///
  823. /// @code
  824. /// // Assign an object to the
  825. /// SimObjectPtr<GameBase> mOrbitObject = Sim::findObject("anObject");
  826. ///
  827. /// // Use it as a GameBase*.
  828. /// mOrbitObject->getWorldBox().getCenter(&mPosition);
  829. ///
  830. /// // And reassign it - it will automatically update the references.
  831. /// mOrbitObject = Sim::findObject("anotherObject");
  832. /// @endcode
  833. template< typename T >
  834. class SimObjectPtr : public WeakRefPtr< T >
  835. {
  836. public:
  837. typedef WeakRefPtr< T > Parent;
  838. SimObjectPtr() {}
  839. SimObjectPtr(T *ptr) { this->mReference = NULL; set(ptr); }
  840. SimObjectPtr( const SimObjectPtr& ref ) { this->mReference = NULL; set(ref.mReference); }
  841. T* getObject() const { return Parent::getPointer(); }
  842. ~SimObjectPtr() { set((WeakRefBase::WeakReference*)NULL); }
  843. SimObjectPtr<T>& operator=(const SimObjectPtr ref)
  844. {
  845. set(ref.mReference);
  846. return *this;
  847. }
  848. SimObjectPtr<T>& operator=(T *ptr)
  849. {
  850. set(ptr);
  851. return *this;
  852. }
  853. protected:
  854. void set(WeakRefBase::WeakReference * ref)
  855. {
  856. if( ref == this->mReference )
  857. return;
  858. if( this->mReference )
  859. {
  860. // Auto-delete
  861. T* obj = this->getPointer();
  862. if ( this->mReference->getRefCount() == 2 && obj && obj->isAutoDeleted() )
  863. obj->deleteObject();
  864. this->mReference->decRefCount();
  865. }
  866. this->mReference = NULL;
  867. if( ref )
  868. {
  869. this->mReference = ref;
  870. this->mReference->incRefCount();
  871. }
  872. }
  873. void set(T * obj)
  874. {
  875. set(obj ? obj->getWeakReference() : (WeakRefBase::WeakReference *)NULL);
  876. }
  877. };
  878. #endif // _SIMOBJECT_H_