Polyphase Game Engine
Loading...
Searching...
No Matches
EditorState.h
Go to the documentation of this file.
1#pragma once
2
3#if EDITOR
4
5#include <array>
6#include <string>
7#include <set>
8#include <unordered_map>
9#include <vector>
10#include "Maths.h"
11#include "AssetRef.h"
12#include "SmartPointer.h"
13#include "Property.h"
14#include "Enums.h"
15#include "EditorTypes.h"
16#include "Nodes/Widgets/Text.h"
17#include "imgui.h"
18#include "./ImGuizmo/ImGuizmo.h"
19
20class Node;
21class Scene;
22class Timeline;
24class Widget;
25class Text;
26class Asset;
27struct AssetStub;
28class AssetDir;
29class ActionList;
30class Canvas;
31class Camera3D;
32class Viewport3D;
33class Viewport2D;
34class PaintManager;
35class VoxelSculptManager;
36class TilePaintManager;
37struct SubSceneOverride;
38
39enum class ControlMode
40{
41 Default,
42 Pilot,
44 Rotate,
45 Scale,
46 Pan,
47 Orbit
48};
49
50enum class TransformLock
51{
52 None,
53 AxisX,
54 AxisY,
55 AxisZ,
56 PlaneYZ,
57 PlaneXZ,
58 PlaneXY,
59 Count
60};
61
62enum class EditorMode
63{
64 Scene,
65 Scene2D,
66 Scene3D,
67
68 Count
69};
70
71enum class PaintMode
72{
73 None,
74 Color,
75 Instance,
76 Voxel,
77 Terrain,
78 TilePaint,
79
80 Count
81};
82
83enum class AssetBrowserTab
84{
85 Project = 0,
86 Addons = 1,
87 Count
88};
89
90struct LinkedSceneProps
91{
92 Node* mNode = nullptr;
93 std::vector<Property> mProps;
94 std::vector<SubSceneOverride> mSubSceneOverrides;
95};
96
97struct EditScene
98{
99 SceneRef mSceneAsset;
100 NodePtr mRootNode;
101 glm::mat4 mCameraTransform;
102 std::vector<LinkedSceneProps> mLinkedSceneProps;
103};
104
105struct RecentScene
106{
107 std::string mSceneName;
108 uint64_t mTimestamp = 0;
109};
110
111// Editor 3D viewport camera bookmark. One of 10 per-scene slots driven by the
112// `View_SaveBookmark*` / `View_GotoBookmark*` editor actions. Persisted in
113// EditorProject.sav, keyed by scene name.
114constexpr int32_t kEditorCameraBookmarkSlotCount = 10;
115
116struct EditorCameraBookmark
117{
118 bool mValid = false;
119 glm::vec3 mPosition = { 0.0f, 0.0f, 0.0f };
120 glm::quat mRotation = { 1.0f, 0.0f, 0.0f, 0.0f };
122 float mPerspectiveNearZ = 0.25f;
123 float mPerspectiveFarZ = 4096.0f;
124 float mPerspectiveFov = 70.0f;
125 float mOrthoNearZ = -2048.0f;
126 float mOrthoFarZ = 2048.0f;
127 float mOrthoWidth = 12.8f;
128 float mFocalDistance = 10.0f;
129};
130
131using EditorCameraBookmarkArray = std::array<EditorCameraBookmark, kEditorCameraBookmarkSlotCount>;
132
133// Per-asset state captured at BeginPlayInEditor and re-applied at
134// EndPlayInEditor so script mutations during play don't leak into the editor.
135struct PieAssetSnapshot
136{
137 std::vector<uint8_t> mBytes;
138 bool mWasDirty = false;
139};
140
141struct EditorState
142{
143 // Data
144 EditorMode mMode;
145 std::vector<Node*> mSelectedNodes;
146 Node* mShiftSelectAnchor = nullptr;
147 int32_t mSelectedInstance = -1;
148 std::vector<EditScene> mEditScenes;
149 AssetStub* mSelectedAssetStub = nullptr;
150 std::vector<AssetStub*> mSelectedAssetStubs;
151 ControlMode mControlMode = ControlMode::Default;
152 TransformLock mTransformLock = TransformLock::None;
153 SharedPtr<Camera3D> mEditorCamera;
154 float mPerspectiveNearZ = 0.25f;
155 float mPerspectiveFarZ = 4096.0f;
156 float mPerspectiveFov = 70.0f;
157 float mOrthoNearZ = -2048.0f;
158 float mOrthoFarZ = 2048.0f;
159 float mOrthoWidth = 12.8f;
160 bool mMouseNeedsRecenter = false;
161 bool mUiEnabled = true;
162 bool mPlayInEditor = false;
163 bool mPlayInGameWindow = false;
164 bool mEjected = false;
165 bool mPaused = false;
166 bool mHasEjectedOnce = false;
167 bool mSavedGridEnabled = false;
168
169 // One-frame latch consumed by Viewport3D's left-click selection path.
170 // Set true to make the next left-click release inside the viewport NOT
171 // change the selection. Plugin tools that handle their own clicks
172 // (Level Builder placement etc.) set this every frame they're armed
173 // via EditorUIHooks::Viewport_SuppressNextSelectionClick. Read-and-
174 // cleared in Viewport3D::HandleDefaultControls, so a stale flag never
175 // survives a real click.
176 bool mSuppressNextSelectionClick = false;
177 glm::vec4 mSavedEditorClearColor = glm::vec4(0.0f, 0.0f, 0.0f, 1.0f);
178 int32_t mSavedWindowRect[4] = {}; // x, y, w, h — saved before Play Full Screen resize
179 int32_t mEditSceneIndex = -1;
180 int32_t mPieEditSceneIdx = -1;
181 std::unordered_map<Asset*, PieAssetSnapshot> mPieAssetSnapshots;
182 // Lazy cache of instantiated default trees for sub-scene source assets,
183 // used by the inspector to detect overridden properties and revert them.
184 // Keyed by source Scene*. Invalidated when an EditScene closes, on
185 // editor shutdown, and whenever a source Scene is reimported/saved.
186 std::unordered_map<Scene*, NodePtr> mInspectorDefaultCache;
187 // Deferred dispatch for long-running editor operations: the click/hotkey
188 // handler sets the appropriate *AtEndOfFrame flag, and EditorMain.cpp
189 // picks them up *after* EditorImguiDraw has returned and runs the work
190 // synchronously. The EditorProgress modal pumps additional ImGui frames
191 // during the work so the user sees animated progress instead of a freeze.
192 bool mBeginPieAtEndOfFrame = false;
193 bool mEndPieAtEndOfFrame = false;
194 bool mSaveSceneAtEndOfFrame = false;
195 bool mSaveSelectedAssetAtEndOfFrame = false;
196 bool mResaveAllAtEndOfFrame = false;
197 bool mReloadScriptsAtEndOfFrame = false;
198 bool mOpenProjectAtEndOfFrame = false;
199 std::string mPendingOpenProjectPath;
200 // Deferred "close current project" — used by File > Close Project and as
201 // a precondition for Tier-2 recovery. Drained by EditorMain's per-frame
202 // dispatcher alongside the open/save deferreds.
203 bool mCloseProjectAtEndOfFrame = false;
204 // Deferred Tier-2 recovery: drop addon DLLs, kill mspdbsrv, wipe
205 // Intermediate/Plugins, reopen project. mPendingAddonRecoveryReason is
206 // surfaced in logs.
207 bool mAddonRecoveryAtEndOfFrame = false;
208 std::string mPendingAddonRecoveryReason;
209 // Deferred Tier-3 recovery: spawn a fresh editor with --addon-recovery
210 // and quit the current one. The new instance does the wipe + reopen.
211 bool mEditorRestartAtEndOfFrame = false;
212 std::string mPendingEditorRestartReason;
213 // Deferred OpenScene. Either a stub (preferred -- path is captured at
214 // request time so a later directory rename doesn't break it) or empty
215 // to trigger the OS file dialog inside the worker. Scene* is held as
216 // a raw pointer; the asset map owns the lifetime and the dispatcher
217 // runs same-tick so dangling is not realistic.
218 bool mOpenSceneAtEndOfFrame = false;
219 AssetStub* mPendingOpenSceneStub = nullptr;
220
221 // Generic progress modal state, consumed by DrawProgressModal and driven
222 // by the EditorProgress::* API. Negative fraction = indeterminate sine
223 // marquee; non-negative = determinate 0..1 fill.
224 bool mProgressActive = false;
225 bool mProgressCancellable = false;
226 bool mProgressCancelRequested = false;
227 std::string mProgressTitle;
228 std::string mProgressStatus;
229 float mProgressFraction = -1.0f;
230 double mProgressLastPumpTime = 0.0;
231 AssetBrowserTab mActiveAssetTab = AssetBrowserTab::Project;
232 AssetDir* mTabCurrentDir[(int)AssetBrowserTab::Count] = {};
233 std::vector<AssetDir*> mTabDirPast[(int)AssetBrowserTab::Count];
234 std::vector<AssetDir*> mTabDirFuture[(int)AssetBrowserTab::Count];
235 std::string mTabFilterStr[(int)AssetBrowserTab::Count];
236 std::vector<AssetStub*> mTabFilteredStubs[(int)AssetBrowserTab::Count];
237 std::vector<Object*> mInspectPast;
238 std::vector<Object*> mInspectFuture;
239 Object* mInspectedObject;
240 Object* mPrevInspectedObject;
241 AssetRef mInspectedAsset;
242 bool mInspectLocked = false;
243 Viewport3D* mViewport3D = nullptr;
244 Viewport2D* mViewport2D = nullptr;
245 std::string mIOAssetPath;
246 bool mRequestSaveSceneAs = false;
247 bool mTrackSelectedAsset = false;
248 bool mTrackSelectedNode = false;
249 std::string mRevealScriptName = "";
250 std::set<AssetDir*> mRevealAssetExpandDirs;
251 uint32_t mViewportX = 0;
252 uint32_t mViewportY = 0;
253 uint32_t mViewportWidth = 100;
254 uint32_t mViewportHeight = 100;
255 glm::uvec4 mPrevViewport = {};
256 bool mShowLeftPane = true;
257 bool mShowRightPane = true;
258 bool mShowInterface = true;
259 bool mPreviewLighting = true;
260 SharedPtr<Text> mOverlayText = nullptr;
261 std::vector<std::string> mFavoritedDirs;
262 std::vector<std::string> mRecentProjects;
263 std::vector<RecentScene> mRecentScenes;
264
265 // Per-scene camera bookmark slots, keyed by Scene asset name. Saved
266 // and restored from EditorProject.sav (kEditorProjectSaveVersion >= 4).
267 // Unsaved / untitled scenes use the empty-string key — those bookmarks
268 // work within the session but never persist.
269 std::unordered_map<std::string, EditorCameraBookmarkArray> mCameraBookmarks;
270 PaintMode mPaintMode = PaintMode::None;
271 PaintManager* mPaintManager = nullptr;
272 VoxelSculptManager* mVoxelSculptManager = nullptr;
273 class TerrainSculptManager* mTerrainSculptManager = nullptr;
274 TilePaintManager* mTilePaintManager = nullptr;
275
276 // ID of the currently-active addon viewport mode (Batch 15), empty when
277 // no addon mode is active. Activation is mutually exclusive with the
278 // built-in PaintMode: selecting an addon mode forces mMode=Scene3D and
279 // mPaintMode=None; selecting any built-in entry clears this string.
280 // Cross-reference: EditorUIHookManager owns the mode registrations
281 // (RegisteredViewportMode) — this struct only holds the active id and
282 // fires activate/deactivate callbacks via the manager on transition.
283 std::string mActiveAddonViewportModeId;
284
285 // Tile-paint mode stashes the editor camera's previous projection AND
286 // transform so it can switch to a top-down orthographic view of the
287 // currently-selected TileMap2D and restore the original camera on exit.
288 bool mTilePaintProjectionStashed = false;
289 bool mTilePaintPrevWasPerspective = true;
290 bool mTilePaintTransformStashed = false;
291 glm::vec3 mTilePaintPrevCameraPosition = { 0.0f, 0.0f, 0.0f };
292 glm::quat mTilePaintPrevCameraRotation = { 1.0f, 0.0f, 0.0f, 0.0f };
293 bool mNodePropertySelect = false;
294 int32_t mNodePropertySelectIndex = 0;
295 std::string mNodePropertySelectName = "";
296 std::string mPendingSceneImportPath = "";
297 std::vector<std::string> mPendingMeshImportPaths;
298 std::vector<std::string> mPendingSceneImportQueue;
299
300 // AssetDir row the mouse is over in the asset browser this frame. Reset
301 // at the top of EditorImguiDraw, set whenever a dir TreeNodeEx / Selectable
302 // reports IsItemHovered. Used by the OS file-drop modal so dropping onto
303 // a specific folder lands the files there instead of the active folder.
304 AssetDir* mMouseHoveredAssetDir = nullptr;
305
306 // Import-time name-clash queue. Filled by ActionManager::ImportAsset when
307 // the source file's basename collides with an existing asset of a different
308 // type (e.g. importing `tent.glb` as StaticMesh while `tent.oct` is already
309 // a Texture). Drained by the "Asset Name Clash" modal in EditorImgui, which
310 // lets the user rename or cancel before any pointers get rebound.
311 struct PendingImportClash
312 {
313 std::string mSourcePath; // file the user dropped / picked
314 std::string mOriginalBaseName; // basename derived from the source file (what would have been used)
315 std::string mProposedName; // user-editable; pre-filled with first free `name_N`
316 std::string mExistingTypeName;
317 std::string mImportTypeName;
318 bool mCombined = false; // true if it came in via ImportAssetCombined
319 MeshImportOptions mMeshOpts; // forwarded from the "Import Mesh Asset" modal so the re-driven import keeps Place-in-subdir / Import Materials / Shading Model / etc.
320 bool mHasMeshOpts = false; // true when mMeshOpts was populated from a mesh-import flow
321 };
322 std::vector<PendingImportClash> mPendingImportClashes;
323 AssetStub* mPendingReimportSceneStub = nullptr;
324 std::string mPendingReimportScenePath = "";
325 bool mShutdownUnsavedCheck = false;
326 bool mDevMode = false;
327 bool mShowBottomPane = true;
328 float mBottomPaneHeight = 180.0f;
329 bool mShowProjectUpgradeModal = false;
330 bool mProjectUpgradeInProgress = false;
331 std::vector<AssetStub*> mAssetsNeedingUpgrade;
332
333 // 3DS Preview Panel state
334 bool mShow3DSPreview = false;
335 int32_t mSceneScreenFilter = -1; // -1 = All Screens, 0 = Top Screen, 1 = Bottom Screen
336
337 // Game Preview Panel state
338 bool mShowGamePreview = false;
339 bool mGamePreviewCaptured = false;
340
341 // Play target (shared between viewport toolbar and Game Preview)
342 int32_t mPlayTarget = 0; // 0=PlayInEditor, 1=PlayFullScreen, 2=Dolphin, 3=Azahar, 4=Standalone, 5=Send3dsLink
343
344 // Node Graph Panel state
345 bool mShowNodeGraphPanel = false;
346
347 // Timeline Panel state
348 bool mShowTimelinePanel = false;
349
350 // Profiling Panel state
351 bool mShowProfilingPanel = false;
352
353 // Input Tester Panel state
354 bool mShowInputTesterPanel = false;
355
356 // Texture Atlas Viewer state
357 bool mShowTextureAtlasViewer = false;
358
359 // Git Panel state
360 bool mShowGitPanel = false;
361
362 // Animation Browser Panel state
363 bool mShowAnimationBrowser = false;
364 // Bone Mask Editor Panel state
365 bool mShowBoneMaskEditor = false;
366 TimelineRef mEditedTimelineRef;
367 TimelineInstance* mTimelinePreviewInstance = nullptr;
368 float mTimelinePlayheadTime = 0.0f;
369 bool mTimelinePreviewing = false;
370 float mTimelineZoom = 100.0f;
371 float mTimelineScrollX = 0.0f;
372 float mTimelineSnapInterval = 0.1f;
373 int32_t mTimelineSelectedTrack = -1;
374 int32_t mTimelineSelectedClip = -1;
375 int32_t mTimelineSelectedKeyframe = -1;
376
377 // ImGuizmo state
378 ImGuizmo::OPERATION mGizmoOperation = ImGuizmo::TRANSLATE;
379 ImGuizmo::MODE mGizmoMode = ImGuizmo::WORLD;
380 bool mGizmoBlockedBySelection = false;
381
382 // Methods
383 void Init();
384 void Shutdown();
385 void Update(float deltaTime);
386
387 void GatherProperties(std::vector<Property>& props);
388
389 void SetEditorMode(EditorMode mode);
390 EditorMode GetEditorMode();
391
392 void SetPaintMode(PaintMode paintMode);
393 PaintMode GetPaintMode();
394
395 // ===== Batch 15: Addon viewport mode helpers =====
396
411 void SetActiveAddonViewportMode(const std::string& modeId);
412
419 void ClearActiveAddonViewportMode();
420
422 bool HasActiveAddonViewportMode() const { return !mActiveAddonViewportModeId.empty(); }
423
425 const std::string& GetActiveAddonViewportModeId() const { return mActiveAddonViewportModeId; }
426
427 void ReadEditorSave();
428 void WriteEditorSave();
429
430 void ReadEditorProjectSave();
431 void WriteEditorProjectSave();
432
433 void HandleNodeDestroy(Node* node);
434
435 void SetSelectedNode(Node* newNode);
436 void AddSelectedNode(Node* node, bool addAllChildren);
437 void SelectNodesInRange(Node* rootNode, Node* endNode);
438 void RemoveSelectedNode(Node* node);
439 void SetSelectedAssetStub(AssetStub* newStub);
440 void AddSelectedAssetStub(AssetStub* stub);
441 void RemoveSelectedAssetStub(AssetStub* stub);
442 void ClearSelectedAssetStubs();
443 const std::vector<AssetStub*>& GetSelectedAssetStubs();
444 bool IsAssetStubSelected(AssetStub* stub);
445 void SetControlMode(ControlMode newMode);
446
447 void BeginPlayInEditor();
448 void EndPlayInEditor();
449 // Defer the start/stop by one frame so the loading modal can render
450 // before the (potentially slow) snapshot/clone or restore work runs.
451 void RequestBeginPlayInEditor();
452 void RequestEndPlayInEditor();
453 // Defer a Lua "Reload All Scripts" until end-of-frame so the progress
454 // modal can render before the script reload loop blocks. The worker is
455 // the global ::ReloadAllScripts() in Engine.cpp.
456 void RequestReloadAllScripts();
457 void EjectPlayInEditor();
458 void InjectPlayInEditor();
459 void SnapshotAssetsForPie();
460 void RestoreAssetsFromPie();
461
462 // Sub-scene override inspector helpers. The cache holds an instantiated
463 // copy of each source Scene asset that's currently being inspected; the
464 // inspector compares the live node's property values against the
465 // corresponding default node in the cached tree to detect overrides.
466 // Pass nullptr to InvalidateSubSceneDefaultCache to clear everything.
467 Node* GetSubSceneDefaultTree(Scene* src);
468 void InvalidateSubSceneDefaultCache(Scene* src = nullptr);
469 bool IsPropertyOverridden(Node* node, const std::string& propName);
470 void RevertPropertyToSource(Node* node, const std::string& propName);
471 void SetPlayInEditorPaused(bool paused);
472 bool IsPlayInEditorPaused();
473
474 void SetNodePropertySelect(bool enable, int32_t index, const std::string& propName);
475 void ClearNodePropertySelect();
476 void AssignNodePropertySelect(Node* targetNode);
477
478 Camera3D* GetEditorCamera();
479 void ToggleEditorCameraProjection();
480 void ApplyEditorCameraSettings();
481
482 // Camera bookmarks. Slots are 0..kEditorCameraBookmarkSlotCount-1; the
483 // hotkey labels (1..0) correspond to slots 0..9. Save captures the editor
484 // camera's transform / projection / focal distance, Restore re-applies
485 // them, and Has reports whether a slot has been populated. Restore is
486 // intentionally NOT undoable — it changes editor view state, not scene
487 // content.
488 void SaveCameraBookmark(int32_t slot);
489 void RestoreCameraBookmark(int32_t slot);
490 bool HasCameraBookmark(int32_t slot) const;
491 const EditorCameraBookmarkArray* GetActiveSceneCameraBookmarks() const;
492 EditorCameraBookmarkArray* GetOrCreateActiveSceneCameraBookmarks();
493
494 void LoadStartupScene();
495
496 Node* GetSelectedNode();
497 Widget* GetSelectedWidget();
498 const std::vector<Node*>& GetSelectedNodes();
499 bool IsNodeSelected(Node* node);
500 void DeselectNode(Node* node);
501 int32_t GetSelectedInstance();
502 void SetSelectedInstance(int32_t instance);
503 //void ShowTextPrompt(const char* title, TextFieldHandlerFP confirmHandler, const char* defaultText = nullptr);
504
505 void OpenEditScene(Scene* scene);
506 void OpenEditScene(int32_t idx);
507 void CloseEditScene(int32_t idx);
508 void ShelveEditScene();
509 EditScene* GetEditScene(int32_t idx = -1);
510 void CloseAllEditScenes();
511 void EnsureActiveScene();
512
513 void ShowEditorUi(bool show);
514
515 Asset* GetSelectedAsset();
516 AssetStub* GetSelectedAssetStub();
517 ControlMode GetControlMode();
518 glm::vec3 GetTransformLockVector(TransformLock lock);
519 void SetTransformLock(TransformLock lock);
520
521 Object* GetInspectedObject();
522 Node* GetInspectedNode();
523 Asset* GetInspectedAsset();
524 void InspectObject(Object* obj, bool force = false, bool recordHistory = true);
525 void LockInspect(bool lock);
526 bool IsInspectLocked();
527 void RecordInspectHistory();
528 void ClearInspectHistory();
529 void RemoveFromInspectHistory(Object* obj);
530 void ProgressInspectFuture();
531 void RegressInspectPast();
532 void ClearAssetDirHistory();
533 void SetAssetDirectory(AssetDir* assetDir, bool recordHistory);
534 AssetDir* GetAssetDirectory();
535 void BrowseToAsset(const std::string& name);
536 void BrowseToScript(const std::string& scriptName);
537
538 void CaptureAndSaveScene(AssetStub* stub, Node* rootNode);
539 void DuplicateAsset(AssetStub* srcStub, const char* overrideName = nullptr);
540
541 void ProgressDirFuture();
542 void RegressDirPast();
543
544 void RemoveFilteredAssetStub(AssetStub* stub);
545 int ActiveTab() const { return (int)mActiveAssetTab; }
546
547 Viewport3D* GetViewport3D();
548 Viewport2D* GetViewport2D();
549
550 bool IsDirFavorited(const std::string& dirPath);
551 void AddFavoriteDir(const std::string& dirPath);
552 void RemoveFavoriteDir(const std::string& dirPath);
553
554 void AddRecentProject(const std::string& projPath);
555 void AddRecentScene(const std::string& sceneName);
556};
557
558EditorState* GetEditorState();
559
560#endif
bool Update()
Definition Engine.cpp:790
void Shutdown()
Definition Engine.cpp:1026
ProjectionMode
Definition Enums.h:27
Definition AssetDir.h:11
Definition AssetRef.h:18
Definition Asset.h:119
Definition Camera3d.h:12
Definition Canvas.h:9
Definition Node.h:67
Definition Object.h:13
Definition Scene.h:36
Definition Text.h:24
Definition TimelineInstance.h:32
Definition Timeline.h:10
Definition Viewport2d.h:33
Definition Viewport3d.h:7
Definition Widget.h:53
Definition Asset.h:88
Definition Scene.h:13