diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..5e7c904 --- /dev/null +++ b/.clang-format @@ -0,0 +1,139 @@ +--- +# Core +Language: Cpp +Standard: Cpp11 +ColumnLimit: '0' # No limit + +### Bin pack ### +BinPackArguments: 'true' +BinPackParameters: 'true' + +# Includes +SortIncludes: 'true' +IncludeBlocks: Regroup +IncludeCategories: + # Current Project + - Regex: '"' + Priority: 001 + + # Custom Project Categories... + + # Dependecies + - Regex: '<' + Priority: 500 + + # Custom Deependencies Categories... + + # C++ includes + - Regex: '[^.h .hpp]>' + Priority: 998 + + # C includes + - Regex: '<[^/\n]+[.]h>' + Priority: 999 + +# Braces +BreakBeforeBraces: Custom +BraceWrapping: + AfterCaseLabel: true + AfterClass: true + AfterControlStatement: true + AfterEnum: true + AfterFunction: true + AfterNamespace: false + AfterObjCDeclaration: true + AfterStruct: true + AfterUnion: true + AfterExternBlock: true + BeforeCatch: true + BeforeElse: true + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true + +# Indentation +UseTab: ForIndentation +TabWidth: '4' +IndentWidth: '4' +ContinuationIndentWidth: '4' +ConstructorInitializerIndentWidth: '4' +IndentCaseLabels: 'false' +IndentWrappedFunctionNames: 'true' +IndentPPDirectives: BeforeHash +NamespaceIndentation: None +AccessModifierOffset: '-4' + +# Space +SpaceAfterCStyleCast: 'false' +SpaceAfterLogicalNot: 'false' +SpaceAfterTemplateKeyword: 'false' +SpaceBeforeAssignmentOperators: 'true' +SpaceBeforeCpp11BracedList: 'true' +SpaceBeforeCtorInitializerColon: 'false' +SpaceBeforeInheritanceColon: 'false' +SpaceBeforeParens: ControlStatements +SpaceBeforeRangeBasedForLoopColon: 'true' +SpaceInEmptyParentheses: 'false' +SpacesBeforeTrailingComments: '1' +SpacesInAngles: 'false' +SpacesInCStyleCastParentheses: 'false' +SpacesInContainerLiterals: 'false' +SpacesInParentheses: 'false' +SpacesInSquareBrackets: 'false' + +### Alignment ### +PointerAlignment: Left +DerivePointerAlignment: 'false' +AlignAfterOpenBracket: Align +AlignEscapedNewlines: Left +AlignConsecutiveDeclarations: 'false' +AlignConsecutiveAssignments: 'true' +AlignConsecutiveMacros: 'true' +AlignOperands: 'true' +AlignTrailingComments: 'true' + +### Single Line ### +AllowShortCaseLabelsOnASingleLine: 'true' +AllowShortFunctionsOnASingleLine: Inline +AllowShortLambdasOnASingleLine: Inline +AllowAllArgumentsOnNextLine: 'false' +AllowShortLoopsOnASingleLine: 'false' +AllowShortBlocksOnASingleLine: 'false' +AllowAllParametersOfDeclarationOnNextLine: 'false' +AllowShortIfStatementsOnASingleLine: Never + +### Break ### +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: 'false' +AlwaysBreakTemplateDeclarations: 'Yes' +BreakBeforeBinaryOperators: None +BreakBeforeTernaryOperators: 'false' +BreakInheritanceList: BeforeComma +BreakStringLiterals: 'false' + +# Penalties +PenaltyBreakAssignment: '0' +PenaltyBreakBeforeFirstCallParameter: '0' +PenaltyBreakComment: '0' +PenaltyBreakFirstLessLess: '0' +PenaltyBreakString: '0' +PenaltyBreakTemplateDeclaration: '0' +PenaltyExcessCharacter: '0' +PenaltyReturnTypeOnItsOwnLine: '999999999' # Nope + +# Constructor Initializers +ConstructorInitializerAllOnOneLineOrOnePerLine: 'true' +AllowAllConstructorInitializersOnNextLine: 'true' +BreakConstructorInitializers: BeforeComma + +# Comments +ReflowComments: 'false' +CommentPragmas: '^ TODO@:' +FixNamespaceComments: 'true' + +# Misc +Cpp11BracedListStyle: 'false' +SortUsingDeclarations: 'true' +KeepEmptyLinesAtTheStartOfBlocks: 'false' +MaxEmptyLinesToKeep: '2' diff --git a/CMakeLists.txt b/CMakeLists.txt index 97a4b23..988b550 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,15 +29,20 @@ add_subdirectory(${MIRROR_DIR}/) # Dependencies add_subdirectory(${DEPENDENCIES_DIR}GLAD/) add_subdirectory(${DEPENDENCIES_DIR}GLFW/) +add_subdirectory(${DEPENDENCIES_DIR}) add_subdirectory(${DEPENDENCIES_DIR}spdlog/) add_subdirectory(${DEPENDENCIES_DIR}glm/) add_subdirectory(${DEPENDENCIES_DIR}entt/) -add_subdirectory(${DEPENDENCIES_DIR}imgui/) add_subdirectory(${DEPENDENCIES_DIR}stb_image/) add_subdirectory(${DEPENDENCIES_DIR}yaml-cpp/) add_subdirectory(${DEPENDENCIES_DIR}shaderc/) # Link +target_link_libraries( + imgui + PUBLIC glad + PUBLIC glfw) + target_link_libraries( Engine PRIVATE glad @@ -48,14 +53,10 @@ target_link_libraries( PRIVATE yaml-cpp PRIVATE shaderc) -target_link_libraries( - imgui - PRIVATE glad - PRIVATE glfw) - target_link_libraries( Mirror - PRIVATE Engine) + PRIVATE Engine + PRIVATE imgui) # Precompiled headers target_precompile_headers(Engine PUBLIC ${ENGINE_DIR}src/Engine/ltpch.h) diff --git a/Dependencies/CMakeLists.txt b/Dependencies/CMakeLists.txt index 0b8cb0c..a3cc6bb 100644 --- a/Dependencies/CMakeLists.txt +++ b/Dependencies/CMakeLists.txt @@ -9,22 +9,28 @@ if(MSVC) endif() file(GLOB IMGUI_FILES true ABSOLUTE -${CMAKE_CURRENT_SOURCE_DIR} *.cpp *.h) + ${CMAKE_CURRENT_SOURCE_DIR}/imgui/imgui.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/imgui/imgui_tables.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/imgui/imgui_widgets.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/imgui/imgui_draw.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/imgui/imgui_demo.cpp +) -set(BACKENDS_DIR ${CMAKE_CURRENT_SOURCE_DIR}/backends/) +set(BACKENDS_DIR ${CMAKE_CURRENT_SOURCE_DIR}/imgui/backends/) -include_directories(${CMAKE_CURRENT_SOURCE_DIR}) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/imgui) file(GLOB IMGUI_BACKEND_FILES true ABSOLUTE -${BACKENDS_DIR}imgui_impl_opengl3.cpp ${BACKENDS_DIR}imgui_impl_opengl3.h -# ${BACKENDS_DIR}imgui_impl_vulkan.cpp ${BACKENDS_DIR}imgui_impl_vulkan.h -${BACKENDS_DIR}imgui_impl_glfw.cpp ${BACKENDS_DIR}imgui_impl_glfw.h) + ${BACKENDS_DIR}imgui_impl_opengl3.cpp + ${BACKENDS_DIR}imgui_impl_glfw.cpp + # ${BACKENDS_DIR}imgui_impl_vulkan.cpp ${BACKENDS_DIR}imgui_impl_vulkan.h +) if(WIN32) file(GLOB IMGUI_WINDOWS_BACKEND_FILES true ABSOLUTE ${CMAKE_CURRENT_SOURCE_DIR}/backends/ - ${BACKENDS_DIR}imgui_impl_dx11.cpp ${BACKENDS_DIR}imgui_impl_dx11.h - # ${BACKENDS_DIR}imgui_impl_dx12.cpp ${BACKENDS_DIR}imgui_impl_dx12.h - ${BACKENDS_DIR}imgui_impl_win32.cpp ${BACKENDS_DIR}imgui_impl_win32.h) + ${BACKENDS_DIR}imgui_impl_dx11.cpp + ${BACKENDS_DIR}imgui_impl_win32.cpp +) list(APPEND IMGUI_BACKEND_FILES ${IMGUI_WINDOWS_BACKEND_FILES}) endif() @@ -32,5 +38,10 @@ endif() add_compile_definitions(IMGUI_IMPL_OPENGL_LOADER_GLAD) include_directories(${DEPENDENCIES_DIR}GLAD/include) include_directories(${DEPENDENCIES_DIR}GLFW/include) - +include_directories(${DEPENDENCIES_DIR}glm/) add_library(imgui STATIC ${IMGUI_FILES} ${IMGUI_BACKEND_FILES}) + + +# Copy imconfig.h over +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/Configurations/imgui/imconfig.h + DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/imgui/) diff --git a/Dependencies/Configurations/imgui/imconfig.h b/Dependencies/Configurations/imgui/imconfig.h new file mode 100644 index 0000000..6d39fb1 --- /dev/null +++ b/Dependencies/Configurations/imgui/imconfig.h @@ -0,0 +1,131 @@ +//----------------------------------------------------------------------------- +// COMPILE-TIME OPTIONS FOR DEAR IMGUI +// Runtime options (clipboard callbacks, enabling various features, etc.) can generally be set via the ImGuiIO structure. +// You can use ImGui::SetAllocatorFunctions() before calling ImGui::CreateContext() to rewire memory allocation functions. +//----------------------------------------------------------------------------- +// A) You may edit imconfig.h (and not overwrite it when updating Dear ImGui, or maintain a patch/rebased branch with your modifications to it) +// B) or '#define IMGUI_USER_CONFIG "my_imgui_config.h"' in your project and then add directives in your own file without touching this template. +//----------------------------------------------------------------------------- +// You need to make sure that configuration settings are defined consistently _everywhere_ Dear ImGui is used, which include the imgui*.cpp +// files but also _any_ of your code that uses Dear ImGui. This is because some compile-time options have an affect on data structures. +// Defining those options in imconfig.h will ensure every compilation unit gets to see the same data structure layouts. +// Call IMGUI_CHECKVERSION() from your .cpp files to verify that the data structures your files are using are matching the ones imgui.cpp is using. +//----------------------------------------------------------------------------- + +#pragma once + +//---- Define assertion handler. Defaults to calling assert(). +// If your macro uses multiple statements, make sure is enclosed in a 'do { .. } while (0)' block so it can be used as a single statement. +//#define IM_ASSERT(_EXPR) MyAssert(_EXPR) +//#define IM_ASSERT(_EXPR) ((void)(_EXPR)) // Disable asserts + +//---- Define attributes of all API symbols declarations, e.g. for DLL under Windows +// Using Dear ImGui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility. +// DLL users: heaps and globals are not shared across DLL boundaries! You will need to call SetCurrentContext() + SetAllocatorFunctions() +// for each static/DLL boundary you are calling from. Read "Context and Memory Allocators" section of imgui.cpp for more details. +//#define IMGUI_API __declspec( dllexport ) +//#define IMGUI_API __declspec( dllimport ) + +//---- Don't define obsolete functions/enums/behaviors. Consider enabling from time to time after updating to avoid using soon-to-be obsolete function/names. +//#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS +//#define IMGUI_DISABLE_OBSOLETE_KEYIO // 1.87: disable legacy io.KeyMap[]+io.KeysDown[] in favor io.AddKeyEvent(). This will be folded into IMGUI_DISABLE_OBSOLETE_FUNCTIONS in a few versions. + +//---- Disable all of Dear ImGui or don't implement standard windows. +// It is very strongly recommended to NOT disable the demo windows during development. Please read comments in imgui_demo.cpp. +//#define IMGUI_DISABLE // Disable everything: all headers and source files will be empty. +//#define IMGUI_DISABLE_DEMO_WINDOWS // Disable demo windows: ShowDemoWindow()/ShowStyleEditor() will be empty. Not recommended. +//#define IMGUI_DISABLE_METRICS_WINDOW // Disable metrics/debugger and other debug tools: ShowMetricsWindow() and ShowStackToolWindow() will be empty. + +//---- Don't implement some functions to reduce linkage requirements. +//#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc. (user32.lib/.a, kernel32.lib/.a) +//#define IMGUI_ENABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with Visual Studio] Implement default IME handler (require imm32.lib/.a, auto-link for Visual Studio, -limm32 on command-line for MinGW) +//#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with non-Visual Studio compilers] Don't implement default IME handler (won't require imm32.lib/.a) +//#define IMGUI_DISABLE_WIN32_FUNCTIONS // [Win32] Won't use and link with any Win32 function (clipboard, ime). +//#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS // [OSX] Implement default OSX clipboard handler (need to link with '-framework ApplicationServices', this is why this is not the default). +//#define IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself (e.g. if you don't want to link with vsnprintf) +//#define IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS // Don't implement ImFabs/ImSqrt/ImPow/ImFmod/ImCos/ImSin/ImAcos/ImAtan2 so you can implement them yourself. +//#define IMGUI_DISABLE_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle at all (replace them with dummies) +//#define IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle so you can implement them yourself if you don't want to link with fopen/fclose/fread/fwrite. This will also disable the LogToTTY() function. +//#define IMGUI_DISABLE_DEFAULT_ALLOCATORS // Don't implement default allocators calling malloc()/free() to avoid linking with them. You will need to call ImGui::SetAllocatorFunctions(). +//#define IMGUI_DISABLE_SSE // Disable use of SSE intrinsics even if available + +//---- Include imgui_user.h at the end of imgui.h as a convenience +//#define IMGUI_INCLUDE_IMGUI_USER_H + +//---- Pack colors to BGRA8 instead of RGBA8 (to avoid converting from one to another) +//#define IMGUI_USE_BGRA_PACKED_COLOR + +//---- Use 32-bit for ImWchar (default is 16-bit) to support unicode planes 1-16. (e.g. point beyond 0xFFFF like emoticons, dingbats, symbols, shapes, ancient languages, etc...) +//#define IMGUI_USE_WCHAR32 + +//---- Avoid multiple STB libraries implementations, or redefine path/filenames to prioritize another version +// By default the embedded implementations are declared static and not available outside of Dear ImGui sources files. +//#define IMGUI_STB_TRUETYPE_FILENAME "my_folder/stb_truetype.h" +//#define IMGUI_STB_RECT_PACK_FILENAME "my_folder/stb_rect_pack.h" +//#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION +//#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION + +//---- Use stb_printf's faster implementation of vsnprintf instead of the one from libc (unless IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS is defined) +// Requires 'stb_sprintf.h' to be available in the include path. Compatibility checks of arguments and formats done by clang and GCC will be disabled in order to support the extra formats provided by STB sprintf. +// #define IMGUI_USE_STB_SPRINTF + +//---- Use FreeType to build and rasterize the font atlas (instead of stb_truetype which is embedded by default in Dear ImGui) +// Requires FreeType headers to be available in the include path. Requires program to be compiled with 'misc/freetype/imgui_freetype.cpp' (in this repository) + the FreeType library (not provided). +// On Windows you may use vcpkg with 'vcpkg install freetype --triplet=x64-windows' + 'vcpkg integrate install'. +//#define IMGUI_ENABLE_FREETYPE + +//---- Use stb_truetype to build and rasterize the font atlas (default) +// The only purpose of this define is if you want force compilation of the stb_truetype backend ALONG with the FreeType backend. +//#define IMGUI_ENABLE_STB_TRUETYPE + +//---- Define constructor and implicit cast operators to convert back<>forth between your math types and ImVec2/ImVec4. +// This will be inlined as part of ImVec2 and ImVec4 class declarations. + +#include + +#define IM_VEC2_CLASS_EXTRA \ + bool operator==(glm::vec2 rhs) { return x == rhs.x && y == rhs.y; } \ + bool operator!=(glm::vec2 rhs) { return (*this) == rhs; } \ + bool operator==(ImVec2 rhs) { return x == rhs.x && y == rhs.y; } \ + bool operator!=(ImVec2 rhs) { return (*this) == rhs; } + + +#define IM_VEC4_CLASS_EXTRA \ + bool operator==(glm::vec4 rhs) { return x == rhs.x && y == rhs.y && z == rhs.z && w == rhs.w; } \ + bool operator!=(glm::vec4 rhs) { return (*this) == rhs; } \ + bool operator==(ImVec4 rhs) { return x == rhs.x && y == rhs.y && z == rhs.z && w == rhs.w; } \ + bool operator!=(ImVec4 rhs) { return (*this) == rhs; } + + +//---- Use 32-bit vertex indices (default is 16-bit) is one way to allow large meshes with more than 64K vertices. +// Your renderer backend will need to support it (most example renderer backends support both 16/32-bit indices). +// Another way to allow large meshes while keeping 16-bit indices is to handle ImDrawCmd::VtxOffset in your renderer. +// Read about ImGuiBackendFlags_RendererHasVtxOffset for details. +//#define ImDrawIdx unsigned int + +//---- Override ImDrawCallback signature (will need to modify renderer backends accordingly) +//struct ImDrawList; +//struct ImDrawCmd; +//typedef void (*MyImDrawCallback)(const ImDrawList* draw_list, const ImDrawCmd* cmd, void* my_renderer_user_data); +//#define ImDrawCallback MyImDrawCallback + +//---- Debug Tools: Macro to break in Debugger +// (use 'Metrics->Tools->Item Picker' to pick widgets with the mouse and break into them for easy debugging.) +//#define IM_DEBUG_BREAK IM_ASSERT(0) +//#define IM_DEBUG_BREAK __debugbreak() + +//---- Debug Tools: Have the Item Picker break in the ItemAdd() function instead of ItemHoverable(), +// (which comes earlier in the code, will catch a few extra items, allow picking items other than Hovered one.) +// This adds a small runtime cost which is why it is not enabled by default. +//#define IMGUI_DEBUG_TOOL_ITEM_PICKER_EX + +//---- Debug Tools: Enable slower asserts +//#define IMGUI_DEBUG_PARANOID + +//---- Tip: You can add extra functions within the ImGui:: namespace, here or in your own headers files. +/* +namespace ImGui +{ + void MyFunction(const char* name, const MyMatrix44& v); +} +*/ diff --git a/Dependencies/imgui b/Dependencies/imgui index 419e401..5f3925c 160000 --- a/Dependencies/imgui +++ b/Dependencies/imgui @@ -1 +1 @@ -Subproject commit 419e401d1fe8e9b6e45a31b5c0a27673b5d88fdc +Subproject commit 5f3925c45393cf5e82fd1b106a1548ad68baf52e diff --git a/Mirror/src/EditorLayer.cpp~ b/Mirror/src/EditorLayer.cpp~ new file mode 100644 index 0000000..c6f953c --- /dev/null +++ b/Mirror/src/EditorLayer.cpp~ @@ -0,0 +1,103 @@ +#include "EditorLayer.h" + +#include "Utility/Serializer.h" + +namespace Light { + +EditorLayer::EditorLayer(const std::string& name, const std::vector& args) + : Layer(name), m_SceneDir(args.empty() ? "" : args[0]) +{ + m_Scene = CreateRef(); + + m_PropertiesPanel = CreateRef(); + m_SceneHierarchyPanel = CreateRef(m_Scene, m_PropertiesPanel); + m_ContentBrowserPanel = CreateRef(); + + m_Framebuffer = Framebuffer::Create({ 1, 1, 1 }, GraphicsContext::GetSharedContext()); + + if (m_SceneDir.empty()) + { + m_CameraEntity = m_Scene->CreateEntity("Camera"); + m_CameraEntity.AddComponent(SceneCamera(), true); + + ResourceManager::LoadTexture("Awesomeface", "Assets/Textures/awesomeface.png"); + Entity entity = m_Scene->CreateEntity("Awesomeface", {}); + entity.AddComponent(ResourceManager::GetTexture("Awesomeface"), glm::vec4 { 0.0f, 1.0f, 1.0f, 1.0f }); + } + else + { + SceneSerializer serializer(m_Scene); + LT_ENGINE_ASSERT(serializer.Deserialize(m_SceneDir), "EditorLayer::EditorLayer: failed to de-serialize: ", m_SceneDir); + + m_CameraEntity = m_Scene->GetEntityByTag("Game Camera"); + } +} + +EditorLayer::~EditorLayer() +{ + if (!m_SceneDir.empty()) + { + SceneSerializer serializer(m_Scene); + serializer.Serialize(m_SceneDir); + } +} + +void EditorLayer::OnUpdate(float deltaTime) +{ + m_Scene->OnUpdate(deltaTime); + + m_Direction.x = Input::GetKeyboardKey(Key::A) ? -1.0f : + Input::GetKeyboardKey(Key::D) ? 1.0f : + 0.0f; + + m_Direction.y = Input::GetKeyboardKey(Key::S) ? -1.0f : + Input::GetKeyboardKey(Key::W) ? 1.0f : + 0.0f; + + auto& cameraTranslation = m_CameraEntity.GetComponent().translation; + cameraTranslation += glm::vec3(m_Direction * m_Speed * deltaTime, 0.0f); + + if (Input::GetKeyboardKey(Key::Escape)) + Application::Quit(); +} + +void EditorLayer::OnRender() +{ + m_Scene->OnRender(m_Framebuffer); +} + +void EditorLayer::OnUserInterfaceUpdate() +{ + UserInterface::DockspaceBegin(); + ImGui::ShowDemoWindow(); + + if (ImGui::Begin("Game")) + { + Input::ReceiveGameEvents(ImGui::IsWindowFocused()); + ImVec2 regionAvail = ImGui::GetContentRegionAvail(); + + if (m_AvailableContentRegionPrev != regionAvail) + { + m_Framebuffer->Resize({ regionAvail.x, regionAvail.y }); + auto& camera = m_CameraEntity.GetComponent().camera; + camera.SetViewportSize(regionAvail.x, regionAvail.y); + + m_AvailableContentRegionPrev = regionAvail; + } + + if (GraphicsContext::GetGraphicsAPI() == GraphicsAPI::DirectX) + ImGui::Image(m_Framebuffer->GetColorAttachment(), regionAvail); + else + ImGui::Image(m_Framebuffer->GetColorAttachment(), regionAvail, ImVec2(0, 1), ImVec2(1, 0)); + } + ImGui::End(); + + // Panels + m_SceneHierarchyPanel->OnUserInterfaceUpdate(); + m_PropertiesPanel->OnUserInterfaceUpdate(); + m_ContentBrowserPanel->OnUserInterfaceUpdate(); + + UserInterface::DockspaceEnd(); +} + +} // namespace Light diff --git a/Mirror/src/Panels/ContentBrowser.cpp b/Mirror/src/Panels/ContentBrowser.cpp index fe634a3..ebecf35 100644 --- a/Mirror/src/Panels/ContentBrowser.cpp +++ b/Mirror/src/Panels/ContentBrowser.cpp @@ -1,11 +1,16 @@ #include "ContentBrowser.h" +#include #include namespace Light { ContentBrowserPanel::ContentBrowserPanel() - : m_CurrentDirectory("Assets"), m_AssetsPath("Assets") {} + : m_CurrentDirectory("Assets"), m_AssetsPath("Assets") +{ + // ResourceManager::LoadTexture("_Assets_Directory", "EngineResources/Icons/Asset_Directory"); + // m_DirectoryTexture = ResourceManager::GetTexture("_Assets_Directory"); +} void ContentBrowserPanel::OnUserInterfaceUpdate() { @@ -19,30 +24,66 @@ void ContentBrowserPanel::OnUserInterfaceUpdate() } } - for (auto& dirEntry : std::filesystem::directory_iterator(m_CurrentDirectory)) - { - const auto& path = dirEntry.path(); - { - auto relativePath = std::filesystem::relative(path, m_AssetsPath); - std::string relativePathString = relativePath.string(); - if (dirEntry.is_directory()) + ImVec2 regionAvail = ImGui::GetContentRegionAvail(); + uint32_t cellSize = m_FileSize + m_FilePadding; + uint32_t columnCount = std::clamp(static_cast(std::floor(regionAvail.x / cellSize)), 1u, 64u); + + if (ImGui::BeginTable("ContentBrowser", columnCount)) + { + for (auto& dirEntry : std::filesystem::directory_iterator(m_CurrentDirectory)) + { + ImGui::TableNextColumn(); + LT_ENGINE_TRACE("File: ", dirEntry.path().string()); + FileType assetType; + std::string extension = dirEntry.path().extension().string(); + + // TODO: Tidy up + assetType = extension.empty() ? FileType::Directory : + extension == ".txt" ? FileType::Text : + extension == ".png" ? FileType::Image : + FileType::None; + + if (assetType == FileType::None) { - if (ImGui::Button(relativePathString.c_str())) - { - m_CurrentDirectory /= path.filename(); - } + LT_ENGINE_ERROR("Unsupported file exetnsion: {}", extension); + return; } - else + + const auto& path = dirEntry.path(); { - if (ImGui::Button(relativePathString.c_str())) + auto relativePath = std::filesystem::relative(path, m_AssetsPath); + std::string relativePathString = relativePath.string(); + + switch (assetType) { + case FileType::Directory: + if (ImGui::Button(relativePathString.c_str(), ImVec2(m_FileSize, m_FileSize))) + { + m_CurrentDirectory /= path.filename(); + } + ImGui::Text("Test"); + break; + case FileType::Image: + if (ImGui::Button(relativePathString.c_str(), ImVec2(m_FileSize, m_FileSize))) + { + } + break; + case FileType::Text: + if (ImGui::Button(relativePathString.c_str(), ImVec2(m_FileSize, m_FileSize))) + { + } + default: + break; } } } - ImGui::End(); + ImGui::EndTable(); } + ImGui::DragInt("Size", (int*)&m_FileSize, 32u, 512u); + ImGui::DragInt("Padding", (int*)&m_FilePadding, 32u, 512u); + ImGui::End(); } } // namespace Light diff --git a/Mirror/src/Panels/ContentBrowser.h b/Mirror/src/Panels/ContentBrowser.h index 4f421aa..3181871 100644 --- a/Mirror/src/Panels/ContentBrowser.h +++ b/Mirror/src/Panels/ContentBrowser.h @@ -2,22 +2,36 @@ #include "Panel.h" +#include #include namespace Light { - class ContentBrowserPanel : public Panel +class ContentBrowserPanel: public Panel +{ +private: + enum FileType { - private: - - public: - ContentBrowserPanel(); - - void OnUserInterfaceUpdate(); - - private: - std::filesystem::path m_CurrentDirectory; - const std::filesystem::path m_AssetsPath; + None = 0, + Directory, + Text, + Image, }; -} \ No newline at end of file +public: + ContentBrowserPanel(); + + void OnUserInterfaceUpdate(); + +private: + std::filesystem::path m_CurrentDirectory; + const std::filesystem::path m_AssetsPath; + + // TODO: Save configuration + uint32_t m_FileSize = 256u; + uint32_t m_FilePadding = 16u; + + Ref m_DirectoryTexture; +}; + +} // namespace Light diff --git a/Mirror/src/Panels/PropertiesPanel.cpp b/Mirror/src/Panels/PropertiesPanel.cpp index 0e4165d..939e899 100644 --- a/Mirror/src/Panels/PropertiesPanel.cpp +++ b/Mirror/src/Panels/PropertiesPanel.cpp @@ -1,240 +1,232 @@ #include "PropertiesPanel.h" #include "Scene/Components.h" - #include "Utility/ResourceManager.h" #include #include - #include #include namespace Light { - void PropertiesPanel::OnUserInterfaceUpdate() +void PropertiesPanel::OnUserInterfaceUpdate() +{ + ImGui::Begin("Properties"); + + if (m_EntityContext.IsValid()) { - ImGui::Begin("Properties"); - - if (m_EntityContext.IsValid()) + if (m_EntityContext.HasComponent()) { - if (m_EntityContext.HasComponent()) + auto& tagComponent = m_EntityContext.GetComponent(); + + char buffer[256]; + memset(buffer, 0, sizeof(buffer)); + std::strncpy(buffer, tagComponent.tag.c_str(), sizeof(buffer)); + + if (ImGui::InputText("##Tag", buffer, sizeof(buffer))) + tagComponent.tag = std::string(buffer); + } + + ImGui::SameLine(); + ImGui::PushItemWidth(-1); + + if (ImGui::Button("Add component")) + ImGui::OpenPopup("Components"); + + if (ImGui::BeginPopup("Components")) + { + if (ImGui::Selectable("SpriteRenderer", false, m_EntityContext.HasComponent() ? ImGuiSelectableFlags_Disabled : NULL)) + m_EntityContext.AddComponent(Light::ResourceManager::GetTexture("awesomeface")); + + if (ImGui::Selectable("Camera", false, m_EntityContext.HasComponent() ? ImGuiSelectableFlags_Disabled : NULL)) + m_EntityContext.AddComponent(); + + ImGui::EndPopup(); + } + ImGui::PopItemWidth(); + + DrawComponent("Transform Component", m_EntityContext, [&](auto& transformComponent) { + DrawVec3Control("Translation", transformComponent.translation); + }); + + DrawComponent("SpriteRenderer Component", m_EntityContext, [&](auto& spriteRendererComponent) { + ImGui::ColorEdit4("Color", &spriteRendererComponent.tint[0]); + }); + + DrawComponent("Camera Component", m_EntityContext, [&](auto& cameraComponent) { + auto& camera = cameraComponent.camera; + + SceneCamera::ProjectionType projectionType = camera.GetProjectionType(); + const char* projectionTypesString[] = { "Orthographic", "Perspective" }; + + if (ImGui::BeginCombo("ProjectionType", projectionTypesString[(int)projectionType])) { - auto& tagComponent = m_EntityContext.GetComponent(); - - char buffer[256]; - memset(buffer, 0, sizeof(buffer)); - std::strncpy(buffer, tagComponent.tag.c_str(), sizeof(buffer)); - - if (ImGui::InputText("##Tag", buffer, sizeof(buffer))) - tagComponent.tag = std::string(buffer); - - } - - ImGui::SameLine(); - ImGui::PushItemWidth(-1); - - if (ImGui::Button("Add component")) - ImGui::OpenPopup("Components"); - - if (ImGui::BeginPopup("Components")) - { - if (ImGui::Selectable("SpriteRenderer", false, m_EntityContext.HasComponent() ? ImGuiSelectableFlags_Disabled : NULL)) - m_EntityContext.AddComponent(Light::ResourceManager::GetTexture("awesomeface")); - - if (ImGui::Selectable("Camera", false, m_EntityContext.HasComponent() ? ImGuiSelectableFlags_Disabled : NULL)) - m_EntityContext.AddComponent(); - - ImGui::EndPopup(); - } - ImGui::PopItemWidth(); - - DrawComponent("Transform Component", m_EntityContext, [&](auto& transformComponent) - { - DrawVec3Control("Translation", transformComponent.translation); - }); - - DrawComponent("SpriteRenderer Component", m_EntityContext, [&](auto& spriteRendererComponent) - { - ImGui::ColorEdit4("Color", &spriteRendererComponent.tint[0]); - }); - - DrawComponent("Camera Component", m_EntityContext, [&](auto& cameraComponent) - { - auto& camera = cameraComponent.camera; - - SceneCamera::ProjectionType projectionType = camera.GetProjectionType(); - const char* projectionTypesString[] = { "Orthographic", "Perspective" }; - - if (ImGui::BeginCombo("ProjectionType", projectionTypesString[(int)projectionType])) + for (int i = 0; i < 2; i++) { - for (int i = 0; i < 2; i++) + const bool isSelected = (int)projectionType == i; + if (ImGui::Selectable(projectionTypesString[i], isSelected)) { - const bool isSelected = (int)projectionType == i; - if (ImGui::Selectable(projectionTypesString[i], isSelected)) - { - projectionType = (SceneCamera::ProjectionType)i; - camera.SetProjectionType(projectionType); - } - - if (isSelected) - ImGui::SetItemDefaultFocus(); + projectionType = (SceneCamera::ProjectionType)i; + camera.SetProjectionType(projectionType); } - ImGui::EndCombo(); + if (isSelected) + ImGui::SetItemDefaultFocus(); } - if (projectionType == SceneCamera::ProjectionType::Orthographic) - { - float orthoSize, nearPlane, farPlane; - - orthoSize = camera.GetOrthographicSize(); - nearPlane = camera.GetOrthographicNearPlane(); - farPlane = camera.GetOrthographicFarPlane(); - - if (ImGui::DragFloat("Orthographic Size", &orthoSize)) - camera.SetOrthographicSize(orthoSize); - - if (ImGui::DragFloat("Near Plane", &nearPlane)) - camera.SetOrthographicNearPlane(nearPlane); - - if (ImGui::DragFloat("Far Plane", &farPlane)) - camera.SetOrthographicFarPlane(farPlane); - } - - else // perspective - { - float verticalFOV, nearPlane, farPlane; - - verticalFOV = glm::degrees(camera.GetPerspectiveVerticalFOV()); - nearPlane = camera.GetPerspectiveNearPlane(); - farPlane = camera.GetPerspectiveFarPlane(); - - if (ImGui::DragFloat("Vertical FOV", &verticalFOV)) - camera.SetPerspectiveVerticalFOV(glm::radians(verticalFOV)); - - if (ImGui::DragFloat("Near Plane", &nearPlane)) - camera.SetPerspectiveNearPlane(nearPlane); - - if (ImGui::DragFloat("Far Plane", &farPlane)) - camera.SetPerspectiveFarPlane(farPlane); - } - - ImGui::Separator(); - }); - - - } - - ImGui::End(); - } - - void PropertiesPanel::SetEntityContext(Entity entity) - { - m_EntityContext = entity; - } - - void PropertiesPanel::DrawVec3Control(const std::string& label, glm::vec3& values, float resetValue /*= 0.0f*/, float columnWidth /*= 100.0f*/) - { - ImGuiIO& io = ImGui::GetIO(); - - auto boldFont = io.Fonts->Fonts[0]; - - ImGui::Columns(2); - ImGui::SetColumnWidth(0, columnWidth); - ImGui::Text(label.c_str()); - ImGui::NextColumn(); - - ImGui::PushMultiItemsWidths(3, ImGui::CalcItemWidth()); - ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2{ 0, 0 }); - - float lineHeight = GImGui->Font->FontSize + GImGui->Style.FramePadding.y * 2.0f; - ImVec2 buttonSize = { lineHeight + 3.0f, lineHeight }; - - ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.8f, 0.1f, 0.15f, 1.0f)); - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.9f, 0.2f, 0.2f, 1.0f)); - ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0.8f, 0.1f, 0.15f, 1.0f)); - ImGui::PushFont(boldFont); - if (ImGui::Button("X", buttonSize)) - values.x = resetValue; - ImGui::PopFont(); - ImGui::PopStyleColor(3); - - ImGui::SameLine(); - ImGui::DragFloat("##X", &values.x, 0.1f); - ImGui::PopItemWidth(); - ImGui::SameLine(); - - ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.2f, 0.7f, 0.2f, 1.0f)); - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.3f, 0.8f, 0.3f, 1.0f)); - ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0.2f, 0.7f, 0.2f, 1.0f)); - ImGui::PushFont(boldFont); - if (ImGui::Button("Y", buttonSize)) - values.y = resetValue; - ImGui::PopFont(); - ImGui::PopStyleColor(3); - - ImGui::SameLine(); - ImGui::DragFloat("##Y", &values.y, 0.1f); - ImGui::PopItemWidth(); - ImGui::SameLine(); - - - ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.1f, 0.25f, 0.8f, 1.0f)); - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.2f, 0.35f, 0.9f, 1.0f)); - ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0.1f, 0.25f, 0.8f, 1.0f)); - ImGui::PushFont(boldFont); - if (ImGui::Button("Z", buttonSize)) - values.z = resetValue; - ImGui::PopFont(); - ImGui::PopStyleColor(3); - - ImGui::SameLine(); - ImGui::DragFloat("##Z", &values.z, 0.1f); - ImGui::PopItemWidth(); - - ImGui::PopStyleVar(); - ImGui::Columns(1); - } - - - template - void PropertiesPanel::DrawComponent(const std::string& name, Entity entity, UIFunction userInterfaceFunction) - { - if (!entity.HasComponent()) - return; - - auto& component = entity.GetComponent(); - - ImVec2 regionAvail = ImGui::GetContentRegionAvail(); - - ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_DefaultOpen | ImGuiTreeNodeFlags_SpanAvailWidth | ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_AllowItemOverlap | ImGuiTreeNodeFlags_FramePadding; - - ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, { 4, 4 }); - float lineHeight = GImGui->Font->FontSize + GImGui->Style.FramePadding.y * 2.0f; - ImGui::Separator(); - - if (ImGui::TreeNodeEx((void*)typeid(ComponentType).hash_code(), flags, name.c_str())) - { - ImGui::PopStyleVar(); - - ImGui::SameLine(regionAvail.x - lineHeight * .5f); - if (ImGui::Button("+", { lineHeight, lineHeight })) - ImGui::OpenPopup("ComponentSettings"); - - if (ImGui::BeginPopup("ComponentSettings")) - { - if (ImGui::Selectable("Remove component")) - entity.RemoveComponent(); - - ImGui::EndPopup(); + ImGui::EndCombo(); } - userInterfaceFunction(component); - ImGui::TreePop(); - } - else - ImGui::PopStyleVar(); + if (projectionType == SceneCamera::ProjectionType::Orthographic) + { + float orthoSize, nearPlane, farPlane; + + orthoSize = camera.GetOrthographicSize(); + nearPlane = camera.GetOrthographicNearPlane(); + farPlane = camera.GetOrthographicFarPlane(); + + if (ImGui::DragFloat("Orthographic Size", &orthoSize)) + camera.SetOrthographicSize(orthoSize); + + if (ImGui::DragFloat("Near Plane", &nearPlane)) + camera.SetOrthographicNearPlane(nearPlane); + + if (ImGui::DragFloat("Far Plane", &farPlane)) + camera.SetOrthographicFarPlane(farPlane); + } + + else // perspective + { + float verticalFOV, nearPlane, farPlane; + + verticalFOV = glm::degrees(camera.GetPerspectiveVerticalFOV()); + nearPlane = camera.GetPerspectiveNearPlane(); + farPlane = camera.GetPerspectiveFarPlane(); + + if (ImGui::DragFloat("Vertical FOV", &verticalFOV)) + camera.SetPerspectiveVerticalFOV(glm::radians(verticalFOV)); + + if (ImGui::DragFloat("Near Plane", &nearPlane)) + camera.SetPerspectiveNearPlane(nearPlane); + + if (ImGui::DragFloat("Far Plane", &farPlane)) + camera.SetPerspectiveFarPlane(farPlane); + } + + ImGui::Separator(); + }); } -} \ No newline at end of file + ImGui::End(); +} + +void PropertiesPanel::SetEntityContext(Entity entity) +{ + m_EntityContext = entity; +} + +void PropertiesPanel::DrawVec3Control(const std::string& label, glm::vec3& values, float resetValue /*= 0.0f*/, float columnWidth /*= 100.0f*/) +{ + ImGuiIO& io = ImGui::GetIO(); + + auto boldFont = io.Fonts->Fonts[0]; + + ImGui::Columns(2); + ImGui::SetColumnWidth(0, columnWidth); + ImGui::Text(label.c_str()); + ImGui::NextColumn(); + + ImGui::PushMultiItemsWidths(3, ImGui::CalcItemWidth()); + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2 { 0, 0 }); + + float lineHeight = GImGui->Font->FontSize + GImGui->Style.FramePadding.y * 2.0f; + ImVec2 buttonSize = { lineHeight + 3.0f, lineHeight }; + + ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.8f, 0.1f, 0.15f, 1.0f)); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.9f, 0.2f, 0.2f, 1.0f)); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0.8f, 0.1f, 0.15f, 1.0f)); + ImGui::PushFont(boldFont); + if (ImGui::Button("X", buttonSize)) + values.x = resetValue; + ImGui::PopFont(); + ImGui::PopStyleColor(3); + + ImGui::SameLine(); + ImGui::DragFloat("##X", &values.x, 0.1f); + ImGui::PopItemWidth(); + ImGui::SameLine(); + + ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.2f, 0.7f, 0.2f, 1.0f)); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.3f, 0.8f, 0.3f, 1.0f)); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0.2f, 0.7f, 0.2f, 1.0f)); + ImGui::PushFont(boldFont); + if (ImGui::Button("Y", buttonSize)) + values.y = resetValue; + ImGui::PopFont(); + ImGui::PopStyleColor(3); + + ImGui::SameLine(); + ImGui::DragFloat("##Y", &values.y, 0.1f); + ImGui::PopItemWidth(); + ImGui::SameLine(); + + + ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.1f, 0.25f, 0.8f, 1.0f)); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.2f, 0.35f, 0.9f, 1.0f)); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0.1f, 0.25f, 0.8f, 1.0f)); + ImGui::PushFont(boldFont); + if (ImGui::Button("Z", buttonSize)) + values.z = resetValue; + ImGui::PopFont(); + ImGui::PopStyleColor(3); + + ImGui::SameLine(); + ImGui::DragFloat("##Z", &values.z, 0.1f); + ImGui::PopItemWidth(); + + ImGui::PopStyleVar(); + ImGui::Columns(1); +} + + +template +void PropertiesPanel::DrawComponent(const std::string& name, Entity entity, UIFunction userInterfaceFunction) +{ + if (!entity.HasComponent()) + return; + + auto& component = entity.GetComponent(); + + ImVec2 regionAvail = ImGui::GetContentRegionAvail(); + + ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_DefaultOpen | ImGuiTreeNodeFlags_SpanAvailWidth | ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_AllowItemOverlap | ImGuiTreeNodeFlags_FramePadding; + + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, { 4, 4 }); + float lineHeight = GImGui->Font->FontSize + GImGui->Style.FramePadding.y * 2.0f; + ImGui::Separator(); + + if (ImGui::TreeNodeEx((void*)typeid(ComponentType).hash_code(), flags, name.c_str())) + { + ImGui::PopStyleVar(); + + ImGui::SameLine(regionAvail.x - lineHeight * .5f); + if (ImGui::Button("+", { lineHeight, lineHeight })) + ImGui::OpenPopup("ComponentSettings"); + + if (ImGui::BeginPopup("ComponentSettings")) + { + if (ImGui::Selectable("Remove component")) + entity.RemoveComponent(); + + ImGui::EndPopup(); + } + + userInterfaceFunction(component); + ImGui::TreePop(); + } + else + ImGui::PopStyleVar(); +} + +} // namespace Light diff --git a/Mirror/src/Panels/PropertiesPanel.h b/Mirror/src/Panels/PropertiesPanel.h index e51963b..cc45cd8 100644 --- a/Mirror/src/Panels/PropertiesPanel.h +++ b/Mirror/src/Panels/PropertiesPanel.h @@ -1,30 +1,29 @@ #pragma once #include "Panel.h" - #include "Scene/Entity.h" namespace Light { - class PropertiesPanel : public Panel - { - private: - Entity m_EntityContext; +class PropertiesPanel: public Panel +{ +private: + Entity m_EntityContext; - public: - PropertiesPanel() = default; - ~PropertiesPanel() = default; - - void OnUserInterfaceUpdate(); +public: + PropertiesPanel() = default; + ~PropertiesPanel() = default; - void SetEntityContext(Entity entity); + void OnUserInterfaceUpdate(); - private: - void DrawVec3Control(const std::string& label, glm::vec3& values, float resetValue = 0.0f, float columnWidth = 100.0f); + void SetEntityContext(Entity entity); - template - void DrawComponent(const std::string& name, Entity entity, UIFunction function); - }; +private: + void DrawVec3Control(const std::string& label, glm::vec3& values, float resetValue = 0.0f, float columnWidth = 100.0f); + + template + void DrawComponent(const std::string& name, Entity entity, UIFunction function); +}; -} \ No newline at end of file +} // namespace Light