missionMarker.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657
  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. #include "T3D/missionMarker.h"
  23. #include "console/consoleTypes.h"
  24. #include "core/color.h"
  25. #include "console/engineAPI.h"
  26. extern bool gEditingMission;
  27. IMPLEMENT_CO_DATABLOCK_V1(MissionMarkerData);
  28. ConsoleDocClass( MissionMarkerData,
  29. "@brief A very basic class containing information used by MissionMarker objects for rendering\n\n"
  30. "MissionMarkerData, is an extremely barebones class derived from ShapeBaseData. It is solely used by "
  31. "MissionMarker classes (such as SpawnSphere), so that you can see the object while editing a level.\n\n"
  32. "@tsexample\n"
  33. "datablock MissionMarkerData(SpawnSphereMarker)\n"
  34. "{\n"
  35. " category = \"Misc\";\n"
  36. " shapeFile = \"core/art/shapes/octahedron.dts\";\n"
  37. "};\n"
  38. "@endtsexample\n\n"
  39. "@see MissionMarker\n\n"
  40. "@see SpawnSphere\n\n"
  41. "@see WayPoint\n\n"
  42. "@ingroup enviroMisc\n"
  43. );
  44. //------------------------------------------------------------------------------
  45. // Class: MissionMarker
  46. //------------------------------------------------------------------------------
  47. IMPLEMENT_CO_NETOBJECT_V1(MissionMarker);
  48. ConsoleDocClass( MissionMarker,
  49. "@brief This is a base class for all \"marker\" related objets. It is a 3D representation of a point in the level.\n\n"
  50. "The main use of a MissionMarker is to represent a point in 3D space with a mesh and basic ShapeBase information. "
  51. "If you simply need to mark a spot in your level, with no overhead from additional fields, this is a useful object.\n\n"
  52. "@tsexample\n"
  53. "new MissionMarker()\n"
  54. "{\n"
  55. " dataBlock = \"WayPointMarker\";\n"
  56. " position = \"295.699 -171.817 280.124\";\n"
  57. " rotation = \"0 0 -1 13.8204\";\n"
  58. " scale = \"1 1 1\";\n"
  59. " isRenderEnabled = \"true\";\n"
  60. " canSaveDynamicFields = \"1\";\n"
  61. " enabled = \"1\";\n"
  62. "};\n"
  63. "@endtsexample\n\n"
  64. "@note MissionMarkers will not add themselves to the scene except when in the editor.\n\n"
  65. "@see MissionMarkerData\n\n"
  66. "@see SpawnSphere\n\n"
  67. "@see WayPoint\n\n"
  68. "@ingroup enviroMisc\n"
  69. );
  70. MissionMarker::MissionMarker()
  71. {
  72. mTypeMask |= StaticObjectType;
  73. mDataBlock = 0;
  74. mAddedToScene = false;
  75. mNetFlags.set(Ghostable | ScopeAlways);
  76. }
  77. bool MissionMarker::onAdd()
  78. {
  79. if(!Parent::onAdd() || !mDataBlock)
  80. return(false);
  81. if(gEditingMission)
  82. {
  83. addToScene();
  84. mAddedToScene = true;
  85. }
  86. return(true);
  87. }
  88. void MissionMarker::onRemove()
  89. {
  90. if( mAddedToScene )
  91. {
  92. removeFromScene();
  93. mAddedToScene = false;
  94. }
  95. Parent::onRemove();
  96. }
  97. void MissionMarker::inspectPostApply()
  98. {
  99. Parent::inspectPostApply();
  100. setMaskBits(PositionMask);
  101. }
  102. void MissionMarker::onEditorEnable()
  103. {
  104. if(!mAddedToScene)
  105. {
  106. addToScene();
  107. mAddedToScene = true;
  108. }
  109. }
  110. void MissionMarker::onEditorDisable()
  111. {
  112. if(mAddedToScene)
  113. {
  114. removeFromScene();
  115. mAddedToScene = false;
  116. }
  117. }
  118. bool MissionMarker::onNewDataBlock( GameBaseData *dptr, bool reload )
  119. {
  120. mDataBlock = dynamic_cast<MissionMarkerData*>( dptr );
  121. if ( !mDataBlock || !Parent::onNewDataBlock( dptr, reload ) )
  122. return(false);
  123. scriptOnNewDataBlock();
  124. return(true);
  125. }
  126. void MissionMarker::setTransform(const MatrixF& mat)
  127. {
  128. Parent::setTransform(mat);
  129. setMaskBits(PositionMask);
  130. }
  131. U32 MissionMarker::packUpdate(NetConnection * con, U32 mask, BitStream * stream)
  132. {
  133. U32 retMask = Parent::packUpdate(con, mask, stream);
  134. if(stream->writeFlag(mask & PositionMask))
  135. {
  136. stream->writeAffineTransform(mObjToWorld);
  137. mathWrite(*stream, mObjScale);
  138. }
  139. return(retMask);
  140. }
  141. void MissionMarker::unpackUpdate(NetConnection * con, BitStream * stream)
  142. {
  143. Parent::unpackUpdate(con, stream);
  144. if(stream->readFlag())
  145. {
  146. MatrixF mat;
  147. stream->readAffineTransform(&mat);
  148. Parent::setTransform(mat);
  149. Point3F scale;
  150. mathRead(*stream, &scale);
  151. setScale(scale);
  152. }
  153. }
  154. void MissionMarker::initPersistFields() {
  155. Parent::initPersistFields();
  156. }
  157. //------------------------------------------------------------------------------
  158. // Class: WayPoint
  159. //------------------------------------------------------------------------------
  160. IMPLEMENT_CO_NETOBJECT_V1(WayPoint);
  161. ConsoleDocClass( WayPoint,
  162. "@brief Special type of marker, distinguished by a name and team ID number\n\n"
  163. "The original Torque engines were built from a multi-player game called Tribes. "
  164. "The Tribes series featured various team based game modes, such as capture the flag. "
  165. "The WayPoint class survived the conversion from game (Tribes) to game engine (Torque).\n\n"
  166. "Essentially, this is a MissionMarker with the addition of two variables: markerName and team. "
  167. "Whenever a WayPoint is created, it is added to a unique global list called WayPointSet. "
  168. "You can iterate through this set, seeking out specific markers determined by their markerName and team ID. "
  169. "This avoids the overhead of constantly calling commandToClient and commandToServer to determine "
  170. "a WayPoint object's name, unique ID, etc.\n\n"
  171. "@note The <i>markerName<i> field was previously called <i>name</i>, but was changed "
  172. "because this conflicted with the SimObject name field. Existing scripts that relied "
  173. "on the WayPoint <i>name</i> field will need to be updated.\n\n"
  174. "@tsexample\n"
  175. "new WayPoint()\n"
  176. "{\n"
  177. " team = \"1\";\n"
  178. " dataBlock = \"WayPointMarker\";\n"
  179. " position = \"-0.0224786 1.53471 2.93219\";\n"
  180. " rotation = \"1 0 0 0\";\n"
  181. " scale = \"1 1 1\";\n"
  182. " canSave = \"1\";\n"
  183. " canSaveDynamicFields = \"1\";\n"
  184. "};\n"
  185. "@endtsexample\n\n"
  186. "@see MissionMarker\n\n"
  187. "@see MissionMarkerData\n\n"
  188. "@ingroup enviroMisc\n"
  189. );
  190. WayPointTeam::WayPointTeam()
  191. {
  192. mTeamId = 0;
  193. mWayPoint = 0;
  194. }
  195. WayPoint::WayPoint()
  196. {
  197. mName = StringTable->insert("");
  198. }
  199. void WayPoint::setHidden(bool hidden)
  200. {
  201. // Skip ShapeBase::setHidden (only ever added to scene if in the editor)
  202. ShapeBase::Parent::setHidden( hidden );
  203. if(isServerObject())
  204. setMaskBits(UpdateHiddenMask);
  205. }
  206. bool WayPoint::onAdd()
  207. {
  208. if(!Parent::onAdd())
  209. return(false);
  210. //
  211. if(isClientObject())
  212. Sim::getWayPointSet()->addObject(this);
  213. else
  214. {
  215. mTeam.mWayPoint = this;
  216. setMaskBits(UpdateNameMask|UpdateTeamMask);
  217. }
  218. return(true);
  219. }
  220. void WayPoint::inspectPostApply()
  221. {
  222. Parent::inspectPostApply();
  223. if(!mName || !mName[0])
  224. mName = StringTable->insert("");
  225. setMaskBits(UpdateNameMask|UpdateTeamMask);
  226. }
  227. U32 WayPoint::packUpdate(NetConnection * con, U32 mask, BitStream * stream)
  228. {
  229. U32 retMask = Parent::packUpdate(con, mask, stream);
  230. if(stream->writeFlag(mask & UpdateNameMask))
  231. stream->writeString(mName);
  232. if(stream->writeFlag(mask & UpdateTeamMask))
  233. stream->write(mTeam.mTeamId);
  234. if(stream->writeFlag(mask & UpdateHiddenMask))
  235. stream->writeFlag(isHidden());
  236. return(retMask);
  237. }
  238. void WayPoint::unpackUpdate(NetConnection * con, BitStream * stream)
  239. {
  240. Parent::unpackUpdate(con, stream);
  241. if(stream->readFlag())
  242. mName = stream->readSTString(true);
  243. if(stream->readFlag())
  244. stream->read(&mTeam.mTeamId);
  245. if(stream->readFlag())
  246. setHidden(stream->readFlag());
  247. }
  248. //-----------------------------------------------------------------------------
  249. // TypeWayPointTeam
  250. //-----------------------------------------------------------------------------
  251. IMPLEMENT_STRUCT( WayPointTeam, WayPointTeam,,
  252. "" )
  253. END_IMPLEMENT_STRUCT;
  254. //FIXME: this should work but does not; need to check the stripping down to base types within TYPE
  255. //ConsoleType( WayPointTeam, TypeWayPointTeam, WayPointTeam* )
  256. ConsoleType( WayPointTeam, TypeWayPointTeam, WayPointTeam )
  257. ConsoleGetType( TypeWayPointTeam )
  258. {
  259. static const U32 bufSize = 32;
  260. char * buf = Con::getReturnBuffer(bufSize);
  261. dSprintf(buf, bufSize, "%d", ((WayPointTeam*)dptr)->mTeamId);
  262. return(buf);
  263. }
  264. ConsoleSetType( TypeWayPointTeam )
  265. {
  266. WayPointTeam * pTeam = (WayPointTeam*)dptr;
  267. pTeam->mTeamId = dAtoi(argv[0]);
  268. if(pTeam->mWayPoint && pTeam->mWayPoint->isServerObject())
  269. pTeam->mWayPoint->setMaskBits(WayPoint::UpdateTeamMask);
  270. }
  271. void WayPoint::initPersistFields()
  272. {
  273. addGroup("Misc");
  274. addField("markerName", TypeCaseString, Offset(mName, WayPoint), "Unique name representing this waypoint");
  275. addField("team", TypeWayPointTeam, Offset(mTeam, WayPoint), "Unique numerical ID assigned to this waypoint, or set of waypoints");
  276. endGroup("Misc");
  277. Parent::initPersistFields();
  278. }
  279. //------------------------------------------------------------------------------
  280. // Class: SpawnSphere
  281. //------------------------------------------------------------------------------
  282. IMPLEMENT_CO_NETOBJECT_V1(SpawnSphere);
  283. ConsoleDocClass( SpawnSphere,
  284. "@brief This class is used for creating any type of game object, assigning it a class, datablock, and other "
  285. "properties when it is spawned.\n\n"
  286. "Torque 3D uses a simple spawn system, which can be easily modified to spawn any kind of object (of any class). "
  287. "Each new level already contains at least one SpawnSphere, which is represented by a green octahedron in stock Torque 3D. "
  288. "The spawnClass field determines the object type, such as Player, AIPlayer, etc. The spawnDataBlock field applies the "
  289. "pre-defined datablock to each spawned object instance. The really powerful feature of this class is provided by "
  290. "the spawnScript field which allows you to define a simple script (multiple lines) that will be executed once the "
  291. "object has been spawned.\n\n"
  292. "@tsexample\n"
  293. "// Define an SpawnSphere that essentially performs the following each time an object is spawned\n"
  294. "//$SpawnObject = new Player()\n"
  295. "//{\n"
  296. "// dataBlock = \"DefaultPlayerData\";\n"
  297. "// name = \"Bob\";\n"
  298. "// lifeTotal = 3;\n"
  299. "//};\n"
  300. "//echo(\"Spawned a Player: \" @ $SpawnObject);\n\n"
  301. "new SpawnSphere(DefaultSpawnSphere)\n"
  302. "{\n"
  303. " spawnClass = \"Player\";\n"
  304. " spawnDatablock = \"DefaultPlayerData\";\n"
  305. " spawnScript = \"echo(\\\"Spawned a Player: \\\" @ $SpawnObject);\"; // embedded quotes must be escaped with \\ \n"
  306. " spawnProperties = \"name = \\\"Bob\\\";lifeTotal = 3;\"; // embedded quotes must be escaped with \\ \n"
  307. " autoSpawn = \"1\";\n"
  308. " dataBlock = \"SpawnSphereMarker\";\n"
  309. " position = \"-0.77266 -19.882 17.8153\";\n"
  310. " rotation = \"1 0 0 0\";\n"
  311. " scale = \"1 1 1\";\n"
  312. " canSave = \"1\";\n"
  313. " canSaveDynamicFields = \"1\";\n"
  314. "};\n\n"
  315. "// Because autoSpawn is set to true in the above example, the following lines\n"
  316. "// of code will execute AFTER the Player object has been spawned.\n"
  317. "echo(\"Object Spawned\");\n"
  318. "echo(\"Hello World\");\n\n"
  319. "@endtsexample\n\n"
  320. "@see MissionMarker\n\n"
  321. "@see MissionMarkerData\n\n"
  322. "@ingroup gameObjects\n"
  323. "@ingroup enviroMisc\n"
  324. );
  325. SpawnSphere::SpawnSphere()
  326. {
  327. mAutoSpawn = false;
  328. mSpawnTransform = false;
  329. mRadius = 100.f;
  330. mSphereWeight = 100.f;
  331. mIndoorWeight = 100.f;
  332. mOutdoorWeight = 100.f;
  333. }
  334. IMPLEMENT_CALLBACK( SpawnSphere, onAdd, void, ( U32 objectId ), ( objectId ),
  335. "Called when the SpawnSphere is being created.\n"
  336. "@param objectId The unique SimObjectId generated when SpawnSphere is created (%%this in script)\n" );
  337. bool SpawnSphere::onAdd()
  338. {
  339. if(!Parent::onAdd())
  340. return(false);
  341. if(!isClientObject())
  342. setMaskBits(UpdateSphereMask);
  343. if (!isGhost())
  344. {
  345. onAdd_callback( getId());
  346. if (mAutoSpawn)
  347. spawnObject();
  348. }
  349. return true;
  350. }
  351. SimObject* SpawnSphere::spawnObject(String additionalProps)
  352. {
  353. SimObject* spawnObject = Sim::spawnObject(mSpawnClass, mSpawnDataBlock, mSpawnName,
  354. mSpawnProperties + " " + additionalProps, mSpawnScript);
  355. // If we have a spawnObject add it to the MissionCleanup group
  356. if (spawnObject)
  357. {
  358. if (mSpawnTransform)
  359. {
  360. if(SceneObject *s = dynamic_cast<SceneObject*>(spawnObject))
  361. s->setTransform(getTransform());
  362. }
  363. SimObject* cleanup = Sim::findObject("MissionCleanup");
  364. if (cleanup)
  365. {
  366. SimGroup* missionCleanup = dynamic_cast<SimGroup*>(cleanup);
  367. missionCleanup->addObject(spawnObject);
  368. }
  369. }
  370. return spawnObject;
  371. }
  372. void SpawnSphere::inspectPostApply()
  373. {
  374. Parent::inspectPostApply();
  375. setMaskBits(UpdateSphereMask);
  376. }
  377. U32 SpawnSphere::packUpdate(NetConnection * con, U32 mask, BitStream * stream)
  378. {
  379. U32 retMask = Parent::packUpdate(con, mask, stream);
  380. //
  381. if(stream->writeFlag(mask & UpdateSphereMask))
  382. {
  383. stream->writeFlag(mAutoSpawn);
  384. stream->writeFlag(mSpawnTransform);
  385. stream->write(mSpawnClass);
  386. stream->write(mSpawnDataBlock);
  387. stream->write(mSpawnName);
  388. stream->write(mSpawnProperties);
  389. stream->write(mSpawnScript);
  390. }
  391. return(retMask);
  392. }
  393. void SpawnSphere::unpackUpdate(NetConnection * con, BitStream * stream)
  394. {
  395. Parent::unpackUpdate(con, stream);
  396. if(stream->readFlag())
  397. {
  398. mAutoSpawn = stream->readFlag();
  399. mSpawnTransform = stream->readFlag();
  400. stream->read(&mSpawnClass);
  401. stream->read(&mSpawnDataBlock);
  402. stream->read(&mSpawnName);
  403. stream->read(&mSpawnProperties);
  404. stream->read(&mSpawnScript);
  405. }
  406. }
  407. void SpawnSphere::processTick( const Move *move )
  408. {
  409. if ( isServerObject() && isMounted() )
  410. {
  411. MatrixF mat( true );
  412. mMount.object->getRenderMountTransform( 0.f, mMount.node, mMount.xfm, &mat );
  413. setTransform( mat );
  414. }
  415. }
  416. void SpawnSphere::advanceTime( F32 timeDelta )
  417. {
  418. if ( isMounted() )
  419. {
  420. MatrixF mat( true );
  421. mMount.object->getRenderMountTransform( 0.f, mMount.node, mMount.xfm, &mat );
  422. setTransform( mat );
  423. }
  424. }
  425. void SpawnSphere::initPersistFields()
  426. {
  427. addGroup( "Spawn" );
  428. addField( "spawnClass", TypeRealString, Offset(mSpawnClass, SpawnSphere),
  429. "Object class to create (eg. Player, AIPlayer, Debris etc)" );
  430. addField( "spawnDatablock", TypeRealString, Offset(mSpawnDataBlock, SpawnSphere),
  431. "Predefined datablock assigned to the object when created" );
  432. addField( "spawnProperties", TypeRealString, Offset(mSpawnProperties, SpawnSphere),
  433. "String containing semicolon (;) delimited properties to set when the object is created." );
  434. addField( "spawnScript", TypeCommand, Offset(mSpawnScript, SpawnSphere),
  435. "Command to execute immediately after spawning an object. New object id is stored in $SpawnObject. Max 255 characters." );
  436. addField( "autoSpawn", TypeBool, Offset(mAutoSpawn, SpawnSphere),
  437. "Flag to spawn object as soon as SpawnSphere is created, true to enable or false to disable." );
  438. addField( "spawnTransform", TypeBool, Offset(mSpawnTransform, SpawnSphere),
  439. "Flag to set the spawned object's transform to the SpawnSphere's transform." );
  440. endGroup( "Spawn" );
  441. addGroup( "Dimensions" );
  442. addField( "radius", TypeF32, Offset(mRadius, SpawnSphere), "Deprecated" );
  443. endGroup( "Dimensions" );
  444. addGroup( "Weight" );
  445. addField( "sphereWeight", TypeF32, Offset(mSphereWeight, SpawnSphere), "Deprecated" );
  446. addField( "indoorWeight", TypeF32, Offset(mIndoorWeight, SpawnSphere), "Deprecated" );
  447. addField( "outdoorWeight", TypeF32, Offset(mOutdoorWeight, SpawnSphere), "Deprecated" );
  448. endGroup( "Weight" );
  449. Parent::initPersistFields();
  450. }
  451. ConsoleDocFragment _SpawnSpherespawnObject1(
  452. "@brief Dynamically create a new game object with a specified class, datablock, and optional properties.\n\n"
  453. "This is called on the actual SpawnSphere, not to be confused with the Sim::spawnObject() "
  454. "global function\n\n"
  455. "@param additionalProps Optional set of semiconlon delimited parameters applied to the spawn object during creation.\n\n"
  456. "@tsexample\n"
  457. "// Use the SpawnSphere::spawnObject function to create a game object\n"
  458. "// No additional properties assigned\n"
  459. "%player = DefaultSpawnSphere.spawnObject();\n\n"
  460. "@endtsexample\n\n",
  461. "SpawnSphere",
  462. "bool spawnObject(string additionalProps);"
  463. );
  464. ConsoleMethod(SpawnSphere, spawnObject, S32, 2, 3,
  465. "([string additionalProps]) Spawns the object based on the SpawnSphere's "
  466. "class, datablock, properties, and script settings. Allows you to pass in "
  467. "extra properties."
  468. "@hide" )
  469. {
  470. String additionalProps;
  471. if (argc == 3)
  472. additionalProps = String(argv[2]);
  473. SimObject* obj = object->spawnObject(additionalProps);
  474. if (obj)
  475. return obj->getId();
  476. return -1;
  477. }
  478. //------------------------------------------------------------------------------
  479. // Class: CameraBookmark
  480. //------------------------------------------------------------------------------
  481. IMPLEMENT_CO_NETOBJECT_V1(CameraBookmark);
  482. ConsoleDocClass( CameraBookmark,
  483. "@brief Special type of mission marker which allows a level editor's camera to jump to specific points.\n\n"
  484. "For Torque 3D editors only, not for actual game development\n\n"
  485. "@internal"
  486. );
  487. CameraBookmark::CameraBookmark()
  488. {
  489. mName = StringTable->insert("");
  490. }
  491. bool CameraBookmark::onAdd()
  492. {
  493. if(!Parent::onAdd())
  494. return(false);
  495. //
  496. if(!isClientObject())
  497. {
  498. setMaskBits(UpdateNameMask);
  499. }
  500. if( isServerObject() && isMethod("onAdd") )
  501. Con::executef( this, "onAdd" );
  502. return(true);
  503. }
  504. void CameraBookmark::onRemove()
  505. {
  506. if( isServerObject() && isMethod("onRemove") )
  507. Con::executef( this, "onRemove" );
  508. Parent::onRemove();
  509. }
  510. void CameraBookmark::onGroupAdd()
  511. {
  512. if( isServerObject() && isMethod("onGroupAdd") )
  513. Con::executef( this, "onGroupAdd" );
  514. }
  515. void CameraBookmark::onGroupRemove()
  516. {
  517. if( isServerObject() && isMethod("onGroupRemove") )
  518. Con::executef( this, "onGroupRemove" );
  519. }
  520. void CameraBookmark::inspectPostApply()
  521. {
  522. Parent::inspectPostApply();
  523. if(!mName || !mName[0])
  524. mName = StringTable->insert("");
  525. setMaskBits(UpdateNameMask);
  526. if( isMethod("onInspectPostApply") )
  527. Con::executef( this, "onInspectPostApply" );
  528. }
  529. U32 CameraBookmark::packUpdate(NetConnection * con, U32 mask, BitStream * stream)
  530. {
  531. U32 retMask = Parent::packUpdate(con, mask, stream);
  532. if(stream->writeFlag(mask & UpdateNameMask))
  533. stream->writeString(mName);
  534. return(retMask);
  535. }
  536. void CameraBookmark::unpackUpdate(NetConnection * con, BitStream * stream)
  537. {
  538. Parent::unpackUpdate(con, stream);
  539. if(stream->readFlag())
  540. mName = stream->readSTString(true);
  541. }
  542. void CameraBookmark::initPersistFields()
  543. {
  544. //addGroup("Misc");
  545. //addField("name", TypeCaseString, Offset(mName, CameraBookmark));
  546. //endGroup("Misc");
  547. Parent::initPersistFields();
  548. removeField("nameTag"); // From GameBase
  549. }