ObjectManager.cpp 88 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027
  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. #include "EditorDefs.h"
  9. #include "ObjectManager.h"
  10. // Qt
  11. #include <QMessageBox>
  12. // Editor
  13. #include "Settings.h"
  14. #include "DisplaySettings.h"
  15. #include "EntityObject.h"
  16. #include "Viewport.h"
  17. #include "GizmoManager.h"
  18. #include "AxisGizmo.h"
  19. #include "GameEngine.h"
  20. #include "WaitProgress.h"
  21. #include "Util/Image.h"
  22. #include "ObjectManagerLegacyUndo.h"
  23. #include "Include/HitContext.h"
  24. #include "EditMode/DeepSelection.h"
  25. #include "Plugins/ComponentEntityEditorPlugin/Objects/ComponentEntityObject.h"
  26. #include <AzCore/Console/Console.h>
  27. AZ_CVAR_EXTERNED(bool, ed_visibility_logTiming);
  28. AZ_CVAR(
  29. bool, ed_visibility_use, true, nullptr, AZ::ConsoleFunctorFlags::Null,
  30. "Enable/disable using the new IVisibilitySystem for Entity visibility determination");
  31. /*!
  32. * Class Description used for object templates.
  33. * This description filled from Xml template files.
  34. */
  35. class CXMLObjectClassDesc
  36. : public CObjectClassDesc
  37. {
  38. public:
  39. CObjectClassDesc* superType;
  40. QString type;
  41. QString category;
  42. QString fileSpec;
  43. GUID guid;
  44. public:
  45. REFGUID ClassID() override
  46. {
  47. return guid;
  48. }
  49. ObjectType GetObjectType() override { return superType->GetObjectType(); };
  50. QString ClassName() override { return type; };
  51. QString Category() override { return category; };
  52. QObject* CreateQObject() const override { return superType->CreateQObject(); }
  53. QString GetTextureIcon() override { return superType->GetTextureIcon(); };
  54. QString GetFileSpec() override
  55. {
  56. if (!fileSpec.isEmpty())
  57. {
  58. return fileSpec;
  59. }
  60. else
  61. {
  62. return superType->GetFileSpec();
  63. }
  64. };
  65. int GameCreationOrder() override { return superType->GameCreationOrder(); };
  66. };
  67. void CBaseObjectsCache::AddObject(CBaseObject* object)
  68. {
  69. m_objects.push_back(object);
  70. if (object->GetType() == OBJTYPE_AZENTITY)
  71. {
  72. auto componentEntityObject = static_cast<CComponentEntityObject*>(object);
  73. m_entityIds.push_back(componentEntityObject->GetAssociatedEntityId());
  74. }
  75. }
  76. //////////////////////////////////////////////////////////////////////////
  77. // CObjectManager implementation.
  78. //////////////////////////////////////////////////////////////////////////
  79. CObjectManager* g_pObjectManager = nullptr;
  80. //////////////////////////////////////////////////////////////////////////
  81. CObjectManager::CObjectManager()
  82. : m_lastHideMask(0)
  83. , m_maxObjectViewDistRatio(0.00001f)
  84. , m_currSelection(&m_defaultSelection)
  85. , m_nLastSelCount(0)
  86. , m_bSelectionChanged(false)
  87. , m_selectCallback(nullptr)
  88. , m_currEditObject(nullptr)
  89. , m_bSingleSelection(false)
  90. , m_createGameObjects(true)
  91. , m_bGenUniqObjectNames(true)
  92. , m_gizmoManager(new CGizmoManager())
  93. , m_pLoadProgress(nullptr)
  94. , m_loadedObjects(0)
  95. , m_totalObjectsToLoad(0)
  96. , m_bExiting(false)
  97. , m_isUpdateVisibilityList(false)
  98. , m_currentHideCount(CBaseObject::s_invalidHiddenID)
  99. , m_bInReloading(false)
  100. , m_bSkipObjectUpdate(false)
  101. , m_bLevelExporting(false)
  102. {
  103. g_pObjectManager = this;
  104. RegisterObjectClasses();
  105. m_objectsByName.reserve(1024);
  106. LoadRegistry();
  107. AzToolsFramework::ComponentModeFramework::EditorComponentModeNotificationBus::Handler::BusConnect(
  108. AzToolsFramework::GetEntityContextId());
  109. }
  110. //////////////////////////////////////////////////////////////////////////
  111. CObjectManager::~CObjectManager()
  112. {
  113. AzToolsFramework::ComponentModeFramework::EditorComponentModeNotificationBus::Handler::BusDisconnect();
  114. m_bExiting = true;
  115. SaveRegistry();
  116. DeleteAllObjects();
  117. delete m_gizmoManager;
  118. }
  119. //////////////////////////////////////////////////////////////////////////
  120. void CObjectManager::RegisterObjectClasses()
  121. {
  122. LoadRegistry();
  123. }
  124. //////////////////////////////////////////////////////////////////////////
  125. void CObjectManager::SaveRegistry()
  126. {
  127. }
  128. void CObjectManager::LoadRegistry()
  129. {
  130. }
  131. //////////////////////////////////////////////////////////////////////////
  132. CBaseObject* CObjectManager::NewObject(CObjectClassDesc* cls, CBaseObject* prev, const QString& file, const char* newObjectName)
  133. {
  134. // Suspend undo operations when initializing object.
  135. GetIEditor()->SuspendUndo();
  136. CBaseObjectPtr obj;
  137. {
  138. obj = qobject_cast<CBaseObject*>(cls->CreateQObject());
  139. obj->SetClassDesc(cls);
  140. obj->InitVariables();
  141. obj->m_guid = AZ::Uuid::CreateRandom(); // generate uniq GUID for this object.
  142. GetIEditor()->GetErrorReport()->SetCurrentValidatorObject(obj);
  143. if (obj->Init(GetIEditor(), prev, file))
  144. {
  145. if ((newObjectName)&&(newObjectName[0]))
  146. {
  147. obj->SetName(newObjectName);
  148. }
  149. else
  150. {
  151. if (obj->GetName().isEmpty())
  152. {
  153. obj->GenerateUniqueName();
  154. }
  155. }
  156. // Create game object itself.
  157. obj->CreateGameObject();
  158. if (!AddObject(obj))
  159. {
  160. obj = nullptr;
  161. }
  162. }
  163. else
  164. {
  165. obj = nullptr;
  166. }
  167. GetIEditor()->GetErrorReport()->SetCurrentValidatorObject(nullptr);
  168. }
  169. GetIEditor()->ResumeUndo();
  170. if (obj != nullptr && GetIEditor()->IsUndoRecording())
  171. {
  172. // AZ entity creations are handled through the AZ undo system.
  173. if (obj->GetType() != OBJTYPE_AZENTITY)
  174. {
  175. GetIEditor()->RecordUndo(new CUndoBaseObjectNew(obj));
  176. // check for script entities
  177. const char* scriptClassName = "";
  178. CEntityObject* entityObj = qobject_cast<CEntityObject*>(obj);
  179. QByteArray entityClass; // Leave it outside of the if. Otherwise buffer is deleted.
  180. if (entityObj)
  181. {
  182. entityClass = entityObj->GetEntityClass().toUtf8();
  183. scriptClassName = entityClass.data();
  184. }
  185. }
  186. }
  187. return obj;
  188. }
  189. //////////////////////////////////////////////////////////////////////////
  190. CBaseObject* CObjectManager::NewObject(CObjectArchive& ar, CBaseObject* pUndoObject, bool bMakeNewId)
  191. {
  192. XmlNodeRef objNode = ar.node;
  193. // Load all objects from XML.
  194. QString typeName;
  195. GUID id = GUID_NULL;
  196. if (!objNode->getAttr("Type", typeName))
  197. {
  198. return nullptr;
  199. }
  200. if (!objNode->getAttr("Id", id))
  201. {
  202. // Make new ID for object that doesn't have if.
  203. id = AZ::Uuid::CreateRandom();
  204. }
  205. if (bMakeNewId)
  206. {
  207. // Make new guid for this object.
  208. GUID newId = AZ::Uuid::CreateRandom();
  209. ar.RemapID(id, newId); // Mark this id remapped.
  210. id = newId;
  211. }
  212. CBaseObjectPtr pObject;
  213. if (pUndoObject)
  214. {
  215. // if undoing restore object pointer.
  216. pObject = pUndoObject;
  217. }
  218. else
  219. {
  220. // New object creation.
  221. // Suspend undo operations when initializing object.
  222. CUndoSuspend undoSuspender;
  223. QString entityClass;
  224. if (objNode->getAttr("EntityClass", entityClass))
  225. {
  226. typeName = typeName + "::" + entityClass;
  227. }
  228. CObjectClassDesc* cls = FindClass(typeName);
  229. if (!cls)
  230. {
  231. CryWarning(VALIDATOR_MODULE_EDITOR, VALIDATOR_ERROR, "RuntimeClass %s not registered", typeName.toUtf8().data());
  232. return nullptr;
  233. }
  234. pObject = qobject_cast<CBaseObject*>(cls->CreateQObject());
  235. assert(pObject);
  236. pObject->SetClassDesc(cls);
  237. pObject->m_guid = id;
  238. pObject->InitVariables();
  239. QString objName;
  240. objNode->getAttr("Name", objName);
  241. pObject->m_name = objName;
  242. CBaseObject* obj = FindObject(pObject->GetId());
  243. if (obj)
  244. {
  245. // If id is taken.
  246. QString error;
  247. error = QObject::tr("[Error] Object %1 already exists in the Object Manager and has been deleted as it is a duplicate of object %2").arg(pObject->m_name, obj->GetName());
  248. CLogFile::WriteLine(error.toUtf8().data());
  249. if (!GetIEditor()->IsInTestMode() && !GetIEditor()->IsInLevelLoadTestMode())
  250. {
  251. CErrorRecord errorRecord;
  252. errorRecord.pObject = obj;
  253. errorRecord.count = 1;
  254. errorRecord.severity = CErrorRecord::ESEVERITY_ERROR;
  255. errorRecord.error = error;
  256. errorRecord.description = "Possible duplicate objects being loaded, potential fix is to remove duplicate objects from level files.";
  257. GetIEditor()->GetErrorReport()->ReportError(errorRecord);
  258. }
  259. return nullptr;
  260. //CoCreateGuid( &pObject->m_guid ); // generate uniq GUID for this object.
  261. }
  262. }
  263. GetIEditor()->GetErrorReport()->SetCurrentValidatorObject(pObject);
  264. if (!pObject->Init(GetIEditor(), nullptr, ""))
  265. {
  266. GetIEditor()->GetErrorReport()->SetCurrentValidatorObject(nullptr);
  267. return nullptr;
  268. }
  269. if (!AddObject(pObject))
  270. {
  271. GetIEditor()->GetErrorReport()->SetCurrentValidatorObject(nullptr);
  272. return nullptr;
  273. }
  274. //pObject->Serialize( ar );
  275. GetIEditor()->GetErrorReport()->SetCurrentValidatorObject(nullptr);
  276. if (pObject != nullptr && pUndoObject == nullptr)
  277. {
  278. // If new object with no undo, record it.
  279. if (CUndo::IsRecording())
  280. {
  281. GetIEditor()->RecordUndo(new CUndoBaseObjectNew(pObject));
  282. }
  283. }
  284. m_loadedObjects++;
  285. if (m_pLoadProgress && m_totalObjectsToLoad > 0)
  286. {
  287. m_pLoadProgress->Step((m_loadedObjects * 100) / m_totalObjectsToLoad);
  288. }
  289. return pObject;
  290. }
  291. //////////////////////////////////////////////////////////////////////////
  292. CBaseObject* CObjectManager::NewObject(const QString& typeName, CBaseObject* prev, const QString& file, const char* newObjectName)
  293. {
  294. // [9/22/2009 evgeny] If it is "Entity", figure out if a CEntity subclass is actually needed
  295. QString fullName = typeName + "::" + file;
  296. CObjectClassDesc* cls = FindClass(fullName);
  297. if (!cls)
  298. {
  299. cls = FindClass(typeName);
  300. }
  301. if (!cls)
  302. {
  303. GetIEditor()->GetSystem()->GetILog()->Log("Warning: RuntimeClass %s (as well as %s) not registered", typeName.toUtf8().data(), fullName.toUtf8().data());
  304. return nullptr;
  305. }
  306. CBaseObject* pObject = NewObject(cls, prev, file, newObjectName);
  307. return pObject;
  308. }
  309. //////////////////////////////////////////////////////////////////////////
  310. void CObjectManager::DeleteObject(CBaseObject* obj)
  311. {
  312. AZ_PROFILE_FUNCTION(Editor);
  313. if (m_currEditObject == obj)
  314. {
  315. EndEditParams();
  316. }
  317. if (!obj)
  318. {
  319. return;
  320. }
  321. // If object already deleted.
  322. if (obj->CheckFlags(OBJFLAG_DELETED))
  323. {
  324. return;
  325. }
  326. NotifyObjectListeners(obj, CBaseObject::ON_PREDELETE);
  327. obj->NotifyListeners(CBaseObject::ON_PREDELETE);
  328. // Must be after object DetachAll to support restoring Parent/Child relations.
  329. // AZ entity deletions are handled through the AZ undo system.
  330. if (CUndo::IsRecording() && obj->GetType() != OBJTYPE_AZENTITY)
  331. {
  332. // Store undo for all child objects.
  333. for (int i = 0; i < obj->GetChildCount(); i++)
  334. {
  335. obj->GetChild(i)->StoreUndo("DeleteParent");
  336. }
  337. CUndo::Record(new CUndoBaseObjectDelete(obj));
  338. }
  339. AABB objAAB;
  340. obj->GetBoundBox(objAAB);
  341. GetIEditor()->GetGameEngine()->OnAreaModified(objAAB);
  342. obj->Done();
  343. NotifyObjectListeners(obj, CBaseObject::ON_DELETE);
  344. RemoveObject(obj);
  345. }
  346. //////////////////////////////////////////////////////////////////////////
  347. void CObjectManager::DeleteSelection(CSelectionGroup* pSelection)
  348. {
  349. AZ_PROFILE_FUNCTION(Editor);
  350. if (pSelection == nullptr)
  351. {
  352. return;
  353. }
  354. // if the object contains an entity which has link, the link information should be recorded for undo separately. p
  355. if (CUndo::IsRecording())
  356. {
  357. for (int i = 0, iSize(pSelection->GetCount()); i < iSize; ++i)
  358. {
  359. CBaseObject* pObj = pSelection->GetObject(i);
  360. if (!qobject_cast<CEntityObject*>(pObj))
  361. {
  362. continue;
  363. }
  364. CEntityObject* pEntity = (CEntityObject*)pObj;
  365. if (pEntity->GetEntityLinkCount() <= 0)
  366. {
  367. continue;
  368. }
  369. CEntityObject::StoreUndoEntityLink(pSelection);
  370. break;
  371. }
  372. }
  373. AzToolsFramework::EntityIdList selectedComponentEntities;
  374. for (int i = 0, iObjSize(pSelection->GetCount()); i < iObjSize; i++)
  375. {
  376. CBaseObject* object = pSelection->GetObject(i);
  377. // AZ::Entity deletion is handled through AZ undo system (DeleteSelected bus call below).
  378. if (object->GetType() != OBJTYPE_AZENTITY)
  379. {
  380. DeleteObject(object);
  381. }
  382. else
  383. {
  384. AZ::EntityId id;
  385. EBUS_EVENT_ID_RESULT(id, object, AzToolsFramework::ComponentEntityObjectRequestBus, GetAssociatedEntityId);
  386. if (id.IsValid())
  387. {
  388. selectedComponentEntities.push_back(id);
  389. }
  390. }
  391. }
  392. // Delete AZ (component) entities.
  393. if (QApplication::keyboardModifiers() & Qt::ShiftModifier)
  394. {
  395. EBUS_EVENT(AzToolsFramework::ToolsApplicationRequests::Bus, DeleteEntities, selectedComponentEntities);
  396. }
  397. else
  398. {
  399. EBUS_EVENT(AzToolsFramework::ToolsApplicationRequests::Bus, DeleteEntitiesAndAllDescendants, selectedComponentEntities);
  400. }
  401. }
  402. //////////////////////////////////////////////////////////////////////////
  403. void CObjectManager::DeleteAllObjects()
  404. {
  405. AZ_PROFILE_FUNCTION(Editor);
  406. EndEditParams();
  407. ClearSelection();
  408. int i;
  409. InvalidateVisibleList();
  410. // Delete all selection groups.
  411. std::vector<CSelectionGroup*> sel;
  412. stl::map_to_vector(m_selections, sel);
  413. for (i = 0; i < sel.size(); i++)
  414. {
  415. delete sel[i];
  416. }
  417. m_selections.clear();
  418. TBaseObjects objectsHolder;
  419. GetAllObjects(objectsHolder);
  420. // Clear map. Need to do this before deleting objects in case someone tries to get object list during shutdown.
  421. m_objects.clear();
  422. m_objectsByName.clear();
  423. for (i = 0; i < objectsHolder.size(); i++)
  424. {
  425. objectsHolder[i]->Done();
  426. }
  427. //! Delete object instances.
  428. objectsHolder.clear();
  429. // Clear name map.
  430. m_nameNumbersMap.clear();
  431. m_animatedAttachedEntities.clear();
  432. }
  433. CBaseObject* CObjectManager::CloneObject(CBaseObject* obj)
  434. {
  435. AZ_PROFILE_FUNCTION(Editor);
  436. assert(obj);
  437. //CRuntimeClass *cls = obj->GetRuntimeClass();
  438. //CBaseObject *clone = (CBaseObject*)cls->CreateObject();
  439. //clone->CloneCopy( obj );
  440. CBaseObject* clone = NewObject(obj->GetClassDesc(), obj);
  441. return clone;
  442. }
  443. //////////////////////////////////////////////////////////////////////////
  444. CBaseObject* CObjectManager::FindObject(REFGUID guid) const
  445. {
  446. CBaseObject* result = stl::find_in_map(m_objects, guid, (CBaseObject*)nullptr);
  447. return result;
  448. }
  449. //////////////////////////////////////////////////////////////////////////
  450. CBaseObject* CObjectManager::FindObject(const QString& sName) const
  451. {
  452. const AZ::Crc32 crc(sName.toUtf8().data(), sName.toUtf8().count(), true);
  453. auto iter = m_objectsByName.find(crc);
  454. if (iter != m_objectsByName.end())
  455. {
  456. return iter->second;
  457. }
  458. return nullptr;
  459. }
  460. //////////////////////////////////////////////////////////////////////////
  461. void CObjectManager::FindObjectsOfType(ObjectType type, std::vector<CBaseObject*>& result)
  462. {
  463. result.clear();
  464. CBaseObjectsArray objects;
  465. GetObjects(objects);
  466. for (size_t i = 0, n = objects.size(); i < n; ++i)
  467. {
  468. if (objects[i]->GetType() == type)
  469. {
  470. result.push_back(objects[i]);
  471. }
  472. }
  473. }
  474. //////////////////////////////////////////////////////////////////////////
  475. void CObjectManager::FindObjectsOfType(const QMetaObject* pClass, std::vector<CBaseObject*>& result)
  476. {
  477. result.clear();
  478. CBaseObjectsArray objects;
  479. GetObjects(objects);
  480. for (size_t i = 0, n = objects.size(); i < n; ++i)
  481. {
  482. CBaseObject* pObject = objects[i];
  483. if (pObject->metaObject() == pClass)
  484. {
  485. result.push_back(pObject);
  486. }
  487. }
  488. }
  489. //////////////////////////////////////////////////////////////////////////
  490. void CObjectManager::FindObjectsInAABB(const AABB& aabb, std::vector<CBaseObject*>& result) const
  491. {
  492. result.clear();
  493. CBaseObjectsArray objects;
  494. GetObjects(objects);
  495. for (size_t i = 0, n = objects.size(); i < n; ++i)
  496. {
  497. CBaseObject* pObject = objects[i];
  498. AABB aabbObj;
  499. pObject->GetBoundBox(aabbObj);
  500. if (aabb.IsIntersectBox(aabbObj))
  501. {
  502. result.push_back(pObject);
  503. }
  504. }
  505. }
  506. //////////////////////////////////////////////////////////////////////////
  507. bool CObjectManager::AddObject(CBaseObject* obj)
  508. {
  509. CBaseObjectPtr p = stl::find_in_map(m_objects, obj->GetId(), nullptr);
  510. if (p)
  511. {
  512. CErrorRecord err;
  513. err.error = QObject::tr("New Object %1 has Duplicate GUID %2, New Object Ignored").arg(obj->GetName()).arg(GuidUtil::ToString(obj->GetId()));
  514. err.severity = CErrorRecord::ESEVERITY_ERROR;
  515. err.pObject = obj;
  516. err.flags = CErrorRecord::FLAG_OBJECTID;
  517. GetIEditor()->GetErrorReport()->ReportError(err);
  518. return false;
  519. }
  520. m_objects[obj->GetId()] = obj;
  521. // Handle adding object to type-specific containers if needed
  522. {
  523. if (CEntityObject* entityObj = qobject_cast<CEntityObject*>(obj))
  524. {
  525. CEntityObject::EAttachmentType attachType = entityObj->GetAttachType();
  526. if (attachType == CEntityObject::EAttachmentType::eAT_GeomCacheNode || attachType == CEntityObject::EAttachmentType::eAT_CharacterBone)
  527. {
  528. m_animatedAttachedEntities.insert(entityObj);
  529. }
  530. }
  531. }
  532. const AZ::Crc32 nameCrc(obj->GetName().toUtf8().data(), obj->GetName().toUtf8().count(), true);
  533. m_objectsByName[nameCrc] = obj;
  534. RegisterObjectName(obj->GetName());
  535. InvalidateVisibleList();
  536. NotifyObjectListeners(obj, CBaseObject::ON_ADD);
  537. return true;
  538. }
  539. //////////////////////////////////////////////////////////////////////////
  540. void CObjectManager::RemoveObject(CBaseObject* obj)
  541. {
  542. assert(obj != 0);
  543. InvalidateVisibleList();
  544. // Handle removing object from type-specific containers if needed
  545. {
  546. if (CEntityObject* entityObj = qobject_cast<CEntityObject*>(obj))
  547. {
  548. m_animatedAttachedEntities.erase(entityObj);
  549. }
  550. }
  551. // Remove this object from selection groups.
  552. m_currSelection->RemoveObject(obj);
  553. std::vector<CSelectionGroup*> sel;
  554. stl::map_to_vector(m_selections, sel);
  555. for (int i = 0; i < sel.size(); i++)
  556. {
  557. sel[i]->RemoveObject(obj);
  558. }
  559. m_objectsByName.erase(AZ::Crc32(obj->GetName().toUtf8().data(), obj->GetName().toUtf8().count(), true));
  560. // Need to erase this last since it is a smart pointer and can end up deleting the object if it is the last reference to it being kept
  561. m_objects.erase(obj->GetId());
  562. }
  563. //////////////////////////////////////////////////////////////////////////
  564. void CObjectManager::GetAllObjects(TBaseObjects& objects) const
  565. {
  566. objects.clear();
  567. objects.reserve(m_objects.size());
  568. for (Objects::const_iterator it = m_objects.begin(); it != m_objects.end(); ++it)
  569. {
  570. objects.push_back(it->second);
  571. }
  572. }
  573. //////////////////////////////////////////////////////////////////////////
  574. void CObjectManager::ChangeObjectId(REFGUID oldGuid, REFGUID newGuid)
  575. {
  576. Objects::iterator it = m_objects.find(oldGuid);
  577. if (it != m_objects.end())
  578. {
  579. CBaseObjectPtr pRemappedObject = (*it).second;
  580. pRemappedObject->SetId(newGuid);
  581. m_objects.erase(it);
  582. m_objects.insert(std::make_pair(newGuid, pRemappedObject));
  583. }
  584. }
  585. //////////////////////////////////////////////////////////////////////////
  586. void CObjectManager::ShowDuplicationMsgWarning(CBaseObject* obj, const QString& newName, bool bShowMsgBox) const
  587. {
  588. CBaseObject* pExisting = FindObject(newName);
  589. if (pExisting)
  590. {
  591. QString sRenameWarning = QObject::tr("%1 \"%2\" was NOT renamed to \"%3\" because %4 with the same name already exists.")
  592. .arg(obj->GetClassDesc()->ClassName())
  593. .arg(obj->GetName())
  594. .arg(newName)
  595. .arg(pExisting->GetClassDesc()->ClassName()
  596. );
  597. // If id is taken.
  598. CryWarning(VALIDATOR_MODULE_EDITOR, VALIDATOR_WARNING, sRenameWarning.toUtf8().data());
  599. if (bShowMsgBox)
  600. {
  601. QMessageBox::critical(QApplication::activeWindow(), QString(), sRenameWarning);
  602. }
  603. }
  604. }
  605. //////////////////////////////////////////////////////////////////////////
  606. void CObjectManager::ChangeObjectName(CBaseObject* obj, const QString& newName)
  607. {
  608. assert(obj);
  609. if (newName != obj->GetName())
  610. {
  611. if (IsDuplicateObjectName(newName))
  612. {
  613. return;
  614. }
  615. // Remove previous name from map
  616. const AZ::Crc32 oldNameCrc(obj->GetName().toUtf8().data(), obj->GetName().count(), true);
  617. m_objectsByName.erase(oldNameCrc);
  618. obj->SetName(newName);
  619. // Add new name to map
  620. const AZ::Crc32 nameCrc(newName.toUtf8().data(), newName.count(), true);
  621. m_objectsByName[nameCrc] = obj;
  622. }
  623. }
  624. //////////////////////////////////////////////////////////////////////////
  625. int CObjectManager::GetObjectCount() const
  626. {
  627. return static_cast<int>(m_objects.size());
  628. }
  629. //////////////////////////////////////////////////////////////////////////
  630. void CObjectManager::GetObjects(CBaseObjectsArray& objects) const
  631. {
  632. objects.clear();
  633. objects.reserve(m_objects.size());
  634. for (Objects::const_iterator it = m_objects.begin(); it != m_objects.end(); ++it)
  635. {
  636. objects.push_back(it->second);
  637. }
  638. }
  639. void CObjectManager::GetObjects(DynArray<CBaseObject*>& objects) const
  640. {
  641. CBaseObjectsArray objectArray;
  642. GetObjects(objectArray);
  643. objects.clear();
  644. for (size_t i = 0, iCount(objectArray.size()); i < iCount; ++i)
  645. {
  646. objects.push_back(objectArray[i]);
  647. }
  648. }
  649. void CObjectManager::GetObjects(CBaseObjectsArray& objects, BaseObjectFilterFunctor const& filter) const
  650. {
  651. objects.clear();
  652. objects.reserve(m_objects.size());
  653. for (Objects::const_iterator it = m_objects.begin(); it != m_objects.end(); ++it)
  654. {
  655. assert(it->second);
  656. if (filter.first(*it->second, filter.second))
  657. {
  658. objects.push_back(it->second);
  659. }
  660. }
  661. }
  662. //////////////////////////////////////////////////////////////////////////
  663. void CObjectManager::SendEvent(ObjectEvent event)
  664. {
  665. if (event == EVENT_RELOAD_ENTITY)
  666. {
  667. m_bInReloading = true;
  668. }
  669. for (Objects::iterator it = m_objects.begin(); it != m_objects.end(); ++it)
  670. {
  671. CBaseObject* obj = it->second;
  672. obj->OnEvent(event);
  673. }
  674. if (event == EVENT_RELOAD_ENTITY)
  675. {
  676. m_bInReloading = false;
  677. GetIEditor()->Notify(eNotify_OnReloadTrackView);
  678. }
  679. }
  680. //////////////////////////////////////////////////////////////////////////
  681. void CObjectManager::SendEvent(ObjectEvent event, const AABB& bounds)
  682. {
  683. AABB box;
  684. for (Objects::iterator it = m_objects.begin(); it != m_objects.end(); ++it)
  685. {
  686. CBaseObject* obj = it->second;
  687. obj->GetBoundBox(box);
  688. if (bounds.IsIntersectBox(box))
  689. {
  690. obj->OnEvent(event);
  691. }
  692. }
  693. }
  694. //////////////////////////////////////////////////////////////////////////
  695. void CObjectManager::Update()
  696. {
  697. if (m_bSkipObjectUpdate)
  698. {
  699. return;
  700. }
  701. QWidget* prevActiveWindow = QApplication::activeWindow();
  702. // Restore focus if it changed.
  703. if (prevActiveWindow && QApplication::activeWindow() != prevActiveWindow)
  704. {
  705. prevActiveWindow->setFocus();
  706. }
  707. }
  708. //////////////////////////////////////////////////////////////////////////
  709. void CObjectManager::HideObject(CBaseObject* obj, bool hide)
  710. {
  711. assert(obj != 0);
  712. if (hide)
  713. {
  714. obj->SetHidden(hide, ++m_currentHideCount);
  715. }
  716. else
  717. {
  718. obj->SetHidden(false);
  719. }
  720. InvalidateVisibleList();
  721. }
  722. void CObjectManager::ShowLastHiddenObject()
  723. {
  724. uint64 mostRecentID = CBaseObject::s_invalidHiddenID;
  725. CBaseObject* mostRecentObject = nullptr;
  726. for (auto it : m_objects)
  727. {
  728. CBaseObject* obj = it.second;
  729. uint64 hiddenID = obj->GetHideOrder();
  730. if (hiddenID > mostRecentID)
  731. {
  732. mostRecentID = hiddenID;
  733. mostRecentObject = obj;
  734. }
  735. }
  736. if (mostRecentObject != nullptr)
  737. {
  738. mostRecentObject->SetHidden(false);
  739. }
  740. }
  741. //////////////////////////////////////////////////////////////////////////
  742. void CObjectManager::UnhideAll()
  743. {
  744. for (Objects::iterator it = m_objects.begin(); it != m_objects.end(); ++it)
  745. {
  746. CBaseObject* obj = it->second;
  747. obj->SetHidden(false);
  748. }
  749. InvalidateVisibleList();
  750. }
  751. //////////////////////////////////////////////////////////////////////////
  752. void CObjectManager::FreezeObject(CBaseObject* obj, bool freeze)
  753. {
  754. assert(obj != 0);
  755. // Remove object from main object set and put it to hidden set.
  756. obj->SetFrozen(freeze);
  757. InvalidateVisibleList();
  758. }
  759. //////////////////////////////////////////////////////////////////////////
  760. void CObjectManager::UnfreezeAll()
  761. {
  762. for (Objects::iterator it = m_objects.begin(); it != m_objects.end(); ++it)
  763. {
  764. CBaseObject* obj = it->second;
  765. obj->SetFrozen(false);
  766. }
  767. InvalidateVisibleList();
  768. }
  769. //////////////////////////////////////////////////////////////////////////
  770. bool CObjectManager::SelectObject(CBaseObject* obj, bool bUseMask)
  771. {
  772. assert(obj);
  773. if (obj == nullptr)
  774. {
  775. return false;
  776. }
  777. // Check if can be selected.
  778. if (bUseMask && (!(obj->GetType() & gSettings.objectSelectMask)))
  779. {
  780. return false;
  781. }
  782. if (m_selectCallback)
  783. {
  784. if (!m_selectCallback->OnSelectObject(obj))
  785. {
  786. return true;
  787. }
  788. }
  789. m_currSelection->AddObject(obj);
  790. // while in ComponentMode we never explicitly change selection (the entity will always be selected).
  791. // this check is to handle the case where an undo or redo action has occurred and
  792. // the entity has been destroyed and recreated as part of the deserialization step.
  793. // we want the internal state to stay consistent but do not want to notify other systems of the change.
  794. if (AzToolsFramework::ComponentModeFramework::InComponentMode())
  795. {
  796. obj->SetSelected(true);
  797. }
  798. else
  799. {
  800. SetObjectSelected(obj, true);
  801. GetIEditor()->Notify(eNotify_OnSelectionChange);
  802. }
  803. return true;
  804. }
  805. void CObjectManager::SelectEntities(std::set<CEntityObject*>& s)
  806. {
  807. for (std::set<CEntityObject*>::iterator it = s.begin(), end = s.end(); it != end; ++it)
  808. {
  809. SelectObject(*it);
  810. }
  811. }
  812. void CObjectManager::UnselectObject(CBaseObject* obj)
  813. {
  814. // while in ComponentMode we never explicitly change selection (the entity will always be selected).
  815. // this check is to handle the case where an undo or redo action has occurred and
  816. // the entity has been destroyed and recreated as part of the deserialization step.
  817. // we want the internal state to stay consistent but do not want to notify other systems of the change.
  818. if (AzToolsFramework::ComponentModeFramework::InComponentMode())
  819. {
  820. obj->SetSelected(false);
  821. }
  822. else
  823. {
  824. SetObjectSelected(obj, false);
  825. }
  826. m_currSelection->RemoveObject(obj);
  827. }
  828. CSelectionGroup* CObjectManager::GetSelection(const QString& name) const
  829. {
  830. CSelectionGroup* selection = stl::find_in_map(m_selections, name, (CSelectionGroup*)nullptr);
  831. return selection;
  832. }
  833. void CObjectManager::GetNameSelectionStrings(QStringList& names)
  834. {
  835. for (TNameSelectionMap::iterator it = m_selections.begin(); it != m_selections.end(); ++it)
  836. {
  837. names.push_back(it->first);
  838. }
  839. }
  840. void CObjectManager::NameSelection(const QString& name)
  841. {
  842. if (m_currSelection->IsEmpty())
  843. {
  844. return;
  845. }
  846. CSelectionGroup* selection = stl::find_in_map(m_selections, name, (CSelectionGroup*)nullptr);
  847. if (selection)
  848. {
  849. assert(selection != 0);
  850. // Check if trying to rename itself to the same name.
  851. if (selection == m_currSelection)
  852. {
  853. return;
  854. }
  855. m_selections.erase(name);
  856. delete selection;
  857. }
  858. selection = new CSelectionGroup;
  859. selection->Copy(*m_currSelection);
  860. selection->SetName(name);
  861. m_selections[name] = selection;
  862. m_currSelection = selection;
  863. m_defaultSelection.RemoveAll();
  864. }
  865. void CObjectManager::SerializeNameSelection(XmlNodeRef& rootNode, bool bLoading)
  866. {
  867. if (!rootNode)
  868. {
  869. return;
  870. }
  871. _smart_ptr<CSelectionGroup> tmpGroup(nullptr);
  872. QString selRootStr("NameSelection");
  873. QString selNodeStr("NameSelectionNode");
  874. QString selNodeNameStr("name");
  875. QString idStr("id");
  876. QString objAttrStr("obj");
  877. XmlNodeRef startNode = rootNode->findChild(selRootStr.toUtf8().data());
  878. if (bLoading)
  879. {
  880. m_selections.erase(m_selections.begin(), m_selections.end());
  881. if (startNode)
  882. {
  883. for (int selNodeNo = 0; selNodeNo < startNode->getChildCount(); ++selNodeNo)
  884. {
  885. XmlNodeRef selNode = startNode->getChild(selNodeNo);
  886. tmpGroup = new CSelectionGroup;
  887. for (int objIDNodeNo = 0; objIDNodeNo < selNode->getChildCount(); ++objIDNodeNo)
  888. {
  889. GUID curID = GUID_NULL;
  890. XmlNodeRef idNode = selNode->getChild(objIDNodeNo);
  891. if (!idNode->getAttr(idStr.toUtf8().data(), curID))
  892. {
  893. continue;
  894. }
  895. if (curID != GUID_NULL)
  896. {
  897. if (GetIEditor()->GetObjectManager()->FindObject(curID))
  898. {
  899. tmpGroup->AddObject(GetIEditor()->GetObjectManager()->FindObject(curID));
  900. }
  901. }
  902. }
  903. if (tmpGroup->GetCount() > 0)
  904. {
  905. QString nameStr;
  906. if (!selNode->getAttr(selNodeNameStr.toUtf8().data(), nameStr))
  907. {
  908. continue;
  909. }
  910. tmpGroup->SetName(nameStr);
  911. m_selections[nameStr] = tmpGroup;
  912. }
  913. }
  914. }
  915. }
  916. else
  917. {
  918. startNode = rootNode->newChild(selRootStr.toUtf8().data());
  919. CSelectionGroup* objSelection = nullptr;
  920. for (TNameSelectionMap::iterator it = m_selections.begin(); it != m_selections.end(); ++it)
  921. {
  922. XmlNodeRef selectionNameNode = startNode->newChild(selNodeStr.toUtf8().data());
  923. selectionNameNode->setAttr(selNodeNameStr.toUtf8().data(), it->first.toUtf8().data());
  924. objSelection = it->second;
  925. if (!objSelection)
  926. {
  927. continue;
  928. }
  929. if (objSelection->GetCount() == 0)
  930. {
  931. continue;
  932. }
  933. for (int i = 0; i < objSelection->GetCount(); ++i)
  934. {
  935. if (objSelection->GetObject(i))
  936. {
  937. XmlNodeRef objNode = selectionNameNode->newChild(objAttrStr.toUtf8().data());
  938. objNode->setAttr(idStr.toUtf8().data(), GuidUtil::ToString(objSelection->GetObject(i)->GetId()));
  939. }
  940. }
  941. }
  942. }
  943. }
  944. //////////////////////////////////////////////////////////////////////////
  945. int CObjectManager::ClearSelection()
  946. {
  947. AZ_PROFILE_FUNCTION(Editor);
  948. // Make sure to unlock selection.
  949. GetIEditor()->LockSelection(false);
  950. int numSel = m_currSelection->GetCount();
  951. // Handle Undo/Redo of Component Entities
  952. bool isUndoRecording = GetIEditor()->IsUndoRecording();
  953. if (isUndoRecording)
  954. {
  955. m_processingBulkSelect = true;
  956. GetIEditor()->RecordUndo(new CUndoBaseObjectClearSelection(*m_currSelection));
  957. }
  958. // Handle legacy entities separately so the selection group can be cleared safely.
  959. // This prevents every AzEntity from being removed one by one from a vector.
  960. m_currSelection->RemoveAllExceptLegacySet();
  961. // Kick off Deselect for Legacy Entities
  962. for (CBaseObjectPtr legacyObject : m_currSelection->GetLegacyObjects())
  963. {
  964. if (isUndoRecording && legacyObject->IsSelected())
  965. {
  966. GetIEditor()->RecordUndo(new CUndoBaseObjectSelect(legacyObject));
  967. }
  968. SetObjectSelected(legacyObject, false);
  969. }
  970. // Legacy set is cleared
  971. m_defaultSelection.RemoveAll();
  972. m_currSelection = &m_defaultSelection;
  973. m_bSelectionChanged = true;
  974. // Unselect all component entities as one bulk operation instead of individually
  975. AzToolsFramework::ToolsApplicationRequestBus::Broadcast(
  976. &AzToolsFramework::ToolsApplicationRequests::SetSelectedEntities,
  977. AzToolsFramework::EntityIdList());
  978. m_processingBulkSelect = false;
  979. if (!m_bExiting)
  980. {
  981. GetIEditor()->Notify(eNotify_OnSelectionChange);
  982. }
  983. return numSel;
  984. }
  985. //////////////////////////////////////////////////////////////////////////
  986. int CObjectManager::InvertSelection()
  987. {
  988. AZ_PROFILE_FUNCTION(Editor);
  989. int selCount = 0;
  990. // iterate all objects.
  991. for (Objects::const_iterator it = m_objects.begin(); it != m_objects.end(); ++it)
  992. {
  993. CBaseObject* pObj = it->second;
  994. if (pObj->IsSelected())
  995. {
  996. UnselectObject(pObj);
  997. }
  998. else
  999. {
  1000. if (SelectObject(pObj))
  1001. {
  1002. selCount++;
  1003. }
  1004. }
  1005. }
  1006. return selCount;
  1007. }
  1008. void CObjectManager::SetSelection(const QString& name)
  1009. {
  1010. AZ_PROFILE_FUNCTION(Editor);
  1011. CSelectionGroup* selection = stl::find_in_map(m_selections, name, (CSelectionGroup*)nullptr);
  1012. if (selection)
  1013. {
  1014. UnselectCurrent();
  1015. assert(selection != 0);
  1016. m_currSelection = selection;
  1017. SelectCurrent();
  1018. }
  1019. }
  1020. void CObjectManager::RemoveSelection(const QString& name)
  1021. {
  1022. AZ_PROFILE_FUNCTION(Editor);
  1023. QString selName = name;
  1024. CSelectionGroup* selection = stl::find_in_map(m_selections, name, (CSelectionGroup*)nullptr);
  1025. if (selection)
  1026. {
  1027. if (selection == m_currSelection)
  1028. {
  1029. UnselectCurrent();
  1030. m_currSelection = &m_defaultSelection;
  1031. m_defaultSelection.RemoveAll();
  1032. }
  1033. delete selection;
  1034. m_selections.erase(selName);
  1035. }
  1036. }
  1037. void CObjectManager::SelectCurrent()
  1038. {
  1039. AZ_PROFILE_FUNCTION(Editor);
  1040. for (int i = 0; i < m_currSelection->GetCount(); i++)
  1041. {
  1042. CBaseObject* obj = m_currSelection->GetObject(i);
  1043. if (GetIEditor()->IsUndoRecording() && !obj->IsSelected())
  1044. {
  1045. GetIEditor()->RecordUndo(new CUndoBaseObjectSelect(obj));
  1046. }
  1047. SetObjectSelected(obj, true);
  1048. }
  1049. }
  1050. void CObjectManager::UnselectCurrent()
  1051. {
  1052. AZ_PROFILE_FUNCTION(Editor);
  1053. // Make sure to unlock selection.
  1054. GetIEditor()->LockSelection(false);
  1055. // Unselect all component entities as one bulk operation instead of individually
  1056. AzToolsFramework::EntityIdList selectedEntities;
  1057. EBUS_EVENT(AzToolsFramework::ToolsApplicationRequests::Bus, SetSelectedEntities, selectedEntities);
  1058. for (int i = 0; i < m_currSelection->GetCount(); i++)
  1059. {
  1060. CBaseObject* obj = m_currSelection->GetObject(i);
  1061. if (GetIEditor()->IsUndoRecording() && obj->IsSelected())
  1062. {
  1063. GetIEditor()->RecordUndo(new CUndoBaseObjectSelect(obj));
  1064. }
  1065. SetObjectSelected(obj, false);
  1066. }
  1067. }
  1068. //////////////////////////////////////////////////////////////////////////
  1069. void CObjectManager::Display(DisplayContext& dc)
  1070. {
  1071. AZ_PROFILE_FUNCTION(Editor);
  1072. int currentHideMask = GetIEditor()->GetDisplaySettings()->GetObjectHideMask();
  1073. if (m_lastHideMask != currentHideMask)
  1074. {
  1075. // a setting has changed which may cause the set of currently visible objects to change, so invalidate the serial number
  1076. // so that viewports and anyone else that needs to update settings knows it has to.
  1077. m_lastHideMask = currentHideMask;
  1078. ++m_visibilitySerialNumber;
  1079. }
  1080. // the object manager itself has a visibility list, so it also has to update its cache when the serial has changed
  1081. if (m_visibilitySerialNumber != m_lastComputedVisibility)
  1082. {
  1083. m_lastComputedVisibility = m_visibilitySerialNumber;
  1084. UpdateVisibilityList();
  1085. }
  1086. bool viewIsDirty = dc.settings->IsDisplayHelpers(); // displaying helpers require computing all the bound boxes and things anyway.
  1087. if (!viewIsDirty)
  1088. {
  1089. if (CBaseObjectsCache* cache = dc.view->GetVisibleObjectsCache())
  1090. {
  1091. // if the current rendering viewport has an out-of-date cache serial number, it needs to be refreshed too.
  1092. // views set their cache empty when they indicate they need to force a refresh.
  1093. if ((cache->GetObjectCount() == 0) || (cache->GetSerialNumber() != m_visibilitySerialNumber))
  1094. {
  1095. viewIsDirty = true;
  1096. }
  1097. }
  1098. }
  1099. if (viewIsDirty)
  1100. {
  1101. FindDisplayableObjects(dc, true); // this also actually draws the helpers.
  1102. // Also broadcast for anyone else that needs to draw global debug to do so now
  1103. AzFramework::DebugDisplayEventBus::Broadcast(&AzFramework::DebugDisplayEvents::DrawGlobalDebugInfo);
  1104. }
  1105. if (m_gizmoManager)
  1106. {
  1107. m_gizmoManager->Display(dc);
  1108. }
  1109. }
  1110. void CObjectManager::ForceUpdateVisibleObjectCache(DisplayContext& dc)
  1111. {
  1112. FindDisplayableObjects(dc, false);
  1113. }
  1114. void CObjectManager::FindDisplayableObjects(DisplayContext& dc, [[maybe_unused]] bool bDisplay)
  1115. {
  1116. // if the new IVisibilitySystem is being used, do not run this logic
  1117. if (ed_visibility_use)
  1118. {
  1119. return;
  1120. }
  1121. AZ_PROFILE_FUNCTION(Editor);
  1122. auto start = std::chrono::steady_clock::now();
  1123. CBaseObjectsCache* pDispayedViewObjects = dc.view->GetVisibleObjectsCache();
  1124. if (!pDispayedViewObjects)
  1125. {
  1126. return;
  1127. }
  1128. pDispayedViewObjects->SetSerialNumber(m_visibilitySerialNumber); // update viewport to be latest serial number
  1129. AABB bbox;
  1130. bbox.min.zero();
  1131. bbox.max.zero();
  1132. pDispayedViewObjects->ClearObjects();
  1133. pDispayedViewObjects->Reserve(static_cast<int>(m_visibleObjects.size()));
  1134. if (dc.flags & DISPLAY_2D)
  1135. {
  1136. int numVis = static_cast<int>(m_visibleObjects.size());
  1137. for (int i = 0; i < numVis; i++)
  1138. {
  1139. CBaseObject* obj = m_visibleObjects[i];
  1140. obj->GetBoundBox(bbox);
  1141. if (dc.box.IsIntersectBox(bbox))
  1142. {
  1143. pDispayedViewObjects->AddObject(obj);
  1144. }
  1145. }
  1146. }
  1147. else
  1148. {
  1149. CSelectionGroup* pSelection = GetSelection();
  1150. if (pSelection && pSelection->GetCount() > 1)
  1151. {
  1152. AABB mergedAABB;
  1153. mergedAABB.Reset();
  1154. for (int i = 0, iCount(pSelection->GetCount()); i < iCount; ++i)
  1155. {
  1156. CBaseObject* pObj(pSelection->GetObject(i));
  1157. if (pObj == nullptr)
  1158. {
  1159. continue;
  1160. }
  1161. AABB aabb;
  1162. pObj->GetBoundBox(aabb);
  1163. mergedAABB.Add(aabb);
  1164. }
  1165. pSelection->GetObject(0)->CBaseObject::DrawDimensions(dc, &mergedAABB);
  1166. }
  1167. int numVis = static_cast<int>(m_visibleObjects.size());
  1168. for (int i = 0; i < numVis; i++)
  1169. {
  1170. CBaseObject* obj = m_visibleObjects[i];
  1171. if (obj)
  1172. {
  1173. if ((dc.flags & DISPLAY_SELECTION_HELPERS) || obj->IsSelected())
  1174. {
  1175. pDispayedViewObjects->AddObject(obj);
  1176. }
  1177. }
  1178. }
  1179. }
  1180. if (ed_visibility_logTiming && !ed_visibility_use)
  1181. {
  1182. auto stop = std::chrono::steady_clock::now();
  1183. std::chrono::duration<double> diff = stop - start;
  1184. AZ_Printf("Visibility", "FindDisplayableObjects (old) - Duration: %f", diff);
  1185. }
  1186. }
  1187. void CObjectManager::BeginEditParams(CBaseObject* obj, int flags)
  1188. {
  1189. assert(obj != 0);
  1190. if (obj == m_currEditObject)
  1191. {
  1192. return;
  1193. }
  1194. if (GetSelection()->GetCount() > 1)
  1195. {
  1196. return;
  1197. }
  1198. QWidget* prevActiveWindow = QApplication::activeWindow();
  1199. if (m_currEditObject)
  1200. {
  1201. //if (obj->GetClassDesc() != m_currEditObject->GetClassDesc())
  1202. if (!obj->IsSameClass(m_currEditObject))
  1203. {
  1204. EndEditParams(flags);
  1205. }
  1206. }
  1207. m_currEditObject = obj;
  1208. if (flags & OBJECT_CREATE)
  1209. {
  1210. // Unselect all other objects.
  1211. ClearSelection();
  1212. // Select this object.
  1213. SelectObject(obj, false);
  1214. }
  1215. m_bSingleSelection = true;
  1216. // Restore focus if it changed.
  1217. // OBJECT_EDIT is used by the EntityOutliner when items are selected. Using it here to prevent shifting focus to the EntityInspector on select.
  1218. if (!(flags & OBJECT_EDIT) && prevActiveWindow && QApplication::activeWindow() != prevActiveWindow)
  1219. {
  1220. prevActiveWindow->setFocus();
  1221. }
  1222. }
  1223. void CObjectManager::EndEditParams([[maybe_unused]] int flags)
  1224. {
  1225. m_bSingleSelection = false;
  1226. m_currEditObject = nullptr;
  1227. //m_bSelectionChanged = false; // don't need to clear for ungroup
  1228. }
  1229. //! Select objects within specified distance from given position.
  1230. int CObjectManager::SelectObjects(const AABB& box, bool bUnselect)
  1231. {
  1232. AZ_PROFILE_FUNCTION(Editor);
  1233. int numSel = 0;
  1234. AABB objBounds;
  1235. for (Objects::iterator it = m_objects.begin(); it != m_objects.end(); ++it)
  1236. {
  1237. CBaseObject* obj = it->second;
  1238. if (obj->IsHidden())
  1239. {
  1240. continue;
  1241. }
  1242. obj->GetBoundBox(objBounds);
  1243. if (box.IsIntersectBox(objBounds))
  1244. {
  1245. numSel++;
  1246. if (!bUnselect)
  1247. {
  1248. SelectObject(obj);
  1249. }
  1250. else
  1251. {
  1252. UnselectObject(obj);
  1253. }
  1254. }
  1255. }
  1256. return numSel;
  1257. }
  1258. //////////////////////////////////////////////////////////////////////////
  1259. int CObjectManager::MoveObjects(const AABB& box, const Vec3& offset, ImageRotationDegrees rotation, [[maybe_unused]] bool bIsCopy)
  1260. {
  1261. AABB objBounds;
  1262. Vec3 src = (box.min + box.max) / 2;
  1263. Vec3 dst = src + offset;
  1264. float alpha = 0.0f;
  1265. switch (rotation)
  1266. {
  1267. case ImageRotationDegrees::Rotate90:
  1268. alpha = gf_halfPI;
  1269. break;
  1270. case ImageRotationDegrees::Rotate180:
  1271. alpha = gf_PI;
  1272. break;
  1273. case ImageRotationDegrees::Rotate270:
  1274. alpha = gf_PI + gf_halfPI;
  1275. break;
  1276. default:
  1277. break;
  1278. }
  1279. float cosa = cos(alpha);
  1280. float sina = sin(alpha);
  1281. for (Objects::iterator it = m_objects.begin(); it != m_objects.end(); ++it)
  1282. {
  1283. CBaseObject* obj = it->second;
  1284. if (obj->GetParent())
  1285. {
  1286. continue;
  1287. }
  1288. obj->GetBoundBox(objBounds);
  1289. if (box.IsIntersectBox(objBounds))
  1290. {
  1291. if (rotation == ImageRotationDegrees::Rotate0)
  1292. {
  1293. obj->SetPos(obj->GetPos() - src + dst);
  1294. }
  1295. else
  1296. {
  1297. Vec3 pos = obj->GetPos() - src;
  1298. Vec3 newPos(pos);
  1299. newPos.x = cosa * pos.x - sina * pos.y;
  1300. newPos.y = sina * pos.x + cosa * pos.y;
  1301. obj->SetPos(newPos + dst);
  1302. Quat q;
  1303. obj->SetRotation(q.CreateRotationZ(alpha) * obj->GetRotation());
  1304. }
  1305. }
  1306. }
  1307. return 0;
  1308. }
  1309. bool CObjectManager::IsObjectDeletionAllowed(CBaseObject* pObject)
  1310. {
  1311. if (!pObject)
  1312. {
  1313. return false;
  1314. }
  1315. return true;
  1316. };
  1317. //////////////////////////////////////////////////////////////////////////
  1318. void CObjectManager::DeleteSelection()
  1319. {
  1320. AZ_PROFILE_FUNCTION(Editor);
  1321. // Make sure to unlock selection.
  1322. GetIEditor()->LockSelection(false);
  1323. CSelectionGroup objects;
  1324. for (int i = 0; i < m_currSelection->GetCount(); i++)
  1325. {
  1326. // Check condition(s) if object could be deleted
  1327. if (!IsObjectDeletionAllowed(m_currSelection->GetObject(i)))
  1328. {
  1329. return;
  1330. }
  1331. objects.AddObject(m_currSelection->GetObject(i));
  1332. }
  1333. RemoveSelection(m_currSelection->GetName());
  1334. m_currSelection = &m_defaultSelection;
  1335. m_defaultSelection.RemoveAll();
  1336. DeleteSelection(&objects);
  1337. }
  1338. //////////////////////////////////////////////////////////////////////////
  1339. bool CObjectManager::HitTestObject(CBaseObject* obj, HitContext& hc)
  1340. {
  1341. AZ_PROFILE_FUNCTION(Editor);
  1342. if (obj->IsFrozen())
  1343. {
  1344. return false;
  1345. }
  1346. if (obj->IsHidden())
  1347. {
  1348. return false;
  1349. }
  1350. // This object is rejected by deep selection.
  1351. if (obj->CheckFlags(OBJFLAG_NO_HITTEST))
  1352. {
  1353. return false;
  1354. }
  1355. ObjectType objType = obj->GetType();
  1356. // Check if this object type is masked for selection.
  1357. if (!(objType & gSettings.objectSelectMask))
  1358. {
  1359. return false;
  1360. }
  1361. const bool bSelectionHelperHit = obj->HitHelperTest(hc);
  1362. if (hc.bUseSelectionHelpers && !bSelectionHelperHit)
  1363. {
  1364. return false;
  1365. }
  1366. if (!bSelectionHelperHit)
  1367. {
  1368. // Fast checking.
  1369. if (hc.camera && !obj->IsInCameraView(*hc.camera))
  1370. {
  1371. return false;
  1372. }
  1373. else if (hc.bounds && !obj->IntersectRectBounds(*hc.bounds))
  1374. {
  1375. return false;
  1376. }
  1377. // Do 2D space testing.
  1378. if (hc.nSubObjFlags == 0)
  1379. {
  1380. Ray ray(hc.raySrc, hc.rayDir);
  1381. if (!obj->IntersectRayBounds(ray))
  1382. {
  1383. return false;
  1384. }
  1385. }
  1386. else if (!obj->HitTestRect(hc))
  1387. {
  1388. return false;
  1389. }
  1390. }
  1391. return (bSelectionHelperHit || obj->HitTest(hc));
  1392. }
  1393. //////////////////////////////////////////////////////////////////////////
  1394. bool CObjectManager::HitTest(HitContext& hitInfo)
  1395. {
  1396. AZ_PROFILE_FUNCTION(Editor);
  1397. hitInfo.object = nullptr;
  1398. hitInfo.dist = FLT_MAX;
  1399. hitInfo.axis = 0;
  1400. hitInfo.manipulatorMode = 0;
  1401. HitContext hcOrg = hitInfo;
  1402. if (hcOrg.view)
  1403. {
  1404. hcOrg.view->GetPerpendicularAxis(nullptr, &hcOrg.b2DViewport);
  1405. }
  1406. hcOrg.rayDir = hcOrg.rayDir.GetNormalized();
  1407. HitContext hc = hcOrg;
  1408. float mindist = FLT_MAX;
  1409. if (!hitInfo.bIgnoreAxis && !hc.bUseSelectionHelpers)
  1410. {
  1411. // Test gizmos.
  1412. if (m_gizmoManager->HitTest(hc))
  1413. {
  1414. if (hc.axis != 0)
  1415. {
  1416. hitInfo.object = hc.object;
  1417. hitInfo.gizmo = hc.gizmo;
  1418. hitInfo.axis = hc.axis;
  1419. hitInfo.manipulatorMode = hc.manipulatorMode;
  1420. hitInfo.dist = hc.dist;
  1421. return true;
  1422. }
  1423. }
  1424. }
  1425. if (hitInfo.bOnlyGizmo)
  1426. {
  1427. return false;
  1428. }
  1429. // Only HitTest objects, that where previously Displayed.
  1430. CBaseObjectsCache* pDispayedViewObjects = hitInfo.view->GetVisibleObjectsCache();
  1431. const bool iconsPrioritized = true; // Force icons to always be prioritized over other things you hit. Can change to be a configurable option in the future.
  1432. CBaseObject* selected = nullptr;
  1433. const char* name = nullptr;
  1434. bool iconHit = false;
  1435. int numVis = pDispayedViewObjects->GetObjectCount();
  1436. for (int i = 0; i < numVis; i++)
  1437. {
  1438. CBaseObject* obj = pDispayedViewObjects->GetObject(i);
  1439. if (obj == hitInfo.pExcludedObject)
  1440. {
  1441. continue;
  1442. }
  1443. if (HitTestObject(obj, hc))
  1444. {
  1445. if (m_selectCallback && !m_selectCallback->CanSelectObject(obj))
  1446. {
  1447. continue;
  1448. }
  1449. // Check if this object is nearest.
  1450. if (hc.axis != 0)
  1451. {
  1452. hitInfo.object = obj;
  1453. hitInfo.axis = hc.axis;
  1454. hitInfo.dist = hc.dist;
  1455. return true;
  1456. }
  1457. // When prioritizing icons, we don't allow non-icon hits to beat icon hits
  1458. if (iconsPrioritized && iconHit && !hc.iconHit)
  1459. {
  1460. continue;
  1461. }
  1462. if (hc.dist < mindist || (!iconHit && hc.iconHit))
  1463. {
  1464. if (hc.iconHit)
  1465. {
  1466. iconHit = true;
  1467. }
  1468. mindist = hc.dist;
  1469. name = hc.name;
  1470. selected = obj;
  1471. }
  1472. // Clear the object pointer if an object was hit, not just if the collision
  1473. // was closer than any previous. Not all paths from HitTestObject set the object pointer and so you could get
  1474. // an object from a previous (rejected) result but with collision information about a closer hit.
  1475. hc.object = nullptr;
  1476. hc.iconHit = false;
  1477. // If use deep selection
  1478. if (hitInfo.pDeepSelection)
  1479. {
  1480. hitInfo.pDeepSelection->AddObject(hc.dist, obj);
  1481. }
  1482. }
  1483. }
  1484. if (selected)
  1485. {
  1486. hitInfo.object = selected;
  1487. hitInfo.dist = mindist;
  1488. hitInfo.name = name;
  1489. hitInfo.iconHit = iconHit;
  1490. return true;
  1491. }
  1492. return false;
  1493. }
  1494. void CObjectManager::FindObjectsInRect(CViewport* view, const QRect& rect, std::vector<GUID>& guids)
  1495. {
  1496. AZ_PROFILE_FUNCTION(Editor);
  1497. if (rect.width() < 1 || rect.height() < 1)
  1498. {
  1499. return;
  1500. }
  1501. HitContext hc;
  1502. hc.view = view;
  1503. hc.b2DViewport = view->GetType() != ET_ViewportCamera;
  1504. hc.rect = rect;
  1505. hc.bUseSelectionHelpers = view->GetAdvancedSelectModeFlag();
  1506. guids.clear();
  1507. CBaseObjectsCache* pDispayedViewObjects = view->GetVisibleObjectsCache();
  1508. int numVis = pDispayedViewObjects->GetObjectCount();
  1509. for (int i = 0; i < numVis; ++i)
  1510. {
  1511. CBaseObject* pObj = pDispayedViewObjects->GetObject(i);
  1512. HitTestObjectAgainstRect(pObj, view, hc, guids);
  1513. }
  1514. }
  1515. //////////////////////////////////////////////////////////////////////////
  1516. void CObjectManager::SelectObjectsInRect(CViewport* view, const QRect& rect, bool bSelect)
  1517. {
  1518. AZ_PROFILE_FUNCTION(Editor);
  1519. // Ignore too small rectangles.
  1520. if (rect.width() < 1 || rect.height() < 1)
  1521. {
  1522. return;
  1523. }
  1524. CUndo undo("Select Object(s)");
  1525. HitContext hc;
  1526. hc.view = view;
  1527. hc.b2DViewport = view->GetType() != ET_ViewportCamera;
  1528. hc.rect = rect;
  1529. hc.bUseSelectionHelpers = view->GetAdvancedSelectModeFlag();
  1530. bool isUndoRecording = GetIEditor()->IsUndoRecording();
  1531. if (isUndoRecording)
  1532. {
  1533. m_processingBulkSelect = true;
  1534. }
  1535. CBaseObjectsCache* displayedViewObjects = view->GetVisibleObjectsCache();
  1536. int numVis = displayedViewObjects->GetObjectCount();
  1537. // Tracking the previous selection allows proper undo/redo functionality of additional
  1538. // selections (CTRL + drag select)
  1539. AZStd::unordered_set<const CBaseObject*> previousSelection;
  1540. for (int i = 0; i < numVis; ++i)
  1541. {
  1542. CBaseObject* object = displayedViewObjects->GetObject(i);
  1543. if (object->IsSelected())
  1544. {
  1545. previousSelection.insert(object);
  1546. }
  1547. else
  1548. {
  1549. // This will update m_currSelection
  1550. SelectObjectInRect(object, view, hc, bSelect);
  1551. // Legacy undo/redo does not go through the Ebus system and must be done individually
  1552. if (isUndoRecording && object->GetType() != OBJTYPE_AZENTITY)
  1553. {
  1554. GetIEditor()->RecordUndo(new CUndoBaseObjectSelect(object, true));
  1555. }
  1556. }
  1557. }
  1558. if (isUndoRecording && m_currSelection)
  1559. {
  1560. // Component Entities can handle undo/redo in bulk due to Ebuses
  1561. GetIEditor()->RecordUndo(new CUndoBaseObjectBulkSelect(previousSelection, *m_currSelection));
  1562. }
  1563. m_processingBulkSelect = false;
  1564. }
  1565. //////////////////////////////////////////////////////////////////////////
  1566. uint16 FindPossibleObjectNameNumber(std::set<uint16>& numberSet)
  1567. {
  1568. const int LIMIT = 65535;
  1569. size_t nSetSize = numberSet.size();
  1570. for (uint16 i = 1; i < LIMIT; ++i)
  1571. {
  1572. uint16 candidateNumber = (i + nSetSize) % LIMIT;
  1573. if (numberSet.find(candidateNumber) == numberSet.end())
  1574. {
  1575. numberSet.insert(candidateNumber);
  1576. return candidateNumber;
  1577. }
  1578. }
  1579. return 0;
  1580. }
  1581. void CObjectManager::RegisterObjectName(const QString& name)
  1582. {
  1583. // Remove all numbers from the end of typename.
  1584. QString typeName = name;
  1585. int nameLen = typeName.length();
  1586. int len = nameLen;
  1587. while (len > 0 && typeName[len - 1].isDigit())
  1588. {
  1589. len--;
  1590. }
  1591. typeName = typeName.left(len);
  1592. uint16 num = 1;
  1593. if (len < nameLen)
  1594. {
  1595. num = (uint16)atoi((const char*)name.toUtf8().data() + len) + 0;
  1596. }
  1597. NameNumbersMap::iterator iNameNumber = m_nameNumbersMap.find(typeName);
  1598. if (iNameNumber == m_nameNumbersMap.end())
  1599. {
  1600. std::set<uint16> numberSet;
  1601. numberSet.insert(num);
  1602. m_nameNumbersMap[typeName] = numberSet;
  1603. }
  1604. else
  1605. {
  1606. std::set<uint16>& numberSet = iNameNumber->second;
  1607. numberSet.insert(num);
  1608. }
  1609. }
  1610. //////////////////////////////////////////////////////////////////////////
  1611. void CObjectManager::UpdateRegisterObjectName(const QString& name)
  1612. {
  1613. // Remove all numbers from the end of typename.
  1614. QString typeName = name;
  1615. int nameLen = typeName.length();
  1616. int len = nameLen;
  1617. while (len > 0 && typeName[len - 1].isDigit())
  1618. {
  1619. len--;
  1620. }
  1621. typeName = typeName.left(len);
  1622. uint16 num = 1;
  1623. if (len < nameLen)
  1624. {
  1625. num = (uint16)atoi((const char*)name.toUtf8().data() + len) + 0;
  1626. }
  1627. NameNumbersMap::iterator it = m_nameNumbersMap.find(typeName);
  1628. if (it != m_nameNumbersMap.end())
  1629. {
  1630. if (it->second.end() != it->second.find(num))
  1631. {
  1632. it->second.erase(num);
  1633. if (it->second.empty())
  1634. {
  1635. m_nameNumbersMap.erase(it);
  1636. }
  1637. }
  1638. }
  1639. }
  1640. //////////////////////////////////////////////////////////////////////////
  1641. QString CObjectManager::GenerateUniqueObjectName(const QString& theTypeName)
  1642. {
  1643. if (!m_bGenUniqObjectNames)
  1644. {
  1645. return theTypeName;
  1646. }
  1647. QString typeName = theTypeName;
  1648. const int subIndex = theTypeName.indexOf("::");
  1649. if (subIndex != -1 && subIndex > typeName.length() - 2)
  1650. {
  1651. typeName.remove(0, subIndex + 2);
  1652. }
  1653. // Remove all numbers from the end of typename.
  1654. int len = typeName.length();
  1655. while (len > 0 && typeName[len - 1].isDigit())
  1656. {
  1657. len--;
  1658. }
  1659. typeName = typeName.left(len);
  1660. NameNumbersMap::iterator ii = m_nameNumbersMap.find(typeName);
  1661. uint16 lastNumber = 1;
  1662. if (ii != m_nameNumbersMap.end())
  1663. {
  1664. lastNumber = FindPossibleObjectNameNumber(ii->second);
  1665. }
  1666. else
  1667. {
  1668. std::set<uint16> numberSet;
  1669. numberSet.insert(lastNumber);
  1670. m_nameNumbersMap[typeName] = numberSet;
  1671. }
  1672. QString str = QStringLiteral("%1%2").arg(typeName).arg(lastNumber);
  1673. return str;
  1674. }
  1675. //////////////////////////////////////////////////////////////////////////
  1676. bool CObjectManager::EnableUniqObjectNames(bool bEnable)
  1677. {
  1678. bool bPrev = m_bGenUniqObjectNames;
  1679. m_bGenUniqObjectNames = bEnable;
  1680. return bPrev;
  1681. }
  1682. //////////////////////////////////////////////////////////////////////////
  1683. CObjectClassDesc* CObjectManager::FindClass(const QString& className)
  1684. {
  1685. IClassDesc* cls = CClassFactory::Instance()->FindClass(className.toUtf8().data());
  1686. if (cls != nullptr && cls->SystemClassID() == ESYSTEM_CLASS_OBJECT)
  1687. {
  1688. return (CObjectClassDesc*)cls;
  1689. }
  1690. return nullptr;
  1691. }
  1692. //////////////////////////////////////////////////////////////////////////
  1693. void CObjectManager::GetClassCategories(QStringList& categories)
  1694. {
  1695. std::vector<IClassDesc*> classes;
  1696. CClassFactory::Instance()->GetClassesBySystemID(ESYSTEM_CLASS_OBJECT, classes);
  1697. std::set<QString> cset;
  1698. for (int i = 0; i < classes.size(); i++)
  1699. {
  1700. QString category = classes[i]->Category();
  1701. if (!category.isEmpty())
  1702. {
  1703. cset.insert(category);
  1704. }
  1705. }
  1706. categories.clear();
  1707. categories.reserve(static_cast<int>(cset.size()));
  1708. for (std::set<QString>::iterator cit = cset.begin(); cit != cset.end(); ++cit)
  1709. {
  1710. categories.push_back(*cit);
  1711. }
  1712. }
  1713. void CObjectManager::GetClassCategoryToolClassNamePairs(std::vector< std::pair<QString, QString> >& categoryToolClassNamePairs)
  1714. {
  1715. std::vector<IClassDesc*> classes;
  1716. CClassFactory::Instance()->GetClassesBySystemID(ESYSTEM_CLASS_OBJECT, classes);
  1717. std::set< std::pair<QString, QString> > cset;
  1718. for (int i = 0; i < classes.size(); i++)
  1719. {
  1720. QString category = classes[i]->Category();
  1721. QString toolClassName = ((CObjectClassDesc*)classes[i])->GetToolClassName();
  1722. if (!category.isEmpty())
  1723. {
  1724. cset.insert(std::pair<QString, QString>(category, toolClassName));
  1725. }
  1726. }
  1727. categoryToolClassNamePairs.clear();
  1728. categoryToolClassNamePairs.reserve(cset.size());
  1729. for (std::set< std::pair<QString, QString> >::iterator cit = cset.begin(); cit != cset.end(); ++cit)
  1730. {
  1731. categoryToolClassNamePairs.push_back(*cit);
  1732. }
  1733. }
  1734. void CObjectManager::GetClassTypes(const QString& category, QStringList& types)
  1735. {
  1736. std::vector<IClassDesc*> classes;
  1737. CClassFactory::Instance()->GetClassesBySystemID(ESYSTEM_CLASS_OBJECT, classes);
  1738. for (int i = 0; i < classes.size(); i++)
  1739. {
  1740. QString cat = classes[i]->Category();
  1741. if (QString::compare(cat, category, Qt::CaseInsensitive) == 0 && classes[i]->IsEnabled())
  1742. {
  1743. types.push_back(classes[i]->ClassName());
  1744. }
  1745. }
  1746. }
  1747. //////////////////////////////////////////////////////////////////////////
  1748. void CObjectManager::RegisterClassTemplate(const XmlNodeRef& templ)
  1749. {
  1750. QString typeName = templ->getTag();
  1751. QString superTypeName;
  1752. if (!templ->getAttr("SuperType", superTypeName))
  1753. {
  1754. return;
  1755. }
  1756. CObjectClassDesc* superType = FindClass(superTypeName);
  1757. if (!superType)
  1758. {
  1759. return;
  1760. }
  1761. QString category, fileSpec, initialName;
  1762. templ->getAttr("Category", category);
  1763. templ->getAttr("File", fileSpec);
  1764. templ->getAttr("Name", initialName);
  1765. CXMLObjectClassDesc* classDesc = new CXMLObjectClassDesc;
  1766. classDesc->superType = superType;
  1767. classDesc->type = typeName;
  1768. classDesc->category = category;
  1769. classDesc->fileSpec = fileSpec;
  1770. classDesc->guid = AZ::Uuid::CreateRandom();
  1771. CClassFactory::Instance()->RegisterClass(classDesc);
  1772. }
  1773. //////////////////////////////////////////////////////////////////////////
  1774. void CObjectManager::LoadClassTemplates(const QString& path)
  1775. {
  1776. QString dir = Path::AddPathSlash(path);
  1777. IFileUtil::FileArray files;
  1778. CFileUtil::ScanDirectory(dir, "*.xml", files, false);
  1779. for (int k = 0; k < files.size(); k++)
  1780. {
  1781. // Construct the full filepath of the current file
  1782. XmlNodeRef node = XmlHelpers::LoadXmlFromFile((dir + files[k].filename).toUtf8().data());
  1783. if (node != nullptr && node->isTag("ObjectTemplates"))
  1784. {
  1785. QString name;
  1786. for (int i = 0; i < node->getChildCount(); i++)
  1787. {
  1788. RegisterClassTemplate(node->getChild(i));
  1789. }
  1790. }
  1791. }
  1792. }
  1793. //////////////////////////////////////////////////////////////////////////
  1794. void CObjectManager::RegisterCVars()
  1795. {
  1796. REGISTER_CVAR2("AxisHelperHitRadius",
  1797. &m_axisHelperHitRadius,
  1798. 20,
  1799. VF_DEV_ONLY,
  1800. "Adjust the hit radius used for axis helpers, like the transform gizmo.");
  1801. }
  1802. //////////////////////////////////////////////////////////////////////////
  1803. void CObjectManager::Serialize(XmlNodeRef& xmlNode, bool bLoading, int flags)
  1804. {
  1805. if (!xmlNode)
  1806. {
  1807. return;
  1808. }
  1809. if (bLoading)
  1810. {
  1811. m_loadedObjects = 0;
  1812. if (flags == SERIALIZE_ONLY_NOTSHARED)
  1813. {
  1814. DeleteNotSharedObjects();
  1815. }
  1816. else if (flags == SERIALIZE_ONLY_SHARED)
  1817. {
  1818. DeleteSharedObjects();
  1819. }
  1820. else
  1821. {
  1822. DeleteAllObjects();
  1823. }
  1824. XmlNodeRef root = xmlNode->findChild("Objects");
  1825. int totalObjects = 0;
  1826. if (root)
  1827. {
  1828. root->getAttr("NumObjects", totalObjects);
  1829. }
  1830. StartObjectsLoading(totalObjects);
  1831. CObjectArchive ar(this, xmlNode, true);
  1832. // Loading.
  1833. if (root)
  1834. {
  1835. ar.node = root;
  1836. LoadObjects(ar, false);
  1837. }
  1838. EndObjectsLoading();
  1839. }
  1840. else
  1841. {
  1842. // Saving.
  1843. XmlNodeRef root = xmlNode->newChild("Objects");
  1844. CObjectArchive ar(this, root, false);
  1845. // Save all objects to XML.
  1846. for (Objects::iterator it = m_objects.begin(); it != m_objects.end(); ++it)
  1847. {
  1848. CBaseObject* obj = it->second;
  1849. if (obj->CheckFlags(OBJFLAG_DONT_SAVE))
  1850. {
  1851. continue;
  1852. }
  1853. if ((flags == SERIALIZE_ONLY_SHARED) && !obj->CheckFlags(OBJFLAG_SHARED))
  1854. {
  1855. continue;
  1856. }
  1857. else if ((flags == SERIALIZE_ONLY_NOTSHARED) && obj->CheckFlags(OBJFLAG_SHARED))
  1858. {
  1859. continue;
  1860. }
  1861. XmlNodeRef objNode = root->newChild("Object");
  1862. ar.node = objNode;
  1863. obj->Serialize(ar);
  1864. }
  1865. }
  1866. }
  1867. //////////////////////////////////////////////////////////////////////////
  1868. void CObjectManager::LoadObjects(CObjectArchive& objectArchive, bool bSelect)
  1869. {
  1870. m_bLoadingObjects = true;
  1871. XmlNodeRef objectsNode = objectArchive.node;
  1872. int numObjects = objectsNode->getChildCount();
  1873. for (int i = 0; i < numObjects; i++)
  1874. {
  1875. objectArchive.node = objectsNode->getChild(i);
  1876. CBaseObject* obj = objectArchive.LoadObject(objectsNode->getChild(i));
  1877. if (obj && bSelect)
  1878. {
  1879. SelectObject(obj);
  1880. }
  1881. }
  1882. EndObjectsLoading(); // End progress bar, here, Resolve objects have his own.
  1883. objectArchive.ResolveObjects();
  1884. InvalidateVisibleList();
  1885. m_bLoadingObjects = false;
  1886. }
  1887. //////////////////////////////////////////////////////////////////////////
  1888. void CObjectManager::Export(const QString& levelPath, XmlNodeRef& rootNode, bool onlyShared)
  1889. {
  1890. // Clear export files.
  1891. QFile::remove(QStringLiteral("%1TagPoints.ini").arg(levelPath));
  1892. QFile::remove(QStringLiteral("%1Volumes.ini").arg(levelPath));
  1893. // Save all objects to XML.
  1894. for (Objects::iterator it = m_objects.begin(); it != m_objects.end(); ++it)
  1895. {
  1896. CBaseObject* obj = it->second;
  1897. // Export Only shared objects.
  1898. if ((obj->CheckFlags(OBJFLAG_SHARED) && onlyShared) ||
  1899. (!obj->CheckFlags(OBJFLAG_SHARED) && !onlyShared))
  1900. {
  1901. obj->Export(levelPath, rootNode);
  1902. }
  1903. }
  1904. }
  1905. //////////////////////////////////////////////////////////////////////////
  1906. void CObjectManager::ExportEntities(XmlNodeRef& rootNode)
  1907. {
  1908. // Save all objects to XML.
  1909. for (Objects::iterator it = m_objects.begin(); it != m_objects.end(); ++it)
  1910. {
  1911. CBaseObject* obj = it->second;
  1912. if (qobject_cast<CEntityObject*>(obj))
  1913. {
  1914. obj->Export("", rootNode);
  1915. }
  1916. }
  1917. }
  1918. void CObjectManager::DeleteNotSharedObjects()
  1919. {
  1920. TBaseObjects objects;
  1921. GetAllObjects(objects);
  1922. for (int i = 0; i < objects.size(); i++)
  1923. {
  1924. CBaseObject* obj = objects[i];
  1925. if (!obj->CheckFlags(OBJFLAG_SHARED))
  1926. {
  1927. DeleteObject(obj);
  1928. }
  1929. }
  1930. }
  1931. void CObjectManager::DeleteSharedObjects()
  1932. {
  1933. TBaseObjects objects;
  1934. GetAllObjects(objects);
  1935. for (int i = 0; i < objects.size(); i++)
  1936. {
  1937. CBaseObject* obj = objects[i];
  1938. if (obj->CheckFlags(OBJFLAG_SHARED))
  1939. {
  1940. DeleteObject(obj);
  1941. }
  1942. }
  1943. }
  1944. //////////////////////////////////////////////////////////////////////////
  1945. IObjectSelectCallback* CObjectManager::SetSelectCallback(IObjectSelectCallback* callback)
  1946. {
  1947. IObjectSelectCallback* prev = m_selectCallback;
  1948. m_selectCallback = callback;
  1949. return prev;
  1950. }
  1951. //////////////////////////////////////////////////////////////////////////
  1952. void CObjectManager::InvalidateVisibleList()
  1953. {
  1954. if (m_isUpdateVisibilityList)
  1955. {
  1956. return;
  1957. }
  1958. ++m_visibilitySerialNumber;
  1959. m_visibleObjects.clear();
  1960. }
  1961. //////////////////////////////////////////////////////////////////////////
  1962. void CObjectManager::UpdateVisibilityList()
  1963. {
  1964. m_isUpdateVisibilityList = true;
  1965. m_visibleObjects.clear();
  1966. bool isInIsolationMode = false;
  1967. AzToolsFramework::ToolsApplicationRequestBus::BroadcastResult(
  1968. isInIsolationMode, &AzToolsFramework::ToolsApplicationRequestBus::Events::IsEditorInIsolationMode);
  1969. for (Objects::iterator it = m_objects.begin(); it != m_objects.end(); ++it)
  1970. {
  1971. CBaseObject* obj = it->second;
  1972. bool visible = obj->IsPotentiallyVisible();
  1973. // entities not isolated in Isolation Mode will be invisible
  1974. bool isObjectIsolated = obj->IsIsolated();
  1975. visible = visible && (!isInIsolationMode || isObjectIsolated);
  1976. obj->UpdateVisibility(visible);
  1977. // when the new viewport interaction model is enabled we always want to add objects
  1978. // in the view (frustum) to the visible objects list so we can draw feedback for
  1979. // entities being hidden in the viewport when selected in the entity outliner
  1980. // (EditorVisibleEntityDataCache must be populated even if entities are 'hidden')
  1981. m_visibleObjects.push_back(obj);
  1982. }
  1983. m_isUpdateVisibilityList = false;
  1984. }
  1985. //////////////////////////////////////////////////////////////////////////
  1986. bool CObjectManager::ConvertToType(CBaseObject* pObject, const QString& typeName)
  1987. {
  1988. QString message = QString("Convert ") + pObject->GetName() + " to " + typeName;
  1989. CUndo undo(message.toUtf8().data());
  1990. CBaseObjectPtr pNewObject = GetIEditor()->NewObject(typeName.toUtf8().data());
  1991. if (pNewObject)
  1992. {
  1993. if (pNewObject->ConvertFromObject(pObject))
  1994. {
  1995. DeleteObject(pObject);
  1996. return true;
  1997. }
  1998. DeleteObject(pNewObject);
  1999. }
  2000. Log((message + " is failed.").toUtf8().data());
  2001. return false;
  2002. }
  2003. //////////////////////////////////////////////////////////////////////////
  2004. void CObjectManager::SetObjectSelected(CBaseObject* pObject, bool bSelect)
  2005. {
  2006. AZ_PROFILE_FUNCTION(Editor);
  2007. // Only select/unselect once.
  2008. if ((pObject->IsSelected() && bSelect) || (!pObject->IsSelected() && !bSelect))
  2009. {
  2010. return;
  2011. }
  2012. // Store selection undo.
  2013. if (CUndo::IsRecording() && !m_processingBulkSelect)
  2014. {
  2015. CUndo::Record(new CUndoBaseObjectSelect(pObject));
  2016. }
  2017. pObject->SetSelected(bSelect);
  2018. m_bSelectionChanged = true;
  2019. if (bSelect && !GetIEditor()->GetTransformManipulator())
  2020. {
  2021. if (CAxisGizmo::GetGlobalAxisGizmoCount() < gSettings.gizmo.axisGizmoMaxCount)
  2022. {
  2023. // Create axis gizmo for this object.
  2024. m_gizmoManager->AddGizmo(new CAxisGizmo(pObject));
  2025. }
  2026. }
  2027. if (bSelect)
  2028. {
  2029. NotifyObjectListeners(pObject, CBaseObject::ON_SELECT);
  2030. }
  2031. else
  2032. {
  2033. NotifyObjectListeners(pObject, CBaseObject::ON_UNSELECT);
  2034. }
  2035. }
  2036. //////////////////////////////////////////////////////////////////////////
  2037. void CObjectManager::HideTransformManipulators()
  2038. {
  2039. m_gizmoManager->DeleteAllTransformManipulators();
  2040. }
  2041. //////////////////////////////////////////////////////////////////////////
  2042. //////////////////////////////////////////////////////////////////////////
  2043. void CObjectManager::AddObjectEventListener(EventListener* listener)
  2044. {
  2045. stl::push_back_unique(m_objectEventListeners, listener);
  2046. }
  2047. //////////////////////////////////////////////////////////////////////////
  2048. void CObjectManager::RemoveObjectEventListener(EventListener* listener)
  2049. {
  2050. stl::find_and_erase(m_objectEventListeners, listener);
  2051. }
  2052. //////////////////////////////////////////////////////////////////////////
  2053. void CObjectManager::NotifyObjectListeners(CBaseObject* pObject, CBaseObject::EObjectListenerEvent event)
  2054. {
  2055. std::list<EventListener*>::iterator next;
  2056. for (std::list<EventListener*>::iterator it = m_objectEventListeners.begin(); it != m_objectEventListeners.end(); it = next)
  2057. {
  2058. next = it;
  2059. ++next;
  2060. // Call listener callback.
  2061. (*it)->OnObjectEvent(pObject, event);
  2062. }
  2063. }
  2064. //////////////////////////////////////////////////////////////////////////
  2065. void CObjectManager::StartObjectsLoading(int numObjects)
  2066. {
  2067. if (m_pLoadProgress)
  2068. {
  2069. return;
  2070. }
  2071. m_pLoadProgress = new CWaitProgress("Loading Objects");
  2072. m_totalObjectsToLoad = numObjects;
  2073. m_loadedObjects = 0;
  2074. }
  2075. //////////////////////////////////////////////////////////////////////////
  2076. void CObjectManager::EndObjectsLoading()
  2077. {
  2078. if (m_pLoadProgress)
  2079. {
  2080. delete m_pLoadProgress;
  2081. }
  2082. m_pLoadProgress = nullptr;
  2083. }
  2084. //////////////////////////////////////////////////////////////////////////
  2085. void CObjectManager::GatherUsedResources(CUsedResources& resources)
  2086. {
  2087. CBaseObjectsArray objects;
  2088. GetIEditor()->GetObjectManager()->GetObjects(objects);
  2089. for (int i = 0; i < objects.size(); i++)
  2090. {
  2091. CBaseObject* pObject = objects[i];
  2092. pObject->GatherUsedResources(resources);
  2093. }
  2094. }
  2095. //////////////////////////////////////////////////////////////////////////
  2096. IGizmoManager* CObjectManager::GetGizmoManager()
  2097. {
  2098. return m_gizmoManager;
  2099. }
  2100. //////////////////////////////////////////////////////////////////////////
  2101. bool CObjectManager::IsLightClass(CBaseObject* pObject)
  2102. {
  2103. if (qobject_cast<CEntityObject*>(pObject))
  2104. {
  2105. CEntityObject* pEntity = (CEntityObject*)pObject;
  2106. if (pEntity)
  2107. {
  2108. if (pEntity->GetEntityClass().compare(CLASS_LIGHT) == 0)
  2109. {
  2110. return true;
  2111. }
  2112. if (pEntity->GetEntityClass().compare(CLASS_RIGIDBODY_LIGHT) == 0)
  2113. {
  2114. return true;
  2115. }
  2116. if (pEntity->GetEntityClass().compare(CLASS_DESTROYABLE_LIGHT) == 0)
  2117. {
  2118. return true;
  2119. }
  2120. }
  2121. }
  2122. return false;
  2123. }
  2124. void CObjectManager::FindAndRenameProperty2(const char* property2Name, const QString& oldValue, const QString& newValue)
  2125. {
  2126. CBaseObjectsArray objects;
  2127. GetObjects(objects);
  2128. for (size_t i = 0, n = objects.size(); i < n; ++i)
  2129. {
  2130. CBaseObject* pObject = objects[i];
  2131. if (qobject_cast<CEntityObject*>(pObject))
  2132. {
  2133. CEntityObject* pEntity = static_cast<CEntityObject*>(pObject);
  2134. CVarBlock* pProperties2 = pEntity->GetProperties2();
  2135. if (pProperties2)
  2136. {
  2137. IVariable* pVariable = pProperties2->FindVariable(property2Name);
  2138. if (pVariable)
  2139. {
  2140. QString sValue;
  2141. pVariable->Get(sValue);
  2142. if (sValue == oldValue)
  2143. {
  2144. pEntity->StoreUndo("Rename Property2");
  2145. pVariable->Set(newValue);
  2146. }
  2147. }
  2148. }
  2149. }
  2150. }
  2151. }
  2152. void CObjectManager::FindAndRenameProperty2If(const char* property2Name, const QString& oldValue, const QString& newValue, const char* otherProperty2Name, const QString& otherValue)
  2153. {
  2154. CBaseObjectsArray objects;
  2155. GetObjects(objects);
  2156. for (size_t i = 0, n = objects.size(); i < n; ++i)
  2157. {
  2158. CBaseObject* pObject = objects[i];
  2159. if (qobject_cast<CEntityObject*>(pObject))
  2160. {
  2161. CEntityObject* pEntity = static_cast<CEntityObject*>(pObject);
  2162. CVarBlock* pProperties2 = pEntity->GetProperties2();
  2163. if (pProperties2)
  2164. {
  2165. IVariable* pVariable = pProperties2->FindVariable(property2Name);
  2166. IVariable* pOtherVariable = pProperties2->FindVariable(otherProperty2Name);
  2167. if (pVariable && pOtherVariable)
  2168. {
  2169. QString sValue;
  2170. pVariable->Get(sValue);
  2171. QString sOtherValue;
  2172. pOtherVariable->Get(sOtherValue);
  2173. if ((sValue == oldValue) && (sOtherValue == otherValue))
  2174. {
  2175. pEntity->StoreUndo("Rename Property2 If");
  2176. pVariable->Set(newValue);
  2177. }
  2178. }
  2179. }
  2180. }
  2181. }
  2182. }
  2183. //////////////////////////////////////////////////////////////////////////
  2184. void CObjectManager::HitTestObjectAgainstRect(CBaseObject* pObj, CViewport* view, HitContext hc, std::vector<GUID>& guids)
  2185. {
  2186. if (!pObj->IsSelectable())
  2187. {
  2188. return;
  2189. }
  2190. AABB box;
  2191. // Retrieve world space bound box.
  2192. pObj->GetBoundBox(box);
  2193. // Check if object visible in viewport.
  2194. if (!view->IsBoundsVisible(box))
  2195. {
  2196. return;
  2197. }
  2198. if (pObj->HitTestRect(hc))
  2199. {
  2200. stl::push_back_unique(guids, pObj->GetId());
  2201. }
  2202. }
  2203. //////////////////////////////////////////////////////////////////////////
  2204. void CObjectManager::SelectObjectInRect(CBaseObject* pObj, CViewport* view, HitContext hc, bool bSelect)
  2205. {
  2206. if (!pObj->IsSelectable())
  2207. {
  2208. return;
  2209. }
  2210. AABB box;
  2211. // Retrieve world space bound box.
  2212. pObj->GetBoundBox(box);
  2213. // Check if object visible in viewport.
  2214. if (!view->IsBoundsVisible(box))
  2215. {
  2216. return;
  2217. }
  2218. if (pObj->HitTestRect(hc))
  2219. {
  2220. if (bSelect)
  2221. {
  2222. SelectObject(pObj);
  2223. }
  2224. else
  2225. {
  2226. UnselectObject(pObj);
  2227. }
  2228. }
  2229. }
  2230. void CObjectManager::EnteredComponentMode(const AZStd::vector<AZ::Uuid>& /*componentModeTypes*/)
  2231. {
  2232. // hide current gizmo for entity (translate/rotate/scale)
  2233. IGizmoManager* gizmoManager = GetGizmoManager();
  2234. const size_t gizmoCount = static_cast<size_t>(gizmoManager->GetGizmoCount());
  2235. for (size_t i = 0; i < gizmoCount; ++i)
  2236. {
  2237. gizmoManager->RemoveGizmo(gizmoManager->GetGizmoByIndex(static_cast<int>(i)));
  2238. }
  2239. }
  2240. void CObjectManager::LeftComponentMode(const AZStd::vector<AZ::Uuid>& /*componentModeTypes*/)
  2241. {
  2242. // show translate/rotate/scale gizmo again
  2243. if (IGizmoManager* gizmoManager = GetGizmoManager())
  2244. {
  2245. if (CBaseObject* selectedObject = GetIEditor()->GetSelectedObject())
  2246. {
  2247. gizmoManager->AddGizmo(new CAxisGizmo(selectedObject));
  2248. }
  2249. }
  2250. }
  2251. //////////////////////////////////////////////////////////////////////////
  2252. namespace
  2253. {
  2254. AZStd::vector<AZStd::string> PyGetAllObjects()
  2255. {
  2256. IObjectManager* pObjMgr = GetIEditor()->GetObjectManager();
  2257. CBaseObjectsArray objects;
  2258. pObjMgr->GetObjects(objects);
  2259. int count = pObjMgr->GetObjectCount();
  2260. AZStd::vector<AZStd::string> result;
  2261. for (int i = 0; i < count; ++i)
  2262. {
  2263. result.push_back(objects[i]->GetName().toUtf8().data());
  2264. }
  2265. return result;
  2266. }
  2267. AZStd::vector<AZStd::string> PyGetNamesOfSelectedObjects()
  2268. {
  2269. CSelectionGroup* pSel = GetIEditor()->GetSelection();
  2270. AZStd::vector<AZStd::string> result;
  2271. const int selectionCount = pSel->GetCount();
  2272. result.reserve(selectionCount);
  2273. for (int i = 0; i < selectionCount; i++)
  2274. {
  2275. result.push_back(pSel->GetObject(i)->GetName().toUtf8().data());
  2276. }
  2277. return result;
  2278. }
  2279. void PySelectObject(const char* objName)
  2280. {
  2281. CUndo undo("Select Object");
  2282. CBaseObject* pObject = GetIEditor()->GetObjectManager()->FindObject(objName);
  2283. if (pObject)
  2284. {
  2285. GetIEditor()->GetObjectManager()->SelectObject(pObject);
  2286. }
  2287. }
  2288. void PyUnselectObjects(const AZStd::vector<AZStd::string>& names)
  2289. {
  2290. CUndo undo("Unselect Objects");
  2291. std::vector<CBaseObject*> pBaseObjects;
  2292. for (int i = 0; i < names.size(); i++)
  2293. {
  2294. if (!GetIEditor()->GetObjectManager()->FindObject(names[i].c_str()))
  2295. {
  2296. throw std::logic_error((QString("\"") + names[i].c_str() + "\" is an invalid entity.").toUtf8().data());
  2297. }
  2298. pBaseObjects.push_back(GetIEditor()->GetObjectManager()->FindObject(names[i].c_str()));
  2299. }
  2300. for (int i = 0; i < pBaseObjects.size(); i++)
  2301. {
  2302. GetIEditor()->GetObjectManager()->UnselectObject(pBaseObjects[i]);
  2303. }
  2304. }
  2305. void PySelectObjects(const AZStd::vector<AZStd::string>& names)
  2306. {
  2307. CUndo undo("Select Objects");
  2308. CBaseObject* pObject;
  2309. for (size_t i = 0; i < names.size(); ++i)
  2310. {
  2311. pObject = GetIEditor()->GetObjectManager()->FindObject(names[i].c_str());
  2312. if (!pObject)
  2313. {
  2314. throw std::logic_error((QString("\"") + names[i].c_str() + "\" is an invalid entity.").toUtf8().data());
  2315. }
  2316. GetIEditor()->GetObjectManager()->SelectObject(pObject);
  2317. }
  2318. }
  2319. bool PyIsObjectHidden(const char* objName)
  2320. {
  2321. CBaseObject* pObject = GetIEditor()->GetObjectManager()->FindObject(objName);
  2322. if (!pObject)
  2323. {
  2324. throw std::logic_error((QString("\"") + objName + "\" is an invalid object name.").toUtf8().data());
  2325. }
  2326. return pObject->IsHidden();
  2327. }
  2328. void PyHideAllObjects()
  2329. {
  2330. CBaseObjectsArray baseObjects;
  2331. GetIEditor()->GetObjectManager()->GetObjects(baseObjects);
  2332. if (baseObjects.size() <= 0)
  2333. {
  2334. throw std::logic_error("Objects not found.");
  2335. }
  2336. CUndo undo("Hide All Objects");
  2337. for (int i = 0; i < baseObjects.size(); i++)
  2338. {
  2339. GetIEditor()->GetObjectManager()->HideObject(baseObjects[i], true);
  2340. }
  2341. }
  2342. void PyUnHideAllObjects()
  2343. {
  2344. CUndo undo("Unhide All Objects");
  2345. GetIEditor()->GetObjectManager()->UnhideAll();
  2346. }
  2347. void PyHideObject(const char* objName)
  2348. {
  2349. CUndo undo("Hide Object");
  2350. CBaseObject* pObject = GetIEditor()->GetObjectManager()->FindObject(objName);
  2351. if (pObject)
  2352. {
  2353. GetIEditor()->GetObjectManager()->HideObject(pObject, true);
  2354. }
  2355. }
  2356. void PyUnhideObject(const char* objName)
  2357. {
  2358. CUndo undo("Unhide Object");
  2359. CBaseObject* pObject = GetIEditor()->GetObjectManager()->FindObject(objName);
  2360. if (pObject)
  2361. {
  2362. GetIEditor()->GetObjectManager()->HideObject(pObject, false);
  2363. }
  2364. }
  2365. void PyFreezeObject(const char* objName)
  2366. {
  2367. CUndo undo("Freeze Object");
  2368. CBaseObject* pObject = GetIEditor()->GetObjectManager()->FindObject(objName);
  2369. if (pObject)
  2370. {
  2371. GetIEditor()->GetObjectManager()->FreezeObject(pObject, true);
  2372. }
  2373. }
  2374. void PyUnfreezeObject(const char* objName)
  2375. {
  2376. CUndo undo("Unfreeze Object");
  2377. CBaseObject* pObject = GetIEditor()->GetObjectManager()->FindObject(objName);
  2378. if (pObject)
  2379. {
  2380. GetIEditor()->GetObjectManager()->FreezeObject(pObject, false);
  2381. }
  2382. }
  2383. bool PyIsObjectFrozen(const char* objName)
  2384. {
  2385. CBaseObject* pObject = GetIEditor()->GetObjectManager()->FindObject(objName);
  2386. if (!pObject)
  2387. {
  2388. throw std::logic_error((QString("\"") + objName + "\" is an invalid object name.").toUtf8().data());
  2389. }
  2390. return pObject->IsFrozen();
  2391. }
  2392. void PyDeleteObject(const char* objName)
  2393. {
  2394. CUndo undo("Delete Object");
  2395. CBaseObject* pObject = GetIEditor()->GetObjectManager()->FindObject(objName);
  2396. if (pObject)
  2397. {
  2398. GetIEditor()->GetObjectManager()->DeleteObject(pObject);
  2399. }
  2400. }
  2401. int PyClearSelection()
  2402. {
  2403. CUndo undo("Clear Selection");
  2404. return GetIEditor()->GetObjectManager()->ClearSelection();
  2405. }
  2406. void PyDeleteSelected()
  2407. {
  2408. CUndo undo("Delete Selected Object");
  2409. GetIEditor()->GetObjectManager()->DeleteSelection();
  2410. }
  2411. int PyGetNumSelectedObjects()
  2412. {
  2413. if (CSelectionGroup* pGroup = GetIEditor()->GetObjectManager()->GetSelection())
  2414. {
  2415. return pGroup->GetCount();
  2416. }
  2417. return 0;
  2418. }
  2419. AZ::Vector3 PyGetSelectionCenter()
  2420. {
  2421. if (CSelectionGroup* pGroup = GetIEditor()->GetObjectManager()->GetSelection())
  2422. {
  2423. if (pGroup->GetCount() == 0)
  2424. {
  2425. throw std::runtime_error("Nothing selected");
  2426. }
  2427. const Vec3 center = pGroup->GetCenter();
  2428. return AZ::Vector3(center.x, center.y, center.z);
  2429. }
  2430. throw std::runtime_error("Nothing selected");
  2431. }
  2432. AZ::Aabb PyGetSelectionAABB()
  2433. {
  2434. if (CSelectionGroup* pGroup = GetIEditor()->GetObjectManager()->GetSelection())
  2435. {
  2436. if (pGroup->GetCount() == 0)
  2437. {
  2438. throw std::runtime_error("Nothing selected");
  2439. }
  2440. const AABB aabb = pGroup->GetBounds();
  2441. AZ::Aabb result;
  2442. result.Set(
  2443. AZ::Vector3(
  2444. aabb.min.x,
  2445. aabb.min.y,
  2446. aabb.min.z
  2447. ),
  2448. AZ::Vector3(
  2449. aabb.max.x,
  2450. aabb.max.y,
  2451. aabb.max.z
  2452. )
  2453. );
  2454. return result;
  2455. }
  2456. throw std::runtime_error("Nothing selected");
  2457. }
  2458. AZ::Vector3 PyGetObjectPosition(const char* pName)
  2459. {
  2460. CBaseObject* pObject = GetIEditor()->GetObjectManager()->FindObject(pName);
  2461. if (!pObject)
  2462. {
  2463. throw std::logic_error((QString("\"") + pName + "\" is an invalid object.").toUtf8().data());
  2464. }
  2465. Vec3 position = pObject->GetPos();
  2466. return AZ::Vector3(position.x, position.y, position.z);
  2467. }
  2468. void PySetObjectPosition(const char* pName, float fValueX, float fValueY, float fValueZ)
  2469. {
  2470. CBaseObject* pObject = GetIEditor()->GetObjectManager()->FindObject(pName);
  2471. if (!pObject)
  2472. {
  2473. throw std::logic_error((QString("\"") + pName + "\" is an invalid object.").toUtf8().data());
  2474. }
  2475. CUndo undo("Set Object Base Position");
  2476. pObject->SetPos(Vec3(fValueX, fValueY, fValueZ));
  2477. }
  2478. AZ::Vector3 PyGetObjectRotation(const char* pName)
  2479. {
  2480. CBaseObject* pObject = GetIEditor()->GetObjectManager()->FindObject(pName);
  2481. if (!pObject)
  2482. {
  2483. throw std::logic_error((QString("\"") + pName + "\" is an invalid object.").toUtf8().data());
  2484. }
  2485. Ang3 ang = RAD2DEG(Ang3(pObject->GetRotation()));
  2486. return AZ::Vector3(ang.x, ang.y, ang.z);
  2487. }
  2488. void PySetObjectRotation(const char* pName, float fValueX, float fValueY, float fValueZ)
  2489. {
  2490. CBaseObject* pObject = GetIEditor()->GetObjectManager()->FindObject(pName);
  2491. if (!pObject)
  2492. {
  2493. throw std::logic_error((QString("\"") + pName + "\" is an invalid object.").toUtf8().data());
  2494. }
  2495. CUndo undo("Set Object Rotation");
  2496. pObject->SetRotation(Quat(DEG2RAD(Ang3(fValueX, fValueY, fValueZ))));
  2497. }
  2498. AZ::Vector3 PyGetObjectScale(const char* pName)
  2499. {
  2500. CBaseObject* pObject = GetIEditor()->GetObjectManager()->FindObject(pName);
  2501. if (!pObject)
  2502. {
  2503. throw std::logic_error((QString("\"") + pName + "\" is an invalid object.").toUtf8().data());
  2504. }
  2505. Vec3 scaleVec3 = pObject->GetScale();
  2506. return AZ::Vector3(scaleVec3.x, scaleVec3.y, scaleVec3.z);
  2507. }
  2508. void PySetObjectScale(const char* pName, float fValueX, float fValueY, float fValueZ)
  2509. {
  2510. CBaseObject* pObject = GetIEditor()->GetObjectManager()->FindObject(pName);
  2511. if (!pObject)
  2512. {
  2513. throw std::logic_error((QString("\"") + pName + "\" is an invalid object.").toUtf8().data());
  2514. }
  2515. CUndo undo("Set Object Scale");
  2516. pObject->SetScale(Vec3(fValueX, fValueY, fValueZ));
  2517. }
  2518. void PyRenameObject(const char* pOldName, const char* pNewName)
  2519. {
  2520. CBaseObject* pObject = GetIEditor()->GetObjectManager()->FindObject(pOldName);
  2521. if (!pObject)
  2522. {
  2523. throw std::runtime_error("Could not find object");
  2524. }
  2525. if (strcmp(pNewName, "") == 0 || GetIEditor()->GetObjectManager()->FindObject(pNewName))
  2526. {
  2527. throw std::runtime_error("Invalid object name.");
  2528. }
  2529. CUndo undo("Rename object");
  2530. pObject->SetName(pNewName);
  2531. }
  2532. }
  2533. namespace AzToolsFramework
  2534. {
  2535. void ObjectManagerFuncsHandler::Reflect(AZ::ReflectContext* context)
  2536. {
  2537. if (auto behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
  2538. {
  2539. // this will put these methods into the 'azlmbr.legacy.general' module
  2540. auto addLegacyGeneral = [](AZ::BehaviorContext::GlobalMethodBuilder methodBuilder)
  2541. {
  2542. methodBuilder->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation)
  2543. ->Attribute(AZ::Script::Attributes::Category, "Legacy/Editor")
  2544. ->Attribute(AZ::Script::Attributes::Module, "legacy.general");
  2545. };
  2546. addLegacyGeneral(behaviorContext->Method("get_all_objects", PyGetAllObjects, nullptr, "Gets the list of names of all objects in the whole level."));
  2547. addLegacyGeneral(behaviorContext->Method("get_names_of_selected_objects", PyGetNamesOfSelectedObjects, nullptr, "Get the name from selected object/objects."));
  2548. addLegacyGeneral(behaviorContext->Method("select_object", PySelectObject, nullptr, "Selects a specified object."));
  2549. addLegacyGeneral(behaviorContext->Method("unselect_objects", PyUnselectObjects, nullptr, "Unselects a list of objects."));
  2550. addLegacyGeneral(behaviorContext->Method("select_objects", PySelectObjects, nullptr, "Selects a list of objects."));
  2551. addLegacyGeneral(behaviorContext->Method("get_num_selected", PyGetNumSelectedObjects, nullptr, "Returns the number of selected objects."));
  2552. addLegacyGeneral(behaviorContext->Method("clear_selection", PyClearSelection, nullptr, "Clears selection."));
  2553. addLegacyGeneral(behaviorContext->Method("get_selection_center", PyGetSelectionCenter, nullptr, "Returns the center point of the selection group."));
  2554. addLegacyGeneral(behaviorContext->Method("get_selection_aabb", PyGetSelectionAABB, nullptr, "Returns the aabb of the selection group."));
  2555. addLegacyGeneral(behaviorContext->Method("hide_object", PyHideObject, nullptr, "Hides a specified object."));
  2556. addLegacyGeneral(behaviorContext->Method("is_object_hidden", PyIsObjectHidden, nullptr, "Checks if object is hidden and returns a bool value."));
  2557. addLegacyGeneral(behaviorContext->Method("unhide_object", PyUnhideObject, nullptr, "Unhides a specified object."));
  2558. addLegacyGeneral(behaviorContext->Method("hide_all_objects", PyHideAllObjects, nullptr, "Hides all objects."));
  2559. addLegacyGeneral(behaviorContext->Method("unhide_all_objects", PyUnHideAllObjects, nullptr, "Unhides all objects."));
  2560. addLegacyGeneral(behaviorContext->Method("freeze_object", PyFreezeObject, nullptr, "Freezes a specified object."));
  2561. addLegacyGeneral(behaviorContext->Method("is_object_frozen", PyIsObjectFrozen, nullptr, "Checks if object is frozen and returns a bool value."));
  2562. addLegacyGeneral(behaviorContext->Method("unfreeze_object", PyUnfreezeObject, nullptr, "Unfreezes a specified object."));
  2563. addLegacyGeneral(behaviorContext->Method("delete_object", PyDeleteObject, nullptr, "Deletes a specified object."));
  2564. addLegacyGeneral(behaviorContext->Method("delete_selected", PyDeleteSelected, nullptr, "Deletes selected object(s)."));
  2565. addLegacyGeneral(behaviorContext->Method("get_position", PyGetObjectPosition, nullptr, "Gets the position of an object."));
  2566. addLegacyGeneral(behaviorContext->Method("set_position", PySetObjectPosition, nullptr, "Sets the position of an object."));
  2567. addLegacyGeneral(behaviorContext->Method("get_rotation", PyGetObjectRotation, nullptr, "Gets the rotation of an object."));
  2568. addLegacyGeneral(behaviorContext->Method("set_rotation", PySetObjectRotation, nullptr, "Sets the rotation of an object."));
  2569. addLegacyGeneral(behaviorContext->Method("get_scale", PyGetObjectScale, nullptr, "Gets the scale of an object."));
  2570. addLegacyGeneral(behaviorContext->Method("set_scale", PySetObjectScale, nullptr, "Sets the scale of an object."));
  2571. addLegacyGeneral(behaviorContext->Method("rename_object", PyRenameObject, nullptr, "Renames object with oldObjectName to newObjectName."));
  2572. }
  2573. }
  2574. }