EntityObject.cpp 50 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. // Description : StaticObject implementation.
  9. #include "EditorDefs.h"
  10. #include "EntityObject.h"
  11. // AzToolsFramework
  12. #include <AzToolsFramework/API/ComponentEntityObjectBus.h>
  13. // Editor
  14. #include "Settings.h"
  15. #include "Viewport.h"
  16. #include "Include/IObjectManager.h"
  17. #include "Objects/ObjectManager.h"
  18. #include "ViewManager.h"
  19. #include "AnimationContext.h"
  20. #include "HitContext.h"
  21. static constexpr int VIEW_DISTANCE_MULTIPLIER_MAX = 100;
  22. namespace
  23. {
  24. CEntityObject* s_pPropertyPanelEntityObject = nullptr;
  25. };
  26. //////////////////////////////////////////////////////////////////////////
  27. CEntityObject::CEntityObject()
  28. {
  29. m_bLoadFailed = false;
  30. m_box.min.Set(0, 0, 0);
  31. m_box.max.Set(0, 0, 0);
  32. m_proximityRadius = 0;
  33. m_innerRadius = 0;
  34. m_outerRadius = 0;
  35. m_boxSizeX = 1;
  36. m_boxSizeY = 1;
  37. m_boxSizeZ = 1;
  38. m_bProjectInAllDirs = false;
  39. m_bProjectorHasTexture = false;
  40. m_bDisplayBBox = true;
  41. m_bBBoxSelection = false;
  42. m_bDisplaySolidBBox = false;
  43. m_bDisplayAbsoluteRadius = false;
  44. m_bIconOnTop = false;
  45. m_bDisplayArrow = false;
  46. m_entityId = 0;
  47. m_bVisible = true;
  48. m_bCalcPhysics = true;
  49. m_bLight = false;
  50. m_bAreaLight = false;
  51. m_fAreaWidth = 1;
  52. m_fAreaHeight = 1;
  53. m_fAreaLightSize = 0.05f;
  54. m_bBoxProjectedCM = false;
  55. m_fBoxWidth = 1;
  56. m_fBoxHeight = 1;
  57. m_fBoxLength = 1;
  58. m_bEnableReload = true;
  59. m_lightColor = Vec3(1, 1, 1);
  60. SetColor(QColor(255, 255, 0));
  61. // Init Variables.
  62. mv_castShadow = true;
  63. mv_outdoor = false;
  64. mv_recvWind = false;
  65. mv_renderNearest = false;
  66. mv_noDecals = false;
  67. mv_createdThroughPool = false;
  68. mv_obstructionMultiplier = 1.f;
  69. mv_obstructionMultiplier.SetLimits(0.f, 1.f, 0.01f);
  70. mv_hiddenInGame = false;
  71. mv_ratioLOD = 100;
  72. mv_viewDistanceMultiplier = 1.0f;
  73. mv_ratioLOD.SetLimits(0, 255);
  74. mv_viewDistanceMultiplier.SetLimits(0.0f, VIEW_DISTANCE_MULTIPLIER_MAX);
  75. m_physicsState = nullptr;
  76. m_attachmentType = eAT_Pivot;
  77. // cache all the variable callbacks, must match order of enum defined in header
  78. m_onSetCallbacksCache.emplace_back([this](IVariable* var) { OnAreaHeightChange(var); });
  79. m_onSetCallbacksCache.emplace_back([this](IVariable* var) { OnAreaLightChange(var); });
  80. m_onSetCallbacksCache.emplace_back([this](IVariable* var) { OnAreaLightSizeChange(var); });
  81. m_onSetCallbacksCache.emplace_back([this](IVariable* var) { OnAreaWidthChange(var); });
  82. m_onSetCallbacksCache.emplace_back([this](IVariable* var) { OnBoxHeightChange(var); });
  83. m_onSetCallbacksCache.emplace_back([this](IVariable* var) { OnBoxLengthChange(var); });
  84. m_onSetCallbacksCache.emplace_back([this](IVariable* var) { OnBoxProjectionChange(var); });
  85. m_onSetCallbacksCache.emplace_back([this](IVariable* var) { OnBoxSizeXChange(var); });
  86. m_onSetCallbacksCache.emplace_back([this](IVariable* var) { OnBoxSizeYChange(var); });
  87. m_onSetCallbacksCache.emplace_back([this](IVariable* var) { OnBoxSizeZChange(var); });
  88. m_onSetCallbacksCache.emplace_back([this](IVariable* var) { OnBoxWidthChange(var); });
  89. m_onSetCallbacksCache.emplace_back([this](IVariable* var) { OnColorChange(var); });
  90. m_onSetCallbacksCache.emplace_back([this](IVariable* var) { OnInnerRadiusChange(var); });
  91. m_onSetCallbacksCache.emplace_back([this](IVariable* var) { OnOuterRadiusChange(var); });
  92. m_onSetCallbacksCache.emplace_back([this](IVariable* var) { OnProjectInAllDirsChange(var); });
  93. m_onSetCallbacksCache.emplace_back([this](IVariable* var) { OnProjectorFOVChange(var); });
  94. m_onSetCallbacksCache.emplace_back([this](IVariable* var) { OnProjectorTextureChange(var); });
  95. m_onSetCallbacksCache.emplace_back([this](IVariable* var) { OnRadiusChange(var); });
  96. }
  97. CEntityObject::~CEntityObject()
  98. {
  99. }
  100. //////////////////////////////////////////////////////////////////////////
  101. void CEntityObject::InitVariables()
  102. {
  103. mv_castShadow.SetFlags(mv_castShadow.GetFlags() | IVariable::UI_INVISIBLE);
  104. AddVariable(mv_outdoor, "OutdoorOnly", tr("Outdoor Only"));
  105. AddVariable(mv_castShadow, "CastShadow", tr("Cast Shadow"));
  106. AddVariable(mv_ratioLOD, "LodRatio");
  107. AddVariable(mv_viewDistanceMultiplier, "ViewDistanceMultiplier");
  108. AddVariable(mv_hiddenInGame, "HiddenInGame");
  109. AddVariable(mv_recvWind, "RecvWind", tr("Receive Wind"));
  110. // [artemk]: Add RenderNearest entity param because of animator request.
  111. // This will cause that slot zero is rendered with ENTITY_SLOT_RENDER_NEAREST flag raised.
  112. AddVariable(mv_renderNearest, "RenderNearest");
  113. mv_renderNearest.SetDescription("Used to eliminate z-buffer artifacts when rendering from first person view");
  114. AddVariable(mv_noDecals, "NoStaticDecals");
  115. AddVariable(mv_createdThroughPool, "CreatedThroughPool", tr("Created Through Pool"));
  116. AddVariable(mv_obstructionMultiplier, "ObstructionMultiplier", tr("Obstruction Multiplier"));
  117. }
  118. //////////////////////////////////////////////////////////////////////////&
  119. void CEntityObject::Done()
  120. {
  121. DeleteEntity();
  122. ReleaseEventTargets();
  123. RemoveAllEntityLinks();
  124. CBaseObject::Done();
  125. }
  126. //////////////////////////////////////////////////////////////////////////
  127. void CEntityObject::FreeGameData()
  128. {
  129. DeleteEntity();
  130. }
  131. //////////////////////////////////////////////////////////////////////////
  132. bool CEntityObject::Init(IEditor* pEditor, CBaseObject* pPrev, const QString& file)
  133. {
  134. CBaseObject::Init(pEditor, pPrev, file);
  135. if (pPrev)
  136. {
  137. CEntityObject* pPreviousEntity = ( CEntityObject* )pPrev;
  138. // Clone Properties.
  139. if (pPreviousEntity->m_pProperties)
  140. {
  141. m_pProperties = CloneProperties(pPreviousEntity->m_pProperties);
  142. }
  143. if (pPreviousEntity->m_pProperties2)
  144. {
  145. m_pProperties2 = CloneProperties(pPreviousEntity->m_pProperties2);
  146. }
  147. mv_createdThroughPool = pPreviousEntity->mv_createdThroughPool;
  148. }
  149. else if (!file.isEmpty())
  150. {
  151. SetUniqueName(file);
  152. m_entityClass = file;
  153. }
  154. ResetCallbacks();
  155. return true;
  156. }
  157. //////////////////////////////////////////////////////////////////////////
  158. /*static*/ CEntityObject* CEntityObject::FindFromEntityId(const AZ::EntityId& id)
  159. {
  160. CEntityObject* retEntity = nullptr;
  161. AzToolsFramework::ComponentEntityEditorRequestBus::EventResult(retEntity, id, &AzToolsFramework::ComponentEntityEditorRequestBus::Events::GetSandboxObject);
  162. return retEntity;
  163. }
  164. //////////////////////////////////////////////////////////////////////////
  165. void CEntityObject::SetTransformDelegate(ITransformDelegate* pTransformDelegate)
  166. {
  167. CBaseObject::SetTransformDelegate(pTransformDelegate);
  168. if (this == s_pPropertyPanelEntityObject)
  169. {
  170. return;
  171. }
  172. ForceVariableUpdate();
  173. ResetCallbacks();
  174. }
  175. //////////////////////////////////////////////////////////////////////////
  176. bool CEntityObject::ConvertFromObject(CBaseObject* object)
  177. {
  178. CBaseObject::ConvertFromObject(object);
  179. if (qobject_cast<CEntityObject*>(object))
  180. {
  181. CEntityObject* pObject = ( CEntityObject* )object;
  182. mv_outdoor = pObject->mv_outdoor;
  183. mv_ratioLOD = pObject->mv_ratioLOD;
  184. mv_viewDistanceMultiplier = pObject->mv_viewDistanceMultiplier;
  185. mv_hiddenInGame = pObject->mv_hiddenInGame;
  186. mv_recvWind = pObject->mv_recvWind;
  187. mv_renderNearest = pObject->mv_renderNearest;
  188. mv_noDecals = pObject->mv_noDecals;
  189. mv_createdThroughPool = pObject->mv_createdThroughPool;
  190. mv_obstructionMultiplier = pObject->mv_obstructionMultiplier;
  191. return true;
  192. }
  193. return false;
  194. }
  195. //////////////////////////////////////////////////////////////////////////
  196. void CEntityObject::GetLocalBounds(AABB& box)
  197. {
  198. box = m_box;
  199. }
  200. //////////////////////////////////////////////////////////////////////////
  201. bool CEntityObject::HitTest(HitContext& hc)
  202. {
  203. if (!hc.b2DViewport)
  204. {
  205. // Test 3D viewport.
  206. }
  207. //////////////////////////////////////////////////////////////////////////
  208. if ((m_bDisplayBBox && gSettings.viewports.bShowTriggerBounds) || hc.b2DViewport || (m_bDisplayBBox && m_bBBoxSelection))
  209. {
  210. float hitEpsilon = hc.view->GetScreenScaleFactor(GetWorldPos()) * 0.01f;
  211. float hitDist;
  212. float fScale = GetScale().x;
  213. AABB boxScaled;
  214. boxScaled.min = m_box.min * fScale;
  215. boxScaled.max = m_box.max * fScale;
  216. Matrix34 invertWTM = GetWorldTM();
  217. invertWTM.Invert();
  218. Vec3 xformedRaySrc = invertWTM.TransformPoint(hc.raySrc);
  219. Vec3 xformedRayDir = invertWTM.TransformVector(hc.rayDir);
  220. xformedRayDir.Normalize();
  221. {
  222. Vec3 intPnt;
  223. if (m_bBBoxSelection)
  224. {
  225. // Check intersection with bbox.
  226. if (Intersect::Ray_AABB(xformedRaySrc, xformedRayDir, boxScaled, intPnt))
  227. {
  228. hc.dist = xformedRaySrc.GetDistance(intPnt);
  229. hc.object = this;
  230. return true;
  231. }
  232. }
  233. else
  234. {
  235. // Check intersection with bbox edges.
  236. if (Intersect::Ray_AABBEdge(xformedRaySrc, xformedRayDir, boxScaled, hitEpsilon, hitDist, intPnt))
  237. {
  238. hc.dist = xformedRaySrc.GetDistance(intPnt);
  239. hc.object = this;
  240. return true;
  241. }
  242. }
  243. }
  244. }
  245. return false;
  246. }
  247. //////////////////////////////////////////////////////////////////////////
  248. bool CEntityObject::HitTestRect(HitContext& hc)
  249. {
  250. bool bResult = CBaseObject::HitTestRect(hc);
  251. if (bResult)
  252. {
  253. hc.object = this;
  254. }
  255. return bResult;
  256. }
  257. //////////////////////////////////////////////////////////////////////////
  258. IVariable* CEntityObject::FindVariableInSubBlock(CVarBlockPtr& properties, IVariable* pSubBlockVar, const char* pVarName)
  259. {
  260. IVariable* pVar = pSubBlockVar ? pSubBlockVar->FindVariable(pVarName) : properties->FindVariable(pVarName);
  261. return pVar;
  262. }
  263. //////////////////////////////////////////////////////////////////////////
  264. void CEntityObject::AdjustLightProperties(CVarBlockPtr& properties, const char* pSubBlock)
  265. {
  266. IVariable* pSubBlockVar = pSubBlock ? properties->FindVariable(pSubBlock) : nullptr;
  267. if (IVariable* pRadius = FindVariableInSubBlock(properties, pSubBlockVar, "Radius"))
  268. {
  269. // The value of 0.01 was found through asking Crysis 2 designer
  270. // team.
  271. pRadius->SetLimits(0.01f, 100.0f, 0.0f, true, false);
  272. }
  273. if (IVariable* pBoxSizeX = FindVariableInSubBlock(properties, pSubBlockVar, "BoxSizeX"))
  274. {
  275. pBoxSizeX->SetLimits(0.01f, 100.0f, 0.0f, true, false);
  276. }
  277. if (IVariable* pBoxSizeY = FindVariableInSubBlock(properties, pSubBlockVar, "BoxSizeY"))
  278. {
  279. pBoxSizeY->SetLimits(0.01f, 100.0f, 0.0f, true, false);
  280. }
  281. if (IVariable* pBoxSizeZ = FindVariableInSubBlock(properties, pSubBlockVar, "BoxSizeZ"))
  282. {
  283. pBoxSizeZ->SetLimits(0.01f, 100.0f, 0.0f, true, false);
  284. }
  285. if (IVariable* pProjectorFov = FindVariableInSubBlock(properties, pSubBlockVar, "fProjectorFov"))
  286. {
  287. pProjectorFov->SetLimits(0.01f, 180.0f, 0.0f, true, true);
  288. }
  289. if (IVariable* pPlaneWidth = FindVariableInSubBlock(properties, pSubBlockVar, "fPlaneWidth"))
  290. {
  291. pPlaneWidth->SetLimits(0.01f, 10.0f, 0.0f, true, false);
  292. pPlaneWidth->SetHumanName("SourceWidth");
  293. }
  294. if (IVariable* pPlaneHeight = FindVariableInSubBlock(properties, pSubBlockVar, "fPlaneHeight"))
  295. {
  296. pPlaneHeight->SetLimits(0.01f, 10.0f, 0.0f, true, false);
  297. pPlaneHeight->SetHumanName("SourceDiameter");
  298. }
  299. // For backwards compatibility with old lights (avoids changing settings in Lua which will break loading compatibility).
  300. // Todo: Change the Lua property names on the next big light refactor.
  301. if (IVariable* pAreaLight = FindVariableInSubBlock(properties, pSubBlockVar, "bAreaLight"))
  302. {
  303. pAreaLight->SetHumanName("PlanarLight");
  304. }
  305. if (IVariable* pCastShadowVarLegacy = FindVariableInSubBlock(properties, pSubBlockVar, "bCastShadow"))
  306. {
  307. pCastShadowVarLegacy->SetFlags(pCastShadowVarLegacy->GetFlags() | IVariable::UI_INVISIBLE);
  308. const QString zeroPrefix("0");
  309. if (!pCastShadowVarLegacy->GetDisplayValue().startsWith(zeroPrefix))
  310. {
  311. pCastShadowVarLegacy->SetDisplayValue(zeroPrefix);
  312. }
  313. }
  314. if (IVariable* pFade = FindVariableInSubBlock(properties, pSubBlockVar, "vFadeDimensionsLeft"))
  315. {
  316. pFade->SetFlags(pFade->GetFlags() | IVariable::UI_INVISIBLE);
  317. }
  318. if (IVariable* pFade = FindVariableInSubBlock(properties, pSubBlockVar, "vFadeDimensionsRight"))
  319. {
  320. pFade->SetFlags(pFade->GetFlags() | IVariable::UI_INVISIBLE);
  321. }
  322. if (IVariable* pFade = FindVariableInSubBlock(properties, pSubBlockVar, "vFadeDimensionsNear"))
  323. {
  324. pFade->SetFlags(pFade->GetFlags() | IVariable::UI_INVISIBLE);
  325. }
  326. if (IVariable* pFade = FindVariableInSubBlock(properties, pSubBlockVar, "vFadeDimensionsFar"))
  327. {
  328. pFade->SetFlags(pFade->GetFlags() | IVariable::UI_INVISIBLE);
  329. }
  330. if (IVariable* pFade = FindVariableInSubBlock(properties, pSubBlockVar, "vFadeDimensionsTop"))
  331. {
  332. pFade->SetFlags(pFade->GetFlags() | IVariable::UI_INVISIBLE);
  333. }
  334. if (IVariable* pFade = FindVariableInSubBlock(properties, pSubBlockVar, "vFadeDimensionsBottom"))
  335. {
  336. pFade->SetFlags(pFade->GetFlags() | IVariable::UI_INVISIBLE);
  337. }
  338. if (IVariable* pSortPriority = FindVariableInSubBlock(properties, pSubBlockVar, "SortPriority"))
  339. {
  340. pSortPriority->SetLimits(0, 255, 1, true, true);
  341. }
  342. if (IVariable* pAttenFalloffMax = FindVariableInSubBlock(properties, pSubBlockVar, "fAttenuationFalloffMax"))
  343. {
  344. pAttenFalloffMax->SetLimits(0.0f, 1.0f, 1.0f / 255.0f, true, true);
  345. }
  346. if (IVariable* pVer = FindVariableInSubBlock(properties, pSubBlockVar, "_nVersion"))
  347. {
  348. int version = -1;
  349. pVer->Get(version);
  350. if (version == -1)
  351. {
  352. version++;
  353. pVer->Set(version);
  354. }
  355. }
  356. }
  357. //////////////////////////////////////////////////////////////////////////
  358. void CEntityObject::SetName(const QString& name)
  359. {
  360. if (name == GetName())
  361. {
  362. return;
  363. }
  364. const QString oldName = GetName();
  365. CBaseObject::SetName(name);
  366. }
  367. //////////////////////////////////////////////////////////////////////////
  368. void CEntityObject::SetSelected(bool bSelect)
  369. {
  370. CBaseObject::SetSelected(bSelect);
  371. if (bSelect)
  372. {
  373. UpdateLightProperty();
  374. }
  375. }
  376. template <typename T>
  377. struct IVariableType {};
  378. template <>
  379. struct IVariableType<bool>
  380. {
  381. enum
  382. {
  383. value = IVariable::BOOL
  384. };
  385. };
  386. template <>
  387. struct IVariableType<int>
  388. {
  389. enum
  390. {
  391. value = IVariable::INT
  392. };
  393. };
  394. template <>
  395. struct IVariableType<float>
  396. {
  397. enum
  398. {
  399. value = IVariable::FLOAT
  400. };
  401. };
  402. template <>
  403. struct IVariableType<QString>
  404. {
  405. enum
  406. {
  407. value = IVariable::STRING
  408. };
  409. };
  410. template <>
  411. struct IVariableType<Vec3>
  412. {
  413. enum
  414. {
  415. value = IVariable::VECTOR
  416. };
  417. };
  418. //////////////////////////////////////////////////////////////////////////
  419. void CEntityObject::Serialize(CObjectArchive& ar)
  420. {
  421. CBaseObject::Serialize(ar);
  422. XmlNodeRef xmlNode = ar.node;
  423. if (ar.bLoading)
  424. {
  425. // Load
  426. QString entityClass = m_entityClass;
  427. m_bLoadFailed = false;
  428. xmlNode->getAttr("EntityClass", entityClass);
  429. m_physicsState = xmlNode->findChild("PhysicsState");
  430. Vec3 angles;
  431. // Backward compatibility, with FarCry levels.
  432. if (xmlNode->getAttr("Angles", angles))
  433. {
  434. angles = DEG2RAD(angles);
  435. angles.z += gf_PI / 2;
  436. Quat quat;
  437. quat.SetRotationXYZ(Ang3(angles));
  438. SetRotation(quat);
  439. }
  440. // Load Event Targets.
  441. ReleaseEventTargets();
  442. XmlNodeRef eventTargets = xmlNode->findChild("EventTargets");
  443. if (eventTargets)
  444. {
  445. for (int i = 0; i < eventTargets->getChildCount(); i++)
  446. {
  447. XmlNodeRef eventTarget = eventTargets->getChild(i);
  448. CEntityEventTarget et;
  449. et.target = nullptr;
  450. GUID targetId = GUID_NULL;
  451. eventTarget->getAttr("TargetId", targetId);
  452. eventTarget->getAttr("Event", et.event);
  453. eventTarget->getAttr("SourceEvent", et.sourceEvent);
  454. m_eventTargets.emplace_back(AZStd::move(et));
  455. if (targetId != GUID_NULL)
  456. {
  457. ar.SetResolveCallback(
  458. this, targetId,
  459. [this,i](CBaseObject* object) { ResolveEventTarget(object, i); });
  460. }
  461. }
  462. }
  463. XmlNodeRef propsNode = xmlNode->findChild("Properties");
  464. XmlNodeRef props2Node = xmlNode->findChild("Properties2");
  465. QString attachmentType;
  466. xmlNode->getAttr("AttachmentType", attachmentType);
  467. if (attachmentType == "CharacterBone")
  468. {
  469. m_attachmentType = eAT_CharacterBone;
  470. }
  471. else
  472. {
  473. m_attachmentType = eAT_Pivot;
  474. }
  475. xmlNode->getAttr("AttachmentTarget", m_attachmentTarget);
  476. if (ar.bUndo)
  477. {
  478. RemoveAllEntityLinks();
  479. PostLoad(ar);
  480. }
  481. }
  482. else
  483. {
  484. if (m_attachmentType != eAT_Pivot)
  485. {
  486. if (m_attachmentType == eAT_CharacterBone)
  487. {
  488. xmlNode->setAttr("AttachmentType", "CharacterBone");
  489. }
  490. xmlNode->setAttr("AttachmentTarget", m_attachmentTarget.toUtf8().data());
  491. }
  492. // Saving.
  493. if (!m_entityClass.isEmpty())
  494. {
  495. xmlNode->setAttr("EntityClass", m_entityClass.toUtf8().data());
  496. }
  497. if (m_physicsState)
  498. {
  499. xmlNode->addChild(m_physicsState);
  500. }
  501. //! Save properties.
  502. if (m_pProperties)
  503. {
  504. XmlNodeRef propsNode = xmlNode->newChild("Properties");
  505. m_pProperties->Serialize(propsNode, ar.bLoading);
  506. }
  507. //! Save properties.
  508. if (m_pProperties2)
  509. {
  510. XmlNodeRef propsNode = xmlNode->newChild("Properties2");
  511. m_pProperties2->Serialize(propsNode, ar.bLoading);
  512. }
  513. // Save Event Targets.
  514. if (!m_eventTargets.empty())
  515. {
  516. XmlNodeRef eventTargets = xmlNode->newChild("EventTargets");
  517. for (int i = 0; i < m_eventTargets.size(); i++)
  518. {
  519. CEntityEventTarget& et = m_eventTargets[i];
  520. GUID targetId = GUID_NULL;
  521. if (et.target != nullptr)
  522. {
  523. targetId = et.target->GetId();
  524. }
  525. XmlNodeRef eventTarget = eventTargets->newChild("EventTarget");
  526. eventTarget->setAttr("TargetId", targetId);
  527. eventTarget->setAttr("Event", et.event.toUtf8().data());
  528. eventTarget->setAttr("SourceEvent", et.sourceEvent.toUtf8().data());
  529. }
  530. }
  531. // Save Entity Links.
  532. SaveLink(xmlNode);
  533. }
  534. }
  535. //////////////////////////////////////////////////////////////////////////
  536. void CEntityObject::PostLoad(CObjectArchive& ar)
  537. {
  538. //////////////////////////////////////////////////////////////////////////
  539. // Load Links.
  540. XmlNodeRef linksNode = ar.node->findChild("EntityLinks");
  541. LoadLink(linksNode, &ar);
  542. }
  543. //////////////////////////////////////////////////////////////////////////
  544. XmlNodeRef CEntityObject::Export([[maybe_unused]] const QString& levelPath, XmlNodeRef& xmlExportNode)
  545. {
  546. if (m_bLoadFailed)
  547. {
  548. return nullptr;
  549. }
  550. // Do not export entity with bad id.
  551. if (!m_entityId)
  552. {
  553. return XmlHelpers::CreateXmlNode("Temp");
  554. }
  555. // Export entities to entities.ini
  556. XmlNodeRef objNode = xmlExportNode->newChild("Entity");
  557. objNode->setAttr("Name", GetName().toUtf8().data());
  558. Vec3 pos = GetPos(), scale = GetScale();
  559. Quat rotate = GetRotation();
  560. if (GetParent())
  561. {
  562. if (qobject_cast<CEntityObject*>(GetParent()))
  563. {
  564. // Store parent entity id.
  565. CEntityObject* parentEntity = ( CEntityObject* )GetParent();
  566. if (parentEntity)
  567. {
  568. objNode->setAttr("ParentId", parentEntity->GetEntityId());
  569. if (m_attachmentType != eAT_Pivot)
  570. {
  571. if (m_attachmentType == eAT_CharacterBone)
  572. {
  573. objNode->setAttr("AttachmentType", "CharacterBone");
  574. }
  575. objNode->setAttr("AttachmentTarget", m_attachmentTarget.toUtf8().data());
  576. }
  577. }
  578. }
  579. else
  580. {
  581. // Export world coordinates.
  582. AffineParts ap;
  583. ap.SpectralDecompose(GetWorldTM());
  584. pos = ap.pos;
  585. rotate = ap.rot;
  586. scale = ap.scale;
  587. }
  588. }
  589. if (!IsEquivalent(pos, Vec3(0, 0, 0), 0))
  590. {
  591. objNode->setAttr("Pos", pos);
  592. }
  593. if (!rotate.IsIdentity())
  594. {
  595. objNode->setAttr("Rotate", rotate);
  596. }
  597. if (!IsEquivalent(scale, Vec3(1, 1, 1), 0))
  598. {
  599. objNode->setAttr("Scale", scale);
  600. }
  601. objNode->setTag("Entity");
  602. objNode->setAttr("EntityClass", m_entityClass.toUtf8().data());
  603. objNode->setAttr("EntityId", m_entityId);
  604. if (mv_ratioLOD != 100)
  605. {
  606. objNode->setAttr("LodRatio", ( int )mv_ratioLOD);
  607. }
  608. if (fabs(mv_viewDistanceMultiplier - 1.f) > FLT_EPSILON)
  609. {
  610. objNode->setAttr("ViewDistanceMultiplier", mv_viewDistanceMultiplier);
  611. }
  612. if (mv_recvWind)
  613. {
  614. objNode->setAttr("RecvWind", true);
  615. }
  616. if (mv_noDecals)
  617. {
  618. objNode->setAttr("NoDecals", true);
  619. }
  620. if (mv_outdoor)
  621. {
  622. objNode->setAttr("OutdoorOnly", true);
  623. }
  624. if (mv_hiddenInGame)
  625. {
  626. objNode->setAttr("HiddenInGame", true);
  627. }
  628. if (mv_createdThroughPool)
  629. {
  630. objNode->setAttr("CreatedThroughPool", true);
  631. }
  632. if (mv_obstructionMultiplier != 1.f)
  633. {
  634. objNode->setAttr("ObstructionMultiplier", (float)mv_obstructionMultiplier);
  635. }
  636. if (m_physicsState)
  637. {
  638. objNode->addChild(m_physicsState);
  639. }
  640. // Export Event Targets.
  641. if (!m_eventTargets.empty())
  642. {
  643. XmlNodeRef eventTargets = objNode->newChild("EventTargets");
  644. for (int i = 0; i < m_eventTargets.size(); i++)
  645. {
  646. CEntityEventTarget& et = m_eventTargets[i];
  647. int entityId = 0;
  648. if (et.target)
  649. {
  650. if (qobject_cast<CEntityObject*>(et.target))
  651. {
  652. entityId = (( CEntityObject* )et.target)->GetEntityId();
  653. }
  654. }
  655. XmlNodeRef eventTarget = eventTargets->newChild("EventTarget");
  656. eventTarget->setAttr("Target", entityId);
  657. eventTarget->setAttr("Event", et.event.toUtf8().data());
  658. eventTarget->setAttr("SourceEvent", et.sourceEvent.toUtf8().data());
  659. }
  660. }
  661. // Save Entity Links.
  662. if (!m_links.empty())
  663. {
  664. XmlNodeRef linksNode = objNode->newChild("EntityLinks");
  665. for (size_t i = 0, num = m_links.size(); i < num; i++)
  666. {
  667. if (m_links[i].target)
  668. {
  669. XmlNodeRef linkNode = linksNode->newChild("Link");
  670. linkNode->setAttr("TargetId", m_links[i].target->GetEntityId());
  671. linkNode->setAttr("Name", m_links[i].name.toUtf8().data());
  672. }
  673. }
  674. }
  675. //! Export properties.
  676. if (m_pProperties)
  677. {
  678. XmlNodeRef propsNode = objNode->newChild("Properties");
  679. m_pProperties->Serialize(propsNode, false);
  680. }
  681. //! Export properties.
  682. if (m_pProperties2)
  683. {
  684. XmlNodeRef propsNode = objNode->newChild("Properties2");
  685. m_pProperties2->Serialize(propsNode, false);
  686. }
  687. return objNode;
  688. }
  689. //////////////////////////////////////////////////////////////////////////
  690. void CEntityObject::OnEvent(ObjectEvent event)
  691. {
  692. CBaseObject::OnEvent(event);
  693. switch (event)
  694. {
  695. case EVENT_RELOAD_ENTITY:
  696. GetIEditor()->GetErrorReport()->SetCurrentValidatorObject(this);
  697. break;
  698. case EVENT_RELOAD_GEOM:
  699. GetIEditor()->GetErrorReport()->SetCurrentValidatorObject(this);
  700. break;
  701. case EVENT_FREE_GAME_DATA:
  702. FreeGameData();
  703. break;
  704. case EVENT_CONFIG_SPEC_CHANGE:
  705. {
  706. break;
  707. }
  708. default:
  709. break;
  710. }
  711. }
  712. //////////////////////////////////////////////////////////////////////////
  713. void CEntityObject::UpdateVisibility(bool bVisible)
  714. {
  715. CBaseObject::UpdateVisibility(bVisible);
  716. bool bVisibleWithSpec = bVisible;
  717. if (bVisibleWithSpec != static_cast<bool>(m_bVisible))
  718. {
  719. m_bVisible = bVisibleWithSpec;
  720. }
  721. size_t const numChildren = GetChildCount();
  722. for (size_t i = 0; i < numChildren; ++i)
  723. {
  724. CBaseObject* const pChildObject = GetChild(i);
  725. pChildObject->SetHidden(!m_bVisible);
  726. if (qobject_cast<CEntityObject*>(pChildObject))
  727. {
  728. pChildObject->UpdateVisibility(m_bVisible);
  729. }
  730. }
  731. };
  732. //////////////////////////////////////////////////////////////////////////
  733. IVariable* CEntityObject::GetLightVariable(const char* name0) const
  734. {
  735. if (m_pProperties2)
  736. {
  737. IVariable* pLightProperties = m_pProperties2->FindVariable("LightProperties_Base");
  738. if (pLightProperties)
  739. {
  740. for (int i = 0; i < pLightProperties->GetNumVariables(); ++i)
  741. {
  742. IVariable* pChild = pLightProperties->GetVariable(i);
  743. if (pChild == nullptr)
  744. {
  745. continue;
  746. }
  747. QString name(pChild->GetName());
  748. if (name == name0)
  749. {
  750. return pChild;
  751. }
  752. }
  753. }
  754. }
  755. return m_pProperties ? m_pProperties->FindVariable(name0) : nullptr;
  756. }
  757. //////////////////////////////////////////////////////////////////////////
  758. QString CEntityObject::GetLightAnimation() const
  759. {
  760. IVariable* pStyleGroup = GetLightVariable("Style");
  761. if (pStyleGroup)
  762. {
  763. for (int i = 0; i < pStyleGroup->GetNumVariables(); ++i)
  764. {
  765. IVariable* pChild = pStyleGroup->GetVariable(i);
  766. if (pChild == nullptr)
  767. {
  768. continue;
  769. }
  770. QString name(pChild->GetName());
  771. if (name == "lightanimation_LightAnimation")
  772. {
  773. QString lightAnimationName;
  774. pChild->Get(lightAnimationName);
  775. return lightAnimationName;
  776. }
  777. }
  778. }
  779. return "";
  780. }
  781. //////////////////////////////////////////////////////////////////////////
  782. void CEntityObject::ResolveEventTarget(CBaseObject* object, unsigned int index)
  783. {
  784. // Find target id.
  785. assert(index < m_eventTargets.size());
  786. if (object)
  787. {
  788. object->AddEventListener(this);
  789. }
  790. m_eventTargets[index].target = object;
  791. }
  792. //////////////////////////////////////////////////////////////////////////
  793. void CEntityObject::RemoveAllEntityLinks()
  794. {
  795. while (!m_links.empty())
  796. {
  797. RemoveEntityLink(static_cast<int>(m_links.size() - 1));
  798. }
  799. m_links.clear();
  800. SetModified(false);
  801. }
  802. //////////////////////////////////////////////////////////////////////////
  803. void CEntityObject::ReleaseEventTargets()
  804. {
  805. while (!m_eventTargets.empty())
  806. {
  807. RemoveEventTarget(static_cast<int>(m_eventTargets.size() - 1), false);
  808. }
  809. m_eventTargets.clear();
  810. SetModified(false);
  811. }
  812. //////////////////////////////////////////////////////////////////////////
  813. void CEntityObject::LoadLink(XmlNodeRef xmlNode, CObjectArchive* pArchive)
  814. {
  815. RemoveAllEntityLinks();
  816. if (!xmlNode)
  817. {
  818. return;
  819. }
  820. QString name;
  821. GUID targetId;
  822. for (int i = 0; i < xmlNode->getChildCount(); i++)
  823. {
  824. XmlNodeRef linkNode = xmlNode->getChild(i);
  825. linkNode->getAttr("Name", name);
  826. if (linkNode->getAttr("TargetId", targetId))
  827. {
  828. int version = 0;
  829. linkNode->getAttr("Version", version);
  830. GUID newTargetId = pArchive ? pArchive->ResolveID(targetId) : targetId;
  831. // Backwards compatibility with old bone attachment system
  832. const char kOldBoneLinkPrefix = '@';
  833. if (version == 0 && !name.isEmpty() && name[0] == kOldBoneLinkPrefix)
  834. {
  835. CBaseObject* pObject = FindObject(newTargetId);
  836. if (qobject_cast<CEntityObject*>(pObject))
  837. {
  838. CEntityObject* pTargetEntity = static_cast<CEntityObject*>(pObject);
  839. Quat relRot(IDENTITY);
  840. linkNode->getAttr("RelRot", relRot);
  841. Vec3 relPos(IDENTITY);
  842. linkNode->getAttr("RelPos", relPos);
  843. SetAttachType(eAT_CharacterBone);
  844. SetAttachTarget(name.mid(1).toUtf8().data());
  845. pTargetEntity->AttachChild(this);
  846. SetPos(relPos);
  847. SetRotation(relRot);
  848. }
  849. }
  850. else
  851. {
  852. AddEntityLink(name, newTargetId);
  853. }
  854. }
  855. }
  856. }
  857. //////////////////////////////////////////////////////////////////////////
  858. void CEntityObject::SaveLink(XmlNodeRef xmlNode)
  859. {
  860. if (m_links.empty())
  861. {
  862. return;
  863. }
  864. XmlNodeRef linksNode = xmlNode->newChild("EntityLinks");
  865. for (size_t i = 0, num = m_links.size(); i < num; i++)
  866. {
  867. XmlNodeRef linkNode = linksNode->newChild("Link");
  868. linkNode->setAttr("TargetId", m_links[i].targetId);
  869. linkNode->setAttr("Name", m_links[i].name.toUtf8().data());
  870. linkNode->setAttr("Version", 1);
  871. }
  872. }
  873. //////////////////////////////////////////////////////////////////////////
  874. void CEntityObject::OnObjectEvent(CBaseObject* target, int event)
  875. {
  876. // When event target is deleted.
  877. if (event == CBaseObject::ON_DELETE)
  878. {
  879. // Find this target in events list and remove.
  880. int numTargets = static_cast<int>(m_eventTargets.size());
  881. for (int i = 0; i < numTargets; i++)
  882. {
  883. if (m_eventTargets[i].target == target)
  884. {
  885. RemoveEventTarget(i);
  886. numTargets = static_cast<int>(m_eventTargets.size());
  887. i--;
  888. }
  889. }
  890. }
  891. else if (event == CBaseObject::ON_PREDELETE)
  892. {
  893. int numTargets = static_cast<int>(m_links.size());
  894. for (int i = 0; i < numTargets; i++)
  895. {
  896. if (m_links[i].target == target)
  897. {
  898. RemoveEntityLink(i);
  899. numTargets = static_cast<int>(m_eventTargets.size());
  900. i--;
  901. }
  902. }
  903. }
  904. }
  905. //////////////////////////////////////////////////////////////////////////
  906. int CEntityObject::AddEventTarget(CBaseObject* target, const QString& event, const QString& sourceEvent, [[maybe_unused]] bool bUpdateScript)
  907. {
  908. StoreUndo();
  909. CEntityEventTarget et;
  910. et.target = target;
  911. et.event = event;
  912. et.sourceEvent = sourceEvent;
  913. // Assign event target.
  914. if (et.target)
  915. {
  916. et.target->AddEventListener(this);
  917. }
  918. m_eventTargets.push_back(et);
  919. SetModified(false);
  920. return static_cast<int>(m_eventTargets.size() - 1);
  921. }
  922. //////////////////////////////////////////////////////////////////////////
  923. void CEntityObject::RemoveEventTarget(int index, [[maybe_unused]] bool bUpdateScript)
  924. {
  925. if (index >= 0 && index < m_eventTargets.size())
  926. {
  927. StoreUndo();
  928. if (m_eventTargets[index].target)
  929. {
  930. m_eventTargets[index].target->RemoveEventListener(this);
  931. }
  932. m_eventTargets.erase(m_eventTargets.begin() + index);
  933. SetModified(false);
  934. }
  935. }
  936. //////////////////////////////////////////////////////////////////////////
  937. int CEntityObject::AddEntityLink(const QString& name, GUID targetEntityId)
  938. {
  939. CEntityObject* target = nullptr;
  940. if (targetEntityId != GUID_NULL)
  941. {
  942. CBaseObject* pObject = FindObject(targetEntityId);
  943. if (qobject_cast<CEntityObject*>(pObject))
  944. {
  945. target = ( CEntityObject* )pObject;
  946. // Legacy entities and AZ entities shouldn't be linked.
  947. if (target->GetType() == OBJTYPE_AZENTITY || GetType() == OBJTYPE_AZENTITY)
  948. {
  949. return -1;
  950. }
  951. }
  952. }
  953. StoreUndo();
  954. CEntityLink lnk;
  955. lnk.targetId = targetEntityId;
  956. lnk.target = target;
  957. lnk.name = name;
  958. m_links.push_back(lnk);
  959. SetModified(false);
  960. return static_cast<int>(m_links.size() - 1);
  961. }
  962. //////////////////////////////////////////////////////////////////////////
  963. bool CEntityObject::EntityLinkExists(const QString& name, GUID targetEntityId)
  964. {
  965. for (size_t i = 0, num = m_links.size(); i < num; ++i)
  966. {
  967. if (m_links[i].targetId == targetEntityId && name.compare(m_links[i].name, Qt::CaseInsensitive) == 0)
  968. {
  969. return true;
  970. }
  971. }
  972. return false;
  973. }
  974. //////////////////////////////////////////////////////////////////////////
  975. void CEntityObject::RemoveEntityLink(int index)
  976. {
  977. if (index >= 0 && index < m_links.size())
  978. {
  979. CEntityLink& link = m_links[index];
  980. StoreUndo();
  981. if (link.target)
  982. {
  983. link.target->RemoveEventListener(this);
  984. link.target->EntityUnlinked(link.name, GetId());
  985. }
  986. m_links.erase(m_links.begin() + index);
  987. SetModified(false);
  988. }
  989. }
  990. //////////////////////////////////////////////////////////////////////////
  991. void CEntityObject::RenameEntityLink(int index, const QString& newName)
  992. {
  993. if (index >= 0 && index < m_links.size())
  994. {
  995. StoreUndo();
  996. m_links[index].name = newName;
  997. SetModified(false);
  998. }
  999. }
  1000. //////////////////////////////////////////////////////////////////////////
  1001. void CEntityObject::OnRadiusChange(IVariable* var)
  1002. {
  1003. var->Get(m_proximityRadius);
  1004. }
  1005. //////////////////////////////////////////////////////////////////////////
  1006. void CEntityObject::OnInnerRadiusChange(IVariable* var)
  1007. {
  1008. var->Get(m_innerRadius);
  1009. }
  1010. //////////////////////////////////////////////////////////////////////////
  1011. void CEntityObject::OnOuterRadiusChange(IVariable* var)
  1012. {
  1013. var->Get(m_outerRadius);
  1014. }
  1015. //////////////////////////////////////////////////////////////////////////
  1016. void CEntityObject::OnBoxSizeXChange(IVariable* var)
  1017. {
  1018. var->Get(m_boxSizeX);
  1019. }
  1020. //////////////////////////////////////////////////////////////////////////
  1021. void CEntityObject::OnBoxSizeYChange(IVariable* var)
  1022. {
  1023. var->Get(m_boxSizeY);
  1024. }
  1025. //////////////////////////////////////////////////////////////////////////
  1026. void CEntityObject::OnBoxSizeZChange(IVariable* var)
  1027. {
  1028. var->Get(m_boxSizeZ);
  1029. }
  1030. //////////////////////////////////////////////////////////////////////////
  1031. void CEntityObject::OnProjectorFOVChange(IVariable* var)
  1032. {
  1033. var->Get(m_projectorFOV);
  1034. }
  1035. //////////////////////////////////////////////////////////////////////////
  1036. void CEntityObject::OnProjectInAllDirsChange(IVariable* var)
  1037. {
  1038. int value;
  1039. var->Get(value);
  1040. m_bProjectInAllDirs = value;
  1041. }
  1042. //////////////////////////////////////////////////////////////////////////
  1043. void CEntityObject::OnProjectorTextureChange(IVariable* var)
  1044. {
  1045. QString texture;
  1046. var->Get(texture);
  1047. m_bProjectorHasTexture = !texture.isEmpty();
  1048. }
  1049. //////////////////////////////////////////////////////////////////////////
  1050. void CEntityObject::OnAreaLightChange(IVariable* var)
  1051. {
  1052. int value;
  1053. var->Get(value);
  1054. m_bAreaLight = value;
  1055. }
  1056. //////////////////////////////////////////////////////////////////////////
  1057. void CEntityObject::OnAreaWidthChange(IVariable* var)
  1058. {
  1059. var->Get(m_fAreaWidth);
  1060. }
  1061. //////////////////////////////////////////////////////////////////////////
  1062. void CEntityObject::OnAreaHeightChange(IVariable* var)
  1063. {
  1064. var->Get(m_fAreaHeight);
  1065. }
  1066. //////////////////////////////////////////////////////////////////////////
  1067. void CEntityObject::OnAreaLightSizeChange(IVariable* var)
  1068. {
  1069. var->Get(m_fAreaLightSize);
  1070. }
  1071. //////////////////////////////////////////////////////////////////////////
  1072. void CEntityObject::OnColorChange(IVariable* var)
  1073. {
  1074. var->Get(m_lightColor);
  1075. }
  1076. //////////////////////////////////////////////////////////////////////////
  1077. void CEntityObject::OnBoxProjectionChange(IVariable* var)
  1078. {
  1079. int value;
  1080. var->Get(value);
  1081. m_bBoxProjectedCM = value;
  1082. }
  1083. //////////////////////////////////////////////////////////////////////////
  1084. void CEntityObject::OnBoxWidthChange(IVariable* var)
  1085. {
  1086. var->Get(m_fBoxWidth);
  1087. }
  1088. //////////////////////////////////////////////////////////////////////////
  1089. void CEntityObject::OnBoxHeightChange(IVariable* var)
  1090. {
  1091. var->Get(m_fBoxHeight);
  1092. }
  1093. //////////////////////////////////////////////////////////////////////////
  1094. void CEntityObject::OnBoxLengthChange(IVariable* var)
  1095. {
  1096. var->Get(m_fBoxLength);
  1097. }
  1098. //////////////////////////////////////////////////////////////////////////
  1099. CVarBlock* CEntityObject::CloneProperties(CVarBlock* srcProperties)
  1100. {
  1101. assert(srcProperties);
  1102. return srcProperties->Clone(true);
  1103. }
  1104. //////////////////////////////////////////////////////////////////////////
  1105. void CEntityObject::OnLoadFailed()
  1106. {
  1107. m_bLoadFailed = true;
  1108. CErrorRecord err;
  1109. err.error = tr("Entity %1 Failed to Spawn (Script: %2)").arg(GetName(), m_entityClass);
  1110. err.pObject = this;
  1111. GetIEditor()->GetErrorReport()->ReportError(err);
  1112. }
  1113. //////////////////////////////////////////////////////////////////////////
  1114. //! Analyze errors for this object.
  1115. void CEntityObject::Validate(IErrorReport* report)
  1116. {
  1117. CBaseObject::Validate(report);
  1118. if (!m_entityClass.isEmpty())
  1119. {
  1120. CErrorRecord err;
  1121. err.error = tr("Entity %1 Failed to Spawn (Script: %2)").arg(GetName(), m_entityClass);
  1122. err.pObject = this;
  1123. report->ReportError(err);
  1124. return;
  1125. }
  1126. }
  1127. //////////////////////////////////////////////////////////////////////////
  1128. void CEntityObject::GatherUsedResources(CUsedResources& resources)
  1129. {
  1130. CBaseObject::GatherUsedResources(resources);
  1131. if (m_pProperties)
  1132. {
  1133. m_pProperties->GatherUsedResources(resources);
  1134. }
  1135. if (m_pProperties2)
  1136. {
  1137. m_pProperties2->GatherUsedResources(resources);
  1138. }
  1139. }
  1140. //////////////////////////////////////////////////////////////////////////
  1141. bool CEntityObject::IsSimilarObject(CBaseObject* pObject)
  1142. {
  1143. if (pObject->GetClassDesc() == GetClassDesc() && pObject->metaObject() == metaObject())
  1144. {
  1145. CEntityObject* pEntity = ( CEntityObject* )pObject;
  1146. if (m_entityClass == pEntity->m_entityClass &&
  1147. m_proximityRadius == pEntity->m_proximityRadius &&
  1148. m_innerRadius == pEntity->m_innerRadius &&
  1149. m_outerRadius == pEntity->m_outerRadius)
  1150. {
  1151. return true;
  1152. }
  1153. }
  1154. return false;
  1155. }
  1156. //////////////////////////////////////////////////////////////////////////
  1157. void CEntityObject::PreInitLightProperty()
  1158. {
  1159. if (!IsLight() || !m_pProperties)
  1160. {
  1161. return;
  1162. }
  1163. }
  1164. //////////////////////////////////////////////////////////////////////////
  1165. void CEntityObject::UpdateLightProperty()
  1166. {
  1167. if (!IsLight() || !m_pProperties)
  1168. {
  1169. return;
  1170. }
  1171. }
  1172. //////////////////////////////////////////////////////////////////////////
  1173. void CEntityObject::ForceVariableUpdate()
  1174. {
  1175. if (m_pProperties)
  1176. {
  1177. m_pProperties->OnSetValues();
  1178. }
  1179. if (m_pProperties2)
  1180. {
  1181. m_pProperties2->OnSetValues();
  1182. }
  1183. }
  1184. //////////////////////////////////////////////////////////////////////////
  1185. void CEntityObject::ResetCallbacks()
  1186. {
  1187. ClearCallbacks();
  1188. CVarBlock* pProperties = m_pProperties;
  1189. CVarBlock* pProperties2 = m_pProperties2;
  1190. if (pProperties)
  1191. {
  1192. m_callbacks.reserve(6);
  1193. //@FIXME Hack to display radii of properties.
  1194. // wires properties from param block, to this entity internal variables.
  1195. IVariable* var = nullptr;
  1196. var = pProperties->FindVariable("Radius", false);
  1197. if (var && (var->GetType() == IVariable::FLOAT || var->GetType() == IVariable::INT))
  1198. {
  1199. var->Get(m_proximityRadius);
  1200. SetVariableCallback(var, &m_onSetCallbacksCache[VariableCallbackIndex::OnRadiusChange]);
  1201. }
  1202. else
  1203. {
  1204. var = pProperties->FindVariable("radius", false);
  1205. if (var && (var->GetType() == IVariable::FLOAT || var->GetType() == IVariable::INT))
  1206. {
  1207. var->Get(m_proximityRadius);
  1208. SetVariableCallback(var, &m_onSetCallbacksCache[VariableCallbackIndex::OnRadiusChange]);
  1209. }
  1210. }
  1211. var = pProperties->FindVariable("InnerRadius", false);
  1212. if (var && (var->GetType() == IVariable::FLOAT || var->GetType() == IVariable::INT))
  1213. {
  1214. var->Get(m_innerRadius);
  1215. SetVariableCallback(var, &m_onSetCallbacksCache[VariableCallbackIndex::OnInnerRadiusChange]);
  1216. }
  1217. var = pProperties->FindVariable("OuterRadius", false);
  1218. if (var && (var->GetType() == IVariable::FLOAT || var->GetType() == IVariable::INT))
  1219. {
  1220. var->Get(m_outerRadius);
  1221. SetVariableCallback(var, &m_onSetCallbacksCache[VariableCallbackIndex::OnOuterRadiusChange]);
  1222. }
  1223. var = pProperties->FindVariable("BoxSizeX", false);
  1224. if (var && (var->GetType() == IVariable::FLOAT || var->GetType() == IVariable::INT))
  1225. {
  1226. var->Get(m_boxSizeX);
  1227. SetVariableCallback(var, &m_onSetCallbacksCache[VariableCallbackIndex::OnBoxSizeXChange]);
  1228. }
  1229. var = pProperties->FindVariable("BoxSizeY", false);
  1230. if (var && (var->GetType() == IVariable::FLOAT || var->GetType() == IVariable::INT))
  1231. {
  1232. var->Get(m_boxSizeY);
  1233. SetVariableCallback(var, &m_onSetCallbacksCache[VariableCallbackIndex::OnBoxSizeYChange]);
  1234. }
  1235. var = pProperties->FindVariable("BoxSizeZ", false);
  1236. if (var && (var->GetType() == IVariable::FLOAT || var->GetType() == IVariable::INT))
  1237. {
  1238. var->Get(m_boxSizeZ);
  1239. SetVariableCallback(var, &m_onSetCallbacksCache[VariableCallbackIndex::OnBoxSizeZChange]);
  1240. }
  1241. var = pProperties->FindVariable("fAttenuationBulbSize");
  1242. if (var && (var->GetType() == IVariable::FLOAT || var->GetType() == IVariable::INT))
  1243. {
  1244. var->Get(m_fAreaLightSize);
  1245. SetVariableCallback(var, &m_onSetCallbacksCache[VariableCallbackIndex::OnAreaLightSizeChange]);
  1246. }
  1247. IVariable* pProjector = pProperties->FindVariable("Projector");
  1248. if (pProjector)
  1249. {
  1250. var = pProjector->FindVariable("fProjectorFov");
  1251. if (var && (var->GetType() == IVariable::FLOAT || var->GetType() == IVariable::INT))
  1252. {
  1253. var->Get(m_projectorFOV);
  1254. SetVariableCallback(var, &m_onSetCallbacksCache[VariableCallbackIndex::OnProjectorFOVChange]);
  1255. }
  1256. var = pProjector->FindVariable("bProjectInAllDirs");
  1257. if (var && var->GetType() == IVariable::BOOL)
  1258. {
  1259. int value;
  1260. var->Get(value);
  1261. m_bProjectInAllDirs = value;
  1262. SetVariableCallback(var, &m_onSetCallbacksCache[VariableCallbackIndex::OnProjectInAllDirsChange]);
  1263. }
  1264. var = pProjector->FindVariable("texture_Texture");
  1265. if (var && var->GetType() == IVariable::STRING)
  1266. {
  1267. QString projectorTexture;
  1268. var->Get(projectorTexture);
  1269. m_bProjectorHasTexture = !projectorTexture.isEmpty();
  1270. SetVariableCallback(var, &m_onSetCallbacksCache[VariableCallbackIndex::OnProjectorTextureChange]);
  1271. }
  1272. }
  1273. IVariable* pColorGroup = pProperties->FindVariable("Color", false);
  1274. if (pColorGroup)
  1275. {
  1276. const int nChildCount = pColorGroup->GetNumVariables();
  1277. for (int i = 0; i < nChildCount; ++i)
  1278. {
  1279. IVariable* pChild = pColorGroup->GetVariable(i);
  1280. if (!pChild)
  1281. {
  1282. continue;
  1283. }
  1284. QString name(pChild->GetName());
  1285. if (name == "clrDiffuse")
  1286. {
  1287. pChild->Get(m_lightColor);
  1288. SetVariableCallback(pChild, &m_onSetCallbacksCache[VariableCallbackIndex::OnColorChange]);
  1289. break;
  1290. }
  1291. }
  1292. }
  1293. IVariable* pType = pProperties->FindVariable("Shape");
  1294. if (pType)
  1295. {
  1296. var = pType->FindVariable("bAreaLight");
  1297. if (var && var->GetType() == IVariable::BOOL)
  1298. {
  1299. int value;
  1300. var->Get(value);
  1301. m_bAreaLight = value;
  1302. SetVariableCallback(var, &m_onSetCallbacksCache[VariableCallbackIndex::OnAreaLightChange]);
  1303. }
  1304. var = pType->FindVariable("fPlaneWidth");
  1305. if (var && (var->GetType() == IVariable::FLOAT || var->GetType() == IVariable::INT))
  1306. {
  1307. var->Get(m_fAreaWidth);
  1308. SetVariableCallback(var, &m_onSetCallbacksCache[VariableCallbackIndex::OnAreaWidthChange]);
  1309. }
  1310. var = pType->FindVariable("fPlaneHeight");
  1311. if (var && (var->GetType() == IVariable::FLOAT || var->GetType() == IVariable::INT))
  1312. {
  1313. var->Get(m_fAreaHeight);
  1314. SetVariableCallback(var, &m_onSetCallbacksCache[VariableCallbackIndex::OnAreaHeightChange]);
  1315. }
  1316. }
  1317. IVariable* pProjection = pProperties->FindVariable("Projection");
  1318. if (pProjection)
  1319. {
  1320. var = pProjection->FindVariable("bBoxProject");
  1321. if (var && var->GetType() == IVariable::BOOL)
  1322. {
  1323. int value;
  1324. var->Get(value);
  1325. m_bBoxProjectedCM = value;
  1326. SetVariableCallback(var, &m_onSetCallbacksCache[VariableCallbackIndex::OnBoxProjectionChange]);
  1327. }
  1328. var = pProjection->FindVariable("fBoxWidth");
  1329. if (var && (var->GetType() == IVariable::FLOAT || var->GetType() == IVariable::INT))
  1330. {
  1331. var->Get(m_fBoxWidth);
  1332. SetVariableCallback(var, &m_onSetCallbacksCache[VariableCallbackIndex::OnBoxWidthChange]);
  1333. }
  1334. var = pProjection->FindVariable("fBoxHeight");
  1335. if (var && (var->GetType() == IVariable::FLOAT || var->GetType() == IVariable::INT))
  1336. {
  1337. var->Get(m_fBoxHeight);
  1338. SetVariableCallback(var, &m_onSetCallbacksCache[VariableCallbackIndex::OnBoxHeightChange]);
  1339. }
  1340. var = pProjection->FindVariable("fBoxLength");
  1341. if (var && (var->GetType() == IVariable::FLOAT || var->GetType() == IVariable::INT))
  1342. {
  1343. var->Get(m_fBoxLength);
  1344. SetVariableCallback(var, &m_onSetCallbacksCache[VariableCallbackIndex::OnBoxLengthChange]);
  1345. }
  1346. }
  1347. // Each property must have callback to our OnPropertyChange.
  1348. pProperties->AddOnSetCallback(&m_onSetCallbacksCache[VariableCallbackIndex::OnPropertyChange]);
  1349. }
  1350. if (pProperties2)
  1351. {
  1352. pProperties2->AddOnSetCallback(&m_onSetCallbacksCache[VariableCallbackIndex::OnPropertyChange]);
  1353. }
  1354. }
  1355. //////////////////////////////////////////////////////////////////////////
  1356. void CEntityObject::SetVariableCallback(IVariable* pVar, IVariable::OnSetCallback* func)
  1357. {
  1358. pVar->AddOnSetCallback(func);
  1359. m_callbacks.push_back(std::make_pair(pVar, func));
  1360. }
  1361. //////////////////////////////////////////////////////////////////////////
  1362. void CEntityObject::ClearCallbacks()
  1363. {
  1364. if (m_pProperties)
  1365. {
  1366. m_pProperties->RemoveOnSetCallback(&m_onSetCallbacksCache[VariableCallbackIndex::OnPropertyChange]);
  1367. }
  1368. if (m_pProperties2)
  1369. {
  1370. m_pProperties2->RemoveOnSetCallback(&m_onSetCallbacksCache[VariableCallbackIndex::OnPropertyChange]);
  1371. }
  1372. for (auto iter = m_callbacks.begin(); iter != m_callbacks.end(); ++iter)
  1373. {
  1374. iter->first->RemoveOnSetCallback(iter->second);
  1375. }
  1376. m_callbacks.clear();
  1377. }
  1378. template <typename T>
  1379. T CEntityObject::GetEntityProperty(const char* pName, T defaultvalue) const
  1380. {
  1381. CVarBlock* pProperties = GetProperties2();
  1382. IVariable* pVariable = nullptr;
  1383. if (pProperties)
  1384. {
  1385. pVariable = pProperties->FindVariable(pName);
  1386. }
  1387. if (!pVariable)
  1388. {
  1389. pProperties = GetProperties();
  1390. if (pProperties)
  1391. {
  1392. pVariable = pProperties->FindVariable(pName);
  1393. }
  1394. if (!pVariable)
  1395. {
  1396. return defaultvalue;
  1397. }
  1398. }
  1399. if (pVariable->GetType() != IVariableType<T>::value)
  1400. {
  1401. return defaultvalue;
  1402. }
  1403. T value;
  1404. pVariable->Get(value);
  1405. return value;
  1406. }
  1407. template <typename T>
  1408. void CEntityObject::SetEntityProperty(const char* pName, T value)
  1409. {
  1410. CVarBlock* pProperties = GetProperties2();
  1411. IVariable* pVariable = nullptr;
  1412. if (pProperties)
  1413. {
  1414. pVariable = pProperties->FindVariable(pName);
  1415. }
  1416. if (!pVariable)
  1417. {
  1418. pProperties = GetProperties();
  1419. if (pProperties)
  1420. {
  1421. pVariable = pProperties->FindVariable(pName);
  1422. }
  1423. if (!pVariable)
  1424. {
  1425. throw std::runtime_error((QString("\"") + pName + "\" is an invalid property.").toUtf8().data());
  1426. }
  1427. }
  1428. if (pVariable->GetType() != IVariableType<T>::value)
  1429. {
  1430. throw std::logic_error("Data type is invalid.");
  1431. }
  1432. pVariable->Set(value);
  1433. }
  1434. bool CEntityObject::GetEntityPropertyBool(const char* name) const
  1435. {
  1436. return GetEntityProperty<bool>(name, false);
  1437. }
  1438. int CEntityObject::GetEntityPropertyInteger(const char* name) const
  1439. {
  1440. return GetEntityProperty<int>(name, 0);
  1441. }
  1442. float CEntityObject::GetEntityPropertyFloat(const char* name) const
  1443. {
  1444. return GetEntityProperty<float>(name, 0.0f);
  1445. }
  1446. QString CEntityObject::GetEntityPropertyString(const char* name) const
  1447. {
  1448. return GetEntityProperty<QString>(name, "");
  1449. }
  1450. void CEntityObject::SetEntityPropertyBool(const char* name, bool value)
  1451. {
  1452. SetEntityProperty<bool>(name, value);
  1453. }
  1454. void CEntityObject::SetEntityPropertyInteger(const char* name, int value)
  1455. {
  1456. SetEntityProperty<int>(name, value);
  1457. }
  1458. void CEntityObject::SetEntityPropertyFloat(const char* name, float value)
  1459. {
  1460. SetEntityProperty<float>(name, value);
  1461. }
  1462. void CEntityObject::SetEntityPropertyString(const char* name, const QString& value)
  1463. {
  1464. SetEntityProperty<QString>(name, value);
  1465. }
  1466. #include <Objects/moc_EntityObject.cpp>