From 93d383ece0c1de2d190b78b2f0d31a8a4610d87a Mon Sep 17 00:00:00 2001 From: Maddie Slockbower Date: Wed, 18 Sep 2024 11:46:27 -0400 Subject: [PATCH] File System --- CMakeLists.txt | 13 +- External/imgui-docking/imgui.h | 2 +- Include/Core/Console.h | 288 +++++++++--------- Include/Core/Engine.h | 34 ++- Include/Core/EventSystem.h | 208 ++++++------- Include/Core/Renderer.h | 8 +- Include/Core/Window.h | 150 ++++----- Include/Editor/ConsoleWindow.h | 16 +- Include/Editor/EditorSystem.h | 58 ++-- Include/Editor/EditorWindow.h | 152 ++++----- Include/Editor/MainMenuBar.h | 26 ++ Include/Editor/Profiler.h | 54 ++-- Include/FileSystem/Asset.h | 46 +++ Include/FileSystem/FileManager.h | 91 ++++++ .../Renderer.cpp => Include/Graph/Compiler.h | 4 +- Include/Graph/Nodes/Math.h | 8 - Include/Graph/ShaderGraph.h | 11 +- Include/Project/Project.h | 35 +++ Include/Utility/Timer.h | 22 +- Source/Core/Console.cpp | 40 +-- Source/Core/Engine.cpp | 26 +- Source/Core/EventSystem.cpp | 4 +- Source/Core/Window.cpp | 72 ++--- Source/Editor/EditorSystem.cpp | 14 +- Source/Editor/EditorWindow.cpp | 20 +- Source/Editor/Profiler.cpp | 14 +- Source/Entry.cpp | 3 +- Source/FileSystem/FileManager.cpp | 259 ++++++++++++++++ Source/Graph/Compiler.cpp | 3 + Source/Graph/ShaderGraph.cpp | 64 ++-- Source/Project/Project.cpp | 169 ++++++++++ imgui.ini | 48 +-- 32 files changed, 1332 insertions(+), 630 deletions(-) create mode 100644 Include/Editor/MainMenuBar.h create mode 100644 Include/FileSystem/Asset.h create mode 100644 Include/FileSystem/FileManager.h rename Source/Core/Renderer.cpp => Include/Graph/Compiler.h (93%) create mode 100644 Include/Project/Project.h create mode 100644 Source/FileSystem/FileManager.cpp create mode 100644 Source/Graph/Compiler.cpp create mode 100644 Source/Project/Project.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 6145f76..de92036 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,6 +23,7 @@ find_package(GLEW REQUIRED) find_package(glm REQUIRED) find_package(OpenGL REQUIRED COMPONENTS OpenGL) find_package(SDL2 REQUIRED) +find_package(RapidJSON REQUIRED) if(MSVC) add_compile_options("$<$:/utf-8>") @@ -33,6 +34,7 @@ include_directories(Include) include_directories(External) # Add External Libraries +add_subdirectory(External/portable-file-dialogs) add_subdirectory(External/open-cpp-utils) add_subdirectory(External/glw) @@ -55,7 +57,6 @@ add_executable(OpenShaderDesigner Source/Core/Console.cpp Source/Core/EventSystem.cpp Source/Core/Engine.cpp - Source/Core/Renderer.cpp # Editor Source/Editor/EditorSystem.cpp @@ -68,6 +69,14 @@ add_executable(OpenShaderDesigner # Nodes Source/Graph/Nodes/Math.cpp + Include/Graph/Compiler.h + Source/Graph/Compiler.cpp + Source/FileSystem/FileManager.cpp + Include/FileSystem/FileManager.h + Include/FileSystem/Asset.h + Source/Project/Project.cpp + Include/Project/Project.h + Include/Editor/MainMenuBar.h ) target_link_libraries(OpenShaderDesigner PRIVATE @@ -75,6 +84,8 @@ target_link_libraries(OpenShaderDesigner PRIVATE GLEW::GLEW OpenGL::GL ${SDL2_LIBRARIES} + rapidjson + open-cpp-utils imgui-docking imgui-extras imnode-graph diff --git a/External/imgui-docking/imgui.h b/External/imgui-docking/imgui.h index dc5e67f..33fc040 100644 --- a/External/imgui-docking/imgui.h +++ b/External/imgui-docking/imgui.h @@ -2282,7 +2282,7 @@ struct ImGuiIO bool ConfigDragClickToInputText; // = false // [BETA] Enable turning DragXXX widgets into text input with a simple mouse click-release (without moving). Not desirable on devices without a keyboard. bool ConfigWindowsResizeFromEdges; // = true // Enable resizing of windows from their edges and from the lower-left corner. This requires (io.BackendFlags & ImGuiBackendFlags_HasMouseCursors) because it needs mouse cursor feedback. (This used to be a per-window ImGuiWindowFlags_ResizeFromAnySide flag) bool ConfigWindowsMoveFromTitleBarOnly; // = false // Enable allowing to move windows only when clicking on their title bar. Does not apply to windows without a title bar. - float ConfigMemoryCompactTimer; // = 60.0f // Timer (in seconds) to free transient windows/tables memory buffers when unused. Set to -1.0f to disable. + float ConfigMemoryCompactTimer; // = 60.0f // Timer_ (in seconds) to free transient windows/tables memory buffers when unused. Set to -1.0f to disable. // Inputs Behaviors // (other variables, ones which are expected to be tweaked within UI code, are exposed in ImGuiStyle) diff --git a/Include/Core/Console.h b/Include/Core/Console.h index 9cf0ac1..4b9e5cb 100644 --- a/Include/Core/Console.h +++ b/Include/Core/Console.h @@ -27,158 +27,160 @@ namespace OpenShaderDesigner { - class Console + +class Console +{ +public: + /** + * \brief Setting for displaying log entries. + */ + enum Settings + : uint8_t { - public: - /** - * \brief Setting for displaying log entries. - */ - enum Setting - : uint8_t - { - SHOW_TIMESTAMP = 0b00000001 - , SHOW_THREAD = 0b00000010 - , SHOW_SEVERITY = 0b00000100 - , SHOW_FILE_INFO = 0b00001000 - , WRAP_TEXT = 0b00010000 + Settings_ShowTimeStamp = 0b00000001 + , Settings_ShowThread = 0b00000010 + , Settings_Severity = 0b00000100 + , Settings_ShowFileInfo = 0b00001000 + , Settings_WrapText = 0b00010000 - , ALL_SETTINGS = 0xFF - , DEFAULT_SETTINGS = ALL_SETTINGS ^ WRAP_TEXT - }; - - /** - * \brief String representations of the settings. - */ - inline static const std::string SettingNames[] = - { - "Timestamps", "Thread IDs", "Severity", "File Info", "Wrapping" - }; - - /** - * \brief Severity levels for log entries. - */ - enum class Severity - : int - { - MESSAGE = 0, - WARNING, - ERROR, - FATAL, - ALERT, - COMMAND, - COUNT, - DEFAULT = WARNING - }; - - /** - * \brief String representations of the Severity levels. - */ - static inline const std::string Severities[] = - { - "Message", "Warning", "Error", "Fatal", "Alert", "Command" - }; - - /** - * \brief Integer to floating point color. (ImGui APIVersion) - * \param RGB The Integer color to convert. - * \return The rgba floating point color. - */ - inline static constexpr ImVec4 ImGuiColor(unsigned int RGB) - { - return { - static_cast((RGB >> 24) & 255) / 255.0f, static_cast((RGB >> 16) & 255) / 255.0f, - static_cast((RGB >> 8) & 255) / 255.0f, static_cast((RGB >> 0) & 255) / 255.0f - }; - } - - /** - * \brief Color for rendering each Severity level text in editor. - */ - inline static const ImVec4 SeverityColors[] = { - ImGuiColor(0xA4B9C4FF), ImGuiColor(0xF2C554FF), ImGuiColor(0xE57327FF), ImGuiColor(0xCC211EFF), - ImGuiColor(0x9CDCFEFF), - }; - - static std::string ThreadID() - { - std::stringstream ss; - ss << std::this_thread::get_id(); - return ss.str(); - } - - /** - * \brief Thread-Safe Log function for debugging. - * \tparam Args Variadic Arguments template for PixelLayout Parameters - * \param file The name of the file this was called from. - * \param line The line number this was called from. - * \param severity The severity level of the log entry. - * \param message A format string for the entry message. - * \param vargs Arguments for the format string. - */ - template - static void Log(const std::string& file - , const int line - , Severity severity = Severity::DEFAULT - , const std::format_string& message = "" - , Args&&... vargs); - - static void DrawMenu(); - static void DrawWindow(); - - static inline bool Open = true; - - private: - struct LogEntry - { - const std::string Message; - const Severity Severity; - const std::string File, Timestamp, Thread; - const int Line; - }; - - /** - * \brief Get a formatted Entry for printing. - * \param entry The Entry to format. - * \return The Entry formatted into a string. - */ - static std::string Format(const LogEntry& entry, Setting settings); - - /** - * \brief Command handling. - * \param command Command string to process. - */ - static void ProcessCommand(const std::string& command); - - inline static std::list EntryLog; - inline static std::mutex Lock; - inline static int Filter = static_cast(0xFFFFFFFF); - inline static Setting Settings = DEFAULT_SETTINGS; - inline static std::string Command; + , Settings_ALL = 0xFF + , Settings_Default = Settings_ALL ^ Settings_WrapText }; - template - void Console::Log( - const std::string& file - , const int line - , Severity severity - , const std::format_string& fmt - , Args&&... vargs) + /** + * \brief String representations of the settings. + */ + inline static const std::string SettingNames[] = { - auto t = std::time(nullptr); + "Timestamps", "Thread IDs", "Severity", "File Info", "Wrapping" + }; + + /** + * \brief Severity levels for log entries. + */ + enum Severity + : int + { + Message = 0, + Warning, + Error, + Fatal, + Alert, + Command, + COUNT, + DEFAULT = Warning + }; + + /** + * \brief String representations of the Severity levels. + */ + static inline const std::string Severities[] = + { + "Message", "Warning", "Error", "Fatal", "Alert", "Command" + }; + + /** + * \brief Integer to floating point color. (ImGui APIVersion) + * \param RGB The Integer color to convert. + * \return The rgba floating point color. + */ + inline static constexpr ImVec4 ImGuiColor(unsigned int RGB) + { + return { + static_cast((RGB >> 24) & 255) / 255.0f, static_cast((RGB >> 16) & 255) / 255.0f, + static_cast((RGB >> 8) & 255) / 255.0f, static_cast((RGB >> 0) & 255) / 255.0f + }; + } + + /** + * \brief Color for rendering each Severity level text in editor. + */ + inline static const ImVec4 SeverityColors[] = { + ImGuiColor(0xA4B9C4FF), ImGuiColor(0xF2C554FF), ImGuiColor(0xE57327FF), ImGuiColor(0xCC211EFF), + ImGuiColor(0x9CDCFEFF), + }; + + static std::string ThreadID() + { + std::stringstream ss; + ss << std::this_thread::get_id(); + return ss.str(); + } + + /** + * \brief Thread-Safe Log function for debugging. + * \tparam Args Variadic Arguments template for PixelLayout Parameters + * \param file The name of the file this was called from. + * \param line The line number this was called from. + * \param severity The severity level of the log entry. + * \param message A format string for the entry message. + * \param vargs Arguments for the format string. + */ + template + static void Log(const std::string& file + , const int line + , Severity severity = Severity::DEFAULT + , const std::format_string& message = "" + , Args&&... vargs); + + static void DrawMenu(); + static void DrawWindow(); + + static inline bool Open = true; + +private: + struct LogEntry + { + const std::string Message; + const Severity Severity; + const std::string File, Timestamp, Thread; + const int Line; + }; + + /** + * \brief Get a formatted Entry for printing. + * \param entry The Entry to format. + * \return The Entry formatted into a string. + */ + static std::string Format(const LogEntry& entry, uint8_t settings); + + /** + * \brief Command handling. + * \param command Command string to process. + */ + static void ProcessCommand(const std::string& command); + + inline static std::list EntryLog_; + inline static std::mutex Lock_; + inline static int Filter_ = static_cast(0xFFFFFFFF); + inline static uint8_t Settings_ = Settings_Default; + inline static std::string CommandBuffer_; +}; + +template +void Console::Log( + const std::string& file + , const int line + , Severity severity + , const std::format_string& fmt + , Args&&... vargs) +{ + auto t = std::time(nullptr); #ifdef _MSC_VER #pragma warning(disable:4996) #endif - auto tm = *std::localtime(&t); + auto tm = *std::localtime(&t); - std::lock_guard guard(Lock); - LogEntry entry{ - std::vformat(fmt.get(), std::make_format_args(vargs...)), severity, file, std::format( - "{:0>2}:{:0>2}:{:0>2}", tm.tm_hour, tm.tm_min, tm.tm_sec), - ThreadID(), line - }; - EntryLog.push_back(entry); - std::cout << Format(entry, ALL_SETTINGS) << std::endl; - } + std::lock_guard guard(Lock_); + LogEntry entry{ + std::vformat(fmt.get(), std::make_format_args(vargs...)), severity, file, std::format( + "{:0>2}:{:0>2}:{:0>2}", tm.tm_hour, tm.tm_min, tm.tm_sec), + ThreadID(), line + }; + EntryLog_.push_back(entry); + std::cout << Format(entry, Settings_ALL) << std::endl; +} + } #define Log(...) Log(__FILE__, __LINE__, __VA_ARGS__) diff --git a/Include/Core/Engine.h b/Include/Core/Engine.h index 6dc8cf9..05c65e4 100644 --- a/Include/Core/Engine.h +++ b/Include/Core/Engine.h @@ -22,25 +22,27 @@ namespace OpenShaderDesigner { - class Engine - { - public: - static void Start(const Window::Configuration& config); - static void Stop(); + +class Engine +{ +public: + static void Start(const Window::Configuration& config); + static void Stop(); - static Window& GetMainWindow() { return *MainWindow; } - private: - static void Initialize(); - static void Shutdown(); - static void Update(); + static Window& GetMainWindow() { return *MainWindow; } +private: + static void Initialize(); + static void Shutdown(); + static void Update(); - inline static Timer Frame; - inline static double _Delta; - inline static Window* MainWindow; + inline static Timer Frame; + inline static double _Delta; + inline static Window* MainWindow; - public: - inline static const double& Delta = _Delta; - }; +public: + inline static const double& Delta = _Delta; +}; + } diff --git a/Include/Core/EventSystem.h b/Include/Core/EventSystem.h index d8b1921..bd5035d 100644 --- a/Include/Core/EventSystem.h +++ b/Include/Core/EventSystem.h @@ -29,113 +29,115 @@ namespace ocu = open_cpp_utils; namespace OpenShaderDesigner { - /** - * \brief Base Event class for sending events to the Engine. - */ - struct Event - { - template - static uint8_t TypeOf() { return static_cast(ocu::unique_id()); } - - /** - * \brief Get the Event's type ID. - * \return A pointer to the Event type ID. - */ - virtual inline uint8_t GetID() const = 0; - }; - - - /** - * \brief Base EventHandler for abstraction. - */ - class _ImplEventHandler - { - virtual bool _HandleEvent(const Event* event) = 0; - - friend class EventSystem; - }; - - /** - * \brief EventHandler interface for creating custom EventHandlers - * \tparam EventType The ComponentType of Event handled by the EventHandler - */ - template - class EventHandler : private _ImplEventHandler - { - public: - using HandledType = EventType; //!< The type handled by the EventHandler - - /** - * \brief Virtual function for custom EventHandler implementations. - * \param event The Event being handled. - */ - virtual bool HandleEvent(const HandledType* event) = 0; - private: - - /** - * \brief Override for abstraction. - * \param event The Event being handled. - */ - bool _HandleEvent(const Event* event) override; - }; - - /** - * \brief EventSystem for posting Events to be handled. - */ - class EventSystem - { - public: - /** - * \brief Post an Event to be Handled. - */ - static void PostEvent(const Event*); - - /** - * \brief Register an EventHandler with the EventSystem. - * \tparam T ComponentType of Event handled by the EventHandler. - */ - template - static void RegisterHandler(EventHandler*); - - /** - * \brief Unregister an EventHandler with the EventSystem. - * \tparam T ComponentType of Event handled by the EventHandler. - */ - template - static void UnregisterHandler(EventHandler*); - - private: - inline static std::list<_ImplEventHandler*> HandlerMap[MAX_EVENT_TYPES]; - inline static std::mutex Lock; - - EventSystem(const EventSystem&) = delete; - EventSystem(EventSystem&&) = delete; - }; - + +/** + * \brief Base Event class for sending events to the Engine. + */ +struct Event +{ template - void EventSystem::UnregisterHandler(EventHandler* handler) - { - // Thread safe - std::lock_guard guard(Lock); - const uint8_t index = T::ID; - std::erase(HandlerMap[index], reinterpret_cast<_ImplEventHandler*>(handler)); - } + static uint8_t TypeOf() { return static_cast(ocu::unique_id()); } + /** + * \brief Get the Event's type ID. + * \return A pointer to the Event type ID. + */ + virtual inline uint8_t GetID() const = 0; +}; + + +/** + * \brief Base EventHandler for abstraction. + */ +class _ImplEventHandler +{ + virtual bool _HandleEvent(const Event* event) = 0; + + friend class EventSystem; +}; + +/** + * \brief EventHandler interface for creating custom EventHandlers + * \tparam EventType The ComponentType of Event handled by the EventHandler + */ +template +class EventHandler : private _ImplEventHandler +{ +public: + using HandledType = EventType; //!< The type handled by the EventHandler + + /** + * \brief Virtual function for custom EventHandler implementations. + * \param event The Event being handled. + */ + virtual bool HandleEvent(const HandledType* event) = 0; +private: + + /** + * \brief Override for abstraction. + * \param event The Event being handled. + */ + bool _HandleEvent(const Event* event) override; +}; + +/** + * \brief EventSystem for posting Events to be handled. + */ +class EventSystem +{ +public: + /** + * \brief Post an Event to be Handled. + */ + static void PostEvent(const Event*); + + /** + * \brief Register an EventHandler with the EventSystem. + * \tparam T ComponentType of Event handled by the EventHandler. + */ template - void EventSystem::RegisterHandler(EventHandler* handler) - { - // Thread safe - std::lock_guard guard(Lock); - const uint8_t index = T::ID; - HandlerMap[index].push_back(reinterpret_cast<_ImplEventHandler*>(handler)); - } + static void RegisterHandler(EventHandler*); - template - bool EventHandler::_HandleEvent(const Event *event) - { - if(EventType::ID != event->GetID()) return false; - return HandleEvent(reinterpret_cast(event)); - } + /** + * \brief Unregister an EventHandler with the EventSystem. + * \tparam T ComponentType of Event handled by the EventHandler. + */ + template + static void UnregisterHandler(EventHandler*); + +private: + inline static std::list<_ImplEventHandler*> HandlerMap_[MAX_EVENT_TYPES]; + inline static std::mutex Lock_; + + EventSystem(const EventSystem&) = delete; + EventSystem(EventSystem&&) = delete; +}; + +template +void EventSystem::UnregisterHandler(EventHandler* handler) +{ + // Thread safe + std::lock_guard guard(Lock_); + const uint8_t index = T::ID; + std::erase(HandlerMap_[index], reinterpret_cast<_ImplEventHandler*>(handler)); +} + +template +void EventSystem::RegisterHandler(EventHandler* handler) +{ + // Thread safe + std::lock_guard guard(Lock_); + const uint8_t index = T::ID; + HandlerMap_[index].push_back(reinterpret_cast<_ImplEventHandler*>(handler)); +} + +template +bool EventHandler::_HandleEvent(const Event *event) +{ + if(EventType::ID != event->GetID()) return false; + return HandleEvent(reinterpret_cast(event)); +} + } #define BeginEvent(EVENT) struct EVENT : OpenShaderDesigner::Event \ diff --git a/Include/Core/Renderer.h b/Include/Core/Renderer.h index 627fdd1..b5396d5 100644 --- a/Include/Core/Renderer.h +++ b/Include/Core/Renderer.h @@ -21,10 +21,12 @@ namespace OpenShaderDesigner { - class Renderer - { - }; +class Renderer +{ + +}; + } diff --git a/Include/Core/Window.h b/Include/Core/Window.h index b3b4e8e..5d20995 100644 --- a/Include/Core/Window.h +++ b/Include/Core/Window.h @@ -27,90 +27,92 @@ namespace ocu = open_cpp_utils; namespace OpenShaderDesigner { - BeginEvent(SDLEvent) - const SDL_Event sdl_event; - SDLEvent() : sdl_event() {} +BeginEvent(SDLEvent) + const SDL_Event sdl_event; - explicit SDLEvent(const SDL_Event &event) : sdl_event(event) {} - EndEvent + SDLEvent() : sdl_event() {} + + explicit SDLEvent(const SDL_Event &event) : sdl_event(event) {} +EndEvent - BeginEvent(BeginFrame) - EndEvent; +BeginEvent(BeginFrame) +EndEvent; - BeginEvent(SDLEventsDone) - EndEvent; +BeginEvent(SDLEventsDone) +EndEvent; - BeginEvent(EndFrame) - EndEvent; +BeginEvent(EndFrame) +EndEvent; - class Window +class Window +{ +public: + enum class VSyncMode : int { - public: - enum class VSyncMode : int - { - DISABLED = 0, - ENABLED = 1, - ADAPTIVE = -1, - DEFAULT = DISABLED, - }; - - enum class FullscreenMode : int - { - WINDOWED = 0, - FULLSCREEN = SDL_WINDOW_FULLSCREEN, - FULLSCREEN_WINDOW = SDL_WINDOW_FULLSCREEN_DESKTOP, - }; - - struct Configuration - { - struct - { - std::string Title; - } Application; - - struct - { - FullscreenMode Fullscreen; - glm::ivec2 Resolution; - VSyncMode VSync; - bool HDR; - ocu::optional Multisamples; - } Video; - - Configuration() - : Application { "App" } - , Video { FullscreenMode::WINDOWED, glm::ivec2(1280, 720), VSyncMode::DISABLED, false } - { } - }; - - inline static const Configuration DefaultConfiguration; - - explicit Window(const Configuration& config); - ~Window(); - - void HandleEvents(); - void BeginFrame(); - void EndFrame(); - - void Close() { Open = false; } - [[nodiscard]] bool IsOpen() const { return Open; } - - SDL_Window* GetHandle() { return Handle; } - [[nodiscard]] const SDL_Window* GetHandle() const { return Handle; } - - SDL_GLContext GetContext() { return Context; } - [[nodiscard]] const SDL_GLContext GetContext() const { return Context; } - - [[nodiscard]] glm::ivec2 Size() const { return Config.Video.Resolution; } - private: - Configuration Config; - SDL_Window* Handle; - SDL_GLContext Context; - bool Open; + DISABLED = 0, + ENABLED = 1, + ADAPTIVE = -1, + DEFAULT = DISABLED, }; + + enum class FullscreenMode : int + { + WINDOWED = 0, + FULLSCREEN = SDL_WINDOW_FULLSCREEN, + FULLSCREEN_WINDOW = SDL_WINDOW_FULLSCREEN_DESKTOP, + }; + + struct Configuration + { + struct + { + std::string Title; + } Application; + + struct + { + FullscreenMode Fullscreen; + glm::ivec2 Resolution; + VSyncMode VSync; + bool HDR; + ocu::optional Multisamples; + } Video; + + Configuration() + : Application { "App" } + , Video { FullscreenMode::WINDOWED, glm::ivec2(1280, 720), VSyncMode::DISABLED, false } + { } + }; + + inline static const Configuration DefaultConfiguration; + + explicit Window(const Configuration& config); + ~Window(); + + void HandleEvents(); + void BeginFrame(); + void EndFrame(); + + void Close() { Open_ = false; } + [[nodiscard]] bool IsOpen() const { return Open_; } + + SDL_Window* GetHandle() { return Handle_; } + [[nodiscard]] const SDL_Window* GetHandle() const { return Handle_; } + + SDL_GLContext GetContext() { return Context_; } + [[nodiscard]] const SDL_GLContext GetContext() const { return Context_; } + + [[nodiscard]] glm::ivec2 Size() const { return Config_.Video.Resolution; } +private: + Configuration Config_; + SDL_Window* Handle_; + SDL_GLContext Context_; + bool Open_; +}; + } diff --git a/Include/Editor/ConsoleWindow.h b/Include/Editor/ConsoleWindow.h index b639016..ec5bed9 100644 --- a/Include/Editor/ConsoleWindow.h +++ b/Include/Editor/ConsoleWindow.h @@ -21,16 +21,16 @@ namespace OpenShaderDesigner { - class ConsoleWindow : public EditorWindow - { - public: - ConsoleWindow(); +class ConsoleWindow : public EditorWindow +{ +public: + ConsoleWindow(); - void DrawMenu() override; - void DrawWindow() override; + void DrawMenu() override; + void DrawWindow() override; - private: - }; +private: +}; } // OpenShaderDesigner diff --git a/Include/Editor/EditorSystem.h b/Include/Editor/EditorSystem.h index 521af8a..074a09a 100644 --- a/Include/Editor/EditorSystem.h +++ b/Include/Editor/EditorSystem.h @@ -21,41 +21,51 @@ #include #include +#include #define MAX_EDITORS 256 namespace OpenShaderDesigner { - class EditorSystem + +class EditorSystem +{ +public: + using WindowID = uint64_t; + + template + static WindowID ID() { return open_cpp_utils::unique_id(); } + + template + static T* Open() { T* window; (window = Get())->Open(); return window; } + + template + static T* Close() { T* window; (window = Get())->Close(); return window; } + + template + static T* Get() { - public: - using WindowID = uint64_t; + T* window = reinterpret_cast(Windows_[ID()]); + if(window == nullptr) Windows_[ID()] = window = new T(); + return window; + } - template - static WindowID ID() { return open_cpp_utils::unique_id(); } + template + static T* SetMainMenuBar() { delete MainMenuBar_; T* bar = new T(); MainMenuBar_ = bar; return bar; } - template - static T* Open() { T* window; (window = Get())->Open(); return window; } + template + static T* GetMainMenuBar() { return static_cast(MainMenuBar_); } - template - static T* Close() { T* window; (window = Get())->Close(); return window; } + static void Initialize(); + static void Draw(); + static void Shutdown(); + static void HandleEvents(SDL_Event* event); - template - static T* Get() - { - T* window = reinterpret_cast(Windows[ID()]); - if(window == nullptr) Windows[ID()] = window = new T(); - return window; - } +private: + inline static EditorWindow* Windows_[MAX_EDITORS] { nullptr }; + inline static MainMenuBar* MainMenuBar_ = nullptr; +}; - static void Initialize(); - static void Draw(); - static void Shutdown(); - static void HandleEvents(SDL_Event* event); - - private: - inline static EditorWindow* Windows[MAX_EDITORS] { nullptr }; - }; } diff --git a/Include/Editor/EditorWindow.h b/Include/Editor/EditorWindow.h index ba6dd29..c7e99d2 100644 --- a/Include/Editor/EditorWindow.h +++ b/Include/Editor/EditorWindow.h @@ -21,85 +21,87 @@ namespace OpenShaderDesigner { + +/** + * \brief EditorWindow class for wrapping ImGui window functionality. + */ +class EditorWindow +{ +public: /** - * \brief EditorWindow class for wrapping ImGui window functionality. + * \brief Open the EditorWindow. */ - class EditorWindow + void Open(); + + /** + * \brief Draw the EditorWindow. + */ + void Draw(); + + /** + * \brief Close the EditorWindow. + */ + void Close(); + + /** + * \brief Check if the EditorWindow is open. + * \return + */ + [[nodiscard]] bool IsOpen() const { return bOpen_; } + + const std::string Title; //!< Title for the EditorWindow. + + void SetFlags(ImGuiWindowFlags flags) { Flags_ |= flags; } + void ClearFlags(ImGuiWindowFlags flags) { Flags_ &= ~flags; } + void ToggleFlags(ImGuiWindowFlags flags) { Flags_ ^= flags; } + [[nodiscard]] bool CheckFlag(ImGuiWindowFlags flag) const { return Flags_ & flag; } + + [[nodiscard]] bool HasMenuBar() const { return CheckFlag(ImGuiWindowFlags_MenuBar); } + +protected: + ~EditorWindow() = default; + EditorWindow(const std::string& title + , ImGuiWindowFlags flags); + + /** + * \brief OnOpen callback for when the EditorWindow is opened. + */ + virtual void OnOpen() { - public: - /** - * \brief Open the EditorWindow. - */ - void Open(); - - /** - * \brief Draw the EditorWindow. - */ - void Draw(); - - /** - * \brief Close the EditorWindow. - */ - void Close(); - - /** - * \brief Check if the EditorWindow is open. - * \return - */ - [[nodiscard]] bool IsOpen() const { return bOpen; } - - const std::string Title; //!< Title for the EditorWindow. - - void SetFlags(ImGuiWindowFlags flags) { Flags |= flags; } - void ClearFlags(ImGuiWindowFlags flags) { Flags &= ~flags; } - void ToggleFlags(ImGuiWindowFlags flags) { Flags ^= flags; } - [[nodiscard]] bool CheckFlag(ImGuiWindowFlags flag) const { return Flags & flag; } - - [[nodiscard]] bool HasMenuBar() const { return CheckFlag(ImGuiWindowFlags_MenuBar); } - - protected: - ~EditorWindow() = default; - EditorWindow(const std::string& title - , ImGuiWindowFlags flags); - - /** - * \brief OnOpen callback for when the EditorWindow is opened. - */ - virtual void OnOpen() - { - }; - - /** - * \brief DrawWindow function for when the EditorWindow is being drawn. - */ - virtual void DrawWindow() - { - }; - - /** - * \brief DrawMenu function for when the EditorWindow Menu is being drawn. - */ - virtual void DrawMenu() - { - }; - - /** - * \brief OnClose callback for when the EditorWindow is closed. - */ - virtual void OnClose() - { - }; - - private: - EditorWindow(const EditorWindow&) = delete; - - EditorWindow(EditorWindow&&) = delete; - - int Flags; - bool bOpen; - - friend class EditorSystem; }; + + /** + * \brief DrawWindow function for when the EditorWindow is being drawn. + */ + virtual void DrawWindow() + { + }; + + /** + * \brief DrawMenu function for when the EditorWindow Menu is being drawn. + */ + virtual void DrawMenu() + { + }; + + /** + * \brief OnClose callback for when the EditorWindow is closed. + */ + virtual void OnClose() + { + }; + +private: + EditorWindow(const EditorWindow&) = delete; + + EditorWindow(EditorWindow&&) = delete; + + int Flags_; + bool bOpen_; + + friend class EditorSystem; +}; + } diff --git a/Include/Editor/MainMenuBar.h b/Include/Editor/MainMenuBar.h new file mode 100644 index 0000000..d1e71bb --- /dev/null +++ b/Include/Editor/MainMenuBar.h @@ -0,0 +1,26 @@ +// +// Created by Maddie on 9/14/2024. +// + +#ifndef MAINMENUBAR_H +#define MAINMENUBAR_H + +#include + +namespace OpenShaderDesigner +{ + +class MainMenuBar +{ +public: + virtual void DrawMenuBar() = 0; + + friend class EditorSystem; + +private: + void Draw() { ImGui::BeginMainMenuBar(); DrawMenuBar(); ImGui::EndMainMenuBar(); } +}; + +} + +#endif //MAINMENUBAR_H diff --git a/Include/Editor/Profiler.h b/Include/Editor/Profiler.h index 834f5e8..d408e8d 100644 --- a/Include/Editor/Profiler.h +++ b/Include/Editor/Profiler.h @@ -24,37 +24,37 @@ namespace OpenShaderDesigner { - class Profiler - : public EditorWindow - , public EventHandler - , public EventHandler +class Profiler + : public EditorWindow + , public EventHandler + , public EventHandler +{ +public: + Profiler(); + ~Profiler(); + + void DrawWindow() override; + + bool HandleEvent(const EventHandler::HandledType* event) override; + bool HandleEvent(const EventHandler::HandledType* event) override; + +private: + enum { - public: - Profiler(); - ~Profiler(); + EVENTS = 0 + , RENDER + , EDITOR + , END - void DrawWindow() override; - - bool HandleEvent(const EventHandler::HandledType* event) override; - bool HandleEvent(const EventHandler::HandledType* event) override; - - private: - enum - { - EVENTS = 0 - , RENDER - , EDITOR - , END - - , COUNT - , LAST = COUNT - 1 - }; - - uint64_t Frame; - double Deltas[COUNT]; - Timer Timer; + , COUNT + , LAST = COUNT - 1 }; + uint64_t Frame_; + double Deltas_[COUNT]; + Timer Timer_; +}; + } diff --git a/Include/FileSystem/Asset.h b/Include/FileSystem/Asset.h new file mode 100644 index 0000000..497b030 --- /dev/null +++ b/Include/FileSystem/Asset.h @@ -0,0 +1,46 @@ +// ===================================================================================================================== +// Copyright 2024 Medusa Slockbower +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ===================================================================================================================== + +#ifndef ASSET_H +#define ASSET_H + +#include + +namespace ocu = open_cpp_utils; + +namespace OpenShaderDesigner +{ + +class Asset +{ +public: + Asset() : Dirty_(false) { } + + bool Dirty() const { return Dirty_; } + + virtual void Open() = 0; + virtual void Load(const std::filesystem::path& path) = 0; + virtual void Save(const std::filesystem::path& path) { Dirty_ = false; }; + +protected: + void MakeDirty() { Dirty_ = true; } + +private: + bool Dirty_; +}; + +} + +#endif //ASSET_H diff --git a/Include/FileSystem/FileManager.h b/Include/FileSystem/FileManager.h new file mode 100644 index 0000000..754f333 --- /dev/null +++ b/Include/FileSystem/FileManager.h @@ -0,0 +1,91 @@ +// ===================================================================================================================== +// Copyright 2024 Medusa Slockbower +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ===================================================================================================================== + +#ifndef FILESYSTEM_H +#define FILESYSTEM_H + +#include +#include + +#include +#include + + +namespace ocu = open_cpp_utils; + +namespace OpenShaderDesigner +{ + +class FileManager : public EditorWindow +{ +public: + using FileSystem = ocu::filesystem; + using File = FileSystem::file; + using Path = std::filesystem::path; + using FileID = FileSystem::file_id; + using FileType = uint32_t; + friend FileSystem; + + enum FileType_ + { + FileType_Folder = 0 + , FileType_Project + }; + + inline static ocu::map ExtensionMap = { + { "", FileType_Folder } + , { ".sgp", FileType_Project } + }; + +private: + static Asset* load(const Path& file); + static Asset* import(const Path& src, const Path& dst); + static Asset* create(const Path& file); + +public: + FileManager(); + + void DrawMenu() override; + void DrawWindow() override; + + FileID CurrentDirectory() const { return CurrentDirectory_; } + void CurrentDirectory(FileID id) { CurrentDirectory_ = id; } + + FileID Create(const std::string& name) { return Filesystem_.create(name, CurrentDirectory_); } + FileID Import(const Path& path) { return Filesystem_.import(path, CurrentDirectory_); } + FileID LoadDirectory(const Path& path) { return Filesystem_.load_directory(path); } + void CloseDirectory(FileID dir) { Filesystem_.close_directory(dir); } + + FileID Get(const Path& path) const { return Filesystem_.find(path); } + File& Get(FileID id) { return Filesystem_[id]; } + const File& Get(FileID id) const { return Filesystem_[id]; } + + FileID Parent(FileID id) const { return Filesystem_.parent(id); } + + bool AnyDirty(); + void SaveAll(); + + static Path GetHomeDirectory(); +private: + FileSystem Filesystem_; + FileID CurrentDirectory_, Selected_; + bool Rename_, FocusRename_; + std::string RenameBuffer_; +}; + +} + + +#endif //FILESYSTEM_H diff --git a/Source/Core/Renderer.cpp b/Include/Graph/Compiler.h similarity index 93% rename from Source/Core/Renderer.cpp rename to Include/Graph/Compiler.h index 9aede7c..f2a5130 100644 --- a/Source/Core/Renderer.cpp +++ b/Include/Graph/Compiler.h @@ -13,5 +13,7 @@ // limitations under the License. // ===================================================================================================================== +#ifndef COMPILER_H +#define COMPILER_H -#include +#endif //COMPILER_H diff --git a/Include/Graph/Nodes/Math.h b/Include/Graph/Nodes/Math.h index b396951..9d02148 100644 --- a/Include/Graph/Nodes/Math.h +++ b/Include/Graph/Nodes/Math.h @@ -50,8 +50,6 @@ struct Integer : public Node [[nodiscard]] Node* Copy(ShaderGraph& graph) const override; void Inspect() override; - - ValueType Value; }; RegisterNode("Math/Constants/Integer", Integer); @@ -68,8 +66,6 @@ struct UnsignedInteger : public Node [[nodiscard]] Node* Copy(ShaderGraph& graph) const override; void Inspect() override; - - ValueType Value; }; RegisterNode("Math/Constants/Unsigned Integer", UnsignedInteger); @@ -86,8 +82,6 @@ struct Scalar : public Node [[nodiscard]] Node* Copy(ShaderGraph& graph) const override; void Inspect() override; - - ValueType Value; }; RegisterNode("Math/Constants/Scalar", Scalar); @@ -104,8 +98,6 @@ struct Vector : public Node [[nodiscard]] Node* Copy(ShaderGraph& graph) const override; void Inspect() override; - - ValueType Value; }; RegisterNode("Math/Constants/Vector", Vector); diff --git a/Include/Graph/ShaderGraph.h b/Include/Graph/ShaderGraph.h index e2fbf91..2383bde 100644 --- a/Include/Graph/ShaderGraph.h +++ b/Include/Graph/ShaderGraph.h @@ -197,15 +197,16 @@ namespace OpenShaderDesigner // History Functionality void PushState(); void PopState(); - GraphState& GetState() { return State; } + GraphState& GetState() { return State_; } private: - bool GrabFocus; + bool GrabFocus_; - GraphState State; - std::stack History; + GraphState State_; + std::stack History_; - ImVec2 ContextMenuPosition; + ImVec2 ContextMenuPosition_; + friend class Inspector; }; diff --git a/Include/Project/Project.h b/Include/Project/Project.h new file mode 100644 index 0000000..fb116fc --- /dev/null +++ b/Include/Project/Project.h @@ -0,0 +1,35 @@ +// +// Created by Maddie on 9/14/2024. +// + +#ifndef PROJECT_H +#define PROJECT_H + +#include +#include + +namespace OpenShaderDesigner +{ + +class Project : public MainMenuBar, public Asset +{ +public: + Project(); + virtual ~Project(); + + void DrawMenuBar() override; + + void Open() override; + void Load(const FileManager::Path& path) override; + void Save(const FileManager::Path& path) override; + void Create(const FileManager::Path& path); + +private: + void Reset(); + + FileManager::FileID ProjectFile_; +}; + +} + +#endif //PROJECT_H diff --git a/Include/Utility/Timer.h b/Include/Utility/Timer.h index 429f121..bb1b7a4 100644 --- a/Include/Utility/Timer.h +++ b/Include/Utility/Timer.h @@ -20,18 +20,20 @@ namespace OpenShaderDesigner { - class Timer - { - public: - Timer() : Start(std::chrono::high_resolution_clock::now()) { } + +class Timer +{ +public: + Timer() : Start(std::chrono::high_resolution_clock::now()) { } - void Reset() { Start = std::chrono::high_resolution_clock::now(); } + void Reset() { Start = std::chrono::high_resolution_clock::now(); } - [[nodiscard]] double Poll() const - { return std::chrono::duration(std::chrono::high_resolution_clock::now() - Start).count(); } - private: - std::chrono::high_resolution_clock::time_point Start; - }; + [[nodiscard]] double Poll() const + { return std::chrono::duration(std::chrono::high_resolution_clock::now() - Start).count(); } +private: + std::chrono::high_resolution_clock::time_point Start; +}; + } #endif //TIMER_H diff --git a/Source/Core/Console.cpp b/Source/Core/Console.cpp index c4418c0..aa4676b 100644 --- a/Source/Core/Console.cpp +++ b/Source/Core/Console.cpp @@ -20,16 +20,16 @@ using namespace OpenShaderDesigner; void Console::DrawMenu() { - std::lock_guard guard(Lock); + std::lock_guard guard(Lock_); if(ImGui::BeginMenu("\uf0e5 Settings")) { for(uint8_t setting = 0; setting < sizeof(SettingNames) / sizeof(std::string); ++setting) { int flag = 0x1 << setting; - if(ImGui::MenuItem(SettingNames[setting].c_str(), nullptr, Settings & flag)) + if(ImGui::MenuItem(SettingNames[setting].c_str(), nullptr, Settings_ & flag)) { - Settings = static_cast(Settings ^ flag); + Settings_ = Settings_ ^ flag; } } @@ -41,9 +41,9 @@ void Console::DrawMenu() for(int severity = 0; severity < static_cast(Severity::COUNT); ++severity) { int flag = 0x1 << severity; - if(ImGui::MenuItem(Severities[severity].c_str(), NULL, Filter & flag)) + if(ImGui::MenuItem(Severities[severity].c_str(), NULL, Filter_ & flag)) { - Filter = Filter ^ flag; + Filter_ = Filter_ ^ flag; } } @@ -53,23 +53,23 @@ void Console::DrawMenu() void Console::DrawWindow() { - std::lock_guard guard(Lock); + std::lock_guard guard(Lock_); - const auto& Log = EntryLog; + const auto& Log = EntryLog_; const float padding = ImGui::GetStyle().ItemSpacing.y + ImGui::GetFrameHeightWithSpacing(); if(ImGui::BeginChild("##scrolling", ImVec2(0, -padding), ImGuiChildFlags_AlwaysAutoResize | ImGuiChildFlags_AlwaysUseWindowPadding | ImGuiChildFlags_AutoResizeY - , ImGuiWindowFlags_AlwaysVerticalScrollbar | (Settings & WRAP_TEXT ? ImGuiWindowFlags_None : ImGuiWindowFlags_AlwaysHorizontalScrollbar))) + , ImGuiWindowFlags_AlwaysVerticalScrollbar | (Settings_ & Settings_WrapText ? ImGuiWindowFlags_None : ImGuiWindowFlags_AlwaysHorizontalScrollbar))) { for(const LogEntry& entry : Log) { int flag = 0x1 << static_cast(entry.Severity); - if((flag & Filter) == 0) continue; + if((flag & Filter_) == 0) continue; ImGui::PushStyleColor(ImGuiCol_Text, SeverityColors[static_cast(entry.Severity)]); - if(Settings & WRAP_TEXT) ImGui::TextWrapped("%s", Format(entry, Settings).c_str()); - else ImGui::Text("%s", Format(entry, Settings).c_str()); + if(Settings_ & Settings_WrapText) ImGui::TextWrapped("%s", Format(entry, Settings_).c_str()); + else ImGui::Text("%s", Format(entry, Settings_).c_str()); ImGui::PopStyleColor(); } @@ -80,23 +80,23 @@ void Console::DrawWindow() ImGui::Text(">"); ImGui::SameLine(); ImGui::SetNextItemWidth(ImGui::GetWindowWidth() - ImGui::GetCursorPosX() - ImGui::GetStyle().WindowPadding.x); - if(ImGui::InputText("##commandline", &Command, ImGuiInputTextFlags_EnterReturnsTrue)) + if(ImGui::InputText("##commandline", &CommandBuffer_, ImGuiInputTextFlags_EnterReturnsTrue)) { - ProcessCommand(Command); - Command.clear(); + ProcessCommand(CommandBuffer_); + CommandBuffer_.clear(); ImGui::SetKeyboardFocusHere(-1); } } -std::string Console::Format(const LogEntry& entry, Setting settings) +std::string Console::Format(const LogEntry& entry, uint8_t settings) { std::string severity = std::format("<{}>", Severities[static_cast(entry.Severity)]); std::string message; // Get Timestamp and Thread bits. - const bool showTimestamp = (settings & SHOW_TIMESTAMP); - const bool showThreadID = (settings & SHOW_THREAD) && entry.Severity != Severity::COMMAND; + const bool showTimestamp = (settings & Settings_ShowTimeStamp); + const bool showThreadID = (settings & Settings_ShowThread) && entry.Severity != Severity::Command; const bool check1 = showTimestamp || showThreadID; // Print Timestamp and/or Thread if enabled. @@ -104,8 +104,8 @@ std::string Console::Format(const LogEntry& entry, Setting settings) if(showThreadID) message += std::format("Thread #{:0>3} | ", entry.Thread); // Get Severity and File bits. - const bool showSeverity = (settings & SHOW_SEVERITY) && entry.Severity != Severity::COMMAND; - const bool showFile = (settings & SHOW_FILE_INFO) && entry.Severity != Severity::COMMAND; + const bool showSeverity = (settings & Settings_Severity) && entry.Severity != Severity::Command; + const bool showFile = (settings & Settings_ShowFileInfo) && entry.Severity != Severity::Command; const bool check2 = showSeverity || showFile; // Print Severity and/or File if enabled. @@ -113,7 +113,7 @@ std::string Console::Format(const LogEntry& entry, Setting settings) if(showFile) message += std::format("{}({})", entry.File, entry.Line); // Print separator if any are enabled - if(check1 || check2) message += entry.Severity == Severity::COMMAND ? "> " : ": "; + if(check1 || check2) message += entry.Severity == Severity::Command ? "> " : ": "; // Add message. message += entry.Message; diff --git a/Source/Core/Engine.cpp b/Source/Core/Engine.cpp index bd1ab0c..8e33745 100644 --- a/Source/Core/Engine.cpp +++ b/Source/Core/Engine.cpp @@ -20,18 +20,22 @@ #include #include +#include + #include +#include "Project/Project.h" + void OpenShaderDesigner::Engine::Start(const Window::Configuration& config) { - Console::Log(Console::Severity::ALERT, "Starting {}", config.Application.Title); + Console::Log(Console::Severity::Alert, "Starting {}", config.Application.Title); - Console::Log(Console::Severity::MESSAGE, "Creating Main Window"); + Console::Log(Console::Message, "Creating Main Window"); MainWindow = new Window(config); Initialize(); - Console::Log(Console::Severity::MESSAGE, "Starting Main Loop"); + Console::Log(Console::Message, "Starting Main Loop"); while(MainWindow->IsOpen()) { Update(); @@ -47,20 +51,26 @@ void OpenShaderDesigner::Engine::Stop() void OpenShaderDesigner::Engine::Initialize() { - Console::Log(Console::Severity::MESSAGE, "Initializing Engine"); + Console::Log(Console::Message, "Initializing Engine"); - Console::Log(Console::Severity::MESSAGE, "Initializing Editor"); + Console::Log(Console::Message, "Initializing Editor"); EditorSystem::Initialize(); - Console::Log(Console::Severity::MESSAGE, "Opening Console"); + Console::Log(Console::Message, "Opening Console"); EditorSystem::Open(); - Console::Log(Console::Severity::MESSAGE, "Opening Profiler"); + Console::Log(Console::Message, "Opening Profiler"); EditorSystem::Open(); - Console::Log(Console::Severity::MESSAGE, "Opening Shader Graph"); + Console::Log(Console::Message, "Opening File Manager"); + EditorSystem::Open(); + + Console::Log(Console::Message, "Opening Shader Graph"); EditorSystem::Open(); EditorSystem::Open(); + + Console::Log(Console::Message, "Setting up Project"); + EditorSystem::SetMainMenuBar(); } void OpenShaderDesigner::Engine::Shutdown() diff --git a/Source/Core/EventSystem.cpp b/Source/Core/EventSystem.cpp index f4da3e9..9400d2e 100644 --- a/Source/Core/EventSystem.cpp +++ b/Source/Core/EventSystem.cpp @@ -23,11 +23,11 @@ using namespace OpenShaderDesigner; void EventSystem::PostEvent(const Event* event) { // Thread safe - std::lock_guard guard(Lock); + std::lock_guard guard(Lock_); // Alert Handlers const int index = event->GetID(); - for(_ImplEventHandler* handler : HandlerMap[index]) + for(_ImplEventHandler* handler : HandlerMap_[index]) { if(handler->_HandleEvent(event)) break; } diff --git a/Source/Core/Window.cpp b/Source/Core/Window.cpp index 15b8867..695f877 100644 --- a/Source/Core/Window.cpp +++ b/Source/Core/Window.cpp @@ -22,10 +22,10 @@ using namespace OpenShaderDesigner; Window::Window(const Configuration& config) - : Config(config) + : Config_(config) { - int flags = static_cast(Config.Video.Fullscreen) | SDL_WINDOW_OPENGL; - flags |= Config.Video.Fullscreen == FullscreenMode::WINDOWED ? SDL_WINDOW_RESIZABLE : 0; + int flags = static_cast(Config_.Video.Fullscreen) | SDL_WINDOW_OPENGL; + flags |= Config_.Video.Fullscreen == FullscreenMode::WINDOWED ? SDL_WINDOW_RESIZABLE : 0; SDL_Init(SDL_INIT_EVERYTHING & ~SDL_INIT_AUDIO); @@ -40,54 +40,54 @@ Window::Window(const Configuration& config) SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 6); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); - if(Config.Video.HDR) + if(Config_.Video.HDR) { - SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 16); - SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 16); - SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 16); - SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 16); + SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 10); + SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 10); + SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 10); + SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 2); SDL_GL_SetAttribute(SDL_GL_FLOATBUFFERS, SDL_TRUE); } - if(Config.Video.Multisamples()) + if(Config_.Video.Multisamples()) { SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, SDL_TRUE); - SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, Config.Video.Multisamples); + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, Config_.Video.Multisamples); } - if((Handle = SDL_CreateWindow( - Config.Application.Title.c_str(), + if((Handle_ = SDL_CreateWindow( + Config_.Application.Title.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, - Config.Video.Resolution.x, Config.Video.Resolution.y, + Config_.Video.Resolution.x, Config_.Video.Resolution.y, flags)) == nullptr) { - Console::Log(Console::Severity::FATAL, "Failed to create SDL Window: {}", SDL_GetError()); + Console::Log(Console::Severity::Fatal, "Failed to create SDL Window: {}", SDL_GetError()); assert(false); return; } - Context = SDL_GL_CreateContext(Handle); + Context_ = SDL_GL_CreateContext(Handle_); - if(Context == nullptr) + if(Context_ == nullptr) { - Console::Log(Console::Severity::FATAL, "Failed to create OpenGL Context: {}", SDL_GetError()); - SDL_DestroyWindow(Handle); + Console::Log(Console::Severity::Fatal, "Failed to create OpenGL Context: {}", SDL_GetError()); + SDL_DestroyWindow(Handle_); assert(false); return; } - if(SDL_GL_MakeCurrent(Handle, Context)) + if(SDL_GL_MakeCurrent(Handle_, Context_)) { - Console::Log(Console::Severity::FATAL, "Failed to set OpenGL Context: {}", SDL_GetError()); - SDL_GL_DeleteContext(Context); - SDL_DestroyWindow(Handle); + Console::Log(Console::Severity::Fatal, "Failed to set OpenGL Context: {}", SDL_GetError()); + SDL_GL_DeleteContext(Context_); + SDL_DestroyWindow(Handle_); assert(false); return; } // Set VSync Mode - SDL_GL_SetSwapInterval(static_cast(Config.Video.VSync)); + SDL_GL_SetSwapInterval(static_cast(Config_.Video.VSync)); // Enable experimental features glewExperimental = GL_TRUE; @@ -96,9 +96,9 @@ Window::Window(const Configuration& config) GLenum error; if((error = glewInit()) != GLEW_OK) { - Console::Log(Console::Severity::FATAL, "Failed to Initialize GLEW: {}", reinterpret_cast(glewGetErrorString(error))); - SDL_GL_DeleteContext(Context); - SDL_DestroyWindow(Handle); + Console::Log(Console::Severity::Fatal, "Failed to Initialize GLEW: {}", reinterpret_cast(glewGetErrorString(error))); + SDL_GL_DeleteContext(Context_); + SDL_DestroyWindow(Handle_); assert(false); return; } @@ -108,22 +108,22 @@ Window::Window(const Configuration& config) glDisable(GL_DEPTH_TEST); glClearColor(0, 0, 0, 1); glClear(GL_COLOR_BUFFER_BIT); - SDL_GL_SwapWindow(Handle); + SDL_GL_SwapWindow(Handle_); // Set running - Open = true; + Open_ = true; const char* glVersion = reinterpret_cast(glGetString(GL_VERSION)); const char* glewVersion = reinterpret_cast(glewGetString(GLEW_VERSION)); SDL_version sdlVersion; SDL_GetVersion(&sdlVersion); - Console::Log(Console::Severity::ALERT, "Initialized SDL ({}.{}.{})", sdlVersion.major, sdlVersion.minor, sdlVersion.patch); - Console::Log(Console::Severity::ALERT, "Running OpenGL ({}), GLEW ({})", glVersion, glewVersion); + Console::Log(Console::Severity::Alert, "Initialized SDL ({}.{}.{})", sdlVersion.major, sdlVersion.minor, sdlVersion.patch); + Console::Log(Console::Severity::Alert, "Running OpenGL ({}), GLEW ({})", glVersion, glewVersion); } Window::~Window() { - SDL_GL_DeleteContext(Context); - SDL_DestroyWindow(Handle); + SDL_GL_DeleteContext(Context_); + SDL_DestroyWindow(Handle_); SDL_Quit(); } @@ -147,8 +147,8 @@ void Window::HandleEvents() switch(event.window.event) { case SDL_WINDOWEVENT_SIZE_CHANGED: - Config.Video.Resolution.x = event.window.data1; - Config.Video.Resolution.y = event.window.data2; + Config_.Video.Resolution.x = event.window.data1; + Config_.Video.Resolution.y = event.window.data2; break; default: break; @@ -170,14 +170,14 @@ void Window::BeginFrame() HandleEvents(); glBindFramebuffer(GL_FRAMEBUFFER, 0); - glViewport(0, 0, Config.Video.Resolution.x, Config.Video.Resolution.y); + glViewport(0, 0, Config_.Video.Resolution.x, Config_.Video.Resolution.y); glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); } void Window::EndFrame() { - SDL_GL_SwapWindow(Handle); + SDL_GL_SwapWindow(Handle_); OpenShaderDesigner::EndFrame event; EventSystem::PostEvent(&event); diff --git a/Source/Editor/EditorSystem.cpp b/Source/Editor/EditorSystem.cpp index f4dadfa..8c40a07 100644 --- a/Source/Editor/EditorSystem.cpp +++ b/Source/Editor/EditorSystem.cpp @@ -30,7 +30,7 @@ void EditorSystem::Initialize() { Window& Window = Engine::GetMainWindow(); - Console::Log(Console::Severity::ALERT, "Initializing Dear ImGUI"); + Console::Log(Console::Severity::Alert, "Initializing Dear ImGUI"); IMGUI_CHECKVERSION(); ImGui::CreateContext(); @@ -136,7 +136,7 @@ void EditorSystem::Initialize() ImGui_ImplSDL2_InitForOpenGL(Window.GetHandle(), Window.GetContext()); ImGui_ImplOpenGL3_Init("#version 460 core"); - Console::Log(Console::Severity::ALERT, "Initialized ImGui ({})", IMGUI_VERSION); + Console::Log(Console::Severity::Alert, "Initialized ImGui ({})", IMGUI_VERSION); } void EditorSystem::Draw() @@ -152,11 +152,16 @@ void EditorSystem::Draw() ImGui::ResetMouseDragDelta(); } + if(MainMenuBar_) + { + MainMenuBar_->Draw(); + } + ImGui::ShowDemoWindow(); for (int i = 0; i < MAX_EDITORS; ++i) { - EditorWindow* editor = Windows[i]; + EditorWindow* editor = Windows_[i]; if(editor == nullptr || !editor->IsOpen()) continue; editor->Draw(); } @@ -168,6 +173,9 @@ void EditorSystem::Draw() void EditorSystem::Shutdown() { + delete MainMenuBar_; + for(auto it : Windows_) delete it; + // Shutdown ImGui ImGui_ImplOpenGL3_Shutdown(); ImGui_ImplSDL2_Shutdown(); diff --git a/Source/Editor/EditorWindow.cpp b/Source/Editor/EditorWindow.cpp index 06ff44d..ebe7153 100644 --- a/Source/Editor/EditorWindow.cpp +++ b/Source/Editor/EditorWindow.cpp @@ -19,15 +19,15 @@ using namespace OpenShaderDesigner; void EditorWindow::Open() { - if(bOpen) return; - bOpen = true; + if(bOpen_) return; + bOpen_ = true; OnOpen(); } void EditorWindow::Draw() { - const bool prev = bOpen; - if(ImGui::Begin(Title.c_str(), &bOpen, Flags)) + const bool prev = bOpen_; + if(ImGui::Begin(Title.c_str(), &bOpen_, Flags_)) { if(HasMenuBar()) { @@ -43,24 +43,24 @@ void EditorWindow::Draw() } ImGui::End(); - if(bOpen != prev) + if(bOpen_ != prev) { - bOpen ? OnOpen() : OnClose(); + bOpen_ ? OnOpen() : OnClose(); } } void EditorWindow::Close() { - if(!bOpen) return; - bOpen = false; + if(!bOpen_) return; + bOpen_ = false; OnClose(); } EditorWindow::EditorWindow(const std::string &title, ImGuiWindowFlags flags) : Title(title) - , Flags(flags) - , bOpen(false) + , Flags_(flags) + , bOpen_(false) { } \ No newline at end of file diff --git a/Source/Editor/Profiler.cpp b/Source/Editor/Profiler.cpp index b0572f2..68b06c4 100644 --- a/Source/Editor/Profiler.cpp +++ b/Source/Editor/Profiler.cpp @@ -19,8 +19,8 @@ using namespace OpenShaderDesigner; Profiler::Profiler() : EditorWindow("\uf214 Profiler", 0) - , Frame(0), Deltas{ 0 } - , Timer() + , Frame_(0), Deltas_{ 0 } + , Timer_() { EventSystem::RegisterHandler(this); EventSystem::RegisterHandler(this); @@ -34,19 +34,19 @@ Profiler::~Profiler() void Profiler::DrawWindow() { - ImGui::Text("Frame #%d", Frame); - ImGui::Text("FPS: %07.02f (%06.02f ms)", 1.0 / Deltas[LAST], 1000.0 * Deltas[LAST]); + ImGui::Text("Frame #%d", Frame_); + ImGui::Text("FPS: %07.02f (%06.02f ms)", 1.0 / Deltas_[LAST], 1000.0 * Deltas_[LAST]); } bool Profiler::HandleEvent(const EventHandler::HandledType* event) { - ++Frame; - Timer.Reset(); + ++Frame_; + Timer_.Reset(); return false; } bool Profiler::HandleEvent(const EventHandler::HandledType* event) { - Deltas[END] = Timer.Poll(); + Deltas_[END] = Timer_.Poll(); return false; } diff --git a/Source/Entry.cpp b/Source/Entry.cpp index 4fe0c9a..3d99568 100644 --- a/Source/Entry.cpp +++ b/Source/Entry.cpp @@ -15,6 +15,7 @@ #include #include +#include int main(int, char**) { @@ -30,4 +31,4 @@ int main(int, char**) Engine::Start(config); return 0; -} \ No newline at end of file +} diff --git a/Source/FileSystem/FileManager.cpp b/Source/FileSystem/FileManager.cpp new file mode 100644 index 0000000..30f2b3f --- /dev/null +++ b/Source/FileSystem/FileManager.cpp @@ -0,0 +1,259 @@ +// ===================================================================================================================== +// Copyright 2024 Medusa Slockbower +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ===================================================================================================================== + +#include +#include +#include + +#include + +#include "Project/Project.h" + +OpenShaderDesigner::Asset * OpenShaderDesigner::FileManager::load(const Path& path) +{ + Console::Log(Console::Message, "Loading File {}", path.string()); + FileType type = ExtensionMap[path.extension().string()]; + + switch (type) + { + case FileType_Project: + { + Project* project = EditorSystem::GetMainMenuBar(); + project->Load(path); + return project; + } + + default: + return nullptr; + } +} + +OpenShaderDesigner::Asset * OpenShaderDesigner::FileManager::import(const Path &src, const Path &dst) +{ + return nullptr; +} + +OpenShaderDesigner::Asset * OpenShaderDesigner::FileManager::create(const Path &path) +{ + Console::Log(Console::Message, "Creating File {}", path.string()); + FileType type = ExtensionMap[path.extension().string()]; + + switch (type) + { + case FileType_Project: + { + Project* project = EditorSystem::GetMainMenuBar(); + project->Create(path); + return project; + } + + default: + return nullptr; + } +} + +OpenShaderDesigner::FileManager::FileManager() + : EditorWindow("File Manager", ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoScrollbar) + , CurrentDirectory_(FileSystem::root), Selected_(FileSystem::root) + , Rename_(false), FocusRename_(false) +{ + //CurrentDirectory_ = Filesystem_.load_directory(std::filesystem::current_path()); +} + +void OpenShaderDesigner::FileManager::DrawMenu() +{ + +} + +void OpenShaderDesigner::FileManager::DrawWindow() +{ + // Directory Hierarchy + ImGui::BeginGroup(); + if (ImGui::BeginChild("##hierarchy", ImVec2(200, 0), + ImGuiChildFlags_ResizeX | ImGuiChildFlags_AlwaysUseWindowPadding | ImGuiChildFlags_Border)) + { + struct Visitor + { + bool operator()(File& file, FileID id) + { + const FileSystem& tree = file.system(); + uint32_t depth = tree.depth(id); + + // Skip root + if(id == FileSystem::root) return false; + + // Skip if we are in a closed directory + if(depth > stack.size()) return false; + + // Skip non-directories + const bool is_dir = file.is_directory(); + if(not is_dir) return false; + + // Pop dead paths + while(depth < stack.size()) + { + stack.pop(); + ImGui::TreePop(); + } + + // Skip if the top of the stack is not the parent of the file + if(stack.top() != tree.parent(id)) return false; + + // Generate display name + const char* icon = "\ued53"; + std::string name = std::format("{} {}##{}", icon, file.path().stem().string(), id); + + // Display flags + int flags = 0; + if(file.has_subdirectory()) + { + flags |= ImGuiTreeNodeFlags_OpenOnArrow; + flags |= ImGuiTreeNodeFlags_OpenOnDoubleClick; + flags |= ImGuiTreeNodeFlags_SpanAvailWidth; + } + else + { + flags |= ImGuiTreeNodeFlags_Leaf; + } + + if(id == directory) flags |= ImGuiTreeNodeFlags_Selected; + + if(ImGui::TreeNodeEx(name.c_str(), flags)) + { + stack.push(id); + } + + if(ImGui::IsItemClicked()) directory = file.get_id(); + + return false; + } + + std::stack stack; + FileID directory; + } visitor; + + visitor.directory = CurrentDirectory_; + visitor.stack.push(FileSystem::root); + Filesystem_.traverse(visitor); + + while(visitor.stack.size() > 1) + { + ImGui::TreePop(); + visitor.stack.pop(); + } + + CurrentDirectory_ = visitor.directory; + } + ImGui::EndChild(); + ImGui::EndGroup(); + + ImGui::SameLine(); + + if(ImGui::BeginTable("##directory", 3, ImGuiTableFlags_RowBg | ImGuiTableFlags_ScrollY | ImGuiTableFlags_BordersOuter)) + { + ImGui::TableSetupScrollFreeze(0, 1); + + ImGui::TableSetupColumn(" Name"); + ImGui::TableSetupColumn("Type"); + ImGui::TableSetupColumn("Source"); + + ImGui::TableHeadersRow(); + + for(FileID it = Filesystem_.begin(CurrentDirectory_); it != Filesystem_.end(CurrentDirectory_); it = Filesystem_.next(it)) + { + File& file = Filesystem_[it]; + ImGui::TableNextRow(); + + const bool selected = Selected_ == it; + + ImGui::TableNextColumn(); + + // Display Name + bool dirty = *file ? file->Dirty() : false; + std::string name = std::format("{}{}", dirty ? "\uea81 " : "", file.path().stem().string()); + if(ImGui::Selectable( + std::format(" {}##{}", Rename_ && selected ? "" : name.c_str(), file.get_id()).c_str() + , selected, ImGuiSelectableFlags_SpanAllColumns + )) + { + Selected_ = Rename_ ? Selected_ : it; + } + + // Renaming + if(selected && Rename_) + { + ImGui::SameLine(); + if(FocusRename_) ImGui::SetKeyboardFocusHere(); + + if(ImGui::InputText(" ##rename", &RenameBuffer_, ImGuiInputTextFlags_EnterReturnsTrue)) + { + if(not RenameBuffer_.empty()) Filesystem_.rename(Selected_, RenameBuffer_); + + Rename_ = false; + } + + if(FocusRename_) + { + FocusRename_ = false; + } + else if(ImGui::IsItemFocused() == false) + { + Rename_ = false; + } + } + + ImGui::TableNextColumn(); + ImGui::Text("%s", file.path().extension().string().c_str()); + + ImGui::TableNextColumn(); + ImGui::Text("%s", file.path().string().c_str()); + } + + ImGui::EndTable(); + } +} + +bool OpenShaderDesigner::FileManager::AnyDirty() +{ + bool res = false; + struct Visitor + { + bool operator()(File& file, FileID id) + { + if(id == FileSystem::root) return false; + + res |= file->Dirty(); + return false; + } + + bool& res; + } visitor{ res }; + Filesystem_.traverse(visitor); + return res; +} + +void OpenShaderDesigner::FileManager::SaveAll() +{ + +} + +OpenShaderDesigner::FileManager::Path OpenShaderDesigner::FileManager::GetHomeDirectory() +{ +#ifdef WIN32 + return Path(getenv("HOMEDRIVE")) / getenv("HOMEPATH"); +#else + return getenv("HOME"); +#endif +} diff --git a/Source/Graph/Compiler.cpp b/Source/Graph/Compiler.cpp new file mode 100644 index 0000000..d794151 --- /dev/null +++ b/Source/Graph/Compiler.cpp @@ -0,0 +1,3 @@ +// +// Created by Maddie on 9/11/2024. +// diff --git a/Source/Graph/ShaderGraph.cpp b/Source/Graph/ShaderGraph.cpp index 7126731..c7ef15b 100644 --- a/Source/Graph/ShaderGraph.cpp +++ b/Source/Graph/ShaderGraph.cpp @@ -210,8 +210,8 @@ void Node::Draw(ImGuiID id) ShaderGraph::ShaderGraph() : EditorWindow("\uED46 Shader Graph", 0) - , GrabFocus(false) - , State(*this) + , GrabFocus_(false) + , State_(*this) { } @@ -223,7 +223,7 @@ void ShaderGraph::OnOpen() { EditorSystem::Open()->Graph = this; - GrabFocus = true; + GrabFocus_ = true; } @@ -236,18 +236,18 @@ void ShaderGraph::DrawWindow() ImNodeGraph::SetGraphValidation(ValidateConnection); - if(GrabFocus) + if(GrabFocus_) { - GrabFocus = false; + GrabFocus_ = false; ImGui::SetWindowFocus(); ImGui::SetNavWindow(ImGui::GetCurrentWindow()); } - for(ImGuiID id = 0; id < State.Nodes.size(); ++id) + for(ImGuiID id = 0; id < State_.Nodes.size(); ++id) { - if(State.Nodes(id) == false) continue; + if(State_.Nodes(id) == false) continue; - State.Nodes[id]->Draw(id); + State_.Nodes[id]->Draw(id); } DrawContextMenu(); @@ -257,14 +257,15 @@ void ShaderGraph::DrawWindow() ImNodeGraph::BeginGraphPostOp("ShaderGraph"); - if(ImGui::IsKeyPressed(ImGuiKey_Delete)) + if(ImGui::IsKeyPressed(ImGuiKey_Delete)) Erase(); + + ImGuiIO& io = ImGui::GetIO(); + + if(!(io.KeyMods & ~ImGuiMod_Ctrl)) { - auto& selected = ImNodeGraph::GetSelected(); - for(ImGuiID node : selected) - { - State.Nodes.erase(ImNodeGraph::GetUserID(node).Int); - } - selected.Clear(); + if(ImGui::IsKeyPressed(ImGuiKey_C)) Copy(); + if(ImGui::IsKeyPressed(ImGuiKey_P)) Paste(ImGui::GetMousePos()); + if(ImGui::IsKeyPressed(ImGuiKey_X)) { Copy(); Erase(); } } ImNodeGraph::EndGraphPostOp(); @@ -275,7 +276,7 @@ void ShaderGraph::DrawContextMenu() { if(ImGui::IsMouseClicked(ImGuiMouseButton_Right)) { - ContextMenuPosition = ImNodeGraph::ScreenToGrid(ImGui::GetMousePos()); + ContextMenuPosition_ = ImNodeGraph::ScreenToGrid(ImGui::GetMousePos()); } if(ImGui::BeginPopupContextWindow("graph_context")) @@ -286,7 +287,7 @@ void ShaderGraph::DrawContextMenu() Copy(); Erase(); } - if(ImGui::MenuItem("Paste", "Ctrl+V", false, false)) Paste(ContextMenuPosition); + if(ImGui::MenuItem("Paste", "Ctrl+V", false, false)) Paste(ContextMenuPosition_); ImGui::Separator(); @@ -295,7 +296,7 @@ void ShaderGraph::DrawContextMenu() ImGui::Separator(); // Create Nodes - ImVec2 position = ContextMenuPosition; + ImVec2 position = ContextMenuPosition_; std::stack context; context.push(0); @@ -319,7 +320,7 @@ void ShaderGraph::DrawContextMenu() { if(ImGui::MenuItem(item.Name.c_str())) { - Graph.State.Nodes.insert(item.Constructor(Graph, Location)); + Graph.State_.Nodes.insert(item.Constructor(Graph, Location)); } } else @@ -360,18 +361,31 @@ void ShaderGraph::DrawContextMenu() } } -void ShaderGraph::Copy() {} -void ShaderGraph::Erase() {} +void ShaderGraph::Copy() +{ + +} + +void ShaderGraph::Erase() +{ + auto& selected = ImNodeGraph::GetSelected(); + for(ImGuiID node : selected) + { + State_.Nodes.erase(ImNodeGraph::GetUserID(node).Int); + } + selected.Clear(); +} + void ShaderGraph::Paste(ImVec2) {} Node* ShaderGraph::FindNode(ImPinPtr ptr) { - return State.Nodes[ImNodeGraph::GetUserID(ptr.Node).Int]; + return State_.Nodes[ImNodeGraph::GetUserID(ptr.Node).Int]; } Pin& ShaderGraph::FindPin(ImPinPtr ptr) { - Node* node = State.Nodes[ImNodeGraph::GetUserID(ptr.Node).Int]; + Node* node = State_.Nodes[ImNodeGraph::GetUserID(ptr.Node).Int]; auto& pins = ptr.Direction ? node->IO.Outputs : node->IO.Inputs; int idx = ImNodeGraph::GetUserID(ptr).Int; if(ptr.Direction) idx *= -1; @@ -410,12 +424,12 @@ void ShaderGraph::Register(const std::filesystem::path& path, ConstructorPtr con if(node == 0 || node != child) { - node = ContextMenu.insert({ decomp.top(), nullptr }, node); + node = ContextMenu.insert({ decomp.top(), nullptr }, node, -1); decomp.pop(); } } - ContextMenu.insert({ name, constructor }, node); + ContextMenu.insert({ name, constructor }, node, -1); } Inspector::Inspector() diff --git a/Source/Project/Project.cpp b/Source/Project/Project.cpp new file mode 100644 index 0000000..ed59a2e --- /dev/null +++ b/Source/Project/Project.cpp @@ -0,0 +1,169 @@ +// +// Created by Maddie on 9/14/2024. +// + +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include +#include + +OpenShaderDesigner::Project::Project() + : ProjectFile_(NULL) +{ + +} + +OpenShaderDesigner::Project::~Project() +{ + +} + +void OpenShaderDesigner::Project::DrawMenuBar() +{ + FileManager* filesystem = EditorSystem::Get(); + + if(ImGui::BeginMenu("File")) + { + if(ImGui::MenuItem("\uecc9 New...")) + { + Console::Log(Console::Message, "Creating Project"); + + bool cancelled = false; + if(filesystem->AnyDirty()) + { + auto save = pfd::message("Unsaved Changes", "Would you like to save your changes?", pfd::choice::yes_no_cancel); + switch(save.result()) + { + case pfd::button::yes: + Console::Log(Console::Message, "Saving Old Project"); + filesystem->SaveAll(); + break; + case pfd::button::cancel: + Console::Log(Console::Message, "Cancelled"); + cancelled = true; + break; + default: case pfd::button::no: + break; + } + } + + if(not cancelled) + { + filesystem->CloseDirectory(filesystem->Parent(ProjectFile_)); + + Console::Log(Console::Message, "Select Location"); + auto res = pfd::save_file("New", FileManager::GetHomeDirectory().string(), { "Project File (.sgp)", "*.sgp" }).result(); + + if(not res.empty()) + { + FileManager::Path path = res; + + if(not path.has_extension()) path = res + ".sgp"; + + Console::Log(Console::Alert, "Creating Project {} in {}", path.filename().string(), path.parent_path().string()); + + create_directories(path.parent_path()); + FileManager::FileID root = filesystem->LoadDirectory(path.parent_path()); + filesystem->CurrentDirectory(root); + ProjectFile_ = filesystem->Create(path.filename().string()); + } + } + } + + if(ImGui::MenuItem("\ued6f Open...")) + { + Console::Log(Console::Message, "Opening Project"); + + bool cancelled = false; + if(filesystem->AnyDirty()) + { + auto save = pfd::message("Unsaved Changes", "Would you like to save your changes?", pfd::choice::yes_no_cancel); + switch(save.result()) + { + case pfd::button::yes: + Console::Log(Console::Message, "Saving Old Project"); + filesystem->SaveAll(); + break; + case pfd::button::cancel: + Console::Log(Console::Message, "Cancelled"); + cancelled = true; + break; + default: case pfd::button::no: + break; + } + } + + if(not cancelled) + { + Console::Log(Console::Message, "Post Dialogue"); + auto project = pfd::open_file("Open", FileManager::GetHomeDirectory().string(), { "Project File (.sgp)", "*.sgp" }); + + if(not project.result().empty()) + { + Console::Log(Console::Message, "Closing Old Project"); + filesystem->CloseDirectory(filesystem->Parent(ProjectFile_)); + + Console::Log(Console::Message, "Closing New Project"); + FileManager::Path res = FileManager::Path(project.result().front()); + FileManager::FileID root = filesystem->LoadDirectory(res.parent_path()); + filesystem->CurrentDirectory(root); + + Console::Log(Console::Message, "Retrieving Project File"); + ProjectFile_ = filesystem->Get(res); + } + } + } + + ImGui::EndMenu(); + } +} + +void OpenShaderDesigner::Project::Open() +{ + +} + +void OpenShaderDesigner::Project::Load(const FileManager::Path& path) +{ + Console::Log(Console::Message, "Loading Project {}", path.string()); +} + +void OpenShaderDesigner::Project::Save(const FileManager::Path& path) +{ + // Setup + rapidjson::Document document; + document.SetObject(); + + // Write to file + std::ofstream file(path); + rapidjson::OStreamWrapper out(file); + rapidjson::PrettyWriter writer(out); + document.Accept(writer); + file.close(); + + // Clear Dirty Flag + Asset::Save(path); + + Console::Log(Console::Alert, "Saved Project {} to {}", path.filename().string(), path.parent_path().string()); +} + +void OpenShaderDesigner::Project::Create(const FileManager::Path &path) +{ + Console::Log(Console::Message, "Setting Up New Project"); + Reset(); + Save(path); +} + +void OpenShaderDesigner::Project::Reset() +{ + +} diff --git a/imgui.ini b/imgui.ini index 5b08191..b52a61b 100644 --- a/imgui.ini +++ b/imgui.ini @@ -8,32 +8,32 @@ Size=400,400 Collapsed=0 [Window][Dear ImGui Demo] -Pos=3070,364 -Size=370,711 +Pos=3070,104 +Size=370,884 Collapsed=0 DockId=0x00000008,0 [Window][ Console] -Pos=303,1077 -Size=3137,340 +Pos=468,990 +Size=2972,427 Collapsed=0 DockId=0x00000004,0 [Window][ Profiler] -Pos=0,1077 -Size=301,340 +Pos=0,990 +Size=466,427 Collapsed=0 DockId=0x00000003,0 [Window][ Shader Graph] -Pos=0,0 -Size=3068,1075 +Pos=0,24 +Size=3068,964 Collapsed=0 DockId=0x00000005,0 [Window][WindowOverViewport_11111111] -Pos=0,0 -Size=3440,1417 +Pos=0,24 +Size=3440,1393 Collapsed=0 [Window][Example: Custom rendering] @@ -65,19 +65,29 @@ Size=487,534 Collapsed=0 [Window][Inspector] -Pos=3070,0 -Size=370,362 +Pos=3070,24 +Size=370,78 Collapsed=0 DockId=0x00000007,0 +[Window][File Manager] +Pos=468,990 +Size=2972,427 +Collapsed=0 +DockId=0x00000004,1 + +[Window][File Manager/##hierarchy_CA8B7713] +IsChild=1 +Size=289,363 + [Docking][Data] -DockSpace ID=0x7C6B3D9B Window=0xA87D555D Pos=0,0 Size=3440,1417 Split=Y - DockNode ID=0x00000001 Parent=0x7C6B3D9B SizeRef=3440,378 Split=X +DockSpace ID=0x7C6B3D9B Window=0xA87D555D Pos=0,24 Size=3440,1393 Split=Y + DockNode ID=0x00000001 Parent=0x7C6B3D9B SizeRef=3440,964 Split=X DockNode ID=0x00000005 Parent=0x00000001 SizeRef=3068,1417 CentralNode=1 Selected=0xD4C89E35 DockNode ID=0x00000006 Parent=0x00000001 SizeRef=370,1417 Split=Y Selected=0xE7039252 - DockNode ID=0x00000007 Parent=0x00000006 SizeRef=370,127 Selected=0xE7039252 - DockNode ID=0x00000008 Parent=0x00000006 SizeRef=370,249 Selected=0xE87781F4 - DockNode ID=0x00000002 Parent=0x7C6B3D9B SizeRef=3440,340 Split=X Selected=0xE9F1AFD1 - DockNode ID=0x00000003 Parent=0x00000002 SizeRef=301,448 Selected=0xAC4B19AE - DockNode ID=0x00000004 Parent=0x00000002 SizeRef=3137,448 Selected=0xE9F1AFD1 + DockNode ID=0x00000007 Parent=0x00000006 SizeRef=370,78 Selected=0xE7039252 + DockNode ID=0x00000008 Parent=0x00000006 SizeRef=370,884 Selected=0xE87781F4 + DockNode ID=0x00000002 Parent=0x7C6B3D9B SizeRef=3440,427 Split=X Selected=0xE9F1AFD1 + DockNode ID=0x00000003 Parent=0x00000002 SizeRef=466,448 Selected=0xAC4B19AE + DockNode ID=0x00000004 Parent=0x00000002 SizeRef=2972,448 Selected=0x9E7C6CAA