!I (1670414, 1670415, 1670416, 1670424, 1670431):
[CRYENGINE.git] / Code / Sandbox / EditorQt / IEditorImpl.cpp
blob7b94ece73f3f3cbd80624f18ef7f432650fd487d
1 // Copyright 2001-2018 Crytek GmbH / Crytek Group. All rights reserved.
3 #include "StdAfx.h"
4 #include "IEditorImpl.h"
5 #include "CryEdit.h"
6 #include "CryEditDoc.h"
7 #include "Dialogs/CustomColorDialog.h"
8 #include "ClassFactory.h"
9 #include <CryCore/ToolsHelpers/ResourceCompilerHelper.h>
11 #include "PluginManager.h"
12 #include "IconManager.h"
13 #include "ViewManager.h"
14 #include "Gizmos/GizmoManager.h"
15 #include "Gizmos/TransformManipulator.h"
16 #include "HyperGraph/FlowGraphManager.h"
17 #include "HyperGraph/FlowGraphModuleManager.h"
18 #include "HyperGraph/Controls/FlowGraphDebuggerEditor.h"
19 #include "Export/ExportManager.h"
20 #include "Material/MaterialFXGraphMan.h"
21 #include "CustomActions/CustomActionsEditorManager.h"
22 #include "AI/AIManager.h"
23 #include "UI/UIManager.h"
24 #include "Undo/Undo.h"
25 #include "Material/MaterialManager.h"
26 #include "Material/MaterialPickTool.h"
27 #include "EntityPrototypeManager.h"
28 #include "GameEngine.h"
29 #include "BaseLibraryDialog.h"
30 #include "Material/Material.h"
31 #include "EntityPrototype.h"
32 #include "Particles/ParticleManager.h"
33 #include "Prefabs/PrefabManager.h"
34 #include "GameTokens/GameTokenManager.h"
35 #include "LensFlareEditor/LensFlareManager.h"
36 #include "DataBaseDialog.h"
37 #include "UIEnumsDatabase.h"
38 #include "Util/Ruler.h"
39 #include "Script/ScriptEnvironment.h"
40 #include "Gizmos/AxisHelper.h"
41 #include "PickObjectTool.h"
42 #include "ObjectCreateTool.h"
43 #include "Vegetation/VegetationMap.h"
44 #include "Terrain/TerrainManager.h"
45 #include "Terrain/SurfaceType.h"
46 #include <Cry3DEngine/I3DEngine.h>
47 #include <CrySystem/IConsole.h>
48 #include <CryEntitySystem/IEntitySystem.h>
49 #include <CryMovie/IMovieSystem.h>
50 #include <ISourceControl.h>
51 #include <IDevManager.h>
52 #include "Objects/ObjectLayerManager.h"
53 #include "BackgroundTaskManager.h"
54 #include "BackgroundScheduleManager.h"
55 #include "EditorFileMonitor.h"
56 #include <CrySandbox/IEditorGame.h>
57 #include "EditMode/ObjectMode.h"
58 #include "Mission.h"
59 #include "Commands/PythonManager.h"
60 #include "Commands/PolledKeyManager.h"
61 #include "EditorFramework/PersonalizationManager.h"
62 #include "EditorFramework/BroadcastManager.h"
63 #include "LevelEditor/LevelEditorSharedState.h"
64 #include "EditorCommonInit.h"
65 #include "AssetSystem/AssetManager.h"
66 #include <Preferences/ViewportPreferences.h>
67 #include "MainThreadWorker.h"
69 #include <CrySerialization/Serializer.h>
70 #include <CrySandbox/CryInterop.h>
71 #include "ResourceSelectorHost.h"
72 #include "Util/BoostPythonHelpers.h"
74 #include "FileSystem/FileSystem_Enumerator.h"
76 #include "QT/QtMainFrame.h"
77 #include "QT/QToolTabManager.h"
78 #include "QT/Widgets/QPreviewWidget.h"
79 #include "Material/MaterialBrowser.h"
81 #include "Controls/QuestionDialog.h"
82 #include "FilePathUtil.h"
83 #include <Notifications/NotificationCenterImpl.h>
84 #include <EditorFramework/TrayArea.h>
85 #include <EditorFramework/Preferences.h>
86 #include <Preferences/GeneralPreferences.h>
87 #include <CrySystem/IProjectManager.h>
89 #include <QFileInfo>
90 #include "ConfigurationManager.h"
91 #include <CryGame/IGameFramework.h>
93 LINK_SYSTEM_LIBRARY("version.lib")
94 // Shell utility library
95 LINK_SYSTEM_LIBRARY("Shlwapi.lib")
97 // CBaseObject hacks
98 #include "SurfaceInfoPicker.h"
99 #include "Objects/PrefabObject.h"
100 #include "PhysTool.h"
102 #include "MFCToolsPlugin.h"
104 // even in Release mode, the editor will return its heap, because there's no Profile build configuration for the editor
105 #ifdef _RELEASE
106 #undef _RELEASE
107 #endif
108 #include <CryCore/CrtDebugStats.h>
109 #include "LinkTool.h"
111 static CCryEditDoc * theDocument;
112 static CEditorImpl* s_pEditor = NULL;
114 IEditor* GetIEditor() { return s_pEditor; }
116 CEditorImpl* GetIEditorImpl()
118 return s_pEditor;
121 CEditorImpl::CEditorImpl(CGameEngine* ge)
122 : m_bInitialized(false)
123 , m_objectHideMask(0)
124 , editorConfigSpec(CONFIG_MEDIUM_SPEC)
125 , m_areHelpersEnabled(true)
127 LOADING_TIME_PROFILE_SECTION;
129 //This is dangerous and should (in theory) be set at the end of the constructor for safety, after everything is properly initialized.
130 //Code within this scope can use GetIEditorImpl() at their own risk
131 s_pEditor = this;
133 //init game engine first as there may be a lot of things depending on pSystem or gEnv.
134 m_pSystem = ge->GetSystem();
135 m_pGameEngine = ge;
136 RegisterNotifyListener(m_pGameEngine);
138 EditorCommon::SetIEditor(this);
139 MFCToolsPlugin::SetEditor(s_pEditor);
141 m_currEditMode = eEditModeSelect;
142 m_prevEditMode = m_currEditMode;
143 m_pEditTool = 0;
144 m_pLevelIndependentFileMan = new CLevelIndependentFileMan;
145 m_pLevelEditorSharedState.reset(new LevelEditorSharedState);
146 m_pExportManager = 0;
147 SetMasterCDFolder();
148 m_bExiting = false;
149 m_pClassFactory = CClassFactory::Instance();
151 m_pGlobalBroadcastManager = new CBroadcastManager();
152 m_pNotificationCenter = new CNotificationCenter();
153 m_pTrayArea = new CTrayArea();
154 m_pCommandManager = new CEditorCommandManager();
155 m_pPersonalizationManager = new CPersonalizationManager();
156 m_pPreferences = new CPreferences();
157 CAutoRegisterPreferencesHelper::RegisterAll();
158 m_pPythonManager = new CEditorPythonManager();
159 m_pPythonManager->Init();//must be initialized before plugins are initialized
160 m_pAssetManager = new CAssetManager();
161 m_pPolledKeyManager = new CPolledKeyManager();
162 m_pConsoleSync = 0;
163 m_pEditorFileMonitor.reset(new CEditorFileMonitor());
164 m_pBackgroundTaskManager.reset(new BackgroundTaskManager::CTaskManager);
165 m_pBackgroundScheduleManager.reset(new BackgroundScheduleManager::CScheduleManager);
166 m_pBGTasks.reset(new BackgroundTaskManager::CBackgroundTasksListener);
168 m_pUIEnumsDatabase = new CUIEnumsDatabase;
169 m_pPluginManager = new CPluginManager;
170 m_pTerrainManager = new CTerrainManager();
171 m_pVegetationMap = new CVegetationMap();
172 m_pObjectManager = new CObjectManager;
173 m_pGizmoManager = new CGizmoManager;
174 m_pViewManager = new CViewManager;
175 m_pIconManager = new CIconManager;
176 m_pUndoManager = new CUndoManager;
177 m_pAIManager = new CAIManager;
178 m_pUIManager = new CUIManager;
179 m_pCustomActionsManager = new CCustomActionsEditorManager;
180 m_pMaterialManager = new CMaterialManager();
181 m_pEntityManager = new CEntityPrototypeManager;
182 m_particleManager = new CParticleManager;
183 m_pPrefabManager = new CPrefabManager;
184 m_pGameTokenManager = new CGameTokenManager;
185 m_pFlowGraphManager = new CFlowGraphManager;
187 m_pLensFlareManager = new CLensFlareManager;
188 m_pFlowGraphModuleManager = new CEditorFlowGraphModuleManager;
189 m_pFlowGraphDebuggerEditor = new CFlowGraphDebuggerEditor;
190 m_pMatFxGraphManager = new CMaterialFXGraphMan;
191 m_pDevManager = new CDevManager();
192 m_pSourceControl = 0;
193 m_pScriptEnv = new EditorScriptEnvironment();
195 m_pResourceSelectorHost.reset(CreateResourceSelectorHost());
196 CAutoRegisterResourceSelector::RegisterAll();
198 m_pRuler = new CRuler;
199 m_pConfigurationManager = new CConfigurationManager();
201 m_pMainThreadWorker = new CMainThreadWorker();
203 m_selectedRegion.min = Vec3(0, 0, 0);
204 m_selectedRegion.max = Vec3(0, 0, 0);
205 ZeroStruct(m_lastAxis);
206 m_lastAxis[eEditModeSelect] = AXIS_XY;
207 m_lastAxis[eEditModeSelectArea] = AXIS_XY;
208 m_lastAxis[eEditModeMove] = AXIS_XY;
209 m_lastAxis[eEditModeRotate] = AXIS_Z;
210 m_lastAxis[eEditModeScale] = AXIS_XY;
211 ZeroStruct(m_lastCoordSys);
212 m_lastCoordSys[eEditModeSelect] = COORDS_LOCAL;
213 m_lastCoordSys[eEditModeSelectArea] = COORDS_LOCAL;
214 m_lastCoordSys[eEditModeMove] = COORDS_LOCAL;
215 m_lastCoordSys[eEditModeRotate] = COORDS_LOCAL;
216 m_lastCoordSys[eEditModeScale] = COORDS_LOCAL;
217 m_bAxisVectorLock = false;
218 m_bUpdates = true;
220 m_bSelectionLocked = false;
221 m_snapModeFlags = 0;
223 m_pPickTool = 0;
224 m_bMatEditMode = false;
225 m_bShowStatusText = true;
227 doc_use_subfolder_for_crash_backup = 0;
229 CPhysPullTool::RegisterCVars();
231 MFCToolsPlugin::Initialize();
232 EditorCommon::Initialize();
234 m_pGameEngine->InitAdditionalEngineComponents();
237 void CEditorImpl::Init()
239 m_pCommandManager->RegisterAutoCommands();
240 AddUIEnums();
242 if (gEnv->pRenderer)
243 gEnv->pRenderer->AddAsyncTextureCompileListener(m_pBGTasks.get());
245 m_pSystem->GetISystemEventDispatcher()->RegisterListener(this, "CEditorImpl");
247 gEnv->pInput->OnFilterInputEvent = OnFilterInputEvent;
249 CAutoRegisterClassHelper::RegisterAll();
251 m_pPolledKeyManager->Init();
253 m_pBackgroundTaskManager->AddListener(m_pBGTasks.get(), "Editor");
255 auto projectPath = PathUtil::GetGameProjectAssetsPath();
256 m_pFileSystemEnumerator.reset(new FileSystem::CEnumerator(projectPath.c_str()));
258 m_pNotificationCenter->Init();
260 DetectVersion();
262 m_templateRegistry.LoadTemplates("%EDITOR%");
264 m_pConfigurationManager->Init();
267 CEditorImpl::~CEditorImpl()
269 m_pSystem->GetISystemEventDispatcher()->RemoveListener(this);
270 m_bExiting = true; // Can't save level after this point (while Crash)
271 SAFE_DELETE(m_pScriptEnv);
272 SAFE_RELEASE(m_pSourceControl);
273 SAFE_DELETE(m_pGameTokenManager);
275 SAFE_DELETE(m_pMatFxGraphManager);
276 SAFE_DELETE(m_pFlowGraphModuleManager);
278 if (m_pFlowGraphDebuggerEditor)
280 m_pFlowGraphDebuggerEditor->Shutdown();
281 SAFE_DELETE(m_pFlowGraphDebuggerEditor);
284 SAFE_DELETE(m_particleManager)
285 SAFE_DELETE(m_pEntityManager)
286 SAFE_DELETE(m_pMaterialManager)
287 SAFE_DELETE(m_pIconManager)
288 SAFE_DELETE(m_pViewManager)
289 SAFE_DELETE(m_pObjectManager) // relies on prefab manager
290 SAFE_DELETE(m_pPrefabManager); // relies on flowgraphmanager
291 SAFE_DELETE(m_pGizmoManager)
292 SAFE_DELETE(m_pFlowGraphManager);
293 SAFE_DELETE(m_pVegetationMap);
294 SAFE_DELETE(m_pTerrainManager);
295 // AI should be destroyed after the object manager, as the objects may
296 // refer to AI components.
297 SAFE_DELETE(m_pAIManager)
298 SAFE_DELETE(m_pUIManager)
299 SAFE_DELETE(m_pCustomActionsManager)
300 SAFE_DELETE(m_pPluginManager)
301 SAFE_DELETE(m_pRuler)
302 SAFE_DELETE(m_pPreferences)
303 SAFE_DELETE(m_pPersonalizationManager)
304 SAFE_DELETE(m_pCommandManager)
305 SAFE_DELETE(m_pTrayArea)
306 SAFE_DELETE(m_pNotificationCenter)
307 SAFE_DELETE(m_pPythonManager)
308 SAFE_DELETE(m_pPolledKeyManager)
310 CAutoRegisterClassHelper::UnregisterAll();
311 SAFE_DELETE(m_pClassFactory)
313 SAFE_DELETE(m_pUIEnumsDatabase)
314 SAFE_DELETE(m_pExportManager);
315 SAFE_DELETE(m_pDevManager);
316 SAFE_DELETE(m_pConfigurationManager);
317 // Game engine should be among the last things to be destroyed, as it
318 // destroys the engine.
319 SAFE_DELETE(m_pLevelIndependentFileMan);
321 UnregisterNotifyListener(m_pGameEngine);
322 SAFE_DELETE(m_pGameEngine);
324 m_pGlobalBroadcastManager->deleteLater();
326 EditorCommon::Deinitialize();
327 MFCToolsPlugin::Deinitialize();
328 s_pEditor = nullptr;
331 bool CEditorImpl::IsMainFrameClosing() const
333 return CEditorMainFrame::GetInstance()->IsClosing();
336 void CEditorImpl::SetMasterCDFolder()
338 m_masterCDFolder = wstring(L".");
341 bool CEditorImpl::OnFilterInputEvent(SInputEvent* pInput)
343 CryInputEvent event(pInput);
344 event.SendToKeyboardFocus();
345 return event.isAccepted();
348 ILevelEditor* CEditorImpl::GetLevelEditor()
350 return CEditorMainFrame::GetInstance()->GetLevelEditor();
353 void CEditorImpl::ExecuteCommand(const char* sCommand, ...)
355 char buffer[1024];
356 va_list args;
357 va_start(args, sCommand);
358 cry_vsprintf(buffer, sCommand, args);
359 va_end(args);
360 m_pCommandManager->Execute(buffer);
363 IPythonManager* CEditorImpl::GetIPythonManager()
365 return m_pPythonManager;
368 ICommandManager* CEditorImpl::GetICommandManager()
370 return m_pCommandManager;
373 void CEditorImpl::WriteToConsole(const char* pszString)
375 CLogFile::WriteLine(pszString);
378 const ISelectionGroup* CEditorImpl::GetISelectionGroup() const
380 return GetSelection();
383 void CEditorImpl::Update()
385 if (!m_bUpdates)
386 return;
388 // Make sure this is not called recursively
389 m_bUpdates = false;
391 CRY_PROFILE_FUNCTION(PROFILE_EDITOR);
392 m_pRuler->Update();
394 //@FIXME: Restore this latter.
395 //if (GetGameEngine() && GetGameEngine()->IsLevelLoaded())
397 m_pObjectManager->Update();
399 if (IsInPreviewMode())
401 SetModifiedFlag(FALSE);
404 if (m_pGameEngine != NULL)
406 IEditorGame* pEditorGame = m_pGameEngine->GetIEditorGame();
407 if (pEditorGame != NULL)
409 IEditorGame::HelpersDrawMode::EType helpersDrawMode = IEditorGame::HelpersDrawMode::Hide;
410 if (GetIEditor()->IsHelpersDisplayed())
412 helpersDrawMode = IEditorGame::HelpersDrawMode::Show;
414 pEditorGame->UpdateHelpers(helpersDrawMode);
418 for (EReloadScriptsType kind : m_reloadScriptsQueue)
420 WPARAM p;
421 switch (kind)
423 case eReloadScriptsType_Actor:
424 p = ID_RELOAD_ACTOR_SCRIPTS;
425 break;
426 case eReloadScriptsType_AI:
427 p = ID_RELOAD_AI_SCRIPTS;
428 break;
429 case eReloadScriptsType_Entity:
430 p = ID_RELOAD_ENTITY_SCRIPTS;
431 break;
432 case eReloadScriptsType_Item:
433 p = ID_RELOAD_ITEM_SCRIPTS;
434 break;
435 case eReloadScriptsType_UI:
436 p = ID_RELOAD_UI_SCRIPTS;
437 break;
438 default:
439 continue;
441 AfxGetMainWnd()->SendMessage(WM_COMMAND, p, 0);
443 m_reloadScriptsQueue.clear();
445 m_bUpdates = true;
448 ISystem* CEditorImpl::GetSystem()
450 return m_pSystem;
453 I3DEngine* CEditorImpl::Get3DEngine()
455 if (gEnv)
456 return gEnv->p3DEngine;
457 return 0;
460 IRenderer* CEditorImpl::GetRenderer()
462 if (gEnv)
463 return gEnv->pRenderer;
464 return 0;
467 IEditorClassFactory* CEditorImpl::GetClassFactory()
469 return m_pClassFactory;
472 CCryEditDoc* CEditorImpl::GetDocument() const
474 return theDocument;
477 void CEditorImpl::SetDocument(CCryEditDoc* pDoc)
479 theDocument = pDoc;
482 void CEditorImpl::CloseDocument()
484 if (theDocument)
486 LOADING_TIME_PROFILE_SECTION;
487 Notify(eNotify_OnBeginSceneClose);
488 theDocument->DeleteContents();
489 delete theDocument;
490 // might be better to just recreate an empty document instead to make sure no invalid access happens
491 theDocument = nullptr;
492 Notify(eNotify_OnEndSceneClose);
496 void CEditorImpl::SetModifiedFlag(bool modified)
498 if (GetDocument() && GetDocument()->IsDocumentReady())
500 GetDocument()->SetModifiedFlag(modified);
502 if (modified)
504 GetDocument()->SetLevelExported(false);
509 bool CEditorImpl::IsLevelExported() const
511 CCryEditDoc* pDoc = GetDocument();
513 if (pDoc)
515 return pDoc->IsLevelExported();
518 return false;
521 bool CEditorImpl::SetLevelExported(bool boExported)
523 if (GetDocument())
525 GetDocument()->SetLevelExported(boExported);
526 return true;
528 return false;
531 bool CEditorImpl::SaveDocument()
533 if (m_bExiting)
534 return false;
536 if (GetDocument())
537 return GetDocument()->Save();
538 else
539 return false;
542 bool CEditorImpl::SaveDocumentBackup()
544 if (m_bExiting)
545 return false;
547 // Assets backup
548 if (doc_use_subfolder_for_crash_backup)
550 const CTime theTime = CTime::GetCurrentTime();
551 const string backupFolder = PathUtil::Make(PathUtil::GetUserSandboxFolder(), theTime.Format("CrashBackup/%Y.%m.%d [%H-%M.%S]"));
552 GetAssetManager()->SaveBackup(backupFolder);
554 else
556 GetAssetManager()->SaveAll(nullptr);
559 const char* const CRASH_FOLDER = "/.CRASH_BACKUP/";
560 const char* const CRASH_FILE_PREFIX = "CRASH_BACKUP_";
562 if (CCryEditDoc* pDocument = GetDocument())
564 bool bShouldCreateBackup = true;
565 if (doc_use_subfolder_for_crash_backup)
567 string sLevelFolder = pDocument->GetPathName().GetString(); // copy the string so we can modify it
568 if (sLevelFolder.GetLength() != 0)
570 IObjectManager* pObjectManager = GetObjectManager();
571 if (!pObjectManager)
573 return false;
576 CObjectLayerManager* pObjectLayerManager = pObjectManager->GetLayersManager();
577 if (!pObjectLayerManager)
579 return false;
582 string backupFolder = sLevelFolder.GetString(); // get the modifiable string buffer
583 backupFolder = PathUtil::GetParentDirectory(backupFolder);
584 backupFolder.Append(CRASH_FOLDER);
586 if (::CreateDirectory(backupFolder, NULL) || (GetLastError() == ERROR_ALREADY_EXISTS))
588 string oldLayerPath = pObjectLayerManager->GetLayersPath();
589 string newLayerPath(CRASH_FOLDER);
590 newLayerPath.Append(oldLayerPath);
591 pObjectLayerManager->SetLayersPath(newLayerPath); // make sure layers are saved in the crash folder, not the current folder
592 string fullLayerPath(backupFolder);
593 fullLayerPath.Append(oldLayerPath);
594 if (::CreateDirectory(fullLayerPath.GetString(), NULL) || (GetLastError() == ERROR_ALREADY_EXISTS))
596 string sLevelName = pDocument->GetPathName(); // copy the string so we can modify it
597 sLevelName = PathUtil::GetFile(sLevelName);
598 char szCrashBackupName[MAX_PATH];
599 cry_sprintf(szCrashBackupName, "%s%s%s", backupFolder.GetString(), CRASH_FILE_PREFIX, sLevelName.GetString());
601 pDocument->SetPathName(szCrashBackupName, false);
603 else
605 bShouldCreateBackup = false;
608 pObjectLayerManager->SetLayersPath(oldLayerPath);
610 else
612 bShouldCreateBackup = false;
617 if (bShouldCreateBackup)
619 return pDocument->Save();
623 return false;
626 string CEditorImpl::GetMasterCDFolder()
628 return CryStringUtils::WStrToUTF8(m_masterCDFolder.c_str());
631 string CEditorImpl::GetLevelFolder()
633 return GetGameEngine()->GetLevelPath();
636 const char* CEditorImpl::GetLevelName()
638 m_levelNameBuffer = GetGameEngine()->GetLevelName();
639 return m_levelNameBuffer.GetBuffer();
642 const char* CEditorImpl::GetLevelPath()
644 return GetLevelFolder();
647 string CEditorImpl::GetLevelDataFolder()
649 return PathUtil::AddSlash(PathUtil::Make(GetGameEngine()->GetLevelPath(), "LevelData")).c_str();
652 const char* CEditorImpl::GetUserFolder()
654 m_userFolder = string(PathUtil::GetUserSandboxFolder().c_str());
655 return m_userFolder;
658 void CEditorImpl::SetDataModified()
660 GetDocument()->SetModifiedFlag(TRUE);
663 int CEditorImpl::GetEditMode()
665 return m_currEditMode;
668 void CEditorImpl::SetEditMode(int editMode)
670 m_currEditMode = (EEditMode)editMode;
671 m_prevEditMode = m_currEditMode;
672 AABB box(Vec3(0, 0, 0), Vec3(0, 0, 0));
673 SetSelectedRegion(box);
675 if (GetEditTool() && !GetEditTool()->IsNeedMoveTool())
677 SetEditTool(0, true);
680 if (editMode == eEditModeMove || editMode == eEditModeRotate || editMode == eEditModeScale)
682 SetAxisConstrains(m_lastAxis[editMode]);
683 SetReferenceCoordSys(m_lastCoordSys[editMode]);
686 Notify(eNotify_OnEditModeChange);
689 void CEditorImpl::SetEditTool(CEditTool* tool, bool bStopCurrentTool)
691 CViewport* pViewport = GetIEditorImpl()->GetActiveView();
692 if (pViewport)
694 pViewport->SetCurrentCursor(STD_CURSOR_DEFAULT);
697 if (tool == 0)
699 // Replace tool with the object modify edit tool.
700 if (m_pEditTool != 0 && m_pEditTool->IsKindOf(RUNTIME_CLASS(CObjectMode)))
702 // Do not change.
703 return;
705 else
707 tool = new CObjectMode;
711 Notify(eNotify_OnEditToolBeginChange);
713 m_pEditTool = tool;
715 // Make sure pick is aborted.
716 if (tool != m_pPickTool)
718 m_pPickTool = 0;
720 Notify(eNotify_OnEditToolEndChange);
723 void CEditorImpl::SetEditTool(const string& sEditToolName, bool bStopCurrentTool)
725 CEditTool* pTool = GetEditTool();
726 if (pTool && pTool->GetRuntimeClass()->m_lpszClassName)
728 // Check if already selected.
729 if (stricmp(pTool->GetRuntimeClass()->m_lpszClassName, sEditToolName) == 0)
730 return;
733 IClassDesc* pClass = GetIEditorImpl()->GetClassFactory()->FindClass(sEditToolName);
734 if (!pClass)
736 Warning("Editor Tool %s not registered.", (const char*)sEditToolName);
737 return;
739 if (pClass->SystemClassID() != ESYSTEM_CLASS_EDITTOOL)
741 Warning("Class name %s is not a valid Edit Tool class.", (const char*)sEditToolName);
742 return;
744 CRuntimeClass* pRtClass = pClass->GetRuntimeClass();
745 if (pRtClass && pRtClass->IsDerivedFrom(RUNTIME_CLASS(CEditTool)))
747 CEditTool* pEditTool = (CEditTool*)pRtClass->CreateObject();
748 GetIEditorImpl()->SetEditTool(pEditTool);
749 return;
751 else
753 Warning("Class name %s is not a valid Edit Tool class.", (const char*)sEditToolName);
754 return;
758 CEditTool* CEditorImpl::GetEditTool()
760 return m_pEditTool;
763 void CEditorImpl::SetAxisConstrains(AxisConstrains axisFlags)
765 gGizmoPreferences.axisConstraint = axisFlags;
766 m_lastAxis[m_currEditMode] = gGizmoPreferences.axisConstraint;
767 m_pViewManager->SetAxisConstrain(axisFlags);
769 // Update all views.
770 UpdateViews(eUpdateObjects, NULL);
771 Notify(eNotify_OnAxisConstraintChanged);
774 AxisConstrains CEditorImpl::GetAxisConstrains()
776 return gGizmoPreferences.axisConstraint;
779 uint16 CEditorImpl::GetSnapMode()
781 return m_snapModeFlags;
784 void CEditorImpl::EnableSnapToTerrain(bool bEnable)
786 m_snapModeFlags &= ~eSnapMode_Terrain;
787 if (bEnable) // Disable geometry before enabling terrain snapping
788 m_snapModeFlags = (m_snapModeFlags & ~eSnapMode_Geometry) | bEnable * eSnapMode_Terrain;
791 bool CEditorImpl::IsSnapToTerrainEnabled() const
793 return m_snapModeFlags & eSnapMode_Terrain;
796 void CEditorImpl::EnableSnapToNormal(bool bEnable)
798 m_snapModeFlags = (m_snapModeFlags & ~eSnapMode_SurfaceNormal) | bEnable * eSnapMode_SurfaceNormal;
801 void CEditorImpl::EnableHelpersDisplay(bool bEnable)
803 m_areHelpersEnabled = bEnable;
806 void CEditorImpl::EnablePivotSnapping(bool bEnable)
808 m_bPivotSnappingEnabled = bEnable;
811 bool CEditorImpl::IsSnapToNormalEnabled() const
813 return m_snapModeFlags & eSnapMode_SurfaceNormal;
816 bool CEditorImpl::IsHelpersDisplayed() const
818 return m_areHelpersEnabled;
821 bool CEditorImpl::IsPivotSnappingEnabled() const
823 return m_bPivotSnappingEnabled;
826 void CEditorImpl::EnableSnapToGeometry(bool bEnable)
828 m_snapModeFlags &= ~eSnapMode_Geometry;
829 if (bEnable) // Disable terrain before enabling geometry snapping
830 m_snapModeFlags = (m_snapModeFlags & ~eSnapMode_Terrain) | bEnable * eSnapMode_Geometry;
833 bool CEditorImpl::IsSnapToGeometryEnabled() const
835 return m_snapModeFlags & eSnapMode_Geometry;
838 void CEditorImpl::SetReferenceCoordSys(RefCoordSys refCoords)
840 if (refCoords != gGizmoPreferences.referenceCoordSys)
842 gGizmoPreferences.referenceCoordSys = refCoords;
843 m_lastCoordSys[m_currEditMode] = gGizmoPreferences.referenceCoordSys;
845 // Update all views.
846 UpdateViews(eUpdateObjects, NULL);
848 // Update the construction plane infos.
849 CViewport* pViewport = GetActiveView();
850 if (pViewport)
851 pViewport->MakeSnappingGridPlane(GetIEditorImpl()->GetAxisConstrains());
853 Notify(eNotify_OnReferenceCoordSysChanged);
857 RefCoordSys CEditorImpl::GetReferenceCoordSys()
859 return gGizmoPreferences.referenceCoordSys;
862 CBaseObject* CEditorImpl::NewObject(const char* type, const char* file /*=nullptr*/, bool bInteractive /*= false*/)
864 CUndo undo("Create new object");
866 CBaseObject* pObject = GetObjectManager()->NewObject(type, 0, file);
867 if (pObject)
869 if (bInteractive)
871 Matrix34 objectTM;
872 objectTM.SetIdentity();
873 pObject->SetLocalTM(objectTM);
875 // if this object type was hidden by category, re-display it.
876 int hideMask = gViewportDebugPreferences.GetObjectHideMask();
877 hideMask = hideMask & ~(pObject->GetType());
878 gViewportDebugPreferences.SetObjectHideMask(hideMask);
880 // Enable display of current layer.
881 CObjectLayer* pLayer = m_pObjectManager->GetLayersManager()->GetCurrentLayer();
882 assert(pLayer);
883 pLayer->SetFrozen(false);
884 pLayer->SetVisible(true);
885 pLayer->SetModified();
887 m_pObjectManager->ClearSelection();
888 m_pObjectManager->SelectObject(pObject);
891 SetModifiedFlag();
892 return pObject;
894 else
896 return nullptr;
900 //////////////////////////////////////////////////////////////////////////
901 void CEditorImpl::DeleteObject(CBaseObject* obj)
903 SetModifiedFlag();
904 GetObjectManager()->DeleteObject(obj);
907 CBaseObject* CEditorImpl::CloneObject(CBaseObject* obj)
909 SetModifiedFlag();
910 return GetObjectManager()->CloneObject(obj);
913 void CEditorImpl::StartObjectCreation(const char* type, const char* file)
915 if (!GetDocument()->IsDocumentReady())
916 return;
918 CObjectCreateTool* tool = new CObjectCreateTool();
919 GetIEditorImpl()->SetEditTool(tool);
920 tool->SelectObjectToCreate(type, file);
923 CBaseObject* CEditorImpl::GetSelectedObject()
925 CBaseObject* obj = 0;
926 if (m_pObjectManager->GetSelection()->GetCount() != 1)
927 return 0;
928 return m_pObjectManager->GetSelection()->GetObject(0);
931 void CEditorImpl::SelectObject(CBaseObject* obj)
933 GetObjectManager()->SelectObject(obj);
936 void CEditorImpl::SelectObjects(std::vector<CBaseObject*> objects)
938 GetObjectManager()->SelectObjects(objects);
941 IObjectManager* CEditorImpl::GetObjectManager()
943 return m_pObjectManager;
946 IGizmoManager* CEditorImpl::GetGizmoManager()
948 return m_pGizmoManager;
951 const CSelectionGroup* CEditorImpl::GetSelection() const
953 return m_pObjectManager->GetSelection();
956 int CEditorImpl::ClearSelection()
958 if (GetSelection()->IsEmpty())
959 return 0;
960 string countString = GetCommandManager()->Execute("selection.clear");
961 int count = 0;
962 FromString(count, countString.c_str());
963 return count;
966 void CEditorImpl::LockSelection(bool bLock)
968 // Selection must be not empty to enable selection lock.
969 if (!GetSelection()->IsEmpty())
970 m_bSelectionLocked = bLock;
971 else
972 m_bSelectionLocked = false;
975 bool CEditorImpl::IsSelectionLocked()
977 return m_bSelectionLocked;
980 bool CEditorImpl::IsUpdateSuspended() const
982 return CCryEditApp::GetInstance()->IsUpdateSuspended();
985 bool CEditorImpl::IsGameInputSuspended()
987 return GetGameEngine()->IsGameInputSuspended();
990 void CEditorImpl::ToggleGameInputSuspended()
992 return GetGameEngine()->ToggleGameInputSuspended();
995 void CEditorImpl::PickObject(IPickObjectCallback* callback, CRuntimeClass* targetClass, bool bMultipick)
997 m_pPickTool = new CPickObjectTool(callback, targetClass);
998 ((CPickObjectTool*)m_pPickTool)->SetMultiplePicks(bMultipick);
999 SetEditTool(m_pPickTool);
1002 void CEditorImpl::CancelPick()
1004 SetEditTool(0);
1005 m_pPickTool = 0;
1008 bool CEditorImpl::IsPicking()
1010 if (GetEditTool() == m_pPickTool && m_pPickTool != 0)
1011 return true;
1012 return false;
1015 LevelEditorSharedState* CEditorImpl::GetLevelEditorSharedState()
1017 return m_pLevelEditorSharedState.get();
1020 CViewManager* CEditorImpl::GetViewManager()
1022 return m_pViewManager;
1025 IViewportManager* CEditorImpl::GetViewportManager()
1027 return static_cast<IViewportManager*>(GetViewManager());
1030 CViewport* CEditorImpl::GetActiveView()
1032 return GetViewManager()->GetActiveViewport();
1035 IDisplayViewport* CEditorImpl::GetActiveDisplayViewport()
1037 return GetViewManager()->GetActiveViewport();
1040 void CEditorImpl::SetActiveView(CViewport* viewport)
1042 m_pViewManager->SelectViewport(viewport);
1045 void CEditorImpl::UpdateViews(int flags, AABB* updateRegion)
1047 AABB prevRegion = m_pViewManager->GetUpdateRegion();
1048 if (updateRegion)
1049 m_pViewManager->SetUpdateRegion(*updateRegion);
1050 m_pViewManager->UpdateViews(flags);
1051 if (updateRegion)
1052 m_pViewManager->SetUpdateRegion(prevRegion);
1055 void CEditorImpl::UpdateSequencer(bool bOnlyKeys)
1057 if (bOnlyKeys)
1058 Notify(eNotify_OnUpdateSequencerKeys);
1059 else
1060 Notify(eNotify_OnUpdateSequencer);
1063 void CEditorImpl::ResetViews()
1065 m_pViewManager->ResetViews();
1068 IIconManager* CEditorImpl::GetIconManager()
1070 return m_pIconManager;
1073 IBackgroundTaskManager* CEditorImpl::GetBackgroundTaskManager()
1075 return m_pBackgroundTaskManager.get();
1078 IBackgroundScheduleManager* CEditorImpl::GetBackgroundScheduleManager()
1080 return m_pBackgroundScheduleManager.get();
1083 IBackgroundTaskManagerListener* CEditorImpl::GetIBackgroundTaskManagerListener()
1085 return m_pBGTasks.get();
1088 IFileChangeMonitor* CEditorImpl::GetFileMonitor()
1090 return m_pEditorFileMonitor.get();
1093 float CEditorImpl::GetTerrainElevation(float x, float y)
1095 I3DEngine* engine = m_pSystem->GetI3DEngine();
1096 if (!engine)
1097 return 0;
1098 return engine->GetTerrainElevation(x, y);
1101 Vec3 CEditorImpl::GetTerrainNormal(const Vec3& pos)
1103 I3DEngine* pEngine = m_pSystem->GetI3DEngine();
1104 if (!pEngine)
1105 return Vec3();
1107 return pEngine->GetTerrainSurfaceNormal(pos);
1110 CHeightmap* CEditorImpl::GetHeightmap()
1112 assert(m_pTerrainManager);
1113 return m_pTerrainManager->GetHeightmap();
1116 CVegetationMap* CEditorImpl::GetVegetationMap()
1118 return m_pVegetationMap;
1121 void CEditorImpl::SetSelectedRegion(const AABB& box)
1123 m_selectedRegion = box;
1126 void CEditorImpl::GetSelectedRegion(AABB& box)
1128 box = m_selectedRegion;
1131 CWnd* CEditorImpl::OpenView(const char* sViewClassName)
1133 return CTabPaneManager::GetInstance()->OpenMFCPane(sViewClassName);
1136 CWnd* CEditorImpl::FindView(const char* sViewClassName)
1138 return CTabPaneManager::GetInstance()->FindMFCPane(sViewClassName);
1141 IPane* CEditorImpl::CreateDockable(const char* className)
1143 return CTabPaneManager::GetInstance()->CreatePane(className);
1146 void CEditorImpl::RaiseDockable(IPane* pPane)
1148 CTabPaneManager::GetInstance()->BringToFront(pPane);
1151 QWidget* CEditorImpl::CreatePreviewWidget(const QString& file, QWidget* pParent)
1153 const static QStringList validGeometryExtensions = []()
1155 QStringList result;
1156 result << QStringLiteral(CRY_SKEL_FILE_EXT)
1157 << QStringLiteral(CRY_SKIN_FILE_EXT)
1158 << QStringLiteral(CRY_CHARACTER_DEFINITION_FILE_EXT)
1159 << QStringLiteral(CRY_ANIM_GEOMETRY_FILE_EXT)
1160 << QStringLiteral(CRY_GEOMETRY_FILE_EXT);
1161 return result;
1162 } ();
1164 const QFileInfo info(file);
1165 if (validGeometryExtensions.contains(info.suffix()))
1167 return new QPreviewWidget(file, pParent);
1169 else if (info.suffix() == CRY_MATERIAL_FILE_EXT)
1171 return new QMaterialPreview(file, pParent);
1173 else if (info.suffix() == "dds")
1175 return new QTexturePreview(file, pParent);
1178 return nullptr;
1181 void CEditorImpl::PostOnMainThread(std::function<void()> task)
1183 if (task)
1185 CMainThreadWorker::GetInstance().AddTask(std::move(task));
1189 IDataBaseManager* CEditorImpl::GetDBItemManager(EDataBaseItemType itemType)
1191 switch (itemType)
1193 case EDB_TYPE_MATERIAL:
1194 return m_pMaterialManager;
1195 case EDB_TYPE_ENTITY_ARCHETYPE:
1196 return m_pEntityManager;
1197 case EDB_TYPE_PREFAB:
1198 return m_pPrefabManager;
1199 case EDB_TYPE_GAMETOKEN:
1200 return m_pGameTokenManager;
1201 case EDB_TYPE_PARTICLE:
1202 return m_particleManager;
1204 return 0;
1207 CBaseLibraryDialog* CEditorImpl::OpenDataBaseLibrary(EDataBaseItemType type, IDataBaseItem* pItem)
1209 if (pItem)
1210 type = pItem->GetType();
1212 CWnd* pWnd = NULL;
1213 if (type == EDB_TYPE_MATERIAL)
1215 pWnd = OpenView("Material Editor Legacy");
1217 else
1219 pWnd = OpenView("DataBase View");
1222 IDataBaseManager* pManager = GetDBItemManager(type);
1223 if (pManager)
1224 pManager->SetSelectedItem(pItem);
1226 if (pWnd && pWnd->IsKindOf(RUNTIME_CLASS(CBaseLibraryDialog)))
1228 return (CBaseLibraryDialog*)pWnd;
1230 if (pWnd && pWnd->IsKindOf(RUNTIME_CLASS(CDataBaseDialog)))
1232 CDataBaseDialog* dlgDB = (CDataBaseDialog*)pWnd;
1233 CDataBaseDialogPage* pPage = dlgDB->SelectDialog(type, pItem);
1234 if (pPage && pPage->IsKindOf(RUNTIME_CLASS(CBaseLibraryDialog)))
1236 return (CBaseLibraryDialog*)pPage;
1239 return 0;
1242 bool CEditorImpl::SelectColor(COLORREF& color, CWnd* parent)
1244 COLORREF col = color;
1245 CCustomColorDialog dlg(col, CC_FULLOPEN, parent);
1246 if (dlg.DoModal() == IDOK)
1248 color = dlg.GetColor();
1249 return true;
1251 return false;
1254 void CEditorImpl::SetInGameMode(bool inGame)
1256 static bool bWasInSimulationMode(false);
1258 if (inGame)
1260 bWasInSimulationMode = GetIEditorImpl()->GetGameEngine()->GetSimulationMode();
1261 GetIEditorImpl()->GetGameEngine()->SetSimulationMode(false);
1262 GetIEditorImpl()->GetCommandManager()->Execute("game.enter");
1264 else
1266 GetIEditorImpl()->GetCommandManager()->Execute("game.exit");
1267 GetIEditorImpl()->GetGameEngine()->SetSimulationMode(bWasInSimulationMode);
1271 bool CEditorImpl::IsInGameMode()
1273 if (m_pGameEngine)
1274 return m_pGameEngine->IsInGameMode();
1275 return false;
1278 bool CEditorImpl::IsInTestMode()
1280 return CCryEditApp::GetInstance()->IsInTestMode();
1283 bool CEditorImpl::IsInConsolewMode()
1285 return CCryEditApp::GetInstance()->IsInConsoleMode();
1288 bool CEditorImpl::IsInLevelLoadTestMode()
1290 return CCryEditApp::GetInstance()->IsInLevelLoadTestMode();
1293 bool CEditorImpl::IsInPreviewMode()
1295 return CCryEditApp::GetInstance()->IsInPreviewMode();
1298 void CEditorImpl::EnableAcceleratos(bool bEnable)
1300 m_pCommandManager->SetEditorUIActionsEnabled(bEnable);
1303 void CEditorImpl::DetectVersion()
1305 char exe[_MAX_PATH];
1306 DWORD dwHandle;
1307 UINT len;
1309 char ver[1024 * 8];
1311 GetModuleFileName(NULL, exe, _MAX_PATH);
1313 int verSize = GetFileVersionInfoSize(exe, &dwHandle);
1314 if (verSize > 0)
1316 GetFileVersionInfo(exe, dwHandle, 1024 * 8, ver);
1317 VS_FIXEDFILEINFO* vinfo;
1318 VerQueryValue(ver, "\\", (void**)&vinfo, &len);
1320 m_fileVersion.v[0] = vinfo->dwFileVersionLS & 0xFFFF;
1321 m_fileVersion.v[1] = vinfo->dwFileVersionLS >> 16;
1322 m_fileVersion.v[2] = vinfo->dwFileVersionMS & 0xFFFF;
1323 m_fileVersion.v[3] = vinfo->dwFileVersionMS >> 16;
1325 m_productVersion.v[0] = vinfo->dwProductVersionLS & 0xFFFF;
1326 m_productVersion.v[1] = vinfo->dwProductVersionLS >> 16;
1327 m_productVersion.v[2] = vinfo->dwProductVersionMS & 0xFFFF;
1328 m_productVersion.v[3] = vinfo->dwProductVersionMS >> 16;
1332 XmlNodeRef CEditorImpl::FindTemplate(const string& templateName)
1334 return m_templateRegistry.FindTemplate(templateName);
1337 void CEditorImpl::AddTemplate(const string& templateName, XmlNodeRef& tmpl)
1339 m_templateRegistry.AddTemplate(templateName, tmpl);
1342 void CEditorImpl::OpenAndFocusDataBase(EDataBaseItemType type, IDataBaseItem* pItem)
1344 OpenDataBaseLibrary(type, pItem);
1347 void CEditorImpl::SetConsoleVar(const char* var, float value)
1349 ICVar* ivar = GetSystem()->GetIConsole()->GetCVar(var);
1350 if (ivar)
1351 ivar->Set(value);
1354 void CEditorImpl::SetConsoleStringVar(const char* var, const char* value)
1356 ICVar* ivar = GetSystem()->GetIConsole()->GetCVar(var);
1357 if (ivar)
1358 ivar->Set(value);
1361 float CEditorImpl::GetConsoleVar(const char* var)
1363 ICVar* ivar = GetSystem()->GetIConsole()->GetCVar(var);
1364 if (ivar)
1366 return ivar->GetFVal();
1368 return 0;
1371 IAIManager* CEditorImpl::GetAIManager()
1373 return m_pAIManager;
1376 CCustomActionsEditorManager* CEditorImpl::GetCustomActionManager()
1378 return m_pCustomActionsManager;
1381 void CEditorImpl::OnObjectHideMaskChanged()
1383 int hideMask = gViewportDebugPreferences.GetObjectHideMask();
1384 int maskChanges = m_objectHideMask ^ hideMask;
1386 if (maskChanges & (OBJTYPE_ENTITY | OBJTYPE_PREFAB | OBJTYPE_GROUP | OBJTYPE_BRUSH | OBJTYPE_GEOMCACHE))
1387 gEnv->p3DEngine->OnObjectModified(NULL, ERF_CASTSHADOWMAPS);
1389 GetIEditorImpl()->Notify(eNotify_OnDisplayRenderUpdate);
1391 m_objectHideMask = hideMask;
1394 void CEditorImpl::Notify(EEditorNotifyEvent event)
1396 if (m_bExiting)
1397 return;
1399 std::list<IEditorNotifyListener*>::iterator it = m_listeners.begin();
1400 while (it != m_listeners.end())
1402 (*it++)->OnEditorNotifyEvent(event);
1406 void CEditorImpl::RegisterNotifyListener(IEditorNotifyListener* listener)
1408 listener->m_bIsRegistered = true;
1409 stl::push_back_unique(m_listeners, listener);
1412 void CEditorImpl::UnregisterNotifyListener(IEditorNotifyListener* listener)
1414 m_listeners.remove(listener);
1415 listener->m_bIsRegistered = false;
1418 ISourceControl* CEditorImpl::GetSourceControl()
1420 if (!gEditorGeneralPreferences.enableSourceControl())
1421 return nullptr;
1423 if (m_pSourceControl)
1424 return m_pSourceControl;
1426 std::vector<IClassDesc*> classes;
1427 GetIEditorImpl()->GetClassFactory()->GetClassesBySystemID(ESYSTEM_CLASS_SCM_PROVIDER, classes);
1428 for (int i = 0; i < classes.size(); i++)
1430 IClassDesc* pClass = classes[i];
1431 ISourceControl* pSCM = (ISourceControl*)pClass;
1432 if (pSCM)
1434 m_pSourceControl = pSCM;
1435 return m_pSourceControl;
1439 return 0;
1442 IProjectManager* CEditorImpl::GetProjectManager()
1444 return m_pSystem->GetIProjectManager();
1447 bool CEditorImpl::IsSourceControlAvailable()
1449 if (gEditorGeneralPreferences.enableSourceControl() && GetSourceControl())
1450 return true;
1452 return false;
1455 void CEditorImpl::SetMatEditMode(bool bIsMatEditMode)
1457 m_bMatEditMode = bIsMatEditMode;
1460 void CEditorImpl::ShowStatusText(bool bEnable)
1462 m_bShowStatusText = bEnable;
1465 FileSystem::CEnumerator* CEditorImpl::GetFileSystemEnumerator()
1467 return m_pFileSystemEnumerator.get();
1470 void CEditorImpl::GetMemoryUsage(ICrySizer* pSizer)
1472 SIZER_COMPONENT_NAME(pSizer, "Editor");
1474 if (GetDocument())
1476 SIZER_COMPONENT_NAME(pSizer, "Document");
1478 GetDocument()->GetMemoryUsage(pSizer);
1481 if (m_pVegetationMap)
1482 m_pVegetationMap->GetMemoryUsage(pSizer);
1485 void CEditorImpl::ReduceMemory()
1487 GetIEditorImpl()->GetIUndoManager()->ClearRedoStack();
1488 GetIEditorImpl()->GetIUndoManager()->ClearUndoStack();
1489 GetIEditorImpl()->GetObjectManager()->SendEvent(EVENT_FREE_GAME_DATA);
1491 HANDLE hHeap = GetProcessHeap();
1493 if (hHeap)
1495 uint64 maxsize = (uint64)HeapCompact(hHeap, 0);
1496 CryLogAlways("Max Free Memory Block = %I64d Kb", maxsize / 1024);
1500 IExportManager* CEditorImpl::GetExportManager()
1502 if (!m_pExportManager)
1503 m_pExportManager = new CExportManager();
1505 return m_pExportManager;
1508 void CEditorImpl::AddUIEnums()
1510 // Spec settings for shadow casting lights
1511 string SpecString[4];
1512 std::vector<string> types;
1513 types.push_back("Never=0");
1514 SpecString[0].Format("VeryHigh Spec=%d", CONFIG_VERYHIGH_SPEC);
1515 types.push_back(SpecString[0].c_str());
1516 SpecString[1].Format("High Spec=%d", CONFIG_HIGH_SPEC);
1517 types.push_back(SpecString[1].c_str());
1518 SpecString[2].Format("Medium Spec=%d", CONFIG_MEDIUM_SPEC);
1519 types.push_back(SpecString[2].c_str());
1520 SpecString[3].Format("Low Spec=%d", CONFIG_LOW_SPEC);
1521 types.push_back(SpecString[3].c_str());
1522 m_pUIEnumsDatabase->SetEnumStrings("CastShadows", types);
1524 // Power-of-two percentages
1525 string percentStringPOT[5];
1526 types.clear();
1527 percentStringPOT[0].Format("Default=%d", 0);
1528 types.push_back(percentStringPOT[0].c_str());
1529 percentStringPOT[1].Format("12.5=%d", 1);
1530 types.push_back(percentStringPOT[1].c_str());
1531 percentStringPOT[2].Format("25=%d", 2);
1532 types.push_back(percentStringPOT[2].c_str());
1533 percentStringPOT[3].Format("50=%d", 3);
1534 types.push_back(percentStringPOT[3].c_str());
1535 percentStringPOT[4].Format("100=%d", 4);
1536 types.push_back(percentStringPOT[4].c_str());
1537 m_pUIEnumsDatabase->SetEnumStrings("ShadowMinResPercent", types);
1540 void CEditorImpl::SetEditorConfigSpec(ESystemConfigSpec spec)
1542 editorConfigSpec = spec;
1543 if (m_pSystem->GetConfigSpec(true) != spec)
1545 m_pSystem->SetConfigSpec(spec, true);
1546 editorConfigSpec = m_pSystem->GetConfigSpec(true);
1547 GetObjectManager()->SendEvent(EVENT_CONFIG_SPEC_CHANGE);
1548 if (m_pVegetationMap)
1549 m_pVegetationMap->UpdateConfigSpec();
1550 Notify(eNotify_EditorConfigSpecChanged);
1552 SET_PERSONALIZATION_PROPERTY(CEditorImpl, "configSpec", editorConfigSpec);
1555 ESystemConfigSpec CEditorImpl::GetEditorConfigSpec() const
1557 return editorConfigSpec;
1560 void CEditorImpl::InitFinished()
1562 LOADING_TIME_PROFILE_SECTION;
1564 if (!m_bInitialized)
1566 m_bInitialized = true;
1567 Notify(eNotify_OnInit);
1569 REGISTER_CVAR(doc_use_subfolder_for_crash_backup, 0, VF_NULL, "When saving a level after the editor has crashed, save to a sub-folder instead of overwriting the level");
1570 REGISTER_COMMAND("py", CmdPy, 0, "Execute a Python code snippet.");
1572 // Let system wide listeners know about this as well.
1573 GetISystem()->GetISystemEventDispatcher()->OnSystemEvent(ESYSTEM_EVENT_EDITOR_ON_INIT, 0, 0);
1575 if (m_pPersonalizationManager->HasProperty("CEditorImpl", "configSpec"))
1576 editorConfigSpec = (ESystemConfigSpec)GET_PERSONALIZATION_PROPERTY(CEditorImpl, "configSpec").toInt();
1577 SetEditorConfigSpec(editorConfigSpec);
1579 m_pNotificationCenter->Init();
1580 m_pPreferences->Init();
1581 SEditorSettings::Load();
1582 gViewportDebugPreferences.objectHideMaskChanged.Connect(this, &CEditorImpl::OnObjectHideMaskChanged);
1583 m_pObjectManager->LoadClassTemplates("%EDITOR%");
1587 void CEditorImpl::ReloadTemplates()
1589 m_templateRegistry.LoadTemplates("%EDITOR%");
1592 void CEditorImpl::CmdPy(IConsoleCmdArgs* pArgs)
1594 // Execute the given script command.
1595 string scriptCmd = pArgs->GetCommandLine();
1597 scriptCmd = scriptCmd.Right(scriptCmd.GetLength() - 2); // The part of the text after the 'py'
1598 scriptCmd = scriptCmd.Trim();
1599 PyRun_SimpleString(scriptCmd.GetString());
1600 PyErr_Print();
1603 void CEditorImpl::OnObjectContextMenuOpened(CPopupMenuItem* pMenu, const CBaseObject* pObject)
1605 for (auto iter = m_objectContextMenuExtensions.begin(); iter != m_objectContextMenuExtensions.end(); ++iter)
1607 (*iter)(pMenu, pObject);
1611 void CEditorImpl::RegisterObjectContextMenuExtension(TContextMenuExtensionFunc func)
1613 m_objectContextMenuExtensions.push_back(func);
1616 void CEditorImpl::SetCurrentMissionTime(float time)
1618 if (CMission* pMission = GetIEditorImpl()->GetDocument()->GetCurrentMission())
1619 pMission->SetTime(time);
1622 float CEditorImpl::GetCurrentMissionTime()
1624 if (CMission* pMission = GetIEditorImpl()->GetDocument()->GetCurrentMission())
1625 return pMission->GetTime();
1626 return 12.0f; // return default value noon as 12 hours
1629 void CEditorImpl::OnSystemEvent(ESystemEvent event, UINT_PTR wparam, UINT_PTR lparam)
1631 if (event == ESYSTEM_EVENT_URI)
1633 CCryURI uri((const char*)wparam);
1634 string uriSchema = uri.GetSchema();
1636 TURIListeners::iterator it = m_uriListeners.find(uriSchema);
1637 if (it != m_uriListeners.end())
1639 for (CListenerSet<IUriEventListener*>::Notifier notifier(it->second); notifier.IsValid(); notifier.Next())
1641 notifier->OnUriReceived(uri.GetUri());
1647 void CEditorImpl::RegisterURIListener(IUriEventListener* pListener, const char* szSchema)
1649 TURIListeners::iterator it = m_uriListeners.find(szSchema);
1650 if (it != m_uriListeners.end())
1652 it->second.Add(pListener);
1654 else
1656 string schamaName = szSchema;
1657 CListenerSet<IUriEventListener*> uriListener(4);
1658 uriListener.Add(pListener);
1659 m_uriListeners.insert(std::make_pair(schamaName, uriListener));
1663 void CEditorImpl::UnregisterURIListener(IUriEventListener* pListener, const char* szSchema)
1665 TURIListeners::iterator it = m_uriListeners.find(szSchema);
1666 if (it != m_uriListeners.end())
1668 if (it->second.Contains(pListener))
1670 it->second.Remove(pListener);
1674 void CEditorImpl::RequestScriptReload(const EReloadScriptsType& kind)
1676 m_reloadScriptsQueue.insert(kind);
1678 void CEditorImpl::AddNativeHandler(uintptr_t id, std::function<bool(void*, long*)> callback)
1680 CEditorMainFrame::GetInstance()->m_loopHandler.AddNativeHandler(id, callback);
1683 void CEditorImpl::RemoveNativeHandler(uintptr_t id)
1685 CEditorMainFrame::GetInstance()->m_loopHandler.RemoveNativeHandler(id);
1687 //////////////////////////////////////////////////////////////////////////
1689 bool CEditorImpl::IsDocumentReady() const
1691 return GetDocument()->IsDocumentReady();
1694 void CEditorImpl::RemoveMemberCGroup(CBaseObject* pGroup, CBaseObject* pObject)
1696 CRY_ASSERT(IsCGroup(pGroup));
1698 //Take a faster code path when closing
1699 bool bIsClosing = m_bExiting || GetIEditor()->GetDocument()->IsClosing();
1701 ((CGroup*)pGroup)->RemoveMember(pObject, !bIsClosing, !bIsClosing);
1704 bool CEditorImpl::IsCGroup(CBaseObject* pObject)
1706 return pObject->IsKindOf(RUNTIME_CLASS(CGroup));
1709 bool CEditorImpl::IsCPrefabObject(CBaseObject* pObject)
1711 return pObject->IsKindOf(RUNTIME_CLASS(CPrefabObject));
1714 void CEditorImpl::RegisterEntity(IRenderNode* pRenderNode)
1716 Get3DEngine()->RegisterEntity(pRenderNode);
1719 void CEditorImpl::UnRegisterEntityAsJob(IRenderNode* pRenderNode)
1721 GetIEditorImpl()->Get3DEngine()->UnRegisterEntityAsJob(pRenderNode);
1724 void CEditorImpl::SyncPrefabCPrefabObject(CBaseObject* pObject, const SObjectChangedContext& context)
1726 ((CPrefabObject*)pObject)->SyncPrefab(context);
1729 bool CEditorImpl::IsModifyInProgressCPrefabObject(CBaseObject* pObject)
1731 return ((CPrefabObject*)pObject)->IsModifyInProgress();
1734 bool CEditorImpl::IsGroupOpen(CBaseObject* pObject)
1736 CGroup* pGroup = (CGroup*)pObject;
1737 return pGroup->IsOpen();
1740 void CEditorImpl::OpenGroup(CBaseObject* pObject)
1742 if (!pObject || !IsCGroup(pObject))
1743 return;
1745 CGroup* pGroup = static_cast<CGroup*>(pObject);
1746 if (!pGroup->IsOpen())
1747 pGroup->Open();
1750 void CEditorImpl::ResumeUpdateCGroup(CBaseObject* pObject)
1752 ((CGroup*)pObject)->ResumeUpdate();
1755 bool CEditorImpl::SuspendUpdateCGroup(CBaseObject* pObject)
1757 return ((CGroup*)pObject)->SuspendUpdate();
1760 IEditorMaterial* CEditorImpl::LoadMaterial(const string& name)
1762 if (GetMaterialManager())
1763 return GetMaterialManager()->LoadMaterial(name);
1764 return nullptr;
1767 void CEditorImpl::OnRequestMaterial(IMaterial* pMatInfo)
1769 if (GetMaterialManager())
1770 GetMaterialManager()->OnRequestMaterial(pMatInfo);
1773 void CEditorImpl::OnPrefabMake()
1775 m_pPrefabManager->MakeFromSelection();
1778 bool CEditorImpl::PickObject(const Vec3& vWorldRaySrc, const Vec3& vWorldRayDir, SRayHitInfo& outHitInfo, CBaseObject* pObject)
1780 CSurfaceInfoPicker picker;
1781 return picker.PickObject(vWorldRaySrc, vWorldRayDir, outHitInfo, pObject);
1784 void CEditorImpl::AddWaitProgress(CWaitProgress* pProgress)
1786 if (CEditorMainFrame::GetInstance())
1787 CEditorMainFrame::GetInstance()->AddWaitProgress(pProgress);
1790 void CEditorImpl::RemoveWaitProgress(CWaitProgress* pProgress)
1792 if (CEditorMainFrame::GetInstance())
1793 CEditorMainFrame::GetInstance()->AddWaitProgress(pProgress);
1796 void CEditorImpl::RegisterDeprecatedPropertyEditor(int propertyType, std::function<bool(const string&, string&)>& handler)
1798 m_deprecatedPropertyEditors[propertyType] = handler;
1801 bool CEditorImpl::EditDeprecatedProperty(int propertyType, const string& oldValue, string& newValueOut)
1803 auto handler = m_deprecatedPropertyEditors[propertyType];
1804 if (handler)
1806 return handler(oldValue, newValueOut);
1808 return false;
1811 bool CEditorImpl::CanEditDeprecatedProperty(int propertyType)
1813 auto handler = m_deprecatedPropertyEditors[propertyType];
1814 if (handler)
1815 return true;
1816 else
1817 return false;
1820 bool CEditorImpl::ScanDirectory(const string& path, const string& fileSpec, std::vector<string>& filesOut, bool recursive /*= true*/)
1822 CFileUtil::FileArray result;
1823 bool res = CFileUtil::ScanDirectory(CString(path), fileSpec, result, recursive);
1824 if (res && !result.empty())
1826 for (auto& file : result)
1828 filesOut.push_back(file.filename.GetBuffer());
1831 return res;
1834 void CEditorImpl::SetPlayerViewMatrix(const Matrix34& tm, bool bEyePos /*= true*/)
1836 if (GetGameEngine())
1837 GetGameEngine()->SetPlayerViewMatrix(tm, bEyePos);