File System

This commit is contained in:
Maddie Slockbower 2024-09-18 11:46:27 -04:00
parent 2fbdfd14b9
commit 93d383ece0
32 changed files with 1332 additions and 630 deletions

View File

@ -23,6 +23,7 @@ find_package(GLEW REQUIRED)
find_package(glm REQUIRED) find_package(glm REQUIRED)
find_package(OpenGL REQUIRED COMPONENTS OpenGL) find_package(OpenGL REQUIRED COMPONENTS OpenGL)
find_package(SDL2 REQUIRED) find_package(SDL2 REQUIRED)
find_package(RapidJSON REQUIRED)
if(MSVC) if(MSVC)
add_compile_options("$<$<C_COMPILER_ID:MSVC>:/utf-8>") add_compile_options("$<$<C_COMPILER_ID:MSVC>:/utf-8>")
@ -33,6 +34,7 @@ include_directories(Include)
include_directories(External) include_directories(External)
# Add External Libraries # Add External Libraries
add_subdirectory(External/portable-file-dialogs)
add_subdirectory(External/open-cpp-utils) add_subdirectory(External/open-cpp-utils)
add_subdirectory(External/glw) add_subdirectory(External/glw)
@ -55,7 +57,6 @@ add_executable(OpenShaderDesigner
Source/Core/Console.cpp Source/Core/Console.cpp
Source/Core/EventSystem.cpp Source/Core/EventSystem.cpp
Source/Core/Engine.cpp Source/Core/Engine.cpp
Source/Core/Renderer.cpp
# Editor # Editor
Source/Editor/EditorSystem.cpp Source/Editor/EditorSystem.cpp
@ -68,6 +69,14 @@ add_executable(OpenShaderDesigner
# Nodes # Nodes
Source/Graph/Nodes/Math.cpp 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 target_link_libraries(OpenShaderDesigner PRIVATE
@ -75,6 +84,8 @@ target_link_libraries(OpenShaderDesigner PRIVATE
GLEW::GLEW GLEW::GLEW
OpenGL::GL OpenGL::GL
${SDL2_LIBRARIES} ${SDL2_LIBRARIES}
rapidjson
open-cpp-utils
imgui-docking imgui-docking
imgui-extras imgui-extras
imnode-graph imnode-graph

View File

@ -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 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 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. 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 // Inputs Behaviors
// (other variables, ones which are expected to be tweaked within UI code, are exposed in ImGuiStyle) // (other variables, ones which are expected to be tweaked within UI code, are exposed in ImGuiStyle)

View File

@ -27,23 +27,24 @@
namespace OpenShaderDesigner namespace OpenShaderDesigner
{ {
class Console class Console
{ {
public: public:
/** /**
* \brief Setting for displaying log entries. * \brief Setting for displaying log entries.
*/ */
enum Setting enum Settings
: uint8_t : uint8_t
{ {
SHOW_TIMESTAMP = 0b00000001 Settings_ShowTimeStamp = 0b00000001
, SHOW_THREAD = 0b00000010 , Settings_ShowThread = 0b00000010
, SHOW_SEVERITY = 0b00000100 , Settings_Severity = 0b00000100
, SHOW_FILE_INFO = 0b00001000 , Settings_ShowFileInfo = 0b00001000
, WRAP_TEXT = 0b00010000 , Settings_WrapText = 0b00010000
, ALL_SETTINGS = 0xFF , Settings_ALL = 0xFF
, DEFAULT_SETTINGS = ALL_SETTINGS ^ WRAP_TEXT , Settings_Default = Settings_ALL ^ Settings_WrapText
}; };
/** /**
@ -57,17 +58,17 @@ namespace OpenShaderDesigner
/** /**
* \brief Severity levels for log entries. * \brief Severity levels for log entries.
*/ */
enum class Severity enum Severity
: int : int
{ {
MESSAGE = 0, Message = 0,
WARNING, Warning,
ERROR, Error,
FATAL, Fatal,
ALERT, Alert,
COMMAND, Command,
COUNT, COUNT,
DEFAULT = WARNING DEFAULT = Warning
}; };
/** /**
@ -141,7 +142,7 @@ namespace OpenShaderDesigner
* \param entry The Entry to format. * \param entry The Entry to format.
* \return The Entry formatted into a string. * \return The Entry formatted into a string.
*/ */
static std::string Format(const LogEntry& entry, Setting settings); static std::string Format(const LogEntry& entry, uint8_t settings);
/** /**
* \brief Command handling. * \brief Command handling.
@ -149,11 +150,11 @@ namespace OpenShaderDesigner
*/ */
static void ProcessCommand(const std::string& command); static void ProcessCommand(const std::string& command);
inline static std::list<LogEntry> EntryLog; inline static std::list<LogEntry> EntryLog_;
inline static std::mutex Lock; inline static std::mutex Lock_;
inline static int Filter = static_cast<int>(0xFFFFFFFF); inline static int Filter_ = static_cast<int>(0xFFFFFFFF);
inline static Setting Settings = DEFAULT_SETTINGS; inline static uint8_t Settings_ = Settings_Default;
inline static std::string Command; inline static std::string CommandBuffer_;
}; };
template <typename... Args> template <typename... Args>
@ -170,15 +171,16 @@ namespace OpenShaderDesigner
#endif #endif
auto tm = *std::localtime(&t); auto tm = *std::localtime(&t);
std::lock_guard guard(Lock); std::lock_guard guard(Lock_);
LogEntry entry{ LogEntry entry{
std::vformat(fmt.get(), std::make_format_args(vargs...)), severity, file, std::format( 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), "{:0>2}:{:0>2}:{:0>2}", tm.tm_hour, tm.tm_min, tm.tm_sec),
ThreadID(), line ThreadID(), line
}; };
EntryLog.push_back(entry); EntryLog_.push_back(entry);
std::cout << Format(entry, ALL_SETTINGS) << std::endl; std::cout << Format(entry, Settings_ALL) << std::endl;
} }
} }
#define Log(...) Log(__FILE__, __LINE__, __VA_ARGS__) #define Log(...) Log(__FILE__, __LINE__, __VA_ARGS__)

View File

@ -22,6 +22,7 @@
namespace OpenShaderDesigner namespace OpenShaderDesigner
{ {
class Engine class Engine
{ {
public: public:
@ -41,6 +42,7 @@ namespace OpenShaderDesigner
public: public:
inline static const double& Delta = _Delta; inline static const double& Delta = _Delta;
}; };
} }

View File

@ -29,6 +29,7 @@ namespace ocu = open_cpp_utils;
namespace OpenShaderDesigner namespace OpenShaderDesigner
{ {
/** /**
* \brief Base Event class for sending events to the Engine. * \brief Base Event class for sending events to the Engine.
*/ */
@ -105,8 +106,8 @@ namespace OpenShaderDesigner
static void UnregisterHandler(EventHandler<T>*); static void UnregisterHandler(EventHandler<T>*);
private: private:
inline static std::list<_ImplEventHandler*> HandlerMap[MAX_EVENT_TYPES]; inline static std::list<_ImplEventHandler*> HandlerMap_[MAX_EVENT_TYPES];
inline static std::mutex Lock; inline static std::mutex Lock_;
EventSystem(const EventSystem&) = delete; EventSystem(const EventSystem&) = delete;
EventSystem(EventSystem&&) = delete; EventSystem(EventSystem&&) = delete;
@ -116,18 +117,18 @@ namespace OpenShaderDesigner
void EventSystem::UnregisterHandler(EventHandler<T>* handler) void EventSystem::UnregisterHandler(EventHandler<T>* handler)
{ {
// Thread safe // Thread safe
std::lock_guard guard(Lock); std::lock_guard guard(Lock_);
const uint8_t index = T::ID; const uint8_t index = T::ID;
std::erase(HandlerMap[index], reinterpret_cast<_ImplEventHandler*>(handler)); std::erase(HandlerMap_[index], reinterpret_cast<_ImplEventHandler*>(handler));
} }
template<typename T> template<typename T>
void EventSystem::RegisterHandler(EventHandler<T>* handler) void EventSystem::RegisterHandler(EventHandler<T>* handler)
{ {
// Thread safe // Thread safe
std::lock_guard guard(Lock); std::lock_guard guard(Lock_);
const uint8_t index = T::ID; const uint8_t index = T::ID;
HandlerMap[index].push_back(reinterpret_cast<_ImplEventHandler*>(handler)); HandlerMap_[index].push_back(reinterpret_cast<_ImplEventHandler*>(handler));
} }
template<typename EventType> template<typename EventType>
@ -136,6 +137,7 @@ namespace OpenShaderDesigner
if(EventType::ID != event->GetID()) return false; if(EventType::ID != event->GetID()) return false;
return HandleEvent(reinterpret_cast<const EventType*>(event)); return HandleEvent(reinterpret_cast<const EventType*>(event));
} }
} }
#define BeginEvent(EVENT) struct EVENT : OpenShaderDesigner::Event \ #define BeginEvent(EVENT) struct EVENT : OpenShaderDesigner::Event \

View File

@ -21,10 +21,12 @@
namespace OpenShaderDesigner namespace OpenShaderDesigner
{ {
class Renderer class Renderer
{ {
}; };
} }

View File

@ -27,6 +27,7 @@ namespace ocu = open_cpp_utils;
namespace OpenShaderDesigner namespace OpenShaderDesigner
{ {
BeginEvent(SDLEvent) BeginEvent(SDLEvent)
const SDL_Event sdl_event; const SDL_Event sdl_event;
@ -95,22 +96,23 @@ namespace OpenShaderDesigner
void BeginFrame(); void BeginFrame();
void EndFrame(); void EndFrame();
void Close() { Open = false; } void Close() { Open_ = false; }
[[nodiscard]] bool IsOpen() const { return Open; } [[nodiscard]] bool IsOpen() const { return Open_; }
SDL_Window* GetHandle() { return Handle; } SDL_Window* GetHandle() { return Handle_; }
[[nodiscard]] const SDL_Window* GetHandle() const { return Handle; } [[nodiscard]] const SDL_Window* GetHandle() const { return Handle_; }
SDL_GLContext GetContext() { return Context; } SDL_GLContext GetContext() { return Context_; }
[[nodiscard]] const SDL_GLContext GetContext() const { return Context; } [[nodiscard]] const SDL_GLContext GetContext() const { return Context_; }
[[nodiscard]] glm::ivec2 Size() const { return Config.Video.Resolution; } [[nodiscard]] glm::ivec2 Size() const { return Config_.Video.Resolution; }
private: private:
Configuration Config; Configuration Config_;
SDL_Window* Handle; SDL_Window* Handle_;
SDL_GLContext Context; SDL_GLContext Context_;
bool Open; bool Open_;
}; };
} }

View File

@ -21,11 +21,13 @@
#include <unordered_map> #include <unordered_map>
#include <Editor/EditorWindow.h> #include <Editor/EditorWindow.h>
#include <Editor/MainMenuBar.h>
#define MAX_EDITORS 256 #define MAX_EDITORS 256
namespace OpenShaderDesigner namespace OpenShaderDesigner
{ {
class EditorSystem class EditorSystem
{ {
public: public:
@ -43,19 +45,27 @@ namespace OpenShaderDesigner
template<typename T> template<typename T>
static T* Get() static T* Get()
{ {
T* window = reinterpret_cast<T*>(Windows[ID<T>()]); T* window = reinterpret_cast<T*>(Windows_[ID<T>()]);
if(window == nullptr) Windows[ID<T>()] = window = new T(); if(window == nullptr) Windows_[ID<T>()] = window = new T();
return window; return window;
} }
template<typename T>
static T* SetMainMenuBar() { delete MainMenuBar_; T* bar = new T(); MainMenuBar_ = bar; return bar; }
template<typename T>
static T* GetMainMenuBar() { return static_cast<T*>(MainMenuBar_); }
static void Initialize(); static void Initialize();
static void Draw(); static void Draw();
static void Shutdown(); static void Shutdown();
static void HandleEvents(SDL_Event* event); static void HandleEvents(SDL_Event* event);
private: private:
inline static EditorWindow* Windows[MAX_EDITORS] { nullptr }; inline static EditorWindow* Windows_[MAX_EDITORS] { nullptr };
inline static MainMenuBar* MainMenuBar_ = nullptr;
}; };
} }

View File

@ -21,6 +21,7 @@
namespace OpenShaderDesigner namespace OpenShaderDesigner
{ {
/** /**
* \brief EditorWindow class for wrapping ImGui window functionality. * \brief EditorWindow class for wrapping ImGui window functionality.
*/ */
@ -46,14 +47,14 @@ namespace OpenShaderDesigner
* \brief Check if the EditorWindow is open. * \brief Check if the EditorWindow is open.
* \return * \return
*/ */
[[nodiscard]] bool IsOpen() const { return bOpen; } [[nodiscard]] bool IsOpen() const { return bOpen_; }
const std::string Title; //!< Title for the EditorWindow. const std::string Title; //!< Title for the EditorWindow.
void SetFlags(ImGuiWindowFlags flags) { Flags |= flags; } void SetFlags(ImGuiWindowFlags flags) { Flags_ |= flags; }
void ClearFlags(ImGuiWindowFlags flags) { Flags &= ~flags; } void ClearFlags(ImGuiWindowFlags flags) { Flags_ &= ~flags; }
void ToggleFlags(ImGuiWindowFlags flags) { Flags ^= flags; } void ToggleFlags(ImGuiWindowFlags flags) { Flags_ ^= flags; }
[[nodiscard]] bool CheckFlag(ImGuiWindowFlags flag) const { return Flags & flag; } [[nodiscard]] bool CheckFlag(ImGuiWindowFlags flag) const { return Flags_ & flag; }
[[nodiscard]] bool HasMenuBar() const { return CheckFlag(ImGuiWindowFlags_MenuBar); } [[nodiscard]] bool HasMenuBar() const { return CheckFlag(ImGuiWindowFlags_MenuBar); }
@ -95,11 +96,12 @@ namespace OpenShaderDesigner
EditorWindow(EditorWindow&&) = delete; EditorWindow(EditorWindow&&) = delete;
int Flags; int Flags_;
bool bOpen; bool bOpen_;
friend class EditorSystem; friend class EditorSystem;
}; };
} }

View File

@ -0,0 +1,26 @@
//
// Created by Maddie on 9/14/2024.
//
#ifndef MAINMENUBAR_H
#define MAINMENUBAR_H
#include <imgui-docking/imgui.h>
namespace OpenShaderDesigner
{
class MainMenuBar
{
public:
virtual void DrawMenuBar() = 0;
friend class EditorSystem;
private:
void Draw() { ImGui::BeginMainMenuBar(); DrawMenuBar(); ImGui::EndMainMenuBar(); }
};
}
#endif //MAINMENUBAR_H

View File

@ -50,9 +50,9 @@ namespace OpenShaderDesigner
, LAST = COUNT - 1 , LAST = COUNT - 1
}; };
uint64_t Frame; uint64_t Frame_;
double Deltas[COUNT]; double Deltas_[COUNT];
Timer Timer; Timer Timer_;
}; };
} }

View File

@ -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 <open-cpp-utils/filesystem.h>
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

View File

@ -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 <Editor/EditorWindow.h>
#include <FileSystem/Asset.h>
#include <open-cpp-utils/filesystem.h>
#include <open-cpp-utils/map.h>
namespace ocu = open_cpp_utils;
namespace OpenShaderDesigner
{
class FileManager : public EditorWindow
{
public:
using FileSystem = ocu::filesystem<Asset, FileManager>;
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<std::string, FileType> 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

View File

@ -13,5 +13,7 @@
// limitations under the License. // limitations under the License.
// ===================================================================================================================== // =====================================================================================================================
#ifndef COMPILER_H
#define COMPILER_H
#include <Core/Renderer.h> #endif //COMPILER_H

View File

@ -50,8 +50,6 @@ struct Integer : public Node
[[nodiscard]] Node* Copy(ShaderGraph& graph) const override; [[nodiscard]] Node* Copy(ShaderGraph& graph) const override;
void Inspect() override; void Inspect() override;
ValueType Value;
}; };
RegisterNode("Math/Constants/Integer", Integer); RegisterNode("Math/Constants/Integer", Integer);
@ -68,8 +66,6 @@ struct UnsignedInteger : public Node
[[nodiscard]] Node* Copy(ShaderGraph& graph) const override; [[nodiscard]] Node* Copy(ShaderGraph& graph) const override;
void Inspect() override; void Inspect() override;
ValueType Value;
}; };
RegisterNode("Math/Constants/Unsigned Integer", UnsignedInteger); RegisterNode("Math/Constants/Unsigned Integer", UnsignedInteger);
@ -86,8 +82,6 @@ struct Scalar : public Node
[[nodiscard]] Node* Copy(ShaderGraph& graph) const override; [[nodiscard]] Node* Copy(ShaderGraph& graph) const override;
void Inspect() override; void Inspect() override;
ValueType Value;
}; };
RegisterNode("Math/Constants/Scalar", Scalar); RegisterNode("Math/Constants/Scalar", Scalar);
@ -104,8 +98,6 @@ struct Vector : public Node
[[nodiscard]] Node* Copy(ShaderGraph& graph) const override; [[nodiscard]] Node* Copy(ShaderGraph& graph) const override;
void Inspect() override; void Inspect() override;
ValueType Value;
}; };
RegisterNode("Math/Constants/Vector", Vector); RegisterNode("Math/Constants/Vector", Vector);

View File

@ -197,15 +197,16 @@ namespace OpenShaderDesigner
// History Functionality // History Functionality
void PushState(); void PushState();
void PopState(); void PopState();
GraphState& GetState() { return State; } GraphState& GetState() { return State_; }
private: private:
bool GrabFocus; bool GrabFocus_;
GraphState State; GraphState State_;
std::stack<GraphState> History; std::stack<GraphState> History_;
ImVec2 ContextMenuPosition_;
ImVec2 ContextMenuPosition;
friend class Inspector; friend class Inspector;
}; };

35
Include/Project/Project.h Normal file
View File

@ -0,0 +1,35 @@
//
// Created by Maddie on 9/14/2024.
//
#ifndef PROJECT_H
#define PROJECT_H
#include <Editor/MainMenuBar.h>
#include <FileSystem/FileManager.h>
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

View File

@ -20,6 +20,7 @@
namespace OpenShaderDesigner namespace OpenShaderDesigner
{ {
class Timer class Timer
{ {
public: public:
@ -32,6 +33,7 @@ namespace OpenShaderDesigner
private: private:
std::chrono::high_resolution_clock::time_point Start; std::chrono::high_resolution_clock::time_point Start;
}; };
} }
#endif //TIMER_H #endif //TIMER_H

View File

@ -20,16 +20,16 @@ using namespace OpenShaderDesigner;
void Console::DrawMenu() void Console::DrawMenu()
{ {
std::lock_guard guard(Lock); std::lock_guard guard(Lock_);
if(ImGui::BeginMenu("\uf0e5 Settings")) if(ImGui::BeginMenu("\uf0e5 Settings"))
{ {
for(uint8_t setting = 0; setting < sizeof(SettingNames) / sizeof(std::string); ++setting) for(uint8_t setting = 0; setting < sizeof(SettingNames) / sizeof(std::string); ++setting)
{ {
int flag = 0x1 << 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<Setting>(Settings ^ flag); Settings_ = Settings_ ^ flag;
} }
} }
@ -41,9 +41,9 @@ void Console::DrawMenu()
for(int severity = 0; severity < static_cast<int>(Severity::COUNT); ++severity) for(int severity = 0; severity < static_cast<int>(Severity::COUNT); ++severity)
{ {
int flag = 0x1 << 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() 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(); const float padding = ImGui::GetStyle().ItemSpacing.y + ImGui::GetFrameHeightWithSpacing();
if(ImGui::BeginChild("##scrolling", ImVec2(0, -padding), if(ImGui::BeginChild("##scrolling", ImVec2(0, -padding),
ImGuiChildFlags_AlwaysAutoResize | ImGuiChildFlags_AlwaysUseWindowPadding | ImGuiChildFlags_AutoResizeY 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) for(const LogEntry& entry : Log)
{ {
int flag = 0x1 << static_cast<int>(entry.Severity); int flag = 0x1 << static_cast<int>(entry.Severity);
if((flag & Filter) == 0) continue; if((flag & Filter_) == 0) continue;
ImGui::PushStyleColor(ImGuiCol_Text, SeverityColors[static_cast<int>(entry.Severity)]); ImGui::PushStyleColor(ImGuiCol_Text, SeverityColors[static_cast<int>(entry.Severity)]);
if(Settings & WRAP_TEXT) ImGui::TextWrapped("%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()); else ImGui::Text("%s", Format(entry, Settings_).c_str());
ImGui::PopStyleColor(); ImGui::PopStyleColor();
} }
@ -80,23 +80,23 @@ void Console::DrawWindow()
ImGui::Text(">"); ImGui::SameLine(); ImGui::Text(">"); ImGui::SameLine();
ImGui::SetNextItemWidth(ImGui::GetWindowWidth() - ImGui::GetCursorPosX() - ImGui::GetStyle().WindowPadding.x); 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); ProcessCommand(CommandBuffer_);
Command.clear(); CommandBuffer_.clear();
ImGui::SetKeyboardFocusHere(-1); 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<int>(entry.Severity)]); std::string severity = std::format("<{}>", Severities[static_cast<int>(entry.Severity)]);
std::string message; std::string message;
// Get Timestamp and Thread bits. // Get Timestamp and Thread bits.
const bool showTimestamp = (settings & SHOW_TIMESTAMP); const bool showTimestamp = (settings & Settings_ShowTimeStamp);
const bool showThreadID = (settings & SHOW_THREAD) && entry.Severity != Severity::COMMAND; const bool showThreadID = (settings & Settings_ShowThread) && entry.Severity != Severity::Command;
const bool check1 = showTimestamp || showThreadID; const bool check1 = showTimestamp || showThreadID;
// Print Timestamp and/or Thread if enabled. // 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); if(showThreadID) message += std::format("Thread #{:0>3} | ", entry.Thread);
// Get Severity and File bits. // Get Severity and File bits.
const bool showSeverity = (settings & SHOW_SEVERITY) && entry.Severity != Severity::COMMAND; const bool showSeverity = (settings & Settings_Severity) && entry.Severity != Severity::Command;
const bool showFile = (settings & SHOW_FILE_INFO) && entry.Severity != Severity::COMMAND; const bool showFile = (settings & Settings_ShowFileInfo) && entry.Severity != Severity::Command;
const bool check2 = showSeverity || showFile; const bool check2 = showSeverity || showFile;
// Print Severity and/or File if enabled. // 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); if(showFile) message += std::format("{}({})", entry.File, entry.Line);
// Print separator if any are enabled // Print separator if any are enabled
if(check1 || check2) message += entry.Severity == Severity::COMMAND ? "> " : ": "; if(check1 || check2) message += entry.Severity == Severity::Command ? "> " : ": ";
// Add message. // Add message.
message += entry.Message; message += entry.Message;

View File

@ -20,18 +20,22 @@
#include <Editor/ConsoleWindow.h> #include <Editor/ConsoleWindow.h>
#include <Editor/Profiler.h> #include <Editor/Profiler.h>
#include <FileSystem/FileManager.h>
#include <Graph/ShaderGraph.h> #include <Graph/ShaderGraph.h>
#include "Project/Project.h"
void OpenShaderDesigner::Engine::Start(const Window::Configuration& config) 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); MainWindow = new Window(config);
Initialize(); Initialize();
Console::Log(Console::Severity::MESSAGE, "Starting Main Loop"); Console::Log(Console::Message, "Starting Main Loop");
while(MainWindow->IsOpen()) while(MainWindow->IsOpen())
{ {
Update(); Update();
@ -47,20 +51,26 @@ void OpenShaderDesigner::Engine::Stop()
void OpenShaderDesigner::Engine::Initialize() 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(); EditorSystem::Initialize();
Console::Log(Console::Severity::MESSAGE, "Opening Console"); Console::Log(Console::Message, "Opening Console");
EditorSystem::Open<ConsoleWindow>(); EditorSystem::Open<ConsoleWindow>();
Console::Log(Console::Severity::MESSAGE, "Opening Profiler"); Console::Log(Console::Message, "Opening Profiler");
EditorSystem::Open<Profiler>(); EditorSystem::Open<Profiler>();
Console::Log(Console::Severity::MESSAGE, "Opening Shader Graph"); Console::Log(Console::Message, "Opening File Manager");
EditorSystem::Open<FileManager>();
Console::Log(Console::Message, "Opening Shader Graph");
EditorSystem::Open<Inspector>(); EditorSystem::Open<Inspector>();
EditorSystem::Open<ShaderGraph>(); EditorSystem::Open<ShaderGraph>();
Console::Log(Console::Message, "Setting up Project");
EditorSystem::SetMainMenuBar<Project>();
} }
void OpenShaderDesigner::Engine::Shutdown() void OpenShaderDesigner::Engine::Shutdown()

View File

@ -23,11 +23,11 @@ using namespace OpenShaderDesigner;
void EventSystem::PostEvent(const Event* event) void EventSystem::PostEvent(const Event* event)
{ {
// Thread safe // Thread safe
std::lock_guard guard(Lock); std::lock_guard guard(Lock_);
// Alert Handlers // Alert Handlers
const int index = event->GetID(); const int index = event->GetID();
for(_ImplEventHandler* handler : HandlerMap[index]) for(_ImplEventHandler* handler : HandlerMap_[index])
{ {
if(handler->_HandleEvent(event)) break; if(handler->_HandleEvent(event)) break;
} }

View File

@ -22,10 +22,10 @@
using namespace OpenShaderDesigner; using namespace OpenShaderDesigner;
Window::Window(const Configuration& config) Window::Window(const Configuration& config)
: Config(config) : Config_(config)
{ {
int flags = static_cast<int>(Config.Video.Fullscreen) | SDL_WINDOW_OPENGL; int flags = static_cast<int>(Config_.Video.Fullscreen) | SDL_WINDOW_OPENGL;
flags |= Config.Video.Fullscreen == FullscreenMode::WINDOWED ? SDL_WINDOW_RESIZABLE : 0; flags |= Config_.Video.Fullscreen == FullscreenMode::WINDOWED ? SDL_WINDOW_RESIZABLE : 0;
SDL_Init(SDL_INIT_EVERYTHING & ~SDL_INIT_AUDIO); 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_MINOR_VERSION, 6);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); 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_RED_SIZE, 10);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 16); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 10);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 16); SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 10);
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 16); SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 2);
SDL_GL_SetAttribute(SDL_GL_FLOATBUFFERS, SDL_TRUE); 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_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( if((Handle_ = SDL_CreateWindow(
Config.Application.Title.c_str(), Config_.Application.Title.c_str(),
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
Config.Video.Resolution.x, Config.Video.Resolution.y, Config_.Video.Resolution.x, Config_.Video.Resolution.y,
flags)) == nullptr) 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); assert(false);
return; 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()); Console::Log(Console::Severity::Fatal, "Failed to create OpenGL Context: {}", SDL_GetError());
SDL_DestroyWindow(Handle); SDL_DestroyWindow(Handle_);
assert(false); assert(false);
return; 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()); Console::Log(Console::Severity::Fatal, "Failed to set OpenGL Context: {}", SDL_GetError());
SDL_GL_DeleteContext(Context); SDL_GL_DeleteContext(Context_);
SDL_DestroyWindow(Handle); SDL_DestroyWindow(Handle_);
assert(false); assert(false);
return; return;
} }
// Set VSync Mode // Set VSync Mode
SDL_GL_SetSwapInterval(static_cast<int>(Config.Video.VSync)); SDL_GL_SetSwapInterval(static_cast<int>(Config_.Video.VSync));
// Enable experimental features // Enable experimental features
glewExperimental = GL_TRUE; glewExperimental = GL_TRUE;
@ -96,9 +96,9 @@ Window::Window(const Configuration& config)
GLenum error; GLenum error;
if((error = glewInit()) != GLEW_OK) if((error = glewInit()) != GLEW_OK)
{ {
Console::Log(Console::Severity::FATAL, "Failed to Initialize GLEW: {}", reinterpret_cast<const char*>(glewGetErrorString(error))); Console::Log(Console::Severity::Fatal, "Failed to Initialize GLEW: {}", reinterpret_cast<const char*>(glewGetErrorString(error)));
SDL_GL_DeleteContext(Context); SDL_GL_DeleteContext(Context_);
SDL_DestroyWindow(Handle); SDL_DestroyWindow(Handle_);
assert(false); assert(false);
return; return;
} }
@ -108,22 +108,22 @@ Window::Window(const Configuration& config)
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
glClearColor(0, 0, 0, 1); glClearColor(0, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
SDL_GL_SwapWindow(Handle); SDL_GL_SwapWindow(Handle_);
// Set running // Set running
Open = true; Open_ = true;
const char* glVersion = reinterpret_cast<const char*>(glGetString(GL_VERSION)); const char* glVersion = reinterpret_cast<const char*>(glGetString(GL_VERSION));
const char* glewVersion = reinterpret_cast<const char*>(glewGetString(GLEW_VERSION)); const char* glewVersion = reinterpret_cast<const char*>(glewGetString(GLEW_VERSION));
SDL_version sdlVersion; SDL_GetVersion(&sdlVersion); SDL_version sdlVersion; SDL_GetVersion(&sdlVersion);
Console::Log(Console::Severity::ALERT, "Initialized SDL ({}.{}.{})", sdlVersion.major, sdlVersion.minor, sdlVersion.patch); 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, "Running OpenGL ({}), GLEW ({})", glVersion, glewVersion);
} }
Window::~Window() Window::~Window()
{ {
SDL_GL_DeleteContext(Context); SDL_GL_DeleteContext(Context_);
SDL_DestroyWindow(Handle); SDL_DestroyWindow(Handle_);
SDL_Quit(); SDL_Quit();
} }
@ -147,8 +147,8 @@ void Window::HandleEvents()
switch(event.window.event) switch(event.window.event)
{ {
case SDL_WINDOWEVENT_SIZE_CHANGED: case SDL_WINDOWEVENT_SIZE_CHANGED:
Config.Video.Resolution.x = event.window.data1; Config_.Video.Resolution.x = event.window.data1;
Config.Video.Resolution.y = event.window.data2; Config_.Video.Resolution.y = event.window.data2;
break; break;
default: default:
break; break;
@ -170,14 +170,14 @@ void Window::BeginFrame()
HandleEvents(); HandleEvents();
glBindFramebuffer(GL_FRAMEBUFFER, 0); 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); glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
} }
void Window::EndFrame() void Window::EndFrame()
{ {
SDL_GL_SwapWindow(Handle); SDL_GL_SwapWindow(Handle_);
OpenShaderDesigner::EndFrame event; OpenShaderDesigner::EndFrame event;
EventSystem::PostEvent(&event); EventSystem::PostEvent(&event);

View File

@ -30,7 +30,7 @@ void EditorSystem::Initialize()
{ {
Window& Window = Engine::GetMainWindow(); Window& Window = Engine::GetMainWindow();
Console::Log(Console::Severity::ALERT, "Initializing Dear ImGUI"); Console::Log(Console::Severity::Alert, "Initializing Dear ImGUI");
IMGUI_CHECKVERSION(); IMGUI_CHECKVERSION();
ImGui::CreateContext(); ImGui::CreateContext();
@ -136,7 +136,7 @@ void EditorSystem::Initialize()
ImGui_ImplSDL2_InitForOpenGL(Window.GetHandle(), Window.GetContext()); ImGui_ImplSDL2_InitForOpenGL(Window.GetHandle(), Window.GetContext());
ImGui_ImplOpenGL3_Init("#version 460 core"); 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() void EditorSystem::Draw()
@ -152,11 +152,16 @@ void EditorSystem::Draw()
ImGui::ResetMouseDragDelta(); ImGui::ResetMouseDragDelta();
} }
if(MainMenuBar_)
{
MainMenuBar_->Draw();
}
ImGui::ShowDemoWindow(); ImGui::ShowDemoWindow();
for (int i = 0; i < MAX_EDITORS; ++i) for (int i = 0; i < MAX_EDITORS; ++i)
{ {
EditorWindow* editor = Windows[i]; EditorWindow* editor = Windows_[i];
if(editor == nullptr || !editor->IsOpen()) continue; if(editor == nullptr || !editor->IsOpen()) continue;
editor->Draw(); editor->Draw();
} }
@ -168,6 +173,9 @@ void EditorSystem::Draw()
void EditorSystem::Shutdown() void EditorSystem::Shutdown()
{ {
delete MainMenuBar_;
for(auto it : Windows_) delete it;
// Shutdown ImGui // Shutdown ImGui
ImGui_ImplOpenGL3_Shutdown(); ImGui_ImplOpenGL3_Shutdown();
ImGui_ImplSDL2_Shutdown(); ImGui_ImplSDL2_Shutdown();

View File

@ -19,15 +19,15 @@ using namespace OpenShaderDesigner;
void EditorWindow::Open() void EditorWindow::Open()
{ {
if(bOpen) return; if(bOpen_) return;
bOpen = true; bOpen_ = true;
OnOpen(); OnOpen();
} }
void EditorWindow::Draw() void EditorWindow::Draw()
{ {
const bool prev = bOpen; const bool prev = bOpen_;
if(ImGui::Begin(Title.c_str(), &bOpen, Flags)) if(ImGui::Begin(Title.c_str(), &bOpen_, Flags_))
{ {
if(HasMenuBar()) if(HasMenuBar())
{ {
@ -43,24 +43,24 @@ void EditorWindow::Draw()
} }
ImGui::End(); ImGui::End();
if(bOpen != prev) if(bOpen_ != prev)
{ {
bOpen ? OnOpen() : OnClose(); bOpen_ ? OnOpen() : OnClose();
} }
} }
void EditorWindow::Close() void EditorWindow::Close()
{ {
if(!bOpen) return; if(!bOpen_) return;
bOpen = false; bOpen_ = false;
OnClose(); OnClose();
} }
EditorWindow::EditorWindow(const std::string &title, ImGuiWindowFlags flags) EditorWindow::EditorWindow(const std::string &title, ImGuiWindowFlags flags)
: Title(title) : Title(title)
, Flags(flags) , Flags_(flags)
, bOpen(false) , bOpen_(false)
{ {
} }

View File

@ -19,8 +19,8 @@ using namespace OpenShaderDesigner;
Profiler::Profiler() Profiler::Profiler()
: EditorWindow("\uf214 Profiler", 0) : EditorWindow("\uf214 Profiler", 0)
, Frame(0), Deltas{ 0 } , Frame_(0), Deltas_{ 0 }
, Timer() , Timer_()
{ {
EventSystem::RegisterHandler<BeginFrame>(this); EventSystem::RegisterHandler<BeginFrame>(this);
EventSystem::RegisterHandler<EndFrame>(this); EventSystem::RegisterHandler<EndFrame>(this);
@ -34,19 +34,19 @@ Profiler::~Profiler()
void Profiler::DrawWindow() void Profiler::DrawWindow()
{ {
ImGui::Text("Frame #%d", Frame); ImGui::Text("Frame #%d", Frame_);
ImGui::Text("FPS: %07.02f (%06.02f ms)", 1.0 / Deltas[LAST], 1000.0 * Deltas[LAST]); ImGui::Text("FPS: %07.02f (%06.02f ms)", 1.0 / Deltas_[LAST], 1000.0 * Deltas_[LAST]);
} }
bool Profiler::HandleEvent(const EventHandler<BeginFrame>::HandledType* event) bool Profiler::HandleEvent(const EventHandler<BeginFrame>::HandledType* event)
{ {
++Frame; ++Frame_;
Timer.Reset(); Timer_.Reset();
return false; return false;
} }
bool Profiler::HandleEvent(const EventHandler<EndFrame>::HandledType* event) bool Profiler::HandleEvent(const EventHandler<EndFrame>::HandledType* event)
{ {
Deltas[END] = Timer.Poll(); Deltas_[END] = Timer_.Poll();
return false; return false;
} }

View File

@ -15,6 +15,7 @@
#include <iostream> #include <iostream>
#include <Core/Engine.h> #include <Core/Engine.h>
#include <Editor/EditorSystem.h>
int main(int, char**) int main(int, char**)
{ {

View File

@ -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 <Editor/EditorSystem.h>
#include <FileSystem/FileManager.h>
#include <Core/Console.h>
#include <imgui-docking/misc/cpp/imgui_stdlib.h>
#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>();
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>();
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<FileID> 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
}

View File

@ -0,0 +1,3 @@
//
// Created by Maddie on 9/11/2024.
//

View File

@ -210,8 +210,8 @@ void Node::Draw(ImGuiID id)
ShaderGraph::ShaderGraph() ShaderGraph::ShaderGraph()
: EditorWindow("\uED46 Shader Graph", 0) : EditorWindow("\uED46 Shader Graph", 0)
, GrabFocus(false) , GrabFocus_(false)
, State(*this) , State_(*this)
{ {
} }
@ -223,7 +223,7 @@ void ShaderGraph::OnOpen()
{ {
EditorSystem::Open<Inspector>()->Graph = this; EditorSystem::Open<Inspector>()->Graph = this;
GrabFocus = true; GrabFocus_ = true;
} }
@ -236,18 +236,18 @@ void ShaderGraph::DrawWindow()
ImNodeGraph::SetGraphValidation(ValidateConnection); ImNodeGraph::SetGraphValidation(ValidateConnection);
if(GrabFocus) if(GrabFocus_)
{ {
GrabFocus = false; GrabFocus_ = false;
ImGui::SetWindowFocus(); ImGui::SetWindowFocus();
ImGui::SetNavWindow(ImGui::GetCurrentWindow()); 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(); DrawContextMenu();
@ -257,14 +257,15 @@ void ShaderGraph::DrawWindow()
ImNodeGraph::BeginGraphPostOp("ShaderGraph"); 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(); if(ImGui::IsKeyPressed(ImGuiKey_C)) Copy();
for(ImGuiID node : selected) if(ImGui::IsKeyPressed(ImGuiKey_P)) Paste(ImGui::GetMousePos());
{ if(ImGui::IsKeyPressed(ImGuiKey_X)) { Copy(); Erase(); }
State.Nodes.erase(ImNodeGraph::GetUserID(node).Int);
}
selected.Clear();
} }
ImNodeGraph::EndGraphPostOp(); ImNodeGraph::EndGraphPostOp();
@ -275,7 +276,7 @@ void ShaderGraph::DrawContextMenu()
{ {
if(ImGui::IsMouseClicked(ImGuiMouseButton_Right)) if(ImGui::IsMouseClicked(ImGuiMouseButton_Right))
{ {
ContextMenuPosition = ImNodeGraph::ScreenToGrid(ImGui::GetMousePos()); ContextMenuPosition_ = ImNodeGraph::ScreenToGrid(ImGui::GetMousePos());
} }
if(ImGui::BeginPopupContextWindow("graph_context")) if(ImGui::BeginPopupContextWindow("graph_context"))
@ -286,7 +287,7 @@ void ShaderGraph::DrawContextMenu()
Copy(); Copy();
Erase(); Erase();
} }
if(ImGui::MenuItem("Paste", "Ctrl+V", false, false)) Paste(ContextMenuPosition); if(ImGui::MenuItem("Paste", "Ctrl+V", false, false)) Paste(ContextMenuPosition_);
ImGui::Separator(); ImGui::Separator();
@ -295,7 +296,7 @@ void ShaderGraph::DrawContextMenu()
ImGui::Separator(); ImGui::Separator();
// Create Nodes // Create Nodes
ImVec2 position = ContextMenuPosition; ImVec2 position = ContextMenuPosition_;
std::stack<ContextID> context; context.push(0); std::stack<ContextID> context; context.push(0);
@ -319,7 +320,7 @@ void ShaderGraph::DrawContextMenu()
{ {
if(ImGui::MenuItem(item.Name.c_str())) if(ImGui::MenuItem(item.Name.c_str()))
{ {
Graph.State.Nodes.insert(item.Constructor(Graph, Location)); Graph.State_.Nodes.insert(item.Constructor(Graph, Location));
} }
} }
else else
@ -360,18 +361,31 @@ void ShaderGraph::DrawContextMenu()
} }
} }
void ShaderGraph::Copy() {} void ShaderGraph::Copy()
void ShaderGraph::Erase() {} {
}
void ShaderGraph::Erase()
{
auto& selected = ImNodeGraph::GetSelected();
for(ImGuiID node : selected)
{
State_.Nodes.erase(ImNodeGraph::GetUserID(node).Int);
}
selected.Clear();
}
void ShaderGraph::Paste(ImVec2) {} void ShaderGraph::Paste(ImVec2) {}
Node* ShaderGraph::FindNode(ImPinPtr ptr) 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) 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; auto& pins = ptr.Direction ? node->IO.Outputs : node->IO.Inputs;
int idx = ImNodeGraph::GetUserID(ptr).Int; int idx = ImNodeGraph::GetUserID(ptr).Int;
if(ptr.Direction) idx *= -1; if(ptr.Direction) idx *= -1;
@ -410,12 +424,12 @@ void ShaderGraph::Register(const std::filesystem::path& path, ConstructorPtr con
if(node == 0 || node != child) if(node == 0 || node != child)
{ {
node = ContextMenu.insert({ decomp.top(), nullptr }, node); node = ContextMenu.insert({ decomp.top(), nullptr }, node, -1);
decomp.pop(); decomp.pop();
} }
} }
ContextMenu.insert({ name, constructor }, node); ContextMenu.insert({ name, constructor }, node, -1);
} }
Inspector::Inspector() Inspector::Inspector()

169
Source/Project/Project.cpp Normal file
View File

@ -0,0 +1,169 @@
//
// Created by Maddie on 9/14/2024.
//
#include <Core/Engine.h>
#include <Editor/EditorSystem.h>
#include <Project/Project.h>
#include <fstream>
#include <Core/Console.h>
#include <portable-file-dialogs/portable-file-dialogs.h>
#include <rapidjson/document.h>
#include <rapidjson/istreamwrapper.h>
#include <rapidjson/ostreamwrapper.h>
#include <rapidjson/prettywriter.h>
OpenShaderDesigner::Project::Project()
: ProjectFile_(NULL)
{
}
OpenShaderDesigner::Project::~Project()
{
}
void OpenShaderDesigner::Project::DrawMenuBar()
{
FileManager* filesystem = EditorSystem::Get<FileManager>();
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()
{
}

View File

@ -8,32 +8,32 @@ Size=400,400
Collapsed=0 Collapsed=0
[Window][Dear ImGui Demo] [Window][Dear ImGui Demo]
Pos=3070,364 Pos=3070,104
Size=370,711 Size=370,884
Collapsed=0 Collapsed=0
DockId=0x00000008,0 DockId=0x00000008,0
[Window][ Console] [Window][ Console]
Pos=303,1077 Pos=468,990
Size=3137,340 Size=2972,427
Collapsed=0 Collapsed=0
DockId=0x00000004,0 DockId=0x00000004,0
[Window][ Profiler] [Window][ Profiler]
Pos=0,1077 Pos=0,990
Size=301,340 Size=466,427
Collapsed=0 Collapsed=0
DockId=0x00000003,0 DockId=0x00000003,0
[Window][ Shader Graph] [Window][ Shader Graph]
Pos=0,0 Pos=0,24
Size=3068,1075 Size=3068,964
Collapsed=0 Collapsed=0
DockId=0x00000005,0 DockId=0x00000005,0
[Window][WindowOverViewport_11111111] [Window][WindowOverViewport_11111111]
Pos=0,0 Pos=0,24
Size=3440,1417 Size=3440,1393
Collapsed=0 Collapsed=0
[Window][Example: Custom rendering] [Window][Example: Custom rendering]
@ -65,19 +65,29 @@ Size=487,534
Collapsed=0 Collapsed=0
[Window][Inspector] [Window][Inspector]
Pos=3070,0 Pos=3070,24
Size=370,362 Size=370,78
Collapsed=0 Collapsed=0
DockId=0x00000007,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] [Docking][Data]
DockSpace ID=0x7C6B3D9B Window=0xA87D555D Pos=0,0 Size=3440,1417 Split=Y DockSpace ID=0x7C6B3D9B Window=0xA87D555D Pos=0,24 Size=3440,1393 Split=Y
DockNode ID=0x00000001 Parent=0x7C6B3D9B SizeRef=3440,378 Split=X DockNode ID=0x00000001 Parent=0x7C6B3D9B SizeRef=3440,964 Split=X
DockNode ID=0x00000005 Parent=0x00000001 SizeRef=3068,1417 CentralNode=1 Selected=0xD4C89E35 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=0x00000006 Parent=0x00000001 SizeRef=370,1417 Split=Y Selected=0xE7039252
DockNode ID=0x00000007 Parent=0x00000006 SizeRef=370,127 Selected=0xE7039252 DockNode ID=0x00000007 Parent=0x00000006 SizeRef=370,78 Selected=0xE7039252
DockNode ID=0x00000008 Parent=0x00000006 SizeRef=370,249 Selected=0xE87781F4 DockNode ID=0x00000008 Parent=0x00000006 SizeRef=370,884 Selected=0xE87781F4
DockNode ID=0x00000002 Parent=0x7C6B3D9B SizeRef=3440,340 Split=X Selected=0xE9F1AFD1 DockNode ID=0x00000002 Parent=0x7C6B3D9B SizeRef=3440,427 Split=X Selected=0xE9F1AFD1
DockNode ID=0x00000003 Parent=0x00000002 SizeRef=301,448 Selected=0xAC4B19AE DockNode ID=0x00000003 Parent=0x00000002 SizeRef=466,448 Selected=0xAC4B19AE
DockNode ID=0x00000004 Parent=0x00000002 SizeRef=3137,448 Selected=0xE9F1AFD1 DockNode ID=0x00000004 Parent=0x00000002 SizeRef=2972,448 Selected=0x9E7C6CAA