123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015 |
- /*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
- #include "EditorDefs.h"
- #include "ObjectManager.h"
- // Qt
- #include <QMessageBox>
- // Editor
- #include "Settings.h"
- #include "DisplaySettings.h"
- #include "EntityObject.h"
- #include "Viewport.h"
- #include "GizmoManager.h"
- #include "AxisGizmo.h"
- #include "GameEngine.h"
- #include "WaitProgress.h"
- #include "Util/Image.h"
- #include "ObjectManagerLegacyUndo.h"
- #include "Include/HitContext.h"
- #include "EditMode/DeepSelection.h"
- #include "Plugins/ComponentEntityEditorPlugin/Objects/ComponentEntityObject.h"
- #include <AzCore/Console/Console.h>
- AZ_CVAR_EXTERNED(bool, ed_visibility_logTiming);
- AZ_CVAR(
- bool, ed_visibility_use, true, nullptr, AZ::ConsoleFunctorFlags::Null,
- "Enable/disable using the new IVisibilitySystem for Entity visibility determination");
- /*!
- * Class Description used for object templates.
- * This description filled from Xml template files.
- */
- class CXMLObjectClassDesc
- : public CObjectClassDesc
- {
- public:
- CObjectClassDesc* superType;
- QString type;
- QString category;
- QString fileSpec;
- GUID guid;
- public:
- REFGUID ClassID() override
- {
- return guid;
- }
- ObjectType GetObjectType() override { return superType->GetObjectType(); };
- QString ClassName() override { return type; };
- QString Category() override { return category; };
- QObject* CreateQObject() const override { return superType->CreateQObject(); }
- QString GetTextureIcon() override { return superType->GetTextureIcon(); };
- QString GetFileSpec() override
- {
- if (!fileSpec.isEmpty())
- {
- return fileSpec;
- }
- else
- {
- return superType->GetFileSpec();
- }
- };
- int GameCreationOrder() override { return superType->GameCreationOrder(); };
- };
- void CBaseObjectsCache::AddObject(CBaseObject* object)
- {
- m_objects.push_back(object);
- if (object->GetType() == OBJTYPE_AZENTITY)
- {
- auto componentEntityObject = static_cast<CComponentEntityObject*>(object);
- m_entityIds.push_back(componentEntityObject->GetAssociatedEntityId());
- }
- }
- //////////////////////////////////////////////////////////////////////////
- // CObjectManager implementation.
- //////////////////////////////////////////////////////////////////////////
- CObjectManager* g_pObjectManager = nullptr;
- //////////////////////////////////////////////////////////////////////////
- CObjectManager::CObjectManager()
- : m_lastHideMask(0)
- , m_maxObjectViewDistRatio(0.00001f)
- , m_currSelection(&m_defaultSelection)
- , m_nLastSelCount(0)
- , m_bSelectionChanged(false)
- , m_selectCallback(nullptr)
- , m_currEditObject(nullptr)
- , m_bSingleSelection(false)
- , m_createGameObjects(true)
- , m_bGenUniqObjectNames(true)
- , m_gizmoManager(new CGizmoManager())
- , m_pLoadProgress(nullptr)
- , m_loadedObjects(0)
- , m_totalObjectsToLoad(0)
- , m_bExiting(false)
- , m_isUpdateVisibilityList(false)
- , m_currentHideCount(CBaseObject::s_invalidHiddenID)
- , m_bInReloading(false)
- , m_bSkipObjectUpdate(false)
- , m_bLevelExporting(false)
- {
- g_pObjectManager = this;
- RegisterObjectClasses();
- m_objectsByName.reserve(1024);
- LoadRegistry();
- AzToolsFramework::ComponentModeFramework::EditorComponentModeNotificationBus::Handler::BusConnect(
- AzToolsFramework::GetEntityContextId());
- }
- //////////////////////////////////////////////////////////////////////////
- CObjectManager::~CObjectManager()
- {
- AzToolsFramework::ComponentModeFramework::EditorComponentModeNotificationBus::Handler::BusDisconnect();
- m_bExiting = true;
- SaveRegistry();
- DeleteAllObjects();
- delete m_gizmoManager;
- }
- //////////////////////////////////////////////////////////////////////////
- void CObjectManager::RegisterObjectClasses()
- {
- LoadRegistry();
- }
- //////////////////////////////////////////////////////////////////////////
- void CObjectManager::SaveRegistry()
- {
- }
- void CObjectManager::LoadRegistry()
- {
- }
- //////////////////////////////////////////////////////////////////////////
- CBaseObject* CObjectManager::NewObject(CObjectClassDesc* cls, CBaseObject* prev, const QString& file, const char* newObjectName)
- {
- // Suspend undo operations when initializing object.
- GetIEditor()->SuspendUndo();
- CBaseObjectPtr obj;
- {
- obj = qobject_cast<CBaseObject*>(cls->CreateQObject());
- obj->SetClassDesc(cls);
- obj->InitVariables();
- obj->m_guid = AZ::Uuid::CreateRandom(); // generate uniq GUID for this object.
- GetIEditor()->GetErrorReport()->SetCurrentValidatorObject(obj);
- if (obj->Init(GetIEditor(), prev, file))
- {
- if ((newObjectName)&&(newObjectName[0]))
- {
- obj->SetName(newObjectName);
- }
- else
- {
- if (obj->GetName().isEmpty())
- {
- obj->GenerateUniqueName();
- }
- }
- // Create game object itself.
- obj->CreateGameObject();
- if (!AddObject(obj))
- {
- obj = nullptr;
- }
- }
- else
- {
- obj = nullptr;
- }
- GetIEditor()->GetErrorReport()->SetCurrentValidatorObject(nullptr);
- }
- GetIEditor()->ResumeUndo();
- if (obj != nullptr && GetIEditor()->IsUndoRecording())
- {
- // AZ entity creations are handled through the AZ undo system.
- if (obj->GetType() != OBJTYPE_AZENTITY)
- {
- GetIEditor()->RecordUndo(new CUndoBaseObjectNew(obj));
- // check for script entities
- const char* scriptClassName = "";
- CEntityObject* entityObj = qobject_cast<CEntityObject*>(obj);
- QByteArray entityClass; // Leave it outside of the if. Otherwise buffer is deleted.
- if (entityObj)
- {
- entityClass = entityObj->GetEntityClass().toUtf8();
- scriptClassName = entityClass.data();
- }
- }
- }
- return obj;
- }
- //////////////////////////////////////////////////////////////////////////
- CBaseObject* CObjectManager::NewObject(CObjectArchive& ar, CBaseObject* pUndoObject, bool bMakeNewId)
- {
- XmlNodeRef objNode = ar.node;
- // Load all objects from XML.
- QString typeName;
- GUID id = GUID_NULL;
- if (!objNode->getAttr("Type", typeName))
- {
- return nullptr;
- }
- if (!objNode->getAttr("Id", id))
- {
- // Make new ID for object that doesn't have if.
- id = AZ::Uuid::CreateRandom();
- }
- if (bMakeNewId)
- {
- // Make new guid for this object.
- GUID newId = AZ::Uuid::CreateRandom();
- ar.RemapID(id, newId); // Mark this id remapped.
- id = newId;
- }
- CBaseObjectPtr pObject;
- if (pUndoObject)
- {
- // if undoing restore object pointer.
- pObject = pUndoObject;
- }
- else
- {
- // New object creation.
- // Suspend undo operations when initializing object.
- CUndoSuspend undoSuspender;
- QString entityClass;
- if (objNode->getAttr("EntityClass", entityClass))
- {
- typeName = typeName + "::" + entityClass;
- }
- CObjectClassDesc* cls = FindClass(typeName);
- if (!cls)
- {
- CryWarning(VALIDATOR_MODULE_EDITOR, VALIDATOR_ERROR, "RuntimeClass %s not registered", typeName.toUtf8().data());
- return nullptr;
- }
- pObject = qobject_cast<CBaseObject*>(cls->CreateQObject());
- assert(pObject);
- pObject->SetClassDesc(cls);
- pObject->m_guid = id;
- pObject->InitVariables();
- QString objName;
- objNode->getAttr("Name", objName);
- pObject->m_name = objName;
- CBaseObject* obj = FindObject(pObject->GetId());
- if (obj)
- {
- // If id is taken.
- QString error;
- 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());
- CLogFile::WriteLine(error.toUtf8().data());
- if (!GetIEditor()->IsInTestMode() && !GetIEditor()->IsInLevelLoadTestMode())
- {
- CErrorRecord errorRecord;
- errorRecord.pObject = obj;
- errorRecord.count = 1;
- errorRecord.severity = CErrorRecord::ESEVERITY_ERROR;
- errorRecord.error = error;
- errorRecord.description = "Possible duplicate objects being loaded, potential fix is to remove duplicate objects from level files.";
- GetIEditor()->GetErrorReport()->ReportError(errorRecord);
- }
- return nullptr;
- //CoCreateGuid( &pObject->m_guid ); // generate uniq GUID for this object.
- }
- }
- GetIEditor()->GetErrorReport()->SetCurrentValidatorObject(pObject);
- if (!pObject->Init(GetIEditor(), nullptr, ""))
- {
- GetIEditor()->GetErrorReport()->SetCurrentValidatorObject(nullptr);
- return nullptr;
- }
- if (!AddObject(pObject))
- {
- GetIEditor()->GetErrorReport()->SetCurrentValidatorObject(nullptr);
- return nullptr;
- }
- //pObject->Serialize( ar );
- GetIEditor()->GetErrorReport()->SetCurrentValidatorObject(nullptr);
- if (pObject != nullptr && pUndoObject == nullptr)
- {
- // If new object with no undo, record it.
- if (CUndo::IsRecording())
- {
- GetIEditor()->RecordUndo(new CUndoBaseObjectNew(pObject));
- }
- }
- m_loadedObjects++;
- if (m_pLoadProgress && m_totalObjectsToLoad > 0)
- {
- m_pLoadProgress->Step((m_loadedObjects * 100) / m_totalObjectsToLoad);
- }
- return pObject;
- }
- //////////////////////////////////////////////////////////////////////////
- CBaseObject* CObjectManager::NewObject(const QString& typeName, CBaseObject* prev, const QString& file, const char* newObjectName)
- {
- // [9/22/2009 evgeny] If it is "Entity", figure out if a CEntity subclass is actually needed
- QString fullName = typeName + "::" + file;
- CObjectClassDesc* cls = FindClass(fullName);
- if (!cls)
- {
- cls = FindClass(typeName);
- }
- if (!cls)
- {
- GetIEditor()->GetSystem()->GetILog()->Log("Warning: RuntimeClass %s (as well as %s) not registered", typeName.toUtf8().data(), fullName.toUtf8().data());
- return nullptr;
- }
- CBaseObject* pObject = NewObject(cls, prev, file, newObjectName);
- return pObject;
- }
- //////////////////////////////////////////////////////////////////////////
- void CObjectManager::DeleteObject(CBaseObject* obj)
- {
- AZ_PROFILE_FUNCTION(Editor);
- if (m_currEditObject == obj)
- {
- EndEditParams();
- }
- if (!obj)
- {
- return;
- }
- // If object already deleted.
- if (obj->CheckFlags(OBJFLAG_DELETED))
- {
- return;
- }
- NotifyObjectListeners(obj, CBaseObject::ON_PREDELETE);
- obj->NotifyListeners(CBaseObject::ON_PREDELETE);
- // Must be after object DetachAll to support restoring Parent/Child relations.
- // AZ entity deletions are handled through the AZ undo system.
- if (CUndo::IsRecording() && obj->GetType() != OBJTYPE_AZENTITY)
- {
- // Store undo for all child objects.
- for (int i = 0; i < obj->GetChildCount(); i++)
- {
- obj->GetChild(i)->StoreUndo("DeleteParent");
- }
- CUndo::Record(new CUndoBaseObjectDelete(obj));
- }
- AABB objAAB;
- obj->GetBoundBox(objAAB);
- GetIEditor()->GetGameEngine()->OnAreaModified(objAAB);
- obj->Done();
- NotifyObjectListeners(obj, CBaseObject::ON_DELETE);
- RemoveObject(obj);
- }
- //////////////////////////////////////////////////////////////////////////
- void CObjectManager::DeleteSelection(CSelectionGroup* pSelection)
- {
- AZ_PROFILE_FUNCTION(Editor);
- if (pSelection == nullptr)
- {
- return;
- }
- // if the object contains an entity which has link, the link information should be recorded for undo separately. p
- if (CUndo::IsRecording())
- {
- for (int i = 0, iSize(pSelection->GetCount()); i < iSize; ++i)
- {
- CBaseObject* pObj = pSelection->GetObject(i);
- if (!qobject_cast<CEntityObject*>(pObj))
- {
- continue;
- }
- CEntityObject* pEntity = (CEntityObject*)pObj;
- if (pEntity->GetEntityLinkCount() <= 0)
- {
- continue;
- }
- CEntityObject::StoreUndoEntityLink(pSelection);
- break;
- }
- }
- AzToolsFramework::EntityIdList selectedComponentEntities;
- for (int i = 0, iObjSize(pSelection->GetCount()); i < iObjSize; i++)
- {
- CBaseObject* object = pSelection->GetObject(i);
- // AZ::Entity deletion is handled through AZ undo system (DeleteSelected bus call below).
- if (object->GetType() != OBJTYPE_AZENTITY)
- {
- DeleteObject(object);
- }
- else
- {
- AZ::EntityId id;
- EBUS_EVENT_ID_RESULT(id, object, AzToolsFramework::ComponentEntityObjectRequestBus, GetAssociatedEntityId);
- if (id.IsValid())
- {
- selectedComponentEntities.push_back(id);
- }
- }
- }
- // Delete AZ (component) entities.
- if (QApplication::keyboardModifiers() & Qt::ShiftModifier)
- {
- EBUS_EVENT(AzToolsFramework::ToolsApplicationRequests::Bus, DeleteEntities, selectedComponentEntities);
- }
- else
- {
- EBUS_EVENT(AzToolsFramework::ToolsApplicationRequests::Bus, DeleteEntitiesAndAllDescendants, selectedComponentEntities);
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void CObjectManager::DeleteAllObjects()
- {
- AZ_PROFILE_FUNCTION(Editor);
- EndEditParams();
- ClearSelection();
- int i;
- InvalidateVisibleList();
- // Delete all selection groups.
- std::vector<CSelectionGroup*> sel;
- stl::map_to_vector(m_selections, sel);
- for (i = 0; i < sel.size(); i++)
- {
- delete sel[i];
- }
- m_selections.clear();
- TBaseObjects objectsHolder;
- GetAllObjects(objectsHolder);
- // Clear map. Need to do this before deleting objects in case someone tries to get object list during shutdown.
- m_objects.clear();
- m_objectsByName.clear();
- for (i = 0; i < objectsHolder.size(); i++)
- {
- objectsHolder[i]->Done();
- }
- //! Delete object instances.
- objectsHolder.clear();
- // Clear name map.
- m_nameNumbersMap.clear();
- m_animatedAttachedEntities.clear();
- }
- CBaseObject* CObjectManager::CloneObject(CBaseObject* obj)
- {
- AZ_PROFILE_FUNCTION(Editor);
- assert(obj);
- //CRuntimeClass *cls = obj->GetRuntimeClass();
- //CBaseObject *clone = (CBaseObject*)cls->CreateObject();
- //clone->CloneCopy( obj );
- CBaseObject* clone = NewObject(obj->GetClassDesc(), obj);
- return clone;
- }
- //////////////////////////////////////////////////////////////////////////
- CBaseObject* CObjectManager::FindObject(REFGUID guid) const
- {
- CBaseObject* result = stl::find_in_map(m_objects, guid, (CBaseObject*)nullptr);
- return result;
- }
- //////////////////////////////////////////////////////////////////////////
- CBaseObject* CObjectManager::FindObject(const QString& sName) const
- {
- const AZ::Crc32 crc(sName.toUtf8().data(), sName.toUtf8().count(), true);
- auto iter = m_objectsByName.find(crc);
- if (iter != m_objectsByName.end())
- {
- return iter->second;
- }
- return nullptr;
- }
- //////////////////////////////////////////////////////////////////////////
- void CObjectManager::FindObjectsOfType(ObjectType type, std::vector<CBaseObject*>& result)
- {
- result.clear();
- CBaseObjectsArray objects;
- GetObjects(objects);
- for (size_t i = 0, n = objects.size(); i < n; ++i)
- {
- if (objects[i]->GetType() == type)
- {
- result.push_back(objects[i]);
- }
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void CObjectManager::FindObjectsOfType(const QMetaObject* pClass, std::vector<CBaseObject*>& result)
- {
- result.clear();
- CBaseObjectsArray objects;
- GetObjects(objects);
- for (size_t i = 0, n = objects.size(); i < n; ++i)
- {
- CBaseObject* pObject = objects[i];
- if (pObject->metaObject() == pClass)
- {
- result.push_back(pObject);
- }
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void CObjectManager::FindObjectsInAABB(const AABB& aabb, std::vector<CBaseObject*>& result) const
- {
- result.clear();
- CBaseObjectsArray objects;
- GetObjects(objects);
- for (size_t i = 0, n = objects.size(); i < n; ++i)
- {
- CBaseObject* pObject = objects[i];
- AABB aabbObj;
- pObject->GetBoundBox(aabbObj);
- if (aabb.IsIntersectBox(aabbObj))
- {
- result.push_back(pObject);
- }
- }
- }
- //////////////////////////////////////////////////////////////////////////
- bool CObjectManager::AddObject(CBaseObject* obj)
- {
- CBaseObjectPtr p = stl::find_in_map(m_objects, obj->GetId(), nullptr);
- if (p)
- {
- CErrorRecord err;
- err.error = QObject::tr("New Object %1 has Duplicate GUID %2, New Object Ignored").arg(obj->GetName()).arg(GuidUtil::ToString(obj->GetId()));
- err.severity = CErrorRecord::ESEVERITY_ERROR;
- err.pObject = obj;
- err.flags = CErrorRecord::FLAG_OBJECTID;
- GetIEditor()->GetErrorReport()->ReportError(err);
- return false;
- }
- m_objects[obj->GetId()] = obj;
- // Handle adding object to type-specific containers if needed
- {
- if (CEntityObject* entityObj = qobject_cast<CEntityObject*>(obj))
- {
- CEntityObject::EAttachmentType attachType = entityObj->GetAttachType();
- if (attachType == CEntityObject::EAttachmentType::eAT_GeomCacheNode || attachType == CEntityObject::EAttachmentType::eAT_CharacterBone)
- {
- m_animatedAttachedEntities.insert(entityObj);
- }
- }
- }
- const AZ::Crc32 nameCrc(obj->GetName().toUtf8().data(), obj->GetName().toUtf8().count(), true);
- m_objectsByName[nameCrc] = obj;
- RegisterObjectName(obj->GetName());
- InvalidateVisibleList();
- NotifyObjectListeners(obj, CBaseObject::ON_ADD);
- return true;
- }
- //////////////////////////////////////////////////////////////////////////
- void CObjectManager::RemoveObject(CBaseObject* obj)
- {
- assert(obj != 0);
- InvalidateVisibleList();
- // Handle removing object from type-specific containers if needed
- {
- if (CEntityObject* entityObj = qobject_cast<CEntityObject*>(obj))
- {
- m_animatedAttachedEntities.erase(entityObj);
- }
- }
- // Remove this object from selection groups.
- m_currSelection->RemoveObject(obj);
- std::vector<CSelectionGroup*> sel;
- stl::map_to_vector(m_selections, sel);
- for (int i = 0; i < sel.size(); i++)
- {
- sel[i]->RemoveObject(obj);
- }
- m_objectsByName.erase(AZ::Crc32(obj->GetName().toUtf8().data(), obj->GetName().toUtf8().count(), true));
- // 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
- m_objects.erase(obj->GetId());
- }
- //////////////////////////////////////////////////////////////////////////
- void CObjectManager::GetAllObjects(TBaseObjects& objects) const
- {
- objects.clear();
- objects.reserve(m_objects.size());
- for (Objects::const_iterator it = m_objects.begin(); it != m_objects.end(); ++it)
- {
- objects.push_back(it->second);
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void CObjectManager::ChangeObjectId(REFGUID oldGuid, REFGUID newGuid)
- {
- Objects::iterator it = m_objects.find(oldGuid);
- if (it != m_objects.end())
- {
- CBaseObjectPtr pRemappedObject = (*it).second;
- pRemappedObject->SetId(newGuid);
- m_objects.erase(it);
- m_objects.insert(std::make_pair(newGuid, pRemappedObject));
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void CObjectManager::ShowDuplicationMsgWarning(CBaseObject* obj, const QString& newName, bool bShowMsgBox) const
- {
- CBaseObject* pExisting = FindObject(newName);
- if (pExisting)
- {
- QString sRenameWarning = QObject::tr("%1 \"%2\" was NOT renamed to \"%3\" because %4 with the same name already exists.")
- .arg(obj->GetClassDesc()->ClassName())
- .arg(obj->GetName())
- .arg(newName)
- .arg(pExisting->GetClassDesc()->ClassName()
- );
- // If id is taken.
- CryWarning(VALIDATOR_MODULE_EDITOR, VALIDATOR_WARNING, sRenameWarning.toUtf8().data());
- if (bShowMsgBox)
- {
- QMessageBox::critical(QApplication::activeWindow(), QString(), sRenameWarning);
- }
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void CObjectManager::ChangeObjectName(CBaseObject* obj, const QString& newName)
- {
- assert(obj);
- if (newName != obj->GetName())
- {
- if (IsDuplicateObjectName(newName))
- {
- return;
- }
- // Remove previous name from map
- const AZ::Crc32 oldNameCrc(obj->GetName().toUtf8().data(), obj->GetName().count(), true);
- m_objectsByName.erase(oldNameCrc);
- obj->SetName(newName);
- // Add new name to map
- const AZ::Crc32 nameCrc(newName.toUtf8().data(), newName.count(), true);
- m_objectsByName[nameCrc] = obj;
- }
- }
- //////////////////////////////////////////////////////////////////////////
- int CObjectManager::GetObjectCount() const
- {
- return static_cast<int>(m_objects.size());
- }
- //////////////////////////////////////////////////////////////////////////
- void CObjectManager::GetObjects(CBaseObjectsArray& objects) const
- {
- objects.clear();
- objects.reserve(m_objects.size());
- for (Objects::const_iterator it = m_objects.begin(); it != m_objects.end(); ++it)
- {
- objects.push_back(it->second);
- }
- }
- void CObjectManager::GetObjects(CBaseObjectsArray& objects, BaseObjectFilterFunctor const& filter) const
- {
- objects.clear();
- objects.reserve(m_objects.size());
- for (Objects::const_iterator it = m_objects.begin(); it != m_objects.end(); ++it)
- {
- assert(it->second);
- if (filter.first(*it->second, filter.second))
- {
- objects.push_back(it->second);
- }
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void CObjectManager::SendEvent(ObjectEvent event)
- {
- if (event == EVENT_RELOAD_ENTITY)
- {
- m_bInReloading = true;
- }
- for (Objects::iterator it = m_objects.begin(); it != m_objects.end(); ++it)
- {
- CBaseObject* obj = it->second;
- obj->OnEvent(event);
- }
- if (event == EVENT_RELOAD_ENTITY)
- {
- m_bInReloading = false;
- GetIEditor()->Notify(eNotify_OnReloadTrackView);
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void CObjectManager::SendEvent(ObjectEvent event, const AABB& bounds)
- {
- AABB box;
- for (Objects::iterator it = m_objects.begin(); it != m_objects.end(); ++it)
- {
- CBaseObject* obj = it->second;
- obj->GetBoundBox(box);
- if (bounds.IsIntersectBox(box))
- {
- obj->OnEvent(event);
- }
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void CObjectManager::Update()
- {
- if (m_bSkipObjectUpdate)
- {
- return;
- }
- QWidget* prevActiveWindow = QApplication::activeWindow();
- // Restore focus if it changed.
- if (prevActiveWindow && QApplication::activeWindow() != prevActiveWindow)
- {
- prevActiveWindow->setFocus();
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void CObjectManager::HideObject(CBaseObject* obj, bool hide)
- {
- assert(obj != 0);
- if (hide)
- {
- obj->SetHidden(hide, ++m_currentHideCount);
- }
- else
- {
- obj->SetHidden(false);
- }
- InvalidateVisibleList();
- }
- void CObjectManager::ShowLastHiddenObject()
- {
- uint64 mostRecentID = CBaseObject::s_invalidHiddenID;
- CBaseObject* mostRecentObject = nullptr;
- for (auto it : m_objects)
- {
- CBaseObject* obj = it.second;
- uint64 hiddenID = obj->GetHideOrder();
- if (hiddenID > mostRecentID)
- {
- mostRecentID = hiddenID;
- mostRecentObject = obj;
- }
- }
- if (mostRecentObject != nullptr)
- {
- mostRecentObject->SetHidden(false);
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void CObjectManager::UnhideAll()
- {
- for (Objects::iterator it = m_objects.begin(); it != m_objects.end(); ++it)
- {
- CBaseObject* obj = it->second;
- obj->SetHidden(false);
- }
- InvalidateVisibleList();
- }
- //////////////////////////////////////////////////////////////////////////
- void CObjectManager::FreezeObject(CBaseObject* obj, bool freeze)
- {
- assert(obj != 0);
- // Remove object from main object set and put it to hidden set.
- obj->SetFrozen(freeze);
- InvalidateVisibleList();
- }
- //////////////////////////////////////////////////////////////////////////
- void CObjectManager::UnfreezeAll()
- {
- for (Objects::iterator it = m_objects.begin(); it != m_objects.end(); ++it)
- {
- CBaseObject* obj = it->second;
- obj->SetFrozen(false);
- }
- InvalidateVisibleList();
- }
- //////////////////////////////////////////////////////////////////////////
- bool CObjectManager::SelectObject(CBaseObject* obj, bool bUseMask)
- {
- assert(obj);
- if (obj == nullptr)
- {
- return false;
- }
- // Check if can be selected.
- if (bUseMask && (!(obj->GetType() & gSettings.objectSelectMask)))
- {
- return false;
- }
- if (m_selectCallback)
- {
- if (!m_selectCallback->OnSelectObject(obj))
- {
- return true;
- }
- }
- m_currSelection->AddObject(obj);
- // while in ComponentMode we never explicitly change selection (the entity will always be selected).
- // this check is to handle the case where an undo or redo action has occurred and
- // the entity has been destroyed and recreated as part of the deserialization step.
- // we want the internal state to stay consistent but do not want to notify other systems of the change.
- if (AzToolsFramework::ComponentModeFramework::InComponentMode())
- {
- obj->SetSelected(true);
- }
- else
- {
- SetObjectSelected(obj, true);
- GetIEditor()->Notify(eNotify_OnSelectionChange);
- }
- return true;
- }
- void CObjectManager::SelectEntities(std::set<CEntityObject*>& s)
- {
- for (std::set<CEntityObject*>::iterator it = s.begin(), end = s.end(); it != end; ++it)
- {
- SelectObject(*it);
- }
- }
- void CObjectManager::UnselectObject(CBaseObject* obj)
- {
- // while in ComponentMode we never explicitly change selection (the entity will always be selected).
- // this check is to handle the case where an undo or redo action has occurred and
- // the entity has been destroyed and recreated as part of the deserialization step.
- // we want the internal state to stay consistent but do not want to notify other systems of the change.
- if (AzToolsFramework::ComponentModeFramework::InComponentMode())
- {
- obj->SetSelected(false);
- }
- else
- {
- SetObjectSelected(obj, false);
- }
- m_currSelection->RemoveObject(obj);
- }
- CSelectionGroup* CObjectManager::GetSelection(const QString& name) const
- {
- CSelectionGroup* selection = stl::find_in_map(m_selections, name, (CSelectionGroup*)nullptr);
- return selection;
- }
- void CObjectManager::GetNameSelectionStrings(QStringList& names)
- {
- for (TNameSelectionMap::iterator it = m_selections.begin(); it != m_selections.end(); ++it)
- {
- names.push_back(it->first);
- }
- }
- void CObjectManager::NameSelection(const QString& name)
- {
- if (m_currSelection->IsEmpty())
- {
- return;
- }
- CSelectionGroup* selection = stl::find_in_map(m_selections, name, (CSelectionGroup*)nullptr);
- if (selection)
- {
- assert(selection != 0);
- // Check if trying to rename itself to the same name.
- if (selection == m_currSelection)
- {
- return;
- }
- m_selections.erase(name);
- delete selection;
- }
- selection = new CSelectionGroup;
- selection->Copy(*m_currSelection);
- selection->SetName(name);
- m_selections[name] = selection;
- m_currSelection = selection;
- m_defaultSelection.RemoveAll();
- }
- void CObjectManager::SerializeNameSelection(XmlNodeRef& rootNode, bool bLoading)
- {
- if (!rootNode)
- {
- return;
- }
- _smart_ptr<CSelectionGroup> tmpGroup(nullptr);
- QString selRootStr("NameSelection");
- QString selNodeStr("NameSelectionNode");
- QString selNodeNameStr("name");
- QString idStr("id");
- QString objAttrStr("obj");
- XmlNodeRef startNode = rootNode->findChild(selRootStr.toUtf8().data());
- if (bLoading)
- {
- m_selections.erase(m_selections.begin(), m_selections.end());
- if (startNode)
- {
- for (int selNodeNo = 0; selNodeNo < startNode->getChildCount(); ++selNodeNo)
- {
- XmlNodeRef selNode = startNode->getChild(selNodeNo);
- tmpGroup = new CSelectionGroup;
- for (int objIDNodeNo = 0; objIDNodeNo < selNode->getChildCount(); ++objIDNodeNo)
- {
- GUID curID = GUID_NULL;
- XmlNodeRef idNode = selNode->getChild(objIDNodeNo);
- if (!idNode->getAttr(idStr.toUtf8().data(), curID))
- {
- continue;
- }
- if (curID != GUID_NULL)
- {
- if (GetIEditor()->GetObjectManager()->FindObject(curID))
- {
- tmpGroup->AddObject(GetIEditor()->GetObjectManager()->FindObject(curID));
- }
- }
- }
- if (tmpGroup->GetCount() > 0)
- {
- QString nameStr;
- if (!selNode->getAttr(selNodeNameStr.toUtf8().data(), nameStr))
- {
- continue;
- }
- tmpGroup->SetName(nameStr);
- m_selections[nameStr] = tmpGroup;
- }
- }
- }
- }
- else
- {
- startNode = rootNode->newChild(selRootStr.toUtf8().data());
- CSelectionGroup* objSelection = nullptr;
- for (TNameSelectionMap::iterator it = m_selections.begin(); it != m_selections.end(); ++it)
- {
- XmlNodeRef selectionNameNode = startNode->newChild(selNodeStr.toUtf8().data());
- selectionNameNode->setAttr(selNodeNameStr.toUtf8().data(), it->first.toUtf8().data());
- objSelection = it->second;
- if (!objSelection)
- {
- continue;
- }
- if (objSelection->GetCount() == 0)
- {
- continue;
- }
- for (int i = 0; i < objSelection->GetCount(); ++i)
- {
- if (objSelection->GetObject(i))
- {
- XmlNodeRef objNode = selectionNameNode->newChild(objAttrStr.toUtf8().data());
- objNode->setAttr(idStr.toUtf8().data(), GuidUtil::ToString(objSelection->GetObject(i)->GetId()));
- }
- }
- }
- }
- }
- //////////////////////////////////////////////////////////////////////////
- int CObjectManager::ClearSelection()
- {
- AZ_PROFILE_FUNCTION(Editor);
- // Make sure to unlock selection.
- GetIEditor()->LockSelection(false);
- int numSel = m_currSelection->GetCount();
- // Handle Undo/Redo of Component Entities
- bool isUndoRecording = GetIEditor()->IsUndoRecording();
- if (isUndoRecording)
- {
- m_processingBulkSelect = true;
- GetIEditor()->RecordUndo(new CUndoBaseObjectClearSelection(*m_currSelection));
- }
- // Handle legacy entities separately so the selection group can be cleared safely.
- // This prevents every AzEntity from being removed one by one from a vector.
- m_currSelection->RemoveAllExceptLegacySet();
- // Kick off Deselect for Legacy Entities
- for (CBaseObjectPtr legacyObject : m_currSelection->GetLegacyObjects())
- {
- if (isUndoRecording && legacyObject->IsSelected())
- {
- GetIEditor()->RecordUndo(new CUndoBaseObjectSelect(legacyObject));
- }
- SetObjectSelected(legacyObject, false);
- }
- // Legacy set is cleared
- m_defaultSelection.RemoveAll();
- m_currSelection = &m_defaultSelection;
- m_bSelectionChanged = true;
- // Unselect all component entities as one bulk operation instead of individually
- AzToolsFramework::ToolsApplicationRequestBus::Broadcast(
- &AzToolsFramework::ToolsApplicationRequests::SetSelectedEntities,
- AzToolsFramework::EntityIdList());
- m_processingBulkSelect = false;
- if (!m_bExiting)
- {
- GetIEditor()->Notify(eNotify_OnSelectionChange);
- }
- return numSel;
- }
- //////////////////////////////////////////////////////////////////////////
- int CObjectManager::InvertSelection()
- {
- AZ_PROFILE_FUNCTION(Editor);
- int selCount = 0;
- // iterate all objects.
- for (Objects::const_iterator it = m_objects.begin(); it != m_objects.end(); ++it)
- {
- CBaseObject* pObj = it->second;
- if (pObj->IsSelected())
- {
- UnselectObject(pObj);
- }
- else
- {
- if (SelectObject(pObj))
- {
- selCount++;
- }
- }
- }
- return selCount;
- }
- void CObjectManager::SetSelection(const QString& name)
- {
- AZ_PROFILE_FUNCTION(Editor);
- CSelectionGroup* selection = stl::find_in_map(m_selections, name, (CSelectionGroup*)nullptr);
- if (selection)
- {
- UnselectCurrent();
- assert(selection != 0);
- m_currSelection = selection;
- SelectCurrent();
- }
- }
- void CObjectManager::RemoveSelection(const QString& name)
- {
- AZ_PROFILE_FUNCTION(Editor);
- QString selName = name;
- CSelectionGroup* selection = stl::find_in_map(m_selections, name, (CSelectionGroup*)nullptr);
- if (selection)
- {
- if (selection == m_currSelection)
- {
- UnselectCurrent();
- m_currSelection = &m_defaultSelection;
- m_defaultSelection.RemoveAll();
- }
- delete selection;
- m_selections.erase(selName);
- }
- }
- void CObjectManager::SelectCurrent()
- {
- AZ_PROFILE_FUNCTION(Editor);
- for (int i = 0; i < m_currSelection->GetCount(); i++)
- {
- CBaseObject* obj = m_currSelection->GetObject(i);
- if (GetIEditor()->IsUndoRecording() && !obj->IsSelected())
- {
- GetIEditor()->RecordUndo(new CUndoBaseObjectSelect(obj));
- }
- SetObjectSelected(obj, true);
- }
- }
- void CObjectManager::UnselectCurrent()
- {
- AZ_PROFILE_FUNCTION(Editor);
- // Make sure to unlock selection.
- GetIEditor()->LockSelection(false);
- // Unselect all component entities as one bulk operation instead of individually
- AzToolsFramework::EntityIdList selectedEntities;
- EBUS_EVENT(AzToolsFramework::ToolsApplicationRequests::Bus, SetSelectedEntities, selectedEntities);
- for (int i = 0; i < m_currSelection->GetCount(); i++)
- {
- CBaseObject* obj = m_currSelection->GetObject(i);
- if (GetIEditor()->IsUndoRecording() && obj->IsSelected())
- {
- GetIEditor()->RecordUndo(new CUndoBaseObjectSelect(obj));
- }
- SetObjectSelected(obj, false);
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void CObjectManager::Display(DisplayContext& dc)
- {
- AZ_PROFILE_FUNCTION(Editor);
- int currentHideMask = GetIEditor()->GetDisplaySettings()->GetObjectHideMask();
- if (m_lastHideMask != currentHideMask)
- {
- // a setting has changed which may cause the set of currently visible objects to change, so invalidate the serial number
- // so that viewports and anyone else that needs to update settings knows it has to.
- m_lastHideMask = currentHideMask;
- ++m_visibilitySerialNumber;
- }
- // the object manager itself has a visibility list, so it also has to update its cache when the serial has changed
- if (m_visibilitySerialNumber != m_lastComputedVisibility)
- {
- m_lastComputedVisibility = m_visibilitySerialNumber;
- UpdateVisibilityList();
- }
- bool viewIsDirty = dc.settings->IsDisplayHelpers(); // displaying helpers require computing all the bound boxes and things anyway.
- if (!viewIsDirty)
- {
- if (CBaseObjectsCache* cache = dc.view->GetVisibleObjectsCache())
- {
- // if the current rendering viewport has an out-of-date cache serial number, it needs to be refreshed too.
- // views set their cache empty when they indicate they need to force a refresh.
- if ((cache->GetObjectCount() == 0) || (cache->GetSerialNumber() != m_visibilitySerialNumber))
- {
- viewIsDirty = true;
- }
- }
- }
- if (viewIsDirty)
- {
- FindDisplayableObjects(dc, true); // this also actually draws the helpers.
- // Also broadcast for anyone else that needs to draw global debug to do so now
- AzFramework::DebugDisplayEventBus::Broadcast(&AzFramework::DebugDisplayEvents::DrawGlobalDebugInfo);
- }
- if (m_gizmoManager)
- {
- m_gizmoManager->Display(dc);
- }
- }
- void CObjectManager::ForceUpdateVisibleObjectCache(DisplayContext& dc)
- {
- FindDisplayableObjects(dc, false);
- }
- void CObjectManager::FindDisplayableObjects(DisplayContext& dc, [[maybe_unused]] bool bDisplay)
- {
- // if the new IVisibilitySystem is being used, do not run this logic
- if (ed_visibility_use)
- {
- return;
- }
- AZ_PROFILE_FUNCTION(Editor);
- auto start = std::chrono::steady_clock::now();
- CBaseObjectsCache* pDispayedViewObjects = dc.view->GetVisibleObjectsCache();
- if (!pDispayedViewObjects)
- {
- return;
- }
- pDispayedViewObjects->SetSerialNumber(m_visibilitySerialNumber); // update viewport to be latest serial number
- AABB bbox;
- bbox.min.zero();
- bbox.max.zero();
- pDispayedViewObjects->ClearObjects();
- pDispayedViewObjects->Reserve(static_cast<int>(m_visibleObjects.size()));
- if (dc.flags & DISPLAY_2D)
- {
- int numVis = static_cast<int>(m_visibleObjects.size());
- for (int i = 0; i < numVis; i++)
- {
- CBaseObject* obj = m_visibleObjects[i];
- obj->GetBoundBox(bbox);
- if (dc.box.IsIntersectBox(bbox))
- {
- pDispayedViewObjects->AddObject(obj);
- }
- }
- }
- else
- {
- CSelectionGroup* pSelection = GetSelection();
- if (pSelection && pSelection->GetCount() > 1)
- {
- AABB mergedAABB;
- mergedAABB.Reset();
- for (int i = 0, iCount(pSelection->GetCount()); i < iCount; ++i)
- {
- CBaseObject* pObj(pSelection->GetObject(i));
- if (pObj == nullptr)
- {
- continue;
- }
- AABB aabb;
- pObj->GetBoundBox(aabb);
- mergedAABB.Add(aabb);
- }
- pSelection->GetObject(0)->CBaseObject::DrawDimensions(dc, &mergedAABB);
- }
- int numVis = static_cast<int>(m_visibleObjects.size());
- for (int i = 0; i < numVis; i++)
- {
- CBaseObject* obj = m_visibleObjects[i];
- if (obj)
- {
- if ((dc.flags & DISPLAY_SELECTION_HELPERS) || obj->IsSelected())
- {
- pDispayedViewObjects->AddObject(obj);
- }
- }
- }
- }
- if (ed_visibility_logTiming && !ed_visibility_use)
- {
- auto stop = std::chrono::steady_clock::now();
- std::chrono::duration<double> diff = stop - start;
- AZ_Printf("Visibility", "FindDisplayableObjects (old) - Duration: %f", diff);
- }
- }
- void CObjectManager::BeginEditParams(CBaseObject* obj, int flags)
- {
- assert(obj != 0);
- if (obj == m_currEditObject)
- {
- return;
- }
- if (GetSelection()->GetCount() > 1)
- {
- return;
- }
- QWidget* prevActiveWindow = QApplication::activeWindow();
- if (m_currEditObject)
- {
- //if (obj->GetClassDesc() != m_currEditObject->GetClassDesc())
- if (!obj->IsSameClass(m_currEditObject))
- {
- EndEditParams(flags);
- }
- }
- m_currEditObject = obj;
- if (flags & OBJECT_CREATE)
- {
- // Unselect all other objects.
- ClearSelection();
- // Select this object.
- SelectObject(obj, false);
- }
- m_bSingleSelection = true;
- // Restore focus if it changed.
- // OBJECT_EDIT is used by the EntityOutliner when items are selected. Using it here to prevent shifting focus to the EntityInspector on select.
- if (!(flags & OBJECT_EDIT) && prevActiveWindow && QApplication::activeWindow() != prevActiveWindow)
- {
- prevActiveWindow->setFocus();
- }
- }
- void CObjectManager::EndEditParams([[maybe_unused]] int flags)
- {
- m_bSingleSelection = false;
- m_currEditObject = nullptr;
- //m_bSelectionChanged = false; // don't need to clear for ungroup
- }
- //! Select objects within specified distance from given position.
- int CObjectManager::SelectObjects(const AABB& box, bool bUnselect)
- {
- AZ_PROFILE_FUNCTION(Editor);
- int numSel = 0;
- AABB objBounds;
- for (Objects::iterator it = m_objects.begin(); it != m_objects.end(); ++it)
- {
- CBaseObject* obj = it->second;
- if (obj->IsHidden())
- {
- continue;
- }
- obj->GetBoundBox(objBounds);
- if (box.IsIntersectBox(objBounds))
- {
- numSel++;
- if (!bUnselect)
- {
- SelectObject(obj);
- }
- else
- {
- UnselectObject(obj);
- }
- }
- }
- return numSel;
- }
- //////////////////////////////////////////////////////////////////////////
- int CObjectManager::MoveObjects(const AABB& box, const Vec3& offset, ImageRotationDegrees rotation, [[maybe_unused]] bool bIsCopy)
- {
- AABB objBounds;
- Vec3 src = (box.min + box.max) / 2;
- Vec3 dst = src + offset;
- float alpha = 0.0f;
- switch (rotation)
- {
- case ImageRotationDegrees::Rotate90:
- alpha = gf_halfPI;
- break;
- case ImageRotationDegrees::Rotate180:
- alpha = gf_PI;
- break;
- case ImageRotationDegrees::Rotate270:
- alpha = gf_PI + gf_halfPI;
- break;
- default:
- break;
- }
- float cosa = cos(alpha);
- float sina = sin(alpha);
- for (Objects::iterator it = m_objects.begin(); it != m_objects.end(); ++it)
- {
- CBaseObject* obj = it->second;
- if (obj->GetParent())
- {
- continue;
- }
- obj->GetBoundBox(objBounds);
- if (box.IsIntersectBox(objBounds))
- {
- if (rotation == ImageRotationDegrees::Rotate0)
- {
- obj->SetPos(obj->GetPos() - src + dst);
- }
- else
- {
- Vec3 pos = obj->GetPos() - src;
- Vec3 newPos(pos);
- newPos.x = cosa * pos.x - sina * pos.y;
- newPos.y = sina * pos.x + cosa * pos.y;
- obj->SetPos(newPos + dst);
- Quat q;
- obj->SetRotation(q.CreateRotationZ(alpha) * obj->GetRotation());
- }
- }
- }
- return 0;
- }
- bool CObjectManager::IsObjectDeletionAllowed(CBaseObject* pObject)
- {
- if (!pObject)
- {
- return false;
- }
- return true;
- };
- //////////////////////////////////////////////////////////////////////////
- void CObjectManager::DeleteSelection()
- {
- AZ_PROFILE_FUNCTION(Editor);
- // Make sure to unlock selection.
- GetIEditor()->LockSelection(false);
- CSelectionGroup objects;
- for (int i = 0; i < m_currSelection->GetCount(); i++)
- {
- // Check condition(s) if object could be deleted
- if (!IsObjectDeletionAllowed(m_currSelection->GetObject(i)))
- {
- return;
- }
- objects.AddObject(m_currSelection->GetObject(i));
- }
- RemoveSelection(m_currSelection->GetName());
- m_currSelection = &m_defaultSelection;
- m_defaultSelection.RemoveAll();
- DeleteSelection(&objects);
- }
- //////////////////////////////////////////////////////////////////////////
- bool CObjectManager::HitTestObject(CBaseObject* obj, HitContext& hc)
- {
- AZ_PROFILE_FUNCTION(Editor);
- if (obj->IsFrozen())
- {
- return false;
- }
- if (obj->IsHidden())
- {
- return false;
- }
- // This object is rejected by deep selection.
- if (obj->CheckFlags(OBJFLAG_NO_HITTEST))
- {
- return false;
- }
- ObjectType objType = obj->GetType();
- // Check if this object type is masked for selection.
- if (!(objType & gSettings.objectSelectMask))
- {
- return false;
- }
- const bool bSelectionHelperHit = obj->HitHelperTest(hc);
- if (hc.bUseSelectionHelpers && !bSelectionHelperHit)
- {
- return false;
- }
- if (!bSelectionHelperHit)
- {
- // Fast checking.
- if (hc.camera && !obj->IsInCameraView(*hc.camera))
- {
- return false;
- }
- else if (hc.bounds && !obj->IntersectRectBounds(*hc.bounds))
- {
- return false;
- }
- // Do 2D space testing.
- if (hc.nSubObjFlags == 0)
- {
- Ray ray(hc.raySrc, hc.rayDir);
- if (!obj->IntersectRayBounds(ray))
- {
- return false;
- }
- }
- else if (!obj->HitTestRect(hc))
- {
- return false;
- }
- }
- return (bSelectionHelperHit || obj->HitTest(hc));
- }
- //////////////////////////////////////////////////////////////////////////
- bool CObjectManager::HitTest(HitContext& hitInfo)
- {
- AZ_PROFILE_FUNCTION(Editor);
- hitInfo.object = nullptr;
- hitInfo.dist = FLT_MAX;
- hitInfo.axis = 0;
- hitInfo.manipulatorMode = 0;
- HitContext hcOrg = hitInfo;
- if (hcOrg.view)
- {
- hcOrg.view->GetPerpendicularAxis(nullptr, &hcOrg.b2DViewport);
- }
- hcOrg.rayDir = hcOrg.rayDir.GetNormalized();
- HitContext hc = hcOrg;
- float mindist = FLT_MAX;
- if (!hitInfo.bIgnoreAxis && !hc.bUseSelectionHelpers)
- {
- // Test gizmos.
- if (m_gizmoManager->HitTest(hc))
- {
- if (hc.axis != 0)
- {
- hitInfo.object = hc.object;
- hitInfo.gizmo = hc.gizmo;
- hitInfo.axis = hc.axis;
- hitInfo.manipulatorMode = hc.manipulatorMode;
- hitInfo.dist = hc.dist;
- return true;
- }
- }
- }
- if (hitInfo.bOnlyGizmo)
- {
- return false;
- }
- // Only HitTest objects, that where previously Displayed.
- CBaseObjectsCache* pDispayedViewObjects = hitInfo.view->GetVisibleObjectsCache();
- 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.
- CBaseObject* selected = nullptr;
- const char* name = nullptr;
- bool iconHit = false;
- int numVis = pDispayedViewObjects->GetObjectCount();
- for (int i = 0; i < numVis; i++)
- {
- CBaseObject* obj = pDispayedViewObjects->GetObject(i);
- if (obj == hitInfo.pExcludedObject)
- {
- continue;
- }
- if (HitTestObject(obj, hc))
- {
- if (m_selectCallback && !m_selectCallback->CanSelectObject(obj))
- {
- continue;
- }
- // Check if this object is nearest.
- if (hc.axis != 0)
- {
- hitInfo.object = obj;
- hitInfo.axis = hc.axis;
- hitInfo.dist = hc.dist;
- return true;
- }
- // When prioritizing icons, we don't allow non-icon hits to beat icon hits
- if (iconsPrioritized && iconHit && !hc.iconHit)
- {
- continue;
- }
- if (hc.dist < mindist || (!iconHit && hc.iconHit))
- {
- if (hc.iconHit)
- {
- iconHit = true;
- }
- mindist = hc.dist;
- name = hc.name;
- selected = obj;
- }
- // Clear the object pointer if an object was hit, not just if the collision
- // was closer than any previous. Not all paths from HitTestObject set the object pointer and so you could get
- // an object from a previous (rejected) result but with collision information about a closer hit.
- hc.object = nullptr;
- hc.iconHit = false;
- // If use deep selection
- if (hitInfo.pDeepSelection)
- {
- hitInfo.pDeepSelection->AddObject(hc.dist, obj);
- }
- }
- }
- if (selected)
- {
- hitInfo.object = selected;
- hitInfo.dist = mindist;
- hitInfo.name = name;
- hitInfo.iconHit = iconHit;
- return true;
- }
- return false;
- }
- void CObjectManager::FindObjectsInRect(CViewport* view, const QRect& rect, std::vector<GUID>& guids)
- {
- AZ_PROFILE_FUNCTION(Editor);
- if (rect.width() < 1 || rect.height() < 1)
- {
- return;
- }
- HitContext hc;
- hc.view = view;
- hc.b2DViewport = view->GetType() != ET_ViewportCamera;
- hc.rect = rect;
- hc.bUseSelectionHelpers = view->GetAdvancedSelectModeFlag();
- guids.clear();
- CBaseObjectsCache* pDispayedViewObjects = view->GetVisibleObjectsCache();
- int numVis = pDispayedViewObjects->GetObjectCount();
- for (int i = 0; i < numVis; ++i)
- {
- CBaseObject* pObj = pDispayedViewObjects->GetObject(i);
- HitTestObjectAgainstRect(pObj, view, hc, guids);
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void CObjectManager::SelectObjectsInRect(CViewport* view, const QRect& rect, bool bSelect)
- {
- AZ_PROFILE_FUNCTION(Editor);
- // Ignore too small rectangles.
- if (rect.width() < 1 || rect.height() < 1)
- {
- return;
- }
- CUndo undo("Select Object(s)");
- HitContext hc;
- hc.view = view;
- hc.b2DViewport = view->GetType() != ET_ViewportCamera;
- hc.rect = rect;
- hc.bUseSelectionHelpers = view->GetAdvancedSelectModeFlag();
- bool isUndoRecording = GetIEditor()->IsUndoRecording();
- if (isUndoRecording)
- {
- m_processingBulkSelect = true;
- }
- CBaseObjectsCache* displayedViewObjects = view->GetVisibleObjectsCache();
- int numVis = displayedViewObjects->GetObjectCount();
- // Tracking the previous selection allows proper undo/redo functionality of additional
- // selections (CTRL + drag select)
- AZStd::unordered_set<const CBaseObject*> previousSelection;
- for (int i = 0; i < numVis; ++i)
- {
- CBaseObject* object = displayedViewObjects->GetObject(i);
- if (object->IsSelected())
- {
- previousSelection.insert(object);
- }
- else
- {
- // This will update m_currSelection
- SelectObjectInRect(object, view, hc, bSelect);
- // Legacy undo/redo does not go through the Ebus system and must be done individually
- if (isUndoRecording && object->GetType() != OBJTYPE_AZENTITY)
- {
- GetIEditor()->RecordUndo(new CUndoBaseObjectSelect(object, true));
- }
- }
- }
- if (isUndoRecording && m_currSelection)
- {
- // Component Entities can handle undo/redo in bulk due to Ebuses
- GetIEditor()->RecordUndo(new CUndoBaseObjectBulkSelect(previousSelection, *m_currSelection));
- }
- m_processingBulkSelect = false;
- }
- //////////////////////////////////////////////////////////////////////////
- uint16 FindPossibleObjectNameNumber(std::set<uint16>& numberSet)
- {
- const int LIMIT = 65535;
- size_t nSetSize = numberSet.size();
- for (uint16 i = 1; i < LIMIT; ++i)
- {
- uint16 candidateNumber = (i + nSetSize) % LIMIT;
- if (numberSet.find(candidateNumber) == numberSet.end())
- {
- numberSet.insert(candidateNumber);
- return candidateNumber;
- }
- }
- return 0;
- }
- void CObjectManager::RegisterObjectName(const QString& name)
- {
- // Remove all numbers from the end of typename.
- QString typeName = name;
- int nameLen = typeName.length();
- int len = nameLen;
- while (len > 0 && typeName[len - 1].isDigit())
- {
- len--;
- }
- typeName = typeName.left(len);
- uint16 num = 1;
- if (len < nameLen)
- {
- num = (uint16)atoi((const char*)name.toUtf8().data() + len) + 0;
- }
- NameNumbersMap::iterator iNameNumber = m_nameNumbersMap.find(typeName);
- if (iNameNumber == m_nameNumbersMap.end())
- {
- std::set<uint16> numberSet;
- numberSet.insert(num);
- m_nameNumbersMap[typeName] = numberSet;
- }
- else
- {
- std::set<uint16>& numberSet = iNameNumber->second;
- numberSet.insert(num);
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void CObjectManager::UpdateRegisterObjectName(const QString& name)
- {
- // Remove all numbers from the end of typename.
- QString typeName = name;
- int nameLen = typeName.length();
- int len = nameLen;
- while (len > 0 && typeName[len - 1].isDigit())
- {
- len--;
- }
- typeName = typeName.left(len);
- uint16 num = 1;
- if (len < nameLen)
- {
- num = (uint16)atoi((const char*)name.toUtf8().data() + len) + 0;
- }
- NameNumbersMap::iterator it = m_nameNumbersMap.find(typeName);
- if (it != m_nameNumbersMap.end())
- {
- if (it->second.end() != it->second.find(num))
- {
- it->second.erase(num);
- if (it->second.empty())
- {
- m_nameNumbersMap.erase(it);
- }
- }
- }
- }
- //////////////////////////////////////////////////////////////////////////
- QString CObjectManager::GenerateUniqueObjectName(const QString& theTypeName)
- {
- if (!m_bGenUniqObjectNames)
- {
- return theTypeName;
- }
- QString typeName = theTypeName;
- const int subIndex = theTypeName.indexOf("::");
- if (subIndex != -1 && subIndex > typeName.length() - 2)
- {
- typeName.remove(0, subIndex + 2);
- }
- // Remove all numbers from the end of typename.
- int len = typeName.length();
- while (len > 0 && typeName[len - 1].isDigit())
- {
- len--;
- }
- typeName = typeName.left(len);
- NameNumbersMap::iterator ii = m_nameNumbersMap.find(typeName);
- uint16 lastNumber = 1;
- if (ii != m_nameNumbersMap.end())
- {
- lastNumber = FindPossibleObjectNameNumber(ii->second);
- }
- else
- {
- std::set<uint16> numberSet;
- numberSet.insert(lastNumber);
- m_nameNumbersMap[typeName] = numberSet;
- }
- QString str = QStringLiteral("%1%2").arg(typeName).arg(lastNumber);
- return str;
- }
- //////////////////////////////////////////////////////////////////////////
- bool CObjectManager::EnableUniqObjectNames(bool bEnable)
- {
- bool bPrev = m_bGenUniqObjectNames;
- m_bGenUniqObjectNames = bEnable;
- return bPrev;
- }
- //////////////////////////////////////////////////////////////////////////
- CObjectClassDesc* CObjectManager::FindClass(const QString& className)
- {
- IClassDesc* cls = CClassFactory::Instance()->FindClass(className.toUtf8().data());
- if (cls != nullptr && cls->SystemClassID() == ESYSTEM_CLASS_OBJECT)
- {
- return (CObjectClassDesc*)cls;
- }
- return nullptr;
- }
- //////////////////////////////////////////////////////////////////////////
- void CObjectManager::GetClassCategories(QStringList& categories)
- {
- std::vector<IClassDesc*> classes;
- CClassFactory::Instance()->GetClassesBySystemID(ESYSTEM_CLASS_OBJECT, classes);
- std::set<QString> cset;
- for (int i = 0; i < classes.size(); i++)
- {
- QString category = classes[i]->Category();
- if (!category.isEmpty())
- {
- cset.insert(category);
- }
- }
- categories.clear();
- categories.reserve(static_cast<int>(cset.size()));
- for (std::set<QString>::iterator cit = cset.begin(); cit != cset.end(); ++cit)
- {
- categories.push_back(*cit);
- }
- }
- void CObjectManager::GetClassCategoryToolClassNamePairs(std::vector< std::pair<QString, QString> >& categoryToolClassNamePairs)
- {
- std::vector<IClassDesc*> classes;
- CClassFactory::Instance()->GetClassesBySystemID(ESYSTEM_CLASS_OBJECT, classes);
- std::set< std::pair<QString, QString> > cset;
- for (int i = 0; i < classes.size(); i++)
- {
- QString category = classes[i]->Category();
- QString toolClassName = ((CObjectClassDesc*)classes[i])->GetToolClassName();
- if (!category.isEmpty())
- {
- cset.insert(std::pair<QString, QString>(category, toolClassName));
- }
- }
- categoryToolClassNamePairs.clear();
- categoryToolClassNamePairs.reserve(cset.size());
- for (std::set< std::pair<QString, QString> >::iterator cit = cset.begin(); cit != cset.end(); ++cit)
- {
- categoryToolClassNamePairs.push_back(*cit);
- }
- }
- void CObjectManager::GetClassTypes(const QString& category, QStringList& types)
- {
- std::vector<IClassDesc*> classes;
- CClassFactory::Instance()->GetClassesBySystemID(ESYSTEM_CLASS_OBJECT, classes);
- for (int i = 0; i < classes.size(); i++)
- {
- QString cat = classes[i]->Category();
- if (QString::compare(cat, category, Qt::CaseInsensitive) == 0 && classes[i]->IsEnabled())
- {
- types.push_back(classes[i]->ClassName());
- }
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void CObjectManager::RegisterClassTemplate(const XmlNodeRef& templ)
- {
- QString typeName = templ->getTag();
- QString superTypeName;
- if (!templ->getAttr("SuperType", superTypeName))
- {
- return;
- }
- CObjectClassDesc* superType = FindClass(superTypeName);
- if (!superType)
- {
- return;
- }
- QString category, fileSpec, initialName;
- templ->getAttr("Category", category);
- templ->getAttr("File", fileSpec);
- templ->getAttr("Name", initialName);
- CXMLObjectClassDesc* classDesc = new CXMLObjectClassDesc;
- classDesc->superType = superType;
- classDesc->type = typeName;
- classDesc->category = category;
- classDesc->fileSpec = fileSpec;
- classDesc->guid = AZ::Uuid::CreateRandom();
- CClassFactory::Instance()->RegisterClass(classDesc);
- }
- //////////////////////////////////////////////////////////////////////////
- void CObjectManager::LoadClassTemplates(const QString& path)
- {
- QString dir = Path::AddPathSlash(path);
- IFileUtil::FileArray files;
- CFileUtil::ScanDirectory(dir, "*.xml", files, false);
- for (int k = 0; k < files.size(); k++)
- {
- // Construct the full filepath of the current file
- XmlNodeRef node = XmlHelpers::LoadXmlFromFile((dir + files[k].filename).toUtf8().data());
- if (node != nullptr && node->isTag("ObjectTemplates"))
- {
- QString name;
- for (int i = 0; i < node->getChildCount(); i++)
- {
- RegisterClassTemplate(node->getChild(i));
- }
- }
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void CObjectManager::RegisterCVars()
- {
- REGISTER_CVAR2("AxisHelperHitRadius",
- &m_axisHelperHitRadius,
- 20,
- VF_DEV_ONLY,
- "Adjust the hit radius used for axis helpers, like the transform gizmo.");
- }
- //////////////////////////////////////////////////////////////////////////
- void CObjectManager::Serialize(XmlNodeRef& xmlNode, bool bLoading, int flags)
- {
- if (!xmlNode)
- {
- return;
- }
- if (bLoading)
- {
- m_loadedObjects = 0;
- if (flags == SERIALIZE_ONLY_NOTSHARED)
- {
- DeleteNotSharedObjects();
- }
- else if (flags == SERIALIZE_ONLY_SHARED)
- {
- DeleteSharedObjects();
- }
- else
- {
- DeleteAllObjects();
- }
- XmlNodeRef root = xmlNode->findChild("Objects");
- int totalObjects = 0;
- if (root)
- {
- root->getAttr("NumObjects", totalObjects);
- }
- StartObjectsLoading(totalObjects);
- CObjectArchive ar(this, xmlNode, true);
- // Loading.
- if (root)
- {
- ar.node = root;
- LoadObjects(ar, false);
- }
- EndObjectsLoading();
- }
- else
- {
- // Saving.
- XmlNodeRef root = xmlNode->newChild("Objects");
- CObjectArchive ar(this, root, false);
- // Save all objects to XML.
- for (Objects::iterator it = m_objects.begin(); it != m_objects.end(); ++it)
- {
- CBaseObject* obj = it->second;
- if (obj->CheckFlags(OBJFLAG_DONT_SAVE))
- {
- continue;
- }
- if ((flags == SERIALIZE_ONLY_SHARED) && !obj->CheckFlags(OBJFLAG_SHARED))
- {
- continue;
- }
- else if ((flags == SERIALIZE_ONLY_NOTSHARED) && obj->CheckFlags(OBJFLAG_SHARED))
- {
- continue;
- }
- XmlNodeRef objNode = root->newChild("Object");
- ar.node = objNode;
- obj->Serialize(ar);
- }
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void CObjectManager::LoadObjects(CObjectArchive& objectArchive, bool bSelect)
- {
- m_bLoadingObjects = true;
- XmlNodeRef objectsNode = objectArchive.node;
- int numObjects = objectsNode->getChildCount();
- for (int i = 0; i < numObjects; i++)
- {
- objectArchive.node = objectsNode->getChild(i);
- CBaseObject* obj = objectArchive.LoadObject(objectsNode->getChild(i));
- if (obj && bSelect)
- {
- SelectObject(obj);
- }
- }
- EndObjectsLoading(); // End progress bar, here, Resolve objects have his own.
- objectArchive.ResolveObjects();
- InvalidateVisibleList();
- m_bLoadingObjects = false;
- }
- //////////////////////////////////////////////////////////////////////////
- void CObjectManager::Export(const QString& levelPath, XmlNodeRef& rootNode, bool onlyShared)
- {
- // Clear export files.
- QFile::remove(QStringLiteral("%1TagPoints.ini").arg(levelPath));
- QFile::remove(QStringLiteral("%1Volumes.ini").arg(levelPath));
- // Save all objects to XML.
- for (Objects::iterator it = m_objects.begin(); it != m_objects.end(); ++it)
- {
- CBaseObject* obj = it->second;
- // Export Only shared objects.
- if ((obj->CheckFlags(OBJFLAG_SHARED) && onlyShared) ||
- (!obj->CheckFlags(OBJFLAG_SHARED) && !onlyShared))
- {
- obj->Export(levelPath, rootNode);
- }
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void CObjectManager::ExportEntities(XmlNodeRef& rootNode)
- {
- // Save all objects to XML.
- for (Objects::iterator it = m_objects.begin(); it != m_objects.end(); ++it)
- {
- CBaseObject* obj = it->second;
- if (qobject_cast<CEntityObject*>(obj))
- {
- obj->Export("", rootNode);
- }
- }
- }
- void CObjectManager::DeleteNotSharedObjects()
- {
- TBaseObjects objects;
- GetAllObjects(objects);
- for (int i = 0; i < objects.size(); i++)
- {
- CBaseObject* obj = objects[i];
- if (!obj->CheckFlags(OBJFLAG_SHARED))
- {
- DeleteObject(obj);
- }
- }
- }
- void CObjectManager::DeleteSharedObjects()
- {
- TBaseObjects objects;
- GetAllObjects(objects);
- for (int i = 0; i < objects.size(); i++)
- {
- CBaseObject* obj = objects[i];
- if (obj->CheckFlags(OBJFLAG_SHARED))
- {
- DeleteObject(obj);
- }
- }
- }
- //////////////////////////////////////////////////////////////////////////
- IObjectSelectCallback* CObjectManager::SetSelectCallback(IObjectSelectCallback* callback)
- {
- IObjectSelectCallback* prev = m_selectCallback;
- m_selectCallback = callback;
- return prev;
- }
- //////////////////////////////////////////////////////////////////////////
- void CObjectManager::InvalidateVisibleList()
- {
- if (m_isUpdateVisibilityList)
- {
- return;
- }
- ++m_visibilitySerialNumber;
- m_visibleObjects.clear();
- }
- //////////////////////////////////////////////////////////////////////////
- void CObjectManager::UpdateVisibilityList()
- {
- m_isUpdateVisibilityList = true;
- m_visibleObjects.clear();
- bool isInIsolationMode = false;
- AzToolsFramework::ToolsApplicationRequestBus::BroadcastResult(
- isInIsolationMode, &AzToolsFramework::ToolsApplicationRequestBus::Events::IsEditorInIsolationMode);
- for (Objects::iterator it = m_objects.begin(); it != m_objects.end(); ++it)
- {
- CBaseObject* obj = it->second;
- bool visible = obj->IsPotentiallyVisible();
- // entities not isolated in Isolation Mode will be invisible
- bool isObjectIsolated = obj->IsIsolated();
- visible = visible && (!isInIsolationMode || isObjectIsolated);
- obj->UpdateVisibility(visible);
- // when the new viewport interaction model is enabled we always want to add objects
- // in the view (frustum) to the visible objects list so we can draw feedback for
- // entities being hidden in the viewport when selected in the entity outliner
- // (EditorVisibleEntityDataCache must be populated even if entities are 'hidden')
- m_visibleObjects.push_back(obj);
- }
- m_isUpdateVisibilityList = false;
- }
- //////////////////////////////////////////////////////////////////////////
- bool CObjectManager::ConvertToType(CBaseObject* pObject, const QString& typeName)
- {
- QString message = QString("Convert ") + pObject->GetName() + " to " + typeName;
- CUndo undo(message.toUtf8().data());
- CBaseObjectPtr pNewObject = GetIEditor()->NewObject(typeName.toUtf8().data());
- if (pNewObject)
- {
- if (pNewObject->ConvertFromObject(pObject))
- {
- DeleteObject(pObject);
- return true;
- }
- DeleteObject(pNewObject);
- }
- Log((message + " is failed.").toUtf8().data());
- return false;
- }
- //////////////////////////////////////////////////////////////////////////
- void CObjectManager::SetObjectSelected(CBaseObject* pObject, bool bSelect)
- {
- AZ_PROFILE_FUNCTION(Editor);
- // Only select/unselect once.
- if ((pObject->IsSelected() && bSelect) || (!pObject->IsSelected() && !bSelect))
- {
- return;
- }
- // Store selection undo.
- if (CUndo::IsRecording() && !m_processingBulkSelect)
- {
- CUndo::Record(new CUndoBaseObjectSelect(pObject));
- }
- pObject->SetSelected(bSelect);
- m_bSelectionChanged = true;
- if (bSelect && !GetIEditor()->GetTransformManipulator())
- {
- if (CAxisGizmo::GetGlobalAxisGizmoCount() < 1 /*legacy axisGizmoMaxCount*/)
- {
- // Create axis gizmo for this object.
- m_gizmoManager->AddGizmo(new CAxisGizmo(pObject));
- }
- }
- if (bSelect)
- {
- NotifyObjectListeners(pObject, CBaseObject::ON_SELECT);
- }
- else
- {
- NotifyObjectListeners(pObject, CBaseObject::ON_UNSELECT);
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void CObjectManager::HideTransformManipulators()
- {
- m_gizmoManager->DeleteAllTransformManipulators();
- }
- //////////////////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////////////////
- void CObjectManager::AddObjectEventListener(EventListener* listener)
- {
- stl::push_back_unique(m_objectEventListeners, listener);
- }
- //////////////////////////////////////////////////////////////////////////
- void CObjectManager::RemoveObjectEventListener(EventListener* listener)
- {
- stl::find_and_erase(m_objectEventListeners, listener);
- }
- //////////////////////////////////////////////////////////////////////////
- void CObjectManager::NotifyObjectListeners(CBaseObject* pObject, CBaseObject::EObjectListenerEvent event)
- {
- std::list<EventListener*>::iterator next;
- for (std::list<EventListener*>::iterator it = m_objectEventListeners.begin(); it != m_objectEventListeners.end(); it = next)
- {
- next = it;
- ++next;
- // Call listener callback.
- (*it)->OnObjectEvent(pObject, event);
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void CObjectManager::StartObjectsLoading(int numObjects)
- {
- if (m_pLoadProgress)
- {
- return;
- }
- m_pLoadProgress = new CWaitProgress("Loading Objects");
- m_totalObjectsToLoad = numObjects;
- m_loadedObjects = 0;
- }
- //////////////////////////////////////////////////////////////////////////
- void CObjectManager::EndObjectsLoading()
- {
- if (m_pLoadProgress)
- {
- delete m_pLoadProgress;
- }
- m_pLoadProgress = nullptr;
- }
- //////////////////////////////////////////////////////////////////////////
- void CObjectManager::GatherUsedResources(CUsedResources& resources)
- {
- CBaseObjectsArray objects;
- GetIEditor()->GetObjectManager()->GetObjects(objects);
- for (int i = 0; i < objects.size(); i++)
- {
- CBaseObject* pObject = objects[i];
- pObject->GatherUsedResources(resources);
- }
- }
- //////////////////////////////////////////////////////////////////////////
- IGizmoManager* CObjectManager::GetGizmoManager()
- {
- return m_gizmoManager;
- }
- //////////////////////////////////////////////////////////////////////////
- bool CObjectManager::IsLightClass(CBaseObject* pObject)
- {
- if (qobject_cast<CEntityObject*>(pObject))
- {
- CEntityObject* pEntity = (CEntityObject*)pObject;
- if (pEntity)
- {
- if (pEntity->GetEntityClass().compare(CLASS_LIGHT) == 0)
- {
- return true;
- }
- if (pEntity->GetEntityClass().compare(CLASS_RIGIDBODY_LIGHT) == 0)
- {
- return true;
- }
- if (pEntity->GetEntityClass().compare(CLASS_DESTROYABLE_LIGHT) == 0)
- {
- return true;
- }
- }
- }
- return false;
- }
- void CObjectManager::FindAndRenameProperty2(const char* property2Name, const QString& oldValue, const QString& newValue)
- {
- CBaseObjectsArray objects;
- GetObjects(objects);
- for (size_t i = 0, n = objects.size(); i < n; ++i)
- {
- CBaseObject* pObject = objects[i];
- if (qobject_cast<CEntityObject*>(pObject))
- {
- CEntityObject* pEntity = static_cast<CEntityObject*>(pObject);
- CVarBlock* pProperties2 = pEntity->GetProperties2();
- if (pProperties2)
- {
- IVariable* pVariable = pProperties2->FindVariable(property2Name);
- if (pVariable)
- {
- QString sValue;
- pVariable->Get(sValue);
- if (sValue == oldValue)
- {
- pEntity->StoreUndo("Rename Property2");
- pVariable->Set(newValue);
- }
- }
- }
- }
- }
- }
- void CObjectManager::FindAndRenameProperty2If(const char* property2Name, const QString& oldValue, const QString& newValue, const char* otherProperty2Name, const QString& otherValue)
- {
- CBaseObjectsArray objects;
- GetObjects(objects);
- for (size_t i = 0, n = objects.size(); i < n; ++i)
- {
- CBaseObject* pObject = objects[i];
- if (qobject_cast<CEntityObject*>(pObject))
- {
- CEntityObject* pEntity = static_cast<CEntityObject*>(pObject);
- CVarBlock* pProperties2 = pEntity->GetProperties2();
- if (pProperties2)
- {
- IVariable* pVariable = pProperties2->FindVariable(property2Name);
- IVariable* pOtherVariable = pProperties2->FindVariable(otherProperty2Name);
- if (pVariable && pOtherVariable)
- {
- QString sValue;
- pVariable->Get(sValue);
- QString sOtherValue;
- pOtherVariable->Get(sOtherValue);
- if ((sValue == oldValue) && (sOtherValue == otherValue))
- {
- pEntity->StoreUndo("Rename Property2 If");
- pVariable->Set(newValue);
- }
- }
- }
- }
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void CObjectManager::HitTestObjectAgainstRect(CBaseObject* pObj, CViewport* view, HitContext hc, std::vector<GUID>& guids)
- {
- if (!pObj->IsSelectable())
- {
- return;
- }
- AABB box;
- // Retrieve world space bound box.
- pObj->GetBoundBox(box);
- // Check if object visible in viewport.
- if (!view->IsBoundsVisible(box))
- {
- return;
- }
- if (pObj->HitTestRect(hc))
- {
- stl::push_back_unique(guids, pObj->GetId());
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void CObjectManager::SelectObjectInRect(CBaseObject* pObj, CViewport* view, HitContext hc, bool bSelect)
- {
- if (!pObj->IsSelectable())
- {
- return;
- }
- AABB box;
- // Retrieve world space bound box.
- pObj->GetBoundBox(box);
- // Check if object visible in viewport.
- if (!view->IsBoundsVisible(box))
- {
- return;
- }
- if (pObj->HitTestRect(hc))
- {
- if (bSelect)
- {
- SelectObject(pObj);
- }
- else
- {
- UnselectObject(pObj);
- }
- }
- }
- void CObjectManager::EnteredComponentMode(const AZStd::vector<AZ::Uuid>& /*componentModeTypes*/)
- {
- // hide current gizmo for entity (translate/rotate/scale)
- IGizmoManager* gizmoManager = GetGizmoManager();
- const size_t gizmoCount = static_cast<size_t>(gizmoManager->GetGizmoCount());
- for (size_t i = 0; i < gizmoCount; ++i)
- {
- gizmoManager->RemoveGizmo(gizmoManager->GetGizmoByIndex(static_cast<int>(i)));
- }
- }
- void CObjectManager::LeftComponentMode(const AZStd::vector<AZ::Uuid>& /*componentModeTypes*/)
- {
- // show translate/rotate/scale gizmo again
- if (IGizmoManager* gizmoManager = GetGizmoManager())
- {
- if (CBaseObject* selectedObject = GetIEditor()->GetSelectedObject())
- {
- gizmoManager->AddGizmo(new CAxisGizmo(selectedObject));
- }
- }
- }
- //////////////////////////////////////////////////////////////////////////
- namespace
- {
- AZStd::vector<AZStd::string> PyGetAllObjects()
- {
- IObjectManager* pObjMgr = GetIEditor()->GetObjectManager();
- CBaseObjectsArray objects;
- pObjMgr->GetObjects(objects);
- int count = pObjMgr->GetObjectCount();
- AZStd::vector<AZStd::string> result;
- for (int i = 0; i < count; ++i)
- {
- result.push_back(objects[i]->GetName().toUtf8().data());
- }
- return result;
- }
- AZStd::vector<AZStd::string> PyGetNamesOfSelectedObjects()
- {
- CSelectionGroup* pSel = GetIEditor()->GetSelection();
- AZStd::vector<AZStd::string> result;
- const int selectionCount = pSel->GetCount();
- result.reserve(selectionCount);
- for (int i = 0; i < selectionCount; i++)
- {
- result.push_back(pSel->GetObject(i)->GetName().toUtf8().data());
- }
- return result;
- }
- void PySelectObject(const char* objName)
- {
- CUndo undo("Select Object");
- CBaseObject* pObject = GetIEditor()->GetObjectManager()->FindObject(objName);
- if (pObject)
- {
- GetIEditor()->GetObjectManager()->SelectObject(pObject);
- }
- }
- void PyUnselectObjects(const AZStd::vector<AZStd::string>& names)
- {
- CUndo undo("Unselect Objects");
- std::vector<CBaseObject*> pBaseObjects;
- for (int i = 0; i < names.size(); i++)
- {
- if (!GetIEditor()->GetObjectManager()->FindObject(names[i].c_str()))
- {
- throw std::logic_error((QString("\"") + names[i].c_str() + "\" is an invalid entity.").toUtf8().data());
- }
- pBaseObjects.push_back(GetIEditor()->GetObjectManager()->FindObject(names[i].c_str()));
- }
- for (int i = 0; i < pBaseObjects.size(); i++)
- {
- GetIEditor()->GetObjectManager()->UnselectObject(pBaseObjects[i]);
- }
- }
- void PySelectObjects(const AZStd::vector<AZStd::string>& names)
- {
- CUndo undo("Select Objects");
- CBaseObject* pObject;
- for (size_t i = 0; i < names.size(); ++i)
- {
- pObject = GetIEditor()->GetObjectManager()->FindObject(names[i].c_str());
- if (!pObject)
- {
- throw std::logic_error((QString("\"") + names[i].c_str() + "\" is an invalid entity.").toUtf8().data());
- }
- GetIEditor()->GetObjectManager()->SelectObject(pObject);
- }
- }
- bool PyIsObjectHidden(const char* objName)
- {
- CBaseObject* pObject = GetIEditor()->GetObjectManager()->FindObject(objName);
- if (!pObject)
- {
- throw std::logic_error((QString("\"") + objName + "\" is an invalid object name.").toUtf8().data());
- }
- return pObject->IsHidden();
- }
- void PyHideAllObjects()
- {
- CBaseObjectsArray baseObjects;
- GetIEditor()->GetObjectManager()->GetObjects(baseObjects);
- if (baseObjects.size() <= 0)
- {
- throw std::logic_error("Objects not found.");
- }
- CUndo undo("Hide All Objects");
- for (int i = 0; i < baseObjects.size(); i++)
- {
- GetIEditor()->GetObjectManager()->HideObject(baseObjects[i], true);
- }
- }
- void PyUnHideAllObjects()
- {
- CUndo undo("Unhide All Objects");
- GetIEditor()->GetObjectManager()->UnhideAll();
- }
- void PyHideObject(const char* objName)
- {
- CUndo undo("Hide Object");
- CBaseObject* pObject = GetIEditor()->GetObjectManager()->FindObject(objName);
- if (pObject)
- {
- GetIEditor()->GetObjectManager()->HideObject(pObject, true);
- }
- }
- void PyUnhideObject(const char* objName)
- {
- CUndo undo("Unhide Object");
- CBaseObject* pObject = GetIEditor()->GetObjectManager()->FindObject(objName);
- if (pObject)
- {
- GetIEditor()->GetObjectManager()->HideObject(pObject, false);
- }
- }
- void PyFreezeObject(const char* objName)
- {
- CUndo undo("Freeze Object");
- CBaseObject* pObject = GetIEditor()->GetObjectManager()->FindObject(objName);
- if (pObject)
- {
- GetIEditor()->GetObjectManager()->FreezeObject(pObject, true);
- }
- }
- void PyUnfreezeObject(const char* objName)
- {
- CUndo undo("Unfreeze Object");
- CBaseObject* pObject = GetIEditor()->GetObjectManager()->FindObject(objName);
- if (pObject)
- {
- GetIEditor()->GetObjectManager()->FreezeObject(pObject, false);
- }
- }
- bool PyIsObjectFrozen(const char* objName)
- {
- CBaseObject* pObject = GetIEditor()->GetObjectManager()->FindObject(objName);
- if (!pObject)
- {
- throw std::logic_error((QString("\"") + objName + "\" is an invalid object name.").toUtf8().data());
- }
- return pObject->IsFrozen();
- }
- void PyDeleteObject(const char* objName)
- {
- CUndo undo("Delete Object");
- CBaseObject* pObject = GetIEditor()->GetObjectManager()->FindObject(objName);
- if (pObject)
- {
- GetIEditor()->GetObjectManager()->DeleteObject(pObject);
- }
- }
- int PyClearSelection()
- {
- CUndo undo("Clear Selection");
- return GetIEditor()->GetObjectManager()->ClearSelection();
- }
- void PyDeleteSelected()
- {
- CUndo undo("Delete Selected Object");
- GetIEditor()->GetObjectManager()->DeleteSelection();
- }
- int PyGetNumSelectedObjects()
- {
- if (CSelectionGroup* pGroup = GetIEditor()->GetObjectManager()->GetSelection())
- {
- return pGroup->GetCount();
- }
- return 0;
- }
- AZ::Vector3 PyGetSelectionCenter()
- {
- if (CSelectionGroup* pGroup = GetIEditor()->GetObjectManager()->GetSelection())
- {
- if (pGroup->GetCount() == 0)
- {
- throw std::runtime_error("Nothing selected");
- }
- const Vec3 center = pGroup->GetCenter();
- return AZ::Vector3(center.x, center.y, center.z);
- }
- throw std::runtime_error("Nothing selected");
- }
- AZ::Aabb PyGetSelectionAABB()
- {
- if (CSelectionGroup* pGroup = GetIEditor()->GetObjectManager()->GetSelection())
- {
- if (pGroup->GetCount() == 0)
- {
- throw std::runtime_error("Nothing selected");
- }
- const AABB aabb = pGroup->GetBounds();
- AZ::Aabb result;
- result.Set(
- AZ::Vector3(
- aabb.min.x,
- aabb.min.y,
- aabb.min.z
- ),
- AZ::Vector3(
- aabb.max.x,
- aabb.max.y,
- aabb.max.z
- )
- );
- return result;
- }
- throw std::runtime_error("Nothing selected");
- }
- AZ::Vector3 PyGetObjectPosition(const char* pName)
- {
- CBaseObject* pObject = GetIEditor()->GetObjectManager()->FindObject(pName);
- if (!pObject)
- {
- throw std::logic_error((QString("\"") + pName + "\" is an invalid object.").toUtf8().data());
- }
- Vec3 position = pObject->GetPos();
- return AZ::Vector3(position.x, position.y, position.z);
- }
- void PySetObjectPosition(const char* pName, float fValueX, float fValueY, float fValueZ)
- {
- CBaseObject* pObject = GetIEditor()->GetObjectManager()->FindObject(pName);
- if (!pObject)
- {
- throw std::logic_error((QString("\"") + pName + "\" is an invalid object.").toUtf8().data());
- }
- CUndo undo("Set Object Base Position");
- pObject->SetPos(Vec3(fValueX, fValueY, fValueZ));
- }
- AZ::Vector3 PyGetObjectRotation(const char* pName)
- {
- CBaseObject* pObject = GetIEditor()->GetObjectManager()->FindObject(pName);
- if (!pObject)
- {
- throw std::logic_error((QString("\"") + pName + "\" is an invalid object.").toUtf8().data());
- }
- Ang3 ang = RAD2DEG(Ang3(pObject->GetRotation()));
- return AZ::Vector3(ang.x, ang.y, ang.z);
- }
- void PySetObjectRotation(const char* pName, float fValueX, float fValueY, float fValueZ)
- {
- CBaseObject* pObject = GetIEditor()->GetObjectManager()->FindObject(pName);
- if (!pObject)
- {
- throw std::logic_error((QString("\"") + pName + "\" is an invalid object.").toUtf8().data());
- }
- CUndo undo("Set Object Rotation");
- pObject->SetRotation(Quat(DEG2RAD(Ang3(fValueX, fValueY, fValueZ))));
- }
- AZ::Vector3 PyGetObjectScale(const char* pName)
- {
- CBaseObject* pObject = GetIEditor()->GetObjectManager()->FindObject(pName);
- if (!pObject)
- {
- throw std::logic_error((QString("\"") + pName + "\" is an invalid object.").toUtf8().data());
- }
- Vec3 scaleVec3 = pObject->GetScale();
- return AZ::Vector3(scaleVec3.x, scaleVec3.y, scaleVec3.z);
- }
- void PySetObjectScale(const char* pName, float fValueX, float fValueY, float fValueZ)
- {
- CBaseObject* pObject = GetIEditor()->GetObjectManager()->FindObject(pName);
- if (!pObject)
- {
- throw std::logic_error((QString("\"") + pName + "\" is an invalid object.").toUtf8().data());
- }
- CUndo undo("Set Object Scale");
- pObject->SetScale(Vec3(fValueX, fValueY, fValueZ));
- }
- void PyRenameObject(const char* pOldName, const char* pNewName)
- {
- CBaseObject* pObject = GetIEditor()->GetObjectManager()->FindObject(pOldName);
- if (!pObject)
- {
- throw std::runtime_error("Could not find object");
- }
- if (strcmp(pNewName, "") == 0 || GetIEditor()->GetObjectManager()->FindObject(pNewName))
- {
- throw std::runtime_error("Invalid object name.");
- }
- CUndo undo("Rename object");
- pObject->SetName(pNewName);
- }
- }
- namespace AzToolsFramework
- {
- void ObjectManagerFuncsHandler::Reflect(AZ::ReflectContext* context)
- {
- if (auto behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
- {
- // this will put these methods into the 'azlmbr.legacy.general' module
- auto addLegacyGeneral = [](AZ::BehaviorContext::GlobalMethodBuilder methodBuilder)
- {
- methodBuilder->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation)
- ->Attribute(AZ::Script::Attributes::Category, "Legacy/Editor")
- ->Attribute(AZ::Script::Attributes::Module, "legacy.general");
- };
- addLegacyGeneral(behaviorContext->Method("get_all_objects", PyGetAllObjects, nullptr, "Gets the list of names of all objects in the whole level."));
- addLegacyGeneral(behaviorContext->Method("get_names_of_selected_objects", PyGetNamesOfSelectedObjects, nullptr, "Get the name from selected object/objects."));
- addLegacyGeneral(behaviorContext->Method("select_object", PySelectObject, nullptr, "Selects a specified object."));
- addLegacyGeneral(behaviorContext->Method("unselect_objects", PyUnselectObjects, nullptr, "Unselects a list of objects."));
- addLegacyGeneral(behaviorContext->Method("select_objects", PySelectObjects, nullptr, "Selects a list of objects."));
- addLegacyGeneral(behaviorContext->Method("get_num_selected", PyGetNumSelectedObjects, nullptr, "Returns the number of selected objects."));
- addLegacyGeneral(behaviorContext->Method("clear_selection", PyClearSelection, nullptr, "Clears selection."));
- addLegacyGeneral(behaviorContext->Method("get_selection_center", PyGetSelectionCenter, nullptr, "Returns the center point of the selection group."));
- addLegacyGeneral(behaviorContext->Method("get_selection_aabb", PyGetSelectionAABB, nullptr, "Returns the aabb of the selection group."));
- addLegacyGeneral(behaviorContext->Method("hide_object", PyHideObject, nullptr, "Hides a specified object."));
- addLegacyGeneral(behaviorContext->Method("is_object_hidden", PyIsObjectHidden, nullptr, "Checks if object is hidden and returns a bool value."));
- addLegacyGeneral(behaviorContext->Method("unhide_object", PyUnhideObject, nullptr, "Unhides a specified object."));
- addLegacyGeneral(behaviorContext->Method("hide_all_objects", PyHideAllObjects, nullptr, "Hides all objects."));
- addLegacyGeneral(behaviorContext->Method("unhide_all_objects", PyUnHideAllObjects, nullptr, "Unhides all objects."));
- addLegacyGeneral(behaviorContext->Method("freeze_object", PyFreezeObject, nullptr, "Freezes a specified object."));
- addLegacyGeneral(behaviorContext->Method("is_object_frozen", PyIsObjectFrozen, nullptr, "Checks if object is frozen and returns a bool value."));
- addLegacyGeneral(behaviorContext->Method("unfreeze_object", PyUnfreezeObject, nullptr, "Unfreezes a specified object."));
- addLegacyGeneral(behaviorContext->Method("delete_object", PyDeleteObject, nullptr, "Deletes a specified object."));
- addLegacyGeneral(behaviorContext->Method("delete_selected", PyDeleteSelected, nullptr, "Deletes selected object(s)."));
- addLegacyGeneral(behaviorContext->Method("get_position", PyGetObjectPosition, nullptr, "Gets the position of an object."));
- addLegacyGeneral(behaviorContext->Method("set_position", PySetObjectPosition, nullptr, "Sets the position of an object."));
- addLegacyGeneral(behaviorContext->Method("get_rotation", PyGetObjectRotation, nullptr, "Gets the rotation of an object."));
- addLegacyGeneral(behaviorContext->Method("set_rotation", PySetObjectRotation, nullptr, "Sets the rotation of an object."));
- addLegacyGeneral(behaviorContext->Method("get_scale", PyGetObjectScale, nullptr, "Gets the scale of an object."));
- addLegacyGeneral(behaviorContext->Method("set_scale", PySetObjectScale, nullptr, "Sets the scale of an object."));
- addLegacyGeneral(behaviorContext->Method("rename_object", PyRenameObject, nullptr, "Renames object with oldObjectName to newObjectName."));
- }
- }
- }
|