feat: move editor to project / add post processing etc
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
#ifndef EDITOR_ASSETBROWSER_H
|
||||
#define EDITOR_ASSETBROWSER_H
|
||||
|
||||
#include <filesystem>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class AssetBrowser final {
|
||||
public:
|
||||
std::optional<std::string> Draw(bool* open = nullptr);
|
||||
|
||||
private:
|
||||
struct Entry {
|
||||
std::string name;
|
||||
bool directory{false};
|
||||
};
|
||||
|
||||
void Refresh();
|
||||
void Navigate(const std::string& scheme, const std::filesystem::path& folder);
|
||||
[[nodiscard]] std::string VirtualPath(const std::string& name) const;
|
||||
void DrawEntry(const Entry& entry, std::optional<std::string>& opened, bool& navigated);
|
||||
void DrawFolderMenu();
|
||||
|
||||
std::string m_Scheme;
|
||||
std::filesystem::path m_Folder;
|
||||
std::vector<Entry> m_Entries;
|
||||
std::string m_Filter;
|
||||
bool m_Dirty{true};
|
||||
};
|
||||
|
||||
#endif // EDITOR_ASSETBROWSER_H
|
||||
@@ -0,0 +1,141 @@
|
||||
#ifndef EDITOR_EDITOR_H
|
||||
#define EDITOR_EDITOR_H
|
||||
|
||||
#include <filesystem>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
#include <glm/vec2.hpp>
|
||||
|
||||
#include <destrum/AppLayer.h>
|
||||
|
||||
#include <editor/AssetBrowser.h>
|
||||
#include <editor/EditorCamera.h>
|
||||
#include <editor/PlayMode.h>
|
||||
#include <editor/RectGizmo.h>
|
||||
#include <editor/ResourcesInspector.h>
|
||||
#include <editor/SceneInspector.h>
|
||||
#include <editor/ShaderHotReload.h>
|
||||
#include <editor/TransformGizmo.h>
|
||||
#include <editor/UndoStack.h>
|
||||
|
||||
class App;
|
||||
class Scene;
|
||||
|
||||
struct EditorSettings {
|
||||
std::filesystem::path gameAssetsSource;
|
||||
std::string scenePath;
|
||||
bool startInEditMode{true};
|
||||
};
|
||||
|
||||
class Editor final : public AppLayer {
|
||||
public:
|
||||
Editor(App& app, EditorSettings settings);
|
||||
|
||||
void onAttach() override;
|
||||
void onBeginFrame() override;
|
||||
void onImGuiBegin(float dt) override;
|
||||
void onImGui(float dt) override;
|
||||
void onEndFrame() override;
|
||||
void onRender(GameRenderer& renderer) override;
|
||||
|
||||
[[nodiscard]] Camera* viewCamera() override;
|
||||
[[nodiscard]] bool hostsViewport() const override { return true; }
|
||||
[[nodiscard]] InputFocus gameInputFocus() const override;
|
||||
|
||||
bool OpenScene(std::string_view path);
|
||||
bool SaveScene();
|
||||
bool SaveSceneAs(std::string_view path);
|
||||
void NewScene();
|
||||
|
||||
[[nodiscard]] UndoStack& GetUndoStack() { return m_UndoStack; }
|
||||
[[nodiscard]] PlayMode& GetPlayMode() { return m_PlayMode; }
|
||||
|
||||
private:
|
||||
struct Panels {
|
||||
bool inspector{true};
|
||||
bool assets{true};
|
||||
bool stats{true};
|
||||
bool physics{false};
|
||||
bool imageCache{false};
|
||||
};
|
||||
|
||||
struct ViewOptions {
|
||||
bool colliders{false};
|
||||
bool gizmos{true};
|
||||
};
|
||||
|
||||
struct Viewport {
|
||||
glm::vec2 min{0.0f};
|
||||
glm::vec2 size{1.0f};
|
||||
glm::ivec2 desiredSize{0};
|
||||
bool hovered{false};
|
||||
bool focused{false};
|
||||
bool mouseClaimed{false};
|
||||
bool pickSelectsParent{false};
|
||||
std::optional<glm::ivec2> hoverPixel;
|
||||
};
|
||||
|
||||
// Editor.cpp
|
||||
[[nodiscard]] Scene* CurrentScene() const;
|
||||
[[nodiscard]] bool UsesEditorCamera();
|
||||
void HandleShortcuts();
|
||||
void Undo();
|
||||
void Redo();
|
||||
void RecordEdits();
|
||||
void AfterSceneReplaced(bool resetHistory);
|
||||
void DeleteSelection();
|
||||
void DuplicateSelection();
|
||||
void FocusSelection();
|
||||
void SetStatus(std::string status);
|
||||
bool WriteScene(Scene& scene, std::string_view path);
|
||||
|
||||
// EditorViewport.cpp
|
||||
void ApplyViewportResize();
|
||||
void DrawViewport();
|
||||
void DrawGizmos(Scene& scene);
|
||||
void RequestPick();
|
||||
void ApplyPick();
|
||||
void OnAssetDropped(std::string_view path);
|
||||
void SubmitColliderLines(Scene& scene) const;
|
||||
|
||||
// EditorMenus.cpp
|
||||
void DrawDockSpace();
|
||||
void DrawMainMenuBar();
|
||||
void DrawFileMenu();
|
||||
void DrawEditMenu();
|
||||
void DrawViewMenu();
|
||||
void DrawDisplayMenu();
|
||||
void DrawPlayControls();
|
||||
void DrawSceneDialogs();
|
||||
void DrawStatsPanel();
|
||||
void DrawPhysicsPanel();
|
||||
|
||||
App& m_App;
|
||||
EditorSettings m_Settings;
|
||||
|
||||
EditorCamera m_Camera;
|
||||
PlayMode m_PlayMode;
|
||||
UndoStack m_UndoStack;
|
||||
SceneInspector m_Inspector;
|
||||
AssetBrowser m_AssetBrowser;
|
||||
ResourcesInspector m_ResourcesInspector;
|
||||
TransformGizmo m_TransformGizmo;
|
||||
RectGizmo m_RectGizmo;
|
||||
ShaderHotReload m_ShaderHotReload;
|
||||
|
||||
Panels m_Panels;
|
||||
ViewOptions m_View;
|
||||
Viewport m_Viewport;
|
||||
|
||||
std::string m_ScenePath;
|
||||
std::string m_Status;
|
||||
std::string m_SaveAsPath;
|
||||
bool m_OpenSceneDialog{false};
|
||||
bool m_SaveAsDialog{false};
|
||||
bool m_ItemWasActive{false};
|
||||
bool m_EditPending{false};
|
||||
};
|
||||
|
||||
#endif // EDITOR_EDITOR_H
|
||||
@@ -0,0 +1,36 @@
|
||||
#ifndef EDITOR_EDITORCAMERA_H
|
||||
#define EDITOR_EDITORCAMERA_H
|
||||
|
||||
#include <optional>
|
||||
|
||||
#include <glm/vec3.hpp>
|
||||
|
||||
#include <destrum/Graphics/Camera.h>
|
||||
|
||||
class GameObject;
|
||||
class RenderResources;
|
||||
|
||||
struct WorldBounds {
|
||||
glm::vec3 center{0.0f};
|
||||
float radius{1.0f};
|
||||
};
|
||||
|
||||
[[nodiscard]] WorldBounds ComputeWorldBounds(GameObject& object, const RenderResources& resources);
|
||||
|
||||
class EditorCamera final {
|
||||
public:
|
||||
EditorCamera();
|
||||
|
||||
void Update(float dt, bool hasInput);
|
||||
void Focus(const WorldBounds& bounds);
|
||||
|
||||
[[nodiscard]] Camera& GetCamera() { return m_Camera; }
|
||||
[[nodiscard]] bool IsLooking() const { return m_Looking; }
|
||||
|
||||
private:
|
||||
Camera m_Camera;
|
||||
std::optional<glm::vec3> m_FocusTarget;
|
||||
bool m_Looking{false};
|
||||
};
|
||||
|
||||
#endif // EDITOR_EDITORCAMERA_H
|
||||
@@ -0,0 +1,39 @@
|
||||
#ifndef EDITOR_PLAYMODE_H
|
||||
#define EDITOR_PLAYMODE_H
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
class App;
|
||||
class Scene;
|
||||
|
||||
class PlayMode final {
|
||||
public:
|
||||
explicit PlayMode(App& app);
|
||||
|
||||
void EnterEditMode();
|
||||
void RequestToggle() { m_ToggleRequested = true; }
|
||||
void SetPaused(bool paused);
|
||||
|
||||
[[nodiscard]] bool ApplyPendingToggle();
|
||||
|
||||
[[nodiscard]] bool IsPlaying() const { return m_Playing; }
|
||||
[[nodiscard]] bool IsPaused() const { return m_Paused; }
|
||||
[[nodiscard]] bool IsEditing() const { return !m_Playing; }
|
||||
|
||||
private:
|
||||
bool Enter();
|
||||
void Exit();
|
||||
|
||||
App& m_App;
|
||||
bool m_Playing{true};
|
||||
bool m_Paused{false};
|
||||
bool m_ToggleRequested{false};
|
||||
bool m_MouseCapturedBeforePause{false};
|
||||
std::optional<nlohmann::json> m_EditSnapshot;
|
||||
std::weak_ptr<Scene> m_EditScene;
|
||||
};
|
||||
|
||||
#endif // EDITOR_PLAYMODE_H
|
||||
@@ -0,0 +1,28 @@
|
||||
#ifndef EDITOR_RECTGIZMO_H
|
||||
#define EDITOR_RECTGIZMO_H
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
class GameObject;
|
||||
|
||||
class RectGizmo final {
|
||||
public:
|
||||
[[nodiscard]] static bool CanManipulate(GameObject& object);
|
||||
|
||||
bool Manipulate(GameObject& object, const glm::vec2& drawImageSize, const glm::vec2& viewMin, const glm::vec2& viewSize);
|
||||
|
||||
[[nodiscard]] bool IsUsing() const { return m_ActiveHandle >= 0; }
|
||||
[[nodiscard]] bool IsInteracting() const { return m_ActiveHandle >= 0 || m_Hovered; }
|
||||
|
||||
bool snap{false};
|
||||
float snapStep{5.0f};
|
||||
|
||||
private:
|
||||
int m_ActiveHandle{-1};
|
||||
bool m_Hovered{false};
|
||||
glm::vec2 m_DragStartMouse{0.0f};
|
||||
glm::vec2 m_DragStartPosition{0.0f};
|
||||
glm::vec2 m_DragStartSize{0.0f};
|
||||
};
|
||||
|
||||
#endif // EDITOR_RECTGIZMO_H
|
||||
@@ -0,0 +1,35 @@
|
||||
#ifndef EDITOR_RESOURCESINSPECTOR_H
|
||||
#define EDITOR_RESOURCESINSPECTOR_H
|
||||
|
||||
#include <destrum/Graphics/ids.h>
|
||||
|
||||
struct GPUImage;
|
||||
class ImguiPass;
|
||||
class RenderResources;
|
||||
|
||||
// ImGui windows for looking into the render resource caches
|
||||
class ResourcesInspector final
|
||||
{
|
||||
public:
|
||||
void drawImageCacheWindow(bool* open, const RenderResources& resources, ImguiPass& imguiPass);
|
||||
|
||||
private:
|
||||
struct PreviewInfo
|
||||
{
|
||||
bool previewable{false};
|
||||
const char* reason{""};
|
||||
};
|
||||
|
||||
[[nodiscard]] static PreviewInfo getPreviewInfo(const GPUImage& image);
|
||||
|
||||
void drawImagePreview(const GPUImage& image, float maxSize, ImguiPass& imguiPass) const;
|
||||
void drawImageDetails(ImageID id, const RenderResources& resources) const;
|
||||
[[nodiscard]] bool matchesFilter(ImageID id, const RenderResources& resources) const;
|
||||
|
||||
char filter[128]{};
|
||||
float thumbnailSize{48.0f};
|
||||
bool onlyPreviewable{false};
|
||||
ImageID selectedImageId{NULL_IMAGE_ID};
|
||||
};
|
||||
|
||||
#endif //EDITOR_RESOURCESINSPECTOR_H
|
||||
@@ -0,0 +1,60 @@
|
||||
#ifndef EDITOR_SCENEINSPECTOR_H
|
||||
#define EDITOR_SCENEINSPECTOR_H
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <unordered_set>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include <destrum/ObjectModel/ObjectId.h>
|
||||
|
||||
class Component;
|
||||
class GameObject;
|
||||
class Scene;
|
||||
|
||||
class SceneInspector final {
|
||||
public:
|
||||
void Draw(Scene& scene, ObjectId& selectedObjectId, const std::function<void()>& drawSceneSettings, bool* open);
|
||||
|
||||
private:
|
||||
struct PendingMove {
|
||||
ObjectId object{InvalidObjectId};
|
||||
ObjectId parent{InvalidObjectId};
|
||||
ObjectId anchor{InvalidObjectId};
|
||||
bool after{false};
|
||||
};
|
||||
|
||||
void DrawHierarchy(Scene& scene, ObjectId& selectedObjectId);
|
||||
void DrawNode(Scene& scene, GameObject& object, ObjectId& selectedObjectId, std::unordered_set<const GameObject*>& visited);
|
||||
void DrawRenameField(GameObject& object);
|
||||
void DrawNodeDragDrop(GameObject& object);
|
||||
void DrawObjectMenu(Scene& scene, GameObject* object, ObjectId& selectedObjectId);
|
||||
void HandleShortcuts(Scene& scene, ObjectId& selectedObjectId);
|
||||
void ApplyPendingActions(Scene& scene, ObjectId& selectedObjectId);
|
||||
|
||||
void DrawObject(GameObject& object);
|
||||
void DrawTransform(GameObject& object);
|
||||
void DrawComponents(GameObject& object);
|
||||
void DrawComponentMenu(GameObject& object, Component& component, std::size_t index, bool removable);
|
||||
void DrawAddComponent(GameObject& object);
|
||||
|
||||
void BeginRename(const GameObject& object);
|
||||
|
||||
std::string m_Filter;
|
||||
std::string m_ComponentFilter;
|
||||
|
||||
ObjectId m_RenamingId{InvalidObjectId};
|
||||
std::string m_RenameBuffer;
|
||||
bool m_FocusRename{false};
|
||||
|
||||
ObjectId m_OpenNextFrame{InvalidObjectId};
|
||||
PendingMove m_PendingMove;
|
||||
ObjectId m_PendingDelete{InvalidObjectId};
|
||||
ObjectId m_PendingDuplicate{InvalidObjectId};
|
||||
|
||||
std::string m_ClipboardType;
|
||||
nlohmann::json m_Clipboard;
|
||||
};
|
||||
|
||||
#endif // EDITOR_SCENEINSPECTOR_H
|
||||
@@ -0,0 +1,33 @@
|
||||
#ifndef EDITOR_SHADERHOTRELOAD_H
|
||||
#define EDITOR_SHADERHOTRELOAD_H
|
||||
|
||||
#include <filesystem>
|
||||
#include <future>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
class ShaderHotReload final {
|
||||
public:
|
||||
void Configure(std::filesystem::path cooker, std::filesystem::path sourceRoot, std::filesystem::path runtimeRoot);
|
||||
[[nodiscard]] bool IsConfigured() const { return !m_Cooker.empty(); }
|
||||
|
||||
void RequestCook() { m_CookRequested = true; }
|
||||
[[nodiscard]] bool Poll(float dt);
|
||||
[[nodiscard]] bool IsCooking() const { return m_Cook.valid(); }
|
||||
[[nodiscard]] const std::string& GetLastResult() const { return m_LastResult; }
|
||||
|
||||
private:
|
||||
[[nodiscard]] bool SourcesChanged();
|
||||
void StartCook();
|
||||
|
||||
std::filesystem::path m_Cooker;
|
||||
std::filesystem::path m_SourceRoot;
|
||||
std::filesystem::path m_RuntimeRoot;
|
||||
std::unordered_map<std::string, std::filesystem::file_time_type> m_Stamps;
|
||||
std::future<int> m_Cook;
|
||||
std::string m_LastResult;
|
||||
float m_PollTimer{0.0f};
|
||||
bool m_CookRequested{false};
|
||||
};
|
||||
|
||||
#endif // EDITOR_SHADERHOTRELOAD_H
|
||||
@@ -0,0 +1,37 @@
|
||||
#ifndef EDITOR_TRANSFORMGIZMO_H
|
||||
#define EDITOR_TRANSFORMGIZMO_H
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
class Camera;
|
||||
class GameObject;
|
||||
|
||||
enum class GizmoOperation {
|
||||
Translate,
|
||||
Rotate,
|
||||
Scale,
|
||||
};
|
||||
|
||||
enum class GizmoSpace {
|
||||
World,
|
||||
Local,
|
||||
};
|
||||
|
||||
class TransformGizmo final {
|
||||
public:
|
||||
void HandleShortcuts();
|
||||
void DrawToolbar();
|
||||
bool Manipulate(GameObject& object, const Camera& camera, const glm::vec2& viewMin, const glm::vec2& viewSize);
|
||||
|
||||
[[nodiscard]] bool IsUsing() const;
|
||||
[[nodiscard]] bool IsOver() const;
|
||||
|
||||
GizmoOperation operation{GizmoOperation::Translate};
|
||||
GizmoSpace space{GizmoSpace::World};
|
||||
bool snap{false};
|
||||
float translationSnap{0.5f};
|
||||
float rotationSnapDegrees{15.0f};
|
||||
float scaleSnap{0.1f};
|
||||
};
|
||||
|
||||
#endif // EDITOR_TRANSFORMGIZMO_H
|
||||
@@ -0,0 +1,42 @@
|
||||
#ifndef EDITOR_UNDOSTACK_H
|
||||
#define EDITOR_UNDOSTACK_H
|
||||
|
||||
#include <cstddef>
|
||||
#include <deque>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <destrum/ObjectModel/ObjectId.h>
|
||||
|
||||
class Scene;
|
||||
|
||||
class UndoStack final {
|
||||
public:
|
||||
static constexpr std::size_t MaxSteps = 64;
|
||||
|
||||
void Reset(Scene& scene);
|
||||
void Rebase(Scene& scene);
|
||||
bool Record(Scene& scene);
|
||||
bool Undo(Scene& scene);
|
||||
bool Redo(Scene& scene);
|
||||
|
||||
[[nodiscard]] bool CanUndo() const { return !m_Undo.empty(); }
|
||||
[[nodiscard]] bool CanRedo() const { return !m_Redo.empty(); }
|
||||
[[nodiscard]] std::size_t UndoCount() const { return m_Undo.size(); }
|
||||
|
||||
private:
|
||||
struct Snapshot {
|
||||
std::string scene;
|
||||
ObjectId selected{InvalidObjectId};
|
||||
};
|
||||
|
||||
[[nodiscard]] static std::optional<Snapshot> Capture(Scene& scene);
|
||||
bool Restore(Scene& scene, const Snapshot& snapshot);
|
||||
|
||||
std::deque<Snapshot> m_Undo;
|
||||
std::vector<Snapshot> m_Redo;
|
||||
std::optional<Snapshot> m_Current;
|
||||
};
|
||||
|
||||
#endif // EDITOR_UNDOSTACK_H
|
||||
Reference in New Issue
Block a user