entity.cpp 57 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045
  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 "platform/platform.h"
  23. #include "T3D/entity.h"
  24. #include "core/stream/bitStream.h"
  25. #include "console/consoleTypes.h"
  26. #include "console/consoleObject.h"
  27. #include "sim/netConnection.h"
  28. #include "scene/sceneRenderState.h"
  29. #include "scene/sceneManager.h"
  30. #include "T3D/gameBase/gameProcess.h"
  31. #include "console/engineAPI.h"
  32. #include "T3D/gameBase/gameConnection.h"
  33. #include "math/mathIO.h"
  34. #include "math/mTransform.h"
  35. #include "T3D/components/coreInterfaces.h"
  36. #include "T3D/components/render/renderComponentInterface.h"
  37. #include "T3D/components/collision/collisionInterfaces.h"
  38. #include "gui/controls/guiTreeViewCtrl.h"
  39. #include "assets/assetManager.h"
  40. #include "assets/assetQuery.h"
  41. #include "T3D/assets/ComponentAsset.h"
  42. #include "console/consoleInternal.h"
  43. #include "T3D/gameBase/std/stdMoveList.h"
  44. #include "T3D/prefab.h"
  45. #include "T3D/gameBase/gameConnection.h"
  46. #include <thread>
  47. //
  48. #include "gfx/sim/debugDraw.h"
  49. //
  50. #include "T3D/sfx/sfx3DWorld.h"
  51. extern bool gEditingMission;
  52. // Client prediction
  53. static F32 sMinWarpTicks = 0.5f; // Fraction of tick at which instant warp occurs
  54. static S32 sMaxWarpTicks = 3; // Max warp duration in ticks
  55. static S32 sMaxPredictionTicks = 30; // Number of ticks to predict
  56. IMPLEMENT_CO_NETOBJECT_V1(Entity);
  57. ConsoleDocClass(Entity,
  58. "@brief Base Entity class.\n\n"
  59. "Entity is typically made up of a shape and up to two particle emitters. In most cases Entity objects are "
  60. "not created directly. They are usually produced automatically by other means, such as through the Explosion "
  61. "class. When an explosion goes off, its ExplosionData datablock determines what Entity to emit.\n"
  62. "@tsexample\n"
  63. "datablock ExplosionData(GrenadeLauncherExplosion)\n"
  64. "{\n"
  65. " // Assiging Entity data\n"
  66. " Entity = GrenadeEntity;\n\n"
  67. " // Adjust how Entity is ejected\n"
  68. " EntityThetaMin = 10;\n"
  69. " EntityThetaMax = 60;\n"
  70. " EntityNum = 4;\n"
  71. " EntityNumVariance = 2;\n"
  72. " EntityVelocity = 25;\n"
  73. " EntityVelocityVariance = 5;\n\n"
  74. " // Note: other ExplosionData properties are not listed for this example\n"
  75. "};\n"
  76. "@endtsexample\n\n"
  77. "@note Entity are client side only objects.\n"
  78. "@see EntityData\n"
  79. "@see ExplosionData\n"
  80. "@see Explosion\n"
  81. "@ingroup FX\n"
  82. );
  83. Entity::Entity()
  84. {
  85. //mTypeMask |= DynamicShapeObjectType | StaticObjectType | ;
  86. mTypeMask |= EntityObjectType;
  87. mNetFlags.set(Ghostable | ScopeAlways);
  88. mPos = Point3F(0, 0, 0);
  89. mRot = Point3F(0, 0, 0);
  90. mDelta.pos = mDelta.posVec = Point3F::Zero;
  91. mDelta.rot[0].identity();
  92. mDelta.rot[1].identity();
  93. mDelta.warpOffset.set(0.0f, 0.0f, 0.0f);
  94. mDelta.warpTicks = mDelta.warpCount = 0;
  95. mDelta.dt = 1.0f;
  96. mDelta.move = NullMove;
  97. mComponents.clear();
  98. mStartComponentUpdate = false;
  99. mInitialized = false;
  100. mLifetimeMS = 0;
  101. mGameObjectAssetId = StringTable->insert("");
  102. }
  103. Entity::~Entity()
  104. {
  105. }
  106. void Entity::initPersistFields()
  107. {
  108. Parent::initPersistFields();
  109. removeField("DataBlock");
  110. addGroup("Transform");
  111. removeField("Position");
  112. addProtectedField("Position", TypePoint3F, Offset(mPos, Entity), &_setPosition, &_getPosition, "Object world orientation.");
  113. removeField("Rotation");
  114. addProtectedField("Rotation", TypeRotationF, Offset(mRot, Entity), &_setRotation, &_getRotation, "Object world orientation.");
  115. //These are basically renamed mountPos/Rot. pretty much there for conveinence
  116. addField("LocalPosition", TypeMatrixPosition, Offset(mMount.xfm, Entity), "Position we are mounted at ( object space of our mount object ).");
  117. addField("LocalRotation", TypeMatrixRotation, Offset(mMount.xfm, Entity), "Rotation we are mounted at ( object space of our mount object ).");
  118. endGroup("Transform");
  119. addGroup("Misc");
  120. addField("LifetimeMS", TypeS32, Offset(mLifetimeMS, Entity), "Object world orientation.");
  121. endGroup("Misc");
  122. addGroup("GameObject");
  123. addProtectedField("gameObjectName", TypeGameObjectAssetPtr, Offset(mGameObjectAsset, Entity), &_setGameObject, &defaultProtectedGetFn,
  124. "The asset Id used for the game object this entity is based on.");
  125. endGroup("GameObject");
  126. }
  127. //
  128. bool Entity::_setPosition(void *object, const char *index, const char *data)
  129. {
  130. Entity* so = static_cast<Entity*>(object);
  131. if (so)
  132. {
  133. Point3F pos;
  134. if (!dStrcmp(data, ""))
  135. pos = Point3F(0, 0, 0);
  136. else
  137. Con::setData(TypePoint3F, &pos, 0, 1, &data);
  138. so->setTransform(pos, so->mRot);
  139. }
  140. return false;
  141. }
  142. const char * Entity::_getPosition(void* obj, const char* data)
  143. {
  144. Entity* so = static_cast<Entity*>(obj);
  145. if (so)
  146. {
  147. Point3F pos = so->getPosition();
  148. static const U32 bufSize = 256;
  149. char* returnBuffer = Con::getReturnBuffer(bufSize);
  150. dSprintf(returnBuffer, bufSize, "%g %g %g", pos.x, pos.y, pos.z);
  151. return returnBuffer;
  152. }
  153. return "0 0 0";
  154. }
  155. bool Entity::_setRotation(void *object, const char *index, const char *data)
  156. {
  157. Entity* so = static_cast<Entity*>(object);
  158. if (so)
  159. {
  160. RotationF rot;
  161. Con::setData(TypeRotationF, &rot, 0, 1, &data);
  162. //so->mRot = rot;
  163. //MatrixF mat = rot.asMatrixF();
  164. //mat.setPosition(so->getPosition());
  165. //so->setTransform(mat);
  166. so->setTransform(so->getPosition(), rot);
  167. }
  168. return false;
  169. }
  170. const char * Entity::_getRotation(void* obj, const char* data)
  171. {
  172. Entity* so = static_cast<Entity*>(obj);
  173. if (so)
  174. {
  175. EulerF eulRot = so->mRot.asEulerF();
  176. static const U32 bufSize = 256;
  177. char* returnBuffer = Con::getReturnBuffer(bufSize);
  178. dSprintf(returnBuffer, bufSize, "%g %g %g", mRadToDeg(eulRot.x), mRadToDeg(eulRot.y), mRadToDeg(eulRot.z));
  179. return returnBuffer;
  180. }
  181. return "0 0 0";
  182. }
  183. bool Entity::onAdd()
  184. {
  185. if (!Parent::onAdd())
  186. return false;
  187. mObjBox = Box3F(Point3F(-0.5, -0.5, -0.5), Point3F(0.5, 0.5, 0.5));
  188. resetWorldBox();
  189. setObjectBox(mObjBox);
  190. addToScene();
  191. //Make sure we get positioned
  192. if (isServerObject())
  193. {
  194. setMaskBits(TransformMask);
  195. setMaskBits(NamespaceMask);
  196. }
  197. else
  198. {
  199. //We can shortcut the initialization here because stuff generally ghosts down in order, and onPostAdd isn't called on ghosts.
  200. onPostAdd();
  201. }
  202. if (mLifetimeMS != 0)
  203. mStartTimeMS = Platform::getRealMilliseconds();
  204. return true;
  205. }
  206. void Entity::onRemove()
  207. {
  208. clearComponents(true);
  209. removeFromScene();
  210. onDataSet.removeAll();
  211. mGameObjectAsset.clear();
  212. Parent::onRemove();
  213. }
  214. void Entity::onPostAdd()
  215. {
  216. mInitialized = true;
  217. //everything's done and added. go ahead and initialize the components
  218. for (U32 i = 0; i < mComponents.size(); i++)
  219. {
  220. mComponents[i]->onComponentAdd();
  221. }
  222. //Set up the networked components
  223. mNetworkedComponents.clear();
  224. for (U32 i = 0; i < mComponents.size(); i++)
  225. {
  226. if (mComponents[i]->isNetworked())
  227. {
  228. NetworkedComponent netComp;
  229. netComp.componentIndex = i;
  230. netComp.updateState = NetworkedComponent::Adding;
  231. netComp.updateMaskBits = -1;
  232. mNetworkedComponents.push_back(netComp);
  233. }
  234. }
  235. if (!mNetworkedComponents.empty())
  236. {
  237. setMaskBits(AddComponentsMask);
  238. setMaskBits(ComponentsUpdateMask);
  239. }
  240. if (isMethod("onAdd"))
  241. Con::executef(this, "onAdd");
  242. }
  243. bool Entity::_setGameObject(void *object, const char *index, const char *data)
  244. {
  245. Entity *e = static_cast<Entity*>(object);
  246. // Sanity!
  247. AssertFatal(data != NULL, "Cannot use a NULL asset Id.");
  248. return true; //rbI->setMeshAsset(data);
  249. }
  250. void Entity::setDataField(StringTableEntry slotName, const char *array, const char *value)
  251. {
  252. Parent::setDataField(slotName, array, value);
  253. onDataSet.trigger(this, slotName, value);
  254. }
  255. void Entity::onStaticModified(const char* slotName, const char* newValue)
  256. {
  257. Parent::onStaticModified(slotName, newValue);
  258. onDataSet.trigger(this, slotName, newValue);
  259. }
  260. //Updating
  261. void Entity::processTick(const Move* move)
  262. {
  263. if (!isHidden())
  264. {
  265. if (mDelta.warpCount < mDelta.warpTicks)
  266. {
  267. mDelta.warpCount++;
  268. // Set new pos.
  269. mObjToWorld.getColumn(3, &mDelta.pos);
  270. mDelta.pos += mDelta.warpOffset;
  271. mDelta.rot[0] = mDelta.rot[1];
  272. mDelta.rot[1].interpolate(mDelta.warpRot[0], mDelta.warpRot[1], F32(mDelta.warpCount) / mDelta.warpTicks);
  273. setTransform(mDelta.pos, mDelta.rot[1]);
  274. // Pos backstepping
  275. mDelta.posVec.x = -mDelta.warpOffset.x;
  276. mDelta.posVec.y = -mDelta.warpOffset.y;
  277. mDelta.posVec.z = -mDelta.warpOffset.z;
  278. }
  279. else
  280. {
  281. if (isMounted())
  282. {
  283. MatrixF mat;
  284. mMount.object->getMountTransform(mMount.node, mMount.xfm, &mat);
  285. Parent::setTransform(mat);
  286. Parent::setRenderTransform(mat);
  287. }
  288. else
  289. {
  290. if (!move)
  291. {
  292. if (isGhost())
  293. {
  294. // If we haven't run out of prediction time,
  295. // predict using the last known move.
  296. if (mPredictionCount-- <= 0)
  297. return;
  298. move = &mDelta.move;
  299. }
  300. else
  301. {
  302. move = &NullMove;
  303. }
  304. }
  305. }
  306. }
  307. Move prevMove = lastMove;
  308. if (move != NULL)
  309. lastMove = *move;
  310. else
  311. lastMove = NullMove;
  312. if (move && isServerObject())
  313. {
  314. if ((move->y != 0 || prevMove.y != 0)
  315. || (move->x != 0 || prevMove.x != 0)
  316. || (move->z != 0 || prevMove.x != 0))
  317. {
  318. if (isMethod("moveVectorEvent"))
  319. Con::executef(this, "moveVectorEvent", move->x, move->y, move->z);
  320. }
  321. if (move->yaw != 0)
  322. {
  323. if (isMethod("moveYawEvent"))
  324. Con::executef(this, "moveYawEvent", move->yaw);
  325. }
  326. if (move->pitch != 0)
  327. {
  328. if (isMethod("movePitchEvent"))
  329. Con::executef(this, "movePitchEvent", move->pitch);
  330. }
  331. if (move->roll != 0)
  332. {
  333. if (isMethod("moveRollEvent"))
  334. Con::executef(this, "moveRollEvent", move->roll);
  335. }
  336. for (U32 i = 0; i < MaxTriggerKeys; i++)
  337. {
  338. if (move->trigger[i] != prevMove.trigger[i])
  339. {
  340. if (isMethod("moveTriggerEvent"))
  341. Con::executef(this, "moveTriggerEvent", i, move->trigger[i]);
  342. }
  343. }
  344. }
  345. // Save current rigid state interpolation
  346. mDelta.posVec = getPosition();
  347. mDelta.rot[0] = mRot.asQuatF();
  348. //Handle any script updates, which can include physics stuff
  349. if (isServerObject() && isMethod("processTick"))
  350. Con::executef(this, "processTick");
  351. // Wrap up interpolation info
  352. mDelta.pos = getPosition();
  353. mDelta.posVec -= getPosition();
  354. mDelta.rot[1] = mRot.asQuatF();
  355. setTransform(getPosition(), mRot);
  356. //Lifetime test
  357. if (mLifetimeMS != 0)
  358. {
  359. S32 currentTime = Platform::getRealMilliseconds();
  360. if (currentTime - mStartTimeMS >= mLifetimeMS)
  361. deleteObject();
  362. }
  363. }
  364. }
  365. void Entity::advanceTime(F32 dt)
  366. {
  367. }
  368. void Entity::interpolateTick(F32 dt)
  369. {
  370. if (dt == 0.0f)
  371. {
  372. setRenderTransform(mDelta.pos, mDelta.rot[1]);
  373. }
  374. else
  375. {
  376. QuatF rot;
  377. rot.interpolate(mDelta.rot[1], mDelta.rot[0], dt);
  378. Point3F pos = mDelta.pos + mDelta.posVec * dt;
  379. setRenderTransform(pos, rot);
  380. }
  381. mDelta.dt = dt;
  382. }
  383. //Render
  384. void Entity::prepRenderImage(SceneRenderState *state)
  385. {
  386. }
  387. //Networking
  388. U32 Entity::packUpdate(NetConnection *con, U32 mask, BitStream *stream)
  389. {
  390. U32 retMask = Parent::packUpdate(con, mask, stream);
  391. if (stream->writeFlag(mask & TransformMask))
  392. {
  393. stream->writeCompressedPoint(mPos);
  394. mathWrite(*stream, getRotation());
  395. mDelta.move.pack(stream);
  396. stream->writeFlag(!(mask & NoWarpMask));
  397. }
  398. if (stream->writeFlag(mask & BoundsMask))
  399. {
  400. mathWrite(*stream, mObjBox);
  401. }
  402. if (stream->writeFlag(mask & AddComponentsMask))
  403. {
  404. U32 toAddComponentCount = 0;
  405. for (U32 i = 0; i < mNetworkedComponents.size(); i++)
  406. {
  407. if (mNetworkedComponents[i].updateState == NetworkedComponent::Adding)
  408. {
  409. toAddComponentCount++;
  410. }
  411. }
  412. //you reaaaaally shouldn't have >255 networked components on a single entity
  413. stream->writeInt(toAddComponentCount, 8);
  414. for (U32 i = 0; i < mNetworkedComponents.size(); i++)
  415. {
  416. NetworkedComponent::UpdateState state = mNetworkedComponents[i].updateState;
  417. if (mNetworkedComponents[i].updateState == NetworkedComponent::Adding)
  418. {
  419. const char* className = mComponents[mNetworkedComponents[i].componentIndex]->getClassName();
  420. stream->writeString(className, strlen(className));
  421. mNetworkedComponents[i].updateState = NetworkedComponent::Updating;
  422. }
  423. }
  424. }
  425. if (stream->writeFlag(mask & RemoveComponentsMask))
  426. {
  427. /*U32 toRemoveComponentCount = 0;
  428. for (U32 i = 0; i < mNetworkedComponents.size(); i++)
  429. {
  430. if (mNetworkedComponents[i].updateState == NetworkedComponent::Adding)
  431. {
  432. toRemoveComponentCount++;
  433. }
  434. }
  435. //you reaaaaally shouldn't have >255 networked components on a single entity
  436. stream->writeInt(toRemoveComponentCount, 8);
  437. for (U32 i = 0; i < mNetworkedComponents.size(); i++)
  438. {
  439. if (mNetworkedComponents[i].updateState == NetworkedComponent::Removing)
  440. {
  441. stream->writeInt(i, 16);
  442. }
  443. }*/
  444. /*for (U32 i = 0; i < mNetworkedComponents.size(); i++)
  445. {
  446. if (mNetworkedComponents[i].updateState == NetworkedComponent::UpdateState::Removing)
  447. {
  448. removeComponent(mComponents[mNetworkedComponents[i].componentIndex], true);
  449. mNetworkedComponents.erase(i);
  450. i--;
  451. }
  452. }*/
  453. }
  454. //Update our components
  455. if (stream->writeFlag(mask & ComponentsUpdateMask))
  456. {
  457. U32 toUpdateComponentCount = 0;
  458. for (U32 i = 0; i < mNetworkedComponents.size(); i++)
  459. {
  460. if (mNetworkedComponents[i].updateState == NetworkedComponent::Updating)
  461. {
  462. toUpdateComponentCount++;
  463. }
  464. }
  465. //you reaaaaally shouldn't have >255 networked components on a single entity
  466. stream->writeInt(toUpdateComponentCount, 8);
  467. bool forceUpdate = false;
  468. for (U32 i = 0; i < mNetworkedComponents.size(); i++)
  469. {
  470. if (mNetworkedComponents[i].updateState == NetworkedComponent::Updating)
  471. {
  472. stream->writeInt(i, 8);
  473. mNetworkedComponents[i].updateMaskBits = mComponents[mNetworkedComponents[i].componentIndex]->packUpdate(con, mNetworkedComponents[i].updateMaskBits, stream);
  474. if (mNetworkedComponents[i].updateMaskBits != 0)
  475. forceUpdate = true;
  476. else
  477. mNetworkedComponents[i].updateState = NetworkedComponent::None;
  478. }
  479. }
  480. //If we have leftover, we need to re-iterate our packing
  481. if (forceUpdate)
  482. setMaskBits(ComponentsUpdateMask);
  483. }
  484. /*if (stream->writeFlag(mask & NamespaceMask))
  485. {
  486. const char* name = getName();
  487. if (stream->writeFlag(name && name[0]))
  488. stream->writeString(String(name));
  489. if (stream->writeFlag(mSuperClassName && mSuperClassName[0]))
  490. stream->writeString(String(mSuperClassName));
  491. if (stream->writeFlag(mClassName && mClassName[0]))
  492. stream->writeString(String(mClassName));
  493. }*/
  494. return retMask;
  495. }
  496. void Entity::unpackUpdate(NetConnection *con, BitStream *stream)
  497. {
  498. Parent::unpackUpdate(con, stream);
  499. if (stream->readFlag())
  500. {
  501. Point3F pos;
  502. stream->readCompressedPoint(&pos);
  503. RotationF rot;
  504. mathRead(*stream, &rot);
  505. mDelta.move.unpack(stream);
  506. if (stream->readFlag() && isProperlyAdded())
  507. {
  508. // Determine number of ticks to warp based on the average
  509. // of the client and server velocities.
  510. Point3F cp = mDelta.pos + mDelta.posVec * mDelta.dt;
  511. mDelta.warpOffset = pos - cp;
  512. // Calc the distance covered in one tick as the average of
  513. // the old speed and the new speed from the server.
  514. VectorF vel = pos - mDelta.pos;
  515. F32 dt, as = vel.len() * 0.5 * TickSec;
  516. // Cal how many ticks it will take to cover the warp offset.
  517. // If it's less than what's left in the current tick, we'll just
  518. // warp in the remaining time.
  519. if (!as || (dt = mDelta.warpOffset.len() / as) > sMaxWarpTicks)
  520. dt = mDelta.dt + sMaxWarpTicks;
  521. else
  522. dt = (dt <= mDelta.dt) ? mDelta.dt : mCeil(dt - mDelta.dt) + mDelta.dt;
  523. // Adjust current frame interpolation
  524. if (mDelta.dt)
  525. {
  526. mDelta.pos = cp + (mDelta.warpOffset * (mDelta.dt / dt));
  527. mDelta.posVec = (cp - mDelta.pos) / mDelta.dt;
  528. QuatF cr;
  529. cr.interpolate(mDelta.rot[1], mDelta.rot[0], mDelta.dt);
  530. mDelta.rot[1].interpolate(cr, rot.asQuatF(), mDelta.dt / dt);
  531. mDelta.rot[0].extrapolate(mDelta.rot[1], cr, mDelta.dt);
  532. }
  533. // Calculated multi-tick warp
  534. mDelta.warpCount = 0;
  535. mDelta.warpTicks = (S32)(mFloor(dt));
  536. if (mDelta.warpTicks)
  537. {
  538. mDelta.warpOffset = pos - mDelta.pos;
  539. mDelta.warpOffset /= mDelta.warpTicks;
  540. mDelta.warpRot[0] = mDelta.rot[1];
  541. mDelta.warpRot[1] = rot.asQuatF();
  542. }
  543. }
  544. else
  545. {
  546. // Set the entity to the server position
  547. mDelta.dt = 0;
  548. mDelta.pos = pos;
  549. mDelta.posVec.set(0, 0, 0);
  550. mDelta.rot[1] = mDelta.rot[0] = rot.asQuatF();
  551. mDelta.warpCount = mDelta.warpTicks = 0;
  552. setTransform(pos, rot);
  553. }
  554. }
  555. if (stream->readFlag())
  556. {
  557. mathRead(*stream, &mObjBox);
  558. resetWorldBox();
  559. }
  560. //AddComponentMask
  561. if (stream->readFlag())
  562. {
  563. U32 addedComponentCount = stream->readInt(8);
  564. for (U32 i = 0; i < addedComponentCount; i++)
  565. {
  566. char className[256] = "";
  567. stream->readString(className);
  568. //Change to components, so iterate our list and create any new components
  569. // Well, looks like we have to create a new object.
  570. const char* componentType = className;
  571. ConsoleObject *object = ConsoleObject::create(componentType);
  572. // Finally, set currentNewObject to point to the new one.
  573. Component* newComponent = dynamic_cast<Component *>(object);
  574. if (newComponent)
  575. {
  576. addComponent(newComponent);
  577. }
  578. }
  579. }
  580. //RemoveComponentMask
  581. if (stream->readFlag())
  582. {
  583. }
  584. //ComponentUpdateMask
  585. if (stream->readFlag())
  586. {
  587. U32 updatingComponents = stream->readInt(8);
  588. for (U32 i = 0; i < updatingComponents; i++)
  589. {
  590. U32 updateComponentIndex = stream->readInt(8);
  591. Component* comp = mComponents[updateComponentIndex];
  592. comp->unpackUpdate(con, stream);
  593. }
  594. }
  595. /*if (stream->readFlag())
  596. {
  597. if (stream->readFlag())
  598. {
  599. char name[256];
  600. stream->readString(name);
  601. assignName(name);
  602. }
  603. if (stream->readFlag())
  604. {
  605. char superClassname[256];
  606. stream->readString(superClassname);
  607. mSuperClassName = superClassname;
  608. }
  609. if (stream->readFlag())
  610. {
  611. char classname[256];
  612. stream->readString(classname);
  613. mClassName = classname;
  614. }
  615. linkNamespaces();
  616. }*/
  617. }
  618. void Entity::setComponentNetMask(Component* comp, U32 mask)
  619. {
  620. setMaskBits(Entity::ComponentsUpdateMask);
  621. for (U32 i = 0; i < mNetworkedComponents.size(); i++)
  622. {
  623. U32 netCompId = mComponents[mNetworkedComponents[i].componentIndex]->getId();
  624. U32 compId = comp->getId();
  625. if (netCompId == compId &&
  626. (mNetworkedComponents[i].updateState == NetworkedComponent::None || mNetworkedComponents[i].updateState == NetworkedComponent::Updating))
  627. {
  628. mNetworkedComponents[i].updateState = NetworkedComponent::Updating;
  629. mNetworkedComponents[i].updateMaskBits |= mask;
  630. break;
  631. }
  632. }
  633. }
  634. //Manipulation
  635. void Entity::setTransform(const MatrixF &mat)
  636. {
  637. MatrixF oldTransform = getTransform();
  638. if (isMounted())
  639. {
  640. // Use transform from mounted object
  641. Point3F newPos = mat.getPosition();
  642. Point3F parentPos = mMount.object->getTransform().getPosition();
  643. Point3F newOffset = newPos - parentPos;
  644. if (!newOffset.isZero())
  645. {
  646. mPos = newOffset;
  647. }
  648. Point3F matEul = mat.toEuler();
  649. if (matEul != Point3F(0, 0, 0))
  650. {
  651. Point3F mountEul = mMount.object->getTransform().toEuler();
  652. Point3F diff = matEul - mountEul;
  653. mRot = diff;
  654. }
  655. else
  656. {
  657. mRot = Point3F(0, 0, 0);
  658. }
  659. RotationF addRot = mRot + RotationF(mMount.object->getTransform());
  660. MatrixF transf = addRot.asMatrixF();
  661. transf.setPosition(mPos + mMount.object->getPosition());
  662. Parent::setTransform(transf);
  663. if (transf != oldTransform)
  664. setMaskBits(TransformMask);
  665. }
  666. else
  667. {
  668. //Are we part of a prefab?
  669. /*Prefab* p = Prefab::getPrefabByChild(this);
  670. if (p)
  671. {
  672. //just let our prefab know we moved
  673. p->childTransformUpdated(this, mat);
  674. }*/
  675. //else
  676. {
  677. //mRot.set(mat);
  678. //Parent::setTransform(mat);
  679. RotationF rot = RotationF(mat);
  680. EulerF tempRot = rot.asEulerF(RotationF::Degrees);
  681. Point3F pos;
  682. mat.getColumn(3,&pos);
  683. setTransform(pos, rot);
  684. }
  685. }
  686. }
  687. void Entity::setTransform(const Point3F& position, const RotationF& rotation)
  688. {
  689. MatrixF oldTransform = getTransform();
  690. if (isMounted())
  691. {
  692. mPos = position;
  693. mRot = rotation;
  694. RotationF addRot = mRot + RotationF(mMount.object->getTransform());
  695. MatrixF transf = addRot.asMatrixF();
  696. transf.setPosition(mPos + mMount.object->getPosition());
  697. Parent::setTransform(transf);
  698. if (transf != oldTransform)
  699. setMaskBits(TransformMask);
  700. }
  701. else
  702. {
  703. /*MatrixF newMat, imat, xmat, ymat, zmat;
  704. Point3F radRot = Point3F(mDegToRad(rotation.x), mDegToRad(rotation.y), mDegToRad(rotation.z));
  705. xmat.set(EulerF(radRot.x, 0, 0));
  706. ymat.set(EulerF(0.0f, radRot.y, 0.0f));
  707. zmat.set(EulerF(0, 0, radRot.z));
  708. imat.mul(zmat, xmat);
  709. newMat.mul(imat, ymat);*/
  710. MatrixF newMat = rotation.asMatrixF();
  711. newMat.setColumn(3, position);
  712. mPos = position;
  713. mRot = rotation;
  714. //if (isServerObject())
  715. // setMaskBits(TransformMask);
  716. //setTransform(temp);
  717. // This test is a bit expensive so turn it off in release.
  718. #ifdef TORQUE_DEBUG
  719. //AssertFatal( mat.isAffine(), "SceneObject::setTransform() - Bad transform (non affine)!" );
  720. #endif
  721. //PROFILE_SCOPE(Entity_setTransform);
  722. // Update the transforms.
  723. Parent::setTransform(newMat);
  724. U32 compCount = mComponents.size();
  725. for (U32 i = 0; i < compCount; ++i)
  726. {
  727. mComponents[i]->ownerTransformSet(&newMat);
  728. }
  729. Point3F newPos = newMat.getPosition();
  730. RotationF newRot = newMat;
  731. Point3F oldPos = oldTransform.getPosition();
  732. RotationF oldRot = oldTransform;
  733. if (newPos != oldPos || newRot != oldRot)
  734. setMaskBits(TransformMask);
  735. }
  736. }
  737. void Entity::setRenderTransform(const MatrixF &mat)
  738. {
  739. Parent::setRenderTransform(mat);
  740. }
  741. void Entity::setRenderTransform(const Point3F& position, const RotationF& rotation)
  742. {
  743. if (isMounted())
  744. {
  745. mPos = position;
  746. mRot = rotation;
  747. RotationF addRot = mRot + RotationF(mMount.object->getTransform());
  748. MatrixF transf = addRot.asMatrixF();
  749. transf.setPosition(mPos + mMount.object->getPosition());
  750. Parent::setRenderTransform(transf);
  751. }
  752. else
  753. {
  754. MatrixF newMat = rotation.asMatrixF();
  755. newMat.setColumn(3, position);
  756. mPos = position;
  757. mRot = rotation;
  758. Parent::setRenderTransform(newMat);
  759. U32 compCount = mComponents.size();
  760. for (U32 i = 0; i < compCount; ++i)
  761. {
  762. mComponents[i]->ownerTransformSet(&newMat);
  763. }
  764. }
  765. }
  766. MatrixF Entity::getTransform()
  767. {
  768. if (isMounted())
  769. {
  770. MatrixF mat;
  771. //Use transform from mount
  772. mMount.object->getMountTransform(mMount.node, mMount.xfm, &mat);
  773. Point3F transPos = mat.getPosition() + mPos;
  774. mat.mul(mRot.asMatrixF());
  775. mat.setPosition(transPos);
  776. return mat;
  777. }
  778. else
  779. {
  780. return Parent::getTransform();
  781. }
  782. }
  783. void Entity::setMountOffset(const Point3F& posOffset)
  784. {
  785. if (isMounted())
  786. {
  787. mMount.xfm.setColumn(3, posOffset);
  788. //mPos = posOffset;
  789. setMaskBits(MountedMask);
  790. }
  791. }
  792. void Entity::setMountRotation(const EulerF& rotOffset)
  793. {
  794. if (isMounted())
  795. {
  796. MatrixF temp, imat, xmat, ymat, zmat;
  797. Point3F radRot = Point3F(mDegToRad(rotOffset.x), mDegToRad(rotOffset.y), mDegToRad(rotOffset.z));
  798. xmat.set(EulerF(radRot.x, 0, 0));
  799. ymat.set(EulerF(0.0f, radRot.y, 0.0f));
  800. zmat.set(EulerF(0, 0, radRot.z));
  801. imat.mul(zmat, xmat);
  802. temp.mul(imat, ymat);
  803. temp.setColumn(3, mMount.xfm.getPosition());
  804. mMount.xfm = temp;
  805. setMaskBits(MountedMask);
  806. }
  807. }
  808. //
  809. void Entity::getCameraTransform(F32* pos, MatrixF* mat)
  810. {
  811. Vector<CameraInterface*> updaters = getComponents<CameraInterface>();
  812. for (Vector<CameraInterface*>::iterator it = updaters.begin(); it != updaters.end(); it++)
  813. {
  814. if ((*it)->getCameraTransform(pos, mat))
  815. {
  816. return;
  817. }
  818. }
  819. }
  820. void Entity::getMountTransform(S32 index, const MatrixF &xfm, MatrixF *outMat)
  821. {
  822. RenderComponentInterface* renderInterface = getComponent<RenderComponentInterface>();
  823. if (renderInterface)
  824. {
  825. renderInterface->getShapeInstance()->animate();
  826. S32 nodeCount = renderInterface->getShapeInstance()->getShape()->nodes.size();
  827. if (index >= 0 && index < nodeCount)
  828. {
  829. MatrixF mountTransform = renderInterface->getShapeInstance()->mNodeTransforms[index];
  830. mountTransform.mul(xfm);
  831. const Point3F& scale = getScale();
  832. // The position of the mount point needs to be scaled.
  833. Point3F position = mountTransform.getPosition();
  834. position.convolve(scale);
  835. mountTransform.setPosition(position);
  836. // Also we would like the object to be scaled to the model.
  837. outMat->mul(mObjToWorld, mountTransform);
  838. return;
  839. }
  840. }
  841. // Then let SceneObject handle it.
  842. Parent::getMountTransform(index, xfm, outMat);
  843. }
  844. void Entity::getRenderMountTransform(F32 delta, S32 index, const MatrixF &xfm, MatrixF *outMat)
  845. {
  846. RenderComponentInterface* renderInterface = getComponent<RenderComponentInterface>();
  847. if (renderInterface && renderInterface->getShapeInstance())
  848. {
  849. renderInterface->getShapeInstance()->animate();
  850. S32 nodeCount = renderInterface->getShapeInstance()->getShape()->nodes.size();
  851. if (index >= 0 && index < nodeCount)
  852. {
  853. MatrixF mountTransform = renderInterface->getShapeInstance()->mNodeTransforms[index];
  854. mountTransform.mul(xfm);
  855. const Point3F& scale = getScale();
  856. // The position of the mount point needs to be scaled.
  857. Point3F position = mountTransform.getPosition();
  858. position.convolve(scale);
  859. mountTransform.setPosition(position);
  860. // Also we would like the object to be scaled to the model.
  861. outMat->mul(getRenderTransform(), mountTransform);
  862. return;
  863. }
  864. }
  865. // Then let SceneObject handle it.
  866. Parent::getMountTransform(index, xfm, outMat);
  867. }
  868. //
  869. //These basically just redirect to any collision behaviors we have
  870. bool Entity::castRay(const Point3F &start, const Point3F &end, RayInfo* info)
  871. {
  872. Vector<CastRayInterface*> updaters = getComponents<CastRayInterface>();
  873. for (Vector<CastRayInterface*>::iterator it = updaters.begin(); it != updaters.end(); it++)
  874. {
  875. if ((*it)->castRay(start, end, info))
  876. {
  877. return true;
  878. }
  879. }
  880. return false;
  881. }
  882. bool Entity::castRayRendered(const Point3F &start, const Point3F &end, RayInfo *info)
  883. {
  884. Vector<CastRayRenderedInterface*> updaters = getComponents<CastRayRenderedInterface>();
  885. for (Vector<CastRayRenderedInterface*>::iterator it = updaters.begin(); it != updaters.end(); it++)
  886. {
  887. if ((*it)->castRayRendered(start, end, info))
  888. {
  889. return true;
  890. }
  891. }
  892. return false;
  893. }
  894. bool Entity::buildPolyList(PolyListContext context, AbstractPolyList* polyList, const Box3F &box, const SphereF &sphere)
  895. {
  896. Con::errorf("Build Poly List not yet implemented as a passthrough for Entity");
  897. /*Vector<BuildPolyListInterface*> updaters = getComponents<BuildPolyListInterface>();
  898. for (Vector<BuildPolyListInterface*>::iterator it = updaters.begin(); it != updaters.end(); it++)
  899. {
  900. return (*it)->buildPolyList(context, polyList, box, sphere);
  901. }*/
  902. return false;
  903. }
  904. void Entity::buildConvex(const Box3F& box, Convex* convex)
  905. {
  906. Vector<BuildConvexInterface*> updaters = getComponents<BuildConvexInterface>();
  907. for (Vector<BuildConvexInterface*>::iterator it = updaters.begin(); it != updaters.end(); it++)
  908. {
  909. (*it)->buildConvex(box, convex);
  910. }
  911. }
  912. //
  913. // Mounting and heirarchy manipulation
  914. void Entity::mountObject(SceneObject* objB, const MatrixF& txfm)
  915. {
  916. Parent::mountObject(objB, -1, txfm);
  917. Parent::addObject(objB);
  918. }
  919. void Entity::mountObject(SceneObject *obj, S32 node, const MatrixF &xfm)
  920. {
  921. Parent::mountObject(obj, node, xfm);
  922. }
  923. void Entity::onMount(SceneObject *obj, S32 node)
  924. {
  925. deleteNotify(obj);
  926. // Are we mounting to a GameBase object?
  927. Entity *entityObj = dynamic_cast<Entity*>(obj);
  928. if (entityObj && entityObj->getControlObject() != this)
  929. processAfter(entityObj);
  930. if (!isGhost()) {
  931. setMaskBits(MountedMask);
  932. //TODO implement this callback
  933. //onMount_callback( this, obj, node );
  934. }
  935. }
  936. void Entity::onUnmount(SceneObject *obj, S32 node)
  937. {
  938. clearNotify(obj);
  939. Entity *entityObj = dynamic_cast<Entity*>(obj);
  940. if (entityObj && entityObj->getControlObject() != this)
  941. clearProcessAfter();
  942. if (!isGhost()) {
  943. setMaskBits(MountedMask);
  944. //TODO implement this callback
  945. //onUnmount_callback( this, obj, node );
  946. }
  947. }
  948. void Entity::setControllingClient(GameConnection* client)
  949. {
  950. if (isGhost() && gSFX3DWorld)
  951. {
  952. if (gSFX3DWorld->getListener() == this && !client && getControllingClient() && getControllingClient()->isConnectionToServer())
  953. {
  954. // We are the current listener and are no longer a controller object on the
  955. // connection, so clear our listener status.
  956. gSFX3DWorld->setListener(NULL);
  957. }
  958. else if (client && client->isConnectionToServer() && !getControllingObject())
  959. {
  960. // We're on the local client and not controlled by another object, so make
  961. // us the current SFX listener.
  962. gSFX3DWorld->setListener(this);
  963. }
  964. }
  965. Parent::setControllingClient(client);
  966. }
  967. //Heirarchy stuff
  968. void Entity::addObject(SimObject* object)
  969. {
  970. Component* component = dynamic_cast<Component*>(object);
  971. if (component)
  972. {
  973. addComponent(component);
  974. return;
  975. }
  976. Entity* e = dynamic_cast<Entity*>(object);
  977. if (e)
  978. {
  979. MatrixF offset;
  980. //offset.mul(getWorldTransform(), e->getWorldTransform());
  981. //check if we're mounting to a node on a shape we have
  982. String node = e->getDataField("mountNode", NULL);
  983. if (!node.isEmpty())
  984. {
  985. RenderComponentInterface *renderInterface = getComponent<RenderComponentInterface>();
  986. if (renderInterface)
  987. {
  988. TSShape* shape = renderInterface->getShape();
  989. S32 nodeIdx = shape->findNode(node);
  990. mountObject(e, nodeIdx, MatrixF::Identity);
  991. }
  992. else
  993. {
  994. mountObject(e, MatrixF::Identity);
  995. }
  996. }
  997. else
  998. {
  999. /*Point3F posOffset = mPos - e->getPosition();
  1000. mPos = posOffset;
  1001. RotationF rotOffset = mRot - e->getRotation();
  1002. mRot = rotOffset;
  1003. setMaskBits(TransformMask);
  1004. mountObject(e, MatrixF::Identity);*/
  1005. mountObject(e, MatrixF::Identity);
  1006. }
  1007. //e->setMountOffset(e->getPosition() - getPosition());
  1008. //Point3F diff = getWorldTransform().toEuler() - e->getWorldTransform().toEuler();
  1009. //e->setMountRotation(Point3F(mRadToDeg(diff.x),mRadToDeg(diff.y),mRadToDeg(diff.z)));
  1010. //mountObject(e, offset);
  1011. }
  1012. else
  1013. {
  1014. SceneObject* so = dynamic_cast<SceneObject*>(object);
  1015. if (so)
  1016. {
  1017. //get the difference and build it as our offset!
  1018. Point3F posOffset = so->getPosition() - mPos;
  1019. RotationF rotOffset = RotationF(so->getTransform()) - mRot;
  1020. MatrixF offset = rotOffset.asMatrixF();
  1021. offset.setPosition(posOffset);
  1022. mountObject(so, offset);
  1023. return;
  1024. }
  1025. }
  1026. Parent::addObject(object);
  1027. }
  1028. void Entity::removeObject(SimObject* object)
  1029. {
  1030. Entity* e = dynamic_cast<Entity*>(object);
  1031. if (e)
  1032. {
  1033. mPos = mPos + e->getPosition();
  1034. mRot = mRot + e->getRotation();
  1035. unmountObject(e);
  1036. setMaskBits(TransformMask);
  1037. }
  1038. else
  1039. {
  1040. SceneObject* so = dynamic_cast<SceneObject*>(object);
  1041. if (so)
  1042. unmountObject(so);
  1043. }
  1044. Parent::removeObject(object);
  1045. }
  1046. bool Entity::addComponent(Component *comp)
  1047. {
  1048. if (comp == NULL)
  1049. return false;
  1050. //double-check were not re-adding anything
  1051. mComponents.push_back(comp);
  1052. // Register the component with this owner.
  1053. comp->setOwner(this);
  1054. comp->setIsServerObject(isServerObject());
  1055. //if we've already been added and this is being added after the fact(at runtime),
  1056. //then just go ahead and call it's onComponentAdd so it can get to work
  1057. //if (mInitialized)
  1058. {
  1059. comp->onComponentAdd();
  1060. if (comp->isNetworked())
  1061. {
  1062. NetworkedComponent netComp;
  1063. netComp.componentIndex = mComponents.size() - 1;
  1064. netComp.updateState = NetworkedComponent::Adding;
  1065. netComp.updateMaskBits = -1;
  1066. mNetworkedComponents.push_back(netComp);
  1067. setMaskBits(AddComponentsMask);
  1068. setMaskBits(ComponentsUpdateMask);
  1069. }
  1070. }
  1071. onComponentAdded.trigger(comp);
  1072. return true;
  1073. }
  1074. SimObject* Entity::findObjectByInternalName(StringTableEntry internalName, bool searchChildren)
  1075. {
  1076. for (U32 i = 0; i < mComponents.size(); i++)
  1077. {
  1078. if (mComponents[i]->getInternalName() == internalName)
  1079. {
  1080. return mComponents[i];
  1081. }
  1082. }
  1083. return Parent::findObjectByInternalName(internalName, searchChildren);
  1084. }
  1085. //////////////////////////////////////////////////////////////////////////
  1086. bool Entity::removeComponent(Component *comp, bool deleteComponent)
  1087. {
  1088. if (comp == NULL)
  1089. return false;
  1090. if(mComponents.remove(comp))
  1091. {
  1092. AssertFatal(comp->isProperlyAdded(), "Don't know how but a component is not registered w/ the sim");
  1093. //setComponentsDirty();
  1094. onComponentRemoved.trigger(comp);
  1095. comp->onComponentRemove(); //in case the behavior needs to do cleanup on the owner
  1096. comp->setOwner(NULL);
  1097. if (deleteComponent)
  1098. comp->safeDeleteObject();
  1099. return true;
  1100. }
  1101. return false;
  1102. }
  1103. //////////////////////////////////////////////////////////////////////////
  1104. //NOTE:
  1105. //The actor class calls this and flags the deletion of the behaviors to false so that behaviors that should no longer be attached during
  1106. //a network update will indeed be removed from the object. The reason it doesn't delete them is because when clearing the local behavior
  1107. //list, it would delete them, purging the ghost, and causing a crash when the unpack update tried to fetch any existing behaviors' ghosts
  1108. //to re-add them. Need to implement a clean clear function that will clear the local list, and only delete unused behaviors during an update.
  1109. void Entity::clearComponents(bool deleteComponents)
  1110. {
  1111. bool srv = isServerObject();
  1112. if (!deleteComponents)
  1113. {
  1114. while (mComponents.size() > 0)
  1115. {
  1116. removeComponent(mComponents.first(), deleteComponents);
  1117. }
  1118. }
  1119. else
  1120. {
  1121. while (mComponents.size() > 0)
  1122. {
  1123. Component* comp = mComponents.first();
  1124. if (comp)
  1125. {
  1126. comp->onComponentRemove(); //in case the behavior needs to do cleanup on the owner
  1127. bool removed = mComponents.remove(comp);
  1128. //we only need to delete them on the server side. they'll be cleaned up on the client side
  1129. //via the ghosting system for us
  1130. if (isServerObject())
  1131. comp->deleteObject();
  1132. }
  1133. }
  1134. }
  1135. }
  1136. //////////////////////////////////////////////////////////////////////////
  1137. Component *Entity::getComponent(const U32 index) const
  1138. {
  1139. if (index < mComponents.size())
  1140. return mComponents[index];
  1141. return NULL;
  1142. }
  1143. Component *Entity::getComponent(String componentType)
  1144. {
  1145. for (U32 i = 0; i < mComponents.size(); i++)
  1146. {
  1147. Component* comp = mComponents[i];
  1148. /*String namespaceName = comp->getNamespace()->mName;
  1149. //check our namespace first
  1150. if (namespaceName == componentType)
  1151. {
  1152. return comp;
  1153. }
  1154. else
  1155. {*/
  1156. //lets scan up, just to be sure
  1157. Namespace *NS = comp->getNamespace();
  1158. //we shouldn't ever go past Component into net object, as we're no longer dealing with component classes
  1159. while (dStrcmp(NS->getName(), "SimObject"))
  1160. {
  1161. String namespaceName = NS->getName();
  1162. if (namespaceName == componentType)
  1163. {
  1164. return comp;
  1165. }
  1166. else
  1167. {
  1168. NS = NS->getParent();
  1169. }
  1170. }
  1171. //}
  1172. }
  1173. return NULL;
  1174. }
  1175. void Entity::onInspect()
  1176. {
  1177. Vector<EditorInspectInterface*> updaters = getComponents<EditorInspectInterface>();
  1178. for (Vector<EditorInspectInterface*>::iterator it = updaters.begin(); it != updaters.end(); it++)
  1179. {
  1180. (*it)->onInspect();
  1181. }
  1182. }
  1183. void Entity::onEndInspect()
  1184. {
  1185. Vector<EditorInspectInterface*> updaters = getComponents<EditorInspectInterface>();
  1186. for (Vector<EditorInspectInterface*>::iterator it = updaters.begin(); it != updaters.end(); it++) {
  1187. (*it)->onEndInspect();
  1188. }
  1189. GuiTreeViewCtrl *editorTree = dynamic_cast<GuiTreeViewCtrl*>(Sim::findObject("EditorTree"));
  1190. if (!editorTree)
  1191. return;
  1192. S32 componentItemIdx = editorTree->findItemByName("Components");
  1193. editorTree->removeItem(componentItemIdx, false);
  1194. }
  1195. static void writeTabs(Stream &stream, U32 count)
  1196. {
  1197. char tab[] = " ";
  1198. while (count--)
  1199. stream.write(3, (void*)tab);
  1200. }
  1201. void Entity::write(Stream &stream, U32 tabStop, U32 flags)
  1202. {
  1203. // Do *not* call parent on this
  1204. /*VectorPtr<ComponentObject *> &componentList = lockComponentList();
  1205. // export selected only?
  1206. if( ( flags & SelectedOnly ) && !isSelected() )
  1207. {
  1208. for( BehaviorObjectIterator i = componentList.begin(); i != componentList.end(); i++ )
  1209. (*i)->write(stream, tabStop, flags);
  1210. goto write_end;
  1211. }*/
  1212. //catch if we have any written behavior fields already in the file, and clear them. We don't need to double-up
  1213. //the entries for no reason.
  1214. /*if(getFieldDictionary())
  1215. {
  1216. //get our dynamic field count, then parse through them to see if they're a behavior or not
  1217. //reset it
  1218. SimFieldDictionary* fieldDictionary = getFieldDictionary();
  1219. SimFieldDictionaryIterator itr(fieldDictionary);
  1220. for (S32 i = 0; i < fieldDictionary->getNumFields(); i++)
  1221. {
  1222. if (!(*itr))
  1223. break;
  1224. SimFieldDictionary::Entry* entry = *itr;
  1225. if(strstr(entry->slotName, "_behavior"))
  1226. {
  1227. entry->slotName = "";
  1228. entry->value = "";
  1229. }
  1230. ++itr;
  1231. }
  1232. }*/
  1233. //all existing written behavior fields should be cleared. now write the object block
  1234. writeTabs(stream, tabStop);
  1235. char buffer[1024];
  1236. dSprintf(buffer, sizeof(buffer), "new %s(%s) {\r\n", getClassName(), getName() ? getName() : "");
  1237. stream.write(dStrlen(buffer), buffer);
  1238. writeFields(stream, tabStop + 1);
  1239. stream.write(1, "\n");
  1240. ////first, write out our behavior objects
  1241. // NOW we write the behavior fields proper
  1242. if (mComponents.size() > 0)
  1243. {
  1244. // Pack out the behaviors into fields
  1245. U32 i = 0;
  1246. for (U32 i = 0; i < mComponents.size(); i++)
  1247. {
  1248. writeTabs(stream, tabStop + 1);
  1249. char buffer[1024];
  1250. dSprintf(buffer, sizeof(buffer), "new %s() {\r\n", mComponents[i]->getClassName());
  1251. stream.write(dStrlen(buffer), buffer);
  1252. //bi->writeFields( stream, tabStop + 2 );
  1253. mComponents[i]->packToStream(stream, tabStop + 2, i - 1, flags);
  1254. writeTabs(stream, tabStop + 1);
  1255. stream.write(4, "};\r\n");
  1256. }
  1257. }
  1258. //
  1259. //if (size() > 0)
  1260. // stream.write(2, "\r\n");
  1261. for (U32 i = 0; i < size(); i++)
  1262. {
  1263. SimObject* child = (*this)[i];
  1264. if (child->getCanSave())
  1265. child->write(stream, tabStop + 1, flags);
  1266. }
  1267. //stream.write(2, "\r\n");
  1268. writeTabs(stream, tabStop);
  1269. stream.write(4, "};\r\n");
  1270. //write_end:
  1271. //unlockComponentList();
  1272. }
  1273. SimObject* Entity::getTamlChild(const U32 childIndex) const
  1274. {
  1275. // Sanity!
  1276. AssertFatal(childIndex < getTamlChildCount(), "SimSet::getTamlChild() - Child index is out of range.");
  1277. // For when the assert is not used.
  1278. if (childIndex >= getTamlChildCount())
  1279. return NULL;
  1280. //we always order components first, child objects second
  1281. if (childIndex >= getComponentCount())
  1282. return at(childIndex - getComponentCount());
  1283. else
  1284. return getComponent(childIndex);
  1285. }
  1286. //
  1287. void Entity::onCameraScopeQuery(NetConnection* connection, CameraScopeQuery* query)
  1288. {
  1289. // Object itself is in scope.
  1290. Parent::onCameraScopeQuery(connection, query);
  1291. if (CameraInterface* cI = getComponent<CameraInterface>())
  1292. {
  1293. cI->onCameraScopeQuery(connection, query);
  1294. }
  1295. }
  1296. //
  1297. void Entity::setObjectBox(const Box3F& objBox)
  1298. {
  1299. mObjBox = objBox;
  1300. resetWorldBox();
  1301. if (isServerObject())
  1302. setMaskBits(BoundsMask);
  1303. }
  1304. void Entity::updateContainer()
  1305. {
  1306. PROFILE_SCOPE(Entity_updateContainer);
  1307. // Update container drag and buoyancy properties
  1308. containerInfo.box = getWorldBox();
  1309. //containerInfo.mass = mMass;
  1310. getContainer()->findObjects(containerInfo.box, WaterObjectType | PhysicalZoneObjectType, findRouter, &containerInfo);
  1311. //mWaterCoverage = info.waterCoverage;
  1312. //mLiquidType = info.liquidType;
  1313. //mLiquidHeight = info.waterHeight;
  1314. //setCurrentWaterObject( info.waterObject );
  1315. // This value might be useful as a datablock value,
  1316. // This is what allows the player to stand in shallow water (below this coverage)
  1317. // without jiggling from buoyancy
  1318. /*if (info.waterCoverage >= 0.25f)
  1319. {
  1320. // water viscosity is used as drag for in water.
  1321. // ShapeBaseData drag is used for drag outside of water.
  1322. // Combine these two components to calculate this ShapeBase object's
  1323. // current drag.
  1324. mDrag = (info.waterCoverage * info.waterViscosity) +
  1325. (1.0f - info.waterCoverage) * mDrag;
  1326. //mBuoyancy = (info.waterDensity / mDataBlock->density) * info.waterCoverage;
  1327. }
  1328. //mAppliedForce = info.appliedForce;
  1329. mGravityMod = info.gravityScale;*/
  1330. }
  1331. //
  1332. void Entity::notifyComponents(String signalFunction, String argA, String argB, String argC, String argD, String argE)
  1333. {
  1334. for (U32 i = 0; i < mComponents.size(); i++)
  1335. {
  1336. // We can do this because both are in the string table
  1337. Component *comp = mComponents[i];
  1338. if (comp->isActive())
  1339. {
  1340. if (comp->isMethod(signalFunction))
  1341. Con::executef(comp, signalFunction, argA, argB, argC, argD, argE);
  1342. }
  1343. }
  1344. }
  1345. void Entity::setComponentsDirty()
  1346. {
  1347. bool tmp = true;
  1348. /*if (mToLoadComponents.empty())
  1349. mStartComponentUpdate = true;
  1350. //we need to build a list of behaviors that need to be pushed across the network
  1351. for (U32 i = 0; i < mComponents.size(); i++)
  1352. {
  1353. // We can do this because both are in the string table
  1354. Component *comp = mComponents[i];
  1355. if (comp->isNetworked())
  1356. {
  1357. bool unique = true;
  1358. for (U32 i = 0; i < mToLoadComponents.size(); i++)
  1359. {
  1360. if (mToLoadComponents[i]->getId() == comp->getId())
  1361. {
  1362. unique = false;
  1363. break;
  1364. }
  1365. }
  1366. if (unique)
  1367. mToLoadComponents.push_back(comp);
  1368. }
  1369. }
  1370. setMaskBits(ComponentsMask);*/
  1371. }
  1372. void Entity::setComponentDirty(Component *comp, bool forceUpdate)
  1373. {
  1374. bool found = false;
  1375. for (U32 i = 0; i < mComponents.size(); i++)
  1376. {
  1377. if (mComponents[i]->getId() == comp->getId())
  1378. {
  1379. mComponents[i]->setOwner(this);
  1380. return;
  1381. }
  1382. }
  1383. //if (!found)
  1384. // return;
  1385. //if(mToLoadComponents.empty())
  1386. // mStartComponentUpdate = true;
  1387. /*if (comp->isNetworked() || forceUpdate)
  1388. {
  1389. bool unique = true;
  1390. for (U32 i = 0; i < mToLoadComponents.size(); i++)
  1391. {
  1392. if (mToLoadComponents[i]->getId() == comp->getId())
  1393. {
  1394. unique = false;
  1395. break;
  1396. }
  1397. }
  1398. if (unique)
  1399. mToLoadComponents.push_back(comp);
  1400. }
  1401. setMaskBits(ComponentsMask);*/
  1402. }
  1403. DefineEngineMethod(Entity, mountObject, bool,
  1404. (SceneObject* objB, TransformF txfm), (MatrixF::Identity),
  1405. "@brief Mount objB to this object at the desired slot with optional transform.\n\n"
  1406. "@param objB Object to mount onto us\n"
  1407. "@param slot Mount slot ID\n"
  1408. "@param txfm (optional) mount offset transform\n"
  1409. "@return true if successful, false if failed (objB is not valid)")
  1410. {
  1411. if (objB)
  1412. {
  1413. //BUG: Unsure how it broke, but atm the default transform passed in here is rotated 180 degrees. This doesn't happen
  1414. //for the SceneObject mountobject method. Hackish, but for now, just default to a clean MatrixF::Identity
  1415. object->mountObject(objB, /*MatrixF::Identity*/txfm.getMatrix());
  1416. return true;
  1417. }
  1418. return false;
  1419. }
  1420. DefineEngineMethod(Entity, setMountOffset, void,
  1421. (Point3F posOffset), (Point3F(0, 0, 0)),
  1422. "@brief Mount objB to this object at the desired slot with optional transform.\n\n"
  1423. "@param objB Object to mount onto us\n"
  1424. "@param slot Mount slot ID\n"
  1425. "@param txfm (optional) mount offset transform\n"
  1426. "@return true if successful, false if failed (objB is not valid)")
  1427. {
  1428. object->setMountOffset(posOffset);
  1429. }
  1430. DefineEngineMethod(Entity, setMountRotation, void,
  1431. (EulerF rotOffset), (EulerF(0, 0, 0)),
  1432. "@brief Mount objB to this object at the desired slot with optional transform.\n\n"
  1433. "@param objB Object to mount onto us\n"
  1434. "@param slot Mount slot ID\n"
  1435. "@param txfm (optional) mount offset transform\n"
  1436. "@return true if successful, false if failed (objB is not valid)")
  1437. {
  1438. object->setMountRotation(rotOffset);
  1439. }
  1440. DefineEngineMethod(Entity, getMountTransform, TransformF, (), ,
  1441. "@brief Mount objB to this object at the desired slot with optional transform.\n\n"
  1442. "@param objB Object to mount onto us\n"
  1443. "@param slot Mount slot ID\n"
  1444. "@param txfm (optional) mount offset transform\n"
  1445. "@return true if successful, false if failed (objB is not valid)")
  1446. {
  1447. MatrixF mat;
  1448. object->getMountTransform(0, MatrixF::Identity, &mat);
  1449. return mat;
  1450. }
  1451. DefineEngineMethod(Entity, setBox, void,
  1452. (Point3F box), (Point3F(1, 1, 1)),
  1453. "@brief Mount objB to this object at the desired slot with optional transform.\n\n"
  1454. "@param objB Object to mount onto us\n"
  1455. "@param slot Mount slot ID\n"
  1456. "@param txfm (optional) mount offset transform\n"
  1457. "@return true if successful, false if failed (objB is not valid)")
  1458. {
  1459. object->setObjectBox(Box3F(-box, box));
  1460. }
  1461. /*DefineConsoleMethod(Entity, callOnComponents, void, (const char* functionName), ,
  1462. "Get the number of static fields on the object.\n"
  1463. "@return The number of static fields defined on the object.")
  1464. {
  1465. object->callOnComponents(functionName);
  1466. }
  1467. ConsoleMethod(Entity, callMethod, void, 3, 64, "(methodName, argi) Calls script defined method\n"
  1468. "@param methodName The method's name as a string\n"
  1469. "@param argi Any arguments to pass to the method\n"
  1470. "@return No return value"
  1471. "@note %obj.callMethod( %methodName, %arg1, %arg2, ... );\n")
  1472. {
  1473. object->callMethodArgList(argc - 1, argv + 2);
  1474. }
  1475. ConsoleMethod(Entity, addComponents, void, 2, 2, "() - Add all fielded behaviors\n"
  1476. "@return No return value")
  1477. {
  1478. object->addComponents();
  1479. }*/
  1480. ConsoleMethod(Entity, addComponent, bool, 3, 3, "(ComponentInstance bi) - Add a behavior to the object\n"
  1481. "@param bi The behavior instance to add"
  1482. "@return (bool success) Whether or not the behavior was successfully added")
  1483. {
  1484. Component *comp = dynamic_cast<Component *>(Sim::findObject(argv[2]));
  1485. if (comp != NULL)
  1486. {
  1487. bool success = object->addComponent(comp);
  1488. if (success)
  1489. {
  1490. //Placed here so we can differentiate against adding a new behavior during runtime, or when we load all
  1491. //fielded behaviors on mission load. This way, we can ensure that we only call the callback
  1492. //once everything is loaded. This avoids any problems with looking for behaviors that haven't been added yet, etc.
  1493. if (comp->isMethod("onBehaviorAdd"))
  1494. Con::executef(comp, "onBehaviorAdd");
  1495. return true;
  1496. }
  1497. }
  1498. return false;
  1499. }
  1500. ConsoleMethod(Entity, removeComponent, bool, 3, 4, "(ComponentInstance bi, [bool deleteBehavior = true])\n"
  1501. "@param bi The behavior instance to remove\n"
  1502. "@param deleteBehavior Whether or not to delete the behavior\n"
  1503. "@return (bool success) Whether the behavior was successfully removed")
  1504. {
  1505. bool deleteComponent = true;
  1506. if (argc > 3)
  1507. deleteComponent = dAtob(argv[3]);
  1508. return object->removeComponent(dynamic_cast<Component *>(Sim::findObject(argv[2])), deleteComponent);
  1509. }
  1510. ConsoleMethod(Entity, clearComponents, void, 2, 2, "() - Clear all behavior instances\n"
  1511. "@return No return value")
  1512. {
  1513. object->clearComponents();
  1514. }
  1515. ConsoleMethod(Entity, getComponentByIndex, S32, 3, 3, "(int index) - Gets a particular behavior\n"
  1516. "@param index The index of the behavior to get\n"
  1517. "@return (ComponentInstance bi) The behavior instance you requested")
  1518. {
  1519. Component *comp = object->getComponent(dAtoi(argv[2]));
  1520. return (comp != NULL) ? comp->getId() : 0;
  1521. }
  1522. DefineConsoleMethod(Entity, getComponent, S32, (String componentName), (""),
  1523. "Get the number of static fields on the object.\n"
  1524. "@return The number of static fields defined on the object.")
  1525. {
  1526. Component *comp = object->getComponent(componentName);
  1527. return (comp != NULL) ? comp->getId() : 0;
  1528. }
  1529. /*ConsoleMethod(Entity, getBehaviorByType, S32, 3, 3, "(string BehaviorTemplateName) - gets a behavior\n"
  1530. "@param BehaviorTemplateName The name of the template of the behavior instance you want\n"
  1531. "@return (ComponentInstance bi) The behavior instance you requested")
  1532. {
  1533. ComponentInstance *bInstance = object->getComponentByType(StringTable->insert(argv[2]));
  1534. return (bInstance != NULL) ? bInstance->getId() : 0;
  1535. }*/
  1536. /*ConsoleMethod(Entity, reOrder, bool, 3, 3, "(ComponentInstance inst, [int desiredIndex = 0])\n"
  1537. "@param inst The behavior instance you want to reorder\n"
  1538. "@param desiredIndex The index you want the behavior instance to be reordered to\n"
  1539. "@return (bool success) Whether or not the behavior instance was successfully reordered")
  1540. {
  1541. Component *inst = dynamic_cast<Component *>(Sim::findObject(argv[1]));
  1542. if (inst == NULL)
  1543. return false;
  1544. U32 idx = 0;
  1545. if (argc > 2)
  1546. idx = dAtoi(argv[2]);
  1547. return object->reOrder(inst, idx);
  1548. }*/
  1549. ConsoleMethod(Entity, getComponentCount, S32, 2, 2, "() - Get the count of behaviors on an object\n"
  1550. "@return (int count) The number of behaviors on an object")
  1551. {
  1552. return object->getComponentCount();
  1553. }
  1554. DefineConsoleMethod(Entity, setComponentDirty, void, (S32 componentID, bool forceUpdate), (0, false),
  1555. "Get the number of static fields on the object.\n"
  1556. "@return The number of static fields defined on the object.")
  1557. {
  1558. /*Component* comp;
  1559. if (Sim::findObject(componentID, comp))
  1560. object->setComponentDirty(comp, forceUpdate);*/
  1561. }
  1562. DefineConsoleMethod(Entity, getMoveVector, VectorF, (),,
  1563. "Get the number of static fields on the object.\n"
  1564. "@return The number of static fields defined on the object.")
  1565. {
  1566. if (object->getControllingClient() != NULL)
  1567. {
  1568. //fetch our last move
  1569. if (object->lastMove.x != 0 || object->lastMove.y != 0 || object->lastMove.z != 0)
  1570. return VectorF(object->lastMove.x, object->lastMove.y, object->lastMove.z);
  1571. }
  1572. return VectorF::Zero;
  1573. }
  1574. DefineConsoleMethod(Entity, getMoveRotation, VectorF, (), ,
  1575. "Get the number of static fields on the object.\n"
  1576. "@return The number of static fields defined on the object.")
  1577. {
  1578. if(object->getControllingClient() != NULL)
  1579. {
  1580. //fetch our last move
  1581. if (object->lastMove.pitch != 0 || object->lastMove.roll != 0 || object->lastMove.yaw != 0)
  1582. return VectorF(object->lastMove.pitch, object->lastMove.roll, object->lastMove.yaw);
  1583. }
  1584. return VectorF::Zero;
  1585. }
  1586. DefineConsoleMethod(Entity, getMoveTrigger, bool, (S32 triggerNum), (0),
  1587. "Get the number of static fields on the object.\n"
  1588. "@return The number of static fields defined on the object.")
  1589. {
  1590. if (object->getControllingClient() != NULL && triggerNum < MaxTriggerKeys)
  1591. {
  1592. return object->lastMove.trigger[triggerNum];
  1593. }
  1594. return false;
  1595. }
  1596. DefineEngineMethod(Entity, getForwardVector, VectorF, (), ,
  1597. "Get the direction this object is facing.\n"
  1598. "@return a vector indicating the direction this object is facing.\n"
  1599. "@note This is the object's y axis.")
  1600. {
  1601. VectorF forVec = object->getTransform().getForwardVector();
  1602. return forVec;
  1603. }
  1604. DefineConsoleMethod(Entity, setForwardVector, void, (VectorF newForward), (VectorF(0,0,0)),
  1605. "Get the number of static fields on the object.\n"
  1606. "@return The number of static fields defined on the object.")
  1607. {
  1608. object->setForwardVector(newForward);
  1609. }
  1610. DefineConsoleMethod(Entity, lookAt, void, (Point3F lookPosition),,
  1611. "Get the number of static fields on the object.\n"
  1612. "@return The number of static fields defined on the object.")
  1613. {
  1614. //object->setForwardVector(newForward);
  1615. }
  1616. DefineConsoleMethod(Entity, rotateTo, void, (Point3F lookPosition, F32 degreePerSecond), (1.0),
  1617. "Get the number of static fields on the object.\n"
  1618. "@return The number of static fields defined on the object.")
  1619. {
  1620. //object->setForwardVector(newForward);
  1621. }
  1622. DefineConsoleMethod(Entity, notify, void, (String signalFunction, String argA, String argB, String argC, String argD, String argE),
  1623. ("", "", "", "", "", ""),
  1624. "Triggers a signal call to all components for a certain function.")
  1625. {
  1626. if (signalFunction == String(""))
  1627. return;
  1628. object->notifyComponents(signalFunction, argA, argB, argC, argD, argE);
  1629. }
  1630. DefineConsoleFunction(findEntitiesByTag, const char*, (SimGroup* searchingGroup, String tags), (nullAsType<SimGroup*>(), ""),
  1631. "Finds all entities that have the provided tags.\n"
  1632. "@param searchingGroup The SimGroup to search inside. If null, we'll search the entire dictionary(this can be slow!).\n"
  1633. "@param tags Word delimited list of tags to search for. If multiple tags are included, the list is eclusively parsed, requiring all tags provided to be found on an entity for a match.\n"
  1634. "@return A word list of IDs of entities that match the tag search terms.")
  1635. {
  1636. //if (tags.isEmpty())
  1637. return "";
  1638. /*if (searchingGroup == nullptr)
  1639. {
  1640. searchingGroup = Sim::getRootGroup();
  1641. }
  1642. StringTableEntry entityStr = StringTable->insert("Entity");
  1643. std::thread threadBob;
  1644. std::thread::id a = threadBob.get_id();
  1645. std::thread::id b = std::this_thread::get_id().;
  1646. if (a == b)
  1647. {
  1648. //do
  1649. }
  1650. for (SimGroup::iterator itr = searchingGroup->begin(); itr != searchingGroup->end(); itr++)
  1651. {
  1652. Entity* ent = dynamic_cast<Entity*>((*itr));
  1653. if (ent != nullptr)
  1654. {
  1655. ent->mTags.
  1656. }
  1657. }
  1658. object->notifyComponents(signalFunction, argA, argB, argC, argD, argE);*/
  1659. }