CryEdit.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #ifndef CRYINCLUDE_EDITOR_CRYEDIT_H
  9. #define CRYINCLUDE_EDITOR_CRYEDIT_H
  10. #pragma once
  11. #if !defined(Q_MOC_RUN)
  12. #include <AzCore/Outcome/Outcome.h>
  13. #include <AzFramework/Asset/AssetSystemBus.h>
  14. #include "CryEditDoc.h"
  15. #include "ViewPane.h"
  16. #include <QSettings>
  17. #endif
  18. class CCryDocManager;
  19. class CCryEditDoc;
  20. class CEditCommandLineInfo;
  21. class CMainFrame;
  22. class CConsoleDialog;
  23. class QAction;
  24. class MainWindow;
  25. class QSharedMemory;
  26. class SANDBOX_API RecentFileList
  27. {
  28. public:
  29. RecentFileList();
  30. void Remove(int index);
  31. void Add(const QString& filename);
  32. int GetSize();
  33. void GetDisplayName(QString& name, int index, const QString& curDir);
  34. QString& operator[](int index);
  35. void ReadList();
  36. void WriteList();
  37. static const int Max = 12;
  38. QStringList m_arrNames;
  39. QSettings m_settings;
  40. };
  41. /**
  42. * Bus for controlling the application's idle processing (may include things like entity updates, ticks, viewport rendering, etc.).
  43. * This is sometimes necessary in special event-processing loops to prevent long (or infinite) processing time because Idle Processing
  44. * can perpetually generate more events.
  45. */
  46. class EditorIdleProcessing : public AZ::EBusTraits
  47. {
  48. public:
  49. using Bus = AZ::EBus<EditorIdleProcessing>;
  50. static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
  51. static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
  52. /// Disable the Editor's idle processing. EnableIdleProcessing() must be called exactly once when special processing is complete.
  53. virtual void DisableIdleProcessing() {}
  54. /// Re-enables Idle Processing. Must be called exactly one time for every call to DisableIdleProcessing().
  55. virtual void EnableIdleProcessing() {}
  56. };
  57. using EditorIdleProcessingBus = AZ::EBus<EditorIdleProcessing>;
  58. enum class COpenSameLevelOptions
  59. {
  60. ReopenLevelIfSame,
  61. NotReopenIfSame
  62. };
  63. class SANDBOX_API CCryEditApp
  64. : public QObject
  65. , protected AzFramework::AssetSystemInfoBus::Handler
  66. , protected EditorIdleProcessingBus::Handler
  67. , protected AzFramework::AssetSystemStatusBus::Handler
  68. {
  69. friend MainWindow;
  70. Q_OBJECT
  71. public:
  72. enum ECreateLevelResult
  73. {
  74. ECLR_OK = 0,
  75. ECLR_ALREADY_EXISTS,
  76. ECLR_DIR_CREATION_FAILED,
  77. ECLR_MAX_PATH_EXCEEDED
  78. };
  79. CCryEditApp();
  80. ~CCryEditApp();
  81. static CCryEditApp* instance();
  82. bool CreateLevel(bool& wasCreateLevelOperationCancelled);
  83. void LoadFile(QString fileName);
  84. void ForceNextIdleProcessing() { m_bForceProcessIdle = true; }
  85. void KeepEditorActive(bool bActive) { m_bKeepEditorActive = bActive; };
  86. bool IsInTestMode() const { return m_bTestMode; };
  87. bool IsInPreviewMode() const { return m_bPreviewMode; };
  88. bool IsInConsoleMode() const { return m_bConsoleMode; };
  89. bool IsInAutotestMode() const { return m_bAutotestMode; };
  90. bool IsInLevelLoadTestMode() const { return m_bLevelLoadTestMode; }
  91. bool IsInRegularEditorMode();
  92. bool IsExiting() const { return m_bExiting; }
  93. void EnableAccelerator(bool bEnable);
  94. void SaveAutoBackup();
  95. void SaveAutoRemind();
  96. //! \param sTitleStr overwrites the default title of the Editor
  97. void SetEditorWindowTitle(QString sTitleStr = QString(), QString sPreTitleStr = QString(), QString sPostTitleStr = QString());
  98. RecentFileList* GetRecentFileList();
  99. virtual void AddToRecentFileList(const QString& lpszPathName);
  100. ECreateLevelResult CreateLevel(const QString& templateName, const QString& levelName, QString& fullyQualifiedLevelName);
  101. bool FirstInstance(bool bForceNewInstance = false);
  102. void InitFromCommandLine(CEditCommandLineInfo& cmdInfo);
  103. bool CheckIfAlreadyRunning();
  104. //! @return successful outcome if initialization succeeded. or failed outcome with error message.
  105. AZ::Outcome<void, AZStd::string> InitGameSystem(HWND hwndForInputSystem);
  106. void CreateSplashScreen();
  107. void InitPlugins();
  108. bool InitGame();
  109. bool InitConsole();
  110. int IdleProcessing(bool bBackground);
  111. bool IsWindowInForeground();
  112. void RunInitPythonScript(CEditCommandLineInfo& cmdInfo);
  113. void DisableIdleProcessing() override;
  114. void EnableIdleProcessing() override;
  115. // Print to stdout even if there out has been redirected
  116. void PrintAlways(const AZStd::string& output);
  117. //! Launches the Lua Editor/Debugger
  118. //! \param files A space separated list of aliased paths
  119. void OpenLUAEditor(const char* files);
  120. QString GetRootEnginePath() const;
  121. void RedirectStdoutToNull();
  122. // Overrides
  123. public:
  124. virtual bool InitInstance();
  125. virtual int ExitInstance(int exitCode = 0);
  126. virtual bool OnIdle(LONG lCount);
  127. virtual CCryEditDoc* OpenDocumentFile(const char* filename,
  128. bool addToMostRecentFileList=true,
  129. COpenSameLevelOptions openSameLevelOptions = COpenSameLevelOptions::NotReopenIfSame);
  130. CCryDocManager* GetDocManager() { return m_pDocManager; }
  131. // Implementation
  132. void OnCreateLevel();
  133. void OnOpenLevel();
  134. void OnAppAbout();
  135. void OnAppShowWelcomeScreen();
  136. void OnUpdateShowWelcomeScreen(QAction* action);
  137. void OnDocumentationTutorials();
  138. void OnDocumentationGlossary();
  139. void OnDocumentationO3DE();
  140. void OnDocumentationReleaseNotes();
  141. void OnDocumentationGameDevBlog();
  142. void OnDocumentationForums();
  143. void OnEditHold();
  144. void OnEditFetch();
  145. void OnViewSwitchToGame();
  146. void OnViewSwitchToGameFullScreen();
  147. void OnMoveObject();
  148. void OnRenameObj();
  149. void OnUndo();
  150. void OnEditLevelData();
  151. void OnFileEditLogFile();
  152. void OnFileEditEditorini();
  153. void OnPreferences();
  154. void OnOpenProjectManagerSettings();
  155. void OnOpenProjectManagerNew();
  156. void OnOpenProjectManager();
  157. void OnRedo();
  158. void OnUpdateRedo(QAction* action);
  159. void OnUpdateUndo(QAction* action);
  160. void OnSwitchPhysics();
  161. void OnSwitchPhysicsUpdate(QAction* action);
  162. void OnSyncPlayer();
  163. void OnSyncPlayerUpdate(QAction* action);
  164. void OnResourcesReduceworkingset();
  165. void OnDummyCommand() {};
  166. void OnFileSave();
  167. void OnUpdateDocumentReady(QAction* action);
  168. void OnUpdateFileOpen(QAction* action);
  169. void OnUpdateNonGameMode(QAction* action);
  170. void OnUpdateNewLevel(QAction* action);
  171. void OnUpdatePlayGame(QAction* action);
  172. void OnToolsLogMemoryUsage();
  173. void OnToolsPreferences();
  174. protected:
  175. // ------- AzFramework::AssetSystemInfoBus::Handler ------
  176. void OnError(AzFramework::AssetSystem::AssetSystemErrors error) override;
  177. // -------------------------------------------
  178. // ------- AzFramework::AssetSystemStatusBus::Handler ------
  179. void AssetSystemWaiting() override;
  180. // -------------------------------------------
  181. private:
  182. friend class EditorActionsHandler;
  183. void InitLevel(const CEditCommandLineInfo& cmdInfo);
  184. bool ConnectToAssetProcessor() const;
  185. void CompileCriticalAssets() const;
  186. CMainFrame* GetMainFrame() const;
  187. void WriteConfig();
  188. static void ShowSplashScreen(CCryEditApp* app);
  189. static void CloseSplashScreen();
  190. static void OutputStartupMessage(QString str);
  191. bool ShowEnableDisableGemDialog(const QString& title, const QString& message);
  192. QString ShowWelcomeDialog();
  193. bool FixDanglingSharedMemory(const QString& sharedMemName) const;
  194. //! Displays level load errors after a certain number of idle frames have been processed.
  195. //! Due to the asyncrhonous nature of loading assets any errors that are reported by components
  196. //! can happen after the level is loaded. This method will wait for a few idle updates and then
  197. //! display the load errors to ensure all errors are displayed properly.
  198. void DisplayLevelLoadErrors();
  199. class CEditorImpl* m_pEditor = nullptr;
  200. static CCryEditApp* s_currentInstance;
  201. //! True if editor is in test mode.
  202. //! Test mode is a special mode enabled when Editor ran with /test command line.
  203. //! In this mode editor starts up, but exit immediately after all initialization.
  204. bool m_bTestMode = false;
  205. //! If application exiting.
  206. bool m_bExiting = false;
  207. //! True if editor is in preview mode.
  208. //! In this mode only very limited functionality is available and only for fast preview of models.
  209. bool m_bPreviewMode = false;
  210. // Only console window is created.
  211. bool m_bConsoleMode = false;
  212. // Skip showing the WelcomeScreenDialog
  213. bool m_bSkipWelcomeScreenDialog = false;
  214. // Level load test mode
  215. bool m_bLevelLoadTestMode = false;
  216. //! Current file in preview mode.
  217. char m_sPreviewFile[_MAX_PATH];
  218. //! True if "/runpythontest" was passed as a flag.
  219. bool m_bRunPythonTestScript = false;
  220. //! True if "/runpython" was passed as a flag.
  221. bool m_bRunPythonScript = false;
  222. //! File to run on startup
  223. QString m_execFile;
  224. //! Command to run on startup
  225. QString m_execLineCmd;
  226. //! Autotest mode: Special mode meant for automated testing, things like blocking dialogs or error report windows won't appear
  227. bool m_bAutotestMode = false;
  228. CConsoleDialog* m_pConsoleDialog = nullptr;
  229. float m_fastRotateAngle = 45.0f;
  230. float m_moveSpeedStep = 0.1f;
  231. ULONG_PTR m_gdiplusToken;
  232. QSharedMemory* m_mutexApplication = nullptr;
  233. //! was the editor active in the previous frame ... needed to detect if the game lost focus and
  234. //! dispatch proper SystemEvent (needed to release input keys)
  235. bool m_bPrevActive = false;
  236. // If this flag is set, the next OnIdle() will update, even if the app is in the background, and then
  237. // this flag will be reset.
  238. bool m_bForceProcessIdle = false;
  239. // This is set while IdleProcessing is running to prevent re-entrancy
  240. bool m_idleProcessingRunning = false;
  241. // Keep the editor alive, even if no focus is set
  242. bool m_bKeepEditorActive = false;
  243. // Currently creating a new level
  244. bool m_creatingNewLevel = false;
  245. bool m_openingLevel = false;
  246. bool m_savingLevel = false;
  247. // Flag indicating if the errors for the currently loaded level have been displayed
  248. bool m_levelErrorsHaveBeenDisplayed = false;
  249. // Number of idle frames that have passed before displaying level errors
  250. int m_numBeforeDisplayErrorFrames = 0;
  251. QString m_lastOpenLevelPath;
  252. QString m_rootEnginePath;
  253. int m_disableIdleProcessingCounter = 0; //!< Counts requests to disable idle processing. When non-zero, idle processing will be disabled.
  254. CCryDocManager* m_pDocManager = nullptr;
  255. // Disable warning for dll export since this member won't be used outside this class
  256. AZ::IO::FileDescriptorRedirector m_stdoutRedirection = AZ::IO::FileDescriptorRedirector(1); // < 1 for STDOUT
  257. private:
  258. // Optional Uri to start an external lua debugger. If not specified,
  259. // then the Editor will open LuaIDE.exe.
  260. // For example, if using The Visual Studio Debugger Extension provided by lumbermixalot
  261. // The value will be: "vscode://lumbermixalot.o3de-lua-debug/debug?"
  262. // The following parameters will be added to the URI at runtime:
  263. // "projectPath". Absolute path of the game projec root.
  264. // "enginePath". Absolute path of the engine root. if not specified, it will be assume to be one directory above the game project root.
  265. // "files[]". A list of files,
  266. // Full example using the Uri shown below:
  267. // "vscode://lumbermixalot.o3de-lua-debug/debug?projectPath=D:\mydir\myproject&enginePath=C:\GIT\o3de&files[]=D:\mydir\myproject\scripts\something.lua&files[]=D:\mydir\myproject\scripts\utils\something2.lua"
  268. // or
  269. // "vscode://lumbermixalot.o3de-lua-debug/debug?projectPath=D:\GIT\o3de\AutomatedTesting&files[]=D:\GIT\o3de\AutomatedTesting\Assets\Scripts\something.lua"
  270. static constexpr AZStd::string_view LuaDebuggerUriRegistryKey = "/O3DE/Lua/Debugger/Uri";
  271. struct PythonOutputHandler;
  272. AZStd::shared_ptr<PythonOutputHandler> m_pythonOutputHandler;
  273. friend struct PythonTestOutputHandler;
  274. void OpenProjectManager(const AZStd::string& screen);
  275. void OnUpdateWireframe(QAction* action);
  276. void OnViewConfigureLayout();
  277. void OnCustomizeKeyboard();
  278. void OnToolsScriptHelp();
  279. void OnViewCycle2dviewport();
  280. void OnDisplayGotoPosition();
  281. void OnFileSavelevelresources();
  282. void OnClearRegistryData();
  283. void OnSwitchToSequenceCamera();
  284. void OnUpdateSwitchToSequenceCamera(QAction* action);
  285. void OnSwitchToSelectedcamera();
  286. void OnUpdateSwitchToSelectedCamera(QAction* action);
  287. void OnSwitchcameraNext();
  288. void OnOpenProceduralMaterialEditor();
  289. void OnOpenAssetBrowserView();
  290. void OnOpenTrackView();
  291. void OnOpenAudioControlsEditor();
  292. void OnOpenUICanvasEditor();
  293. // @param files: A list of file paths, separated by '|';
  294. void OpenExternalLuaDebugger(AZStd::string_view luaDebuggerUri, AZStd::string_view enginePath, AZStd::string_view projectPath, const char * files);
  295. };
  296. //////////////////////////////////////////////////////////////////////////
  297. class CCrySingleDocTemplate
  298. : public QObject
  299. {
  300. Q_OBJECT
  301. private:
  302. explicit CCrySingleDocTemplate(const QMetaObject* pDocClass)
  303. : QObject()
  304. , m_documentClass(pDocClass)
  305. {
  306. }
  307. public:
  308. enum Confidence
  309. {
  310. noAttempt,
  311. maybeAttemptForeign,
  312. maybeAttemptNative,
  313. yesAttemptForeign,
  314. yesAttemptNative,
  315. yesAlreadyOpen
  316. };
  317. template<typename DOCUMENT>
  318. static CCrySingleDocTemplate* create()
  319. {
  320. return new CCrySingleDocTemplate(&DOCUMENT::staticMetaObject);
  321. }
  322. ~CCrySingleDocTemplate() {};
  323. // avoid creating another CMainFrame
  324. // close other type docs before opening any things
  325. virtual CCryEditDoc* OpenDocumentFile(const char* lpszPathName, bool addToMostRecentFileList, bool bMakeVisible);
  326. virtual CCryEditDoc* OpenDocumentFile(const char* lpszPathName, bool bMakeVisible = TRUE);
  327. virtual Confidence MatchDocType(const char* lpszPathName, CCryEditDoc*& rpDocMatch);
  328. private:
  329. const QMetaObject* m_documentClass = nullptr;
  330. };
  331. class CDocTemplate;
  332. class CCryDocManager
  333. {
  334. CCrySingleDocTemplate* m_pDefTemplate = nullptr;
  335. public:
  336. CCryDocManager();
  337. virtual ~CCryDocManager() = default;
  338. CCrySingleDocTemplate* SetDefaultTemplate(CCrySingleDocTemplate* pNew);
  339. // Copied from MFC to get rid of the silly ugly unoverridable doc-type pick dialog
  340. virtual void OnFileNew();
  341. virtual bool DoPromptFileName(QString& fileName, UINT nIDSTitle,
  342. DWORD lFlags, bool bOpenFileDialog, CDocTemplate* pTemplate);
  343. virtual CCryEditDoc* OpenDocumentFile(const char* filename, bool addToMostRecentFileList, COpenSameLevelOptions openSameLevelOptions = COpenSameLevelOptions::NotReopenIfSame);
  344. QVector<CCrySingleDocTemplate*> m_templateList;
  345. };
  346. #include <AzCore/Component/Component.h>
  347. namespace AzToolsFramework
  348. {
  349. //! A component to reflect scriptable commands for the Editor
  350. class CryEditPythonHandler final
  351. : public AZ::Component
  352. {
  353. public:
  354. AZ_COMPONENT(CryEditPythonHandler, "{D4B19973-54D9-44BD-9E70-6069462A0CDC}")
  355. virtual ~CryEditPythonHandler() = default;
  356. SANDBOX_API static void Reflect(AZ::ReflectContext* context);
  357. // AZ::Component ...
  358. void Activate() override {}
  359. void Deactivate() override {}
  360. class CryEditHandler
  361. {
  362. public:
  363. AZ_RTTI(CryEditHandler, "{6C1FD05A-2F39-4094-80D4-CA526676F13E}")
  364. virtual ~CryEditHandler() = default;
  365. };
  366. class CryEditCheckoutHandler
  367. {
  368. public:
  369. AZ_RTTI(CryEditCheckoutHandler, "{C65EF439-6754-4ACD-AEA2-196F2DBA0AF3}")
  370. virtual ~CryEditCheckoutHandler() = default;
  371. };
  372. };
  373. } // namespace AzToolsFramework
  374. extern "C" AZ_DLL_EXPORT void InitializeDynamicModule();
  375. extern "C" AZ_DLL_EXPORT void UninitializeDynamicModule();
  376. #endif // CRYINCLUDE_EDITOR_CRYEDIT_H