diff --git a/.gitignore b/.gitignore index 06eba80..aaaaa4d 100644 --- a/.gitignore +++ b/.gitignore @@ -22,4 +22,5 @@ cmake_install.cmake Debug/ Release/ .vs/ -CMakeFiles/ \ No newline at end of file +CMakeFiles/ +BuildProjects_Temporary/ \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 1af174f..390f8a8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,16 +12,62 @@ project(FocalEngineEditor) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) -set(CMAKE_CXX_FLAGS_DEBUG "/MP /ZI /W3 /Od /MDd /JMC /sdl /FC /D IMGUI_IMPL_OPENGL_LOADER_GLEW /D WIN32 /D _WINDOWS /D _DEBUG /D FE_DEBUG_ENABLED") -set(CMAKE_CXX_FLAGS_RELEASE "/MP /W3 /O2 /Oi /Gy /sdl /FC /GL /OPT:REF /OPT:ICF /D IMGUI_IMPL_OPENGL_LOADER_GLEW /D NDEBUG /D WIN32 /D _WINDOWS") +# Set compiler flags based on USE_STATIC_RUNTIME +if(MSVC) + # Disable C4251 warning + add_compile_options(/wd4251) + + if(USE_STATIC_RUNTIME) + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT") + set(VISUAL_NODE_SYSTEM_USE_STATIC_RUNTIME ON CACHE BOOL "Use static runtime (/MT) instead of dynamic (/MD) for VisualNodeSystem" FORCE) + else() + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MDd") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MD") + set(VISUAL_NODE_SYSTEM_USE_STATIC_RUNTIME OFF CACHE BOOL "Use static runtime (/MT) instead of dynamic (/MD) for VisualNodeSystem" FORCE) + endif() + + # Always add /MP for multi-processor compilation + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP") +endif() + +set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /ZI /W3 /Od /JMC /sdl /FC /D IMGUI_IMPL_OPENGL_LOADER_GLEW /D WIN32 /D _WINDOWS /D _DEBUG /D FE_DEBUG_ENABLED") +set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /W3 /O2 /Oi /Gy /sdl /FC /GL /OPT:REF /OPT:ICF /D IMGUI_IMPL_OPENGL_LOADER_GLEW /D NDEBUG /D WIN32 /D _WINDOWS") # Turn on the ability to create folders to organize projects (.vcproj) # It creates "CMakePredefinedTargets" folder by default and adds CMake # defined projects like INSTALL.vcproj and ZERO_CHECK.vcproj set_property(GLOBAL PROPERTY USE_FOLDERS ON) -# Force your path to Dear ImGui +# Editor should be built with these options +set(BUILD_SHARED_LIBS ON CACHE BOOL "Build FEBasicApplication as a shared library" FORCE) +set(USE_STATIC_RUNTIME OFF CACHE BOOL "Use static runtime (/MT) instead of dynamic (/MD)" FORCE) + +# Set up Visual node system set(DEAR_IMGUI_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/SubSystems/FocalEngine/SubSystems/FEBasicApplication/ThirdParty/imgui CACHE PATH "Path to Dear ImGui directory." FORCE) +if(BUILD_SHARED_LIBS) + set(VISUAL_NODE_SYSTEM_BUILD_SHARED_LIBS ON CACHE BOOL "Build VisualNodeSystem as a shared library" FORCE) + # Set options for VisualNodeSystem + set(VISUAL_NODE_SYSTEM_USE_EXTERNAL_IMGUI ON CACHE BOOL "Use external ImGui from FEBasicApplication" FORCE) + set(EXTERNAL_IMGUI_LIBRARY FEBasicApplication CACHE FILEPATH "Path to external ImGui library" FORCE) + + if(USE_STATIC_RUNTIME) + message(WARNING "Building a shared library with static runtime is uncommon and may lead to issues.") + set(VISUAL_NODE_SYSTEM_GLFW_LIBRARY ${CMAKE_CURRENT_SOURCE_DIR}/SubSystems/FocalEngine/SubSystems/FEBasicApplication/ThirdParty/GLFW/lib/x64/glfw3_mt.lib CACHE PATH "Path to GLFW library." FORCE) + else() + set(VISUAL_NODE_SYSTEM_GLFW_LIBRARY ${CMAKE_CURRENT_SOURCE_DIR}/SubSystems/FocalEngine/SubSystems/FEBasicApplication/ThirdParty/GLFW/lib/x64/glfw3dll.lib CACHE PATH "Path to GLFW library." FORCE) + endif() + + set(VISUAL_NODE_SYSTEM_GLFW_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/SubSystems/FocalEngine/SubSystems/FEBasicApplication/ThirdParty/ CACHE PATH "Path to GLFW include directory.") +else() + set(VISUAL_NODE_SYSTEM_BUILD_SHARED_LIBS OFF CACHE BOOL "Build VisualNodeSystem as a shared library" FORCE) + + if(USE_STATIC_RUNTIME) + set(VISUAL_NODE_SYSTEM_GLFW_LIBRARY ${CMAKE_CURRENT_SOURCE_DIR}/SubSystems/FocalEngine/SubSystems/FEBasicApplication/ThirdParty/GLFW/lib/x64/glfw3_mt.lib CACHE PATH "Path to GLFW library." FORCE) + else() + set(VISUAL_NODE_SYSTEM_GLFW_LIBRARY ${CMAKE_CURRENT_SOURCE_DIR}/SubSystems/FocalEngine/SubSystems/FEBasicApplication/ThirdParty/GLFW/lib/x64/glfw3.lib CACHE PATH "Path to GLFW library." FORCE) + endif() +endif() if(NOT TARGET VisualNodeSystem) add_subdirectory(SubSystems/NodeSystem/VisualNodeSystem) @@ -31,6 +77,15 @@ if(NOT TARGET FocalEngine) add_subdirectory(SubSystems/FocalEngine) endif() +if(USE_STATIC_RUNTIME) + # Add standard FocalEngine native scripts + # TODO: This should be done in the FocalEngine project, or make it simpler to add it user projects + file(GLOB Unpacked_NativeScript_2B7956623302254F620A675F_SRC + "SubSystems/FocalEngine/Resources/UserScriptsData/ExtractedScriptModules/2B7956623302254F620A675F/FirstScript.h" + "SubSystems/FocalEngine/Resources/UserScriptsData/ExtractedScriptModules/2B7956623302254F620A675F/FirstScript.cpp" + ) +endif() + # Extract the relative path of the engine folder file(RELATIVE_PATH RELATIVE_PATH_TO_ENGINE_FOLDER "${CMAKE_CURRENT_SOURCE_DIR}" "${ENGINE_FOLDER}") # We need to re-configure the Config.h file for the engine @@ -40,27 +95,41 @@ set(ENGINE_FOLDER "${RELATIVE_PATH_TO_ENGINE_FOLDER}") configure_file(${ENGINE_FOLDER}/ResourceManager/Config.h.in ${ENGINE_FOLDER}/ResourceManager/Config.h @ONLY) # *************** EDITOR *************** -file(GLOB Editor_SRC - "main.cpp" + +set(EDITOR_SOURCE_FILES "") +list(APPEND EDITOR_SOURCE_FILES + "main.cpp" "FEEditor.cpp" "FEEditor.h" - "FEEditorContentBrowser.cpp" "FEEditorDragAndDropManager.cpp" "FEEditorDragAndDropManager.h" "FEEditorGizmoManager.cpp" "FEEditorGizmoManager.h" "FEEditorHaloSelectionEffect.cpp" "FEEditorHaloSelectionEffect.h" - "FEEditorInternalResources.cpp" - "FEEditorInternalResources.h" "FEEditorPreviewManager.cpp" "FEEditorPreviewManager.h" "FEEditorSelectedObject.cpp" "FEEditorSelectedObject.h" "FEEditorVirtualFileSystem.cpp" "FEEditorVirtualFileSystem.h" - "FEProject.cpp" - "FEProject.h" + "FEEditorScriptingSystem.cpp" + "FEEditorScriptingSystem.h" + "FEProjectBuildSystem.cpp" + "FEProjectBuildSystem.h" +) + +if(USE_STATIC_RUNTIME) + list(APPEND EDITOR_SOURCE_FILES + ${Unpacked_NativeScript_2B7956623302254F620A675F_SRC} + ) +endif() + +file(GLOB ProjectManagment_SRC + "SubSystems/ProjectManagment/FEProjectManager.cpp" + "SubSystems/ProjectManagment/FEProjectManager.h" + "SubSystems/ProjectManagment/FEProject.cpp" + "SubSystems/ProjectManagment/FEProject.h" ) file(GLOB FEDearImguiWrapper_SRC @@ -68,28 +137,41 @@ file(GLOB FEDearImguiWrapper_SRC "FEDearImguiWrapper/FEDearImguiWrapper.h" ) -file(GLOB FEEditorSubWindows_SRC - "FEEditorSubWindows/deletePopups.cpp" - "FEEditorSubWindows/deletePopups.h" - "FEEditorSubWindows/editPopups.cpp" - "FEEditorSubWindows/editPopups.h" - "FEEditorSubWindows/gyzmosSettingsWindow.h" - "FEEditorSubWindows/combineChannelsToTexturePopUp.cpp" - "FEEditorSubWindows/combineChannelsToTexturePopUp.h" - "FEEditorSubWindows/projectWasModifiedPopUp.cpp" - "FEEditorSubWindows/projectWasModifiedPopUp.h" - "FEEditorSubWindows/renamePopups.cpp" - "FEEditorSubWindows/renamePopups.h" - "FEEditorSubWindows/selectPopups.cpp" - "FEEditorSubWindows/selectPopups.h" - "FEEditorSubWindows/shaderEditorWindow.cpp" - "FEEditorSubWindows/shaderEditorWindow.h" - "FEEditorSubWindows/resizeTexturePopup.cpp" - "FEEditorSubWindows/resizeTexturePopup.h" - "FEEditorSubWindows/prefabEditorWindow.cpp" - "FEEditorSubWindows/prefabEditorWindow.h" - "FEEditorSubWindows/debugTextureViewWindow.cpp" - "FEEditorSubWindows/debugTextureViewWindow.h" +file(GLOB EditorWindows_BaseWindowClasses_SRC + "EditorWindows/EditorBaseWindowClasses/FEEditorSceneWindow.h" + "EditorWindows/EditorBaseWindowClasses/FEEditorSceneWindow.cpp" +) + +file(GLOB EditorWindows_SRC + "EditorWindows/DeletePopups.cpp" + "EditorWindows/DeletePopups.h" + "EditorWindows/EditPopups.cpp" + "EditorWindows/EditPopups.h" + "EditorWindows/GyzmosSettingsWindow.h" + "EditorWindows/GyzmosSettingsWindow.cpp" + "EditorWindows/CombineChannelsToTexturePopUp.cpp" + "EditorWindows/CombineChannelsToTexturePopUp.h" + "EditorWindows/ProjectWasModifiedPopUp.cpp" + "EditorWindows/ProjectWasModifiedPopUp.h" + "EditorWindows/RenamePopups.cpp" + "EditorWindows/RenamePopups.h" + "EditorWindows/SelectPopups.cpp" + "EditorWindows/SelectPopups.h" + "EditorWindows/ShaderEditorWindow.cpp" + "EditorWindows/ShaderEditorWindow.h" + "EditorWindows/ResizeTexturePopup.cpp" + "EditorWindows/ResizeTexturePopup.h" + "EditorWindows/PrefabEditorManager.cpp" + "EditorWindows/PrefabEditorManager.h" + "EditorWindows/DebugTextureViewWindow.cpp" + "EditorWindows/DebugTextureViewWindow.h" + "EditorWindows/SceneGraphWindow.cpp" + "EditorWindows/SceneGraphWindow.h" + "EditorWindows/InspectorWindow.cpp" + "EditorWindows/InspectorWindow.h" + "EditorWindows/ContentBrowserWindow.cpp" + "EditorWindows/ContentBrowserWindow.h" + "EditorWindows/LogWindow.cpp" ) file(GLOB Editor_Materials_SRC @@ -127,29 +209,40 @@ link_directories(${GLFW_LIB_DIR}) # add the executable add_executable(FocalEngineEditor WIN32 - ${Editor_SRC} + ${EDITOR_SOURCE_FILES} ${FEDearImguiWrapper_SRC} - ${FEEditorSubWindows_SRC} + ${EditorWindows_BaseWindowClasses_SRC} + ${EditorWindows_SRC} ${Editor_Materials_SRC} ${VisualNodeSystem_CustomNodes_SRC} # *************** SUB_SYSTEM *************** - + ${ProjectManagment_SRC} # *************** THIRD_PARTY *************** ${textEditor_SRC} ) -target_link_libraries(FocalEngineEditor PRIVATE VisualNodeSystem) -target_link_libraries(FocalEngineEditor PRIVATE FocalEngine) +target_link_libraries(FocalEngineEditor + PRIVATE + FEBasicApplication + VisualNodeSystem + FocalEngine + ${GLFW_LIBRARY} + ${GLEW_LIBRARY} + opengl32.lib +) -source_group("Source Files" FILES ${Application_SRC}) # *************** EDITOR *************** -source_group("Source Files/" FILES ${Editor_SRC}) +source_group("Source Files/" FILES ${EDITOR_SOURCE_FILES}) +if(USE_STATIC_RUNTIME) + source_group("Source Files/FocalEngine/2B7956623302254F620A675F" FILES ${Unpacked_NativeScript_2B7956623302254F620A675F_SRC}) +endif() source_group("Source Files/FEDearImguiWrapper" FILES ${FEDearImguiWrapper_SRC}) -source_group("Source Files/FEEditorSubWindows" FILES ${FEEditorSubWindows_SRC}) +source_group("Source Files/EditorWindows/BaseWindowClasses" FILES ${EditorWindows_BaseWindowClasses_SRC}) +source_group("Source Files/EditorWindows" FILES ${EditorWindows_SRC}) source_group("Source Files/Materials" FILES ${Editor_Materials_SRC}) source_group("Source Files/NodeSystem/CustomNodes" FILES ${VisualNodeSystem_CustomNodes_SRC}) # *************** SUB_SYSTEM *************** - +source_group("Source Files/ProjectManagment" FILES ${ProjectManagment_SRC}) # *************** THIRD_PARTY *************** source_group("Source Files/ThirdParty/textEditor" FILES ${textEditor_SRC}) @@ -161,6 +254,36 @@ include_directories( ${BASICAPP_THIRDPARTY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/SubSystems/FocalEngine/SubSystems/FEBasicApplication/ThirdParty/imgui ${BASICAPP_DIR} - ${FOCAL_ENGINE_THIRD_PARTY_DIR} + ${FOCAL_ENGINE_INCLUDES} ${VISUAL_NODE_SYSTEM_DIR} -) \ No newline at end of file +) + +# If building as DLL, copy necessary DLLs to output directory +if(BUILD_SHARED_LIBS) + add_custom_command(TARGET FocalEngineEditor POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "$/glfw3.dll" + "$" + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "$/FEBasicApplication.dll" + "$" + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "$/VisualNodeSystem.dll" + "$" + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "$/FocalEngine.dll" + "$" + COMMAND ${CMAKE_COMMAND} -E copy_if_different + ${OpenXRLoader_DLL} + "$" + ) +endif() + +# If using dynamic runtime, copy necessary DLLs to output directory +if(NOT USE_STATIC_RUNTIME) + add_custom_command(TARGET FocalEngineEditor POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "${GLEW_LIB_DIR}/glew32.dll" + "$" + ) +endif() \ No newline at end of file diff --git a/FEEditorSubWindows/combineChannelsToTexturePopUp.cpp b/EditorWindows/CombineChannelsToTexturePopUp.cpp similarity index 94% rename from FEEditorSubWindows/combineChannelsToTexturePopUp.cpp rename to EditorWindows/CombineChannelsToTexturePopUp.cpp index 461bae3..79c60ea 100644 --- a/FEEditorSubWindows/combineChannelsToTexturePopUp.cpp +++ b/EditorWindows/CombineChannelsToTexturePopUp.cpp @@ -1,7 +1,6 @@ -#include "combineChannelsToTexturePopUp.h" +#include "CombineChannelsToTexturePopUp.h" using namespace VisNodeSys; -CombineChannelsToTexturePopUp* CombineChannelsToTexturePopUp::Instance = nullptr; ImVec2 CombineChannelsToTexturePopUp::NodeGridRelativePosition = ImVec2(5, 30); ImVec2 CombineChannelsToTexturePopUp::WindowPosition = ImVec2(0, 0); ImVec2 CombineChannelsToTexturePopUp::MousePositionWhenContextMenuWasOpened = ImVec2(0, 0); @@ -23,7 +22,7 @@ CombineChannelsToTexturePopUp::~CombineChannelsToTexturePopUp() void CombineChannelsToTexturePopUp::Show() { Size = ImVec2(800, 800); - Position = ImVec2(FEngine::getInstance().GetWindowWidth() / 2 - Size.x / 2, FEngine::getInstance().GetWindowHeight() / 2 - Size.y / 2); + Position = ImVec2(APPLICATION.GetMainWindow()->GetWidth() / 2 - Size.x / 2, APPLICATION.GetMainWindow()->GetHeight() / 2 - Size.y / 2); Flags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoCollapse; @@ -123,7 +122,7 @@ void CombineChannelsToTexturePopUp::NodeSystemMainContextMenu() if (ImGui::MenuItem("Texture node")) { TextureForNewNode = RESOURCE_MANAGER.NoTexture; - SelectFeObjectPopUp::getInstance().Show(FE_TEXTURE, TextureNodeCreationCallback); + SELECT_FEOBJECT_POPUP.Show(FE_TEXTURE, TextureNodeCreationCallback); } if (ImGui::MenuItem("Float node")) diff --git a/FEEditorSubWindows/combineChannelsToTexturePopUp.h b/EditorWindows/CombineChannelsToTexturePopUp.h similarity index 96% rename from FEEditorSubWindows/combineChannelsToTexturePopUp.h rename to EditorWindows/CombineChannelsToTexturePopUp.h index 2204695..0defc52 100644 --- a/FEEditorSubWindows/combineChannelsToTexturePopUp.h +++ b/EditorWindows/CombineChannelsToTexturePopUp.h @@ -1,6 +1,6 @@ #pragma once -#include "gyzmosSettingsWindow.h" +#include "GyzmosSettingsWindow.h" class CombineChannelsToTexturePopUp : public FEImGuiWindow { diff --git a/EditorWindows/ContentBrowserWindow.cpp b/EditorWindows/ContentBrowserWindow.cpp new file mode 100644 index 0000000..ca6df2c --- /dev/null +++ b/EditorWindows/ContentBrowserWindow.cpp @@ -0,0 +1,1343 @@ +#include "ContentBrowserWindow.h" +#include "../FEEditor.h" +using namespace FocalEngine; + +FEObject* FEEditorContentBrowserWindow::ItemInFocus = nullptr; + +FEEditorContentBrowserWindow::FEEditorContentBrowserWindow() +{ + strcpy_s(NameFilter, ""); + + INPUT.AddMouseButtonCallback(&FEEditorContentBrowserWindow::MouseButtonCallback); +} + +static FETexture* TempTexture = nullptr; +static void AddTransparencyToTextureCallBack(const std::vector SelectionsResult) +{ + if (TempTexture == nullptr) + return; + + if (SelectionsResult.size() == 1 && SelectionsResult[0]->GetType() == FE_TEXTURE) + { + FETexture* OriginalTexture = TempTexture; + + FETexture* NewTexture = RESOURCE_MANAGER.CreateTextureWithTransparency(OriginalTexture, reinterpret_cast(SelectionsResult[0])); + if (NewTexture == nullptr) + { + TempTexture = nullptr; + return; + } + + unsigned char* NewRawData = NewTexture->GetRawData(); + const int MaxDimention = std::max(OriginalTexture->GetWidth(), OriginalTexture->GetHeight()); + const size_t MipCount = size_t(floor(log2(MaxDimention)) + 1); + OriginalTexture->UpdateRawData(NewRawData, MipCount); + FE_GL_ERROR(glGenerateMipmap(GL_TEXTURE_2D)); + FE_GL_ERROR(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 16.0f)); + FE_GL_ERROR(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, 0.0f)); + PROJECT_MANAGER.GetCurrent()->AddUnSavedObject(OriginalTexture); + + delete[] NewRawData; + RESOURCE_MANAGER.DeleteFETexture(NewTexture); + } + + TempTexture = nullptr; +} + +static void CreateNewPrefabCallBack(const std::vector SelectionsResult) +{ + if (!SelectionsResult.empty() && SelectionsResult[0]->GetType() == FE_GAMEMODEL) + { + FEPrefab* NewPrefab = RESOURCE_MANAGER.CreatePrefab(); + for (int i = 0; i < SelectionsResult.size(); i++) + { + if (SelectionsResult[i]->GetType() == FE_GAMEMODEL) + { + FEEntity* NewEntity = NewPrefab->GetScene()->CreateEntity(SelectionsResult[i]->GetName()); + NewEntity->AddComponent(reinterpret_cast(SelectionsResult[i])); + } + } + + PROJECT_MANAGER.GetCurrent()->SetModified(true); + VIRTUAL_FILE_SYSTEM.CreateFile(NewPrefab, VIRTUAL_FILE_SYSTEM.GetCurrentPath()); + } + + SELECT_FEOBJECT_POPUP.SetOneObjectSelectonMode(true); +} + +void FEEditorContentBrowserWindow::MouseButtonCallback(int Button, int Action, int Mods) +{ + ItemInFocus = nullptr; +} + +void FEEditorContentBrowserWindow::OpenItemParentFolder(FEObject* Object) +{ + VIRTUAL_FILE_SYSTEM.SetCurrentPath(VIRTUAL_FILE_SYSTEM.LocateFile(Object)); + ImGui::SetWindowFocus("Content Browser"); + strcpy_s(NameFilter, ""); + ItemInFocus = Object; + + const auto Content = VIRTUAL_FILE_SYSTEM.GetDirectoryContent(VIRTUAL_FILE_SYSTEM.GetCurrentPath()); + size_t TotalItemCount = Content.size(); + + size_t ItemIndex = 0; + for (size_t i = 0; i < Content.size(); i++) + { + if (Content[i]->GetObjectID() == Object->GetObjectID()) + { + ItemIndex = i; + break; + } + } + + ImGuiWindow* ContentBrowserWindow = ImGui::FindWindowByName("Content Browser"); + const int IconsPerWindowWidth = (int)(ContentBrowserWindow->Rect().GetWidth() / (ItemIconSize + 8 + 32)); + const size_t ItemRow = ItemIndex / IconsPerWindowWidth; + + if (ContentBrowserWindow != nullptr) + { + ContentBrowserWindow->Scroll.y = float(ItemRow * (ItemIconSize + 8 + 8 + 32)); + } +} + +void FEEditorContentBrowserWindow::Render() +{ + if (!bVisible) + return; + + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(15, 15)); + ImGui::Begin("Content Browser", nullptr, ImGuiWindowFlags_None); + + RenderFilterMenu(); + + bool bOpenContextMenu = false; + if (ImGui::IsWindowHovered() && ImGui::IsMouseClicked(1)) + bOpenContextMenu = true; + + if (bOpenContextMenu) + ImGui::OpenPopup("##context_menu"); + + bShouldOpenContextMenu = false; + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(15, 15)); + if (ImGui::BeginPopup("##context_menu")) + { + bShouldOpenContextMenu = true; + + if (ItemUnderMouse == -1) + { + if (ImGui::MenuItem("Import Asset...")) + { + std::string FilePath; + FILE_SYSTEM.ShowFileOpenDialog(FilePath, ALL_IMPORT_LOAD_FILTER, 3); + if (!FilePath.empty()) + { + if (EDITOR.GetFocusedScene() != nullptr) + { + const std::vector LoadedObjects = EDITOR.GetFocusedScene()->ImportAsset(FilePath.c_str()); + for (size_t i = 0; i < LoadedObjects.size(); i++) + { + if (LoadedObjects[i] != nullptr) + { + VIRTUAL_FILE_SYSTEM.CreateFile(LoadedObjects[i], VIRTUAL_FILE_SYSTEM.GetCurrentPath()); + PROJECT_MANAGER.GetCurrent()->SetModified(true); + PROJECT_MANAGER.GetCurrent()->AddUnSavedObject(LoadedObjects[i]); + } + } + } + } + } + + if (ImGui::MenuItem("*DEPRECATED*Import Tree...")) + { + std::string FilePath; + FILE_SYSTEM.ShowFileOpenDialog(FilePath, OBJ_LOAD_FILTER, 1); + if (!FilePath.empty()) + { + const std::vector LoadedObjects = RESOURCE_MANAGER.ImportOBJ(FilePath.c_str(), true); + for (size_t i = 0; i < LoadedObjects.size(); i++) + { + if (LoadedObjects[i] != nullptr) + { + VIRTUAL_FILE_SYSTEM.CreateFile(LoadedObjects[i], VIRTUAL_FILE_SYSTEM.GetCurrentPath()); + PROJECT_MANAGER.GetCurrent()->SetModified(true); + PROJECT_MANAGER.GetCurrent()->AddUnSavedObject(LoadedObjects[i]); + } + } + } + } + + if (ImGui::BeginMenu("Add")) + { + if (ImGui::MenuItem("Add folder")) + { + const std::string NewDirectoryName = VIRTUAL_FILE_SYSTEM.CreateDirectory(VIRTUAL_FILE_SYSTEM.GetCurrentPath()); + UpdateDirectoryDragAndDropTargets(); + + for (size_t i = 0; i < FilteredResources.size(); i++) + { + if (FilteredResources[i]->GetName() == NewDirectoryName) + { + RenameIndex = int(i); + strcpy_s(RenameBuffer, FilteredResources[i]->GetName().size() + 1, FilteredResources[i]->GetName().c_str()); + bLastFrameRenameEditWasVisiable = false; + break; + } + } + } + + if (ImGui::BeginMenu("Texture")) + { + if (ImGui::MenuItem("Combine channels...")) + CombineChannelsToTexturePopUp::GetInstance().Show(); + + ImGui::EndMenu(); + } + + if (ImGui::MenuItem("Create new material")) + { + FEMaterial* NewMat = RESOURCE_MANAGER.CreateMaterial(""); + if (NewMat) + { + PROJECT_MANAGER.GetCurrent()->SetModified(true); + NewMat->Shader = RESOURCE_MANAGER.GetShader("0800253C242B05321A332D09"/*"FEPBRShader"*/); + + NewMat->SetAlbedoMap(RESOURCE_MANAGER.NoTexture); + + VIRTUAL_FILE_SYSTEM.CreateFile(NewMat, VIRTUAL_FILE_SYSTEM.GetCurrentPath()); + } + } + + if (ImGui::MenuItem("Create new game model")) + { + FEGameModel* NewGameModel = RESOURCE_MANAGER.CreateGameModel(); + PROJECT_MANAGER.GetCurrent()->SetModified(true); + VIRTUAL_FILE_SYSTEM.CreateFile(NewGameModel, VIRTUAL_FILE_SYSTEM.GetCurrentPath()); + } + + if (ImGui::MenuItem("Create new prefab")) + { + SELECT_FEOBJECT_POPUP.SetOneObjectSelectonMode(false); + SELECT_FEOBJECT_POPUP.Show(FE_GAMEMODEL, CreateNewPrefabCallBack); + } + + if (ImGui::MenuItem("Create new scene")) + { + /*FEObject* NewScene = RESOURCE_MANAGER.CreateScene(); + PROJECT_MANAGER.GetCurrent()->SetModified(true); + VIRTUAL_FILE_SYSTEM.CreateFile(NewScene, VIRTUAL_FILE_SYSTEM.GetCurrentPath());*/ + } + + /*if (ImGui::MenuItem("Create new asset package")) + { + FEAssetPackage* NewAssetPackage = RESOURCE_MANAGER.CreateAssetPackage(); + PROJECT_MANAGER.GetCurrent()->SetModified(true); + VIRTUAL_FILE_SYSTEM.CreateFile(NewAssetPackage, VIRTUAL_FILE_SYSTEM.GetCurrentPath()); + }*/ + + if (ImGui::MenuItem("Create new native script module")) + { + FENativeScriptModule* NewNativeScriptModule = RESOURCE_MANAGER.CreateNativeScriptModule(); + PROJECT_MANAGER.GetCurrent()->SetModified(true); + VIRTUAL_FILE_SYSTEM.CreateFile(NewNativeScriptModule, VIRTUAL_FILE_SYSTEM.GetCurrentPath()); + } + + ImGui::EndMenu(); + } + } + else + { + std::string FullPath = VIRTUAL_FILE_SYSTEM.GetCurrentPath(); + if (FullPath.back() != '/') + FullPath += '/'; + FullPath += FilteredResources[ItemUnderMouse]->GetName(); + + const bool ReadOnlyItem = VIRTUAL_FILE_SYSTEM.IsReadOnly(FilteredResources[ItemUnderMouse], FullPath); + + if (ReadOnlyItem) + ImGui::MenuItem("Read Only"); + + if (!ReadOnlyItem) + { + if (ImGui::MenuItem("Rename")) + { + RenameIndex = ItemUnderMouse; + + strcpy_s(RenameBuffer, FilteredResources[ItemUnderMouse]->GetName().size() + 1, FilteredResources[ItemUnderMouse]->GetName().c_str()); + bLastFrameRenameEditWasVisiable = false; + } + } + + if (!ReadOnlyItem && FilteredResources[ItemUnderMouse]->GetType() == FE_MATERIAL) + { + if (ImGui::MenuItem("Edit")) + { + EDITOR_MATERIAL_WINDOW.Show(RESOURCE_MANAGER.GetMaterial(FilteredResources[ItemUnderMouse]->GetObjectID())); + } + } + + if (!ReadOnlyItem && FilteredResources[ItemUnderMouse]->GetType() == FE_GAMEMODEL) + { + if (ImGui::MenuItem("Edit")) + { + EditGameModelPopup::GetInstance().Show(RESOURCE_MANAGER.GetGameModel(FilteredResources[ItemUnderMouse]->GetObjectID())); + } + + if (ImGui::MenuItem("Create Prefab out of this Game Model")) + { + FEGameModel* GameModel = RESOURCE_MANAGER.GetGameModel(FilteredResources[ItemUnderMouse]->GetObjectID()); + if (GameModel != nullptr) + { + FEPrefab* NewPrefab = RESOURCE_MANAGER.CreatePrefab(); + FEEntity* NewEntity = NewPrefab->GetScene()->CreateEntity(GameModel->GetName()); + NewEntity->AddComponent(GameModel); + PROJECT_MANAGER.GetCurrent()->SetModified(true); + VIRTUAL_FILE_SYSTEM.CreateFile(NewPrefab, VIRTUAL_FILE_SYSTEM.GetCurrentPath()); + } + } + } + + if (!ReadOnlyItem && FilteredResources[ItemUnderMouse]->GetType() == FE_PREFAB) + { + if (ImGui::MenuItem("Edit")) + { + PREFAB_EDITOR_MANAGER.PrepareEditWinow(RESOURCE_MANAGER.GetPrefab(FilteredResources[ItemUnderMouse]->GetObjectID())); + } + } + + if (!ReadOnlyItem && FilteredResources[ItemUnderMouse]->GetType() == FE_SHADER) + { + if (ImGui::MenuItem("Edit")) + { + ShaderEditorWindow::GetInstance().Show(RESOURCE_MANAGER.GetShader(FilteredResources[ItemUnderMouse]->GetObjectID())); + } + } + + if (!ReadOnlyItem && FilteredResources[ItemUnderMouse]->GetType() == FE_NATIVE_SCRIPT_MODULE) + { + FENativeScriptModule* NativeScriptModule = RESOURCE_MANAGER.GetNativeScriptModule(FilteredResources[ItemUnderMouse]->GetObjectID()); + if (NativeScriptModule != nullptr) + { + bool bHaveVSProjectReady = false; + if (NativeScriptModule->GetProject() != nullptr) + { + bHaveVSProjectReady = NativeScriptModule->GetProject()->IsVSProjectFolderValidAndIntact(); + } + + if (bHaveVSProjectReady) + { + if (ImGui::MenuItem("Open VS Project")) + { + if (!NativeScriptModule->GetProject()->RunVSProject()) + LOG.Add("FEEditorContentBrowserWindow::Render: Failed to run Visual Studio project!", "FE_EDITOR_CONTENT_BROWSER", FE_LOG_ERROR); + } + } + else + { + bool bHaveRecoverableVSProject = NativeScriptModule->GetProject()->HasRecoverableVSProjectData(); + if (bHaveRecoverableVSProject) + { + if (ImGui::MenuItem("Recover VS Project")) + { + std::string ProjectFolder = PROJECT_MANAGER.GetCurrent()->GetProjectFolder(); + NativeScriptModule->GetProject()->SetWorkingDirectory(ProjectFolder); + if (!NativeScriptModule->GetProject()->RecreateVSProject()) + { + LOG.Add("FEEditorContentBrowserWindow::Render: Failed to regenerate Visual Studio project!", "FE_EDITOR_CONTENT_BROWSER", FE_LOG_ERROR); + } + } + } + else + { + if (ImGui::MenuItem("Create VS Project")) + { + std::string ProjectFolder = PROJECT_MANAGER.GetCurrent()->GetProjectFolder(); + NativeScriptModule->GetProject()->SetWorkingDirectory(ProjectFolder); + if (!NativeScriptModule->GetProject()->CreateNewVSProject("FirstScript")) + { + LOG.Add("FEEditorContentBrowserWindow::Render: Failed to create Visual Studio project!", "FE_EDITOR_CONTENT_BROWSER", FE_LOG_ERROR); + } + } + } + } + } + else + { + LOG.Add("FEEditorContentBrowserWindow::Render: Native script module is nullptr", "FE_EDITOR_CONTENT_BROWSER", FE_LOG_WARNING); + } + } + + if (!ReadOnlyItem) + { + if (ImGui::MenuItem("Delete")) + { + if (FilteredResources[ItemUnderMouse]->GetType() == FE_NULL) + { + DeleteDirectoryPopup::GetInstance().Show(FilteredResources[ItemUnderMouse]->GetName()); + } + else if (FilteredResources[ItemUnderMouse]->GetType() == FE_MESH) + { + DeleteMeshPopup::GetInstance().Show(RESOURCE_MANAGER.GetMesh(FilteredResources[ItemUnderMouse]->GetObjectID())); + } + else if (FilteredResources[ItemUnderMouse]->GetType() == FE_TEXTURE) + { + DeleteTexturePopup::GetInstance().Show(RESOURCE_MANAGER.GetTexture(FilteredResources[ItemUnderMouse]->GetObjectID())); + } + else if (FilteredResources[ItemUnderMouse]->GetType() == FE_MATERIAL) + { + DeleteMaterialPopup::GetInstance().Show(RESOURCE_MANAGER.GetMaterial(FilteredResources[ItemUnderMouse]->GetObjectID())); + } + else if (FilteredResources[ItemUnderMouse]->GetType() == FE_GAMEMODEL) + { + DeleteGameModelPopup::GetInstance().Show(RESOURCE_MANAGER.GetGameModel(FilteredResources[ItemUnderMouse]->GetObjectID())); + } + else if (FilteredResources[ItemUnderMouse]->GetType() == FE_PREFAB) + { + DeletePrefabPopup::GetInstance().Show(RESOURCE_MANAGER.GetPrefab(FilteredResources[ItemUnderMouse]->GetObjectID())); + } + } + } + + if (FilteredResources[ItemUnderMouse]->GetType() == FE_MESH) + { + if (ImGui::BeginMenu("Export")) + { + FEMesh* MeshToExport = RESOURCE_MANAGER.GetMesh(FilteredResources[ItemUnderMouse]->GetObjectID()); + + if (ImGui::MenuItem("as OBJ")) + { + std::string FilePath; + FILE_SYSTEM.ShowFileSaveDialog(FilePath, TEXTURE_LOAD_FILTER, 1); + + if (!FilePath.empty()) + { + FilePath += ".obj"; + RESOURCE_MANAGER.ExportFEMeshToOBJ(MeshToExport, FilePath.c_str()); + } + } + + ImGui::EndMenu(); + } + } + + if (FilteredResources[ItemUnderMouse]->GetType() == FE_TEXTURE) + { + if (ImGui::BeginMenu("Convert")) + { + if (ImGui::MenuItem("Texture channels to individual textures")) + { + const std::vector NewTextures = RESOURCE_MANAGER.ChannelsToFETextures(RESOURCE_MANAGER.GetTexture(FilteredResources[ItemUnderMouse]->GetObjectID())); + + PROJECT_MANAGER.GetCurrent()->AddUnSavedObject(NewTextures[0]); + PROJECT_MANAGER.GetCurrent()->AddUnSavedObject(NewTextures[1]); + PROJECT_MANAGER.GetCurrent()->AddUnSavedObject(NewTextures[2]); + PROJECT_MANAGER.GetCurrent()->AddUnSavedObject(NewTextures[3]); + + PROJECT_MANAGER.GetCurrent()->SetModified(true); + + VIRTUAL_FILE_SYSTEM.CreateFile(NewTextures[0], VIRTUAL_FILE_SYSTEM.GetCurrentPath()); + VIRTUAL_FILE_SYSTEM.CreateFile(NewTextures[1], VIRTUAL_FILE_SYSTEM.GetCurrentPath()); + VIRTUAL_FILE_SYSTEM.CreateFile(NewTextures[2], VIRTUAL_FILE_SYSTEM.GetCurrentPath()); + VIRTUAL_FILE_SYSTEM.CreateFile(NewTextures[3], VIRTUAL_FILE_SYSTEM.GetCurrentPath()); + } + + if (ImGui::MenuItem("Resize")) + { + FETexture* TextureToResize = RESOURCE_MANAGER.GetTexture(FilteredResources[ItemUnderMouse]->GetObjectID()); + ResizeTexturePopup::GetInstance().Show(TextureToResize); + } + + ImGui::EndMenu(); + } + + if (ImGui::BeginMenu("Add transparency")) + { + if (ImGui::MenuItem("Choose transparency mask")) + { + TempTexture = reinterpret_cast(FilteredResources[ItemUnderMouse]); + SELECT_FEOBJECT_POPUP.Show(FE_TEXTURE, AddTransparencyToTextureCallBack); + } + + ImGui::EndMenu(); + } + + if (ImGui::BeginMenu("Export")) + { + FETexture* TextureToExport = RESOURCE_MANAGER.GetTexture(FilteredResources[ItemUnderMouse]->GetObjectID()); + + if (ImGui::MenuItem("as PNG")) + { + std::string FilePath; + FILE_SYSTEM.ShowFileSaveDialog(FilePath, TEXTURE_LOAD_FILTER, 1); + + if (!FilePath.empty()) + { + FilePath += ".png"; + RESOURCE_MANAGER.ExportFETextureToPNG(TextureToExport, FilePath.c_str()); + } + } + + ImGui::EndMenu(); + } + } + + if (FilteredResources[ItemUnderMouse]->GetType() == FE_SCENE) + { + if (ImGui::MenuItem("Open")) + { + //EDITOR.LoadScene(RESOURCE_MANAGER.GetScene(FilteredResources[ItemUnderMouse]->GetObjectID())); + } + + FEScene* StartingScene = SCENE_MANAGER.GetStartingScene(); + bool bIsSceneStarting = false; + if (StartingScene != nullptr) + bIsSceneStarting = StartingScene->GetObjectID() == FilteredResources[ItemUnderMouse]->GetObjectID(); + + if (ImGui::MenuItem("Starting scene", NULL, &bIsSceneStarting)) + { + if (bIsSceneStarting) + SCENE_MANAGER.SetStartingScene(FilteredResources[ItemUnderMouse]->GetObjectID()); + } + } + } + + ImGui::EndPopup(); + } + + ImGui::PopStyleVar(); + ImGui::PopStyleVar(); + ImGui::End(); +} + +void FEEditorContentBrowserWindow::Clear() +{ + AllResources.clear(); + FilteredResources.clear(); + ItemUnderMouse = -1; + RenameIndex = -1; + strcpy_s(NameFilter, ""); +} + +void FEEditorContentBrowserWindow::InitializeResources() +{ + FolderIcon = RESOURCE_MANAGER.LoadPNGTexture("Resources/Images/folderIcon.png", "folderIcon"); + RESOURCE_MANAGER.SetTag(FolderIcon, EDITOR_RESOURCE_TAG); + + ShaderIcon = RESOURCE_MANAGER.LoadPNGTexture("Resources/Images/shaderIcon.png", "shaderIcon"); + RESOURCE_MANAGER.SetTag(ShaderIcon, EDITOR_RESOURCE_TAG); + + ShaderSmallIcon = RESOURCE_MANAGER.LoadPNGTexture("Resources/Images/Shader_ContentBrowser_32_32_Icon.png", "Shader_Small_ContentBrowser_Icon"); + RESOURCE_MANAGER.SetTag(ShaderSmallIcon, EDITOR_RESOURCE_TAG); + + VFSBackIcon = RESOURCE_MANAGER.LoadPNGTexture("Resources/Images/VFSBackIcon.png", "VFSBackIcon"); + RESOURCE_MANAGER.SetTag(VFSBackIcon, EDITOR_RESOURCE_TAG); + + TextureIcon = RESOURCE_MANAGER.LoadPNGTexture("Resources/Images/textureContentBrowserIcon.png", "textureContentBrowserIcon"); + RESOURCE_MANAGER.SetTag(TextureIcon, EDITOR_RESOURCE_TAG); + + MeshIcon = RESOURCE_MANAGER.LoadPNGTexture("Resources/Images/meshContentBrowserIcon.png", "meshContentBrowserIcon"); + RESOURCE_MANAGER.SetTag(MeshIcon, EDITOR_RESOURCE_TAG); + + MaterialIcon = RESOURCE_MANAGER.LoadPNGTexture("Resources/Images/materialContentBrowserIcon.png", "materialContentBrowserIcon"); + RESOURCE_MANAGER.SetTag(MaterialIcon, EDITOR_RESOURCE_TAG); + + GameModelIcon = RESOURCE_MANAGER.LoadPNGTexture("Resources/Images/gameModelContentBrowserIcon.png", "gameModelContentBrowserIcon"); + RESOURCE_MANAGER.SetTag(GameModelIcon, EDITOR_RESOURCE_TAG); + + PrefabIcon = RESOURCE_MANAGER.LoadPNGTexture("Resources/Images/prefabContentBrowserIcon.png", "prefabContentBrowserIcon"); + RESOURCE_MANAGER.SetTag(PrefabIcon, EDITOR_RESOURCE_TAG); + + SceneIcon = RESOURCE_MANAGER.LoadPNGTexture("Resources/Images/Scene_ContentBrowser_Icon.png", "Scene_ContentBrowser_Icon"); + RESOURCE_MANAGER.SetTag(SceneIcon, EDITOR_RESOURCE_TAG); + + AssetPackageIcon = RESOURCE_MANAGER.LoadPNGTexture("Resources/Images/AssetPackage_ContentBrowser_Icon.png", "AssetPackage_ContentBrowser_Icon"); + RESOURCE_MANAGER.SetTag(AssetPackageIcon, EDITOR_RESOURCE_TAG); + + AssetPackageSmallIcon = RESOURCE_MANAGER.LoadPNGTexture("Resources/Images/AssetPackage_ContentBrowser_32_32_Icon.png", "AssetPackage_Small_ContentBrowser_Icon"); + RESOURCE_MANAGER.SetTag(AssetPackageSmallIcon, EDITOR_RESOURCE_TAG); + + NativeScriptModuleIcon = RESOURCE_MANAGER.LoadPNGTexture("Resources/Images/NativeScriptModule_ContentBrowser_Icon.png", "NativeScriptModule_ContentBrowser_Icon"); + RESOURCE_MANAGER.SetTag(NativeScriptModuleIcon, EDITOR_RESOURCE_TAG); + + NativeScriptModuleSmallIcon = RESOURCE_MANAGER.LoadPNGTexture("Resources/Images/NativeScriptModule_ContentBrowser_32_32_Icon.png", "NativeScriptModule_Small_ContentBrowser_Icon"); + RESOURCE_MANAGER.SetTag(NativeScriptModuleSmallIcon, EDITOR_RESOURCE_TAG); + + AllIcon = RESOURCE_MANAGER.LoadPNGTexture("Resources/Images/allContentBrowserIcon.png", "allIcon"); + FilterAllTypesButton = new ImGuiImageButton(AllIcon); + RESOURCE_MANAGER.SetTag(AllIcon, EDITOR_RESOURCE_TAG); + FilterAllTypesButton->SetSize(ImVec2(32, 32)); + + FilterShaderTypeButton = new ImGuiImageButton(ShaderSmallIcon); + FilterShaderTypeButton->SetSize(ImVec2(32, 32)); + + FilterTextureTypeButton = new ImGuiImageButton(TextureIcon); + FilterTextureTypeButton->SetSize(ImVec2(32, 32)); + + FilterMeshTypeButton = new ImGuiImageButton(MeshIcon); + FilterMeshTypeButton->SetSize(ImVec2(32, 32)); + + FilterMaterialTypeButton = new ImGuiImageButton(MaterialIcon); + FilterMaterialTypeButton->SetSize(ImVec2(32, 32)); + + FilterGameModelTypeButton = new ImGuiImageButton(GameModelIcon); + FilterGameModelTypeButton->SetSize(ImVec2(32, 32)); + + FilterPrefabTypeButton = new ImGuiImageButton(PrefabIcon); + FilterPrefabTypeButton->SetSize(ImVec2(32, 32)); + + FilterSceneTypeButton = new ImGuiImageButton(SceneIcon); + FilterSceneTypeButton->SetSize(ImVec2(32, 32)); + + FilterAssetPackageTypeButton = new ImGuiImageButton(AssetPackageSmallIcon); + FilterAssetPackageTypeButton->SetSize(ImVec2(32, 32)); + + FilterNativeScriptModuleTypeButton = new ImGuiImageButton(NativeScriptModuleSmallIcon); + FilterNativeScriptModuleTypeButton->SetSize(ImVec2(32, 32)); +} + +void FEEditorContentBrowserWindow::ChooseTexturesItem(FETexture*& PreviewTexture, FETexture*& SmallAdditionTypeIcon, ImVec2& UV0, ImVec2& UV1, FEObject* Item) +{ + if (Item->GetType() == FE_NULL) + { + UV0 = ImVec2(0.0f, 0.0f); + UV1 = ImVec2(1.0f, 1.0f); + + PreviewTexture = FolderIcon; + + ImGui::PopStyleColor(); + ImGui::PopStyleColor(); + ImGui::PopStyleColor(); + + ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor(0.5f, 0.5f, 0.5f, 0.0f)); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor(0.95f, 0.90f, 0.0f)); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor(0.1f, 1.0f, 0.1f, 1.0f)); + } + else if (Item->GetType() == FE_SHADER) + { + UV0 = ImVec2(0.0f, 0.0f); + UV1 = ImVec2(1.0f, 1.0f); + + PreviewTexture = ShaderIcon; + + ImGui::PopStyleColor(); + ImGui::PopStyleColor(); + ImGui::PopStyleColor(); + + ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor(0.5f, 0.5f, 0.5f, 0.0f)); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor(0.95f, 0.90f, 0.0f)); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor(0.1f, 1.0f, 0.1f, 1.0f)); + } + else if (Item->GetType() == FE_MESH) + { + UV0 = ImVec2(0.0f, 1.0f); + UV1 = ImVec2(1.0f, 0.0f); + + PreviewTexture = PREVIEW_MANAGER.GetMeshPreview(Item->GetObjectID()); + SmallAdditionTypeIcon = MeshIcon; + } + else if (Item->GetType() == FE_TEXTURE) + { + PreviewTexture = RESOURCE_MANAGER.GetTexture(Item->GetObjectID()); + SmallAdditionTypeIcon = TextureIcon; + } + else if (Item->GetType() == FE_MATERIAL) + { + UV0 = ImVec2(0.0f, 1.0f); + UV1 = ImVec2(1.0f, 0.0f); + + PreviewTexture = PREVIEW_MANAGER.GetMaterialPreview(Item->GetObjectID()); + SmallAdditionTypeIcon = MaterialIcon; + } + else if (Item->GetType() == FE_GAMEMODEL) + { + UV0 = ImVec2(0.0f, 1.0f); + UV1 = ImVec2(1.0f, 0.0f); + + PreviewTexture = PREVIEW_MANAGER.GetGameModelPreview(Item->GetObjectID()); + SmallAdditionTypeIcon = GameModelIcon; + } + else if (Item->GetType() == FE_PREFAB) + { + UV0 = ImVec2(0.0f, 1.0f); + UV1 = ImVec2(1.0f, 0.0f); + + PreviewTexture = PREVIEW_MANAGER.GetPrefabPreview(Item->GetObjectID()); + SmallAdditionTypeIcon = PrefabIcon; + } + else if (Item->GetType() == FE_SCENE) + { + UV0 = ImVec2(0.0f, 1.0f); + UV1 = ImVec2(1.0f, 0.0f); + + //PreviewTexture = PREVIEW_MANAGER.GetPrefabPreview(Item->GetObjectID()); + PreviewTexture = RESOURCE_MANAGER.NoTexture; + SmallAdditionTypeIcon = SceneIcon; + } + else if (Item->GetType() == FE_ASSET_PACKAGE) + { + UV0 = ImVec2(0.0f, 0.0f); + UV1 = ImVec2(1.0f, 1.0f); + + PreviewTexture = AssetPackageIcon; + + ImGui::PopStyleColor(); + ImGui::PopStyleColor(); + ImGui::PopStyleColor(); + + ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor(0.5f, 0.5f, 0.5f, 0.0f)); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor(0.95f, 0.90f, 0.0f)); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor(0.1f, 1.0f, 0.1f, 1.0f)); + } + else if (Item->GetType() == FE_NATIVE_SCRIPT_MODULE) + { + UV0 = ImVec2(0.0f, 0.0f); + UV1 = ImVec2(1.0f, 1.0f); + + PreviewTexture = NativeScriptModuleIcon; + + ImGui::PopStyleColor(); + ImGui::PopStyleColor(); + ImGui::PopStyleColor(); + + ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor(0.5f, 0.5f, 0.5f, 0.0f)); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor(0.95f, 0.90f, 0.0f)); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor(0.1f, 1.0f, 0.1f, 1.0f)); + } +} + +void FEEditorContentBrowserWindow::RenderFilterMenu() +{ + ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor(0.5f, 0.5f, 0.5f, 0.0f)); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::ImColor(0.95f, 0.90f, 0.0f)); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::ImColor(0.1f, 1.0f, 0.1f, 1.0f)); + + float CurrentY = ImGui::GetCursorPosY(); + ImGui::SetCursorPosY(CurrentY); + if (ImGui::ImageButton((void*)(intptr_t)VFSBackIcon->GetTextureID(), ImVec2(64, 64), ImVec2(0.0f, 0.0f), ImVec2(1.0f, 1.0f), 8, ImColor(0.0f, 0.0f, 0.0f, 0.0f), ImColor(1.0f, 1.0f, 1.0f, 1.0f))) + { + VIRTUAL_FILE_SYSTEM.SetCurrentPath(VIRTUAL_FILE_SYSTEM.GetDirectoryParent(VIRTUAL_FILE_SYSTEM.GetCurrentPath())); + strcpy_s(NameFilter, ""); + } + VFSBackButtonTarget->StickToItem(); + + ImGui::PopStyleColor(); + ImGui::PopStyleColor(); + ImGui::PopStyleColor(); + + static std::string LastFramePath; + AllResources.clear(); + AllResources = VIRTUAL_FILE_SYSTEM.GetDirectoryContent(VIRTUAL_FILE_SYSTEM.GetCurrentPath()); + + float CurrentX = 100.0f; + ImGui::SetCursorPosX(CurrentX); + ImGui::SetCursorPosY(CurrentY + 5); + ImGui::Text("Filter by type: "); + + CurrentX += 20.0f + 140.0f; + ImGui::SetCursorPosX(CurrentX); + ImGui::SetCursorPosY(CurrentY - 5); + ObjectTypeFilters.empty() ? SetSelectedStyle(FilterAllTypesButton) : SetDefaultStyle(FilterAllTypesButton); + FilterAllTypesButton->Render(); + if (FilterAllTypesButton->IsClicked()) + ObjectTypeFilters.clear(); + + CurrentX += 48.0f; + ImGui::SetCursorPosX(CurrentX); + ImGui::SetCursorPosY(CurrentY - 5); + bool bIsCurrentTypeInFilters = false; + for (size_t i = 0; i < ObjectTypeFilters.size(); i++) + { + if (ObjectTypeFilters[i] == FEObjectTypeToString(FE_SHADER)) + { + bIsCurrentTypeInFilters = true; + break; + } + } + bIsCurrentTypeInFilters ? SetSelectedStyle(FilterShaderTypeButton) : SetDefaultStyle(FilterShaderTypeButton); + FilterShaderTypeButton->Render(); + if (FilterShaderTypeButton->IsClicked()) + { + if (bIsCurrentTypeInFilters) + { + ObjectTypeFilters.erase(std::remove(ObjectTypeFilters.begin(), ObjectTypeFilters.end(), FEObjectTypeToString(FE_SHADER)), ObjectTypeFilters.end()); + } + else + { + ObjectTypeFilters.push_back(FEObjectTypeToString(FE_SHADER)); + } + } + + CurrentX += 48.0f; + ImGui::SetCursorPosX(CurrentX); + ImGui::SetCursorPosY(CurrentY - 5); + bIsCurrentTypeInFilters = false; + for (size_t i = 0; i < ObjectTypeFilters.size(); i++) + { + if (ObjectTypeFilters[i] == FEObjectTypeToString(FE_TEXTURE)) + { + bIsCurrentTypeInFilters = true; + break; + } + } + bIsCurrentTypeInFilters ? SetSelectedStyle(FilterTextureTypeButton) : SetDefaultStyle(FilterTextureTypeButton); + FilterTextureTypeButton->Render(); + if (FilterTextureTypeButton->IsClicked()) + { + if (bIsCurrentTypeInFilters) + { + ObjectTypeFilters.erase(std::remove(ObjectTypeFilters.begin(), ObjectTypeFilters.end(), FEObjectTypeToString(FE_TEXTURE)), ObjectTypeFilters.end()); + } + else + { + ObjectTypeFilters.push_back(FEObjectTypeToString(FE_TEXTURE)); + } + } + + CurrentX += 48.0f; + ImGui::SetCursorPosX(CurrentX); + ImGui::SetCursorPosY(CurrentY - 5); + bIsCurrentTypeInFilters = false; + for (size_t i = 0; i < ObjectTypeFilters.size(); i++) + { + if (ObjectTypeFilters[i] == FEObjectTypeToString(FE_MESH)) + { + bIsCurrentTypeInFilters = true; + break; + } + } + bIsCurrentTypeInFilters ? SetSelectedStyle(FilterMeshTypeButton) : SetDefaultStyle(FilterMeshTypeButton); + FilterMeshTypeButton->Render(); + if (FilterMeshTypeButton->IsClicked()) + { + if (bIsCurrentTypeInFilters) + { + ObjectTypeFilters.erase(std::remove(ObjectTypeFilters.begin(), ObjectTypeFilters.end(), FEObjectTypeToString(FE_MESH)), ObjectTypeFilters.end()); + } + else + { + ObjectTypeFilters.push_back(FEObjectTypeToString(FE_MESH)); + } + } + + CurrentX += 48.0f; + ImGui::SetCursorPosX(CurrentX); + ImGui::SetCursorPosY(CurrentY - 5); + bIsCurrentTypeInFilters = false; + for (size_t i = 0; i < ObjectTypeFilters.size(); i++) + { + if (ObjectTypeFilters[i] == FEObjectTypeToString(FE_MATERIAL)) + { + bIsCurrentTypeInFilters = true; + break; + } + } + bIsCurrentTypeInFilters ? SetSelectedStyle(FilterMaterialTypeButton) : SetDefaultStyle(FilterMaterialTypeButton); + FilterMaterialTypeButton->Render(); + if (FilterMaterialTypeButton->IsClicked()) + { + if (bIsCurrentTypeInFilters) + { + ObjectTypeFilters.erase(std::remove(ObjectTypeFilters.begin(), ObjectTypeFilters.end(), FEObjectTypeToString(FE_MATERIAL)), ObjectTypeFilters.end()); + } + else + { + ObjectTypeFilters.push_back(FEObjectTypeToString(FE_MATERIAL)); + } + } + + CurrentX += 48.0f; + ImGui::SetCursorPosX(CurrentX); + ImGui::SetCursorPosY(CurrentY - 5); + bIsCurrentTypeInFilters = false; + for (size_t i = 0; i < ObjectTypeFilters.size(); i++) + { + if (ObjectTypeFilters[i] == FEObjectTypeToString(FE_GAMEMODEL)) + { + bIsCurrentTypeInFilters = true; + break; + } + } + bIsCurrentTypeInFilters ? SetSelectedStyle(FilterGameModelTypeButton) : SetDefaultStyle(FilterGameModelTypeButton); + FilterGameModelTypeButton->Render(); + if (FilterGameModelTypeButton->IsClicked()) + { + if (bIsCurrentTypeInFilters) + { + ObjectTypeFilters.erase(std::remove(ObjectTypeFilters.begin(), ObjectTypeFilters.end(), FEObjectTypeToString(FE_GAMEMODEL)), ObjectTypeFilters.end()); + } + else + { + ObjectTypeFilters.push_back(FEObjectTypeToString(FE_GAMEMODEL)); + } + } + + CurrentX += 48.0f; + ImGui::SetCursorPosX(CurrentX); + ImGui::SetCursorPosY(CurrentY - 5); + bIsCurrentTypeInFilters = false; + for (size_t i = 0; i < ObjectTypeFilters.size(); i++) + { + if (ObjectTypeFilters[i] == FEObjectTypeToString(FE_PREFAB)) + { + bIsCurrentTypeInFilters = true; + break; + } + } + bIsCurrentTypeInFilters ? SetSelectedStyle(FilterPrefabTypeButton) : SetDefaultStyle(FilterPrefabTypeButton); + FilterPrefabTypeButton->Render(); + if (FilterPrefabTypeButton->IsClicked()) + { + if (bIsCurrentTypeInFilters) + { + ObjectTypeFilters.erase(std::remove(ObjectTypeFilters.begin(), ObjectTypeFilters.end(), FEObjectTypeToString(FE_PREFAB)), ObjectTypeFilters.end()); + } + else + { + ObjectTypeFilters.push_back(FEObjectTypeToString(FE_PREFAB)); + } + } + + CurrentX += 48.0f; + ImGui::SetCursorPosX(CurrentX); + ImGui::SetCursorPosY(CurrentY - 5); + bIsCurrentTypeInFilters = false; + for (size_t i = 0; i < ObjectTypeFilters.size(); i++) + { + if (ObjectTypeFilters[i] == FEObjectTypeToString(FE_SCENE)) + { + bIsCurrentTypeInFilters = true; + break; + } + } + bIsCurrentTypeInFilters ? SetSelectedStyle(FilterSceneTypeButton) : SetDefaultStyle(FilterSceneTypeButton); + FilterSceneTypeButton->Render(); + if (FilterSceneTypeButton->IsClicked()) + { + if (bIsCurrentTypeInFilters) + { + ObjectTypeFilters.erase(std::remove(ObjectTypeFilters.begin(), ObjectTypeFilters.end(), FEObjectTypeToString(FE_SCENE)), ObjectTypeFilters.end()); + } + else + { + ObjectTypeFilters.push_back(FEObjectTypeToString(FE_SCENE)); + } + } + + CurrentX += 48.0f; + ImGui::SetCursorPosX(CurrentX); + ImGui::SetCursorPosY(CurrentY - 5); + bIsCurrentTypeInFilters = false; + for (size_t i = 0; i < ObjectTypeFilters.size(); i++) + { + if (ObjectTypeFilters[i] == FEObjectTypeToString(FE_ASSET_PACKAGE)) + { + bIsCurrentTypeInFilters = true; + break; + } + } + bIsCurrentTypeInFilters ? SetSelectedStyle(FilterAssetPackageTypeButton) : SetDefaultStyle(FilterAssetPackageTypeButton); + FilterAssetPackageTypeButton->Render(); + if (FilterAssetPackageTypeButton->IsClicked()) + { + if (bIsCurrentTypeInFilters) + { + ObjectTypeFilters.erase(std::remove(ObjectTypeFilters.begin(), ObjectTypeFilters.end(), FEObjectTypeToString(FE_ASSET_PACKAGE)), ObjectTypeFilters.end()); + } + else + { + ObjectTypeFilters.push_back(FEObjectTypeToString(FE_ASSET_PACKAGE)); + } + } + + CurrentX += 48.0f; + ImGui::SetCursorPosX(CurrentX); + ImGui::SetCursorPosY(CurrentY - 5); + bIsCurrentTypeInFilters = false; + for (size_t i = 0; i < ObjectTypeFilters.size(); i++) + { + if (ObjectTypeFilters[i] == FEObjectTypeToString(FE_NATIVE_SCRIPT_MODULE)) + { + bIsCurrentTypeInFilters = true; + break; + } + } + bIsCurrentTypeInFilters ? SetSelectedStyle(FilterNativeScriptModuleTypeButton) : SetDefaultStyle(FilterNativeScriptModuleTypeButton); + FilterNativeScriptModuleTypeButton->Render(); + if (FilterNativeScriptModuleTypeButton->IsClicked()) + { + if (bIsCurrentTypeInFilters) + { + ObjectTypeFilters.erase(std::remove(ObjectTypeFilters.begin(), ObjectTypeFilters.end(), FEObjectTypeToString(FE_NATIVE_SCRIPT_MODULE)), ObjectTypeFilters.end()); + } + else + { + ObjectTypeFilters.push_back(FEObjectTypeToString(FE_NATIVE_SCRIPT_MODULE)); + } + } + + CurrentX += 48.0f; + ImGui::SetCursorPosX(CurrentX); + ImGui::SetCursorPosY(CurrentY - 5); + static bool bIsPrivateTagsInFilters = true; + if (bIsPrivateTagsInFilters && ObjectTagNegativeFilters.empty()) + { + ObjectTagNegativeFilters.push_back(ENGINE_RESOURCE_TAG); + ObjectTagNegativeFilters.push_back(EDITOR_RESOURCE_TAG); + ObjectTagNegativeFilters.push_back(PREFAB_SCENE_DESCRIPTION_TAG); + ObjectTagNegativeFilters.push_back(TERRAIN_SYSTEM_RESOURCE_TAG); + } + + if (ImGui::Checkbox("Hide private tags", &bIsPrivateTagsInFilters)) + { + ObjectTagNegativeFilters.clear(); + if (bIsPrivateTagsInFilters) + { + ObjectTagNegativeFilters.push_back(ENGINE_RESOURCE_TAG); + ObjectTagNegativeFilters.push_back(EDITOR_RESOURCE_TAG); + ObjectTagNegativeFilters.push_back(PREFAB_SCENE_DESCRIPTION_TAG); + ObjectTagNegativeFilters.push_back(TERRAIN_SYSTEM_RESOURCE_TAG); + } + } + + ImGui::SetCursorPosX(100); + ImGui::SetCursorPosY(CurrentY + 50); + ImGui::Text("Filter by name: "); + + ImGui::SetCursorPosX(120 + 140); + ImGui::SetCursorPosY(CurrentY + 47); + ImGui::InputText("##filter", NameFilter, IM_ARRAYSIZE(NameFilter)); + + ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 25); + ImGui::Separator(); + + UpdateFilterForResources(); + UpdateDirectoryDragAndDropTargets(); + + // ************** Drag&Drop ************** + if (VIRTUAL_FILE_SYSTEM.GetCurrentPath() != LastFramePath) + { + LastFramePath = VIRTUAL_FILE_SYSTEM.GetCurrentPath(); + UpdateDirectoryDragAndDropTargets(); + } + int DirectoryIndex = 0; + // ************** Drag&Drop END ************** + + int IconsPerWindowWidth = (int)(FE_IMGUI_WINDOW_MANAGER.GetCurrentWindowImpl()->Rect().GetWidth() / (ItemIconSize + 8 + 32)); + // Possibly window is minimized anyway ImGui::Columns can't take 0 as columns count! + if (IconsPerWindowWidth == 0) + return; + + if (!bShouldOpenContextMenu) ItemUnderMouse = -1; + ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 5); + ImGui::Columns(IconsPerWindowWidth, "mycolumns3", false); + + for (size_t i = 0; i < FilteredResources.size(); i++) + { + ImGui::PushID(int(std::hash{}(FilteredResources[i]->GetObjectID()))); + + if (ItemInFocus != nullptr && ItemInFocus->GetObjectID() == FilteredResources[i]->GetObjectID()) + { + ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor(0.1f, 1.0f, 0.1f, 1.0f)); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor(0.1f, 1.0f, 0.1f, 1.0f)); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor(0.1f, 1.0f, 0.1f, 1.0f)); + } + else + { + ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor(0.5f, 0.5f, 0.5f)); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor(0.95f, 0.90f, 0.0f)); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor(0.1f, 1.0f, 0.1f, 1.0f)); + } + + ImVec2 uv0 = ImVec2(0.0f, 0.0f); + ImVec2 uv1 = ImVec2(1.0f, 1.0f); + + FETexture* PreviewTexture = nullptr; + FETexture* SmallAdditionTypeIcon = nullptr; + + ChooseTexturesItem(PreviewTexture, SmallAdditionTypeIcon, uv0, uv1, FilteredResources[i]); + + if (PreviewTexture != nullptr) + ImGui::ImageButton((void*)(intptr_t)PreviewTexture->GetTextureID(), ImVec2(ItemIconSize, ItemIconSize), uv0, uv1, 8, ImColor(0.0f, 0.0f, 0.0f, 0.0f), ImColor(1.0f, 1.0f, 1.0f, 1.0f)); + + if (FilteredResources[i]->GetType() == FE_NULL && DirectoriesTargets.size() > (size_t)DirectoryIndex) + DirectoriesTargets[DirectoryIndex++]->StickToItem(); + + if (ImGui::IsItemHovered()) + { + if (!bShouldOpenContextMenu && !DRAG_AND_DROP_MANAGER.ObjectIsDraged()) + { + std::string AdditionalTypeInfo; + if (FilteredResources[i]->GetType() == FE_TEXTURE) + { + AdditionalTypeInfo += "\nTexture type: "; + AdditionalTypeInfo += FETexture::TextureInternalFormatToString(RESOURCE_MANAGER.GetTexture(FilteredResources[i]->GetObjectID())->GetInternalFormat()); + } + else if (FilteredResources[i]->GetType() == FE_NATIVE_SCRIPT_MODULE) + { + + } + + ImGui::BeginTooltip(); + ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f); + ImGui::TextUnformatted(("ID: " + FilteredResources[i]->GetObjectID() + + "\nTag: " + FilteredResources[i]->GetTag() + + "\nName: " + FilteredResources[i]->GetName() + + "\nType: " + FEObjectTypeToString(FilteredResources[i]->GetType()) + + AdditionalTypeInfo + + "\nPath: " + VIRTUAL_FILE_SYSTEM.GetCurrentPath() + ).c_str()); + ImGui::PopTextWrapPos(); + ImGui::EndTooltip(); + + ItemUnderMouse = int(i); + + if (ImGui::IsMouseDragging(0)) + DRAG_AND_DROP_MANAGER.SetObjectToDrag(FilteredResources[i], PreviewTexture, uv0, uv1); + } + } + + if (SmallAdditionTypeIcon != nullptr) + { + ImVec2 CursorPosBefore = ImGui::GetCursorPos(); + ImGui::SetCursorPos(ImVec2(CursorPosBefore.x + 10, CursorPosBefore.y - 48)); + ImGui::Image((void*)(intptr_t)SmallAdditionTypeIcon->GetTextureID(), ImVec2(32, 32)); + ImGui::SetCursorPos(CursorPosBefore); + } + + ImGui::PopStyleColor(); + ImGui::PopStyleColor(); + ImGui::PopStyleColor(); + + ImGui::PopID(); + + if (RenameIndex == i) + { + if (!bLastFrameRenameEditWasVisiable) + { + ImGui::SetKeyboardFocusHere(0); + ImGui::SetFocusID(ImGui::GetID("##newNameEditor"), FE_IMGUI_WINDOW_MANAGER.GetCurrentWindowImpl()); + ImGui::SetItemDefaultFocus(); + bLastFrameRenameEditWasVisiable = true; + } + + ImGui::SetNextItemWidth(ItemIconSize + 8.0f + 8.0f); + if (ImGui::InputText("##newNameEditor", RenameBuffer, IM_ARRAYSIZE(RenameBuffer), ImGuiInputTextFlags_EnterReturnsTrue) || + ImGui::IsMouseClicked(0) && !ImGui::IsItemHovered() || !ImGui::IsItemFocused()) + { + if (FilteredResources[RenameIndex]->GetType() == FE_NULL) + { + std::string PathToDirectory = VIRTUAL_FILE_SYSTEM.GetCurrentPath(); + if (PathToDirectory.back() != '/') + PathToDirectory += '/'; + + PathToDirectory += FilteredResources[RenameIndex]->GetName(); + VIRTUAL_FILE_SYSTEM.RenameDirectory(RenameBuffer, PathToDirectory); + + UpdateDirectoryDragAndDropTargets(); + } + else + { + FilteredResources[RenameIndex]->SetDirtyFlag(true); + PROJECT_MANAGER.GetCurrent()->SetModified(true); + FilteredResources[RenameIndex]->SetName(RenameBuffer); + } + + RenameIndex = -1; + } + } + else + { + ImVec2 TextSize = ImGui::CalcTextSize(FilteredResources[i]->GetName().c_str()); + if (TextSize.x < ItemIconSize + 8 + 8) + { + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + (ItemIconSize + 8.0f + 8.0f) / 2.0f - TextSize.x / 2.0f); + ImGui::Text(FilteredResources[i]->GetName().c_str()); + } + else + { + ImGui::Text(FilteredResources[i]->GetName().c_str()); + } + } + + ImGui::NextColumn(); + } + + if (ImGui::IsMouseDoubleClicked(0) && ItemUnderMouse != -1) + { + if (FilteredResources[ItemUnderMouse]->GetType() == FE_NULL) + { + std::string CurrentPath = VIRTUAL_FILE_SYSTEM.GetCurrentPath(); + if (CurrentPath.back() != '/') + CurrentPath += '/'; + + CurrentPath += FilteredResources[ItemUnderMouse]->GetName(); + VIRTUAL_FILE_SYSTEM.SetCurrentPath(CurrentPath); + } + else if (FilteredResources[ItemUnderMouse]->GetType() == FE_MESH) + { + std::string MeshInfo = "Vertex count: "; + MeshInfo += std::to_string(RESOURCE_MANAGER.GetMesh(FilteredResources[ItemUnderMouse]->GetObjectID())->GetVertexCount()); + MeshInfo += "\n"; + MeshInfo += "Sub material socket: "; + MeshInfo += RESOURCE_MANAGER.GetMesh(FilteredResources[ItemUnderMouse]->GetObjectID())->GetMaterialCount() == 2 ? "Yes" : "No"; + MessagePopUp::GetInstance().Show("Mesh info", MeshInfo.c_str()); + } + else if (FilteredResources[ItemUnderMouse]->GetType() == FE_MATERIAL) + { + EDITOR_MATERIAL_WINDOW.Show(RESOURCE_MANAGER.GetMaterial(FilteredResources[ItemUnderMouse]->GetObjectID())); + } + else if (FilteredResources[ItemUnderMouse]->GetType() == FE_GAMEMODEL) + { + if (!bShouldOpenContextMenu && !EditGameModelPopup::GetInstance().IsVisible()) + { + EditGameModelPopup::GetInstance().Show(RESOURCE_MANAGER.GetGameModel(FilteredResources[ItemUnderMouse]->GetObjectID())); + } + } + else if (FilteredResources[ItemUnderMouse]->GetType() == FE_PREFAB) + { + if (!bShouldOpenContextMenu) + { + PREFAB_EDITOR_MANAGER.PrepareEditWinow(RESOURCE_MANAGER.GetPrefab(FilteredResources[ItemUnderMouse]->GetObjectID())); + } + } + } + + ImGui::Columns(1); +} + +void FEEditorContentBrowserWindow::UpdateDirectoryDragAndDropTargets() +{ + for (size_t i = 0; i < DirectoriesTargets.size(); i++) + { + delete DirectoriesTargets[i]; + } + DirectoriesTargets.clear(); + DirectoryDragAndDropInfo.clear(); + AllResources.clear(); + AllResources = VIRTUAL_FILE_SYSTEM.GetDirectoryContent(VIRTUAL_FILE_SYSTEM.GetCurrentPath()); + + UpdateFilterForResources(); + + DirectoryDragAndDropInfo.resize(VIRTUAL_FILE_SYSTEM.SubDirectoriesCount(VIRTUAL_FILE_SYSTEM.GetCurrentPath())); + int SubDirectoryIndex = 0; + for (size_t i = 0; i < FilteredResources.size(); i++) + { + if (FilteredResources[i]->GetType() == FE_NULL) + { + DirectoryDragAndDropCallbackInfo info; + + info.DirectoryPath = VIRTUAL_FILE_SYSTEM.GetCurrentPath(); + if (VIRTUAL_FILE_SYSTEM.GetCurrentPath().back() != '/') + info.DirectoryPath += "/"; + + info.DirectoryPath += FilteredResources[i]->GetName() + "/"; + DirectoryDragAndDropInfo[SubDirectoryIndex] = info; + + DirectoriesTargets.push_back(DRAG_AND_DROP_MANAGER.AddTarget(std::vector { FE_NULL, FE_SHADER, FE_TEXTURE, FE_MESH, FE_MATERIAL, FE_GAMEMODEL, FE_PREFAB }, + DirectoryDragAndDropCallback, reinterpret_cast(&DirectoryDragAndDropInfo[SubDirectoryIndex]), + std::vector { "Drop to move to folder", "Drop to move to folder", "Drop to move to folder", "Drop to move to folder", "Drop to move to folder", "Drop to move to folder", "Drop to move to folder" })); + SubDirectoryIndex++; + } + } + + if (VFSBackButtonTarget == nullptr) + { + VFSBackButtoninfo.DirectoryPath = VIRTUAL_FILE_SYSTEM.GetDirectoryParent(VIRTUAL_FILE_SYSTEM.GetCurrentPath()); + VFSBackButtonTarget = DRAG_AND_DROP_MANAGER.AddTarget(std::vector { FE_NULL, FE_SHADER, FE_TEXTURE, FE_MESH, FE_MATERIAL, FE_GAMEMODEL, FE_PREFAB }, + DirectoryDragAndDropCallback, reinterpret_cast(&VFSBackButtoninfo), + std::vector { "Drop to move to parent folder", "Drop to move to parent folder", "Drop to move to parent folder", "Drop to move to parent folder", "Drop to move to parent folder", "Drop to move to parent folder", "Drop to move to parent folder" }); + } + else + { + VFSBackButtoninfo.DirectoryPath = VIRTUAL_FILE_SYSTEM.GetDirectoryParent(VIRTUAL_FILE_SYSTEM.GetCurrentPath()); + //VFSBackButton->setNewUserData(); + } +} + +void FEEditorContentBrowserWindow::UpdateFilterForResources() +{ + FilteredResources.clear(); + + std::vector TemporaryFilteredList; + TemporaryFilteredList = AllResources; + if (!AnyFilterActive()) + { + FilteredResources = TemporaryFilteredList; + return; + } + + for (size_t i = 0; i < TemporaryFilteredList.size(); i++) + { + if (ShouldPassVisibilityFilter(TemporaryFilteredList[i])) + { + FilteredResources.push_back(TemporaryFilteredList[i]); + } + } +} + +bool FEEditorContentBrowserWindow::AnyFilterActive() +{ + return NameFilter[0] != '\0' || ObjectTypeFilters.size() > 0 || ObjectTagNegativeFilters.size() > 0; +} + +bool FEEditorContentBrowserWindow::ShouldPassVisibilityFilter(FEObject* Object) +{ + if (Object == nullptr) + { + LOG.Add("Object is nullptr in FEEditorContentBrowserWindow::ShouldPassVisibilityFilter", "FE_EDITOR_CONTENT_BROWSER", FE_LOG_WARNING); + return false; + } + + if (strlen(NameFilter) > 0) + { + if (Object->GetName().find(NameFilter) == -1) + return false; + } + + bool bShouldPassTypeFilter = true; + if (!ObjectTypeFilters.empty()) + { + bShouldPassTypeFilter = false; + // Check if object is a folder + if (Object->GetType() == FE_NULL) + { + bShouldPassTypeFilter = true; + } + else + { + for (size_t i = 0; i < ObjectTypeFilters.size(); i++) + { + if (FEObjectTypeToString(Object->GetType()) == ObjectTypeFilters[i]) + { + bShouldPassTypeFilter = true; + break; + } + } + } + } + + if (!bShouldPassTypeFilter) + return false; + + bool bShouldPassNegativeTagFilter = true; + if (!ObjectTagNegativeFilters.empty()) + { + // Check if object is not a folder + if (Object->GetType() != FE_NULL) + { + + for (size_t i = 0; i < ObjectTagNegativeFilters.size(); i++) + { + if (Object->GetTag() == ObjectTagNegativeFilters[i]) + { + bShouldPassNegativeTagFilter = false; + break; + } + } + } + } + + if (!bShouldPassNegativeTagFilter) + return false; + + return true; +} \ No newline at end of file diff --git a/EditorWindows/ContentBrowserWindow.h b/EditorWindows/ContentBrowserWindow.h new file mode 100644 index 0000000..e755d0c --- /dev/null +++ b/EditorWindows/ContentBrowserWindow.h @@ -0,0 +1,126 @@ +#pragma once + +#include "SceneGraphWindow.h" + +#ifdef FE_WIN_32 + const COMDLG_FILTERSPEC OBJ_LOAD_FILTER[] = + { + { L"Wavefront OBJ files (*.obj)", L"*.obj" } + }; + + const COMDLG_FILTERSPEC TEXTURE_LOAD_FILTER[] = + { + { L"Image files (*.png; *.jpg; *.bmp)", L"*.png;*.jpg;*.bmp" } + }; + + const COMDLG_FILTERSPEC ALL_IMPORT_LOAD_FILTER[] = + { + { L"All files (*.png; *.jpg; *.bmp; *.obj)", L"*.png;*.jpg;*.bmp;*.obj" }, + { L"Image files (*.png; *.jpg; *.bmp)", L"*.png;*.jpg;*.bmp" }, + { L"Wavefront OBJ files (*.obj)", L"*.obj" } + }; +#endif + + class FEEditorContentBrowserWindow + { + friend class FEEditor; + friend class FEEditorInspectorWindow; + + SINGLETON_PRIVATE_PART(FEEditorContentBrowserWindow) + + // Visibility and state + bool bVisible = true; + bool bShouldOpenContextMenu = false; + + // Callbacks and rendering + static void MouseButtonCallback(int Button, int Action, int Mods); + void Render(); + void RenderFilterMenu(); + void Clear(); + + // Resource initialization and icons + void InitializeResources(); + FETexture* FolderIcon = nullptr; + FETexture* ShaderIcon = nullptr; + FETexture* ShaderSmallIcon = nullptr; + FETexture* VFSBackIcon = nullptr; + FETexture* TextureIcon = nullptr; + FETexture* MeshIcon = nullptr; + FETexture* MaterialIcon = nullptr; + FETexture* GameModelIcon = nullptr; + FETexture* PrefabIcon = nullptr; + FETexture* SceneIcon = nullptr; + FETexture* AssetPackageIcon = nullptr; + FETexture* AssetPackageSmallIcon = nullptr; + FETexture* NativeScriptModuleIcon = nullptr; + FETexture* NativeScriptModuleSmallIcon = nullptr; + FETexture* AllIcon = nullptr; + + // Item selection and manipulation + void ChooseTexturesItem(FETexture*& PreviewTexture, FETexture*& SmallAdditionTypeIcon, ImVec2& UV0, ImVec2& UV1, FEObject* Item); + void OpenItemParentFolder(FEObject* Object); + + // Item properties and renaming + float ItemIconSize = 128.0; + int ItemUnderMouse = -1; + int RenameIndex = -1; + char RenameBuffer[1024]; + bool bLastFrameRenameEditWasVisiable = false; + static FEObject* ItemInFocus; + + // Resource filtering + std::vector AllResources; + std::vector FilteredResources; + char NameFilter[1024]; + std::vector ObjectTypeFilters; + std::vector ObjectTagNegativeFilters; + bool AnyFilterActive(); + bool ShouldPassVisibilityFilter(FEObject* Object); + void UpdateFilterForResources(); + + // Filter buttons + ImGuiImageButton* FilterAllTypesButton = nullptr; + ImGuiImageButton* FilterShaderTypeButton = nullptr; + ImGuiImageButton* FilterTextureTypeButton = nullptr; + ImGuiImageButton* FilterMeshTypeButton = nullptr; + ImGuiImageButton* FilterMaterialTypeButton = nullptr; + ImGuiImageButton* FilterGameModelTypeButton = nullptr; + ImGuiImageButton* FilterPrefabTypeButton = nullptr; + ImGuiImageButton* FilterSceneTypeButton = nullptr; + ImGuiImageButton* FilterAssetPackageTypeButton = nullptr; + ImGuiImageButton* FilterNativeScriptModuleTypeButton = nullptr; + + // Drag and drop + struct DirectoryDragAndDropCallbackInfo + { + std::string DirectoryPath; + }; + std::vector DirectoryDragAndDropInfo; + std::vector DirectoriesTargets; + DragAndDropTarget* VFSBackButtonTarget = nullptr; + DirectoryDragAndDropCallbackInfo VFSBackButtoninfo; + + static bool DirectoryDragAndDropCallback(FEObject* Object, void** Directory) + { + const DirectoryDragAndDropCallbackInfo* info = reinterpret_cast(Directory); + if (Object->GetType() == FE_NULL) + { + std::string OldPath = VIRTUAL_FILE_SYSTEM.GetCurrentPath(); + if (OldPath.back() != '/') + OldPath += "/"; + VIRTUAL_FILE_SYSTEM.MoveDirectory(OldPath + Object->GetName(), info->DirectoryPath); + } + else + { + VIRTUAL_FILE_SYSTEM.MoveFile(Object, VIRTUAL_FILE_SYSTEM.GetCurrentPath(), info->DirectoryPath); + } + return true; + } + + void UpdateDirectoryDragAndDropTargets(); + + public: + SINGLETON_PUBLIC_PART(FEEditorContentBrowserWindow) + }; + +#define CONTENT_BROWSER_WINDOW FEEditorContentBrowserWindow::GetInstance() \ No newline at end of file diff --git a/FEEditorSubWindows/debugTextureViewWindow.cpp b/EditorWindows/DebugTextureViewWindow.cpp similarity index 74% rename from FEEditorSubWindows/debugTextureViewWindow.cpp rename to EditorWindows/DebugTextureViewWindow.cpp index 02458d9..6c11919 100644 --- a/FEEditorSubWindows/debugTextureViewWindow.cpp +++ b/EditorWindows/DebugTextureViewWindow.cpp @@ -1,6 +1,6 @@ -#include "debugTextureViewWindow.h" +#include "DebugTextureViewWindow.h" -debugTextureViewWindow::debugTextureViewWindow(std::function Func) +DebugTextureViewWindow::DebugTextureViewWindow(std::function Func) { TextureToView = Func; @@ -8,7 +8,7 @@ debugTextureViewWindow::debugTextureViewWindow(std::function Func strcpy_s(Caption, tempCaption.size() + 1, tempCaption.c_str()); Size = ImVec2(800, 800); - Position = ImVec2(FEngine::getInstance().GetWindowWidth() / 2 - Size.x / 2, FEngine::getInstance().GetWindowHeight() / 2 - Size.y / 2); + Position = ImVec2(APPLICATION.GetMainWindow()->GetWidth() / 2 - Size.x / 2, APPLICATION.GetMainWindow()->GetHeight() / 2 - Size.y / 2); Flags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoCollapse; @@ -17,13 +17,13 @@ debugTextureViewWindow::debugTextureViewWindow(std::function Func CloseButton->SetPosition(ImVec2(800.0 / 2.0 - 140.0 / 2.0, 800.0 - 35.0)); } -debugTextureViewWindow::~debugTextureViewWindow() +DebugTextureViewWindow::~DebugTextureViewWindow() { if (CloseButton != nullptr) delete CloseButton; } -void debugTextureViewWindow::Render() +void DebugTextureViewWindow::Render() { FEImGuiWindow::Render(); diff --git a/EditorWindows/DebugTextureViewWindow.h b/EditorWindows/DebugTextureViewWindow.h new file mode 100644 index 0000000..224a496 --- /dev/null +++ b/EditorWindows/DebugTextureViewWindow.h @@ -0,0 +1,14 @@ +#pragma once + +#include "PrefabEditorManager.h" + +class DebugTextureViewWindow : public FEImGuiWindow +{ + ImGuiButton* CloseButton = nullptr; + std::function TextureToView; +public: + DebugTextureViewWindow(std::function Func); + ~DebugTextureViewWindow(); + + void Render() override; +}; \ No newline at end of file diff --git a/FEEditorSubWindows/deletePopups.cpp b/EditorWindows/DeletePopups.cpp similarity index 78% rename from FEEditorSubWindows/deletePopups.cpp rename to EditorWindows/DeletePopups.cpp index 411b94f..9ea266d 100644 --- a/FEEditorSubWindows/deletePopups.cpp +++ b/EditorWindows/DeletePopups.cpp @@ -1,6 +1,5 @@ -#include "deletePopups.h" - -DeleteTexturePopup* DeleteTexturePopup::Instance = nullptr; +#include "DeletePopups.h" +#include "../FEEditor.h" DeleteTexturePopup::DeleteTexturePopup() { @@ -28,7 +27,7 @@ void DeleteTexturePopup::Render() return; } - ImGui::SetWindowPos(ImVec2(ENGINE.GetWindowWidth() / 2.0f - ImGui::GetWindowWidth() / 2.0f, ENGINE.GetWindowHeight() / 2.0f - ImGui::GetWindowHeight() / 2.0f)); + ImGui::SetWindowPos(ImVec2(APPLICATION.GetMainWindow()->GetWidth() / 2.0f - ImGui::GetWindowWidth() / 2.0f, APPLICATION.GetMainWindow()->GetHeight() / 2.0f - ImGui::GetWindowHeight() / 2.0f)); // check if this texture is used in some materials // to-do: should be done through counter, not by searching each time. const std::vector MaterialsThatUseTexture = MaterialsThatUsesTexture(ObjToWorkWith); @@ -64,8 +63,8 @@ void DeleteTexturePopup::Render() std::vector DeleteTexturePopup::MaterialsThatUsesTexture(const FETexture* Texture) { - std::vector result; - const std::vector MateriasList = RESOURCE_MANAGER.GetMaterialList(); + std::vector Result; + const std::vector MateriasList = RESOURCE_MANAGER.GetMaterialIDList(); for (size_t i = 0; i < MateriasList.size(); i++) { @@ -75,24 +74,27 @@ std::vector DeleteTexturePopup::MaterialsThatUsesTexture(const FETe { if (CurrentMaterial->Textures[j] == Texture) { - result.push_back(CurrentMaterial); + Result.push_back(CurrentMaterial); break; } } } - const std::vector TerrainList = SCENE.GetTerrainList(); - for (size_t i = 0; i < TerrainList.size(); i++) + if (EDITOR.GetFocusedScene() != nullptr) { - const FETerrain* CurrentTerrain = SCENE.GetTerrain(TerrainList[i]); - //if (CurrentTerrain->heightMap != nullptr && CurrentTerrain->heightMap->getObjectID() == Texture->getObjectID()) - //{ - // continue; - // result.push_back(nullptr); - //} + const std::vector TerrainList = EDITOR.GetFocusedScene()->GetEntityIDListWithComponent(); + for (size_t i = 0; i < TerrainList.size(); i++) + { + /*FEEntity* CurrentTerrain = SCENE.GetEntity(TerrainList[i]); + FETerrainComponent& TerrainComponent = CurrentTerrain->GetComponent(); + if (TerrainComponent.HeightMap != nullptr && TerrainComponent.HeightMap->GetObjectID() == Texture->GetObjectID()) + { + Result.push_back(nullptr); + }*/ + } } - return result; + return Result; } void DeleteTexturePopup::DeleteTexture(FETexture* Texture) @@ -108,7 +110,7 @@ void DeleteTexturePopup::DeleteTexture(FETexture* Texture) // re-create game model preview that was using material that uses this texture if (!MaterialsThatUseTexture.empty()) { - const std::vector GameModelList = RESOURCE_MANAGER.GetGameModelList(); + const std::vector GameModelList = RESOURCE_MANAGER.GetGameModelIDList(); for (size_t i = 0; i < GameModelList.size(); i++) { const FEGameModel* CurrentGameModel = RESOURCE_MANAGER.GetGameModel(GameModelList[i]); @@ -130,8 +132,6 @@ void DeleteTexturePopup::DeleteTexture(FETexture* Texture) PREVIEW_MANAGER.CreateGameModelPreview(GameModelListToUpdate[i]); } -DeleteMeshPopup* DeleteMeshPopup::Instance = nullptr; - DeleteMeshPopup::DeleteMeshPopup() { PopupCaption = "Delete mesh"; @@ -158,14 +158,14 @@ void DeleteMeshPopup::Render() return; } - ImGui::SetWindowPos(ImVec2(ENGINE.GetWindowWidth() / 2.0f - ImGui::GetWindowWidth() / 2.0f, ENGINE.GetWindowHeight() / 2.0f - ImGui::GetWindowHeight() / 2.0f)); + ImGui::SetWindowPos(ImVec2(APPLICATION.GetMainWindow()->GetWidth() / 2.0f - ImGui::GetWindowWidth() / 2.0f, APPLICATION.GetMainWindow()->GetHeight() / 2.0f - ImGui::GetWindowHeight() / 2.0f)); // check if this mesh is used in some game model // to-do: should be done through counter, not by searching each time. - const int result = TimesMeshUsed(ObjToWorkWith); + const int Result = TimesMeshUsed(ObjToWorkWith); ImGui::Text(("Do you want to delete \"" + ObjToWorkWith->GetName() + "\" mesh ?").c_str()); - if (result > 0) - ImGui::Text(("It is used in " + std::to_string(result) + " game models !").c_str()); + if (Result > 0) + ImGui::Text(("It is used in " + std::to_string(Result) + " game models !").c_str()); ImGui::SetCursorPosX(ImGui::GetWindowWidth() / 4.0f - 120 / 2.0f); if (ImGui::Button("Delete", ImVec2(120, 0))) @@ -194,17 +194,17 @@ void DeleteMeshPopup::Render() int DeleteMeshPopup::TimesMeshUsed(const FEMesh* Mesh) { - int result = 0; - const std::vector GameModelList = RESOURCE_MANAGER.GetGameModelList(); + int Result = 0; + const std::vector GameModelList = RESOURCE_MANAGER.GetGameModelIDList(); for (size_t i = 0; i < GameModelList.size(); i++) { const FEGameModel* CurrentGameModel = RESOURCE_MANAGER.GetGameModel(GameModelList[i]); if (CurrentGameModel->Mesh == Mesh) - result++; + Result++; } - return result; + return Result; } void DeleteMeshPopup::DeleteMesh(FEMesh* Mesh) @@ -215,7 +215,7 @@ void DeleteMeshPopup::DeleteMesh(FEMesh* Mesh) // re-create game model preview std::vector GameModelListToUpdate; - const std::vector GameModelList = RESOURCE_MANAGER.GetGameModelList(); + const std::vector GameModelList = RESOURCE_MANAGER.GetGameModelIDList(); for (size_t i = 0; i < GameModelList.size(); i++) { const FEGameModel* CurrentGameModel = RESOURCE_MANAGER.GetGameModel(GameModelList[i]); @@ -236,8 +236,6 @@ void DeleteMeshPopup::DeleteMesh(FEMesh* Mesh) PREVIEW_MANAGER.MeshPreviewTextures.erase(name); } -DeleteGameModelPopup* DeleteGameModelPopup::Instance = nullptr; - DeleteGameModelPopup::DeleteGameModelPopup() { PopupCaption = "Delete game model"; @@ -264,14 +262,14 @@ void DeleteGameModelPopup::Render() return; } - ImGui::SetWindowPos(ImVec2(ENGINE.GetWindowWidth() / 2.0f - ImGui::GetWindowWidth() / 2.0f, ENGINE.GetWindowHeight() / 2.0f - ImGui::GetWindowHeight() / 2.0f)); + ImGui::SetWindowPos(ImVec2(APPLICATION.GetMainWindow()->GetWidth() / 2.0f - ImGui::GetWindowWidth() / 2.0f, APPLICATION.GetMainWindow()->GetHeight() / 2.0f - ImGui::GetWindowHeight() / 2.0f)); // check if this game model is used in some prefabs // to-do: should be done through counter, not by searching each time. - const int result = TimesGameModelUsed(ObjToWorkWith); + const int Result = TimesGameModelUsed(ObjToWorkWith); ImGui::Text(("Do you want to delete \"" + ObjToWorkWith->GetName() + "\" game model ?").c_str()); - if (result > 0) - ImGui::Text(("It is used in " + std::to_string(result) + " prefabs !").c_str()); + if (Result > 0) + ImGui::Text(("It is used in " + std::to_string(Result) + " prefabs !").c_str()); ImGui::SetCursorPosX(ImGui::GetWindowWidth() / 4.0f - 120.0f / 2.0f); if (ImGui::Button("Delete", ImVec2(120, 0))) @@ -301,35 +299,37 @@ void DeleteGameModelPopup::Render() int DeleteGameModelPopup::TimesGameModelUsed(const FEGameModel* GameModel) { - int result = 0; - const std::vector PrefabList = RESOURCE_MANAGER.GetPrefabList(); + int Result = 0; - for (int i = 0; i < PrefabList.size(); i++) + std::vector SceneList = SCENE_MANAGER.GetSceneIDList(); + for (size_t i = 0; i < SceneList.size(); i++) { - FEPrefab* CurrentPrefab = RESOURCE_MANAGER.GetPrefab(PrefabList[i]); - for (int j = 0; j < CurrentPrefab->ComponentsCount(); j++) + FEScene* CurrentScene = SCENE_MANAGER.GetScene(SceneList[i]); + std::vector EntitiesList = CurrentScene->GetEntityIDListWithComponent(); + for (size_t j = 0; j < EntitiesList.size(); j++) { - if (CurrentPrefab->GetComponent(j)->GameModel == GameModel) - result++; + FEEntity* CurrentEntity = CurrentScene->GetEntity(EntitiesList[j]); + FEGameModelComponent& GameModelComponent = CurrentEntity->GetComponent(); + if (GameModelComponent.GetGameModel() == GameModel) + Result++; } } - return result; + return Result; } void DeleteGameModelPopup::DeleteGameModel(FEGameModel* GameModel) { VIRTUAL_FILE_SYSTEM.LocateAndDeleteFile(GameModel); - std::string name = GameModel->GetName(); - SCENE.PrepareForGameModelDeletion(GameModel); + if (EDITOR.GetFocusedScene() != nullptr) + { + EDITOR.GetFocusedScene()->PrepareForGameModelDeletion(GameModel); + } RESOURCE_MANAGER.DeleteGameModel(GameModel); PROJECT_MANAGER.GetCurrent()->SetModified(true); } - -DeletePrefabPopup* DeletePrefabPopup::Instance = nullptr; - DeletePrefabPopup::DeletePrefabPopup() { PopupCaption = "Delete prefab"; @@ -356,14 +356,14 @@ void DeletePrefabPopup::Render() return; } - ImGui::SetWindowPos(ImVec2(ENGINE.GetWindowWidth() / 2.0f - ImGui::GetWindowWidth() / 2.0f, ENGINE.GetWindowHeight() / 2.0f - ImGui::GetWindowHeight() / 2.0f)); + ImGui::SetWindowPos(ImVec2(APPLICATION.GetMainWindow()->GetWidth() / 2.0f - ImGui::GetWindowWidth() / 2.0f, APPLICATION.GetMainWindow()->GetHeight() / 2.0f - ImGui::GetWindowHeight() / 2.0f)); // check if this prefab is used in some entities // to-do: should be done through counter, not by searching each time. - const int result = TimesPrefabUsed(ObjToWorkWith); + const int Result = TimesPrefabUsed(ObjToWorkWith); ImGui::Text(("Do you want to delete \"" + ObjToWorkWith->GetName() + "\" prefab ?").c_str()); - if (result > 0) - ImGui::Text(("It is used in " + std::to_string(result) + " entities !").c_str()); + if (Result > 0) + ImGui::Text(("It is used in " + std::to_string(Result) + " entities !").c_str()); ImGui::SetCursorPosX(ImGui::GetWindowWidth() / 4.0f - 120.0f / 2.0f); if (ImGui::Button("Delete", ImVec2(120, 0))) @@ -393,31 +393,36 @@ void DeletePrefabPopup::Render() int DeletePrefabPopup::TimesPrefabUsed(const FEPrefab* Prefab) { - int result = 0; - const std::vector EntitiesList = SCENE.GetEntityList(); - - for (size_t i = 0; i < EntitiesList.size(); i++) + int Result = 0; + std::vector SceneList = SCENE_MANAGER.GetSceneIDList(); + for (size_t i = 0; i < SceneList.size(); i++) { - const FEEntity* CurrentEntity = SCENE.GetEntity(EntitiesList[i]); - if (CurrentEntity->Prefab == Prefab) - result++; + FEScene* CurrentScene = SCENE_MANAGER.GetScene(SceneList[i]); + std::vector EntitiesList = CurrentScene->GetEntityIDListWithComponent(); + for (size_t j = 0; j < EntitiesList.size(); j++) + { + FEEntity* CurrentEntity = CurrentScene->GetEntity(EntitiesList[j]); + FEPrefabInstanceComponent& PrefabInstanceComponent = CurrentEntity->GetComponent(); + if (PrefabInstanceComponent.GetPrefab() == Prefab) + Result++; + } } - return result; + return Result; } void DeletePrefabPopup::DeletePrefab(FEPrefab* Prefab) { VIRTUAL_FILE_SYSTEM.LocateAndDeleteFile(Prefab); - std::string name = Prefab->GetName(); - SCENE.PrepareForPrefabDeletion(Prefab); + if (EDITOR.GetFocusedScene() != nullptr) + { + EDITOR.GetFocusedScene()->PrepareForPrefabDeletion(Prefab); + } RESOURCE_MANAGER.DeletePrefab(Prefab); PROJECT_MANAGER.GetCurrent()->SetModified(true); } -DeleteMaterialPopup* DeleteMaterialPopup::Instance = nullptr; - DeleteMaterialPopup::DeleteMaterialPopup() { PopupCaption = "Delete material"; @@ -444,14 +449,14 @@ void DeleteMaterialPopup::Render() return; } - ImGui::SetWindowPos(ImVec2(ENGINE.GetWindowWidth() / 2.0f - ImGui::GetWindowWidth() / 2.0f, ENGINE.GetWindowHeight() / 2.0f - ImGui::GetWindowHeight() / 2.0f)); + ImGui::SetWindowPos(ImVec2(APPLICATION.GetMainWindow()->GetWidth() / 2.0f - ImGui::GetWindowWidth() / 2.0f, APPLICATION.GetMainWindow()->GetHeight() / 2.0f - ImGui::GetWindowHeight() / 2.0f)); // check if this material is used in some game model // to-do: should be done through counter, not by searching each time. - const int result = TimesMaterialUsed(ObjToWorkWith); + const int Result = TimesMaterialUsed(ObjToWorkWith); ImGui::Text(("Do you want to delete \"" + ObjToWorkWith->GetName() + "\" material ?").c_str()); - if (result > 0) - ImGui::Text(("It is used in " + std::to_string(result) + " game models !").c_str()); + if (Result > 0) + ImGui::Text(("It is used in " + std::to_string(Result) + " game models !").c_str()); ImGui::SetCursorPosX(ImGui::GetWindowWidth() / 4.0f - 120 / 2.0f); if (ImGui::Button("Delete", ImVec2(120, 0))) @@ -481,17 +486,17 @@ void DeleteMaterialPopup::Render() int DeleteMaterialPopup::TimesMaterialUsed(const FEMaterial* Material) { - int result = 0; - const std::vector GameModelList = RESOURCE_MANAGER.GetGameModelList(); + int Result = 0; + const std::vector GameModelList = RESOURCE_MANAGER.GetGameModelIDList(); for (size_t i = 0; i < GameModelList.size(); i++) { const FEGameModel* CurrentGameModel = RESOURCE_MANAGER.GetGameModel(GameModelList[i]); if (CurrentGameModel->Material == Material) - result++; + Result++; } - return result; + return Result; } void DeleteMaterialPopup::DeleteMaterial(FEMaterial* Material) @@ -501,7 +506,7 @@ void DeleteMaterialPopup::DeleteMaterial(FEMaterial* Material) const std::string name = Material->GetName(); // re-create game model preview std::vector GameModelListToUpdate; - const std::vector GameModelList = RESOURCE_MANAGER.GetGameModelList(); + const std::vector GameModelList = RESOURCE_MANAGER.GetGameModelIDList(); for (size_t i = 0; i < GameModelList.size(); i++) { const FEGameModel* CurrentGameModel = RESOURCE_MANAGER.GetGameModel(GameModelList[i]); @@ -521,8 +526,6 @@ void DeleteMaterialPopup::DeleteMaterial(FEMaterial* Material) PREVIEW_MANAGER.MaterialPreviewTextures.erase(name); } -DeleteDirectoryPopup* DeleteDirectoryPopup::Instance = nullptr; - DeleteDirectoryPopup::DeleteDirectoryPopup() { PopupCaption = "Delete folder"; @@ -594,7 +597,7 @@ void DeleteDirectoryPopup::Render() ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(15, 15)); if (ImGui::BeginPopupModal(PopupCaption.c_str(), nullptr, ImGuiWindowFlags_AlwaysAutoResize)) { - ImGui::SetWindowPos(ImVec2(ENGINE.GetWindowWidth() / 2.0f - ImGui::GetWindowWidth() / 2.0f, ENGINE.GetWindowHeight() / 2.0f - ImGui::GetWindowHeight() / 2.0f)); + ImGui::SetWindowPos(ImVec2(APPLICATION.GetMainWindow()->GetWidth() / 2.0f - ImGui::GetWindowWidth() / 2.0f, APPLICATION.GetMainWindow()->GetHeight() / 2.0f - ImGui::GetWindowHeight() / 2.0f)); ImGui::Text(("Do you want to delete \"" + ObjToWorkWith + "\" folder ?").c_str()); ImGui::Text("It is not empty !"); @@ -606,7 +609,7 @@ void DeleteDirectoryPopup::Render() PROJECT_MANAGER.GetCurrent()->SetModified(true); // I should do it in a way as windows FS is doing it. - // You can't delete non empty folder + // You can't delete non-empty folder // Firstly you recursively have to delete all files and folders in it diff --git a/FEEditorSubWindows/deletePopups.h b/EditorWindows/DeletePopups.h similarity index 97% rename from FEEditorSubWindows/deletePopups.h rename to EditorWindows/DeletePopups.h index 60177bd..02c0fd7 100644 --- a/FEEditorSubWindows/deletePopups.h +++ b/EditorWindows/DeletePopups.h @@ -1,6 +1,6 @@ #pragma once -#include "../FEProject.h" +#include "../SubSystems/ProjectManagment/FEProjectManager.h" #include "VisualNodeSystem.h" #include "../SubSystems/NodeSystem/CustomNodes/FEEditorStandardNodes.h" diff --git a/FEEditorSubWindows/editPopups.cpp b/EditorWindows/EditPopups.cpp similarity index 52% rename from FEEditorSubWindows/editPopups.cpp rename to EditorWindows/EditPopups.cpp index a014345..1a3b204 100644 --- a/FEEditorSubWindows/editPopups.cpp +++ b/EditorWindows/EditPopups.cpp @@ -1,6 +1,6 @@ -#include "editPopups.h" +#include "EditPopups.h" +#include "../FEEditor.h" -EditGameModelPopup* EditGameModelPopup::Instance = nullptr; FEMesh** EditGameModelPopup::MeshToModify = nullptr; FEMaterial** EditGameModelPopup::MaterialToModify = nullptr; @@ -145,7 +145,7 @@ void EditGameModelPopup::Show(FEGameModel* GameModel) TempCaption += " " + ObjToWorkWith->GetName(); strcpy_s(Caption, TempCaption.size() + 1, TempCaption.c_str()); - Position = ImVec2(FEngine::getInstance().GetWindowWidth() / 2 - Size.x / 2, FEngine::getInstance().GetWindowHeight() / 2 - Size.y / 2); + Position = ImVec2(APPLICATION.GetMainWindow()->GetWidth() / 2 - Size.x / 2, APPLICATION.GetMainWindow()->GetHeight() / 2 - Size.y / 2); FEImGuiWindow::Show(); PREVIEW_MANAGER.CreateGameModelPreview(TempModel, &TempPreview); @@ -380,7 +380,9 @@ void EditGameModelPopup::Render() ImGui::Text("Preview of game model:"); ImGui::SetCursorPosX(Size.x / 2 - 128 / 2); ImGui::SetCursorPosY(CurrentY + 50); - ImGui::Image((void*)static_cast(TempPreview->GetTextureID()), ImVec2(128, 128), ImVec2(0.0f, 1.0f), ImVec2(1.0f, 0.0f)); + + if (TempPreview != nullptr) + ImGui::Image((void*)static_cast(TempPreview->GetTextureID()), ImVec2(128, 128), ImVec2(0.0f, 1.0f), ImVec2(1.0f, 0.0f)); if (CurrentMode == NO_LOD_MODE) { @@ -399,7 +401,7 @@ void EditGameModelPopup::Render() UpdatedLODMeshs[0] = TempModel->GetLODMesh(0); MeshToModify = &UpdatedLODMeshs[0]; - SelectFeObjectPopUp::getInstance().Show(FE_MESH, ChangeMeshCallBack, UpdatedLODMeshs[0]); + SELECT_FEOBJECT_POPUP.Show(FE_MESH, ChangeMeshCallBack, UpdatedLODMeshs[0]); } TextSize = ImGui::CalcTextSize("Material component:"); @@ -416,7 +418,7 @@ void EditGameModelPopup::Render() UpdatedMaterial = TempModel->GetMaterial(); MaterialToModify = &UpdatedMaterial; - SelectFeObjectPopUp::getInstance().Show(FE_MATERIAL, ChangeMaterialCallBack, UpdatedMaterial); + SELECT_FEOBJECT_POPUP.Show(FE_MATERIAL, ChangeMaterialCallBack, UpdatedMaterial); } } else if (CurrentMode == HAS_LOD_MODE) @@ -441,7 +443,7 @@ void EditGameModelPopup::Render() UpdatedLODMeshs[i] = TempModel->GetLODMesh(i); MeshToModify = &UpdatedLODMeshs[i]; - SelectFeObjectPopUp::getInstance().Show(FE_MESH, ChangeMeshCallBack, UpdatedLODMeshs[i]); + SELECT_FEOBJECT_POPUP.Show(FE_MESH, ChangeMeshCallBack, UpdatedLODMeshs[i]); } AddBillboard->SetPosition(ImVec2(CurrentXPosition - AddBillboard->GetSize().x / 2, CurrentY + 210.0f + 128.0f / 2.0f + 10.0f / 2.0f)); @@ -499,7 +501,7 @@ void EditGameModelPopup::Render() UpdatedLODMeshs[i] = TempModel->GetLODMesh(i); MeshToModify = &UpdatedLODMeshs[i]; - SelectFeObjectPopUp::getInstance().Show(FE_MESH, ChangeMeshCallBack, UpdatedLODMeshs[i]); + SELECT_FEOBJECT_POPUP.Show(FE_MESH, ChangeMeshCallBack, UpdatedLODMeshs[i]); } } @@ -523,7 +525,7 @@ void EditGameModelPopup::Render() if (ChangeMaterialButton->IsClicked()) { MaterialToModify = &UpdatedMaterial; - SelectFeObjectPopUp::getInstance().Show(FE_MATERIAL, ChangeMaterialCallBack, UpdatedMaterial); + SELECT_FEOBJECT_POPUP.Show(FE_MATERIAL, ChangeMaterialCallBack, UpdatedMaterial); } TextSize = ImGui::CalcTextSize("Billboard Material component:"); @@ -543,7 +545,7 @@ void EditGameModelPopup::Render() { UpdatedBillboardMaterial = TempModel->GetBillboardMaterial(); - const std::vector TempMaterialList = RESOURCE_MANAGER.GetMaterialList(); + const std::vector TempMaterialList = RESOURCE_MANAGER.GetMaterialIDList(); std::vector FinalMaterialList; for (size_t j = 0; j < TempMaterialList.size(); j++) { @@ -554,7 +556,7 @@ void EditGameModelPopup::Render() } BillboardMaterialToModify = &UpdatedBillboardMaterial; - SelectFeObjectPopUp::getInstance().Show(FE_MATERIAL, ChangeBillboardMaterialCallBack, UpdatedBillboardMaterial, FinalMaterialList); + SELECT_FEOBJECT_POPUP.Show(FE_MATERIAL, ChangeBillboardMaterialCallBack, UpdatedBillboardMaterial, FinalMaterialList); } } else @@ -572,7 +574,7 @@ void EditGameModelPopup::Render() if (ChangeMaterialButton->IsClicked()) { MaterialToModify = &UpdatedMaterial; - SelectFeObjectPopUp::getInstance().Show(FE_MATERIAL, ChangeMaterialCallBack, UpdatedMaterial); + SELECT_FEOBJECT_POPUP.Show(FE_MATERIAL, ChangeMaterialCallBack, UpdatedMaterial); } } @@ -716,52 +718,144 @@ bool EditGameModelPopup::IsLastSetupLOD(const size_t LODIndex) return true; } -EditMaterialPopup* EditMaterialPopup::Instance = nullptr; +FEEntity* EditMaterialWindow::InjectModelViewCamera(FEScene* Scene) +{ + FEEntity* CameraEntity = nullptr; + std::vector CameraPrefab = RESOURCE_MANAGER.GetPrefabByName("Model view camera prefab"); + if (CameraPrefab.size() == 0) + { + LOG.Add("EditMaterialWindow::InjectModelViewCamera: Camera prefab not found! Inserting camera manually.", "FE_LOG_LOADING", FE_LOG_WARNING); + + CameraEntity = Scene->CreateEntity("Prefab scene camera"); + CameraEntity->AddComponent(); + } + else + { + FEPrefab* CameraPrefabToUse = CameraPrefab[0]; + std::vector AddedEntities = SCENE_MANAGER.InstantiatePrefab(CameraPrefabToUse, Scene, true); + if (AddedEntities.empty()) + { + LOG.Add("EditMaterialWindow::InjectModelViewCamera: Camera prefab was not instantiated correctly. Inserting camera manually.", "FE_LOG_LOADING", FE_LOG_WARNING); + + CameraEntity = Scene->CreateEntity("Prefab scene camera"); + CameraEntity->AddComponent(); + } + else + { + CameraEntity = AddedEntities[0]; + } + + if (CameraEntity == nullptr) + { + LOG.Add("EditMaterialWindow::InjectModelViewCamera: Camera prefab was not instantiated correctly. Inserting camera manually.", "FE_LOG_LOADING", FE_LOG_WARNING); + + CameraEntity = Scene->CreateEntity("Prefab scene camera"); + CameraEntity->AddComponent(); + } + } + + RESOURCE_MANAGER.SetTag(CameraEntity, EDITOR_RESOURCE_TAG); + FECameraComponent& CameraComponent = CameraEntity->GetComponent(); + CameraComponent.TryToSetViewportSize(512, 1020); + CameraComponent.SetDistanceFogEnabled(false); + FENativeScriptComponent& CameraScript = CameraEntity->GetComponent(); + CameraScript.SetVariableValue("DistanceToModel", 10.0f); + CAMERA_SYSTEM.SetMainCamera(CameraEntity); + + return CameraEntity; +} -EditMaterialPopup::EditMaterialPopup() +EditMaterialWindow::EditMaterialWindow() { ObjToWorkWith = nullptr; - Flags = ImGuiWindowFlags_NoResize; + Flags = ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoDocking | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse; CancelButton = new ImGuiButton("Cancel"); CancelButton->SetDefaultColor(ImVec4(0.7f, 0.5f, 0.5f, 1.0f)); CancelButton->SetHoveredColor(ImVec4(0.95f, 0.5f, 0.0f, 1.0f)); CancelButton->SetActiveColor(ImVec4(0.1f, 1.0f, 0.1f, 1.0f)); -#ifdef USE_NODES NodeAreaTarget = DRAG_AND_DROP_MANAGER.AddTarget(FE_TEXTURE, DragAndDropnodeAreaTargetCallback, reinterpret_cast(&DragAndDropCallbackInfo), "Drop to add texture"); -#endif // USE_NODES + + PreviewScene = SCENE_MANAGER.CreateScene("MaterialEditor_Scene", "", FESceneFlag::Active | FESceneFlag::EditorMode); + RESOURCE_MANAGER.SetTag(PreviewScene, EDITOR_RESOURCE_TAG); + + PreviewGameModel = new FEGameModel(nullptr, nullptr, "MaterialEditor_Preview_GameModel"); + PreviewGameModel->Mesh = RESOURCE_MANAGER.GetMesh("7F251E3E0D08013E3579315F"/*"sphere"*/); + + PreviewEntity = PreviewScene->CreateEntity("MaterialEditor_Scene_PreviewEntity"); + PreviewEntity->AddComponent(PreviewGameModel); + PreviewEntity->GetComponent().SetVisibility(true); + PreviewEntity->GetComponent().SetScale(glm::vec3(0.1f)); + RESOURCE_MANAGER.SetTag(PreviewEntity, EDITOR_RESOURCE_TAG); + + PreviewCameraEntity = InjectModelViewCamera(PreviewScene); + PreviewCameraEntity->SetName("MaterialEditor_Scene_CameraEntity"); + + PreviewLightEntity = PreviewScene->CreateEntity("MaterialEditor_Scene_LightEntity"); + PreviewLightEntity->AddComponent(FE_DIRECTIONAL_LIGHT); + FELightComponent& LightComponent = PreviewLightEntity->GetComponent(); + PreviewLightEntity->GetComponent().SetRotation(glm::vec3(-40.0f, 10.0f, 0.0f)); + LightComponent.SetIntensity(5.0f); + LightComponent.SetCastShadows(false); + + FEEntity* SkyDome = PreviewScene->CreateEntity("SkyDome"); + SkyDome->GetComponent().SetScale(glm::vec3(150.0f)); + SkyDome->AddComponent(); + + PreviewScene->SetFlag(FESceneFlag::Active, false); + PreviewScene->SetFlag(FESceneFlag::Renderable, false); + INPUT.AddMouseButtonCallback(MouseButtonCallback); } -EditMaterialPopup::~EditMaterialPopup() +void EditMaterialWindow::MouseButtonCallback(const int Button, const int Action, int Mods) +{ + EDITOR_MATERIAL_WINDOW.bWindowHovered = false; + if (ImGui::GetCurrentContext()->HoveredWindow == EDITOR_MATERIAL_WINDOW.GetWindow()) + EDITOR_MATERIAL_WINDOW.bWindowHovered = true; + + if (ImGui::GetIO().WantCaptureMouse && (!EDITOR_MATERIAL_WINDOW.bWindowHovered || !EDITOR_MATERIAL_WINDOW.bCameraOutputHovered)) + { + EDITOR_MATERIAL_WINDOW.PreviewCameraEntity->GetComponent().SetActive(false); + } + + if (Button == GLFW_MOUSE_BUTTON_2 && Action == GLFW_PRESS && EDITOR_MATERIAL_WINDOW.bWindowHovered && EDITOR_MATERIAL_WINDOW.bCameraOutputHovered) + { + EDITOR_MATERIAL_WINDOW.PreviewCameraEntity->GetComponent().SetActive(true); + } + else if (Button == GLFW_MOUSE_BUTTON_2 && Action == GLFW_RELEASE) + { + EDITOR_MATERIAL_WINDOW.PreviewCameraEntity->GetComponent().SetActive(false); + } +} + +EditMaterialWindow::~EditMaterialWindow() { delete CancelButton; delete IconButton; } -#ifdef USE_NODES -FEMaterial* EditMaterialPopup::ObjToWorkWith = nullptr; -VisNodeSys::NodeArea* EditMaterialPopup::MaterialNodeArea = nullptr; -ImVec2 EditMaterialPopup::NodeGridRelativePosition = ImVec2(5, 30); -ImVec2 EditMaterialPopup::WindowPosition = ImVec2(0, 0); -ImVec2 EditMaterialPopup::MousePositionWhenContextMenuWasOpened = ImVec2(0, 0); -FETexture* EditMaterialPopup::TextureForNewNode = nullptr; -#endif // USE_NODES -void EditMaterialPopup::Show(FEMaterial* Material) +FEMaterial* EditMaterialWindow::ObjToWorkWith = nullptr; +VisNodeSys::NodeArea* EditMaterialWindow::MaterialNodeArea = nullptr; +ImVec2 EditMaterialWindow::NodeGridRelativePosition = ImVec2(5, 30); +ImVec2 EditMaterialWindow::WindowPosition = ImVec2(0, 0); +ImVec2 EditMaterialWindow::MousePositionWhenContextMenuWasOpened = ImVec2(0, 0); +FETexture* EditMaterialWindow::TextureForNewNode = nullptr; + +void EditMaterialWindow::Show(FEMaterial* Material) { if (Material != nullptr) { + PreviewGameModel->SetMaterial(Material); + PreviewScene->SetFlag(FESceneFlag::Active | FESceneFlag::Renderable, true); + TempContainer = RESOURCE_MANAGER.NoTexture; ObjToWorkWith = Material; std::string TempCaption = "Edit material:"; TempCaption += " " + ObjToWorkWith->GetName(); strcpy_s(Caption, TempCaption.size() + 1, TempCaption.c_str()); -#ifdef USE_NODES - Size = ImVec2(1500.0f, 1000.0f); -#else - size = ImVec2(1500.0f, 700.0f); -#endif // USE_NODES - Position = ImVec2(FEngine::getInstance().GetWindowWidth() / 2 - Size.x / 2, FEngine::getInstance().GetWindowHeight() / 2 - Size.y / 2); + Size = ImVec2(1512.0f, 1000.0f); + Position = ImVec2(APPLICATION.GetMainWindow()->GetWidth() / 2 - Size.x / 2, APPLICATION.GetMainWindow()->GetHeight() / 2 - Size.y / 2); FEImGuiWindow::Show(); IconButton = new ImGuiImageButton(nullptr); @@ -770,19 +864,20 @@ void EditMaterialPopup::Show(FEMaterial* Material) IconButton->SetUV1(ImVec2(1.0f, 1.0f)); IconButton->SetFramePadding(8); -#ifdef USE_NODES MaterialNodeArea = NODE_SYSTEM.CreateNodeArea(); MaterialNodeArea->SetMainContextMenuFunc(NodeSystemMainContextMenu); - MaterialNodeArea->SetNodeEventCallback(TextureNodeCallback); + MaterialNodeArea->AddNodeEventCallback(TextureNodeCallback); - FEEditorMaterialNode* NewNode = new FEEditorMaterialNode(Material); + MaterialNodeArea->SetRenderOffset(ImVec2(-340, 250)); + + FEEditorMaterialNode* MaterialNode = new FEEditorMaterialNode(Material); ImVec2 PositionOnCanvas; - PositionOnCanvas.x = NodeGridRelativePosition.x + Size.x - Size.x / 6 - NewNode->GetSize().x / 2.0f; - PositionOnCanvas.y = NodeGridRelativePosition.y + Size.y / 2 - NewNode->GetSize().y / 2.0f; - NewNode->SetPosition(PositionOnCanvas); + PositionOnCanvas.x = NodeGridRelativePosition.x + Size.x - Size.x / 6 - MaterialNode->GetSize().x / 2.0f - 150; + PositionOnCanvas.y = NodeGridRelativePosition.y + Size.y / 2 - MaterialNode->GetSize().y / 2.0f - 300; + MaterialNode->SetPosition(PositionOnCanvas); - MaterialNodeArea->AddNode(NewNode); + MaterialNodeArea->AddNode(MaterialNode); // Add all textures of material as a texture nodes // Place them in shifted grid. @@ -804,80 +899,64 @@ void EditMaterialPopup::Show(FEMaterial* Material) // We should recreate proper connections. if (Material->GetAlbedoMap() == Material->Textures[i]) { - MaterialNodeArea->TryToConnect(NewTextureNode, 5, NewNode, 0); + MaterialNodeArea->TryToConnect(NewTextureNode, 5, MaterialNode, 0); } else if (Material->GetAlbedoMap(1) == Material->Textures[i]) { - MaterialNodeArea->TryToConnect(NewTextureNode, 5, NewNode, 6); + MaterialNodeArea->TryToConnect(NewTextureNode, 5, MaterialNode, 6); } if (Material->GetNormalMap() == Material->Textures[i]) { - MaterialNodeArea->TryToConnect(NewTextureNode, 5, NewNode, 1); + MaterialNodeArea->TryToConnect(NewTextureNode, 5, MaterialNode, 1); } else if (Material->GetNormalMap(1) == Material->Textures[i]) { - MaterialNodeArea->TryToConnect(NewTextureNode, 5, NewNode, 7); + MaterialNodeArea->TryToConnect(NewTextureNode, 5, MaterialNode, 7); } if (Material->GetAOMap() == Material->Textures[i]) { - MaterialNodeArea->TryToConnect(NewTextureNode, ObjToWorkWith->GetAOMapChannel(), NewNode, 2); + MaterialNodeArea->TryToConnect(NewTextureNode, ObjToWorkWith->GetAOMapChannel(), MaterialNode, 2); } else if (Material->GetAOMap(1) == Material->Textures[i]) { - MaterialNodeArea->TryToConnect(NewTextureNode, ObjToWorkWith->GetAOMapChannel(), NewNode, 8); + MaterialNodeArea->TryToConnect(NewTextureNode, ObjToWorkWith->GetAOMapChannel(), MaterialNode, 8); } if (Material->GetRoughnessMap() == Material->Textures[i]) { - MaterialNodeArea->TryToConnect(NewTextureNode, ObjToWorkWith->GetRoughnessMapChannel(), NewNode, 3); + MaterialNodeArea->TryToConnect(NewTextureNode, ObjToWorkWith->GetRoughnessMapChannel(), MaterialNode, 3); } else if (Material->GetRoughnessMap(1) == Material->Textures[i]) { - MaterialNodeArea->TryToConnect(NewTextureNode, ObjToWorkWith->GetRoughnessMapChannel(), NewNode, 9); + MaterialNodeArea->TryToConnect(NewTextureNode, ObjToWorkWith->GetRoughnessMapChannel(), MaterialNode, 9); } if (Material->GetMetalnessMap() == Material->Textures[i]) { - MaterialNodeArea->TryToConnect(NewTextureNode, ObjToWorkWith->GetMetalnessMapChannel(), NewNode, 4); + MaterialNodeArea->TryToConnect(NewTextureNode, ObjToWorkWith->GetMetalnessMapChannel(), MaterialNode, 4); } else if (Material->GetMetalnessMap(1) == Material->Textures[i]) { - MaterialNodeArea->TryToConnect(NewTextureNode, ObjToWorkWith->GetMetalnessMapChannel(), NewNode, 10); + MaterialNodeArea->TryToConnect(NewTextureNode, ObjToWorkWith->GetMetalnessMapChannel(), MaterialNode, 10); } if (Material->GetDisplacementMap() == Material->Textures[i]) { - MaterialNodeArea->TryToConnect(NewTextureNode, ObjToWorkWith->GetDisplacementMapChannel(), NewNode, 5); + MaterialNodeArea->TryToConnect(NewTextureNode, ObjToWorkWith->GetDisplacementMapChannel(), MaterialNode, 5); } else if (Material->GetDisplacementMap(1) == Material->Textures[i]) { - MaterialNodeArea->TryToConnect(NewTextureNode, ObjToWorkWith->GetDisplacementMapChannel(), NewNode, 11); + MaterialNodeArea->TryToConnect(NewTextureNode, ObjToWorkWith->GetDisplacementMapChannel(), MaterialNode, 11); } } -#else - // ************** Drag&Drop ************** - TexturesListTarget = DRAG_AND_DROP_MANAGER.addTarget(FE_TEXTURE, DragAndDropTexturesListCallback, reinterpret_cast(&ObjToWorkWith), "Drop to add texture"); - if (MaterialBindingtargets.size() == 0) - { - MaterialBindingInfo.resize(12); - for (size_t i = 0; i < 12; i++) - { - MaterialBindingInfo[i].Material = reinterpret_cast(&ObjToWorkWith); - MaterialBindingInfo[i].TextureBinding = i; - - MaterialBindingCallbackInfo* test = &MaterialBindingInfo[i]; - MaterialBindingtargets.push_back(DRAG_AND_DROP_MANAGER.addTarget(FE_TEXTURE, DragAndDropMaterialBindingsCallback, reinterpret_cast(&MaterialBindingInfo[i]), "Drop to assign texture")); - } - } - // ************** Drag&Drop END ************** -#endif // USE_NODES } } -void EditMaterialPopup::Render() +void EditMaterialWindow::Render() { + bCameraOutputHovered = false; FEImGuiWindow::Render(); if (!IsVisible()) @@ -889,669 +968,32 @@ void EditMaterialPopup::Render() return; } -#ifdef USE_NODES - MaterialNodeArea->SetPosition(ImVec2(0, 0)); - MaterialNodeArea->SetSize(ImVec2(ImGui::GetWindowWidth(), ImGui::GetWindowHeight() - 50.0f)); - MaterialNodeArea->Update(); - NodeAreaTarget->StickToItem(); + RENDERER.Render(PreviewScene); - WindowPosition = ImGui::GetWindowPos(); - - if (ImGui::GetIO().MouseReleased[1]) - MousePositionWhenContextMenuWasOpened = ImGui::GetMousePos(); - - CancelButton->SetPosition(ImVec2(CancelButton->GetPosition().x, ImGui::GetWindowHeight() - 44.0f)); -#else - // lame callback - if (tempContainer != RESOURCE_MANAGER.noTexture) + FETexture* CameraResult = RENDERER.GetCameraResult(PreviewCameraEntity); + if (CameraResult != nullptr) { - if (textureDestination == -1) + ImGui::SetCursorPosX(-10); + ImGui::SetCursorPosY(-10); + + ImGui::Image((void*)(intptr_t)CameraResult->GetTextureID(), ImVec2(512, 1020), ImVec2(0.0f, 1.0f), ImVec2(1.0f, 0.0f)); + if (ImGui::IsItemHovered()) { - ObjToWorkWith->addTexture(tempContainer); - } - else - { - int subMaterial = textureDestination > 5; - if (subMaterial) - textureDestination -= 6; - - switch (textureDestination) - { - case 0: - { - ObjToWorkWith->setAlbedoMap(tempContainer, subMaterial); - break; - } - case 1: - { - ObjToWorkWith->setNormalMap(tempContainer, subMaterial); - break; - } - case 2: - { - ObjToWorkWith->setAOMap(tempContainer, 0, subMaterial); - break; - } - case 3: - { - ObjToWorkWith->setRoughnessMap(tempContainer, 0, subMaterial); - break; - } - case 4: - { - ObjToWorkWith->setMetalnessMap(tempContainer, 0, subMaterial); - break; - } - case 5: - { - ObjToWorkWith->setDisplacementMap(tempContainer, 0, subMaterial); - break; - } - } + bCameraOutputHovered = true; } - - tempContainer = RESOURCE_MANAGER.noTexture; - PREVIEW_MANAGER.createMaterialPreview(ObjToWorkWith->getObjectID()); - PROJECT_MANAGER.getCurrent()->bModified = true; } - ImGui::Text("Textures (%d out of 16):", textureCount); - ImGui::SameLine(); - ImGui::SetCursorPosX(size.x * 0.26f); - ImGui::Text("Bindings:"); - - ImGui::SameLine(); - ImGui::SetCursorPosX(size.x * 0.26f + size.x * 0.49f); - ImGui::Text("Settings:"); - - // Textures - { - ImGui::PushStyleColor(ImGuiCol_ChildBg, IM_COL32(0, 162, 232, 50)); - ImGui::BeginChild("Textures", ImVec2(ImGui::GetContentRegionAvail().x * 0.25f, 600), true, ImGuiWindowFlags_HorizontalScrollbar); - - if (!ImGui::IsPopupOpen("##materialPropertiesContext_menu")) - textureFromListUnderMouse = -1; - - if (ImGui::IsWindowHovered() && ImGui::IsMouseClicked(1)) - ImGui::OpenPopup("##materialPropertiesContext_menu"); - - TexturesListTarget->stickToCurrentWindow(); - - if (ImGui::BeginPopup("##materialPropertiesContext_menu")) - { - if (textureFromListUnderMouse == -1) - { - if (ImGui::MenuItem("Add texture...")) - { - textureDestination = -1; - selectTexturePopUp::getInstance().show(&tempContainer); - } - } - else - { - if (ImGui::MenuItem("Remove")) - { - ObjToWorkWith->removeTexture(textureFromListUnderMouse); - PROJECT_MANAGER.getCurrent()->bModified = true; - } - } - - ImGui::EndPopup(); - } - - ImGui::Columns(2, "TextureColumns", false); - textureCount = 0; - for (size_t i = 0; i < ObjToWorkWith->textures.size(); i++) - { - if (ObjToWorkWith->textures[i] == nullptr) - continue; - - textureCount++; - ImGui::PushID(ObjToWorkWith->textures[i]->getName().c_str()); - - ObjToWorkWith->textures[i]->getName() == "noTexture" ? iconButton->setTexture(RESOURCE_MANAGER.noTexture) : iconButton->setTexture(RESOURCE_MANAGER.getTexture(ObjToWorkWith->textures[i]->getObjectID())); - iconButton->render(); - - if (iconButton->isHovered()) - { - textureFromListUnderMouse = i; - } - - if (iconButton->isHovered() && ImGui::IsMouseDragging(0) && !DRAG_AND_DROP_MANAGER.objectIsDraged()) - DRAG_AND_DROP_MANAGER.setObject(ObjToWorkWith->textures[i], ObjToWorkWith->textures[i], ImVec2(0.0f, 1.0f), ImVec2(1.0f, 0.0f)); - - ImGui::Text(ObjToWorkWith->textures[i]->getName().c_str()); - ImGui::PopID(); - ImGui::NextColumn(); - } - ImGui::Columns(1); - - ImGui::PopStyleColor(); - ImGui::EndChild(); - } - - // material options - { - ImGui::SameLine(); - ImGui::PushStyleColor(ImGuiCol_ChildBg, IM_COL32(0, 162, 232, 50)); - ImGui::BeginChild("Bindings", ImVec2(ImGui::GetContentRegionAvail().x * 0.49f, 600), true, ImGuiWindowFlags_HorizontalScrollbar); - - ImGui::Text("First sub material:"); - - // ************* Albedo ************* - ImGui::SetCursorPosX(10); - ImGui::SetCursorPosY(38); - ImGui::Text("Albedo:"); - ObjToWorkWith->getAlbedoMap() == nullptr ? iconButton->setTexture(RESOURCE_MANAGER.noTexture) : iconButton->setTexture(ObjToWorkWith->getAlbedoMap()); - iconButton->render(); - if (iconButton->getWasClicked()) - { - textureDestination = 0; - selectTexturePopUp::getInstance().showWithCustomList(&tempContainer, ObjToWorkWith->textures); - } - - if (MaterialBindingtargets.size() > 0) - MaterialBindingtargets[0]->stickToItem(); - - if (ObjToWorkWith->getAlbedoMap() != nullptr) - { - ImGui::SetNextItemWidth(85); - if (ImGui::BeginCombo("Channel##albedo", "rgba", ImGuiWindowFlags_None)) - { - bool is_selected = true; - ImGui::Selectable("rgba", is_selected); - ImGui::SetItemDefaultFocus(); - ImGui::EndCombo(); - } - } - - // ************* Normal ************* - ImGui::SetCursorPosX(10 + ImGui::GetContentRegionAvail().x / 3.0f); - ImGui::SetCursorPosY(38); - ImGui::Text("Normal:"); - ObjToWorkWith->getNormalMap() == nullptr ? iconButton->setTexture(RESOURCE_MANAGER.noTexture) : iconButton->setTexture(ObjToWorkWith->getNormalMap()); - ImGui::SetCursorPosX(10 + ImGui::GetContentRegionAvail().x / 3.0f); - iconButton->render(); - if (iconButton->getWasClicked()) - { - textureDestination = 1; - selectTexturePopUp::getInstance().showWithCustomList(&tempContainer, ObjToWorkWith->textures); - } - - if (MaterialBindingtargets.size() > 0) - MaterialBindingtargets[1]->stickToItem(); - - if (ObjToWorkWith->getNormalMap() != nullptr) - { - ImGui::SetCursorPosX(10 + ImGui::GetContentRegionAvail().x / 3.0f); - ImGui::SetNextItemWidth(85); - if (ImGui::BeginCombo("Channel##normal", "rgb", ImGuiWindowFlags_None)) - { - bool is_selected = true; - ImGui::Selectable("rgb", is_selected); - ImGui::SetItemDefaultFocus(); - ImGui::EndCombo(); - } - } - - // ************* AO ************* - ImGui::SetCursorPosX(10 + ImGui::GetContentRegionAvail().x / 3.0f * 2.0f); - ImGui::SetCursorPosY(38); - ImGui::Text("AO:"); - ObjToWorkWith->getAOMap() == nullptr ? iconButton->setTexture(RESOURCE_MANAGER.noTexture) : iconButton->setTexture(ObjToWorkWith->getAOMap()); - ImGui::SetCursorPosX(10 + ImGui::GetContentRegionAvail().x / 3.0f * 2.0f); - iconButton->render(); - if (iconButton->getWasClicked()) - { - textureDestination = 2; - selectTexturePopUp::getInstance().showWithCustomList(&tempContainer, ObjToWorkWith->textures); - } - - if (MaterialBindingtargets.size() > 0) - MaterialBindingtargets[2]->stickToItem(); - - if (ObjToWorkWith->getAOMap() != nullptr) - { - ImGui::SetCursorPosX(10 + ImGui::GetContentRegionAvail().x / 3.0f * 2.0f); - ImGui::SetNextItemWidth(85); - if (ImGui::BeginCombo("Channel##ao", channels[ObjToWorkWith->getAOMapChannel()].c_str(), ImGuiWindowFlags_None)) - { - for (size_t i = 0; i < channels.size(); i++) - { - // if texture was compresed with out alpha channel - if (i == 3 && ObjToWorkWith->getAOMap()->getInternalFormat() == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) - continue; - - bool is_selected = (channels[ObjToWorkWith->getAOMapChannel()] == channels[i]); - if (ImGui::Selectable(channels[i].c_str(), is_selected)) - ObjToWorkWith->setAOMap(ObjToWorkWith->getAOMap(), i); - - if (is_selected) - ImGui::SetItemDefaultFocus(); - } - ImGui::EndCombo(); - } - } - - // ************* Roughness ************* - ImGui::SetCursorPosX(10); - ImGui::SetCursorPosY(38 + 128 + 80); - ImGui::Text("Roughness:"); - ObjToWorkWith->getRoughnessMap() == nullptr ? iconButton->setTexture(RESOURCE_MANAGER.noTexture) : iconButton->setTexture(ObjToWorkWith->getRoughnessMap()); - ImGui::SetCursorPosX(10); - iconButton->render(); - if (iconButton->getWasClicked()) - { - textureDestination = 3; - selectTexturePopUp::getInstance().showWithCustomList(&tempContainer, ObjToWorkWith->textures); - } - - if (MaterialBindingtargets.size() > 0) - MaterialBindingtargets[3]->stickToItem(); - - if (ObjToWorkWith->getRoughnessMap() != nullptr) - { - ImGui::SetCursorPosX(10); - ImGui::SetNextItemWidth(85); - if (ImGui::BeginCombo("Channel##roughness", channels[ObjToWorkWith->getRoughnessMapChannel()].c_str(), ImGuiWindowFlags_None)) - { - for (size_t i = 0; i < channels.size(); i++) - { - // if texture was compresed with out alpha channel - if (i == 3 && ObjToWorkWith->getRoughnessMap()->getInternalFormat() == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) - continue; - - bool is_selected = (channels[ObjToWorkWith->getRoughnessMapChannel()] == channels[i]); - if (ImGui::Selectable(channels[i].c_str(), is_selected)) - ObjToWorkWith->setRoughnessMap(ObjToWorkWith->getRoughnessMap(), i); - - if (is_selected) - ImGui::SetItemDefaultFocus(); - } - ImGui::EndCombo(); - } - } - - // ************* Metalness ************* - ImGui::SetCursorPosX(10 + ImGui::GetContentRegionAvail().x / 3.0f); - ImGui::SetCursorPosY(38 + 128 + 80); - ImGui::Text("Metalness:"); - ObjToWorkWith->getMetalnessMap() == nullptr ? iconButton->setTexture(RESOURCE_MANAGER.noTexture) : iconButton->setTexture(ObjToWorkWith->getMetalnessMap()); - ImGui::SetCursorPosX(10 + ImGui::GetContentRegionAvail().x / 3.0f); - iconButton->render(); - if (iconButton->getWasClicked()) - { - textureDestination = 4; - selectTexturePopUp::getInstance().showWithCustomList(&tempContainer, ObjToWorkWith->textures); - } - - if (MaterialBindingtargets.size() > 0) - MaterialBindingtargets[4]->stickToItem(); - - if (ObjToWorkWith->getMetalnessMap() != nullptr) - { - ImGui::SetCursorPosX(10 + ImGui::GetContentRegionAvail().x / 3.0f); - ImGui::SetNextItemWidth(85); - if (ImGui::BeginCombo("Channel##metalness", channels[ObjToWorkWith->getMetalnessMapChannel()].c_str(), ImGuiWindowFlags_None)) - { - for (size_t i = 0; i < channels.size(); i++) - { - // if texture was compresed with out alpha channel - if (i == 3 && ObjToWorkWith->getMetalnessMap()->getInternalFormat() == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) - continue; - - bool is_selected = (channels[ObjToWorkWith->getMetalnessMapChannel()] == channels[i]); - if (ImGui::Selectable(channels[i].c_str(), is_selected)) - ObjToWorkWith->setMetalnessMap(ObjToWorkWith->getMetalnessMap(), i); - - if (is_selected) - ImGui::SetItemDefaultFocus(); - } - ImGui::EndCombo(); - } - } - - // ************* Displacement ************* - ImGui::SetCursorPosX(10 + ImGui::GetContentRegionAvail().x / 3.0f * 2.0f); - ImGui::SetCursorPosY(38 + 128 + 80); - ImGui::Text("Displacement:"); - ObjToWorkWith->getDisplacementMap() == nullptr ? iconButton->setTexture(RESOURCE_MANAGER.noTexture) : iconButton->setTexture(ObjToWorkWith->getDisplacementMap()); - ImGui::SetCursorPosX(10 + ImGui::GetContentRegionAvail().x / 3.0f * 2.0f); - iconButton->render(); - if (iconButton->getWasClicked()) - { - textureDestination = 5; - selectTexturePopUp::getInstance().showWithCustomList(&tempContainer, ObjToWorkWith->textures); - } - - if (MaterialBindingtargets.size() > 0) - MaterialBindingtargets[5]->stickToItem(); - - if (ObjToWorkWith->getDisplacementMap() != nullptr) - { - ImGui::SetCursorPosX(10 + ImGui::GetContentRegionAvail().x / 3.0f * 2.0f); - ImGui::SetNextItemWidth(85); - if (ImGui::BeginCombo("Channel##displacement", channels[ObjToWorkWith->getDisplacementMapChannel()].c_str(), ImGuiWindowFlags_None)) - { - for (size_t i = 0; i < channels.size(); i++) - { - // if texture was compresed with out alpha channel - if (i == 3 && ObjToWorkWith->getDisplacementMap()->getInternalFormat() == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) - continue; - - bool is_selected = (channels[ObjToWorkWith->getDisplacementMapChannel()] == channels[i]); - if (ImGui::Selectable(channels[i].c_str(), is_selected)) - ObjToWorkWith->setDisplacementMap(ObjToWorkWith->getDisplacementMap(), i); - - if (is_selected) - ImGui::SetItemDefaultFocus(); - } - ImGui::EndCombo(); - } - } - - ImGui::SetCursorPosY(38 + 128 + 80 + 128 + 80); - ImGui::Separator(); - - ImGui::Text("Second sub material:"); - // ************* Albedo ************* - ImGui::SetCursorPosX(10); - ImGui::SetCursorPosY(64 + 128 + 80 + 128 + 80); - ImGui::Text("Albedo:"); - ObjToWorkWith->getAlbedoMap(1) == nullptr ? iconButton->setTexture(RESOURCE_MANAGER.noTexture) : iconButton->setTexture(ObjToWorkWith->getAlbedoMap(1)); - iconButton->render(); - if (iconButton->getWasClicked()) - { - textureDestination = 6; - selectTexturePopUp::getInstance().showWithCustomList(&tempContainer, ObjToWorkWith->textures); - } - - if (MaterialBindingtargets.size() > 0) - MaterialBindingtargets[6]->stickToItem(); - - if (ObjToWorkWith->getAlbedoMap(1) != nullptr) - { - ImGui::SetNextItemWidth(85); - if (ImGui::BeginCombo("Channel##albedoSubmaterial", "rgba", ImGuiWindowFlags_None)) - { - bool is_selected = true; - ImGui::Selectable("rgba", is_selected); - ImGui::SetItemDefaultFocus(); - ImGui::EndCombo(); - } - } - - // ************* Normal ************* - ImGui::SetCursorPosX(10 + ImGui::GetContentRegionAvail().x / 3.0f); - ImGui::SetCursorPosY(64 + 128 + 80 + 128 + 80); - ImGui::Text("Normal:"); - ObjToWorkWith->getNormalMap(1) == nullptr ? iconButton->setTexture(RESOURCE_MANAGER.noTexture) : iconButton->setTexture(ObjToWorkWith->getNormalMap(1)); - ImGui::SetCursorPosX(10 + ImGui::GetContentRegionAvail().x / 3.0f); - iconButton->render(); - if (iconButton->getWasClicked()) - { - textureDestination = 7; - selectTexturePopUp::getInstance().showWithCustomList(&tempContainer, ObjToWorkWith->textures); - } - - if (MaterialBindingtargets.size() > 0) - MaterialBindingtargets[7]->stickToItem(); - - if (ObjToWorkWith->getNormalMap(1) != nullptr) - { - ImGui::SetCursorPosX(10 + ImGui::GetContentRegionAvail().x / 3.0f); - ImGui::SetNextItemWidth(85); - if (ImGui::BeginCombo("Channel##normalSubmaterial", "rgb", ImGuiWindowFlags_None)) - { - bool is_selected = true; - ImGui::Selectable("rgb", is_selected); - ImGui::SetItemDefaultFocus(); - ImGui::EndCombo(); - } - } - - // ************* AO ************* - ImGui::SetCursorPosX(10 + ImGui::GetContentRegionAvail().x / 3.0f * 2.0f); - ImGui::SetCursorPosY(64 + 128 + 80 + 128 + 80); - ImGui::Text("AO:"); - ObjToWorkWith->getAOMap(1) == nullptr ? iconButton->setTexture(RESOURCE_MANAGER.noTexture) : iconButton->setTexture(ObjToWorkWith->getAOMap(1)); - ImGui::SetCursorPosX(10 + ImGui::GetContentRegionAvail().x / 3.0f * 2.0f); - iconButton->render(); - if (iconButton->getWasClicked()) - { - textureDestination = 8; - selectTexturePopUp::getInstance().showWithCustomList(&tempContainer, ObjToWorkWith->textures); - } - - if (MaterialBindingtargets.size() > 0) - MaterialBindingtargets[8]->stickToItem(); - - if (ObjToWorkWith->getAOMap(1) != nullptr) - { - ImGui::SetCursorPosX(10 + ImGui::GetContentRegionAvail().x / 3.0f * 2.0f); - ImGui::SetNextItemWidth(85); - if (ImGui::BeginCombo("Channel##aoSubmaterial", channels[ObjToWorkWith->getAOMapChannel(1)].c_str(), ImGuiWindowFlags_None)) - { - for (size_t i = 0; i < channels.size(); i++) - { - // if texture was compresed with out alpha channel - if (i == 3 && ObjToWorkWith->getAOMap(1)->getInternalFormat() == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) - continue; - - bool is_selected = (channels[ObjToWorkWith->getAOMapChannel(1)] == channels[i]); - if (ImGui::Selectable(channels[i].c_str(), is_selected)) - ObjToWorkWith->setAOMap(ObjToWorkWith->getAOMap(1), i, 1); - - if (is_selected) - ImGui::SetItemDefaultFocus(); - } - ImGui::EndCombo(); - } - } - - // ************* Roughness ************* - ImGui::SetCursorPosX(10); - ImGui::SetCursorPosY(64 + 128 + 80 + 128 + 80 + 128 + 80); - ImGui::Text("Roughness:"); - ObjToWorkWith->getRoughnessMap(1) == nullptr ? iconButton->setTexture(RESOURCE_MANAGER.noTexture) : iconButton->setTexture(ObjToWorkWith->getRoughnessMap(1)); - ImGui::SetCursorPosX(10); - iconButton->render(); - if (iconButton->getWasClicked()) - { - textureDestination = 9; - selectTexturePopUp::getInstance().showWithCustomList(&tempContainer, ObjToWorkWith->textures); - } - - if (MaterialBindingtargets.size() > 0) - MaterialBindingtargets[9]->stickToItem(); - - if (ObjToWorkWith->getRoughnessMap(1) != nullptr) - { - ImGui::SetCursorPosX(10); - ImGui::SetNextItemWidth(85); - if (ImGui::BeginCombo("Channel##roughnessSubmaterial", channels[ObjToWorkWith->getRoughnessMapChannel(1)].c_str(), ImGuiWindowFlags_None)) - { - for (size_t i = 0; i < channels.size(); i++) - { - // if texture was compresed with out alpha channel - if (i == 3 && ObjToWorkWith->getRoughnessMap(1)->getInternalFormat() == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) - continue; - - bool is_selected = (channels[ObjToWorkWith->getRoughnessMapChannel(1)] == channels[i]); - if (ImGui::Selectable(channels[i].c_str(), is_selected)) - ObjToWorkWith->setRoughnessMap(ObjToWorkWith->getRoughnessMap(1), i, 1); - - if (is_selected) - ImGui::SetItemDefaultFocus(); - } - ImGui::EndCombo(); - } - } - - // ************* Metalness ************* - ImGui::SetCursorPosX(10 + ImGui::GetContentRegionAvail().x / 3.0f); - ImGui::SetCursorPosY(64 + 128 + 80 + 128 + 80 + 128 + 80); - ImGui::Text("Metalness:"); - ObjToWorkWith->getMetalnessMap(1) == nullptr ? iconButton->setTexture(RESOURCE_MANAGER.noTexture) : iconButton->setTexture(ObjToWorkWith->getMetalnessMap(1)); - ImGui::SetCursorPosX(10 + ImGui::GetContentRegionAvail().x / 3.0f); - iconButton->render(); - if (iconButton->getWasClicked()) - { - textureDestination = 10; - selectTexturePopUp::getInstance().showWithCustomList(&tempContainer, ObjToWorkWith->textures); - } - - if (MaterialBindingtargets.size() > 0) - MaterialBindingtargets[10]->stickToItem(); - - if (ObjToWorkWith->getMetalnessMap(1) != nullptr) - { - ImGui::SetCursorPosX(10 + ImGui::GetContentRegionAvail().x / 3.0f); - ImGui::SetNextItemWidth(85); - if (ImGui::BeginCombo("Channel##metalnessSubmaterial", channels[ObjToWorkWith->getMetalnessMapChannel(1)].c_str(), ImGuiWindowFlags_None)) - { - for (size_t i = 0; i < channels.size(); i++) - { - // if texture was compresed with out alpha channel - if (i == 3 && ObjToWorkWith->getMetalnessMap(1)->getInternalFormat() == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) - continue; - - bool is_selected = (channels[ObjToWorkWith->getMetalnessMapChannel(1)] == channels[i]); - if (ImGui::Selectable(channels[i].c_str(), is_selected)) - ObjToWorkWith->setMetalnessMap(ObjToWorkWith->getMetalnessMap(1), i, 1); - - if (is_selected) - ImGui::SetItemDefaultFocus(); - } - ImGui::EndCombo(); - } - } - - // ************* Displacement ************* - ImGui::SetCursorPosX(10 + ImGui::GetContentRegionAvail().x / 3.0f * 2.0f); - ImGui::SetCursorPosY(64 + 128 + 80 + 128 + 80 + 128 + 80); - ImGui::Text("Displacement:"); - ObjToWorkWith->getDisplacementMap(1) == nullptr ? iconButton->setTexture(RESOURCE_MANAGER.noTexture) : iconButton->setTexture(ObjToWorkWith->getDisplacementMap(1)); - ImGui::SetCursorPosX(10 + ImGui::GetContentRegionAvail().x / 3.0f * 2.0f); - iconButton->render(); - if (iconButton->getWasClicked()) - { - textureDestination = 11; - selectTexturePopUp::getInstance().showWithCustomList(&tempContainer, ObjToWorkWith->textures); - } - - if (MaterialBindingtargets.size() > 0) - MaterialBindingtargets[11]->stickToItem(); - - if (ObjToWorkWith->getDisplacementMap(1) != nullptr) - { - ImGui::SetCursorPosX(10 + ImGui::GetContentRegionAvail().x / 3.0f * 2.0f); - ImGui::SetNextItemWidth(85); - if (ImGui::BeginCombo("Channel##displacementSubmaterial", channels[ObjToWorkWith->getDisplacementMapChannel(1)].c_str(), ImGuiWindowFlags_None)) - { - for (size_t i = 0; i < channels.size(); i++) - { - // if texture was compresed with out alpha channel - if (i == 3 && ObjToWorkWith->getDisplacementMap(1)->getInternalFormat() == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) - continue; - - bool is_selected = (channels[ObjToWorkWith->getDisplacementMapChannel(1)] == channels[i]); - if (ImGui::Selectable(channels[i].c_str(), is_selected)) - ObjToWorkWith->setDisplacementMap(ObjToWorkWith->getDisplacementMap(1), i, 1); - - if (is_selected) - ImGui::SetItemDefaultFocus(); - } - ImGui::EndCombo(); - } - } - - ImGui::PopStyleColor(); - ImGui::EndChild(); - } - - // Settings - { - static float fieldWidth = 350.0f; - ImGui::SameLine(); - ImGui::PushStyleColor(ImGuiCol_ChildBg, IM_COL32(0, 162, 232, 50)); - ImGui::BeginChild("Settings", ImVec2(ImGui::GetContentRegionAvail().x * 0.30f, 600), true, ImGuiWindowFlags_HorizontalScrollbar); - - FEShaderParam* debugFlag = ObjToWorkWith->getParameter("debugFlag"); - if (debugFlag != nullptr) - { - ImGui::Text("Debug flag:"); - ImGui::SetNextItemWidth(fieldWidth); - int iData = *(int*)debugFlag->data; - ImGui::SliderInt("##Debug flag", &iData, 0, 10); - debugFlag->updateData(iData); - } - - // ************* Normal ************* - ImGui::Text("Normal map intensity:"); - ImGui::SetNextItemWidth(fieldWidth); - float normalMapIntensity = ObjToWorkWith->getNormalMapIntensity(); - ImGui::DragFloat("##Normal map intensity", &normalMapIntensity, 0.01f, 0.0f, 1.0f); - ObjToWorkWith->setNormalMapIntensity(normalMapIntensity); - - // ************* AO ************* - if (ObjToWorkWith->getAOMap() == nullptr) - { - ImGui::Text("Ambient occlusion intensity:"); - ImGui::SetNextItemWidth(fieldWidth); - float ambientOcclusionIntensity = ObjToWorkWith->getAmbientOcclusionIntensity(); - ImGui::DragFloat("##Ambient occlusion intensity", &ambientOcclusionIntensity, 0.01f, 0.0f, 10.0f); - ObjToWorkWith->setAmbientOcclusionIntensity(ambientOcclusionIntensity); - } - else - { - ImGui::Text("Ambient occlusion map intensity:"); - ImGui::SetNextItemWidth(fieldWidth); - float AOMapIntensity = ObjToWorkWith->getAmbientOcclusionMapIntensity(); - ImGui::DragFloat("##Ambient occlusion map intensity", &AOMapIntensity, 0.01f, 0.0f, 10.0f); - ObjToWorkWith->setAmbientOcclusionMapIntensity(AOMapIntensity); - } + MaterialNodeArea->SetPosition(ImVec2(512 - 10, 0)); + MaterialNodeArea->SetSize(ImVec2(ImGui::GetWindowWidth() - 500, ImGui::GetWindowHeight())); + MaterialNodeArea->Update(); + NodeAreaTarget->StickToItem(); - // ************* Roughness ************* - if (ObjToWorkWith->getRoughnessMap() == nullptr) - { - ImGui::Text("Roughness:"); - ImGui::SetNextItemWidth(fieldWidth); - float roughness = ObjToWorkWith->getRoughness(); - ImGui::DragFloat("##Roughness", &roughness, 0.01f, 0.0f, 1.0f); - ObjToWorkWith->setRoughness(roughness); - } - else - { - ImGui::Text("Roughness map intensity:"); - ImGui::SetNextItemWidth(fieldWidth); - float roughness = ObjToWorkWith->getRoughnessMapIntensity(); - ImGui::DragFloat("##Roughness map intensity", &roughness, 0.01f, 0.0f, 10.0f); - ObjToWorkWith->setRoughnessMapIntensity(roughness); - } + WindowPosition = ImGui::GetWindowPos(); - // ************* Metalness ************* - if (ObjToWorkWith->getMetalnessMap() == nullptr) - { - ImGui::Text("Metalness:"); - ImGui::SetNextItemWidth(fieldWidth); - float metalness = ObjToWorkWith->getMetalness(); - ImGui::DragFloat("##Metalness", &metalness, 0.01f, 0.0f, 1.0f); - ObjToWorkWith->setMetalness(metalness); - } - else - { - ImGui::Text("Metalness map intensity:"); - ImGui::SetNextItemWidth(fieldWidth); - float metalness = ObjToWorkWith->getMetalnessMapIntensity(); - ImGui::DragFloat("##Metalness map intensity", &metalness, 0.01f, 0.0f, 10.0f); - ObjToWorkWith->setMetalnessMapIntensity(metalness); - } + if (ImGui::GetIO().MouseReleased[1]) + MousePositionWhenContextMenuWasOpened = ImGui::GetMousePos(); - ImGui::PopStyleColor(); - ImGui::EndChild(); - } -#endif // USE_NODES + CancelButton->SetPosition(ImVec2(CancelButton->GetPosition().x, ImGui::GetWindowHeight() - 44.0f)); CancelButton->Render(); if (CancelButton->IsClicked()) @@ -1563,13 +1005,20 @@ void EditMaterialPopup::Render() FEImGuiWindow::OnRenderEnd(); } -void EditMaterialPopup::Close() +void EditMaterialWindow::Close() { + Stop(); FEImGuiWindow::Close(); } -#ifdef USE_NODES -bool EditMaterialPopup::DragAndDropnodeAreaTargetCallback(FEObject* Object, void** CallbackInfo) +void EditMaterialWindow::Stop() +{ + PreviewScene->SetFlag(FESceneFlag::Active, false); + PreviewScene->SetFlag(FESceneFlag::Renderable, false); + PreviewGameModel->SetMaterial(nullptr); +} + +bool EditMaterialWindow::DragAndDropnodeAreaTargetCallback(FEObject* Object, void** CallbackInfo) { if (ObjToWorkWith->IsTextureInList(RESOURCE_MANAGER.GetTexture(Object->GetObjectID()))) return false; @@ -1587,83 +1036,8 @@ bool EditMaterialPopup::DragAndDropnodeAreaTargetCallback(FEObject* Object, void MaterialNodeArea->AddNode(NewNode); return true; } -#else -bool editMaterialPopup::dragAndDropCallback(FEObject* object, void** oldTexture) -{ - FETexture* newTexture = RESOURCE_MANAGER.getTexture(object->getObjectID()); - *oldTexture = reinterpret_cast(newTexture); - - return true; -} -bool editMaterialPopup::dragAndDropTexturesListCallback(FEObject* object, void** material) -{ - reinterpret_cast(*material)->addTexture(RESOURCE_MANAGER.getTexture(object->getObjectID())); - return true; -} - -bool editMaterialPopup::dragAndDropMaterialBindingsCallback(FEObject* object, void** callbackInfoPointer) -{ - materialBindingCallbackInfo* info = reinterpret_cast(callbackInfoPointer); - FEMaterial* material = reinterpret_cast(*info->material); - - - if (!material->isTextureInList(RESOURCE_MANAGER.getTexture(object->getObjectID()))) - material->addTexture(RESOURCE_MANAGER.getTexture(object->getObjectID())); - - int subMaterial = info->textureBinding > 5; - if (subMaterial) - info->textureBinding -= 6; - - switch (info->textureBinding) - { - case 0: - { - material->setAlbedoMap(RESOURCE_MANAGER.getTexture(object->getObjectID()), subMaterial); - break; - } - - case 1: - { - material->setNormalMap(RESOURCE_MANAGER.getTexture(object->getObjectID()), subMaterial); - break; - } - - case 2: - { - material->setAOMap(RESOURCE_MANAGER.getTexture(object->getObjectID()), 0, subMaterial); - break; - } - - case 3: - { - material->setRoughnessMap(RESOURCE_MANAGER.getTexture(object->getObjectID()), 0, subMaterial); - break; - } - - case 4: - { - material->setMetalnessMap(RESOURCE_MANAGER.getTexture(object->getObjectID()), 0, subMaterial); - break; - } - - case 5: - { - material->setDisplacementMap(RESOURCE_MANAGER.getTexture(object->getObjectID()), 0, subMaterial); - break; - } - - default: - break; - } - - return true; -} -#endif // USE_NODES - - -#ifdef USE_NODES -void EditMaterialPopup::NodeSystemMainContextMenu() +void EditMaterialWindow::NodeSystemMainContextMenu() { if (ImGui::BeginMenu("Add")) { @@ -1671,7 +1045,7 @@ void EditMaterialPopup::NodeSystemMainContextMenu() { TextureForNewNode = RESOURCE_MANAGER.NoTexture; - SelectFeObjectPopUp::getInstance().Show(FE_TEXTURE, TextureNodeCreationCallback); + SELECT_FEOBJECT_POPUP.Show(FE_TEXTURE, TextureNodeCreationCallback); } if (ImGui::MenuItem("Float node")) @@ -1690,7 +1064,7 @@ void EditMaterialPopup::NodeSystemMainContextMenu() } } -void EditMaterialPopup::TextureNodeCallback(VisNodeSys::Node* Node, const VisNodeSys::NODE_EVENT EventWithNode) +void EditMaterialWindow::TextureNodeCallback(VisNodeSys::Node* Node, const VisNodeSys::NODE_EVENT EventWithNode) { if (Node == nullptr) return; @@ -1708,7 +1082,7 @@ void EditMaterialPopup::TextureNodeCallback(VisNodeSys::Node* Node, const VisNod } } -void EditMaterialPopup::TextureNodeCreationCallback(const std::vector SelectionsResult) +void EditMaterialWindow::TextureNodeCreationCallback(const std::vector SelectionsResult) { if (SelectionsResult.size() != 1 && SelectionsResult[0]->GetType() != FE_TEXTURE) return; @@ -1730,5 +1104,4 @@ void EditMaterialPopup::TextureNodeCreationCallback(const std::vector } } } -} -#endif // USE_NODES +} \ No newline at end of file diff --git a/FEEditorSubWindows/editPopups.h b/EditorWindows/EditPopups.h similarity index 80% rename from FEEditorSubWindows/editPopups.h rename to EditorWindows/EditPopups.h index de79ce4..206c59c 100644 --- a/FEEditorSubWindows/editPopups.h +++ b/EditorWindows/EditPopups.h @@ -1,6 +1,6 @@ #pragma once -#include "selectPopups.h" +#include "SelectPopups.h" class EditGameModelPopup : public FEImGuiWindow { @@ -81,11 +81,11 @@ class EditGameModelPopup : public FEImGuiWindow void Close(); }; -#define USE_NODES - -class EditMaterialPopup : public FEImGuiWindow +class EditMaterialWindow : public FEImGuiWindow { - SINGLETON_PRIVATE_PART(EditMaterialPopup) + friend class FEEditor; + + SINGLETON_PRIVATE_PART(EditMaterialWindow) ImGuiButton* CancelButton; ImGuiImageButton* IconButton = nullptr; @@ -96,7 +96,6 @@ class EditMaterialPopup : public FEImGuiWindow FETexture* TempContainer = nullptr; int TextureDestination = -1; -#ifdef USE_NODES static FEMaterial* ObjToWorkWith; // ************** Node area ************** @@ -124,28 +123,28 @@ class EditMaterialPopup : public FEImGuiWindow static bool DragAndDropnodeAreaTargetCallback(FEObject* Object, void** CallbackInfo); // ************** Drag&Drop END ************** -#else - FEMaterial* ObjToWorkWith; - // ************** Drag&Drop ************** - struct MaterialBindingCallbackInfo - { - void** Material; - int TextureBinding; - }; - std::vector MaterialBindingInfo; - std::vector MaterialBindingtargets; - DragAndDropTarget* TexturesListTarget; + // ************** Scene ************** + FEScene* PreviewScene; + FEGameModel* PreviewGameModel; + FEEntity* PreviewEntity; + FEEntity* PreviewCameraEntity; + FEEntity* PreviewLightEntity; - static bool DragAndDropCallback(FEObject* Object, void** OldTexture); - static bool DragAndDropTexturesListCallback(FEObject* Object, void** Material); - static bool DragAndDropMaterialBindingsCallback(FEObject* Object, void** CallbackInfoPointer); - // ************** Drag&Drop END ************** -#endif // USE_NODES + bool bWindowHovered = false; + bool bCameraOutputHovered = false; + static void MouseButtonCallback(const int Button, const int Action, int Mods); + // ************** Scene END ************** + + void Stop(); + + FEEntity* InjectModelViewCamera(FEScene* Scene); public: - SINGLETON_PUBLIC_PART(EditMaterialPopup) + SINGLETON_PUBLIC_PART(EditMaterialWindow) void Show(FEMaterial* Material); void Render() override; void Close(); -}; \ No newline at end of file +}; + +#define EDITOR_MATERIAL_WINDOW EditMaterialWindow::GetInstance() \ No newline at end of file diff --git a/EditorWindows/EditorBaseWindowClasses/FEEditorSceneWindow.cpp b/EditorWindows/EditorBaseWindowClasses/FEEditorSceneWindow.cpp new file mode 100644 index 0000000..4c5d922 --- /dev/null +++ b/EditorWindows/EditorBaseWindowClasses/FEEditorSceneWindow.cpp @@ -0,0 +1,171 @@ +#include "FEEditorSceneWindow.h" +#include "../../FEEditor.h" + +FEEditorSceneWindow::FEEditorSceneWindow(FEScene* Scene) +{ + if (Scene == nullptr) + return; + + this->Scene = Scene; + SceneID = Scene->GetObjectID(); + Flags = ImGuiWindowFlags_None | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse; + + std::string WindowName = Scene->GetName(); + // Window name must be unique. + WindowName += "##" + Scene->GetObjectID(); + + SetCaption(WindowName); + SetBorderSize(0.0f); + SetPadding(glm::vec2(0.0f, 0.0f)); + + AcceptedTypes.push_back(FE_GAMEMODEL); + AcceptedTypes.push_back(FE_PREFAB); + ToolTipTexts.push_back("Drop to add to scene"); + ToolTipTexts.push_back("Drop to add to scene"); + CurrentDragAndDropCallback = DragAndDropCallBack; +} + +bool FEEditorSceneWindow::DragAndDropCallBack(FEObject* Object, void** UserData) +{ + if (EDITOR.GetFocusedScene() == nullptr) + return false; + + if (CAMERA_SYSTEM.GetMainCamera(EDITOR.GetFocusedScene()) == nullptr) + return false; + + if (UserData == nullptr) + return false; + + FEEditorSceneWindow* EditorSceneWindow = reinterpret_cast(UserData); + if (EditorSceneWindow->GetScene() == nullptr) + return false; + + if (Object->GetType() == FE_GAMEMODEL) + { + FEGameModel* GameModel = RESOURCE_MANAGER.GetGameModel(Object->GetObjectID()); + + FETransformComponent& CameraTransformComponent = CAMERA_SYSTEM.GetMainCamera(EDITOR.GetFocusedScene())->GetComponent(); + FECameraComponent& CameraComponent = CAMERA_SYSTEM.GetMainCamera(EDITOR.GetFocusedScene())->GetComponent(); + + FEEntity* Entity = EditorSceneWindow->GetScene()->CreateEntity(Object->GetName()); + Entity->GetComponent().SetPosition(CameraTransformComponent.GetPosition(FE_WORLD_SPACE) + CameraComponent.GetForward() * 10.0f); + Entity->AddComponent(GameModel); + + SELECTED.SetSelected(Entity); + PROJECT_MANAGER.GetCurrent()->SetModified(true); + + return true; + + } + else if (Object->GetType() == FE_PREFAB) + { + FETransformComponent& CameraTransformComponent = CAMERA_SYSTEM.GetMainCamera(EDITOR.GetFocusedScene())->GetComponent(); + FECameraComponent& CameraComponent = CAMERA_SYSTEM.GetMainCamera(EDITOR.GetFocusedScene())->GetComponent(); + + FEPrefab* Prefab = RESOURCE_MANAGER.GetPrefab(Object->GetObjectID()); + FEScene* PrefabScene = Prefab->GetScene(); + FENaiveSceneGraphNode* RootNode = PrefabScene->SceneGraph.GetRoot(); + + std::vector AddedEntities = SCENE_MANAGER.InstantiatePrefab(Prefab, EditorSceneWindow->GetScene()); + if (!AddedEntities.empty()) + { + AddedEntities[0]->GetComponent().SetPosition(CameraTransformComponent.GetPosition(FE_WORLD_SPACE) + CameraComponent.GetForward() * 10.0f); + SELECTED.SetSelected(AddedEntities[0]); + PROJECT_MANAGER.GetCurrent()->SetModified(true); + return true; + } + } + + return false; +} + +FEEditorSceneWindow::~FEEditorSceneWindow() +{ + +} + +void FEEditorSceneWindow::Show() +{ + +} + +void FEEditorSceneWindow::Render() +{ + if (bJustAdded) + { + ImGui::SetWindowFocus(); + Size = ImVec2(910, 512); + bJustAdded = false; + } + + FEImGuiWindow::Render(); + + if (!IsVisible()) + return; + + if (SceneWindowTarget != nullptr) + SceneWindowTarget->StickToCurrentWindow(); + + if (ImGui::IsWindowFocused()) + EDITOR.SetFocusedScene(Scene); + + + FEProject* CurrentProject = PROJECT_MANAGER.GetCurrent(); + if (CurrentProject == nullptr) + return; + + FEEntity* CameraEntity = nullptr; + if (Scene->HasFlag(FESceneFlag::EditorMode)) + { + std::string EditorCameraID = CurrentProject->GetEditorCameraIDBySceneID(Scene->GetObjectID()); + CameraEntity = Scene->GetEntity(EditorCameraID); + } + else if (Scene->HasFlag(FESceneFlag::GameMode)) + { + CameraEntity = CAMERA_SYSTEM.GetMainCamera(Scene); + } + + if (CameraEntity != nullptr) + { + FECameraComponent& CameraComponent = CameraEntity->GetComponent(); + + if (CameraComponent.GetViewport() == nullptr || CameraComponent.GetViewport()->GetType() == FE_VIEWPORT_VIRTUAL) + { + std::string NewViewportID = ENGINE.CreateViewport(GetWindow()); + CAMERA_SYSTEM.SetCameraViewport(CameraEntity, NewViewportID); + SELECTED.AddSceneData(Scene->GetObjectID()); + GIZMO_MANAGER.AddSceneData(Scene->GetObjectID()); + SceneWindowTarget = DRAG_AND_DROP_MANAGER.AddTarget(AcceptedTypes, + CurrentDragAndDropCallback, + reinterpret_cast(this), + ToolTipTexts); + } + + ImGuiStyle& Style = ImGui::GetStyle(); + Style.WindowBorderSize = 0.0f; + Style.WindowPadding = ImVec2(0.0f, 0.0f); + + FETexture* CameraResult = RENDERER.GetCameraResult(CAMERA_SYSTEM.GetMainCamera(Scene)); + if (CameraResult != nullptr) + { + ImGui::Image((void*)(intptr_t)CameraResult->GetTextureID(), ImVec2(GetWindow()->ContentRegionRect.GetWidth(), GetWindow()->ContentRegionRect.GetHeight()), ImVec2(0.0f, 1.0f), ImVec2(1.0f, 0.0f)); + } + } + else + { + ImGui::Text("No camera in scene"); + } + + if (bSelfContained) + OnRenderEnd(); +} + +void FEEditorSceneWindow::OnRenderEnd() +{ + FEImGuiWindow::OnRenderEnd(); +} + +FEScene* FEEditorSceneWindow::GetScene() const +{ + return Scene; +} \ No newline at end of file diff --git a/EditorWindows/EditorBaseWindowClasses/FEEditorSceneWindow.h b/EditorWindows/EditorBaseWindowClasses/FEEditorSceneWindow.h new file mode 100644 index 0000000..0aaae87 --- /dev/null +++ b/EditorWindows/EditorBaseWindowClasses/FEEditorSceneWindow.h @@ -0,0 +1,35 @@ +#pragma once + +#include "../../FEDearImguiWrapper/FEDearImguiWrapper.h" +#include "../../FEEditorDragAndDropManager.h" +#include + +class FEEditorSceneWindow : public FEImGuiWindow +{ + friend class FEEditor; +private: + static bool DragAndDropCallBack(FEObject* Object, void** UserData); +protected: + FEEditorSceneWindow(FEScene* Scene); + ~FEEditorSceneWindow(); + + FEScene* Scene = nullptr; + std::string SceneID = ""; + DragAndDropTarget* SceneWindowTarget = nullptr; + + bool bJustAdded = true; + bool bWindowHovered = false; + + bool bSelfContained = true; + bool bWaitingForRemoval = false; + + std::vector AcceptedTypes; + std::vector ToolTipTexts; + std::function CurrentDragAndDropCallback; +public: + void Show(); + void Render() override; + void OnRenderEnd() override; + + FEScene* GetScene() const; +}; \ No newline at end of file diff --git a/EditorWindows/GyzmosSettingsWindow.cpp b/EditorWindows/GyzmosSettingsWindow.cpp new file mode 100644 index 0000000..d9f3c35 --- /dev/null +++ b/EditorWindows/GyzmosSettingsWindow.cpp @@ -0,0 +1,105 @@ +#include "GyzmosSettingsWindow.h" +#include "../FEEditor.h" + +GyzmosSettingsWindow::GyzmosSettingsWindow() +{ + Flags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoScrollbar; +} + +GyzmosSettingsWindow::~GyzmosSettingsWindow() +{ + delete TransformationGizmoButton; + delete ScaleGizmoButton; + delete RotateGizmoButton; +} + +void GyzmosSettingsWindow::Show() +{ + const std::string TempCaption = "##GizmosSettingsWindow"; + strcpy_s(Caption, TempCaption.size() + 1, TempCaption.c_str()); + Size = ImVec2(146.0f, 48.0f); + Position = ImVec2(APPLICATION.GetMainWindow()->GetWidth() / 2.0f - 150.0f / 2.0f, 10.0f); + FEImGuiWindow::Show(); + + if (TransformationGizmoButton == nullptr) + TransformationGizmoButton = new ImGuiImageButton(GIZMO_MANAGER.TransformationGizmoIcon); + + if (ScaleGizmoButton == nullptr) + ScaleGizmoButton = new ImGuiImageButton(GIZMO_MANAGER.ScaleGizmoIcon); + + if (RotateGizmoButton == nullptr) + RotateGizmoButton = new ImGuiImageButton(GIZMO_MANAGER.RotateGizmoIcon); + + float CurrentX = 5.0f; + TransformationGizmoButton->SetPosition(ImVec2(CurrentX, 5.0f)); + CurrentX += 32.0f + 16.0f; + ScaleGizmoButton->SetPosition(ImVec2(CurrentX, 5.0f)); + CurrentX += 32.0f + 16.0f; + RotateGizmoButton->SetPosition(ImVec2(CurrentX, 5.0f)); +} + +void GyzmosSettingsWindow::Render() +{ + if (!IsVisible()) + return; + + FEScene* CurrentScene = EDITOR.GetFocusedScene(); + if (CurrentScene == nullptr) + return; + + FEGizmoSceneData* GizmoSceneData = GIZMO_MANAGER.GetSceneData(CurrentScene->GetObjectID()); + if (GizmoSceneData == nullptr) + return; + + FEImGuiWindow::Render(); + + GizmoSceneData->GizmosState == TRANSFORM_GIZMOS ? SetSelectedStyle(TransformationGizmoButton) : SetDefaultStyle(TransformationGizmoButton); + ImGui::PushID(0); + TransformationGizmoButton->Render(); + if (TransformationGizmoButton->IsClicked()) + { + if (GizmoSceneData->GizmosState != TRANSFORM_GIZMOS) + { + GIZMO_MANAGER.UpdateGizmoState(TRANSFORM_GIZMOS, CurrentScene); + ImGui::PopID(); + FEImGuiWindow::OnRenderEnd(); + return; + } + } + ImGui::PopID(); + ShowToolTip("Translate objects. key = shift"); + + GizmoSceneData->GizmosState == SCALE_GIZMOS ? SetSelectedStyle(ScaleGizmoButton) : SetDefaultStyle(ScaleGizmoButton); + ImGui::PushID(1); + ScaleGizmoButton->Render(); + if (ScaleGizmoButton->IsClicked()) + { + if (GizmoSceneData->GizmosState != SCALE_GIZMOS) + { + GIZMO_MANAGER.UpdateGizmoState(SCALE_GIZMOS, CurrentScene); + ImGui::PopID(); + FEImGuiWindow::OnRenderEnd(); + return; + } + } + ImGui::PopID(); + ShowToolTip("Scale objects. key = shift"); + + GizmoSceneData->GizmosState == ROTATE_GIZMOS ? SetSelectedStyle(RotateGizmoButton) : SetDefaultStyle(RotateGizmoButton); + ImGui::PushID(2); + RotateGizmoButton->Render(); + if (RotateGizmoButton->IsClicked()) + { + if (GizmoSceneData->GizmosState != ROTATE_GIZMOS) + { + GIZMO_MANAGER.UpdateGizmoState(ROTATE_GIZMOS, CurrentScene); + ImGui::PopID(); + FEImGuiWindow::OnRenderEnd(); + return; + } + } + ImGui::PopID(); + ShowToolTip("Rotate objects. key = shift"); + + FEImGuiWindow::OnRenderEnd(); +} \ No newline at end of file diff --git a/EditorWindows/GyzmosSettingsWindow.h b/EditorWindows/GyzmosSettingsWindow.h new file mode 100644 index 0000000..7a8f0b6 --- /dev/null +++ b/EditorWindows/GyzmosSettingsWindow.h @@ -0,0 +1,17 @@ +#pragma once + +#include "ShaderEditorWindow.h" + +class GyzmosSettingsWindow : public FEImGuiWindow +{ + ImGuiImageButton* TransformationGizmoButton = nullptr; + ImGuiImageButton* ScaleGizmoButton = nullptr; + ImGuiImageButton* RotateGizmoButton = nullptr; +public: + GyzmosSettingsWindow(); + ~GyzmosSettingsWindow(); + + void Show() override; + void Render() override; +}; +static GyzmosSettingsWindow GyzmosSettingsWindowObject; \ No newline at end of file diff --git a/EditorWindows/InspectorWindow.cpp b/EditorWindows/InspectorWindow.cpp new file mode 100644 index 0000000..5ef5b21 --- /dev/null +++ b/EditorWindows/InspectorWindow.cpp @@ -0,0 +1,2459 @@ +#include "InspectorWindow.h" +#include "../FEEditor.h" + +FEEntity* FEEditorInspectorWindow::EntityToModify = nullptr; +FEEntity* FEEditorInspectorWindow::TerrainToWorkWith = nullptr; + +FEEditorInspectorWindow::FEEditorInspectorWindow() +{ + std::vector RegisteredComponentList = COMPONENTS_TOOL.GetComponentInfoList(); + AddComponentHandlers[typeid(FELightComponent)] = &FEEditorInspectorWindow::AddLightComponent; + AddComponentHandlers[typeid(FECameraComponent)] = &FEEditorInspectorWindow::AddCameraComponent; + AddComponentHandlers[typeid(FEGameModelComponent)] = &FEEditorInspectorWindow::AddGameModelComponent; + AddComponentHandlers[typeid(FEInstancedComponent)] = &FEEditorInspectorWindow::AddInstancedComponent; + AddComponentHandlers[typeid(FETerrainComponent)] = &FEEditorInspectorWindow::AddTerrainComponent; + AddComponentHandlers[typeid(FEVirtualUIComponent)] = &FEEditorInspectorWindow::AddVirtualUIComponent; + AddComponentHandlers[typeid(FENativeScriptComponent)] = &FEEditorInspectorWindow::AddNativeScriptComponent; + + RemoveComponentHandlers[typeid(FECameraComponent)] = [](FEEntity* ParentEntity) -> void { + ParentEntity->RemoveComponent(); + }; + RemoveComponentHandlers[typeid(FELightComponent)] = [](FEEntity* ParentEntity) -> void { + ParentEntity->RemoveComponent(); + }; + RemoveComponentHandlers[typeid(FEGameModelComponent)] = [](FEEntity* ParentEntity) -> void { + ParentEntity->RemoveComponent(); + }; + RemoveComponentHandlers[typeid(FEInstancedComponent)] = [](FEEntity* ParentEntity) -> void { + ParentEntity->RemoveComponent(); + }; + RemoveComponentHandlers[typeid(FETerrainComponent)] = [](FEEntity* ParentEntity) -> void { + ParentEntity->RemoveComponent(); + }; + RemoveComponentHandlers[typeid(FESkyDomeComponent)] = [](FEEntity* ParentEntity) -> void { + ParentEntity->RemoveComponent(); + }; + RemoveComponentHandlers[typeid(FEPrefabInstanceComponent)] = [](FEEntity* ParentEntity) -> void { + ParentEntity->RemoveComponent(); + }; + RemoveComponentHandlers[typeid(FEVirtualUIComponent)] = [](FEEntity* ParentEntity) -> void { + ParentEntity->RemoveComponent(); + }; + RemoveComponentHandlers[typeid(FENativeScriptComponent)] = [](FEEntity* ParentEntity) -> void { + ParentEntity->RemoveComponent(); + }; +} + +void FEEditorInspectorWindow::InitializeResources() +{ + // ************** Terrain Settings ************** + ExportHeightMapButton = new ImGuiButton("Export HeightMap"); + ExportHeightMapButton->SetSize(ImVec2(200, 0)); + + ImportHeightMapButton = new ImGuiButton("Import HeightMap"); + ImportHeightMapButton->SetSize(ImVec2(200, 0)); + + SculptBrushIcon = RESOURCE_MANAGER.LoadPNGTexture("Resources/Images/sculptBrush.png", "sculptBrushIcon"); + RESOURCE_MANAGER.SetTag(SculptBrushIcon, EDITOR_RESOURCE_TAG); + SculptBrushButton = new ImGuiImageButton(SculptBrushIcon); + SculptBrushButton->SetSize(ImVec2(24, 24)); + + LevelBrushIcon = RESOURCE_MANAGER.LoadPNGTexture("Resources/Images/levelBrush.png", "levelBrushIcon"); + RESOURCE_MANAGER.SetTag(LevelBrushIcon, EDITOR_RESOURCE_TAG); + LevelBrushButton = new ImGuiImageButton(LevelBrushIcon); + LevelBrushButton->SetSize(ImVec2(24, 24)); + + SmoothBrushIcon = RESOURCE_MANAGER.LoadPNGTexture("Resources/Images/smoothBrush.png", "smoothBrushIcon"); + RESOURCE_MANAGER.SetTag(SmoothBrushIcon, EDITOR_RESOURCE_TAG); + SmoothBrushButton = new ImGuiImageButton(SmoothBrushIcon); + SmoothBrushButton->SetSize(ImVec2(24, 24)); + + DrawBrushIcon = RESOURCE_MANAGER.LoadPNGTexture("Resources/Images/paintbrush.png", "drawBrushIcon"); + RESOURCE_MANAGER.SetTag(DrawBrushIcon, EDITOR_RESOURCE_TAG); + LayerBrushButton = new ImGuiImageButton(DrawBrushIcon); + LayerBrushButton->SetSize(ImVec2(48, 48)); + + EntityChangeGameModelTarget = DRAG_AND_DROP_MANAGER.AddTarget(FE_GAMEMODEL, EntityChangeGameModelTargetCallBack, nullptr, "Drop to assign game model"); + // ************** Terrain Settings END ************** + + MouseCursorIcon = RESOURCE_MANAGER.LoadPNGTexture("Resources/Images/mouseCursorIcon.png", "mouseCursorIcon"); + RESOURCE_MANAGER.SetTag(MouseCursorIcon, EDITOR_RESOURCE_TAG); + ArrowToGroundIcon = RESOURCE_MANAGER.LoadPNGTexture("Resources/Images/arrowToGroundIcon.png", "arrowToGroundIcon"); + RESOURCE_MANAGER.SetTag(ArrowToGroundIcon, EDITOR_RESOURCE_TAG); +} + +void FEEditorInspectorWindow::Clear() +{ + +} + +void FEEditorInspectorWindow::ShowTransformConfiguration(FEObject* Object, FETransformComponent* Transform) const +{ + ShowTransformConfiguration(Object->GetName(), Transform); +} + +bool FEEditorInspectorWindow::EntityChangeGameModelTargetCallBack(FEObject* Object, void** EntityPointer) +{ + if (EDITOR.GetFocusedScene() == nullptr) + return false; + + FEEntity* Entity = SELECTED.GetSelected(EDITOR.GetFocusedScene()); + if (Entity == nullptr) + return false; + + FEGameModelComponent& GameModelComponent = Entity->GetComponent(); + GameModelComponent.SetGameModel(RESOURCE_MANAGER.GetGameModel(Object->GetObjectID())); + + return true; +} + +bool FEEditorInspectorWindow::TerrainChangeMaterialTargetCallBack(FEObject* Object, void** LayerIndex) +{ + if (EDITOR.GetFocusedScene() == nullptr) + return false; + + FEScene* CurrentScene = EDITOR.GetFocusedScene(); + + if (SELECTED.GetSelected(CurrentScene) == nullptr || !SELECTED.GetSelected(CurrentScene)->HasComponent()) + return false; + + FEMaterial* MaterialToAssign = RESOURCE_MANAGER.GetMaterial(Object->GetObjectID()); + if (!MaterialToAssign->IsCompackPacking()) + return false; + + FETerrainComponent& Terrain = SELECTED.GetSelected(CurrentScene)->GetComponent(); + const int TempLayerIndex = *(int*)LayerIndex; + if (TempLayerIndex >= 0 && TempLayerIndex < FE_TERRAIN_MAX_LAYERS) + Terrain.GetLayerInSlot(TempLayerIndex)->SetMaterial(MaterialToAssign); + + return true; +} + +void FEEditorInspectorWindow::ShowTransformConfiguration(const std::string Name, FETransformComponent* Transform) const +{ + static float EditWidth = 70.0f; + bool bModified = false; + // ********************* POSITION ********************* + glm::vec3 Position = Transform->GetPosition(); + ImGui::Text("Position : "); + ImGui::SameLine(); + ImGui::SetNextItemWidth(EditWidth); + if (ImGui::DragFloat((std::string("##X pos : ") + Name).c_str(), &Position[0], 0.1f)) + bModified = true; + ShowToolTip("X position"); + + ImGui::SameLine(); + ImGui::SetNextItemWidth(EditWidth); + if (ImGui::DragFloat((std::string("##Y pos : ") + Name).c_str(), &Position[1], 0.1f)) + bModified = true; + ShowToolTip("Y position"); + + ImGui::SameLine(); + ImGui::SetNextItemWidth(EditWidth); + if (ImGui::DragFloat((std::string("##Z pos : ") + Name).c_str(), &Position[2], 0.1f)) + bModified = true; + ShowToolTip("Z position"); + + if (bModified) + Transform->SetPosition(Position); + + bModified = false; + + // ********************* WORLD POSITION ********************* + glm::vec3 WorldPosition = Transform->GetPosition(FE_WORLD_SPACE); + ImGui::Text("World Position : "); + ImGui::SameLine(); + ImGui::SetNextItemWidth(EditWidth); + if (ImGui::DragFloat((std::string("##World X pos : ") + Name).c_str(), &WorldPosition[0], 0.1f)) + bModified = true; + ShowToolTip("X position"); + + ImGui::SameLine(); + ImGui::SetNextItemWidth(EditWidth); + if (ImGui::DragFloat((std::string("##World Y pos : ") + Name).c_str(), &WorldPosition[1], 0.1f)) + bModified = true; + ShowToolTip("Y position"); + + ImGui::SameLine(); + ImGui::SetNextItemWidth(EditWidth); + if (ImGui::DragFloat((std::string("##World Z pos : ") + Name).c_str(), &WorldPosition[2], 0.1f)) + bModified = true; + ShowToolTip("Z position"); + + if (bModified) + Transform->SetPosition(WorldPosition, FE_WORLD_SPACE); + + bModified = false; + + // ********************* ROTATION ********************* + glm::vec3 Rotation = Transform->GetRotation(); + ImGui::Text("Rotation : "); + ImGui::SameLine(); + ImGui::SetNextItemWidth(EditWidth); + if (ImGui::DragFloat((std::string("##X rot : ") + Name).c_str(), &Rotation[0], 0.1f, -360.0f, 360.0f)) + bModified = true; + ShowToolTip("X rotation"); + + ImGui::SameLine(); + ImGui::SetNextItemWidth(EditWidth); + if (ImGui::DragFloat((std::string("##Y rot : ") + Name).c_str(), &Rotation[1], 0.1f, -360.0f, 360.0f)) + bModified = true; + ShowToolTip("Y rotation"); + + ImGui::SameLine(); + ImGui::SetNextItemWidth(EditWidth); + if (ImGui::DragFloat((std::string("##Z rot : ") + Name).c_str(), &Rotation[2], 0.1f, -360.0f, 360.0f)) + bModified = true; + ShowToolTip("Z rotation"); + + if (bModified) + Transform->SetRotation(Rotation); + + bModified = false; + + // ********************* WORLD ROTATION ********************* + glm::vec3 WorldRotation = Transform->GetRotation(FE_WORLD_SPACE); + ImGui::Text("World Rotation : "); + ImGui::SameLine(); + ImGui::SetNextItemWidth(EditWidth); + if (ImGui::DragFloat((std::string("##World X rot : ") + Name).c_str(), &WorldRotation[0], 0.1f, -360.0f, 360.0f)) + bModified = true; + ShowToolTip("X rotation"); + + ImGui::SameLine(); + ImGui::SetNextItemWidth(EditWidth); + if (ImGui::DragFloat((std::string("##World Y rot : ") + Name).c_str(), &WorldRotation[1], 0.1f, -360.0f, 360.0f)) + bModified = true; + ShowToolTip("Y rotation"); + + ImGui::SameLine(); + ImGui::SetNextItemWidth(EditWidth); + if (ImGui::DragFloat((std::string("##World Z rot : ") + Name).c_str(), &WorldRotation[2], 0.1f, -360.0f, 360.0f)) + bModified = true; + ShowToolTip("Z rotation"); + + if (bModified) + Transform->SetRotation(WorldRotation, FE_WORLD_SPACE); + + bModified = false; + + // ********************* SCALE ********************* + bool bUniformScaling = Transform->IsUniformScalingSet(); + ImGui::Checkbox("Uniform scaling", &bUniformScaling); + Transform->SetUniformScaling(bUniformScaling); + + glm::vec3 Scale = Transform->GetScale(); + float ScaleChangeSpeed = Scale.x * 0.01f; + ImGui::Text("Scale : "); + ImGui::SameLine(); + ImGui::SetNextItemWidth(EditWidth); + if (ImGui::DragFloat((std::string("##X scale : ") + Name).c_str(), &Scale[0], ScaleChangeSpeed, 0.001f, 1000.0f)) + { + bModified = true; + if (bUniformScaling) + { + Scale[1] = Scale[0]; + Scale[2] = Scale[0]; + } + } + ShowToolTip("X scale"); + + ImGui::SameLine(); + ImGui::SetNextItemWidth(EditWidth); + if (ImGui::DragFloat((std::string("##Y scale : ") + Name).c_str(), &Scale[1], ScaleChangeSpeed, 0.001f, 1000.0f)) + { + bModified = true; + if (bUniformScaling) + { + Scale[0] = Scale[1]; + Scale[2] = Scale[1]; + } + } + ShowToolTip("Y scale"); + + ImGui::SameLine(); + ImGui::SetNextItemWidth(EditWidth); + if (ImGui::DragFloat((std::string("##Z scale : ") + Name).c_str(), &Scale[2], ScaleChangeSpeed, 0.001f, 1000.0f)) + { + bModified = true; + if (bUniformScaling) + { + Scale[0] = Scale[2]; + Scale[1] = Scale[2]; + } + } + ShowToolTip("Z scale"); + + if (bModified) + Transform->SetScale(Scale); + + bModified = false; + + // ********************* WORLD SCALE ********************* + glm::vec3 WorldScale = Transform->GetScale(FE_WORLD_SPACE); + ScaleChangeSpeed = WorldScale.x * 0.01f; + ImGui::Text("World Scale : "); + ImGui::SameLine(); + ImGui::SetNextItemWidth(EditWidth); + if (ImGui::DragFloat((std::string("##World X scale : ") + Name).c_str(), &WorldScale[0], ScaleChangeSpeed, 0.001f, 1000.0f)) + { + bModified = true; + if (bUniformScaling) + { + WorldScale[1] = WorldScale[0]; + WorldScale[2] = WorldScale[0]; + } + } + ShowToolTip("X scale"); + + ImGui::SameLine(); + ImGui::SetNextItemWidth(EditWidth); + if (ImGui::DragFloat((std::string("##World Y scale : ") + Name).c_str(), &WorldScale[1], ScaleChangeSpeed, 0.001f, 1000.0f)) + { + bModified = true; + if (bUniformScaling) + { + WorldScale[0] = WorldScale[1]; + WorldScale[2] = WorldScale[1]; + } + } + ShowToolTip("Y scale"); + + ImGui::SameLine(); + ImGui::SetNextItemWidth(EditWidth); + if (ImGui::DragFloat((std::string("##World Z scale : ") + Name).c_str(), &WorldScale[2], ScaleChangeSpeed, 0.001f, 1000.0f)) + { + bModified = true; + if (bUniformScaling) + { + WorldScale[0] = WorldScale[2]; + WorldScale[1] = WorldScale[2]; + } + } + ShowToolTip("Z scale"); + + if (bModified) + Transform->SetScale(WorldScale, FE_WORLD_SPACE); +} + +void FEEditorInspectorWindow::DisplayLightProperties(FEEntity* LightEntity) const +{ + FELightComponent& LightComponent = LightEntity->GetComponent(); + + if (LightComponent.GetType() == FE_DIRECTIONAL_LIGHT) + { + ImGui::Text("Cast shadows:"); + ImGui::SameLine(); + ImGui::SetNextItemWidth(200); + bool bCastShadows = LightComponent.IsCastShadows(); + ImGui::Checkbox("##Cast shadows", &bCastShadows); + LightComponent.SetCastShadows(bCastShadows); + ShowToolTip("Will this light cast shadows."); + + if (!LightComponent.IsCastShadows()) + ImGui::BeginDisabled(); + + ImGui::Text("Number of cascades :"); + ImGui::SameLine(); + ImGui::SetNextItemWidth(200); + int CascadesCount = LightComponent.GetActiveCascades(); + ImGui::SliderInt("##cascades", &CascadesCount, 1, 4); + LightComponent.SetActiveCascades(CascadesCount); + ShowToolTip("How much steps of shadow quality will be used."); + + ImGui::Text("Shadow coverage in M :"); + ImGui::SameLine(); + ImGui::SetNextItemWidth(200); + float FirstCascadeSize = LightComponent.GetShadowCoverage(); + ImGui::DragFloat("##shadowCoverage", &FirstCascadeSize, 0.1f, 0.1f, 500.0f); + LightComponent.SetShadowCoverage(FirstCascadeSize); + ShowToolTip("Distance from camera at which shadows would be present."); + + ImGui::Text("Z depth of shadow map :"); + ImGui::SameLine(); + ImGui::SetNextItemWidth(200); + float CSMZDepth = LightComponent.GetCSMZDepth(); + ImGui::DragFloat("##CSMZDepth", &CSMZDepth, 0.01f, 0.1f, 100.0f); + LightComponent.SetCSMZDepth(CSMZDepth); + ShowToolTip("If you have problems with shadow disapearing when camera is at close distance to shadow reciver, tweaking this parameter could help. Otherwise this parameter should be as small as possible."); + + ImGui::Text("XY depth of shadow map :"); + ImGui::SameLine(); + ImGui::SetNextItemWidth(200); + float CSMXYDepth = LightComponent.GetCSMXYDepth(); + ImGui::DragFloat("##CSMXYDepth", &CSMXYDepth, 0.01f, 0.0f, 100.0f); + LightComponent.SetCSMXYDepth(CSMXYDepth); + ShowToolTip("If you have problems with shadow on edges of screen, tweaking this parameter could help. Otherwise this parameter should be as small as possible."); + + ImGui::Text("Shadows blur factor:"); + ImGui::SameLine(); + ImGui::SetNextItemWidth(200.0f); + float ShadowsBlurFactor = LightComponent.GetShadowBlurFactor(); + ImGui::DragFloat("##Shadows blur factor", &ShadowsBlurFactor, 0.001f, 0.0f, 10.0f); + LightComponent.SetShadowBlurFactor(ShadowsBlurFactor); + + bool bStaticShadowBias = LightComponent.IsStaticShadowBias(); + ImGui::Checkbox("Static shadow bias :", &bStaticShadowBias); + LightComponent.SetIsStaticShadowBias(bStaticShadowBias); + + if (LightComponent.IsStaticShadowBias()) + { + ImGui::Text("Static shadow bias value :"); + ImGui::SameLine(); + ImGui::SetNextItemWidth(200); + float ShadowBias = LightComponent.GetShadowBias(); + ImGui::DragFloat("##shadowBias", &ShadowBias, 0.0001f, 0.00001f, 0.1f); + LightComponent.SetShadowBias(ShadowBias); + } + else + { + ImGui::Text("Intensity of variable shadow bias :"); + ImGui::SameLine(); + ImGui::SetNextItemWidth(200); + float ShadowBiasIntensity = LightComponent.GetShadowBiasVariableIntensity(); + ImGui::DragFloat("##shadowBiasIntensity", &ShadowBiasIntensity, 0.01f, 0.01f, 10.0f); + LightComponent.SetShadowBiasVariableIntensity(ShadowBiasIntensity); + } + + if (!LightComponent.IsCastShadows()) + ImGui::EndDisabled(); + } + else if (LightComponent.GetType() == FE_POINT_LIGHT) + { + ImGui::Text("Light range :"); + ImGui::SameLine(); + ImGui::SetNextItemWidth(200); + float LightRange = LightComponent.GetRange(); + ImGui::DragFloat("##LightRadius", &LightRange, 0.1f, 0.1f, 100.0f); + LightComponent.SetRange(LightRange); + + } + else if (LightComponent.GetType() == FE_SPOT_LIGHT) + { + glm::vec3 Direction = LIGHT_SYSTEM.GetDirection(LightEntity); + ImGui::DragFloat("##x", &Direction[0], 0.01f, 0.0f, 1.0f); + ImGui::DragFloat("##y", &Direction[1], 0.01f, 0.0f, 1.0f); + ImGui::DragFloat("##z", &Direction[2], 0.01f, 0.0f, 1.0f); + + float SpotAngle = LightComponent.GetSpotAngle(); + ImGui::SliderFloat((std::string("Inner angle##") + LightEntity->GetName()).c_str(), &SpotAngle, 0.0f, 90.0f); + LightComponent.SetSpotAngle(SpotAngle); + + float SpotAngleOuter = LightComponent.GetSpotAngleOuter(); + ImGui::SliderFloat((std::string("Outer angle ##") + LightEntity->GetName()).c_str(), &SpotAngleOuter, 0.0f, 90.0f); + LightComponent.SetSpotAngleOuter(SpotAngleOuter); + } + + glm::vec3 Color = LightComponent.GetColor(); + ImGui::ColorEdit3((std::string("Color##") + LightEntity->GetName()).c_str(), &Color.x); + LightComponent.SetColor(Color); + + float Intensity = LightComponent.GetIntensity(); + ImGui::SliderFloat((std::string("Intensity##") + LightEntity->GetName()).c_str(), &Intensity, 0.0f, 100.0f); + LightComponent.SetIntensity(Intensity); +} + +void FEEditorInspectorWindow::DisplayCameraProperties(FEEntity* CameraEntity) const +{ + FECameraComponent& CameraComponent = CameraEntity->GetComponent(); + + if (EDITOR.GetFocusedScene() == nullptr) + return; + + // Because of editor camera system, we need to check if it is main camera in a different way. + std::string MainCameraID = PROJECT_MANAGER.GetCurrent()->GetProperMainCameraIDBySceneID(EDITOR.GetFocusedScene()->GetObjectID()); + bool bIsMainCamera = MainCameraID == CameraEntity->GetObjectID(); + if (ImGui::Checkbox("Main camera", &bIsMainCamera)) + { + if (bIsMainCamera) + { + PROJECT_MANAGER.GetCurrent()->SetProperMainCameraIDBySceneID(EDITOR.GetFocusedScene()->GetObjectID(), CameraEntity->GetObjectID()); + } + else + { + PROJECT_MANAGER.GetCurrent()->SetProperMainCameraIDBySceneID(EDITOR.GetFocusedScene()->GetObjectID(), ""); + } + } + + // Rendering scale + ImGui::Text("Rendering scale:"); + ImGui::SameLine(); + ImGui::SetNextItemWidth(200); + float RenderScale = CameraComponent.GetRenderScale(); + ImGui::DragFloat("##RenderScale", &RenderScale, 0.01f, 0.05f, 2.0f); + CAMERA_SYSTEM.SetCameraRenderScale(CameraEntity, RenderScale); + + // Camera Preview + ImGui::Text("Camera Preview:"); + + FEScene* CurrentScene = CameraEntity->GetParentScene(); + FETexture* CameraPreviewTexture = nullptr; + + // If it is an editor camera, we do not need to render scene again. + if (CameraEntity->GetObjectID() == PROJECT_MANAGER.GetCurrent()->GetEditorCameraIDBySceneID(CurrentScene->GetObjectID())) + { + CameraPreviewTexture = RENDERER.GetCameraResult(CameraEntity); + } + else + { + FEEntity* OldMainCameraEntity = CAMERA_SYSTEM.GetMainCamera(EDITOR.GetFocusedScene()); + CAMERA_SYSTEM.SetMainCamera(CameraEntity); + + CameraComponent.TryToSetViewportSize(452, 256); + RENDERER.Render(CurrentScene); + CameraPreviewTexture = RENDERER.GetCameraResult(CameraEntity); + + CAMERA_SYSTEM.SetMainCamera(OldMainCameraEntity); + } + + if (CameraPreviewTexture != nullptr) + ImGui::Image((void*)(intptr_t)CameraPreviewTexture->GetTextureID(), ImVec2(452, 256), ImVec2(0.0f, 1.0f), ImVec2(1.0f, 0.0f)); + + // Rendering pipeline settings + ImGui::Text("Rendering pipeline:"); + static const char* RenderingPipelineOptions[2] = { "Deferred", "Forward_Simplified" }; + FERenderingPipeline SelectedRenderingPipeline = CameraComponent.GetRenderingPipeline(); + static int CurrentIndex = 0; + if (SelectedRenderingPipeline == FERenderingPipeline::Deferred) + { + CurrentIndex = 0; + } + else if (SelectedRenderingPipeline == FERenderingPipeline::Forward_Simplified) + { + CurrentIndex = 1; + } + + ImGui::SetNextItemWidth(200); + if (ImGui::Combo("##RenderingPipeline", &CurrentIndex, RenderingPipelineOptions, 2)) + { + CAMERA_SYSTEM.SetCameraRenderingPipeline(CameraEntity, CurrentIndex == 0 ? FERenderingPipeline::Deferred : FERenderingPipeline::Forward_Simplified); + } + + float FOV = CameraComponent.GetFOV(); + ImGui::Text("Field of view : "); + ImGui::SameLine(); + ImGui::SetNextItemWidth(70); + ImGui::DragFloat("##FOV", &FOV, 0.1f, 1.0f, 179.0f); + CameraComponent.SetFOV(FOV); + + float NearPlane = CameraComponent.GetNearPlane(); + ImGui::Text("Near plane : "); + ImGui::SameLine(); + ImGui::SetNextItemWidth(70); + ImGui::DragFloat("##NearPlane", &NearPlane, 0.1f, 0.01f, 1000.0f); + CameraComponent.SetNearPlane(NearPlane); + + float FarPlane = CameraComponent.GetFarPlane(); + ImGui::Text("Far plane : "); + ImGui::SameLine(); + ImGui::SetNextItemWidth(70); + ImGui::DragFloat("##FarPlane", &FarPlane, 0.1f, 0.01f, 10000.0f); + CameraComponent.SetFarPlane(FarPlane); + + glm::vec4 CurrentClearColor = CameraComponent.GetClearColor(); + ImGui::ColorEdit4("Clear color", &CurrentClearColor.x); + CameraComponent.SetClearColor(CurrentClearColor); + + float Gamma = CameraComponent.GetGamma(); + ImGui::Text("Gamma : "); + ImGui::SameLine(); + ImGui::SetNextItemWidth(70); + ImGui::DragFloat("##Gamma", &Gamma, 0.1f, 0.1f, 10.0f); + CameraComponent.SetGamma(Gamma); + + float Exposure = CameraComponent.GetExposure(); + ImGui::Text("Exposure : "); + ImGui::SameLine(); + ImGui::SetNextItemWidth(70); + ImGui::DragFloat("##Exposure", &Exposure, 0.1f, 0.1f, 10.0f); + CameraComponent.SetExposure(Exposure); + + // *********** Bloom *********** + ImGui::Separator(); + ImGui::Text("Bloom:"); + ImGui::Text("Threshold:"); + float Threshold = CameraComponent.GetBloomThreshold(); + ImGui::SetNextItemWidth(70); + ImGui::DragFloat("##Threshold", &Threshold, 0.01f, 0.001f, 30.0f); + CameraComponent.SetBloomThreshold(Threshold); + + /*ImGui::PushID(GUIID++); + ImGui::SameLine(); + ResetButton->Render(); + if (ResetButton->IsClicked()) + { + CameraComponent.SetBloomThreshold(1.5f); + } + ImGui::PopID();*/ + + ImGui::Text("Size:"); + float Size = CameraComponent.GetBloomSize(); + ImGui::SetNextItemWidth(70); + ImGui::DragFloat("##BloomSize", &Size, 0.01f, 0.001f, 100.0f); + CameraComponent.SetBloomSize(Size); + + /*ImGui::PushID(GUIID++); + ImGui::SameLine(); + ResetButton->Render(); + if (ResetButton->IsClicked()) + { + CameraComponent.SetBloomSize(5.0f); + } + ImGui::PopID();*/ + + // *********** Anti-Aliasing(FXAA) *********** + ImGui::Separator(); + + bool bTemporalJitterEnabled = CameraComponent.IsTemporalJitterEnabled(); + ImGui::Checkbox("Sub pixel jitter", &bTemporalJitterEnabled); + CameraComponent.SetTemporalJitterEnabled(bTemporalJitterEnabled); + + const std::vector SEQUENCE_OPTIONS = { 72, 32, 24, 18, 8 }; + static size_t TemporalJitterSequenceLength = 64; + + if (ImGui::BeginCombo("Jitter phase sequence Count", std::to_string(TemporalJitterSequenceLength).c_str())) + { + for (const auto& count : SEQUENCE_OPTIONS) + { + bool is_selected = (TemporalJitterSequenceLength == count); + if (ImGui::Selectable(std::to_string(count).c_str(), is_selected)) + TemporalJitterSequenceLength = count; + if (is_selected) + ImGui::SetItemDefaultFocus(); + } + ImGui::EndCombo(); + } + CameraComponent.SetTemporalJitterSequenceLength(TemporalJitterSequenceLength); + + ImGui::Text("Anti-Aliasing(FXAA)"); + static const char* options[5] = { "none", "1x", "2x", "4x", "8x" }; + static std::string SelectedOption = "1x"; + + const float FXAASpanMax = CameraComponent.GetFXAASpanMax(); + if (FXAASpanMax == 0.0f) + { + SelectedOption = options[0]; + } + else if (FXAASpanMax > 0.1f && FXAASpanMax < 1.1f) + { + SelectedOption = options[1]; + } + else if (FXAASpanMax > 1.1f && FXAASpanMax < 2.1f) + { + SelectedOption = options[2]; + } + else if (FXAASpanMax > 2.1f && FXAASpanMax < 4.1f) + { + SelectedOption = options[3]; + } + else if (FXAASpanMax > 4.1f && FXAASpanMax < 8.1f) + { + SelectedOption = options[4]; + } + else + { + SelectedOption = options[5]; + } + + // TO-DO: it should be per camera. + static bool bDebugSettings = false; + if (ImGui::Checkbox("debug view", &bDebugSettings)) + { + const float FXAASpanMax = CameraComponent.GetFXAASpanMax(); + if (FXAASpanMax == 0.0f) + { + SelectedOption = options[0]; + } + else if (FXAASpanMax > 0.1f && FXAASpanMax < 1.1f) + { + SelectedOption = options[1]; + } + else if (FXAASpanMax > 1.1f && FXAASpanMax < 2.1f) + { + SelectedOption = options[2]; + } + else if (FXAASpanMax > 2.1f && FXAASpanMax < 4.1f) + { + SelectedOption = options[3]; + } + else if (FXAASpanMax > 4.1f && FXAASpanMax < 8.1f) + { + SelectedOption = options[4]; + } + else + { + SelectedOption = options[5]; + } + } + + if (!bDebugSettings) + { + ImGui::Text("Anti Aliasing Strength:"); + if (ImGui::BeginCombo("##Anti Aliasing Strength", SelectedOption.c_str(), ImGuiWindowFlags_None)) + { + for (size_t i = 0; i < 5; i++) + { + const bool is_selected = (SelectedOption == options[i]); + if (ImGui::Selectable(options[i], is_selected)) + { + CameraComponent.SetFXAASpanMax(float(pow(2.0, (i - 1)))); + if (i == 0) + CameraComponent.SetFXAASpanMax(0.0f); + SelectedOption = options[i]; + } + + if (is_selected) + ImGui::SetItemDefaultFocus(); + } + ImGui::EndCombo(); + } + } + else + { + ImGui::Text("FXAASpanMax:"); + ImGui::SetNextItemWidth(70); + float FXAASpanMax = CameraComponent.GetFXAASpanMax(); + ImGui::DragFloat("##FXAASpanMax", &FXAASpanMax, 0.0f, 0.001f, 32.0f); + CameraComponent.SetFXAASpanMax(FXAASpanMax); + + /*ImGui::PushID(GUIID++); + ImGui::SameLine(); + ResetButton->Render(); + if (ResetButton->IsClicked()) + { + CameraComponent.SetFXAASpanMax(8.0f); + } + ImGui::PopID();*/ + + ImGui::Text("FXAAReduceMin:"); + ImGui::SetNextItemWidth(70); + float FXAAReduceMin = CameraComponent.GetFXAAReduceMin(); + ImGui::DragFloat("##FXAAReduceMin", &FXAAReduceMin, 0.01f, 0.001f, 100.0f); + CameraComponent.SetFXAAReduceMin(FXAAReduceMin); + + /*ImGui::PushID(GUIID++); + ImGui::SameLine(); + ResetButton->Render(); + if (ResetButton->IsClicked()) + { + CameraComponent.SetFXAAReduceMin(0.008f); + } + ImGui::PopID();*/ + + ImGui::Text("FXAAReduceMul:"); + ImGui::SetNextItemWidth(70); + float FXAAReduceMul = CameraComponent.GetFXAAReduceMul(); + ImGui::DragFloat("##FXAAReduceMul", &FXAAReduceMul, 0.01f, 0.001f, 100.0f); + CameraComponent.SetFXAAReduceMul(FXAAReduceMul); + + /*ImGui::PushID(GUIID++); + ImGui::SameLine(); + ResetButton->Render(); + if (ResetButton->IsClicked()) + { + CameraComponent.SetFXAAReduceMul(0.400f); + } + ImGui::PopID();*/ + } + + ImGui::Separator(); + ImGui::Text("Depth of Field:"); + // *********** Depth of Field *********** + ImGui::Text("Near distance:"); + ImGui::SetNextItemWidth(70); + float DepthThreshold = CameraComponent.GetDOFNearDistance(); + ImGui::DragFloat("##depthThreshold", &DepthThreshold, 0.0f, 0.001f, 100.0f); + CameraComponent.SetDOFNearDistance(DepthThreshold); + + ImGui::Text("Far distance:"); + ImGui::SetNextItemWidth(70); + float DepthThresholdFar = CameraComponent.GetDOFFarDistance(); + ImGui::DragFloat("##depthThresholdFar", &DepthThresholdFar, 0.0f, 0.001f, 100.0f); + CameraComponent.SetDOFFarDistance(DepthThresholdFar); + + ImGui::Text("Strength:"); + ImGui::SetNextItemWidth(70); + float Strength = CameraComponent.GetDOFStrength(); + ImGui::DragFloat("##Strength", &Strength, 0.0f, 0.001f, 10.0f); + CameraComponent.SetDOFStrength(Strength); + + ImGui::Text("Distance dependent strength:"); + ImGui::SetNextItemWidth(70); + float IntMult = CameraComponent.GetDOFDistanceDependentStrength(); + ImGui::DragFloat("##Distance dependent strength", &IntMult, 0.0f, 0.001f, 100.0f); + CameraComponent.SetDOFDistanceDependentStrength(IntMult); + + ImGui::Separator(); + ImGui::Text("Chromatic Aberration:"); + ImGui::Text("Shift strength:"); + ImGui::SetNextItemWidth(70); + float intensity = CameraComponent.GetChromaticAberrationIntensity(); + ImGui::DragFloat("##intensity", &intensity, 0.01f, 0.0f, 30.0f); + CameraComponent.SetChromaticAberrationIntensity(intensity); + + /*ImGui::PushID(GUIID++); + ImGui::SameLine(); + ResetButton->Render(); + if (ResetButton->IsClicked()) + { + CameraComponent.SetChromaticAberrationIntensity(1.0f); + } + ImGui::PopID();*/ + + ImGui::Separator(); + ImGui::Text("SSAO:"); + // *********** SSAO *********** + static const char* SSAO_Options[5] = { "Off", "Low", "Medium", "High", "Custom" }; + static std::string SSAO_SelectedOption = "Medium"; + const int SampleCount = CameraComponent.GetSSAOSampleCount(); + + if (!CameraComponent.IsSSAOEnabled()) + { + SSAO_SelectedOption = SSAO_Options[0]; + } + else if (SampleCount == 4) + { + SSAO_SelectedOption = SSAO_Options[1]; + } + else if (SampleCount == 16 && CameraComponent.GetSSAORadiusSmallDetails()) + { + SSAO_SelectedOption = SSAO_Options[2]; + } + else if (SampleCount == 32 && CameraComponent.GetSSAORadiusSmallDetails()) + { + SSAO_SelectedOption = SSAO_Options[3]; + } + else + { + SSAO_SelectedOption = SSAO_Options[4]; + } + + static bool bSSAO_DebugSettings = false; + if (ImGui::Checkbox("Debug view", &bSSAO_DebugSettings)) + { + + } + + if (!bSSAO_DebugSettings) + { + ImGui::Text("SSAO Quality:"); + ImGui::SetNextItemWidth(150); + if (ImGui::BeginCombo("##SSAO Quality", SSAO_SelectedOption.c_str(), ImGuiWindowFlags_None)) + { + for (size_t i = 0; i < 5; i++) + { + const bool is_selected = (SSAO_SelectedOption == SSAO_Options[i]); + if (ImGui::Selectable(SSAO_Options[i], is_selected)) + { + CameraComponent.SetSSAOResultBlured(true); + CameraComponent.SetSSAOBias(0.013f); + CameraComponent.SetSSAORadius(10.0f); + CameraComponent.SetSSAORadiusSmallDetails(0.4f); + CameraComponent.SetSSAOSmallDetailsWeight(0.2f); + + if (i == 0) + { + CameraComponent.SetSSAOEnabled(false); + } + else if (i == 1) + { + CameraComponent.SetSSAOEnabled(true); + + CameraComponent.SetSSAOSampleCount(4); + CameraComponent.SetSSAOSmallDetailsEnabled(false); + } + else if (i == 2) + { + CameraComponent.SetSSAOEnabled(true); + + CameraComponent.SetSSAOSampleCount(16); + CameraComponent.SetSSAOSmallDetailsEnabled(true); + } + else if (i == 3) + { + CameraComponent.SetSSAOEnabled(true); + + CameraComponent.SetSSAOSampleCount(32); + CameraComponent.SetSSAOSmallDetailsEnabled(true); + } + + SSAO_SelectedOption = SSAO_Options[i]; + } + + if (is_selected) + ImGui::SetItemDefaultFocus(); + } + ImGui::EndCombo(); + } + } + else + { + bool TempBool = CameraComponent.IsSSAOEnabled(); + ImGui::Checkbox("SSAO active", &TempBool); + CameraComponent.SetSSAOEnabled(TempBool); + + TempBool = CameraComponent.IsSSAOSmallDetailsEnabled(); + ImGui::Checkbox("SSAO small details", &TempBool); + CameraComponent.SetSSAOSmallDetailsEnabled(TempBool); + + TempBool = CameraComponent.IsSSAOResultBlured(); + ImGui::Checkbox("SSAO blured", &TempBool); + CameraComponent.SetSSAOResultBlured(TempBool); + + int TempInt = CameraComponent.GetSSAOSampleCount(); + ImGui::SetNextItemWidth(100); + ImGui::DragInt("SSAO sample count", &TempInt); + CameraComponent.SetSSAOSampleCount(TempInt); + + float TempFloat = CameraComponent.GetSSAOBias(); + ImGui::SetNextItemWidth(100); + ImGui::DragFloat("SSAO bias", &TempFloat, 0.1f); + CameraComponent.SetSSAOBias(TempFloat); + + TempFloat = CameraComponent.GetSSAORadius(); + ImGui::SetNextItemWidth(100); + ImGui::DragFloat("SSAO radius", &TempFloat, 0.1f); + CameraComponent.SetSSAORadius(TempFloat); + + TempFloat = CameraComponent.GetSSAORadiusSmallDetails(); + ImGui::SetNextItemWidth(100); + ImGui::DragFloat("SSAO radius small details", &TempFloat, 0.1f); + CameraComponent.SetSSAORadiusSmallDetails(TempFloat); + + TempFloat = CameraComponent.GetSSAOSmallDetailsWeight(); + ImGui::SetNextItemWidth(100); + ImGui::DragFloat("SSAO small details weight", &TempFloat, 0.01f); + CameraComponent.SetSSAOSmallDetailsWeight(TempFloat); + } + + // *********** Distance Fog *********** + ImGui::Separator(); + ImGui::Text("Distance Fog:"); + bool bEnabledFog = CameraComponent.IsDistanceFogEnabled(); + if (ImGui::Checkbox("Enable fog", &bEnabledFog)) + { + CameraComponent.SetDistanceFogEnabled(bEnabledFog); + } + + if (bEnabledFog) + { + ImGui::Text("Density:"); + ImGui::SetNextItemWidth(70); + float FogDensity = CameraComponent.GetDistanceFogDensity(); + ImGui::DragFloat("##fogDensity", &FogDensity, 0.0001f, 0.0f, 5.0f); + CameraComponent.SetDistanceFogDensity(FogDensity); + + /*ImGui::PushID(GUIID++); + ImGui::SameLine(); + ResetButton->Render(); + if (ResetButton->IsClicked()) + { + CameraComponent.SetDistanceFogDensity(0.007f); + } + ImGui::PopID();*/ + + ImGui::Text("Gradient:"); + ImGui::SetNextItemWidth(70); + float FogGradient = CameraComponent.GetDistanceFogGradient(); + ImGui::DragFloat("##fogGradient", &FogGradient, 0.001f, 0.0f, 5.0f); + CameraComponent.SetDistanceFogGradient(FogGradient); + + /*ImGui::PushID(GUIID++); + ImGui::SameLine(); + ResetButton->Render(); + if (ResetButton->IsClicked()) + { + CameraComponent.SetDistanceFogGradient(2.5f); + } + ImGui::PopID();*/ + } +} + +void FEEditorInspectorWindow::ChangeGameModelOfEntityCallBack(const std::vector SelectionsResult) +{ + if (EntityToModify == nullptr) + return; + + if (SelectionsResult.size() == 1 && SelectionsResult[0]->GetType() == FE_GAMEMODEL) + { + FEGameModel* SelectedGameModel = RESOURCE_MANAGER.GetGameModel(SelectionsResult[0]->GetObjectID()); + if (SelectedGameModel == nullptr) + return; + + FEGameModelComponent& GameModelComponent = EntityToModify->GetComponent(); + GameModelComponent.SetGameModel(SelectedGameModel); + } +} + +void FEEditorInspectorWindow::AddLightComponent(FEEntity* Entity) +{ + Entity->AddComponent(FE_POINT_LIGHT); +} + +void FEEditorInspectorWindow::AddCameraComponent(FEEntity* Entity) +{ + Entity->AddComponent(); +} + +std::vector FEEditorInspectorWindow::GetAvailableComponentsToAdd(FEEntity* Entity) const +{ + std::vector Result; + if (Entity == nullptr) + return Result; + + auto RegisteredComponentList = COMPONENTS_TOOL.GetComponentInfoList(); + for (size_t i = 0; i < RegisteredComponentList.size(); i++) + { + if (RegisteredComponentList[i].CanBeAddedToEntity(Entity)) + Result.push_back(RegisteredComponentList[i].Name); + } + + return Result; +} + +bool FEEditorInspectorWindow::AddComponent(FEEntity* Entity, std::string ComponentName) +{ + auto RegisteredComponentList = COMPONENTS_TOOL.GetComponentInfoList(); + + for (size_t i = 0; i < RegisteredComponentList.size(); i++) + { + if (RegisteredComponentList[i].Name == ComponentName) + { + auto ComponentHashCode = RegisteredComponentList[i].Type->hash_code(); + + auto ComponentIterator = AddComponentHandlers.begin(); + while (ComponentIterator != AddComponentHandlers.end()) + { + if (ComponentIterator->first.hash_code() == ComponentHashCode) + { + ComponentIterator->second(Entity); + return true; + } + + ComponentIterator++; + } + } + } + + return false; +} + +bool FEEditorInspectorWindow::RenderComponentDeleteButton(FEEntity* Entity, FEComponentTypeInfo* ComponentInfo) const +{ + if (!ComponentInfo->CanBeRemovedFromEntity(Entity)) + return false; + + float HeaderHeight = ImGui::GetFrameHeight(); + float HeaderWidth = ImGui::GetContentRegionAvail().x; + + float ButtonSize = 24; + ImVec2 PreviosCursorPos = ImGui::GetCursorPos(); + + ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.9f, 0.5f, 0.5f, 1.0f)); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.95f, 0.90f, 0.0f, 1.0f)); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0.1f, 1.0f, 0.1f, 1.0f)); + ImGui::SetCursorPos(ImVec2(HeaderWidth - ButtonSize / 8.0f - 2.0f, PreviosCursorPos.y + 2.0f)); + if (ImGui::Button(std::string("x##" + ComponentInfo->Name).c_str(), ImVec2(ButtonSize, ButtonSize))) + { + size_t ComponentHashCode = ComponentInfo->Type->hash_code(); + + auto ComponentIterator = RemoveComponentHandlers.begin(); + while (ComponentIterator != RemoveComponentHandlers.end()) + { + if (ComponentIterator->first.hash_code() == ComponentHashCode) + { + ComponentIterator->second(Entity); + + ImGui::PopStyleColor(3); + ImGui::SetCursorPos(PreviosCursorPos); + return true; + } + + ComponentIterator++; + } + } + + ImGui::PopStyleColor(3); + ImGui::SetCursorPos(PreviosCursorPos); + + return false; +} + +void FEEditorInspectorWindow::Render() +{ + if (!bVisible) + return; + + if (EDITOR.GetFocusedScene() == nullptr) + return; + + FEScene* CurrentScene = EDITOR.GetFocusedScene(); + FEEntity* MainCameraEntity = CAMERA_SYSTEM.GetMainCamera(CurrentScene); + if (MainCameraEntity == nullptr) + return; + + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(15, 15)); + ImGui::Begin("Inspector", nullptr, ImGuiWindowFlags_None); + + if (SELECTED.GetSelected(CurrentScene) == nullptr) + { + ImGui::PopStyleVar(); + ImGui::End(); + return; + } + + FEEntity* EntitySelected = SELECTED.GetSelected(CurrentScene); + + ImGui::Text("ID : %s", EntitySelected->GetObjectID().c_str()); + ImGui::Text("Name : %s", EntitySelected->GetName().c_str()); + + if (EntitySelected->HasComponent()) + { + if (RenderComponentDeleteButton(EntitySelected, COMPONENTS_TOOL.GetComponentInfo())) + { + ImGui::PopStyleVar(); + ImGui::End(); + return; + } + + if (ImGui::CollapsingHeader("Tag", ImGuiTreeNodeFlags_DefaultOpen)) + { + FETagComponent& TagComponent = EntitySelected->GetComponent(); + char Buffer[1024]; + memset(Buffer, 0, 1024); + strcpy_s(Buffer, TagComponent.GetTag().c_str()); + if (ImGui::InputText("##Tag Edit", Buffer, 1024)) + { + std::string NewTag = Buffer; + TagComponent.SetTag(NewTag); + } + } + } + + if (EntitySelected->HasComponent()) + { + if (RenderComponentDeleteButton(EntitySelected, COMPONENTS_TOOL.GetComponentInfo())) + { + ImGui::PopStyleVar(); + ImGui::End(); + return; + } + + if (ImGui::CollapsingHeader("Transform", ImGuiTreeNodeFlags_DefaultOpen)) + { + FETransformComponent& Transform = EntitySelected->GetComponent(); + ShowTransformConfiguration(EntitySelected->GetName(), &Transform); + } + } + + if (EntitySelected->HasComponent()) + { + if (RenderComponentDeleteButton(EntitySelected, COMPONENTS_TOOL.GetComponentInfo())) + { + ImGui::PopStyleVar(); + ImGui::End(); + return; + } + + if (ImGui::CollapsingHeader("Game Model", ImGuiTreeNodeFlags_DefaultOpen)) + { + ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor(0.5f, 0.5f, 0.5f)); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::ImColor(0.95f, 0.90f, 0.0f)); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::ImColor(0.1f, 1.0f, 0.1f, 1.0f)); + + FEGameModelComponent& GameModelComponent = EntitySelected->GetComponent(); + bool bActive = GameModelComponent.IsWireframeMode(); + ImGui::Checkbox("WireframeMode", &bActive); + GameModelComponent.SetWireframeMode(bActive); + + ImGui::Text("Game Model : "); + FETexture* PreviewTexture = PREVIEW_MANAGER.GetGameModelPreview(GameModelComponent.GetGameModel()->GetObjectID()); + + if (ImGui::ImageButton((void*)(intptr_t)PreviewTexture->GetTextureID(), ImVec2(128, 128), ImVec2(0.0f, 1.0f), ImVec2(1.0f, 0.0f), 8, ImColor(0.0f, 0.0f, 0.0f, 0.0f), ImColor(1.0f, 1.0f, 1.0f, 1.0f))) + { + EntityToModify = EntitySelected; + FEGameModelComponent& GameModelComponent = EntityToModify->GetComponent(); + SELECT_FEOBJECT_POPUP.Show(FE_GAMEMODEL, ChangeGameModelOfEntityCallBack, GameModelComponent.GetGameModel()); + } + EntityChangeGameModelTarget->StickToItem(); + + bool bOpenContextMenu = false; + if (ImGui::IsItemHovered() && ImGui::IsMouseClicked(1)) + bOpenContextMenu = true; + + if (bOpenContextMenu) + ImGui::OpenPopup("##Inspector_context_menu"); + + CONTENT_BROWSER_WINDOW.bShouldOpenContextMenu = false; + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(15, 15)); + if (ImGui::BeginPopup("##Inspector_context_menu")) + { + CONTENT_BROWSER_WINDOW.bShouldOpenContextMenu = true; + + if (ImGui::MenuItem("Show in folder")) + { + CONTENT_BROWSER_WINDOW.OpenItemParentFolder(GameModelComponent.GetGameModel()); + } + + ImGui::EndPopup(); + } + ImGui::PopStyleVar(); + + ImGui::PopStyleColor(); + ImGui::PopStyleColor(); + ImGui::PopStyleColor(); + } + } + + if (EntitySelected->HasComponent()) + { + if (RenderComponentDeleteButton(EntitySelected, COMPONENTS_TOOL.GetComponentInfo())) + { + ImGui::PopStyleVar(); + ImGui::End(); + return; + } + + if (ImGui::CollapsingHeader("Prefab Instance", ImGuiTreeNodeFlags_DefaultOpen)) + { + ImGui::Text("Prefab ID : %s", EntitySelected->GetComponent().GetPrefab()->GetObjectID().c_str()); + } + } + + if (EntitySelected->HasComponent()) + { + if (RenderComponentDeleteButton(EntitySelected, COMPONENTS_TOOL.GetComponentInfo())) + { + ImGui::PopStyleVar(); + ImGui::End(); + return; + } + + if (ImGui::CollapsingHeader("Instanced", ImGuiTreeNodeFlags_DefaultOpen)) + { + FESelectionData* CurrentSelectionData = SELECTED.GetSceneData(CurrentScene->GetObjectID()); + FEInstancedComponent& InstancedComponent = EntitySelected->GetComponent(); + + if (CurrentSelectionData->InstancedSubObjectIndexSelected != -1) + { + std::string InstancedSubObjectInfo = "index: "; + + ImGui::Text("Selected instance info:"); + InstancedSubObjectInfo = "index: " + std::to_string(CurrentSelectionData->InstancedSubObjectIndexSelected); + ImGui::Text(InstancedSubObjectInfo.c_str()); + + FETransformComponent TempTransform = FETransformComponent(InstancedComponent.GetTransformedInstancedMatrix(CurrentSelectionData->InstancedSubObjectIndexSelected)); + TempTransform.SetSceneIndependent(true); + ShowTransformConfiguration("Selected instance", &TempTransform); + + INSTANCED_RENDERING_SYSTEM.ModifyIndividualInstance(EntitySelected, CurrentSelectionData->InstancedSubObjectIndexSelected, TempTransform.GetWorldMatrix()); + + ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor(0.55f, 0.55f, 0.95f)); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::ImColor(0.75f, 0.75f, 0.95f)); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::ImColor(0.75f, 0.75f, 0.95f)); + + if (ImGui::ImageButton((void*)(intptr_t)ArrowToGroundIcon->GetTextureID(), ImVec2(64, 64), ImVec2(0.0f, 0.0f), ImVec2(1.0f, 1.0f), 8, ImColor(0.0f, 0.0f, 0.0f, 0.0f), ImColor(1.0f, 1.0f, 1.0f, 1.0f))) + { + INSTANCED_RENDERING_SYSTEM.TryToSnapIndividualInstance(EntitySelected, CurrentSelectionData->InstancedSubObjectIndexSelected); + } + ShowToolTip("Selected instance will attempt to snap to the terrain."); + + ImGui::PopStyleColor(); + ImGui::PopStyleColor(); + ImGui::PopStyleColor(); + } + else + { + ImGui::Text("Snapped to: "); + ImGui::SameLine(); + + const std::vector TerrainList = CurrentScene->GetEntityIDListWithComponent(); + static std::string CurrentTerrain = "none"; + + if (InstancedComponent.GetSnappedToTerrain() == nullptr) + { + CurrentTerrain = "none"; + } + else + { + CurrentTerrain = InstancedComponent.GetSnappedToTerrain()->GetName(); + } + + ImGui::SetNextItemWidth(220); + if (ImGui::BeginCombo("##Terrain", CurrentTerrain.c_str(), ImGuiWindowFlags_None)) + { + const bool bIsSelected = (CurrentTerrain == "none"); + if (ImGui::Selectable("none", bIsSelected)) + { + if (InstancedComponent.GetSnappedToTerrain() != nullptr) + { + TERRAIN_SYSTEM.UnSnapInstancedEntity(InstancedComponent.GetSnappedToTerrain(), EntitySelected); + } + } + + if (bIsSelected) + ImGui::SetItemDefaultFocus(); + + for (size_t i = 0; i < TerrainList.size(); i++) + { + const bool bIsSelected = (CurrentTerrain == TerrainList[i]); + if (ImGui::Selectable(CurrentScene->GetEntity(TerrainList[i])->GetName().c_str(), bIsSelected)) + { + TERRAIN_SYSTEM.SnapInstancedEntity(CurrentScene->GetEntity(TerrainList[i]), EntitySelected); + } + + if (bIsSelected) + ImGui::SetItemDefaultFocus(); + } + ImGui::EndCombo(); + } + + if (InstancedComponent.GetSnappedToTerrain() != nullptr) + { + ImGui::Text("Terrain layer: "); + ImGui::SameLine(); + + const int CurrentLayer = InstancedComponent.GetTerrainLayer(); + FEEntity* TerrainEntity = InstancedComponent.GetSnappedToTerrain(); + FETerrainComponent& TerrainComponent = TerrainEntity->GetComponent(); + + std::string Caption = "none"; + FETerrainLayer* Layer = TerrainComponent.GetLayerInSlot(CurrentLayer); + if (Layer != nullptr) + Caption = Layer->GetName(); + + ImGui::SetNextItemWidth(220); + if (ImGui::BeginCombo("##TerrainLayers", Caption.c_str(), ImGuiWindowFlags_None)) + { + const bool bIsSelected = (CurrentLayer == -1); + ImGui::PushID("none_TerrainLayers_entity"); + if (ImGui::Selectable("none", bIsSelected)) + { + TERRAIN_SYSTEM.UnConnectInstancedEntityFromLayer(EntitySelected); + } + ImGui::PopID(); + + if (bIsSelected) + ImGui::SetItemDefaultFocus(); + + for (size_t i = 0; i < FE_TERRAIN_MAX_LAYERS; i++) + { + FETerrainLayer* Layer = TerrainComponent.GetLayerInSlot(i); + if (Layer == nullptr) + break; + + const bool bIsSelected = (CurrentLayer == i); + ImGui::PushID(/*Layer->GetObjectID().c_str()*/static_cast(i)); + if (ImGui::Selectable(Layer->GetName().c_str(), bIsSelected)) + { + TERRAIN_SYSTEM.ConnectInstancedEntityToLayer(TerrainEntity, EntitySelected, static_cast(i)); + } + ImGui::PopID(); + + if (bIsSelected) + ImGui::SetItemDefaultFocus(); + } + ImGui::EndCombo(); + } + + if (CurrentLayer != -1) + { + ImGui::Text("Minimal layer intensity to spawn:"); + float MinLevel = InstancedComponent.GetMinimalLayerIntensityToSpawn(); + ImGui::SameLine(); + ImGui::SetNextItemWidth(80); + ImGui::DragFloat("##minLevel", &MinLevel); + InstancedComponent.SetMinimalLayerIntensityToSpawn(MinLevel); + } + } + + ImGui::Separator(); + + ImGui::Text("Seed:"); + int seed = InstancedComponent.SpawnInfo.Seed; + ImGui::SameLine(); + ImGui::SetNextItemWidth(200); + ImGui::DragInt("##Seed", &seed); + InstancedComponent.SpawnInfo.Seed = seed; + + ImGui::Text("Object count:"); + int ObjectCount = InstancedComponent.SpawnInfo.ObjectCount; + ImGui::SameLine(); + ImGui::SetNextItemWidth(200); + ImGui::DragInt("##Object count", &ObjectCount); + if (ObjectCount <= 0) + ObjectCount = 1; + InstancedComponent.SpawnInfo.ObjectCount = ObjectCount; + + ImGui::Text("Radius:"); + float radius = InstancedComponent.SpawnInfo.Radius; + ImGui::SameLine(); + ImGui::SetNextItemWidth(200); + ImGui::DragFloat("##Radius", &radius); + if (radius < 0.0f) + radius = 0.1f; + InstancedComponent.SpawnInfo.Radius = radius; + + // Scale deviation. + ImGui::Text("Scale: "); + + ImGui::SameLine(); + ImGui::Text("min "); + + ImGui::SameLine(); + ImGui::SetNextItemWidth(100); + float MinScale = InstancedComponent.SpawnInfo.GetMinScale(); + ImGui::DragFloat("##minScale", &MinScale, 0.01f); + InstancedComponent.SpawnInfo.SetMinScale(MinScale); + + ImGui::SameLine(); + ImGui::Text("max "); + + ImGui::SameLine(); + float MaxScale = InstancedComponent.SpawnInfo.GetMaxScale(); + ImGui::SetNextItemWidth(100); + ImGui::DragFloat("##maxScale", &MaxScale, 0.01f); + InstancedComponent.SpawnInfo.SetMaxScale(MaxScale); + + ImGui::Text("Rotation deviation:"); + float RotationDeviationX = InstancedComponent.SpawnInfo.RotationDeviation.x; + ImGui::Text("X:"); + ImGui::SameLine(); + ImGui::DragFloat("##Rotation deviation X", &RotationDeviationX, 0.01f); + if (RotationDeviationX < 0.01f) + RotationDeviationX = 0.01f; + if (RotationDeviationX > 1.0f) + RotationDeviationX = 1.0f; + InstancedComponent.SpawnInfo.RotationDeviation.x = RotationDeviationX; + + float RotationDeviationY = InstancedComponent.SpawnInfo.RotationDeviation.y; + ImGui::Text("Y:"); + ImGui::SameLine(); + ImGui::DragFloat("##Rotation deviation Y", &RotationDeviationY, 0.01f); + if (RotationDeviationY < 0.01f) + RotationDeviationY = 0.01f; + if (RotationDeviationY > 1.0f) + RotationDeviationY = 1.0f; + InstancedComponent.SpawnInfo.RotationDeviation.y = RotationDeviationY; + + float RotationDeviationZ = InstancedComponent.SpawnInfo.RotationDeviation.z; + ImGui::Text("Z:"); + ImGui::SameLine(); + ImGui::DragFloat("##Rotation deviation z", &RotationDeviationZ, 0.01f); + if (RotationDeviationZ < 0.01f) + RotationDeviationZ = 0.01f; + if (RotationDeviationZ > 1.0f) + RotationDeviationZ = 1.0f; + InstancedComponent.SpawnInfo.RotationDeviation.z = RotationDeviationZ; + + if (ImGui::Button("Spawn/Re-Spawn")) + { + INSTANCED_RENDERING_SYSTEM.ClearInstance(EntitySelected); + INSTANCED_RENDERING_SYSTEM.PopulateInstance(EntitySelected, InstancedComponent.SpawnInfo); + } + + if (ImGui::Button("Add instance")) + { + glm::mat4 NewInstanceMatrix = glm::identity(); + FETransformComponent& CameraTransformComponent = MainCameraEntity->GetComponent(); + FECameraComponent& CameraComponent = MainCameraEntity->GetComponent(); + NewInstanceMatrix = glm::translate(NewInstanceMatrix, CameraTransformComponent.GetPosition(FE_WORLD_SPACE) + CameraComponent.GetForward() * 10.0f); + INSTANCED_RENDERING_SYSTEM.AddIndividualInstance(EntitySelected, NewInstanceMatrix); + + PROJECT_MANAGER.GetCurrent()->SetModified(true); + } + + if (INSTANCED_RENDERING_SYSTEM.IsIndividualSelectMode(EntitySelected)) + { + ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor(0.0f, 0.75f, 0.0f)); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::ImColor(0.0f, 1.0f, 0.0f)); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::ImColor(0.0f, 1.0f, 0.0f)); + } + else + { + ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor(0.55f, 0.55f, 0.95f)); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::ImColor(0.75f, 0.75f, 0.95f)); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::ImColor(0.75f, 0.75f, 0.95f)); + } + + ImGui::Separator(); + if (ImGui::ImageButton((void*)(intptr_t)MouseCursorIcon->GetTextureID(), ImVec2(64, 64), ImVec2(0.0f, 0.0f), ImVec2(1.0f, 1.0f), 8, ImColor(0.0f, 0.0f, 0.0f, 0.0f), ImColor(1.0f, 1.0f, 1.0f, 1.0f))) + { + INSTANCED_RENDERING_SYSTEM.SetIndividualSelectMode(EntitySelected, !INSTANCED_RENDERING_SYSTEM.IsIndividualSelectMode(EntitySelected)); + if (!INSTANCED_RENDERING_SYSTEM.IsIndividualSelectMode(EntitySelected)) + { + SELECTED.Clear(CurrentScene); + SELECTED.SetSelected(EntitySelected); + } + } + ShowToolTip("Individual selection mode - Used to select individual instances."); + + ImGui::PopStyleColor(); + ImGui::PopStyleColor(); + ImGui::PopStyleColor(); + } + } + } + + if (EntitySelected->HasComponent()) + { + if (RenderComponentDeleteButton(EntitySelected, COMPONENTS_TOOL.GetComponentInfo())) + { + ImGui::PopStyleVar(); + ImGui::End(); + return; + } + + if (ImGui::CollapsingHeader("Terrain", ImGuiTreeNodeFlags_DefaultOpen)) + { + FETerrainComponent& TerrainComponent = EntitySelected->GetComponent(); + DisplayTerrainSettings(EntitySelected); + + if (TERRAIN_SYSTEM.GetBrushMode() != FE_TERRAIN_BRUSH_NONE) + { + // To hide gizmos. + SELECTED.SetSelected(EntitySelected); + + TERRAIN_SYSTEM.SetBrushActive(bLeftMousePressed); + + if (bShiftPressed) + { + if (TERRAIN_SYSTEM.GetBrushMode() == FE_TERRAIN_BRUSH_SCULPT_DRAW) + TERRAIN_SYSTEM.SetBrushMode(EntitySelected, FE_TERRAIN_BRUSH_SCULPT_DRAW_INVERSED); + } + else + { + if (TERRAIN_SYSTEM.GetBrushMode() == FE_TERRAIN_BRUSH_SCULPT_DRAW_INVERSED) + TERRAIN_SYSTEM.SetBrushMode(EntitySelected, FE_TERRAIN_BRUSH_SCULPT_DRAW); + } + } + else + { + // To show gizmos. + SELECTED.SetSelected(EntitySelected); + } + } + } + + if (EntitySelected->HasComponent()) + { + if (RenderComponentDeleteButton(EntitySelected, COMPONENTS_TOOL.GetComponentInfo())) + { + ImGui::PopStyleVar(); + ImGui::End(); + return; + } + + if (ImGui::CollapsingHeader("Light", ImGuiTreeNodeFlags_DefaultOpen)) + { + DisplayLightProperties(SELECTED.GetSelected(CurrentScene)); + } + } + + if (EntitySelected->HasComponent()) + { + if (RenderComponentDeleteButton(EntitySelected, COMPONENTS_TOOL.GetComponentInfo())) + { + ImGui::PopStyleVar(); + ImGui::End(); + return; + } + + if (ImGui::CollapsingHeader("Camera", ImGuiTreeNodeFlags_DefaultOpen)) + { + DisplayCameraProperties(SELECTED.GetSelected(CurrentScene)); + } + } + + if (EntitySelected->HasComponent()) + { + if (RenderComponentDeleteButton(EntitySelected, COMPONENTS_TOOL.GetComponentInfo())) + { + ImGui::PopStyleVar(); + ImGui::End(); + return; + } + + if (ImGui::CollapsingHeader("Virtual UI", ImGuiTreeNodeFlags_DefaultOpen)) + { + DisplayVirtualUIProperties(SELECTED.GetSelected(CurrentScene)); + } + } + + if (EntitySelected->HasComponent()) + { + if (RenderComponentDeleteButton(EntitySelected, COMPONENTS_TOOL.GetComponentInfo())) + { + ImGui::PopStyleVar(); + ImGui::End(); + return; + } + + if (ImGui::CollapsingHeader("Native Script", ImGuiTreeNodeFlags_DefaultOpen)) + { + DisplayNativeScriptProperties(SELECTED.GetSelected(CurrentScene)); + } + } + + std::vector AvailableComponentTypes = GetAvailableComponentsToAdd(EntitySelected); + + ImGui::SetNextItemWidth(220.0f); + ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 6.0f); + + float RegionWidth = ImGui::GetContentRegionAvail().x; + ImGui::SetCursorPosX(RegionWidth * 0.5f - 220.0f / 2.0f + 20.0f); + + if (ImGui::BeginCombo("##Add Component", " Add Component", ImGuiComboFlags_NoArrowButton)) + { + for (size_t i = 0; i < AvailableComponentTypes.size(); i++) + { + if (ImGui::Selectable(AvailableComponentTypes[i].c_str(), false)) + { + AddComponent(EntitySelected, AvailableComponentTypes[i]); + } + } + ImGui::EndCombo(); + } + + ImGui::PopStyleVar(); + ImGui::End(); +} + +void FEEditorInspectorWindow::CreateNewTerrainLayerWithMaterialCallBack(std::vector SelectionsResult) +{ + if (SelectionsResult.size() == 1 && SelectionsResult[0]->GetType() == FE_MATERIAL) + { + if (TerrainToWorkWith == nullptr) + return; + + FEMaterial* SelectedMaterial = RESOURCE_MANAGER.GetMaterial(SelectionsResult[0]->GetObjectID()); + if (SelectedMaterial == nullptr) + return; + + TERRAIN_SYSTEM.ActivateVacantLayerSlot(TerrainToWorkWith, SelectedMaterial); + } + + TerrainToWorkWith = nullptr; +} + +static size_t TempLayerIndex = -1; +void FEEditorInspectorWindow::ChangeMaterialInTerrainLayerCallBack(std::vector SelectionsResult) +{ + if (SelectionsResult.size() == 1 && SelectionsResult[0]->GetType() == FE_MATERIAL) + { + if (TempLayerIndex == -1) + return; + + FEMaterial* SelectedMaterial = RESOURCE_MANAGER.GetMaterial(SelectionsResult[0]->GetObjectID()); + if (SelectedMaterial == nullptr) + return; + + FETerrainComponent& TerrainComponent = TerrainToWorkWith->GetComponent(); + TerrainComponent.GetLayerInSlot(TempLayerIndex)->SetMaterial(SelectedMaterial); + } + + TerrainToWorkWith = nullptr; + TempLayerIndex = -1; +} + +void FEEditorInspectorWindow::DisplayTerrainSettings(FEEntity* TerrainEntity) +{ + FETerrainComponent& TerrainComponent = TerrainEntity->GetComponent(); + if (TerrainChangeLayerMaterialTargets.size() != TerrainComponent.LayersUsed()) + { + for (size_t i = 0; i < TerrainChangeLayerMaterialTargets.size(); i++) + { + delete TerrainChangeLayerMaterialTargets[i]; + } + + TerrainChangeLayerMaterialTargets.resize(TerrainComponent.LayersUsed()); + TerrainChangeMaterialIndecies.resize(TerrainComponent.LayersUsed()); + for (size_t i = 0; i < size_t(TerrainComponent.LayersUsed()); i++) + { + TerrainChangeMaterialIndecies[i] = int(i); + TerrainChangeLayerMaterialTargets[i] = DRAG_AND_DROP_MANAGER.AddTarget(FE_MATERIAL, TerrainChangeMaterialTargetCallBack, (void**)&TerrainChangeMaterialIndecies[i], "Drop to assing material to " + TerrainComponent.GetLayerInSlot(i)->GetName()); + } + } + + if (ImGui::BeginTabBar("##terrainSettings", ImGuiTabBarFlags_None)) + { + if (ImGui::BeginTabItem("General")) + { + bool bActive = TerrainComponent.IsWireframeMode(); + ImGui::Checkbox("WireframeMode", &bActive); + TerrainComponent.SetWireframeMode(bActive); + + FEShaderUniformValue CurrentValue; + if (RESOURCE_MANAGER.GetShader("0800253C242B05321A332D09"/*"FEPBRShader"*/)->GetUniformData("debugFlag", CurrentValue)) + { + + int IData = CurrentValue.GetValue(); + ImGui::SliderInt("debugFlag", &IData, 0, 10); + RESOURCE_MANAGER.GetShader("0800253C242B05321A332D09"/*"FEPBRShader"*/)->UpdateUniformData("debugFlag", IData); + } + + float DisplacementScale = TerrainComponent.GetDisplacementScale(); + ImGui::DragFloat("displacementScale", &DisplacementScale, 0.02f, -10.0f, 10.0f); + TerrainComponent.SetDisplacementScale(DisplacementScale); + + float LODLevel = TerrainComponent.GetLODLevel(); + ImGui::DragFloat("LODlevel", &LODLevel, 2.0f, 2.0f, 128.0f); + TerrainComponent.SetLODLevel(LODLevel); + ShowToolTip("Bigger LODlevel more details terraine will have and less performance you will get."); + + float ChunkPerSide = TerrainComponent.GetChunkPerSide(); + ImGui::DragFloat("chunkPerSide", &ChunkPerSide, 2.0f, 1.0f, 16.0f); + TerrainComponent.SetChunkPerSide(ChunkPerSide); + + // ********************* REAL WORLD COMPARISON SCALE ********************* + FEAABB RealAABB = TERRAIN_SYSTEM.GetAABB(TerrainEntity); + glm::vec3 min = RealAABB.GetMin(); + glm::vec3 max = RealAABB.GetMax(); + + float XSize = sqrt((max.x - min.x) * (max.x - min.x)); + float YSize = sqrt((max.y - min.y) * (max.y - min.y)); + float ZSize = sqrt((max.z - min.z) * (max.z - min.z)); + + std::string SizeInM = "Approximate terrain size: "; + SizeInM += std::to_string(std::max(XSize, std::max(YSize, ZSize))); + SizeInM += " m"; + ImGui::Text(SizeInM.c_str()); + // ********************* REAL WORLD COMPARISON SCALE END ********************* + + ImGui::EndTabItem(); + } + if (ImGui::BeginTabItem("Sculpt")) + { + ExportHeightMapButton->Render(); + if (ExportHeightMapButton->IsClicked()) + { + std::string FilePath = ""; + FILE_SYSTEM.ShowFileSaveDialog(FilePath, TEXTURE_LOAD_FILTER, 1); + + if (!FilePath.empty()) + { + FilePath += ".png"; + RESOURCE_MANAGER.ExportFETextureToPNG(TerrainComponent.GetHeightMap(), FilePath.c_str()); + } + } + + ImGui::SameLine(); + ImportHeightMapButton->Render(); + if (ImportHeightMapButton->IsClicked()) + { + std::string FilePath; + FILE_SYSTEM.ShowFileOpenDialog(FilePath, TEXTURE_LOAD_FILTER, 1); + + if (!FilePath.empty()) + { + TERRAIN_SYSTEM.LoadHeightMap(FilePath.c_str(), TerrainEntity); + FETexture* LoadedTexture = TerrainComponent.GetHeightMap(); + if (LoadedTexture == RESOURCE_MANAGER.NoTexture) + { + LOG.Add(std::string("can't load height map: ") + FilePath, "FE_LOG_LOADING", FE_LOG_ERROR); + } + else + { + LoadedTexture->SetDirtyFlag(true); + PROJECT_MANAGER.GetCurrent()->SetModified(true); + } + } + } + + float HighScale = TerrainComponent.GetHightScale(); + ImGui::DragFloat("hight range in m", &HighScale); + TerrainComponent.SetHightScale(HighScale); + + float CurrentBrushSize = TERRAIN_SYSTEM.GetBrushSize(); + ImGui::DragFloat("brushSize", &CurrentBrushSize, 0.1f, 0.01f, 100.0f); + TERRAIN_SYSTEM.SetBrushSize(CurrentBrushSize); + + float CurrentBrushIntensity = TERRAIN_SYSTEM.GetBrushIntensity(); + ImGui::DragFloat("brushIntensity", &CurrentBrushIntensity, 0.0001f, 0.0001f, 10.0f); + TERRAIN_SYSTEM.SetBrushIntensity(CurrentBrushIntensity); + + SetDefaultStyle(SculptBrushButton); + if (TERRAIN_SYSTEM.GetBrushMode() == FE_TERRAIN_BRUSH_SCULPT_DRAW || + TERRAIN_SYSTEM.GetBrushMode() == FE_TERRAIN_BRUSH_SCULPT_DRAW_INVERSED) + SetSelectedStyle(SculptBrushButton); + + SculptBrushButton->Render(); + ShowToolTip("Sculpt Brush. Left mouse to increase height, hold shift to decrease height."); + + if (SculptBrushButton->IsClicked()) + { + if (TERRAIN_SYSTEM.GetBrushMode() == FE_TERRAIN_BRUSH_SCULPT_DRAW || + TERRAIN_SYSTEM.GetBrushMode() == FE_TERRAIN_BRUSH_SCULPT_DRAW_INVERSED) + { + TERRAIN_SYSTEM.SetBrushMode(TerrainEntity, FE_TERRAIN_BRUSH_NONE); + } + else + { + TERRAIN_SYSTEM.SetBrushMode(TerrainEntity, FE_TERRAIN_BRUSH_SCULPT_DRAW); + } + } + + SetDefaultStyle(LevelBrushButton); + if (TERRAIN_SYSTEM.GetBrushMode() == FE_TERRAIN_BRUSH_SCULPT_LEVEL) + SetSelectedStyle(LevelBrushButton); + + ImGui::SameLine(); + LevelBrushButton->Render(); + ShowToolTip("Level Brush."); + + if (LevelBrushButton->IsClicked()) + { + if (TERRAIN_SYSTEM.GetBrushMode() == FE_TERRAIN_BRUSH_SCULPT_LEVEL) + { + TERRAIN_SYSTEM.SetBrushMode(TerrainEntity, FE_TERRAIN_BRUSH_NONE); + } + else + { + TERRAIN_SYSTEM.SetBrushMode(TerrainEntity, FE_TERRAIN_BRUSH_SCULPT_LEVEL); + } + } + + SetDefaultStyle(SmoothBrushButton); + if (TERRAIN_SYSTEM.GetBrushMode() == FE_TERRAIN_BRUSH_SCULPT_SMOOTH) + SetSelectedStyle(SmoothBrushButton); + + ImGui::SameLine(); + SmoothBrushButton->Render(); + ShowToolTip("Smooth Brush."); + + if (SmoothBrushButton->IsClicked()) + { + if (TERRAIN_SYSTEM.GetBrushMode() == FE_TERRAIN_BRUSH_SCULPT_SMOOTH) + { + TERRAIN_SYSTEM.SetBrushMode(TerrainEntity, FE_TERRAIN_BRUSH_NONE); + } + else + { + TERRAIN_SYSTEM.SetBrushMode(TerrainEntity, FE_TERRAIN_BRUSH_SCULPT_SMOOTH); + } + } + + ImGui::EndTabItem(); + } + if (ImGui::BeginTabItem("Paint")) + { + glm::vec2 TileMult = TerrainComponent.GetTileMult(); + ImGui::DragFloat2("all layers tile factors", &TileMult[0], 0.1f, 1.0f, 100.0f); + TerrainComponent.SetTileMult(TileMult); + + float CurrentBrushSize = TERRAIN_SYSTEM.GetBrushSize(); + ImGui::DragFloat("brushSize", &CurrentBrushSize, 0.1f, 0.01f, 100.0f); + TERRAIN_SYSTEM.SetBrushSize(CurrentBrushSize); + + float CurrentBrushIntensity = TERRAIN_SYSTEM.GetBrushIntensity(); + ImGui::DragFloat("brushIntensity", &CurrentBrushIntensity, 0.0001f, 0.0001f, 10.0f); + TERRAIN_SYSTEM.SetBrushIntensity(CurrentBrushIntensity); + + SetDefaultStyle(LayerBrushButton); + if (TERRAIN_SYSTEM.GetBrushMode() == FE_TERRAIN_BRUSH_LAYER_DRAW) + SetSelectedStyle(LayerBrushButton); + + LayerBrushButton->Render(); + ShowToolTip("Layer draw brush. Left mouse to paint currently selected layer, hold shift to decrease layer influence."); + static int SelectedLayer = -1; + if (SelectedLayer != -1 && TerrainComponent.GetLayerInSlot(SelectedLayer) == nullptr) + SelectedLayer = -1; + + if (LayerBrushButton->IsClicked()) + { + if (SelectedLayer != -1) + { + if (TERRAIN_SYSTEM.GetBrushMode() == FE_TERRAIN_BRUSH_LAYER_DRAW) + { + TERRAIN_SYSTEM.SetBrushMode(TerrainEntity, FE_TERRAIN_BRUSH_NONE); + } + else + { + TERRAIN_SYSTEM.SetBrushMode(TerrainEntity, FE_TERRAIN_BRUSH_LAYER_DRAW); + } + } + + } + + ImGui::PushFont(ImGui::GetIO().Fonts->Fonts[1]); + static bool bContextMenuOpened = false; + + ImGui::Text("Layers:"); + + ImGui::BeginChildFrame(ImGui::GetID("Layers ListBox Child"), ImVec2(ImGui::GetContentRegionAvail().x - 10.0f, 500.0f), ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse); + bool bListBoxHovered = false; + if (ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows)) + bListBoxHovered = true; + + static bool bShouldOpenContextMenu = false; + if (ImGui::IsMouseClicked(1)) + { + if (bListBoxHovered) + { + bShouldOpenContextMenu = true; + } + } + + ImGui::BeginListBox("##Layers ListBox", ImVec2(ImGui::GetContentRegionAvail().x - 10.0f, 500.0f)); + + for (size_t i = 0; i < FE_TERRAIN_MAX_LAYERS; i++) + { + FETerrainLayer* Layer = TerrainComponent.GetLayerInSlot(i); + if (Layer == nullptr) + break; + + ImVec2 PostionBeforeDraw = ImGui::GetCursorPos(); + + ImVec2 TextSize = ImGui::CalcTextSize(Layer->GetName().c_str()); + ImGui::SetCursorPos(PostionBeforeDraw + ImVec2(ImGui::GetContentRegionAvail().x / 2.0f - TextSize.x / 2.0f, 16)); + + if (TerrainLayerRenameIndex == i) + { + if (!bLastFrameTerrainLayerRenameEditWasVisiable) + { + ImGui::SetKeyboardFocusHere(0); + ImGui::SetFocusID(ImGui::GetID("##newNameTerrainLayerEditor"), FE_IMGUI_WINDOW_MANAGER.GetCurrentWindowImpl()); + ImGui::SetItemDefaultFocus(); + bLastFrameTerrainLayerRenameEditWasVisiable = true; + } + + ImGui::SetNextItemWidth(350.0f); + ImGui::SetCursorPos(ImVec2(PostionBeforeDraw.x + 64.0f + (ImGui::GetContentRegionAvail().x - 64.0f) / 2.0f - 350.0f / 2.0f, PostionBeforeDraw.y + 12)); + if (ImGui::InputText("##newNameTerrainLayerEditor", TerrainLayerRename, IM_ARRAYSIZE(TerrainLayerRename), ImGuiInputTextFlags_EnterReturnsTrue) || + ImGui::IsMouseClicked(0) && !ImGui::IsItemHovered() || ImGui::IsItemFocused()/*FE_IMGUI_WINDOW_MANAGER.GetCurrentFocusID() != ImGui::GetID("##newNameTerrainLayerEditor")*/) + { + PROJECT_MANAGER.GetCurrent()->SetModified(true); + Layer->SetName(TerrainLayerRename); + + TerrainLayerRenameIndex = -1; + } + } + else + { + ImGui::Text(Layer->GetName().c_str()); + } + ImGui::SetCursorPos(PostionBeforeDraw); + + ImGui::PushID(int(i)); + if (ImGui::Selectable("##item", SelectedLayer == i ? true : false, ImGuiSelectableFlags_None, ImVec2(ImGui::GetContentRegionAvail().x - 0, 64))) + { + SelectedLayer = int(i); + TERRAIN_SYSTEM.SetBrushLayerIndex(SelectedLayer); + } + TerrainChangeLayerMaterialTargets[i]->StickToItem(); + ImGui::PopID(); + + if (ImGui::IsItemHovered()) + HoveredTerrainLayerItem = int(i); + + ImGui::SetCursorPos(PostionBeforeDraw); + ImColor ImageTint = ImGui::IsItemHovered() ? ImColor(1.0f, 1.0f, 1.0f, 0.5f) : ImColor(1.0f, 1.0f, 1.0f, 1.0f); + FETexture* PreviewTexture = PREVIEW_MANAGER.GetMaterialPreview(Layer->GetMaterial()->GetObjectID()); + ImGui::Image((void*)(intptr_t)PreviewTexture->GetTextureID(), ImVec2(64, 64), ImVec2(0.0f, 0.0f), ImVec2(1.0f, 1.0f), ImageTint); + } + + ImGui::EndListBox(); + ImGui::PopFont(); + + ImGui::EndChildFrame(); + ImGui::EndTabItem(); + + if (bShouldOpenContextMenu) + { + bShouldOpenContextMenu = false; + ImGui::OpenPopup("##layers_listBox_context_menu"); + } + + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(15, 15)); + if (ImGui::BeginPopup("##layers_listBox_context_menu")) + { + bContextMenuOpened = true; + + if (TerrainComponent.GetLayerInSlot(FE_TERRAIN_MAX_LAYERS - 1) != nullptr) + ImGui::BeginDisabled(); + + if (ImGui::MenuItem("Add layer...")) + { + std::vector TempMaterialList = RESOURCE_MANAGER.GetMaterialIDList(); + std::vector FinalMaterialList; + for (size_t i = 0; i < TempMaterialList.size(); i++) + { + if (RESOURCE_MANAGER.GetMaterial(TempMaterialList[i])->IsCompackPacking()) + { + FinalMaterialList.push_back(RESOURCE_MANAGER.GetMaterial(TempMaterialList[i])); + } + } + + if (FinalMaterialList.empty()) + { + MessagePopUp::GetInstance().Show("No suitable material", "There are no materials with compack packing."); + } + else + { + TerrainToWorkWith = TerrainEntity; + SELECT_FEOBJECT_POPUP.Show(FE_MATERIAL, CreateNewTerrainLayerWithMaterialCallBack, nullptr, FinalMaterialList); + } + } + + if (TerrainComponent.GetLayerInSlot(FE_TERRAIN_MAX_LAYERS - 1) != nullptr) + ImGui::EndDisabled(); + + if (HoveredTerrainLayerItem != -1) + { + FETerrainLayer* Layer = TerrainComponent.GetLayerInSlot(HoveredTerrainLayerItem); + if (Layer != nullptr) + { + ImGui::Separator(); + std::string LayerName = Layer->GetName(); + ImGui::Text((std::string("Actions with ") + LayerName).c_str()); + ImGui::Separator(); + + if (ImGui::MenuItem("Rename")) + { + TerrainLayerRenameIndex = HoveredTerrainLayerItem; + + strcpy_s(TerrainLayerRename, Layer->GetName().size() + 1, Layer->GetName().c_str()); + bLastFrameTerrainLayerRenameEditWasVisiable = false; + } + + if (ImGui::MenuItem("Fill")) + { + TERRAIN_SYSTEM.FillTerrainLayerMask(TerrainEntity, HoveredTerrainLayerItem); + } + + if (ImGui::MenuItem("Clear")) + { + TERRAIN_SYSTEM.ClearTerrainLayerMask(TerrainEntity, HoveredTerrainLayerItem); + } + + if (ImGui::MenuItem("Delete")) + { + TERRAIN_SYSTEM.DeleteTerrainLayerMask(TerrainEntity, HoveredTerrainLayerItem); + } + + ImGui::Separator(); + + if (ImGui::MenuItem("Change material...")) + { + std::vector TempMaterialList = RESOURCE_MANAGER.GetMaterialIDList(); + std::vector FinalMaterialList; + for (size_t i = 0; i < TempMaterialList.size(); i++) + { + if (RESOURCE_MANAGER.GetMaterial(TempMaterialList[i])->IsCompackPacking()) + { + FinalMaterialList.push_back(RESOURCE_MANAGER.GetMaterial(TempMaterialList[i])); + } + } + + if (FinalMaterialList.empty()) + { + MessagePopUp::GetInstance().Show("No suitable material", "There are no materials with compack packing."); + } + else + { + TerrainToWorkWith = TerrainEntity; + TempLayerIndex = HoveredTerrainLayerItem; + SELECT_FEOBJECT_POPUP.Show(FE_MATERIAL, ChangeMaterialInTerrainLayerCallBack, TerrainComponent.GetLayerInSlot(HoveredTerrainLayerItem)->GetMaterial(), FinalMaterialList); + } + } + + if (ImGui::MenuItem("Export mask...")) + { + std::string FilePath = ""; + FILE_SYSTEM.ShowFileSaveDialog(FilePath, TEXTURE_LOAD_FILTER, 1); + if (!FilePath.empty()) + { + FilePath += ".png"; + TERRAIN_SYSTEM.SaveTerrainLayerMask(TerrainEntity, FilePath, HoveredTerrainLayerItem); + } + } + + if (ImGui::MenuItem("Import mask...")) + { + std::string FilePath = ""; + FILE_SYSTEM.ShowFileOpenDialog(FilePath, TEXTURE_LOAD_FILTER, 1); + if (!FilePath.empty()) + { + TERRAIN_SYSTEM.LoadTerrainLayerMask(TerrainEntity, FilePath, HoveredTerrainLayerItem); + PROJECT_MANAGER.GetCurrent()->SetModified(true); + } + } + } + } + + ImGui::EndPopup(); + } + ImGui::PopStyleVar(); + + if (!bContextMenuOpened) + HoveredTerrainLayerItem = -1; + + bContextMenuOpened = false; + } + ImGui::EndTabBar(); + } +} + +void FEEditorInspectorWindow::AddVirtualUIComponent(FEEntity* Entity) +{ + Entity->AddComponent(); + FEVirtualUIComponent& VirtualUIComponent = Entity->GetComponent(); + VirtualUIComponent.SetWindowToListen(APPLICATION.GetMainWindow()); +} + +void FEEditorInspectorWindow::DisplayVirtualUIProperties(FEEntity* VirtualUIEntity) const +{ + FEVirtualUIComponent& VirtualUIComponent = VirtualUIEntity->GetComponent(); + + // TO-DO: Give user ability to change window. + FEWindow* CurrentWindow = VirtualUIComponent.GetWindowToListen(); + + // TO-DO: Give user ability to change canvas mesh. + FEMesh* CurrentCanvasMesh = VirtualUIComponent.GetCanvasMesh(); + + // Internal resolution. + ImGui::Text("Internal Resolution:"); + glm::vec2 InternalResolution = VirtualUIComponent.GetCanvasResolution(); + ImGui::DragFloat2("##InternalResolution", &InternalResolution[0], 1.0f, 1.0f, 4096.0f); + VirtualUIComponent.SetCanvasResolution(InternalResolution); + + bool bActive = VirtualUIComponent.IsInputActive(); + ImGui::Checkbox("Input Active", &bActive); + VirtualUIComponent.SetInputActive(bActive); + + bool bMouseButtonPassThrough = VirtualUIComponent.IsMouseButtonPassThroughActive(); + ImGui::Checkbox("Mouse Button Pass Through", &bMouseButtonPassThrough); + VirtualUIComponent.SetMouseButtonPassThrough(bMouseButtonPassThrough); + + bool bMouseMovePassThrough = VirtualUIComponent.IsMouseMovePassThroughActive(); + ImGui::Checkbox("Mouse Move Pass Through", &bMouseMovePassThrough); + VirtualUIComponent.SetMouseMovePassThrough(bMouseMovePassThrough); + + bool bMouseScrollPassThrough = VirtualUIComponent.IsScrollPassThroughActive(); + ImGui::Checkbox("Mouse Scroll Pass Through", &bMouseScrollPassThrough); + VirtualUIComponent.SetScrollPassThrough(bMouseScrollPassThrough); + + bool bCharPassThrough = VirtualUIComponent.IsCharPassThroughActive(); + ImGui::Checkbox("Char Pass Through", &bCharPassThrough); + VirtualUIComponent.SetCharPassThrough(bCharPassThrough); + + bool bKeyboardPassThrough = VirtualUIComponent.IsKeyPassThroughActive(); + ImGui::Checkbox("Key Pass Through", &bKeyboardPassThrough); + VirtualUIComponent.SetKeyPassThrough(bKeyboardPassThrough); + + bool bDropPassThrough = VirtualUIComponent.IsDropPassThroughActive(); + ImGui::Checkbox("Drop Pass Through", &bDropPassThrough); + VirtualUIComponent.SetDropPassThrough(bDropPassThrough); +} + +void FEEditorInspectorWindow::AddGameModelComponent(FEEntity* Entity) +{ + INSPECTOR_WINDOW.EntityToWorkWith = Entity; + SELECT_FEOBJECT_POPUP.Show(FE_GAMEMODEL, AddNewGameModelComponentCallBack); +} + +void FEEditorInspectorWindow::AddNewGameModelComponentCallBack(const std::vector SelectionsResult) +{ + if (!SelectionsResult.empty() && SelectionsResult[0]->GetType() == FE_GAMEMODEL) + { + FEGameModel* SelectedGameModel = RESOURCE_MANAGER.GetGameModel(SelectionsResult[0]->GetObjectID()); + if (SelectedGameModel == nullptr) + { + LOG.Add("Can't add game model component. Game model is not loaded.", "FE_LOG_LOADING", FE_LOG_ERROR); + return; + } + + if (INSPECTOR_WINDOW.EntityToWorkWith == nullptr) + { + LOG.Add("Can't add game model component. No entity selected.", "FE_LOG_LOADING", FE_LOG_ERROR); + return; + } + + INSPECTOR_WINDOW.EntityToWorkWith->AddComponent(SelectedGameModel); + + PROJECT_MANAGER.GetCurrent()->SetModified(true); + } +} + +void FEEditorInspectorWindow::AddTerrainComponent(FEEntity* Entity) +{ + Entity->AddComponent(); + TERRAIN_SYSTEM.SetHeightMap(RESOURCE_MANAGER.CreateBlankHightMapTexture(1024, 1024), Entity); +} + +void FEEditorInspectorWindow::AddInstancedComponent(FEEntity* Entity) +{ + Entity->AddComponent(); +} + +void FEEditorInspectorWindow::AddNativeScriptComponent(FEEntity* Entity) +{ + Entity->AddComponent(); +} + +// TO-DO: Make it more general with more templated magic. +template +void HandleScriptVariable(FENativeScriptComponent& Component, const std::string VariableName) +{ + T Value; + if (Component.GetVariableValue(VariableName, Value)) + { + if constexpr (std::is_same_v || std::is_same_v) + { + if (ImGui::InputScalar(VariableName.c_str(), ImGuiDataType_Float, &Value)) + Component.SetVariableValue(VariableName, Value); + } + else if constexpr (std::is_same_v) + { + if (ImGui::InputInt(VariableName.c_str(), &Value)) + Component.SetVariableValue(VariableName, Value); + } + else if constexpr (std::is_same_v) + { + if (ImGui::Checkbox(VariableName.c_str(), &Value)) + Component.SetVariableValue(VariableName, Value); + } + else if constexpr (std::is_same_v) + { + char Buffer[1024]; + strcpy_s(Buffer, sizeof(Buffer), Value.c_str()); + if (ImGui::InputText(VariableName.c_str(), Buffer, sizeof(Buffer))) + { + Value = Buffer; + Component.SetVariableValue(VariableName, Value); + } + } + else if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + int VectorCardinality = std::is_same_v ? 2 : std::is_same_v ? 3 : 4; + if (ImGui::InputScalarN(VariableName.c_str(), ImGuiDataType_Float, glm::value_ptr(Value), VectorCardinality)) + Component.SetVariableValue(VariableName, Value); + } + else if constexpr (std::is_same_v) + { + std::string PrefabName = ""; + if (Value != nullptr) + PrefabName = Value->GetName(); + if (ImGui::BeginCombo(VariableName.c_str(), PrefabName.c_str())) + { + std::vector PrefabIDList = RESOURCE_MANAGER.GetPrefabIDList(); + for (size_t i = 0; i < PrefabIDList.size(); i++) + { + FEPrefab* CurrentPrefab = RESOURCE_MANAGER.GetPrefab(PrefabIDList[i]); + bool bIsSelected = PrefabName == CurrentPrefab->GetName(); + if (ImGui::Selectable(CurrentPrefab->GetName().c_str(), bIsSelected)) + { + Value = RESOURCE_MANAGER.GetPrefab(PrefabIDList[i]); + Component.SetVariableValue(VariableName, Value); + } + + if (bIsSelected) + ImGui::SetItemDefaultFocus(); + } + + ImGui::EndCombo(); + } + } + } +} + +// TO-DO: Make it more general with more templated magic. +template +void HandleScriptArrayVariable(FENativeScriptComponent& Component, const std::string VariableName) +{ + std::vector Value; + if (Component.GetVariableValue(VariableName, Value)) + { + for (size_t i = 0; i < Value.size(); i++) + { + ImGui::Text((VariableName + "[" + std::to_string(i) + "]").c_str()); + ImGui::SameLine(); + + std::string ElementName = "##" + VariableName + "[" + std::to_string(i) + "]"; + if constexpr (std::is_same_v || std::is_same_v) + { + if (ImGui::InputScalar(ElementName.c_str(), ImGuiDataType_Float, &Value[i])) + Component.SetVariableValue(VariableName, Value); + } + else if constexpr (std::is_same_v) + { + if (ImGui::InputInt(ElementName.c_str(), &Value[i])) + Component.SetVariableValue(VariableName, Value); + } + else if constexpr (std::is_same_v) + { + // std::vector is a special case. + bool bTemporaryValue = Value[i]; + if (ImGui::Checkbox(ElementName.c_str(), &bTemporaryValue)) + { + Value[i] = bTemporaryValue; + Component.SetVariableValue(VariableName, Value); + } + } + else if constexpr (std::is_same_v) + { + char Buffer[1024]; + strcpy_s(Buffer, sizeof(Buffer), Value[i].c_str()); + if (ImGui::InputText(ElementName.c_str(), Buffer, sizeof(Buffer))) + { + Value[i] = Buffer; + Component.SetVariableValue(VariableName, Value); + } + } + else if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + { + int VectorCardinality = std::is_same_v ? 2 : std::is_same_v ? 3 : 4; + if (ImGui::InputScalarN(ElementName.c_str(), ImGuiDataType_Float, glm::value_ptr(Value[i]), VectorCardinality)) + Component.SetVariableValue(VariableName, Value); + } + else if constexpr (std::is_same_v) + { + std::string PrefabName = ""; + if (Value[i] != nullptr) + PrefabName = Value[i]->GetName(); + if (ImGui::BeginCombo((VariableName + "[" + std::to_string(i) + "]").c_str(), PrefabName.c_str())) + { + std::vector PrefabIDList = RESOURCE_MANAGER.GetPrefabIDList(); + for (size_t j = 0; j < PrefabIDList.size(); j++) + { + FEPrefab* CurrentPrefab = RESOURCE_MANAGER.GetPrefab(PrefabIDList[j]); + bool bIsSelected = PrefabName == CurrentPrefab->GetName(); + if (ImGui::Selectable(CurrentPrefab->GetName().c_str(), bIsSelected)) + { + Value[i] = RESOURCE_MANAGER.GetPrefab(PrefabIDList[j]); + Component.SetVariableValue(VariableName, Value); + } + + if (bIsSelected) + ImGui::SetItemDefaultFocus(); + } + + ImGui::EndCombo(); + } + } + } + + if (ImGui::Button(("Add##" + VariableName).c_str())) + { + Value.push_back(T()); + Component.SetVariableValue(VariableName, Value); + } + } +} + +void FEEditorInspectorWindow::DisplayNativeScriptProperties(FEEntity* NativeScriptEntity) const +{ + FENativeScriptComponent& NativeScriptComponent = NativeScriptEntity->GetComponent(); + + if (!NativeScriptComponent.IsInitialized()) + { + if (NativeScriptComponent.IsFailedToLoad()) + { + ImGui::Text("Script failed to load."); + FENativeScriptFailedToLoadData* FailedToLoadData = NativeScriptComponent.GetFailedToLoadData(); + ImGui::Text(("Module ID: " + FailedToLoadData->GetModuleID()).c_str()); + // And show raw data in multiline text box. + Json::Value Data = FailedToLoadData->GetRawData(); + std::string RawData = Data.toStyledString(); + + static char buffer[10240] = {}; + + strncpy_s(buffer, RawData.c_str(), sizeof(buffer) - 1); + + ImGui::InputTextMultiline("##FailedToLoadData", buffer, sizeof(buffer), ImVec2(500, 500), ImGuiInputTextFlags_ReadOnly); + + } + else + { + std::vector ModuleList = NATIVE_SCRIPT_SYSTEM.GetActiveModuleIDList(); + + for (size_t i = 0; i < ModuleList.size(); i++) + { + ImGui::Text(("Module ID: " + ModuleList[i]).c_str()); + + ImGui::Text("Script list: "); + std::vector ScriptList = NATIVE_SCRIPT_SYSTEM.GetActiveModuleScriptNameList(ModuleList[i]); + for (size_t j = 0; j < ScriptList.size(); j++) + { + ImGui::Text(ScriptList[j].c_str()); + ImGui::SameLine(); + if (ImGui::Button(("Add##" + ModuleList[i] + "_" + ScriptList[j]).c_str())) + { + NATIVE_SCRIPT_SYSTEM.InitializeScriptComponent(NativeScriptEntity, ModuleList[i], ScriptList[j]); + } + } + } + } + } + else + { + std::string ModuleID = NativeScriptComponent.GetModuleID(); + const FEScriptData* ScriptData = NativeScriptComponent.GetScriptData(); + + // Showing general information. + ImGui::Text(("Module: " + ModuleID).c_str()); + ImGui::Text(("Script name: " + ScriptData->Name).c_str()); + ImGui::Text((std::string("Run in editor: ") + std::string(ScriptData->bRunInEditor ? "Yes" : "No")).c_str()); + + // Showing script variables. + std::unordered_map VariablesRegistry = ScriptData->VariablesRegistry; + auto VariablesIterator = VariablesRegistry.begin(); + while (VariablesIterator != VariablesRegistry.end()) + { + std::string VariableName = VariablesIterator->first; + std::string VariableType = VariablesIterator->second.Type; + + // TO-DO: Make it more general with more templated magic. + if (VariableType.find("vector<") != std::string::npos || VariableType.find("std::vector<") != std::string::npos) + { + if (VariableType.find("float>") != std::string::npos) HandleScriptArrayVariable(NativeScriptComponent, VariableName); + else if (VariableType.find("int>") != std::string::npos) HandleScriptArrayVariable(NativeScriptComponent, VariableName); + else if (VariableType.find("bool>") != std::string::npos) HandleScriptArrayVariable(NativeScriptComponent, VariableName); + else if (VariableType.find("std::string>") != std::string::npos) HandleScriptArrayVariable(NativeScriptComponent, VariableName); + else if (VariableType.find("glm::vec2>") != std::string::npos) HandleScriptArrayVariable(NativeScriptComponent, VariableName); + else if (VariableType.find("glm::vec3>") != std::string::npos) HandleScriptArrayVariable(NativeScriptComponent, VariableName); + else if (VariableType.find("glm::vec4>") != std::string::npos) HandleScriptArrayVariable(NativeScriptComponent, VariableName); + else if (VariableType.find("FEShader*>") != std::string::npos) HandleScriptArrayVariable(NativeScriptComponent, VariableName); + else if (VariableType.find("FEMesh*>") != std::string::npos) HandleScriptArrayVariable(NativeScriptComponent, VariableName); + else if (VariableType.find("FETexture*>") != std::string::npos) HandleScriptArrayVariable(NativeScriptComponent, VariableName); + else if (VariableType.find("FEMaterial*>") != std::string::npos) HandleScriptArrayVariable(NativeScriptComponent, VariableName); + else if (VariableType.find("FEGameModel*>") != std::string::npos) HandleScriptArrayVariable(NativeScriptComponent, VariableName); + // TO-DO: Think how to make it work with enitity. Right now it is not consistent between editor and game mode scenes. + //else if (VariableType.find("FEEntity*>") != std::string::npos) HandleScriptArrayVariable(NativeScriptComponent, VariableName); + else if (VariableType.find("FEFramebuffer*>") != std::string::npos) HandleScriptArrayVariable(NativeScriptComponent, VariableName); + else if (VariableType.find("FEPostProcess*>") != std::string::npos) HandleScriptArrayVariable(NativeScriptComponent, VariableName); + else if (VariableType.find("FEPrefab*>") != std::string::npos) HandleScriptArrayVariable(NativeScriptComponent, VariableName); + // TO-DO: Check if it is working. + else if (VariableType.find("FEScene*>") != std::string::npos) HandleScriptArrayVariable(NativeScriptComponent, VariableName); + else if (VariableType.find("FEAssetPackage*>") != std::string::npos) HandleScriptArrayVariable(NativeScriptComponent, VariableName); + else if (VariableType.find("FENativeScriptModule*>") != std::string::npos) HandleScriptArrayVariable(NativeScriptComponent, VariableName); + } + else + { + if (VariableType == "float") HandleScriptVariable(NativeScriptComponent, VariableName); + else if (VariableType == "int") HandleScriptVariable(NativeScriptComponent, VariableName); + else if (VariableType == "bool") HandleScriptVariable(NativeScriptComponent, VariableName); + else if (VariableType == "std::string") HandleScriptVariable(NativeScriptComponent, VariableName); + else if (VariableType == "glm::vec2") HandleScriptVariable(NativeScriptComponent, VariableName); + else if (VariableType == "glm::vec3") HandleScriptVariable(NativeScriptComponent, VariableName); + else if (VariableType == "glm::vec4") HandleScriptVariable(NativeScriptComponent, VariableName); + else if (VariableType == "FEShader*") HandleScriptVariable(NativeScriptComponent, VariableName); + else if (VariableType == "FEMesh*") HandleScriptVariable(NativeScriptComponent, VariableName); + else if (VariableType == "FETexture*") HandleScriptVariable(NativeScriptComponent, VariableName); + else if (VariableType == "FEMaterial*") HandleScriptVariable(NativeScriptComponent, VariableName); + else if (VariableType == "FEGameModel*") HandleScriptVariable(NativeScriptComponent, VariableName); + // TO-DO: Think how to make it work with enitity. Right now it is not consistent between editor and game mode scenes. + //else if (VariableType == "FEEntity*") HandleScriptVariable(NativeScriptComponent, VariableName); + else if (VariableType == "FEFramebuffer*") HandleScriptVariable(NativeScriptComponent, VariableName); + else if (VariableType == "FEPostProcess*") HandleScriptVariable(NativeScriptComponent, VariableName); + else if (VariableType == "FEPrefab*") HandleScriptVariable(NativeScriptComponent, VariableName); + // TO-DO: Check if it is working. + else if (VariableType == "FEScene*") HandleScriptVariable(NativeScriptComponent, VariableName); + else if (VariableType == "FEAssetPackage*") HandleScriptVariable(NativeScriptComponent, VariableName); + else if (VariableType == "FENativeScriptModule*") HandleScriptVariable(NativeScriptComponent, VariableName); + } + + VariablesIterator++; + } + } +} \ No newline at end of file diff --git a/EditorWindows/InspectorWindow.h b/EditorWindows/InspectorWindow.h new file mode 100644 index 0000000..594a177 --- /dev/null +++ b/EditorWindows/InspectorWindow.h @@ -0,0 +1,87 @@ +#pragma once + +#include "ContentBrowserWindow.h" +#include "../FEEditorScriptingSystem.h" +#include "../FEProjectBuildSystem.h" + +class FEEditorInspectorWindow +{ + friend class FEEditorSceneGraphWindow; + friend class FEEditor; + SINGLETON_PRIVATE_PART(FEEditorInspectorWindow) + + // Visibility + bool bVisible = true; + static FEEntity* EntityToModify; + + void DisplayLightProperties(FEEntity* LightEntity) const; + void DisplayCameraProperties(FEEntity* CameraEntity) const; + void DisplayVirtualUIProperties(FEEntity* VirtualUIEntity) const; + void DisplayNativeScriptProperties(FEEntity* NativeScriptEntity) const; + + // Terrain settings + static FEEntity* TerrainToWorkWith; + static void CreateNewTerrainLayerWithMaterialCallBack(std::vector SelectionsResult); + static void ChangeMaterialInTerrainLayerCallBack(std::vector SelectionsResult); + ImGuiButton* ExportHeightMapButton = nullptr; + ImGuiButton* ImportHeightMapButton = nullptr; + ImGuiImageButton* SculptBrushButton = nullptr; + ImGuiImageButton* LevelBrushButton = nullptr; + ImGuiImageButton* SmoothBrushButton = nullptr; + ImGuiImageButton* LayerBrushButton = nullptr; + static bool EntityChangeGameModelTargetCallBack(FEObject* Object, void** EntityPointer); + static bool TerrainChangeMaterialTargetCallBack(FEObject* Object, void** LayerIndex); + static void ChangeGameModelOfEntityCallBack(std::vector SelectionsResult); + DragAndDropTarget* EntityChangeGameModelTarget = nullptr; + std::vector TerrainChangeMaterialIndecies; + std::vector TerrainChangeLayerMaterialTargets; + int HoveredTerrainLayerItem = -1; + void DisplayTerrainSettings(FEEntity* TerrainEntity); + int TerrainLayerRenameIndex = -1; + char TerrainLayerRename[1024]; + bool bLastFrameTerrainLayerRenameEditWasVisiable = false; + + // Brush icons + FETexture* SculptBrushIcon = nullptr; + FETexture* LevelBrushIcon = nullptr; + FETexture* SmoothBrushIcon = nullptr; + FETexture* MouseCursorIcon = nullptr; + FETexture* ArrowToGroundIcon = nullptr; + FETexture* DrawBrushIcon = nullptr; + + // Context menu + bool bShouldOpenContextMenu = false; + + bool bLeftMousePressed = false; + bool bShiftPressed = false; + + void ShowTransformConfiguration(FEObject* Object, FETransformComponent* Transform) const; + void ShowTransformConfiguration(std::string Name, FETransformComponent* Transform) const; + + // Rendering and initialization + void Render(); + void Clear(); + void InitializeResources(); + + std::vector GetAvailableComponentsToAdd(FEEntity* Entity) const; + + bool AddComponent(FEEntity* Entity, std::string ComponentName); + std::unordered_map> AddComponentHandlers; + std::unordered_map> RemoveComponentHandlers; + + bool RenderComponentDeleteButton(FEEntity* Entity, FEComponentTypeInfo* ComponentInfo) const; + + FEEntity* EntityToWorkWith = nullptr; + static void AddLightComponent(FEEntity* Entity); + static void AddCameraComponent(FEEntity* Entity); + static void AddGameModelComponent(FEEntity* Entity); + static void AddNewGameModelComponentCallBack(const std::vector SelectionsResult); + static void AddTerrainComponent(FEEntity* Entity); + static void AddInstancedComponent(FEEntity* Entity); + static void AddVirtualUIComponent(FEEntity* Entity); + static void AddNativeScriptComponent(FEEntity* Entity); +public: + SINGLETON_PUBLIC_PART(FEEditorInspectorWindow) +}; + +#define INSPECTOR_WINDOW FEEditorInspectorWindow::GetInstance() \ No newline at end of file diff --git a/EditorWindows/LogWindow.cpp b/EditorWindows/LogWindow.cpp new file mode 100644 index 0000000..5b9d795 --- /dev/null +++ b/EditorWindows/LogWindow.cpp @@ -0,0 +1,116 @@ +#include "../FEEditor.h" + +void FEEditor::DisplayLogWindow() const +{ + if (!bLogWindowVisible) + return; + + const auto TopicList = LOG.GetTopicList(); + + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(15, 15)); + ImGui::Begin("Log", nullptr, ImGuiWindowFlags_None); + + static std::string SelectedChannel = "FE_LOG_GENERAL"; + ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 3); + ImGui::Text("Channel:"); + ImGui::SameLine(); + ImGui::SetCursorPosY(ImGui::GetCursorPosY() - 5); + ImGui::SetNextItemWidth(200); + if (ImGui::BeginCombo("##Channel", (SelectedChannel.empty() ? "ALL" : SelectedChannel).c_str(), ImGuiWindowFlags_None)) + { + for (int i = -1; i < int(TopicList.size()); i++) + { + ImGui::PushID(i); + + if (i == -1) + { + const bool bIsSelected = (SelectedChannel.empty()); + + if (ImGui::Selectable("ALL", bIsSelected)) + { + SelectedChannel = ""; + } + + if (bIsSelected) + ImGui::SetItemDefaultFocus(); + } + else + { + const bool bIsSelected = (SelectedChannel == TopicList[i]); + if (ImGui::Selectable(TopicList[i].c_str(), bIsSelected)) + { + SelectedChannel = TopicList[i]; + } + + if (bIsSelected) + ImGui::SetItemDefaultFocus(); + } + + ImGui::PopID(); + } + ImGui::EndCombo(); + } + + std::string LogMessages; + std::vector LogItems; + + if (SelectedChannel.empty()) + { + std::vector TempItems; + for (int i = 0; i < int(TopicList.size()); i++) + { + TempItems = LOG.GetLogItems(TopicList[i]); + for (size_t j = 0; j < TempItems.size(); j++) + { + LogItems.push_back(TempItems[j]); + } + } + } + else + { + LogItems = LOG.GetLogItems(SelectedChannel); + } + + std::sort(LogItems.begin(), LogItems.end(), + [](const LogItem& A, const LogItem& B) -> bool + { + return A.TimeStamp < B.TimeStamp; + }); + + for (size_t i = 0; i < LogItems.size(); i++) + { + LogMessages += LogItems[i].Text; + + if (LogItems[i].Count < 1000) + { + LogMessages += " | COUNT: " + std::to_string(LogItems[i].Count); + } + else + { + LogMessages += " | COUNT: 1000+(Suppressed)"; + } + + LogMessages += " | SEVERITY: " + LOG.SeverityLevelToString(LogItems[i].Severity); + + if (SelectedChannel.empty()) + { + LogMessages += " | CHANNEL: " + LogItems[i].Topic; + } + + if (i < LogItems.size() - 1) + LogMessages += "\n"; + } + + /*static TextEditor LogEditor; + LogEditor.SetReadOnly(true); + LogEditor.SetShowWhitespaces(false); + LogEditor.SetText(LogMessages); + LogEditor.Update("Log messages");*/ + + static char LogMessages_[1000000]; + strcpy_s(LogMessages_, LogMessages.c_str()); + ImGui::InputTextMultiline("Log messages", LogMessages_, 1000000, ImVec2(ImGui::GetWindowWidth() - 30, ImGui::GetWindowHeight() - 100), ImGuiInputTextFlags_ReadOnly); + + ImGui::PopStyleVar(); + ImGui::End(); +} \ No newline at end of file diff --git a/EditorWindows/PrefabEditorManager.cpp b/EditorWindows/PrefabEditorManager.cpp new file mode 100644 index 0000000..a55058e --- /dev/null +++ b/EditorWindows/PrefabEditorManager.cpp @@ -0,0 +1,324 @@ +#include "PrefabEditorManager.h" +#include "SceneGraphWindow.h" +#include "../FEEditor.h" + +FEPrefabSceneEditorWindow::FEPrefabSceneEditorWindow(FEScene* Scene) : FEEditorSceneWindow(Scene) +{ + bSelfContained = false; + + ApplyButton = new ImGuiButton("Apply"); + ApplyButton->SetSize(ImVec2(140, 24)); + ApplyButton->SetDefaultColor(ImVec4(0.2f, 0.8f, 0.2f, 1.0f)); + + CloseButton = new ImGuiButton("Close"); + CloseButton->SetSize(ImVec2(140, 24)); + CloseButton->SetDefaultColor(ImVec4(0.8f, 0.2f, 0.2f, 1.0f)); + + AcceptedTypes.clear(); + AcceptedTypes.push_back(FE_GAMEMODEL); + ToolTipTexts.clear(); + ToolTipTexts.push_back("Drop to add to scene"); + CurrentDragAndDropCallback = FEPrefabSceneEditorWindow::DragAndDropCallBack; +} + +FEPrefabSceneEditorWindow::~FEPrefabSceneEditorWindow() +{ + delete CloseButton; + // Using ID instead of Scene pointer because it's possible that scene was already deleted. + SCENE_MANAGER.DeleteScene(SceneID); + + if (!PREFAB_EDITOR_MANAGER.bClearing) + { + auto WindowIterator = PREFAB_EDITOR_MANAGER.PrefabWindows.begin(); + while (WindowIterator != PREFAB_EDITOR_MANAGER.PrefabWindows.end()) + { + if (WindowIterator->second == this) + { + PREFAB_EDITOR_MANAGER.PrefabWindows.erase(WindowIterator); + break; + } + + WindowIterator++; + } + } +} + +void FEPrefabSceneEditorWindow::Render() +{ + FEEditorSceneWindow::Render(); + + if (!IsVisible()) + return; + + ApplyButton->SetSize(ImVec2(GetWindow()->ContentRegionRect.GetWidth() / 10.0f, GetWindow()->Rect().GetHeight() / 20.0f)); + ApplyButton->SetPosition(ImVec2(5.0f, GetWindow()->Rect().GetHeight() - ApplyButton->GetSize().y - 5.0f)); + ApplyButton->Render(); + if (ApplyButton->IsClicked()) + { + PREFAB_EDITOR_MANAGER.ApplyModificationsToPrefabScene(this); + } + + CloseButton->SetSize(ApplyButton->GetSize()); + CloseButton->SetPosition(ImVec2(GetWindow()->ContentRegionRect.GetWidth() - CloseButton->GetSize().x - 5.0f, + GetWindow()->Rect().GetHeight() - CloseButton->GetSize().y - 5.0f)); + CloseButton->Render(); + if (CloseButton->IsClicked()) + { + bWaitingForRemoval = true; + Close(); + } + + FEEditorSceneWindow::OnRenderEnd(); +} + +bool FEPrefabSceneEditorWindow::DragAndDropCallBack(FEObject* Object, void** UserData) +{ + if (EDITOR.GetFocusedScene() == nullptr) + return false; + + if (CAMERA_SYSTEM.GetMainCamera(EDITOR.GetFocusedScene()) == nullptr) + return false; + + if (UserData == nullptr) + return false; + + FEEditorSceneWindow* EditorSceneWindow = reinterpret_cast(UserData); + if (EditorSceneWindow->GetScene() == nullptr) + return false; + + if (Object->GetType() == FE_GAMEMODEL) + { + FEGameModel* GameModel = RESOURCE_MANAGER.GetGameModel(Object->GetObjectID()); + + FETransformComponent& CameraTransformComponent = CAMERA_SYSTEM.GetMainCamera(EDITOR.GetFocusedScene())->GetComponent(); + FECameraComponent& CameraComponent = CAMERA_SYSTEM.GetMainCamera(EDITOR.GetFocusedScene())->GetComponent(); + + FEEntity* Entity = EditorSceneWindow->GetScene()->CreateEntity(Object->GetName()); + Entity->AddComponent(GameModel); + + SELECTED.SetSelected(Entity); + PROJECT_MANAGER.GetCurrent()->SetModified(true); + + return true; + + } + + return false; +} + +FEPrefabEditorManager::FEPrefabEditorManager() +{ + +} + +FEPrefabEditorManager::~FEPrefabEditorManager() +{ + Clear(); +} + +void FEPrefabEditorManager::Clear() +{ + bClearing = true; + + auto WindowIterator = PrefabWindows.begin(); + while (WindowIterator != PrefabWindows.end()) + { + delete WindowIterator->second; + WindowIterator = PrefabWindows.erase(WindowIterator); + } + + PrefabWindows.clear(); + bClearing = false; +} + +FEEntity* FEPrefabEditorManager::InjectModelViewCamera(FEScene* Scene) +{ + FEProject* CurrentProject = PROJECT_MANAGER.GetCurrent(); + if (CurrentProject->SceneIDToEditorCameraID.find(Scene->GetObjectID()) != CurrentProject->SceneIDToEditorCameraID.end()) + { + FEEntity* CameraEntity = Scene->GetEntity(CurrentProject->SceneIDToEditorCameraID[Scene->GetObjectID()]); + if (CameraEntity != nullptr) + { + LOG.Add("FEPrefabEditorManager::InjectModelViewCamera: Editor camera already exists in scene " + Scene->GetName(), "FE_LOG_LOADING", FE_LOG_WARNING); + return nullptr; + } + else + { + CurrentProject->SceneIDToEditorCameraID.erase(Scene->GetObjectID()); + } + } + + FEEntity* CameraEntity = nullptr; + std::vector CameraPrefab = RESOURCE_MANAGER.GetPrefabByName("Model view camera prefab"); + if (CameraPrefab.size() == 0) + { + LOG.Add("FEPrefabEditorManager::InjectModelViewCamera: Camera prefab not found! Inserting camera manually.", "FE_LOG_LOADING", FE_LOG_WARNING); + + CameraEntity = Scene->CreateEntity("Prefab scene camera"); + CameraEntity->AddComponent(); + } + else + { + FEPrefab* CameraPrefabToUse = CameraPrefab[0]; + std::vector AddedEntities = SCENE_MANAGER.InstantiatePrefab(CameraPrefabToUse, Scene, true); + if (AddedEntities.empty()) + { + LOG.Add("FEPrefabEditorManager::InjectModelViewCamera: Camera prefab was not instantiated correctly. Inserting camera manually.", "FE_LOG_LOADING", FE_LOG_WARNING); + + CameraEntity = Scene->CreateEntity("Prefab scene camera"); + CameraEntity->AddComponent(); + } + else + { + CameraEntity = AddedEntities[0]; + } + + if (CameraEntity == nullptr) + { + LOG.Add("FEPrefabEditorManager::InjectModelViewCamera: Camera prefab was not instantiated correctly. Inserting camera manually.", "FE_LOG_LOADING", FE_LOG_WARNING); + + CameraEntity = Scene->CreateEntity("Prefab scene camera"); + CameraEntity->AddComponent(); + } + } + + RESOURCE_MANAGER.SetTag(CameraEntity, EDITOR_RESOURCE_TAG); + CAMERA_SYSTEM.SetMainCamera(CameraEntity); + + CurrentProject->SceneIDToEditorCameraID[Scene->GetObjectID()] = CameraEntity->GetObjectID(); + + return CameraEntity; +} + +void FEPrefabEditorManager::PrepareEditWinow(FEPrefab* Prefab) +{ + if (Prefab->GetScene() == nullptr) + return; + + // We don't want to open the same prefab scene twice + if (IsPrefabWindowOpen(Prefab)) + return; + + FEScene* CurrentPrefabScene = SCENE_MANAGER.DuplicateScene(Prefab->GetScene(), "Scene: " + Prefab->GetName(), nullptr, FESceneFlag::Active | FESceneFlag::EditorMode | FESceneFlag::Renderable); + RESOURCE_MANAGER.SetTag(CurrentPrefabScene, EDITOR_RESOURCE_TAG); + + // Because by default camera is looking at 0,0,0 we need to place "empty" entity at 0,0,0. + // To ensure that scene AABB would include some entity at 0,0,0. + FEEntity* EmptyEntity = CurrentPrefabScene->CreateEntity("Empty entity"); + + FEAABB SceneAABB = CurrentPrefabScene->GetSceneAABB([](FEEntity* Entity) -> bool { + if (Entity->GetTag() == EDITOR_RESOURCE_TAG) + return false; + + if (Entity->HasComponent()) + return false; + + if (Entity->HasComponent()) + return false; + + return true; + }); + + CurrentPrefabScene->DeleteEntity(EmptyEntity); + + FEEntity* Camera = InjectModelViewCamera(CurrentPrefabScene); + FECameraComponent& CameraComponent = Camera->GetComponent(); + CameraComponent.SetSSAOEnabled(false); + + // We want to make sure that distance to model is at least 1.0 + float CalculatedDistance = SceneAABB.GetLongestAxisLength() * 2.5f; + FENativeScriptComponent& ScriptComponent = Camera->GetComponent(); + ScriptComponent.SetVariableValue("DistanceToModel", CalculatedDistance > 1.0f ? SceneAABB.GetLongestAxisLength() * 2.5f : 1.0f); + + // To make sure that next scene FEAABB calculation will include correct camera position. + CAMERA_SYSTEM.IndividualUpdate(Camera, 0.0); + + FEEntity* SkyDomeEntity = CurrentPrefabScene->CreateEntity("Prefab scene skydome"); + RESOURCE_MANAGER.SetTag(SkyDomeEntity, EDITOR_RESOURCE_TAG); + SkyDomeEntity->GetComponent().SetScale(glm::vec3(100.0f)); + SkyDomeEntity->AddComponent(); + + FEEntity* LightEntity = CurrentPrefabScene->CreateEntity("Prefab scene light"); + RESOURCE_MANAGER.SetTag(LightEntity, EDITOR_RESOURCE_TAG); + LightEntity->AddComponent(FE_DIRECTIONAL_LIGHT); + FELightComponent& LightComponent = LightEntity->GetComponent(); + LightEntity->GetComponent().SetRotation(glm::vec3(-40.0f, 10.0f, 0.0f)); + LightComponent.SetIntensity(4.3f); + SceneAABB = CurrentPrefabScene->GetSceneAABB([](FEEntity* Entity) -> bool { + if (Entity->GetTag() == EDITOR_RESOURCE_TAG && !Entity->HasComponent()) + return false; + + if (Entity->HasComponent()) + return false; + + return true; + }); + LightComponent.SetShadowCoverage(SceneAABB.GetLongestAxisLength() * 2); + LightComponent.SetCastShadows(true); + + PrefabWindows[Prefab] = new FEPrefabSceneEditorWindow(CurrentPrefabScene); + EDITOR.AddCustomEditorScene(PrefabWindows[Prefab]); +} + +void FEPrefabEditorManager::ApplyModificationsToPrefabScene(FEPrefabSceneEditorWindow* Window) +{ + FEPrefab* Prefab = nullptr; + + auto WindowIterator = PrefabWindows.begin(); + while (WindowIterator != PrefabWindows.end()) + { + if (WindowIterator->second == Window) + { + Prefab = WindowIterator->first; + break; + } + + WindowIterator++; + } + + if (Prefab == nullptr) + return; + + FEScene* ModifiedScene = Window->GetScene(); + Prefab->GetScene()->Clear(); + + SCENE_MANAGER.ImportSceneAsNode(ModifiedScene, Prefab->GetScene(), Prefab->GetScene()->SceneGraph.GetRoot(), [](FEEntity* EntityToCheck) { + return !(EntityToCheck->GetTag() == EDITOR_RESOURCE_TAG); + }); + + Prefab->SetDirtyFlag(true); + PREVIEW_MANAGER.GetPrefabPreview(Prefab->GetObjectID()); +} + +bool FEPrefabEditorManager::IsPrefabWindowOpen(FEPrefab* Prefab) +{ + return PrefabWindows.find(Prefab) != PrefabWindows.end(); +} + +bool FEPrefabEditorManager::IsEditorWindowIsPrefabWindow(FEEditorSceneWindow* Window) +{ + auto WindowIterator = PrefabWindows.begin(); + while (WindowIterator != PrefabWindows.end()) + { + if (WindowIterator->second == Window) + return true; + + WindowIterator++; + } + + return false; +} + +FEPrefab* FEPrefabEditorManager::GetPrefabFromEditorWindow(FEEditorSceneWindow* Window) +{ + auto WindowIterator = PrefabWindows.begin(); + while (WindowIterator != PrefabWindows.end()) + { + if (WindowIterator->second == Window) + return WindowIterator->first; + + WindowIterator++; + } + + return nullptr; +} \ No newline at end of file diff --git a/EditorWindows/PrefabEditorManager.h b/EditorWindows/PrefabEditorManager.h new file mode 100644 index 0000000..a74a15b --- /dev/null +++ b/EditorWindows/PrefabEditorManager.h @@ -0,0 +1,45 @@ +#pragma once + +#include "CombineChannelsToTexturePopUp.h" +#include "EditorBaseWindowClasses/FEEditorSceneWindow.h" + +class FEPrefabSceneEditorWindow : public FEEditorSceneWindow +{ + friend class FEPrefabEditorManager; + + ~FEPrefabSceneEditorWindow(); + + ImGuiButton* CloseButton = nullptr; + ImGuiButton* ApplyButton = nullptr; + + static bool DragAndDropCallBack(FEObject* Object, void** UserData); +public: + FEPrefabSceneEditorWindow(FEScene* Scene); + void Render() override; +}; + +class FEPrefabEditorManager +{ + friend class FEEditor; + friend class FEPrefabSceneEditorWindow; + + SINGLETON_PRIVATE_PART(FEPrefabEditorManager) + + std::unordered_map PrefabWindows; + bool bClearing = false; + + void ApplyModificationsToPrefabScene(FEPrefabSceneEditorWindow* Window); + FEEntity* InjectModelViewCamera(FEScene* Scene); +public: + SINGLETON_PUBLIC_PART(FEPrefabEditorManager) + + void PrepareEditWinow(FEPrefab* Prefab); + void Clear(); + + bool IsPrefabWindowOpen(FEPrefab* Prefab); + bool IsEditorWindowIsPrefabWindow(FEEditorSceneWindow* Window); + + FEPrefab* GetPrefabFromEditorWindow(FEEditorSceneWindow* Window); +}; + +#define PREFAB_EDITOR_MANAGER FEPrefabEditorManager::GetInstance() \ No newline at end of file diff --git a/FEEditorSubWindows/projectWasModifiedPopUp.cpp b/EditorWindows/ProjectWasModifiedPopUp.cpp similarity index 73% rename from FEEditorSubWindows/projectWasModifiedPopUp.cpp rename to EditorWindows/ProjectWasModifiedPopUp.cpp index c896366..bfd7669 100644 --- a/FEEditorSubWindows/projectWasModifiedPopUp.cpp +++ b/EditorWindows/ProjectWasModifiedPopUp.cpp @@ -1,21 +1,19 @@ -#include "projectWasModifiedPopUp.h" +#include "ProjectWasModifiedPopUp.h" -projectWasModifiedPopUp* projectWasModifiedPopUp::Instance = nullptr; - -projectWasModifiedPopUp::projectWasModifiedPopUp() +ProjectWasModifiedPopUp::ProjectWasModifiedPopUp() { PopupCaption = "Save project ?"; ObjToWorkWith = nullptr; } -void projectWasModifiedPopUp::Show(FEProject* Project, const bool FullyCloseApplication) +void ProjectWasModifiedPopUp::Show(FEProject* Project, const bool FullyCloseApplication) { bShouldOpen = true; ObjToWorkWith = Project; bShouldTerminate = FullyCloseApplication; } -void projectWasModifiedPopUp::Render() +void ProjectWasModifiedPopUp::Render() { ImGuiModalPopup::Render(); @@ -32,14 +30,14 @@ void projectWasModifiedPopUp::Render() bool ButtonPressed = false; - ImGui::SetWindowPos(ImVec2(ENGINE.GetWindowWidth() / 2.0f - ImGui::GetWindowWidth() / 2.0f, ENGINE.GetWindowHeight() / 2.0f - ImGui::GetWindowHeight() / 2.0f)); + ImGui::SetWindowPos(ImVec2(APPLICATION.GetMainWindow()->GetWidth() / 2.0f - ImGui::GetWindowWidth() / 2.0f, APPLICATION.GetMainWindow()->GetHeight() / 2.0f - ImGui::GetWindowHeight() / 2.0f)); ImGui::Text("Project was modified, should it be saved before exit ?"); ImGui::SetCursorPosX(ImGui::GetWindowWidth() * 0.15f - 140.0f / 2.0f); ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 10.0f); if (ImGui::Button("Save", ImVec2(140, 0))) { - PROJECT_MANAGER.GetCurrent()->SaveScene(); - ENGINE.TakeScreenshot((PROJECT_MANAGER.GetCurrent()->GetProjectFolder() + "projectScreenShot.texture").c_str()); + PROJECT_MANAGER.GetCurrent()->SaveProject(); + //ENGINE.SaveScreenshot((PROJECT_MANAGER.GetCurrent()->GetProjectFolder() + "projectScreenShot.texture").c_str(), PROJECT_MANAGER.GetCurrent()->GetScene()); ObjToWorkWith = nullptr; ImGuiModalPopup::Close(); ButtonPressed = true; diff --git a/EditorWindows/ProjectWasModifiedPopUp.h b/EditorWindows/ProjectWasModifiedPopUp.h new file mode 100644 index 0000000..ba00641 --- /dev/null +++ b/EditorWindows/ProjectWasModifiedPopUp.h @@ -0,0 +1,17 @@ +#pragma once + +#include "DebugTextureViewWindow.h" + +class ProjectWasModifiedPopUp : public ImGuiModalPopup +{ + FEProject* ObjToWorkWith; + bool bShouldTerminate = false; +public: + SINGLETON_PUBLIC_PART(ProjectWasModifiedPopUp) + + void Show(FEProject* Project, bool FullyCloseApplication); + void Render() override; + +private: + SINGLETON_PRIVATE_PART(ProjectWasModifiedPopUp) +}; \ No newline at end of file diff --git a/FEEditorSubWindows/renamePopups.cpp b/EditorWindows/RenamePopups.cpp similarity index 71% rename from FEEditorSubWindows/renamePopups.cpp rename to EditorWindows/RenamePopups.cpp index 2eb4f80..fb35ce5 100644 --- a/FEEditorSubWindows/renamePopups.cpp +++ b/EditorWindows/RenamePopups.cpp @@ -1,8 +1,6 @@ -#include "renamePopups.h" +#include "RenamePopups.h" -renameFailedPopUp* renameFailedPopUp::Instance = nullptr; - -renameFailedPopUp::renameFailedPopUp() +RenameFailedPopUp::RenameFailedPopUp() { PopupCaption = "Invalid name"; OkButton = new ImGuiButton("OK"); @@ -11,19 +9,19 @@ renameFailedPopUp::renameFailedPopUp() OkButton->SetPosition(ImVec2(0, 0)); } -renameFailedPopUp::~renameFailedPopUp() +RenameFailedPopUp::~RenameFailedPopUp() { delete OkButton; } -void renameFailedPopUp::Render() +void RenameFailedPopUp::Render() { ImGuiModalPopup::Render(); ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(15, 15)); if (ImGui::BeginPopupModal(PopupCaption.c_str(), nullptr, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove)) { - ImGui::SetWindowPos(ImVec2(ENGINE.GetWindowWidth() / 2.0f - ImGui::GetWindowWidth() / 2.0f, ENGINE.GetWindowHeight() / 2.0f - ImGui::GetWindowHeight() / 2.0f)); + ImGui::SetWindowPos(ImVec2(APPLICATION.GetMainWindow()->GetWidth() / 2.0f - ImGui::GetWindowWidth() / 2.0f, APPLICATION.GetMainWindow()->GetHeight() / 2.0f - ImGui::GetWindowHeight() / 2.0f)); ImGui::Text("Entered name is incorrect !"); OkButton->SetPosition(ImVec2(ImGui::GetWindowWidth() / 2.0f - 120.0f / 2.0f, ImGui::GetCursorPosY() + 10.0f)); @@ -42,22 +40,20 @@ void renameFailedPopUp::Render() } } -renamePopUp* renamePopUp::Instance = nullptr; - -renamePopUp::renamePopUp() +RenamePopUp::RenamePopUp() { PopupCaption = "Rename object"; ObjToWorkWith = nullptr; } -void renamePopUp::Show(FEObject* ObjToWorkWith) +void RenamePopUp::Show(FEObject* ObjToWorkWith) { bShouldOpen = true; this->ObjToWorkWith = ObjToWorkWith; strcpy_s(NewName, ObjToWorkWith->GetName().size() + 1, ObjToWorkWith->GetName().c_str()); } -void renamePopUp::Render() +void RenamePopUp::Render() { ImGuiModalPopup::Render(); @@ -71,7 +67,7 @@ void renamePopUp::Render() return; } - ImGui::SetWindowPos(ImVec2(ENGINE.GetWindowWidth() / 2.0f - ImGui::GetWindowWidth() / 2.0f, ENGINE.GetWindowHeight() / 2.0f - ImGui::GetWindowHeight() / 2.0f)); + ImGui::SetWindowPos(ImVec2(APPLICATION.GetMainWindow()->GetWidth() / 2.0f - ImGui::GetWindowWidth() / 2.0f, APPLICATION.GetMainWindow()->GetHeight() / 2.0f - ImGui::GetWindowHeight() / 2.0f)); ImGui::Text("New object name :"); ImGui::InputText("##New object name", NewName, IM_ARRAYSIZE(NewName)); @@ -88,6 +84,14 @@ void renamePopUp::Render() ObjToWorkWith->SetName(NewName); + if (ObjToWorkWith->GetType() == FE_SCENE_GRAPH_NODE) + { + FENaiveSceneGraphNode* Node = reinterpret_cast(ObjToWorkWith); + FEEntity* Entity = Node->GetEntity(); + if (Entity != nullptr) + Entity->SetName(NewName); + } + ImGuiModalPopup::Close(); strcpy_s(NewName, ""); } @@ -95,7 +99,7 @@ void renamePopUp::Render() { ObjToWorkWith = nullptr; ImGuiModalPopup::Close(); - renameFailedPopUp::getInstance().Show(); + RenameFailedPopUp::GetInstance().Show(); } } ImGui::SetItemDefaultFocus(); diff --git a/EditorWindows/RenamePopups.h b/EditorWindows/RenamePopups.h new file mode 100644 index 0000000..79b07af --- /dev/null +++ b/EditorWindows/RenamePopups.h @@ -0,0 +1,26 @@ +#pragma once + +#include "DeletePopups.h" + +class RenameFailedPopUp : public ImGuiModalPopup +{ + ImGuiButton* OkButton = nullptr; +public: + SINGLETON_PUBLIC_PART(RenameFailedPopUp) + void Render() override; +private: + SINGLETON_PRIVATE_PART(RenameFailedPopUp) +}; + +class RenamePopUp : public ImGuiModalPopup +{ + FEObject* ObjToWorkWith; + char NewName[512]; +public: + SINGLETON_PUBLIC_PART(RenamePopUp) + + void Show(FEObject* ObjToWorkWith); + void Render() override; +private: + SINGLETON_PRIVATE_PART(RenamePopUp) +}; \ No newline at end of file diff --git a/FEEditorSubWindows/resizeTexturePopup.cpp b/EditorWindows/ResizeTexturePopup.cpp similarity index 88% rename from FEEditorSubWindows/resizeTexturePopup.cpp rename to EditorWindows/ResizeTexturePopup.cpp index 98eff32..9ad6644 100644 --- a/FEEditorSubWindows/resizeTexturePopup.cpp +++ b/EditorWindows/ResizeTexturePopup.cpp @@ -1,8 +1,6 @@ -#include "resizeTexturePopup.h" +#include "ResizeTexturePopup.h" -resizeTexturePopup* resizeTexturePopup::Instance = nullptr; - -resizeTexturePopup::resizeTexturePopup() +ResizeTexturePopup::ResizeTexturePopup() { PopupCaption = "Resize texture"; ObjToWorkWith = nullptr; @@ -15,13 +13,13 @@ resizeTexturePopup::resizeTexturePopup() ApplyButton = new ImGuiButton("Apply"); } -resizeTexturePopup::~resizeTexturePopup() +ResizeTexturePopup::~ResizeTexturePopup() { delete CancelButton; delete ApplyButton; } -void resizeTexturePopup::Show(FETexture* ObjToWorkWith) +void ResizeTexturePopup::Show(FETexture* ObjToWorkWith) { if (ObjToWorkWith == nullptr) return; @@ -32,7 +30,7 @@ void resizeTexturePopup::Show(FETexture* ObjToWorkWith) NewHeight = ObjToWorkWith->GetHeight(); } -void resizeTexturePopup::Render() +void ResizeTexturePopup::Render() { ImGuiModalPopup::Render(); @@ -47,7 +45,7 @@ void resizeTexturePopup::Render() return; } - ImGui::SetWindowPos(ImVec2(ENGINE.GetWindowWidth() / 2.0f - ImGui::GetWindowWidth() / 2.0f, ENGINE.GetWindowHeight() / 2.0f - ImGui::GetWindowHeight() / 2.0f)); + ImGui::SetWindowPos(ImVec2(APPLICATION.GetMainWindow()->GetWidth() / 2.0f - ImGui::GetWindowWidth() / 2.0f, APPLICATION.GetMainWindow()->GetHeight() / 2.0f - ImGui::GetWindowHeight() / 2.0f)); ImGui::SetCursorPos(ImVec2(20, 45)); ImGui::Text("Width:"); diff --git a/FEEditorSubWindows/resizeTexturePopup.h b/EditorWindows/ResizeTexturePopup.h similarity index 64% rename from FEEditorSubWindows/resizeTexturePopup.h rename to EditorWindows/ResizeTexturePopup.h index 8de7617..67f4239 100644 --- a/FEEditorSubWindows/resizeTexturePopup.h +++ b/EditorWindows/ResizeTexturePopup.h @@ -1,8 +1,8 @@ #pragma once -#include "renamePopups.h" +#include "RenamePopups.h" -class resizeTexturePopup : public ImGuiModalPopup +class ResizeTexturePopup : public ImGuiModalPopup { FETexture* ObjToWorkWith; int NewWidth; @@ -14,10 +14,10 @@ class resizeTexturePopup : public ImGuiModalPopup ImGuiButton* ApplyButton; ImVec2 PopupSize = ImVec2(450, 260); public: - SINGLETON_PUBLIC_PART(resizeTexturePopup) + SINGLETON_PUBLIC_PART(ResizeTexturePopup) void Show(FETexture* ObjToWorkWith); void Render() override; private: - SINGLETON_PRIVATE_PART(resizeTexturePopup) + SINGLETON_PRIVATE_PART(ResizeTexturePopup) }; \ No newline at end of file diff --git a/EditorWindows/SceneGraphWindow.cpp b/EditorWindows/SceneGraphWindow.cpp new file mode 100644 index 0000000..da7355e --- /dev/null +++ b/EditorWindows/SceneGraphWindow.cpp @@ -0,0 +1,607 @@ +#include "SceneGraphWindow.h" +#include "../FEEditor.h" + +FEEditorSceneGraphWindow::FEEditorSceneGraphWindow() +{ + strcpy_s(FilterForEntities, "Filter entities..."); +} + +void FEEditorSceneGraphWindow::InitializeResources() +{ + EntityIcon = RESOURCE_MANAGER.LoadPNGTexture("Resources/Images/entitySceneBrowserIcon.png", "entitySceneBrowserIcon"); + RESOURCE_MANAGER.SetTag(EntityIcon, EDITOR_RESOURCE_TAG); + InstancedEntityIcon = RESOURCE_MANAGER.LoadPNGTexture("Resources/Images/instancedEntitySceneBrowserIcon.png", "instancedEntitySceneBrowserIcon"); + RESOURCE_MANAGER.SetTag(InstancedEntityIcon, EDITOR_RESOURCE_TAG); + + DirectionalLightIcon = RESOURCE_MANAGER.LoadPNGTexture("Resources/Images/directionalLightSceneBrowserIcon.png", "directionalLightSceneBrowserIcon"); + RESOURCE_MANAGER.SetTag(DirectionalLightIcon, EDITOR_RESOURCE_TAG); + SpotLightIcon = RESOURCE_MANAGER.LoadPNGTexture("Resources/Images/spotLightSceneBrowserIcon.png", "spotLightSceneBrowserIcon"); + RESOURCE_MANAGER.SetTag(SpotLightIcon, EDITOR_RESOURCE_TAG); + PointLightIcon = RESOURCE_MANAGER.LoadPNGTexture("Resources/Images/pointLightSceneBrowserIcon.png", "pointLightSceneBrowserIcon"); + RESOURCE_MANAGER.SetTag(PointLightIcon, EDITOR_RESOURCE_TAG); + + TerrainIcon = RESOURCE_MANAGER.LoadPNGTexture("Resources/Images/terrainSceneBrowserIcon.png", "terrainSceneBrowserIcon"); + RESOURCE_MANAGER.SetTag(TerrainIcon, EDITOR_RESOURCE_TAG); + + CameraIcon = RESOURCE_MANAGER.LoadPNGTexture("Resources/Images/cameraSceneBrowserIcon.png", "cameraSceneBrowserIcon"); + RESOURCE_MANAGER.SetTag(CameraIcon, EDITOR_RESOURCE_TAG); +} + +void FEEditorSceneGraphWindow::Clear() +{ + strcpy_s(FilterForEntities, ""); + bLastFrameWasInvisible = true; +} + +static void CreateInstancedEntityCallBack(const std::vector SelectionsResult) +{ + if (EDITOR.GetFocusedScene() == nullptr) + return; + + if (SelectionsResult.size() == 1 && SelectionsResult[0]->GetType() == FE_PREFAB) + { + FEGameModel* SelectedGameModel = RESOURCE_MANAGER.GetGameModel(SelectionsResult[0]->GetObjectID()); + if (SelectedGameModel == nullptr) + return; + + FETransformComponent& CameraTransformComponent = CAMERA_SYSTEM.GetMainCamera(EDITOR.GetFocusedScene())->GetComponent(); + FECameraComponent& CameraComponent = CAMERA_SYSTEM.GetMainCamera(EDITOR.GetFocusedScene())->GetComponent(); + FEEntity* Entity = EDITOR.GetFocusedScene()->CreateEntity(); + Entity->GetComponent().SetPosition(CameraTransformComponent.GetPosition(FE_WORLD_SPACE) + CameraComponent.GetForward() * 10.0f); + Entity->AddComponent(SelectedGameModel); + Entity->AddComponent(); + SELECTED.SetSelected(Entity); + + PROJECT_MANAGER.GetCurrent()->SetModified(true); + } +} + +static void CreateEntityCallBack(const std::vector SelectionsResult) +{ + if (EDITOR.GetFocusedScene() == nullptr) + return; + + if (SelectionsResult.size() == 1 && SelectionsResult[0]->GetType() == FE_PREFAB) + { + FEPrefab* SelectedPrefab = RESOURCE_MANAGER.GetPrefab(SelectionsResult[0]->GetObjectID()); + if (SelectedPrefab == nullptr) + return; + + FETransformComponent& CameraTransformComponent = CAMERA_SYSTEM.GetMainCamera(EDITOR.GetFocusedScene())->GetComponent(); + FECameraComponent& CameraComponent = CAMERA_SYSTEM.GetMainCamera(EDITOR.GetFocusedScene())->GetComponent(); + FEEntity* Entity = EDITOR.GetFocusedScene()->CreateEntity(); + Entity->GetComponent().SetPosition(CameraTransformComponent.GetPosition(FE_WORLD_SPACE) + CameraComponent.GetForward() * 10.0f); + SELECTED.SetSelected(Entity); + + PROJECT_MANAGER.GetCurrent()->SetModified(true); + } +} + +// FIXME: Make icons colored and place them in the right place. +// Currently this function is not working properly. +void FEEditorSceneGraphWindow::DrawCorrectIcon(FEEntity* SceneEntity) const +{ + if (SceneEntity == nullptr) + return; + + float CurrentCursorPosX = ImGui::GetCursorPosX(); + ImGui::SameLine(); + + if (SceneEntity->HasComponent()) + { + ImGui::Image((void*)(intptr_t)InstancedEntityIcon->GetTextureID(), ImVec2(16, 16), ImVec2(0.0f, 0.0f), ImVec2(1.0f, 1.0f)); + } + + if (SceneEntity->HasComponent()) + { + if (SceneEntity->GetComponent().GetType() == FE_DIRECTIONAL_LIGHT) + { + ImGui::Image((void*)(intptr_t)DirectionalLightIcon->GetTextureID(), ImVec2(16, 16), ImVec2(0.0f, 0.0f), ImVec2(1.0f, 1.0f)); + } + if (SceneEntity->GetComponent().GetType() == FE_SPOT_LIGHT) + { + ImGui::Image((void*)(intptr_t)SpotLightIcon->GetTextureID(), ImVec2(16, 16), ImVec2(0.0f, 0.0f), ImVec2(1.0f, 1.0f)); + } + if (SceneEntity->GetComponent().GetType() == FE_POINT_LIGHT) + { + ImGui::Image((void*)(intptr_t)PointLightIcon->GetTextureID(), ImVec2(16, 16), ImVec2(0.0f, 0.0f), ImVec2(1.0f, 1.0f)); + } + } + + if (SceneEntity->HasComponent()) + { + ImGui::Image((void*)(intptr_t)TerrainIcon->GetTextureID(), ImVec2(16, 16), ImVec2(0.0f, 0.0f), ImVec2(1.0f, 1.0f)); + } + + if (SceneEntity->HasComponent()) + { + ImGui::Image((void*)(intptr_t)CameraIcon->GetTextureID(), ImVec2(16, 16), ImVec2(0.0f, 0.0f), ImVec2(1.0f, 1.0f)); + } + + ImGui::SetCursorPosX(CurrentCursorPosX); +} + +DragAndDropTarget* FEEditorSceneGraphWindow::GetSceneNodeDragAndDropTarget(FENaiveSceneGraphNode* NodeToFind) +{ + int64_t UniqueID = 0; + // If node is root. + if (NodeToFind->GetEntity() == nullptr) + { + UniqueID = -1; + } + else + { + UniqueID = static_cast(std::hash{}(NodeToFind->GetEntity()->GetObjectID().c_str())); + } + + if (SceneNodeDragAndDropTargets.find(UniqueID) == SceneNodeDragAndDropTargets.end()) + { + SceneNodeDragAndDropTargets[UniqueID] = DRAG_AND_DROP_MANAGER.AddTarget(std::vector { FE_SCENE_GRAPH_NODE }, + SceneNodeDragAndDropCallback, reinterpret_cast(NodeToFind), + std::vector { "Drop move to that parent" }); + } + + return SceneNodeDragAndDropTargets[UniqueID]; +} + +void FEEditorSceneGraphWindow::RenderNodeBackground() +{ + // Calculate the expected height of the node. + float NodeHeight = ImGui::GetFrameHeight(); + NodeHeight += BackgroundHeightModifier; + + ImRect BackgroundRect = ImRect(ImVec2(bIndintationAwareNodeBackground ? ImGui::GetCursorScreenPos().x : ImGui::GetWindowContentRegionMin().x, ImGui::GetCursorScreenPos().y), + ImVec2(ImGui::GetWindowContentRegionMax().x, ImGui::GetCursorScreenPos().y + NodeHeight)); + + // Shift the background rectangle + BackgroundRect.Min.y += BackgroundColorYShift; + BackgroundRect.Max.y += BackgroundColorYShift; + + // Render + ImColor BackgroundColor = bBackgroundColorSwitch ? ImColor(EvenNodeBackgroundColor) : ImColor(OddNodeBackgroundColor); + ImGui::GetWindowDrawList()->AddRectFilled(BackgroundRect.Min, BackgroundRect.Max, BackgroundColor); + bBackgroundColorSwitch = !bBackgroundColorSwitch; +} + +ImRect FEEditorSceneGraphWindow::RenderSubTree(FENaiveSceneGraphNode* SubTreeRoot) +{ + if (SubTreeRoot == nullptr) + return ImRect(); + + FEEntity* CurrentEntity = SubTreeRoot->GetEntity(); + if (CurrentEntity != nullptr) + { + if (CurrentEntity->GetTag() == EDITOR_RESOURCE_TAG) + return ImRect(); + } + + SceneNodeDragAndDropTargetIndex++; + int64_t UniqueID = 0; + bool bIsLeaf = SubTreeRoot->GetChildren().size() == 0; + ImGuiTreeNodeFlags NodeFlags = bIsLeaf ? ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen : ImGuiTreeNodeFlags_OpenOnArrow; + std::string Name = SubTreeRoot->GetParent() == nullptr ? PROJECT_MANAGER.GetCurrent()->GetName() : SubTreeRoot->GetName(); + + if (SELECTED.GetSelected(EDITOR.GetFocusedScene()) != nullptr && CurrentEntity != nullptr) + { + if (SELECTED.GetSelected(EDITOR.GetFocusedScene())->GetObjectID() == CurrentEntity->GetObjectID()) + { + NodeFlags |= ImGuiTreeNodeFlags_Selected; + } + } + + // If node is root. + if (CurrentEntity == nullptr) + { + UniqueID = -1; + } + else + { + UniqueID = static_cast(std::hash{}(CurrentEntity->GetObjectID().c_str())); + } + + // If last frame scene graph was invisible, open root node. + if (bLastFrameWasInvisible && CurrentEntity == nullptr) + ImGui::SetNextItemOpen(true); + + if (bUseNodeBackground) + RenderNodeBackground(); + + bool bOpened = ImGui::TreeNodeEx((void*)UniqueID, NodeFlags, Name.c_str(), 0); + GetSceneNodeDragAndDropTarget(SubTreeRoot)->StickToItem(); + const ImRect NodeRect = ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax()); + //DrawCorrectIcon(SubTreeRoot->GetEntity()); + + ImVec2 VerticalLineStart = ImGui::GetCursorScreenPos(); + VerticalLineStart.x += VerticalTreeLineXOffset; + VerticalLineStart.y += VerticalTreeLineYOffset; + ImVec2 VerticalLineEnd = VerticalLineStart; + + if (ImGui::IsItemClicked()) + { + if (SubTreeRoot->GetParent() != nullptr) + { + SELECTED.SetSelected(CurrentEntity); + } + } + + if (ImGui::IsItemHovered()) + { + if (!bShouldOpenContextMenu && !DRAG_AND_DROP_MANAGER.ObjectIsDraged()) + { + /*std::string AdditionalTypeInfo; + if (FilteredResources[i]->GetType() == FE_TEXTURE) + { + AdditionalTypeInfo += "\nTexture type: "; + AdditionalTypeInfo += FETexture::TextureInternalFormatToString(RESOURCE_MANAGER.GetTexture(FilteredResources[i]->GetObjectID())->GetInternalFormat()); + } + + ImGui::BeginTooltip(); + ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f); + ImGui::TextUnformatted(("Name: " + FilteredResources[i]->GetName() + + "\nType: " + FEObjectTypeToString(FilteredResources[i]->GetType()) + + AdditionalTypeInfo + + "\nPath: " + VIRTUAL_FILE_SYSTEM.GetCurrentPath() + ).c_str()); + ImGui::PopTextWrapPos(); + ImGui::EndTooltip();*/ + + SceneGraphNodeHoveredID = SubTreeRoot->GetObjectID(); + + ItemUnderMouse = UniqueID; + + if (ImGui::IsMouseDragging(0)) + DRAG_AND_DROP_MANAGER.SetObjectToDrag(SubTreeRoot, nullptr, ImVec2(), ImVec2()); + } + } + + if (bOpened) + { + auto Children = SubTreeRoot->GetChildren(); + if (!Children.empty()) + { + for (size_t i = 0; i < Children.size(); i++) + { + // Double check if we need to draw child to make sure we don't draw internal editor resources. + FEEntity* ChildEntity = Children[i]->GetEntity(); + if (ChildEntity != nullptr) + { + if (ChildEntity->GetTag() == EDITOR_RESOURCE_TAG) + continue; + } + + const ImRect ChildRect = RenderSubTree(Children[i]); + + // Draw horizontal line. + const float MiddlePoint = (ChildRect.Min.y + ChildRect.Max.y) / 2.0f; + bool bChildHaveChildren = Children[i]->GetChildren().size() > 0; + ImVec2 HorizontalLineStart = ImVec2(VerticalLineStart.x, MiddlePoint); + ImVec2 HorizontalLineEnd = ImVec2(VerticalLineStart.x + HorizontalTreeLineLength, MiddlePoint); + if (bChildHaveChildren) + HorizontalLineEnd.x += HorizontalTreeLineLengthParentOffset; + ImGui::GetWindowDrawList()->AddLine(HorizontalLineStart, HorizontalLineEnd, ImColor(VerticalTreeLineColor)); + + VerticalLineEnd.y = MiddlePoint; + } + + ImGui::TreePop(); + } + + // Draw vertical line. + ImGui::GetWindowDrawList()->AddLine(VerticalLineStart, VerticalLineEnd, ImColor(VerticalTreeLineColor)); + } + + SceneGraphBackgroundRect.Max.x = SceneGraphBackgroundRect.Max.x > NodeRect.Max.x ? SceneGraphBackgroundRect.Max.x : NodeRect.Max.x; + SceneGraphBackgroundRect.Max.y = SceneGraphBackgroundRect.Max.y > NodeRect.Max.y ? SceneGraphBackgroundRect.Max.y : NodeRect.Max.y; + + return NodeRect; +} + +int FEEditorSceneGraphWindow::FilterInputTextCallback(ImGuiInputTextCallbackData* Data) +{ + if (Data->EventFlag == ImGuiInputTextFlags_CallbackAlways) + { + bool isFocused = ImGui::IsItemActive(); + if (SCENE_GRAPH_WINDOW.bIsPlaceHolderTextUsed) + { + // Check if the input just gained focus + if (isFocused && !SCENE_GRAPH_WINDOW.bFilterInputWasFocused) + { + strcpy_s(SCENE_GRAPH_WINDOW.FilterForEntities, ""); + + // Update ImGui's buffer. + Data->BufDirty = true; + Data->DeleteChars(0, Data->BufTextLen); + Data->InsertChars(0, SCENE_GRAPH_WINDOW.FilterForEntities); + + SCENE_GRAPH_WINDOW.bIsPlaceHolderTextUsed = false; + } + } + + SCENE_GRAPH_WINDOW.bFilterInputWasFocused = isFocused; + } + + return 0; +} + + +void FEEditorSceneGraphWindow::RenderFilterInput() +{ + const bool bIsPlaceHolderTextUsedWasOn = bIsPlaceHolderTextUsed; + + if (bIsPlaceHolderTextUsedWasOn) + ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(255, 255, 255, 150)); + + // Setting up the callback for the input text. + std::function Callback = std::bind(&FEEditorSceneGraphWindow::FilterInputTextCallback, std::placeholders::_1); + auto StaticCallback = [](ImGuiInputTextCallbackData* Data) -> int { + const auto& Callback = *static_cast*>(Data->UserData); + return Callback(Data); + }; + + if (ImGui::InputText("##SceneGraphWindowFilter", FilterForEntities, FilterInputBufferSize, ImGuiInputTextFlags_CallbackAlways, StaticCallback, &Callback)) + { + + } + + if (!ImGui::IsItemActive()) + { + if (strlen(FilterForEntities) == 0) + { + strcpy_s(FilterForEntities, PlaceHolderTextString.c_str()); + bIsPlaceHolderTextUsed = true; + bFilterInputWasFocused = false; + } + } + + if (bIsPlaceHolderTextUsedWasOn) + ImGui::PopStyleColor(); +} + +void FEEditorSceneGraphWindow::RenderSceneGraph() +{ + if (EDITOR.GetFocusedScene() == nullptr) + return; + + FENaiveSceneGraphNode* Root = EDITOR.GetFocusedScene()->SceneGraph.GetRoot(); + + if (bSceneNodeTargetsDirty) + SceneNodeDragAndDropTargets.clear(); + + SceneGraphBackgroundRect.Min = ImGui::GetCursorScreenPos(); + SceneGraphBackgroundRect.Max = SceneGraphBackgroundRect.Min; + + RenderFilterInput(); + + SceneNodeDragAndDropTargetIndex = -1; + bBackgroundColorSwitch = true; + RenderSubTree(Root); + + SceneGraphBackgroundRect.Max.x = ImGui::GetWindowContentRegionMax().x; + SceneGraphBackgroundRect.Min -= ImVec2(10.0f, 10.0f); + SceneGraphBackgroundRect.Max += ImVec2(10.0f, 10.0f); + // Render box around the scene graph. + ImGui::GetWindowDrawList()->AddRect(SceneGraphBackgroundRect.Min, SceneGraphBackgroundRect.Max, ImColor(ImVec4(0.0f, 0.0f, 0.0f, 0.7f)), 2.0f); + + ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 15.0f); + + // Uncomment this to tweak the scene graph rendering. + /*ImGui::DragFloat("VerticalTreeLineXOffset", &VerticalTreeLineXOffset, 0.1f); + ImGui::DragFloat("VerticalTreeLineYOffset", &VerticalTreeLineYOffset, 0.1f); + ImGui::DragFloat("HorizontalTreeLineLenght", &HorizontalTreeLineLength, 0.1f); + ImGui::DragFloat("HorizontalTreeLineLenghtOffset", &HorizontalTreeLineLengthParentOffset, 0.1f); + ImGui::DragFloat("BackgroundColorYShift", &BackgroundColorYShift, 0.1f); + ImGui::DragFloat("BackgroundHeightModifier", &BackgroundHeightModifier, 0.1f); + ImGui::ColorEdit4("VerticalTreeLineColor", (float*)&VerticalTreeLineColor); + ImGui::ColorEdit4("EvenNodeBackgroundColor", (float*)&EvenNodeBackgroundColor); + ImGui::ColorEdit4("OddNodeBackgroundColor", (float*)&OddNodeBackgroundColor); + ImGui::Checkbox("Draw node background", &bUseNodeBackground); + ImGui::Checkbox("IndintationAwareNodeBackground", &bIndintationAwareNodeBackground);*/ + + if (bSceneNodeTargetsDirty) + bSceneNodeTargetsDirty = false; + + bLastFrameWasInvisible = false; +} + +void FEEditorSceneGraphWindow::Render() +{ + if (!bVisible) + { + bLastFrameWasInvisible = true; + return; + } + + FEScene* CurrentScene = EDITOR.GetFocusedScene(); + if (CurrentScene == nullptr) + { + bLastFrameWasInvisible = true; + return; + } + + if (!bShouldOpenContextMenu) + SceneGraphNodeHoveredID = ""; + + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(15, 15)); + ImGui::Begin("Scene Entities", nullptr, ImGuiWindowFlags_None); + + ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor::ImColor(0.6f, 0.24f, 0.24f)); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::ImColor(0.7f, 0.21f, 0.21f)); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::ImColor(0.8f, 0.16f, 0.16f)); + + RenderSceneGraph(); + + ImGui::PopStyleColor(); + ImGui::PopStyleColor(); + ImGui::PopStyleColor(); + + bool bOpenContextMenu = false; + if (ImGui::IsWindowHovered() && ImGui::IsMouseClicked(1)) + bOpenContextMenu = true; + + if (bOpenContextMenu) + ImGui::OpenPopup("##context_menu"); + + bShouldOpenContextMenu = false; + + if (ImGui::BeginPopup("##context_menu")) + { + bShouldOpenContextMenu = true; + + if (SceneGraphNodeHoveredID.empty()) + { + if (ImGui::BeginMenu("Add")) + { + if (ImGui::MenuItem("Empty entity")) + { + CurrentScene->CreateEntity("Unnamed entity"); + } + + ImGui::EndMenu(); + } + } + else + { + FENaiveSceneGraphNode* HoveredNode = CurrentScene->SceneGraph.GetNode(SceneGraphNodeHoveredID); + if (HoveredNode != nullptr) + { + FEEntity* HoveredEntity = CurrentScene->SceneGraph.GetNode(SceneGraphNodeHoveredID)->GetEntity(); + if (HoveredEntity != nullptr) + { + if (ImGui::MenuItem("Rename")) + { + RenamePopUp::GetInstance().Show(HoveredNode); + } + + if (ImGui::MenuItem("Delete")) + { + if (SELECTED.GetSelected(CurrentScene) == HoveredEntity) + SELECTED.Clear(CurrentScene); + + CurrentScene->DeleteEntity(HoveredEntity); + } + } + } + } + + ImGui::EndPopup(); + } + + // FIXME: Grid settings should be moved to other window, not scene graph window. + //static bool bDisplayGrid = true; + //ImGui::Checkbox("Display grid", &bDisplayGrid); + + //static glm::vec3 color = glm::vec3(0.2f, 0.3f, 0.4f); + + //const float BasicW = 0.1f; + //float width = BasicW * 4.0f; + //if (bDisplayGrid) + //{ + // const int GridSize = 200; + // for (int i = -GridSize / 2; i < GridSize / 2; i++) + // { + // color = glm::vec3(0.4f, 0.65f, 0.73f); + // width = BasicW * 4.0f; + // if (i % 2 != 0 && i != 0) + // { + // color = color / 4.0f; + // width = width / 4.0f; + // } + // else if (i == 0) + // { + // color = glm::vec3(0.9f, 0.9f, 0.9f); + // width = BasicW * 4.0f; + // } + + // RENDERER.DrawLine(glm::vec3(i, 0.0f, -GridSize / 2), glm::vec3(i, 0.0f, GridSize / 2), color, width); + // RENDERER.DrawLine(glm::vec3(-GridSize / 2, 0.0f, i), glm::vec3(GridSize / 2, 0.0f, i), color, width); + // } + //} + + static float FavgTime = 0.0f; + static std::vector AvgTime; + static int counter = 0; + + ImGui::Text((std::string("Time : ") + std::to_string(RENDERER.LastTestTime)).c_str()); + + if (AvgTime.size() < 100) + { + AvgTime.push_back(RENDERER.LastTestTime); + } + else if (AvgTime.size() >= 100) + { + AvgTime[counter++ % 100] = RENDERER.LastTestTime; + } + + for (size_t i = 0; i < AvgTime.size(); i++) + { + FavgTime += AvgTime[i]; + } + FavgTime /= AvgTime.size(); + + + if (counter > 1000000) + counter = 0; + + ImGui::Text((std::string("avg Time : ") + std::to_string(FavgTime)).c_str()); + + bool bFreezeCulling = RENDERER.bFreezeCulling; + ImGui::Checkbox("bFreezeCulling", &bFreezeCulling); + RENDERER.bFreezeCulling = bFreezeCulling; + + bool bFreezeOcclusionCulling = !RENDERER.IsOcclusionCullingEnabled(); + ImGui::Checkbox("freezeOcclusionCulling", &bFreezeOcclusionCulling); + RENDERER.SetOcclusionCullingEnabled(!bFreezeOcclusionCulling); + + static bool bDisplaySelectedObjAABB = false; + ImGui::Checkbox("Display AABB of selected object", &bDisplaySelectedObjAABB); + + // Draw AABB + FEEntity* SelectedEntity = SELECTED.GetSelected(CurrentScene); + if (SelectedEntity != nullptr && + (SelectedEntity->HasComponent() || SelectedEntity->HasComponent()) && + bDisplaySelectedObjAABB) + { + FEAABB SelectedAABB; + SelectedAABB = SelectedEntity->GetParentScene()->GetEntityAABB(SelectedEntity); + RENDERER.DrawAABB(SelectedAABB); + + if (SelectedEntity->HasComponent()) + { + static bool bDisplaySubObjAABB = false; + ImGui::Checkbox("Display AABB of instanced entity subobjects", &bDisplaySubObjAABB); + + if (bDisplaySubObjAABB) + { + FEInstancedComponent& InstancedComponent = SelectedEntity->GetComponent(); + const int MaxIterations = InstancedComponent.IndividualInstancedAABB.size() * 8 >= FE_MAX_LINES ? FE_MAX_LINES : int(InstancedComponent.IndividualInstancedAABB.size()); + + for (size_t j = 0; j < MaxIterations; j++) + { + RENDERER.DrawAABB(InstancedComponent.IndividualInstancedAABB[j]); + } + } + } + } + + static bool bDisplaySceneAABB = false; + ImGui::Checkbox("Display AABB of scene", &bDisplaySceneAABB); + if (bDisplaySceneAABB) + { + FEAABB SceneAABB = CurrentScene->GetSceneAABB([](FEEntity* Entity) -> bool { + if (Entity->GetTag() == EDITOR_RESOURCE_TAG) + return false; + + if (Entity->HasComponent()) + return false; + + if (Entity->HasComponent()) + return false; + + return true; + }); + RENDERER.DrawAABB(SceneAABB); + } + + ImGui::PopStyleVar(); + ImGui::End(); +} \ No newline at end of file diff --git a/EditorWindows/SceneGraphWindow.h b/EditorWindows/SceneGraphWindow.h new file mode 100644 index 0000000..03de875 --- /dev/null +++ b/EditorWindows/SceneGraphWindow.h @@ -0,0 +1,89 @@ +#pragma once + +#include "ProjectWasModifiedPopUp.h" + +class FEEditorSceneGraphWindow +{ + friend class FEEditor; + SINGLETON_PRIVATE_PART(FEEditorSceneGraphWindow) + + // Visibility + bool bVisible = true; + + // Icon management + void DrawCorrectIcon(FEEntity* SceneEntity) const; + FETexture* EntityIcon = nullptr; + FETexture* InstancedEntityIcon = nullptr; + FETexture* DirectionalLightIcon = nullptr; + FETexture* SpotLightIcon = nullptr; + FETexture* PointLightIcon = nullptr; + FETexture* TerrainIcon = nullptr; + FETexture* CameraIcon = nullptr; + + // Entity filtering + static const size_t FilterInputBufferSize = 2048; + char FilterForEntities[FilterInputBufferSize]; + bool bIsPlaceHolderTextUsed = true; + bool bFilterInputWasFocused = false; + std::string PlaceHolderTextString = "Filter entities..."; + void RenderFilterInput(); + static int FilterInputTextCallback(ImGuiInputTextCallbackData* data); + + // Context menu + bool bShouldOpenContextMenu = false; + bool bLastFrameWasInvisible = true; + + // Drag and drop + int64_t ItemUnderMouse = 0; + int SceneNodeDragAndDropTargetIndex = -1; + std::unordered_map SceneNodeDragAndDropTargets; + DragAndDropTarget* GetSceneNodeDragAndDropTarget(FENaiveSceneGraphNode* NodeToFind); + + bool bSceneNodeTargetsDirty = true; + static bool SceneNodeDragAndDropCallback(FEObject* Object, void** SceneNodeTarget) + { + if (Object == nullptr || SceneNodeTarget == nullptr || Object->GetType() != FE_SCENE_GRAPH_NODE) + return false; + + FENaiveSceneGraphNode* NodeTarget = reinterpret_cast(SceneNodeTarget); + FENaiveSceneGraphNode* SceneEntity = reinterpret_cast(Object); + + FEScene* CurrentScene = SceneEntity->GetEntity()->GetParentScene(); + return CurrentScene->SceneGraph.MoveNode(SceneEntity->GetObjectID(), NodeTarget->GetObjectID()); + } + + //void UpdateSceneNodeDragAndDropTargets(); + + // Rendering and initialization. + void Render(); + void RenderSceneGraph(); + ImRect RenderSubTree(FENaiveSceneGraphNode* SubTreeRoot); + void Clear(); + void InitializeResources(); + + bool bBackgroundColorSwitch = true; + ImRect SceneGraphBackgroundRect; + + // Colors + ImVec4 EvenNodeBackgroundColor = ImVec4(50.0f / 255.0f, 50.0f / 255.0f, 50.0f / 255.0f, 1.0f); + ImVec4 OddNodeBackgroundColor = ImVec4(90.0f / 255.0f, 90.0f / 255.0f, 90.0f / 255.0f, 1.0f); + ImVec4 VerticalTreeLineColor = ImVec4(0.5f, 140.0f / 255.0f, 170.0f / 255.0f, 1.0f); + + // Layout + float VerticalTreeLineXOffset = -6.5f; // Used to nicely line up with the arrow symbol. + float VerticalTreeLineYOffset = -8.5f; // Used to nicely line up with the arrow symbol. + float HorizontalTreeLineLength = 32.0f; // Used to make sure the horizontal line is "touching" the arrow symbol of children. + float HorizontalTreeLineLengthParentOffset = -15.6f; // Used to create small gap for nodes that have children. + float BackgroundColorYShift = -2.0f; // Used to shift background color of the scene graph tree. + float BackgroundHeightModifier = -4.0f; // Modifier of the scene graph background height. + bool bUseNodeBackground = true; // Do we want to render the background of the scene graph tree? + bool bIndintationAwareNodeBackground = false; // Used to make sure the background of the scene graph tree is indented properly. + + void RenderNodeBackground(); + + std::string SceneGraphNodeHoveredID = ""; +public: + SINGLETON_PUBLIC_PART(FEEditorSceneGraphWindow) +}; + +#define SCENE_GRAPH_WINDOW FEEditorSceneGraphWindow::GetInstance() \ No newline at end of file diff --git a/FEEditorSubWindows/selectPopups.cpp b/EditorWindows/SelectPopups.cpp similarity index 72% rename from FEEditorSubWindows/selectPopups.cpp rename to EditorWindows/SelectPopups.cpp index eaa4bd2..5bf0b91 100644 --- a/FEEditorSubWindows/selectPopups.cpp +++ b/EditorWindows/SelectPopups.cpp @@ -1,10 +1,9 @@ -#include "selectPopups.h" +#include "SelectPopups.h" -SelectFeObjectPopUp* SelectFeObjectPopUp::Instance = nullptr; -bool SelectFeObjectPopUp::ControlButtonPressed = false; -bool SelectFeObjectPopUp::bOneObjectSelectonMode = true; +bool SelectFEObjectPopUp::ControlButtonPressed = false; +bool SelectFEObjectPopUp::bOneObjectSelectonMode = true; -SelectFeObjectPopUp::SelectFeObjectPopUp() +SelectFEObjectPopUp::SelectFEObjectPopUp() { PopupCaption = "Select"; IconButton = new ImGuiImageButton(nullptr); @@ -20,17 +19,35 @@ SelectFeObjectPopUp::SelectFeObjectPopUp() CancelButton->SetSize(ImVec2(140, 24)); CancelButton->SetPosition(ImVec2(660, 35)); - ENGINE.AddKeyCallback(SelectFeObjectPopUp::KeyButtonCallback); + INPUT.AddKeyCallback(SelectFEObjectPopUp::KeyButtonCallback); } -SelectFeObjectPopUp::~SelectFeObjectPopUp() +SelectFEObjectPopUp::~SelectFEObjectPopUp() { delete SelectButton; delete CancelButton; delete IconButton; } -void SelectFeObjectPopUp::Show(const FE_OBJECT_TYPE Type, void(*CallBack)(std::vector), FEObject* HighlightedObject, const std::vector CustomList) +void SelectFEObjectPopUp::FilterOutTags(std::vector& FEObjectIDList, std::vector ListOfTagsToFilterOut) +{ + for (int i = 0; i < FEObjectIDList.size(); i++) + { + FEObject* CurrentObject = OBJECT_MANAGER.GetFEObject(FEObjectIDList[i]); + + for (size_t j = 0; j < ListOfTagsToFilterOut.size(); j++) + { + if (CurrentObject->GetTag() == ListOfTagsToFilterOut[j]) + { + FEObjectIDList.erase(FEObjectIDList.begin() + i); + i--; + break; + } + } + } +} + +void SelectFEObjectPopUp::Show(const FE_OBJECT_TYPE Type, void(*CallBack)(std::vector), FEObject* HighlightedObject, const std::vector CustomList) { CurrenType = Type; if (CurrenType == FE_NULL) @@ -50,48 +67,42 @@ void SelectFeObjectPopUp::Show(const FE_OBJECT_TYPE Type, void(*CallBack)(std::v { case FE_TEXTURE: { - TempList = RESOURCE_MANAGER.GetTextureList(); - TempList.insert(TempList.begin(), RESOURCE_MANAGER.NoTexture->GetObjectID()); - + TempList = RESOURCE_MANAGER.GetTextureIDList(); break; } case FE_MESH: { - TempList = RESOURCE_MANAGER.GetMeshList(); - - const std::vector StandardMeshList = RESOURCE_MANAGER.GetStandardMeshList(); - for (size_t i = 0; i < StandardMeshList.size(); i++) - { - if (EDITOR_INTERNAL_RESOURCES.IsInInternalEditorList(RESOURCE_MANAGER.GetMesh(StandardMeshList[i]))) - continue; - - TempList.push_back(StandardMeshList[i]); - } - + TempList = RESOURCE_MANAGER.GetMeshIDList(); break; } case FE_MATERIAL: { - TempList = RESOURCE_MANAGER.GetMaterialList(); - TempList.insert(TempList.begin(), "18251A5E0F08013Z3939317U"/*"SolidColorMaterial"*/); - + TempList = RESOURCE_MANAGER.GetMaterialIDList(); break; } case FE_GAMEMODEL: { - TempList = RESOURCE_MANAGER.GetGameModelList(); + TempList = RESOURCE_MANAGER.GetGameModelIDList(); break; } case FE_PREFAB: { - TempList = RESOURCE_MANAGER.GetPrefabList(); + TempList = RESOURCE_MANAGER.GetPrefabIDList(); break; } } + + FilterOutTags(TempList, std::vector{ ENGINE_RESOURCE_TAG, EDITOR_RESOURCE_TAG}); + + if (CurrenType == FE_TEXTURE) + TempList.insert(TempList.begin(), RESOURCE_MANAGER.NoTexture->GetObjectID()); + + if (CurrenType == FE_MATERIAL) + TempList.insert(TempList.begin(), "18251A5E0F08013Z3939317U"/*"SolidColorMaterial"*/); for (size_t i = 0; i < TempList.size(); i++) ItemsList.push_back(OBJECT_MANAGER.GetFEObject(TempList[i])); @@ -118,14 +129,14 @@ void SelectFeObjectPopUp::Show(const FE_OBJECT_TYPE Type, void(*CallBack)(std::v } } -void SelectFeObjectPopUp::Render() +void SelectFEObjectPopUp::Render() { ImGuiModalPopup::Render(); ImGui::SetNextWindowSize(ImVec2(128 * 7, 800)); if (ImGui::BeginPopupModal(PopupCaption.c_str(), nullptr, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove)) { - ImGui::SetWindowPos(ImVec2(ENGINE.GetWindowWidth() / 2.0f - ImGui::GetWindowWidth() / 2.0f, ENGINE.GetWindowHeight() / 2.0f - ImGui::GetWindowHeight() / 2.0f)); + ImGui::SetWindowPos(ImVec2(APPLICATION.GetMainWindow()->GetWidth() / 2.0f - ImGui::GetWindowWidth() / 2.0f, APPLICATION.GetMainWindow()->GetHeight() / 2.0f - ImGui::GetWindowHeight() / 2.0f)); ImGui::SetCursorPosX(10); ImGui::SetCursorPosY(40); ImGui::Text("Filter: "); @@ -212,7 +223,6 @@ void SelectFeObjectPopUp::Render() SelectButton->Render(); if (SelectButton->IsClicked()) { - AddToSelected(OBJECT_MANAGER.GetFEObject(FilteredItemsList[IndexUnderMouse]->GetObjectID())); OnSelectAction(); Close(); @@ -228,7 +238,7 @@ void SelectFeObjectPopUp::Render() } } -void SelectFeObjectPopUp::OnSelectAction() +void SelectFEObjectPopUp::OnSelectAction() { if (CallBack != nullptr) { @@ -237,7 +247,7 @@ void SelectFeObjectPopUp::OnSelectAction() } } -void SelectFeObjectPopUp::Close() +void SelectFEObjectPopUp::Close() { ImGuiModalPopup::Close(); IndexUnderMouse = -1; @@ -245,7 +255,7 @@ void SelectFeObjectPopUp::Close() SelectedObjects.clear(); } -void SelectFeObjectPopUp::KeyButtonCallback(const int Key, int Scancode, const int Action, int Mods) +void SelectFEObjectPopUp::KeyButtonCallback(const int Key, int Scancode, const int Action, int Mods) { if ((Key == GLFW_KEY_LEFT_CONTROL || Action == GLFW_KEY_RIGHT_CONTROL) && Action == GLFW_RELEASE) { @@ -257,7 +267,7 @@ void SelectFeObjectPopUp::KeyButtonCallback(const int Key, int Scancode, const i } } -bool SelectFeObjectPopUp::IsSelected(const FEObject* Object) const +bool SelectFEObjectPopUp::IsSelected(const FEObject* Object) const { for (size_t i = 0; i < SelectedObjects.size(); i++) { @@ -268,19 +278,19 @@ bool SelectFeObjectPopUp::IsSelected(const FEObject* Object) const return false; } -bool SelectFeObjectPopUp::IsOneObjectSelectonMode() +bool SelectFEObjectPopUp::IsOneObjectSelectonMode() { return bOneObjectSelectonMode; } -void SelectFeObjectPopUp::SetOneObjectSelectonMode(const bool NewValue) +void SelectFEObjectPopUp::SetOneObjectSelectonMode(const bool NewValue) { bOneObjectSelectonMode = NewValue; if (bOneObjectSelectonMode && SelectedObjects.size() > 1) SelectedObjects.resize(1); } -void SelectFeObjectPopUp::AddToSelected(FEObject* Object) +void SelectFEObjectPopUp::AddToSelected(FEObject* Object) { if (IsSelected(Object)) return; diff --git a/FEEditorSubWindows/selectPopups.h b/EditorWindows/SelectPopups.h similarity index 73% rename from FEEditorSubWindows/selectPopups.h rename to EditorWindows/SelectPopups.h index e3e99d9..0c118a9 100644 --- a/FEEditorSubWindows/selectPopups.h +++ b/EditorWindows/SelectPopups.h @@ -1,10 +1,10 @@ #pragma once -#include "resizeTexturePopup.h" +#include "ResizeTexturePopup.h" -class SelectFeObjectPopUp : public ImGuiModalPopup +class SelectFEObjectPopUp : public ImGuiModalPopup { - SINGLETON_PRIVATE_PART(SelectFeObjectPopUp) + SINGLETON_PRIVATE_PART(SelectFEObjectPopUp) int IndexUnderMouse = -1; FEObject* HighlightedObject = nullptr; @@ -28,8 +28,10 @@ class SelectFeObjectPopUp : public ImGuiModalPopup static bool bOneObjectSelectonMode; bool IsSelected(const FEObject* Object) const; void AddToSelected(FEObject* Object); + + void FilterOutTags(std::vector& FEObjectIDList, std::vector ListOfTagsToFilterOut); public: - SINGLETON_PUBLIC_PART(SelectFeObjectPopUp) + SINGLETON_PUBLIC_PART(SelectFEObjectPopUp) void Show(FE_OBJECT_TYPE Type, void(*CallBack)(std::vector), FEObject* HighlightedObject = nullptr, std::vector CustomList = std::vector()); void Close() override; @@ -37,4 +39,6 @@ class SelectFeObjectPopUp : public ImGuiModalPopup bool IsOneObjectSelectonMode(); void SetOneObjectSelectonMode(bool NewValue); -}; \ No newline at end of file +}; + +#define SELECT_FEOBJECT_POPUP SelectFEObjectPopUp::GetInstance() \ No newline at end of file diff --git a/FEEditorSubWindows/shaderEditorWindow.cpp b/EditorWindows/ShaderEditorWindow.cpp similarity index 88% rename from FEEditorSubWindows/shaderEditorWindow.cpp rename to EditorWindows/ShaderEditorWindow.cpp index ef3e0be..db8400d 100644 --- a/FEEditorSubWindows/shaderEditorWindow.cpp +++ b/EditorWindows/ShaderEditorWindow.cpp @@ -1,8 +1,7 @@ -#include "shaderEditorWindow.h" +#include "ShaderEditorWindow.h" +#include "../FEEditor.h" -shaderDebugWindow* shaderDebugWindow::Instance = nullptr; - -shaderDebugWindow::shaderDebugWindow() +ShaderDebugWindow::ShaderDebugWindow() { Flags = ImGuiWindowFlags_HorizontalScrollbar | ImGuiWindowFlags_MenuBar; Editor.SetShowWhitespaces(false); @@ -14,7 +13,7 @@ shaderDebugWindow::shaderDebugWindow() Editor.SetColorizerEnable(false); } -shaderDebugWindow::~shaderDebugWindow() +ShaderDebugWindow::~ShaderDebugWindow() { delete CloseButton; delete UpdateButton; @@ -22,7 +21,7 @@ shaderDebugWindow::~shaderDebugWindow() ShaderToWorkWith = nullptr; } -void shaderDebugWindow::Show(FEShader* Shader, std::string Caption) +void ShaderDebugWindow::Show(FEShader* Shader, std::string Caption) { bUpdateNeeded = true; ShaderToWorkWith = Shader; @@ -39,7 +38,7 @@ void shaderDebugWindow::Show(FEShader* Shader, std::string Caption) FEImGuiWindow::Show(); } -void shaderDebugWindow::Render() +void ShaderDebugWindow::Render() { FEImGuiWindow::Render(); @@ -129,15 +128,11 @@ void shaderDebugWindow::Render() bUpdateNeeded = true; } - //ImGui::GetCurrentWindow()->Size = ImVec2(ImGui::GetCurrentWindow()->Size.x, ImGui::GetCurrentWindow()->Size.y - 150); - Editor.Render("TextEditor", ImVec2(ImGui::GetCurrentWindow()->Size.x, 250)); - //ImGui::GetCurrentWindow()->Size = ImVec2(ImGui::GetCurrentWindow()->Size.x, ImGui::GetCurrentWindow()->Size.y + 150); + Editor.Render("TextEditor", ImVec2(FE_IMGUI_WINDOW_MANAGER.GetCurrentWindowImpl()->Size.x, 250)); FEImGuiWindow::OnRenderEnd(); } -shaderEditorWindow* shaderEditorWindow::Instance = nullptr; - -shaderEditorWindow::shaderEditorWindow() +ShaderEditorWindow::ShaderEditorWindow() { Flags = ImGuiWindowFlags_HorizontalScrollbar | ImGuiWindowFlags_MenuBar; CurrentEditor = &VertexShaderEditor; @@ -163,12 +158,12 @@ shaderEditorWindow::shaderEditorWindow() CloseButton->SetHoveredColor((ImVec4)ImColor(0.8f, 0.16f, 0.16f)); } -shaderEditorWindow::~shaderEditorWindow() +ShaderEditorWindow::~ShaderEditorWindow() { delete CompileButton; } -void shaderEditorWindow::Show(FEShader* Shader) +void ShaderEditorWindow::Show(FEShader* Shader) { ShaderToEdit = Shader; std::string TempCaption = "Edit shader: "; @@ -257,7 +252,7 @@ void shaderEditorWindow::Show(FEShader* Shader) } } -void shaderEditorWindow::Render() +void ShaderEditorWindow::Render() { FEImGuiWindow::Render(); @@ -383,7 +378,8 @@ void shaderEditorWindow::Render() } ImGui::PopStyleColor(); - CurrentEditor->Render("Editor", ImVec2(ImGui::GetCurrentWindow()->Size.x - 40, ImGui::GetCurrentWindow()->Size.y - 190)); + ImGuiWindow* CurrentWindow = FE_IMGUI_WINDOW_MANAGER.GetCurrentWindowImpl(); + CurrentEditor->Render("Editor", ImVec2(CurrentWindow->Size.x - 40, CurrentWindow->Size.y - 190)); const float CurrentYPosition = ImGui::GetCursorPosY() + 15; CompileButton->SetPosition(ImVec2(ImGui::GetWindowWidth() / 2.0f - ImGui::GetWindowWidth() / 8.0f - 120.0f / 2.0f, CurrentYPosition)); @@ -401,7 +397,8 @@ void shaderEditorWindow::Render() bComputeShaderUsed ? ComputeShaderEditor.GetText().c_str() : nullptr, true); - DummyShader->AddParametersFromShader(ShaderToEdit); + // TODO: Verify if this is needed. + DummyShader->AddUniformsFromShader(ShaderToEdit); std::string Errors = DummyShader->GetCompilationErrors(); Errors += "\n"; @@ -423,13 +420,14 @@ void shaderEditorWindow::Render() bGeometryShaderUsed ? GeometryShaderEditor.GetText().c_str() : nullptr, bComputeShaderUsed ? ComputeShaderEditor.GetText().c_str() : nullptr); - ReCompiledShader->AddParametersFromShader(ShaderToEdit); + // TODO: Verify if this is needed. + ReCompiledShader->AddUniformsFromShader(ShaderToEdit); RESOURCE_MANAGER.ReplaceShader(ShaderToEdit->GetObjectID(), ReCompiledShader); if (ShaderToEdit->IsDebugRequest()) { - shaderDebugWindow::getInstance().Show(ShaderToEdit, "Shader debug info"); + ShaderDebugWindow::GetInstance().Show(ShaderToEdit, "Shader debug info"); } } } @@ -444,9 +442,9 @@ void shaderEditorWindow::Render() FEImGuiWindow::OnRenderEnd(); } -void shaderEditorWindow::ReplaceShader(FEShader* OldShader, FEShader* NewShader) +void ShaderEditorWindow::ReplaceShader(FEShader* OldShader, FEShader* NewShader) { - std::vector MaterialList = RESOURCE_MANAGER.GetMaterialList(); + std::vector MaterialList = RESOURCE_MANAGER.GetMaterialIDList(); for (size_t i = 0; i < MaterialList.size(); i++) { FEMaterial* TempMaterial = RESOURCE_MANAGER.GetMaterial(MaterialList[i]); @@ -456,7 +454,7 @@ void shaderEditorWindow::ReplaceShader(FEShader* OldShader, FEShader* NewShader) } } - MaterialList = RESOURCE_MANAGER.GetStandardMaterialList(); + MaterialList = RESOURCE_MANAGER.GetEnginePrivateMaterialIDList(); for (size_t i = 0; i < MaterialList.size(); i++) { FEMaterial* TempMaterial = RESOURCE_MANAGER.GetMaterial(MaterialList[i]); @@ -466,13 +464,18 @@ void shaderEditorWindow::ReplaceShader(FEShader* OldShader, FEShader* NewShader) } } - const std::vector TerrainList = SCENE.GetTerrainList(); - for (size_t i = 0; i < TerrainList.size(); i++) + if (EDITOR.GetFocusedScene() != nullptr) { - FETerrain* TempTerrain = SCENE.GetTerrain(TerrainList[i]); - if (TempTerrain->Shader->GetNameHash() == OldShader->GetNameHash()) + FEScene* CurrentScene = EDITOR.GetFocusedScene(); + const std::vector TerrainList = CurrentScene->GetEntityIDListWithComponent(); + for (size_t i = 0; i < TerrainList.size(); i++) { - TempTerrain->Shader = NewShader; + FEEntity* TempTerrain = CurrentScene->GetEntity(TerrainList[i]); + FETerrainComponent& TerrainComponent = TempTerrain->GetComponent(); + if (TerrainComponent.Shader->GetNameHash() == OldShader->GetNameHash()) + { + TerrainComponent.Shader = NewShader; + } } } } \ No newline at end of file diff --git a/FEEditorSubWindows/shaderEditorWindow.h b/EditorWindows/ShaderEditorWindow.h similarity index 80% rename from FEEditorSubWindows/shaderEditorWindow.h rename to EditorWindows/ShaderEditorWindow.h index 4d2f17d..82a1c85 100644 --- a/FEEditorSubWindows/shaderEditorWindow.h +++ b/EditorWindows/ShaderEditorWindow.h @@ -1,11 +1,11 @@ #pragma once -#include "editPopups.h" +#include "EditPopups.h" #pragma warning (disable: 4724) -class shaderDebugWindow : public FEImGuiWindow +class ShaderDebugWindow : public FEImGuiWindow { - SINGLETON_PRIVATE_PART(shaderDebugWindow) + SINGLETON_PRIVATE_PART(ShaderDebugWindow) TextEditor Editor; ImGuiButton* CloseButton = nullptr; @@ -17,15 +17,15 @@ class shaderDebugWindow : public FEImGuiWindow std::vector>* Data = nullptr; std::vector> DataDump; public: - SINGLETON_PUBLIC_PART(shaderDebugWindow) + SINGLETON_PUBLIC_PART(ShaderDebugWindow) void Show(FEShader* Shader, std::string Caption); void Render() override; }; -class shaderEditorWindow : public FEImGuiWindow +class ShaderEditorWindow : public FEImGuiWindow { - SINGLETON_PRIVATE_PART(shaderEditorWindow) + SINGLETON_PRIVATE_PART(ShaderEditorWindow) FEShader* ShaderToEdit = nullptr; FEShader* DummyShader = nullptr; @@ -50,7 +50,7 @@ class shaderEditorWindow : public FEImGuiWindow void ReplaceShader(FEShader* OldShader, FEShader* NewShader); public: - SINGLETON_PUBLIC_PART(shaderEditorWindow) + SINGLETON_PUBLIC_PART(ShaderEditorWindow) void Show(FEShader* Shader); diff --git a/FEDearImguiWrapper/FEDearImguiWrapper.cpp b/FEDearImguiWrapper/FEDearImguiWrapper.cpp index 13c8683..0bd8ac3 100644 --- a/FEDearImguiWrapper/FEDearImguiWrapper.cpp +++ b/FEDearImguiWrapper/FEDearImguiWrapper.cpp @@ -1,13 +1,11 @@ #include "FEDearImguiWrapper.h" -WindowsManager* WindowsManager::Instance = nullptr; - ImGuiModalPopup::ImGuiModalPopup() { PopupCaption = ""; bShouldOpen = false; bOpened = false; - WindowsManager::getInstance().RegisterPopup(this); + FE_IMGUI_WINDOW_MANAGER.RegisterPopup(this); } void ImGuiModalPopup::Show() @@ -317,11 +315,12 @@ FEImGuiWindow::FEImGuiWindow() Position = ImVec2(0.0f, 0.0f); Size = ImVec2(100.0f, 100.0f); bVisible = false; - WindowsManager::getInstance().RegisterWindow(this); + FE_IMGUI_WINDOW_MANAGER.RegisterWindow(this); } FEImGuiWindow::~FEImGuiWindow() { + FE_IMGUI_WINDOW_MANAGER.UnRegisterWindow(this); } void FEImGuiWindow::Show() @@ -342,6 +341,15 @@ bool FEImGuiWindow::IsMouseHovered() const return false; } +ImGuiWindow* WindowsManager::GetCurrentWindowImpl() +{ + ImGuiContext* Context = ImGui::GetCurrentContext(); + if (Context == nullptr) + return nullptr; + + return Context->CurrentWindow; +} + void FEImGuiWindow::Render() { if (bVisible) @@ -353,10 +361,15 @@ void FEImGuiWindow::Render() ImGui::SetNextWindowSize(Size); bWasClosedLastFrame = false; - ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 2); - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(15, 15)); + + if (GetBorderSize() != 0.0f) + ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, GetBorderSize()); + + if (GetPadding().x != 0.0f || GetPadding().y != 0.0f) + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(GetPadding().x, GetPadding().y)); + ImGui::Begin(Caption, nullptr, Flags); - Window = ImGui::GetCurrentWindow(); + Window = FE_IMGUI_WINDOW_MANAGER.GetCurrentWindowImpl(); } } @@ -366,8 +379,13 @@ void FEImGuiWindow::OnRenderEnd() { if (!Window->Collapsed) Size = ImGui::GetWindowSize(); - ImGui::PopStyleVar(); - ImGui::PopStyleVar(); + + if (GetBorderSize() != 0.0f) + ImGui::PopStyleVar(); + + if (GetPadding().x != 0.0f || GetPadding().y != 0.0f) + ImGui::PopStyleVar(); + ImGui::End(); } } @@ -382,8 +400,13 @@ void FEImGuiWindow::Close() if (bVisible) { bVisible = false; - ImGui::PopStyleVar(); - ImGui::PopStyleVar(); + + if (GetBorderSize() != 0.0f) + ImGui::PopStyleVar(); + + if (GetPadding().x != 0.0f || GetPadding().y != 0.0f) + ImGui::PopStyleVar(); + ImGui::End(); } } @@ -393,11 +416,36 @@ void FEImGuiWindow::SetCaption(const std::string NewCaption) strcpy_s(Caption, NewCaption.size() + 1, NewCaption.c_str()); } +ImGuiWindow* FEImGuiWindow::GetWindow() const +{ + return Window; +} + void FEImGuiWindow::SetVisible(bool NewValue) { bVisible = NewValue; } +float FEImGuiWindow::GetBorderSize() const +{ + return BorderSize; +} + +void FEImGuiWindow::SetBorderSize(float NewValue) +{ + BorderSize = NewValue; +} + +glm::vec2 FEImGuiWindow::GetPadding() const +{ + return Padding; +} + +void FEImGuiWindow::SetPadding(glm::vec2 NewValue) +{ + Padding = NewValue; +} + WindowsManager::WindowsManager() { } @@ -407,6 +455,18 @@ void WindowsManager::RegisterWindow(FEImGuiWindow* Window) Windows.push_back(Window); } +void WindowsManager::UnRegisterWindow(FEImGuiWindow* Window) +{ + for (size_t i = 0; i < Windows.size(); i++) + { + if (Windows[i] == Window) + { + Windows.erase(Windows.begin() + i); + break; + } + } +} + void WindowsManager::RegisterPopup(ImGuiModalPopup* Popup) { PopUps.push_back(Popup); @@ -619,8 +679,9 @@ void FERangeConfigurator::NormalizeRanges() void FERangeConfigurator::InputCalculations() { - const float MouseXWindows = ImGui::GetIO().MousePos.x - ImGui::GetCurrentWindow()->Pos.x; - const float MouseYWindows = ImGui::GetIO().MousePos.y - ImGui::GetCurrentWindow()->Pos.y; + ImGuiWindow* CurrentWindow = FE_IMGUI_WINDOW_MANAGER.GetCurrentWindowImpl(); + const float MouseXWindows = ImGui::GetIO().MousePos.x - CurrentWindow->Pos.x; + const float MouseYWindows = ImGui::GetIO().MousePos.y - CurrentWindow->Pos.y; for (size_t i = 0; i < Ranges.size(); i++) { @@ -638,13 +699,13 @@ void FERangeConfigurator::InputCalculations() break; } - ImGui::GetCurrentWindow()->Flags = ImGuiWindowFlags_None; + CurrentWindow->Flags = ImGuiWindowFlags_None; for (size_t i = 0; i < Ranges.size(); i++) { const float NeedToAdd = Ranges[i].Scroller.GetLastFrameDelta() / Size.x; if (NeedToAdd != 0.0f) { - ImGui::GetCurrentWindow()->Flags = ImGuiWindowFlags_NoMove; + CurrentWindow->Flags = ImGuiWindowFlags_NoMove; if (Ranges[i + 1].RangeSpan - NeedToAdd < 0.001f || Ranges[i].RangeSpan + NeedToAdd < 0.001f) break; @@ -662,8 +723,9 @@ void FERangeConfigurator::Render() NormalizeRanges(); InputCalculations(); - ScreenX = ImGui::GetCurrentWindow()->Pos.x + Position.x; - ScreenY = ImGui::GetCurrentWindow()->Pos.y + Position.y; + ImGuiWindow* CurrentWindow = FE_IMGUI_WINDOW_MANAGER.GetCurrentWindowImpl(); + ScreenX = CurrentWindow->Pos.x + Position.x; + ScreenY = CurrentWindow->Pos.y + Position.y; float BeginX = ScreenX; for (size_t i = 0; i < Ranges.size(); i++) @@ -744,8 +806,6 @@ void FERangeConfigurator::Clear() Ranges.clear(); } -MessagePopUp* MessagePopUp::Instance = nullptr; - MessagePopUp::MessagePopUp() {}; void MessagePopUp::Show(const std::string NewWindowCaption, const std::string MessageToShow) @@ -762,7 +822,7 @@ void MessagePopUp::Render() ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(15, 15)); if (ImGui::BeginPopupModal(PopupCaption.c_str(), nullptr, ImGuiWindowFlags_AlwaysAutoResize)) { - ImGui::SetWindowPos(ImVec2(ENGINE.GetWindowWidth() / 2.0f - ImGui::GetWindowWidth() / 2.0f, ENGINE.GetWindowHeight() / 2.0f - ImGui::GetWindowHeight() / 2.0f)); + ImGui::SetWindowPos(ImVec2(APPLICATION.GetMainWindow()->GetWidth() / 2.0f - ImGui::GetWindowWidth() / 2.0f, APPLICATION.GetMainWindow()->GetHeight() / 2.0f - ImGui::GetWindowHeight() / 2.0f)); ImGui::Text(Message.c_str()); ImGui::SetCursorPosX(ImGui::GetWindowWidth() / 2.0f - 120.0f / 2.0f); if (ImGui::Button("Ok", ImVec2(120, 0))) @@ -835,8 +895,9 @@ void FEArrowScroller::SetSelected(const bool NewValue) void FEArrowScroller::Render() { - const float MouseXWindows = ImGui::GetIO().MousePos.x - ImGui::GetCurrentWindow()->Pos.x; - const float MouseYWindows = ImGui::GetIO().MousePos.y - ImGui::GetCurrentWindow()->Pos.y; + ImGuiWindow* CurrentWindow = FE_IMGUI_WINDOW_MANAGER.GetCurrentWindowImpl(); + const float MouseXWindows = ImGui::GetIO().MousePos.x - CurrentWindow->Pos.x; + const float MouseYWindows = ImGui::GetIO().MousePos.y - CurrentWindow->Pos.y; bMouseHover = false; if (MouseXWindows >= Area.left && MouseXWindows < Area.right && @@ -848,14 +909,14 @@ void FEArrowScroller::Render() if (!bMouseHover && bWindowFlagWasAdded) { bWindowFlagWasAdded = false; - ImGui::GetCurrentWindow()->Flags = OriginalWindowFlags; + CurrentWindow->Flags = OriginalWindowFlags; } - if (!(ImGui::GetCurrentWindow()->Flags & ImGuiWindowFlags_NoMove) && bMouseHover) + if (!(CurrentWindow->Flags & ImGuiWindowFlags_NoMove) && bMouseHover) { bWindowFlagWasAdded = true; - OriginalWindowFlags = ImGui::GetCurrentWindow()->Flags; - ImGui::GetCurrentWindow()->Flags |= ImGuiWindowFlags_NoMove; + OriginalWindowFlags = CurrentWindow->Flags; + CurrentWindow->Flags |= ImGuiWindowFlags_NoMove; } if (ImGui::GetIO().MouseClicked[0]) @@ -896,21 +957,21 @@ void FEArrowScroller::Render() if (bHorizontal) { - P1 = ImVec2(ImGui::GetCurrentWindow()->Pos.x + Area.left, - ImGui::GetCurrentWindow()->Pos.y + Area.top); - P2 = ImVec2(ImGui::GetCurrentWindow()->Pos.x + Area.right, - ImGui::GetCurrentWindow()->Pos.y + Area.top); - P3 = ImVec2(ImGui::GetCurrentWindow()->Pos.x + Area.left + (Area.right - Area.left) / 2.0f, - ImGui::GetCurrentWindow()->Pos.y + Area.bottom); + P1 = ImVec2(CurrentWindow->Pos.x + Area.left, + CurrentWindow->Pos.y + Area.top); + P2 = ImVec2(CurrentWindow->Pos.x + Area.right, + CurrentWindow->Pos.y + Area.top); + P3 = ImVec2(CurrentWindow->Pos.x + Area.left + (Area.right - Area.left) / 2.0f, + CurrentWindow->Pos.y + Area.bottom); } else { - P1 = ImVec2(ImGui::GetCurrentWindow()->Pos.x + Area.left, - ImGui::GetCurrentWindow()->Pos.y + Area.top); - P2 = ImVec2(ImGui::GetCurrentWindow()->Pos.x + Area.left, - ImGui::GetCurrentWindow()->Pos.y + Area.bottom); - P3 = ImVec2(ImGui::GetCurrentWindow()->Pos.x + Area.right, - ImGui::GetCurrentWindow()->Pos.y + Area.top + (Area.right - Area.left) / 2.0f); + P1 = ImVec2(CurrentWindow->Pos.x + Area.left, + CurrentWindow->Pos.y + Area.top); + P2 = ImVec2(CurrentWindow->Pos.x + Area.left, + CurrentWindow->Pos.y + Area.bottom); + P3 = ImVec2(CurrentWindow->Pos.x + Area.right, + CurrentWindow->Pos.y + Area.top + (Area.right - Area.left) / 2.0f); } if (IsSelected()) diff --git a/FEDearImguiWrapper/FEDearImguiWrapper.h b/FEDearImguiWrapper/FEDearImguiWrapper.h index 3aebf94..d3a4468 100644 --- a/FEDearImguiWrapper/FEDearImguiWrapper.h +++ b/FEDearImguiWrapper/FEDearImguiWrapper.h @@ -23,6 +23,11 @@ class WindowsManager void CloseAllWindows() const; void RenderAllWindows() const; + + void UnRegisterWindow(FEImGuiWindow* Window); + + // FIXME: Currently using internal ImGui functions. Need to find an alternative approach. + ImGuiWindow* GetCurrentWindowImpl(); private: SINGLETON_PRIVATE_PART(WindowsManager) @@ -30,7 +35,7 @@ class WindowsManager std::vector Windows; }; -#define FE_IMGUI_WINDOW_MANAGER WindowsManager::getInstance() +#define FE_IMGUI_WINDOW_MANAGER WindowsManager::GetInstance() class ImGuiModalPopup { @@ -162,6 +167,9 @@ class FEImGuiWindow bool bWasClosedLastFrame = false; FEImGuiWindow(); ImGuiWindow* Window = nullptr; + + float BorderSize = 2.0f; + glm::vec2 Padding = glm::vec2(15.0f, 15.0f); public: virtual ~FEImGuiWindow(); virtual void Show(); @@ -175,6 +183,14 @@ class FEImGuiWindow bool IsMouseHovered() const; virtual void SetCaption(std::string NewCaption); + + ImGuiWindow* GetWindow() const; + + float GetBorderSize() const; + void SetBorderSize(float NewValue); + + glm::vec2 GetPadding() const; + void SetPadding(glm::vec2 NewValue); }; class FEArrowScroller diff --git a/FEEditor.cpp b/FEEditor.cpp index 7fa8001..a8a4595 100644 --- a/FEEditor.cpp +++ b/FEEditor.cpp @@ -1,83 +1,11 @@ #include "FEEditor.h" -FEEditor* FEEditor::Instance = nullptr; -ImGuiWindow* FEEditor::SceneWindow = nullptr; -FEEntity* FEEditor::EntityToModify = nullptr; -FEObject* FEEditor::ItemInFocus = nullptr; - -bool SceneWindowDragAndDropCallBack(FEObject* Object, void** UserData) -{ - if (Object->GetType() == FE_PREFAB) - { - FEEntity* NewEntity = SCENE.AddEntity(RESOURCE_MANAGER.GetPrefab(Object->GetObjectID())); - NewEntity->Transform.SetPosition(ENGINE.GetCamera()->GetPosition() + ENGINE.GetCamera()->GetForward() * 10.0f); - SELECTED.SetSelected(NewEntity); - PROJECT_MANAGER.GetCurrent()->SetModified(true); - - return true; - } - - return false; -} - -static void CreateNewInstancedEntityCallBack(const std::vector SelectionsResult) -{ - if (SelectionsResult.size() == 1 && SelectionsResult[0]->GetType() == FE_PREFAB) - { - FEPrefab* SelectedPrefab = RESOURCE_MANAGER.GetPrefab(SelectionsResult[0]->GetObjectID()); - if (SelectedPrefab == nullptr) - return; - - FEEntityInstanced* NewEntity = SCENE.AddEntityInstanced(SelectedPrefab); - NewEntity->Transform.SetPosition(ENGINE.GetCamera()->GetPosition() + ENGINE.GetCamera()->GetForward() * 10.0f); - SELECTED.SetSelected(NewEntity); - - PROJECT_MANAGER.GetCurrent()->SetModified(true); - } -} - -static void CreateNewEntityCallBack(const std::vector SelectionsResult) -{ - if (SelectionsResult.size() == 1 && SelectionsResult[0]->GetType() == FE_PREFAB) - { - FEPrefab* SelectedPrefab = RESOURCE_MANAGER.GetPrefab(SelectionsResult[0]->GetObjectID()); - if (SelectedPrefab == nullptr) - return; - - FEEntity* NewEntity = SCENE.AddEntity(SelectedPrefab); - NewEntity->Transform.SetPosition(ENGINE.GetCamera()->GetPosition() + ENGINE.GetCamera()->GetForward() * 10.0f); - SELECTED.SetSelected(NewEntity); - - PROJECT_MANAGER.GetCurrent()->SetModified(true); - } -} - -void FEEditor::ChangePrefabOfEntityCallBack(const std::vector SelectionsResult) -{ - if (EntityToModify == nullptr) - return; - - if (SelectionsResult.size() == 1 && SelectionsResult[0]->GetType() == FE_PREFAB) - { - FEPrefab* SelectedPrefab = RESOURCE_MANAGER.GetPrefab(SelectionsResult[0]->GetObjectID()); - if (SelectedPrefab == nullptr) - return; - - EntityToModify->Prefab = SelectedPrefab; - } -} - FEEditor::FEEditor() { - ENGINE.SetRenderTargetMode(FE_CUSTOM_MODE); - ImGuiIO& io = ImGui::GetIO(); - io.ConfigWindowsMoveFromTitleBarOnly = true; - - if (ENGINE.GetCamera()->GetCameraType() == 1) - ENGINE.RenderTargetCenterForCamera(reinterpret_cast(ENGINE.GetCamera())); - - strcpy_s(FilterForResourcesContentBrowser, ""); - strcpy_s(FilterForSceneEntities, ""); + ImGuiIO& IO = ImGui::GetIO(); + IO.ConfigWindowsMoveFromTitleBarOnly = true; + ENGINE.SetVsyncEnabled(true); + RESOURCE_MANAGER.AddTagThatWillPreventDeletion(EDITOR_RESOURCE_TAG); } FEEditor::~FEEditor() {} @@ -122,74 +50,83 @@ void FEEditor::SetMouseY(const double NewValue) MouseY = NewValue; } -std::string FEEditor::GetObjectNameInClipboard() +std::string FEEditor::GetSceneEntityIDInClipboard() { - return ObjectNameInClipboard; + return SceneEntityIDInClipboard; } -void FEEditor::SetObjectNameInClipboard(const std::string NewValue) +void FEEditor::SetSceneEntityIDInClipboard(const std::string NewValue) { - ObjectNameInClipboard = NewValue; + SceneEntityIDInClipboard = NewValue; } void FEEditor::MouseButtonCallback(const int Button, const int Action, int Mods) { - ItemInFocus = nullptr; - - if (ImGui::GetCurrentContext()->HoveredWindow != nullptr && FEEditor::SceneWindow != nullptr) - { - EDITOR.bSceneWindowHovered = ImGui::GetCurrentContext()->HoveredWindow->Name == EDITOR.SceneWindow->Name; - } - else - { - EDITOR.bSceneWindowHovered = false; - } - - if (FEEditor::SceneWindow == nullptr || !FEEditor::SceneWindow->Active) - EDITOR.bSceneWindowHovered = false; - if (Button == GLFW_MOUSE_BUTTON_1 && Action == GLFW_RELEASE) DRAG_AND_DROP_MANAGER.DropAction(); - if (ImGui::GetIO().WantCaptureMouse && !EDITOR.bSceneWindowHovered) + for (size_t i = 0; i < EDITOR.EditorSceneWindows.size(); i++) { - EDITOR.bIsCameraInputActive = false; - ENGINE.GetCamera()->SetIsInputActive(false); + EDITOR.EditorSceneWindows[i]->bWindowHovered = false; - return; - } + if (EDITOR.EditorSceneWindows[i]->Scene != EDITOR.GetFocusedScene()) + continue; - if (Button == GLFW_MOUSE_BUTTON_1 && Action == GLFW_PRESS) - { - bool bEditingTerrain = false; - if (SELECTED.GetTerrain() != nullptr) + if (ImGui::GetCurrentContext()->HoveredWindow != nullptr && EDITOR.EditorSceneWindows[i]->GetWindow() != nullptr) + EDITOR.EditorSceneWindows[i]->bWindowHovered = ImGui::GetCurrentContext()->HoveredWindow->Name == EDITOR.EditorSceneWindows[i]->GetWindow()->Name; + + FEEntity* CurrentMainCamera = CAMERA_SYSTEM.GetMainCamera(EDITOR.EditorSceneWindows[i]->Scene); + + if (ImGui::GetIO().WantCaptureMouse && !EDITOR.EditorSceneWindows[i]->bWindowHovered) { - bEditingTerrain = SELECTED.GetTerrain()->GetBrushMode() != FE_TERRAIN_BRUSH_NONE; + if (EDITOR.EditorSceneWindows[i]->Scene != nullptr && CurrentMainCamera != nullptr) + { + if (CurrentMainCamera != nullptr) + CurrentMainCamera->GetComponent().SetActive(false); + } + + continue; } - - if (!bEditingTerrain) + + if (Button == GLFW_MOUSE_BUTTON_2 && Action == GLFW_PRESS) { - SELECTED.DetermineEntityUnderMouse(EDITOR.GetMouseX(), EDITOR.GetMouseY()); - SELECTED.CheckForSelectionisNeeded = true; + if (CurrentMainCamera != nullptr) + CurrentMainCamera->GetComponent().SetActive(true); + } + else if (Button == GLFW_MOUSE_BUTTON_2 && Action == GLFW_RELEASE) + { + if (CurrentMainCamera != nullptr) + CurrentMainCamera->GetComponent().SetActive(false); } - - EDITOR.bLeftMousePressed = true; - } - else if (Button == GLFW_MOUSE_BUTTON_1 && Action == GLFW_RELEASE) - { - EDITOR.bLeftMousePressed = false; - GIZMO_MANAGER.DeactivateAllGizmo(); - } - if (Button == GLFW_MOUSE_BUTTON_2 && Action == GLFW_PRESS) - { - EDITOR.bIsCameraInputActive = true; - ENGINE.GetCamera()->SetIsInputActive(true); - } - else if (Button == GLFW_MOUSE_BUTTON_2 && Action == GLFW_RELEASE) - { - EDITOR.bIsCameraInputActive = false; - ENGINE.GetCamera()->SetIsInputActive(false); + if (Button == GLFW_MOUSE_BUTTON_1 && Action == GLFW_PRESS) + { + if (EDITOR.EditorSceneWindows[i]->bWindowHovered) + { + bool bEditingTerrain = false; + if (SELECTED.GetSelected(EDITOR.EditorSceneWindows[i]->Scene) != nullptr && SELECTED.GetSelected(EDITOR.EditorSceneWindows[i]->Scene)->HasComponent()) + { + bEditingTerrain = TERRAIN_SYSTEM.GetBrushMode() != FE_TERRAIN_BRUSH_NONE; + } + + if (!bEditingTerrain) + { + FESelectionData* CurrentSelectionData = SELECTED.GetSceneData(EDITOR.EditorSceneWindows[i]->Scene->GetObjectID()); + if (CurrentSelectionData != nullptr) + { + SELECTED.DetermineEntityUnderMouse(EDITOR.GetMouseX(), EDITOR.GetMouseY(), EDITOR.EditorSceneWindows[i]->Scene); + CurrentSelectionData->CheckForSelectionisNeeded = true; + } + } + } + + INSPECTOR_WINDOW.bLeftMousePressed = true; + } + else if (Button == GLFW_MOUSE_BUTTON_1 && Action == GLFW_RELEASE) + { + INSPECTOR_WINDOW.bLeftMousePressed = false; + GIZMO_MANAGER.DeactivateAllGizmo(EDITOR.EditorSceneWindows[i]->Scene); + } } } @@ -197,2947 +134,560 @@ void FEEditor::KeyButtonCallback(int Key, int Scancode, int Action, int Mods) { if (Key == GLFW_KEY_ESCAPE && Action == GLFW_PRESS) { - if (FEEditor::getInstance().IsInGameMode()) - { - FEEditor::getInstance().SetGameMode(false); - } - else - { - if (PROJECT_MANAGER.GetCurrent() == nullptr) - ENGINE.Terminate(); - projectWasModifiedPopUp::getInstance().Show(PROJECT_MANAGER.GetCurrent(), true); - } + if (PROJECT_MANAGER.GetCurrent() == nullptr) + ENGINE.Terminate(); + ProjectWasModifiedPopUp::GetInstance().Show(PROJECT_MANAGER.GetCurrent(), true); } - if (!ImGui::GetIO().WantCaptureKeyboard && Key == GLFW_KEY_DELETE) + for (size_t i = 0; i < EDITOR.EditorSceneWindows.size(); i++) { - if (SELECTED.GetSelected() != nullptr && SELECTED.GetSelected()->GetType() == FE_ENTITY_INSTANCED) + if (EDITOR.EditorSceneWindows[i]->Scene != EDITOR.GetFocusedScene()) + continue; + + FESelectionData* CurrentSelectionData = SELECTED.GetSceneData(EDITOR.EditorSceneWindows[i]->Scene->GetObjectID()); + if (!ImGui::GetIO().WantCaptureKeyboard && Key == GLFW_KEY_DELETE) { - if (SELECTED.InstancedSubObjectIndexSelected != -1) + if (SELECTED.GetSelected(EDITOR.EditorSceneWindows[i]->Scene) != nullptr) { - FEEntityInstanced* SelectedEntityInstanced = SCENE.GetEntityInstanced(SELECTED.GetSelected()->GetObjectID()); - SelectedEntityInstanced->DeleteInstance(SELECTED.InstancedSubObjectIndexSelected); - SELECTED.Clear(); + if (CurrentSelectionData->InstancedSubObjectIndexSelected != -1 && SELECTED.GetSelected(EDITOR.EditorSceneWindows[i]->Scene)->HasComponent()) + { + INSTANCED_RENDERING_SYSTEM.DeleteIndividualInstance(SELECTED.GetSelected(EDITOR.EditorSceneWindows[i]->Scene), CurrentSelectionData->InstancedSubObjectIndexSelected); + } + else + { + if (EDITOR.GetFocusedScene() != nullptr) + { + EDITOR.GetFocusedScene()->DeleteEntity(SELECTED.GetSelected(EDITOR.EditorSceneWindows[i]->Scene)); + } + } + + SELECTED.Clear(EDITOR.EditorSceneWindows[i]->Scene); PROJECT_MANAGER.GetCurrent()->SetModified(true); } } - if (SELECTED.GetEntity() != nullptr) + if (!ImGui::GetIO().WantCaptureKeyboard && Mods == GLFW_MOD_CONTROL && Key == GLFW_KEY_C && Action == GLFW_RELEASE) { - SCENE.DeleteEntity(SELECTED.GetEntity()->GetObjectID()); - SELECTED.Clear(); - PROJECT_MANAGER.GetCurrent()->SetModified(true); + if (SELECTED.GetSelected(EDITOR.EditorSceneWindows[i]->Scene) != nullptr) + EDITOR.SetSceneEntityIDInClipboard(SELECTED.GetSelected(EDITOR.EditorSceneWindows[i]->Scene)->GetObjectID()); } - else if (SELECTED.GetTerrain() != nullptr) + + if (!ImGui::GetIO().WantCaptureKeyboard && (Key == GLFW_KEY_RIGHT_SHIFT || Key == GLFW_KEY_LEFT_SHIFT) && Action == GLFW_RELEASE) { - SCENE.DeleteTerrain(SELECTED.GetTerrain()->GetObjectID()); - SELECTED.Clear(); - PROJECT_MANAGER.GetCurrent()->SetModified(true); + FEGizmoSceneData* GizmoSceneData = GIZMO_MANAGER.GetSceneData(EDITOR.EditorSceneWindows[i]->Scene->GetObjectID()); + int NewState = GizmoSceneData->GizmosState + 1; + if (NewState > 2) + NewState = 0; + GIZMO_MANAGER.UpdateGizmoState(NewState, EDITOR.EditorSceneWindows[i]->Scene); } } - if (!ImGui::GetIO().WantCaptureKeyboard && Mods == GLFW_MOD_CONTROL && Key == GLFW_KEY_C && Action == GLFW_RELEASE) - { - if (SELECTED.GetEntity() != nullptr) - EDITOR.SetObjectNameInClipboard(SELECTED.GetEntity()->GetObjectID()); - } - if (!ImGui::GetIO().WantCaptureKeyboard && Mods == GLFW_MOD_CONTROL && Key == GLFW_KEY_V && Action == GLFW_RELEASE) { - if (!EDITOR.GetObjectNameInClipboard().empty()) + if (!EDITOR.GetSceneEntityIDInClipboard().empty()) { - FEEntity* NewEntity = SCENE.AddEntity(SCENE.GetEntity(EDITOR.GetObjectNameInClipboard())->Prefab, ""); - NewEntity->Transform = SCENE.GetEntity(EDITOR.GetObjectNameInClipboard())->Transform; - NewEntity->Transform.SetPosition(NewEntity->Transform.GetPosition() * 1.1f); - SELECTED.SetSelected(NewEntity); + if (EDITOR.GetFocusedScene() != nullptr) + { + FEEntity* EntityToDuplicate = EDITOR.GetFocusedScene()->GetEntity(EDITOR.GetSceneEntityIDInClipboard()); + // Skip if entity was deleted or belongs to another scene + if (EntityToDuplicate != nullptr) + { + FENaiveSceneGraphNode* NodeToDuplicate = EDITOR.GetFocusedScene()->SceneGraph.GetNodeByEntityID(EntityToDuplicate->GetObjectID()); + FENaiveSceneGraphNode* DuplicatedNode = EDITOR.GetFocusedScene()->SceneGraph.DuplicateNode(NodeToDuplicate->GetObjectID(), NodeToDuplicate->GetParent()->GetObjectID()); + if (DuplicatedNode != nullptr) + { + FEEntity* DuplicatedEntity = DuplicatedNode->GetEntity(); + SELECTED.SetSelected(DuplicatedEntity); + } + } + } } } if (!ImGui::GetIO().WantCaptureKeyboard && (Key == GLFW_KEY_RIGHT_SHIFT || Key == GLFW_KEY_LEFT_SHIFT) && Action == GLFW_RELEASE) { - int NewState = GIZMO_MANAGER.GizmosState + 1; - if (NewState > 2) - NewState = 0; - GIZMO_MANAGER.UpdateGizmoState(NewState); - } - - if (!ImGui::GetIO().WantCaptureKeyboard && (Key == GLFW_KEY_RIGHT_SHIFT || Key == GLFW_KEY_LEFT_SHIFT) && Action == GLFW_RELEASE) - { - EDITOR.bShiftPressed = false; + INSPECTOR_WINDOW.bShiftPressed = false; } else if (!ImGui::GetIO().WantCaptureKeyboard && (Key == GLFW_KEY_RIGHT_SHIFT || Key == GLFW_KEY_LEFT_SHIFT) && Action == GLFW_PRESS) { - EDITOR.bShiftPressed = true; + INSPECTOR_WINDOW.bShiftPressed = true; } } -void FEEditor::ShowTransformConfiguration(FEObject* Object, FETransformComponent* Transform) const +void FEEditor::InitializeResources() { - // ********************* POSITION ********************* - glm::vec3 position = Transform->GetPosition(); - ImGui::Text("Position : "); - ImGui::SameLine(); - ImGui::SetNextItemWidth(50); - ImGui::DragFloat((std::string("##X pos : ") + Object->GetName()).c_str(), &position[0], 0.1f); - ShowToolTip("X position"); - - ImGui::SameLine(); - ImGui::SetNextItemWidth(50); - ImGui::DragFloat((std::string("##Y pos : ") + Object->GetName()).c_str(), &position[1], 0.1f); - ShowToolTip("Y position"); - - ImGui::SameLine(); - ImGui::SetNextItemWidth(50); - ImGui::DragFloat((std::string("##Z pos : ") + Object->GetName()).c_str(), &position[2], 0.1f); - ShowToolTip("Z position"); - Transform->SetPosition(position); - - // ********************* ROTATION ********************* - glm::vec3 rotation = Transform->GetRotation(); - ImGui::Text("Rotation : "); - ImGui::SameLine(); - ImGui::SetNextItemWidth(50); - ImGui::DragFloat((std::string("##X rot : ") + Object->GetName()).c_str(), &rotation[0], 0.1f, -360.0f, 360.0f); - ShowToolTip("X rotation"); - - ImGui::SameLine(); - ImGui::SetNextItemWidth(50); - ImGui::DragFloat((std::string("##Y rot : ") + Object->GetName()).c_str(), &rotation[1], 0.1f, -360.0f, 360.0f); - ShowToolTip("Y rotation"); - - ImGui::SameLine(); - ImGui::SetNextItemWidth(50); - ImGui::DragFloat((std::string("##Z rot : ") + Object->GetName()).c_str(), &rotation[2], 0.1f, -360.0f, 360.0f); - ShowToolTip("Z rotation"); - Transform->SetRotation(rotation); - - // ********************* SCALE ********************* - bool bUniformScaling = Transform->IsUniformScalingSet(); - ImGui::Checkbox("Uniform scaling", &bUniformScaling); - Transform->SetUniformScaling(bUniformScaling); - - glm::vec3 scale = Transform->GetScale(); - ImGui::Text("Scale : "); - ImGui::SameLine(); - ImGui::SetNextItemWidth(50); - ImGui::DragFloat((std::string("##X scale : ") + Object->GetName()).c_str(), &scale[0], 0.01f, 0.01f, 1000.0f); - ShowToolTip("X scale"); - - ImGui::SameLine(); - ImGui::SetNextItemWidth(50); - ImGui::DragFloat((std::string("##Y scale : ") + Object->GetName()).c_str(), &scale[1], 0.01f, 0.01f, 1000.0f); - ShowToolTip("Y scale"); - - ImGui::SameLine(); - ImGui::SetNextItemWidth(50); - ImGui::DragFloat((std::string("##Z scale : ") + Object->GetName()).c_str(), &scale[2], 0.01f, 0.01f, 1000.0f); - ShowToolTip("Z scale"); - - glm::vec3 OldScale = Transform->GetScale(); - Transform->ChangeXScaleBy(scale[0] - OldScale[0]); - Transform->ChangeYScaleBy(scale[1] - OldScale[1]); - Transform->ChangeZScaleBy(scale[2] - OldScale[2]); - - // ********************* REAL WORLD COMPARISON SCALE ********************* - if (Object->GetType() == FE_ENTITY || Object->GetType() == FE_ENTITY_INSTANCED) - { - FEEntity* entity = SCENE.GetEntity(Object->GetObjectID()); - - FEAABB RealAabb = entity->GetAABB(); - const glm::vec3 min = RealAabb.GetMin(); - const glm::vec3 max = RealAabb.GetMax(); - - const float XSize = sqrt((max.x - min.x) * (max.x - min.x)); - const float YSize = sqrt((max.y - min.y) * (max.y - min.y)); - const float ZSize = sqrt((max.z - min.z) * (max.z - min.z)); - - std::string SizeInM = "Approximate object size: "; - SizeInM += std::to_string(std::max(XSize, std::max(YSize, ZSize))); - SizeInM += " m"; - - /*std::string dementionsInM = "Xlength: "; - dementionsInM += std::to_string(xSize); - dementionsInM += " m Ylength: "; - dementionsInM += std::to_string(ySize); - dementionsInM += " m Zlength: "; - dementionsInM += std::to_string(zSize); - dementionsInM += " m";*/ + INPUT.AddKeyCallback(KeyButtonCallback); + INPUT.AddMouseButtonCallback(MouseButtonCallback); + INPUT.AddMouseMoveCallback(MouseMoveCallback); + ENGINE.AddOnViewportResizeCallback(OnViewportResize); + ENGINE.AddDropCallback(DropCallback); + + SELECTED.InitializeResources(); + PROJECT_MANAGER.InitializeResources(); + PREVIEW_MANAGER.InitializeResources(); + DRAG_AND_DROP_MANAGER.InitializeResources(); + + GIZMO_MANAGER.InitializeResources(); + SCENE_GRAPH_WINDOW.InitializeResources(); + CONTENT_BROWSER_WINDOW.InitializeResources(); + INSPECTOR_WINDOW.InitializeResources(); + + ENGINE.AddOnAfterUpdateCallback(AfterEngineUpdate); + ENGINE.AddWindowCloseCallback(CloseWindowCallBack); - ImGui::Text(SizeInM.c_str()); - } + SetUpImgui(); } -void FEEditor::ShowTransformConfiguration(const std::string Name, FETransformComponent* Transform) const +void FEEditor::MouseMoveCallback(double Xpos, double Ypos) { - // ********************* POSITION ********************* - glm::vec3 position = Transform->GetPosition(); - ImGui::Text("Position : "); - ImGui::SameLine(); - ImGui::SetNextItemWidth(50); - ImGui::DragFloat((std::string("##X pos : ") + Name).c_str(), &position[0], 0.1f); - ShowToolTip("X position"); - - ImGui::SameLine(); - ImGui::SetNextItemWidth(50); - ImGui::DragFloat((std::string("##Y pos : ") + Name).c_str(), &position[1], 0.1f); - ShowToolTip("Y position"); - - ImGui::SameLine(); - ImGui::SetNextItemWidth(50); - ImGui::DragFloat((std::string("##Z pos : ") + Name).c_str(), &position[2], 0.1f); - ShowToolTip("Z position"); - Transform->SetPosition(position); - - // ********************* ROTATION ********************* - glm::vec3 rotation = Transform->GetRotation(); - ImGui::Text("Rotation : "); - ImGui::SameLine(); - ImGui::SetNextItemWidth(50); - ImGui::DragFloat((std::string("##X rot : ") + Name).c_str(), &rotation[0], 0.1f, -360.0f, 360.0f); - ShowToolTip("X rotation"); - - ImGui::SameLine(); - ImGui::SetNextItemWidth(50); - ImGui::DragFloat((std::string("##Y rot : ") + Name).c_str(), &rotation[1], 0.1f, -360.0f, 360.0f); - ShowToolTip("Y rotation"); - - ImGui::SameLine(); - ImGui::SetNextItemWidth(50); - ImGui::DragFloat((std::string("##Z rot : ") + Name).c_str(), &rotation[2], 0.1f, -360.0f, 360.0f); - ShowToolTip("Z rotation"); - Transform->SetRotation(rotation); - - // ********************* SCALE ********************* - bool bUniformScaling = Transform->IsUniformScalingSet(); - ImGui::Checkbox("Uniform scaling", &bUniformScaling); - Transform->SetUniformScaling(bUniformScaling); - - glm::vec3 scale = Transform->GetScale(); - ImGui::Text("Scale : "); - ImGui::SameLine(); - ImGui::SetNextItemWidth(50); - ImGui::DragFloat((std::string("##X scale : ") + Name).c_str(), &scale[0], 0.01f, 0.01f, 1000.0f); - ShowToolTip("X scale"); - - ImGui::SameLine(); - ImGui::SetNextItemWidth(50); - ImGui::DragFloat((std::string("##Y scale : ") + Name).c_str(), &scale[1], 0.01f, 0.01f, 1000.0f); - ShowToolTip("Y scale"); - - ImGui::SameLine(); - ImGui::SetNextItemWidth(50); - ImGui::DragFloat((std::string("##Z scale : ") + Name).c_str(), &scale[2], 0.01f, 0.01f, 1000.0f); - ShowToolTip("Z scale"); - - glm::vec3 OldScale = Transform->GetScale(); - Transform->ChangeXScaleBy(scale[0] - OldScale[0]); - Transform->ChangeYScaleBy(scale[1] - OldScale[1]); - Transform->ChangeZScaleBy(scale[2] - OldScale[2]); -} + EDITOR.SetLastMouseX(EDITOR.GetMouseX()); + EDITOR.SetLastMouseY(EDITOR.GetMouseY()); -void FEEditor::DisplayLightProperties(FELight* Light) const -{ - ShowTransformConfiguration(Light, &Light->Transform); + EDITOR.SetMouseX(Xpos); + EDITOR.SetMouseY(Ypos); + + DRAG_AND_DROP_MANAGER.MouseMove(); - if (Light->GetType() == FE_DIRECTIONAL_LIGHT) + for (size_t i = 0; i < EDITOR.EditorSceneWindows.size(); i++) { - FEDirectionalLight* DirectionalLight = reinterpret_cast(Light); - ImGui::Separator(); - ImGui::Text("-------------Shadow settings--------------"); - - ImGui::Text("Cast shadows:"); - ImGui::SameLine(); - ImGui::SetNextItemWidth(200); - bool bCastShadows = DirectionalLight->IsCastShadows(); - ImGui::Checkbox("##Cast shadows", &bCastShadows); - DirectionalLight->SetCastShadows(bCastShadows); - ShowToolTip("Will this light cast shadows."); - - if (!DirectionalLight->IsCastShadows()) - ImGui::BeginDisabled(); - - ImGui::Text("Number of cascades :"); - ImGui::SameLine(); - ImGui::SetNextItemWidth(200); - int cascades = DirectionalLight->GetActiveCascades(); - ImGui::SliderInt("##cascades", &cascades, 1, 4); - DirectionalLight->SetActiveCascades(cascades); - ShowToolTip("How much steps of shadow quality will be used."); - - ImGui::Text("Shadow coverage in M :"); - ImGui::SameLine(); - ImGui::SetNextItemWidth(200); - float FirstCascadeSize = DirectionalLight->GetShadowCoverage(); - ImGui::DragFloat("##shadowCoverage", &FirstCascadeSize, 0.1f, 0.1f, 500.0f); - DirectionalLight->SetShadowCoverage(FirstCascadeSize); - ShowToolTip("Distance from camera at which shadows would be present."); - - ImGui::Text("Z depth of shadow map :"); - ImGui::SameLine(); - ImGui::SetNextItemWidth(200); - float CSMZDepth = DirectionalLight->GetCSMZDepth(); - ImGui::DragFloat("##CSMZDepth", &CSMZDepth, 0.01f, 0.1f, 100.0f); - DirectionalLight->SetCSMZDepth(CSMZDepth); - ShowToolTip("If you have problems with shadow disapearing when camera is at close distance to shadow reciver, tweaking this parameter could help. Otherwise this parameter should be as small as possible."); - - ImGui::Text("XY depth of shadow map :"); - ImGui::SameLine(); - ImGui::SetNextItemWidth(200); - float CSMXYDepth = DirectionalLight->GetCSMXYDepth(); - ImGui::DragFloat("##CSMXYDepth", &CSMXYDepth, 0.01f, 0.0f, 100.0f); - DirectionalLight->SetCSMXYDepth(CSMXYDepth); - ShowToolTip("If you have problems with shadow on edges of screen, tweaking this parameter could help. Otherwise this parameter should be as small as possible."); - - ImGui::Text("Shadows blur factor:"); - ImGui::SameLine(); - ImGui::SetNextItemWidth(200.0f); - float ShadowsBlurFactor = DirectionalLight->GetShadowBlurFactor(); - ImGui::DragFloat("##Shadows blur factor", &ShadowsBlurFactor, 0.001f, 0.0f, 10.0f); - DirectionalLight->SetShadowBlurFactor(ShadowsBlurFactor); - - bool bStaticShadowBias = DirectionalLight->IsStaticShadowBias(); - ImGui::Checkbox("Static shadow bias :", &bStaticShadowBias); - DirectionalLight->SetIsStaticShadowBias(bStaticShadowBias); + if (EDITOR.EditorSceneWindows[i]->Scene != EDITOR.GetFocusedScene()) + continue; - if (DirectionalLight->IsStaticShadowBias()) - { - ImGui::Text("Static shadow bias value :"); - ImGui::SameLine(); - ImGui::SetNextItemWidth(200); - float ShadowBias = DirectionalLight->GetShadowBias(); - ImGui::DragFloat("##shadowBias", &ShadowBias, 0.0001f, 0.00001f, 0.1f); - DirectionalLight->SetShadowBias(ShadowBias); - } - else + if (SELECTED.GetSelected(EDITOR.EditorSceneWindows[i]->Scene) != nullptr) { - ImGui::Text("Intensity of variable shadow bias :"); - ImGui::SameLine(); - ImGui::SetNextItemWidth(200); - float ShadowBiasIntensity = DirectionalLight->GetShadowBiasVariableIntensity(); - ImGui::DragFloat("##shadowBiasIntensity", &ShadowBiasIntensity, 0.01f, 0.01f, 10.0f); - DirectionalLight->SetShadowBiasVariableIntensity(ShadowBiasIntensity); - } + if (SELECTED.GetSelected(EDITOR.EditorSceneWindows[i]->Scene) != nullptr && SELECTED.GetSelected(EDITOR.EditorSceneWindows[i]->Scene)->HasComponent()) + { + if (TERRAIN_SYSTEM.GetBrushMode() != FE_TERRAIN_BRUSH_NONE) + return; + } - if (!DirectionalLight->IsCastShadows()) - ImGui::EndDisabled(); - } - else if (Light->GetType() == FE_POINT_LIGHT) - { - } - else if (Light->GetType() == FE_SPOT_LIGHT) - { - FESpotLight* SpotLight = reinterpret_cast(Light); - glm::vec3 direction = SpotLight->GetDirection(); - ImGui::DragFloat("##x", &direction[0], 0.01f, 0.0f, 1.0f); - ImGui::DragFloat("##y", &direction[1], 0.01f, 0.0f, 1.0f); - ImGui::DragFloat("##z", &direction[2], 0.01f, 0.0f, 1.0f); - - float SpotAngle = SpotLight->GetSpotAngle(); - ImGui::SliderFloat((std::string("Inner angle##") + SpotLight->GetName()).c_str(), &SpotAngle, 0.0f, 90.0f); - SpotLight->SetSpotAngle(SpotAngle); - - float SpotAngleOuter = SpotLight->GetSpotAngleOuter(); - ImGui::SliderFloat((std::string("Outer angle ##") + SpotLight->GetName()).c_str(), &SpotAngleOuter, 0.0f, 90.0f); - SpotLight->SetSpotAngleOuter(SpotAngleOuter); + GIZMO_MANAGER.MouseMove(EDITOR.GetLastMouseX(), EDITOR.GetLastMouseY(), EDITOR.GetMouseX(), EDITOR.GetMouseY(), EDITOR.EditorSceneWindows[i]->Scene); + } } - - glm::vec3 color = Light->GetColor(); - ImGui::ColorEdit3((std::string("Color##") + Light->GetName()).c_str(), &color.x); - Light->SetColor(color); - - float intensity = Light->GetIntensity(); - ImGui::SliderFloat((std::string("Intensity##") + Light->GetName()).c_str(), &intensity, 0.0f, 100.0f); - Light->SetIntensity(intensity); } -void FEEditor::DisplayLightsProperties() const +void FEEditor::AfterEngineUpdate() { - const std::vector LightList = SCENE.GetLightsList(); - - for (size_t i = 0; i < LightList.size(); i++) - { - if (ImGui::TreeNode(LightList[i].c_str())) - { - DisplayLightProperties(SCENE.GetLight(LightList[i])); - ImGui::TreePop(); - } - } + SELECTED.OnCameraUpdate(); + GIZMO_MANAGER.Update(); } -void FEEditor::DrawCorrectSceneBrowserIcon(const FEObject* SceneObject) const +void FEEditor::Render() { - ImGui::SetCursorPosX(20); + EDITOR_SCRIPTING_SYSTEM.Update(); - if (SceneObject->GetType() == FE_ENTITY || SceneObject->GetType() == FE_ENTITY_INSTANCED) + std::vector ActiveScenes = SCENE_MANAGER.GetScenesByFlagMask(FESceneFlag::Active | FESceneFlag::Renderable); + if (ActiveScenes.empty()) { - const FEEntity* entity = SCENE.GetEntity(SceneObject->GetObjectID()); - - if (EDITOR_INTERNAL_RESOURCES.IsInInternalEditorList(entity)) - return; - - if (entity->GetType() == FE_ENTITY_INSTANCED) - { - - ImGui::Image((void*)(intptr_t)InstancedEntitySceneBrowserIcon->GetTextureID(), ImVec2(16, 16), ImVec2(0.0f, 0.0f), ImVec2(1.0f, 1.0f)); - } - else - { - ImGui::Image((void*)(intptr_t)EntitySceneBrowserIcon->GetTextureID(), ImVec2(16, 16), ImVec2(0.0f, 0.0f), ImVec2(1.0f, 1.0f)); - } + EditorSceneWindows.clear(); + SetFocusedScene(nullptr); } - if (SceneObject->GetType() == FE_DIRECTIONAL_LIGHT) - { - ImGui::Image((void*)(intptr_t)DirectionalLightSceneBrowserIcon->GetTextureID(), ImVec2(16, 16), ImVec2(0.0f, 0.0f), ImVec2(1.0f, 1.0f)); - - } + DRAG_AND_DROP_MANAGER.Render(); - if (SceneObject->GetType() == FE_SPOT_LIGHT) + if (PROJECT_MANAGER.GetCurrent()) { - ImGui::Image((void*)(intptr_t)SpotLightSceneBrowserIcon->GetTextureID(), ImVec2(16, 16), ImVec2(0.0f, 0.0f), ImVec2(1.0f, 1.0f)); - - } + ImGui::DockSpaceOverViewport(ImGui::GetMainViewport()); + DockspaceID = ImGui::GetMainViewport()->ID; - if (SceneObject->GetType() == FE_POINT_LIGHT) - { - ImGui::Image((void*)(intptr_t)PointLightSceneBrowserIcon->GetTextureID(), ImVec2(16, 16), ImVec2(0.0f, 0.0f), ImVec2(1.0f, 1.0f)); - - } + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(15, 15)); + if (ImGui::BeginMainMenuBar()) + { + if (ImGui::BeginMenu("File")) + { + if (ImGui::MenuItem("Save project")) + { + PROJECT_MANAGER.GetCurrent()->SaveProject(); + } - if (SceneObject->GetType() == FE_TERRAIN) - { - ImGui::Image((void*)(intptr_t)TerrainSceneBrowserIcon->GetTextureID(), ImVec2(16, 16), ImVec2(0.0f, 0.0f), ImVec2(1.0f, 1.0f)); - } + if (ImGui::MenuItem("Save project as...")) + { + std::string Path; + FILE_SYSTEM.ShowFolderOpenDialog(Path); + if (!Path.empty()) + { + PROJECT_MANAGER.GetCurrent()->SaveProjectTo(Path + "\\"); + } + } - if (SceneObject->GetType() == FE_CAMERA) - { - ImGui::Image((void*)(intptr_t)CameraSceneBrowserIcon->GetTextureID(), ImVec2(16, 16), ImVec2(0.0f, 0.0f), ImVec2(1.0f, 1.0f)); - } + if (ImGui::MenuItem("Close project")) + { + if (PROJECT_MANAGER.GetCurrent()->IsModified()) + { + ProjectWasModifiedPopUp::GetInstance().Show(PROJECT_MANAGER.GetCurrent(), false); + } + else + { + OnProjectClose(); - ImGui::SameLine(); - return; -} + ImGui::PopStyleVar(); + ImGui::EndMenu(); + ImGui::EndMainMenuBar(); -void FEEditor::DisplaySceneBrowser() -{ - if (!bSceneBrowserVisible) - return; + return; + } + } - static int SceneObjectHoveredIndex = -1; + if (ImGui::MenuItem("Exit")) + { + if (PROJECT_MANAGER.GetCurrent()->IsModified()) + { + APPLICATION.GetMainWindow()->CancelClose(); + ProjectWasModifiedPopUp::GetInstance().Show(PROJECT_MANAGER.GetCurrent(), true); + } + else + { + OnProjectClose(); + ENGINE.Terminate(); + return; + } + } + + ImGui::EndMenu(); + } - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(15, 15)); - ImGui::Begin("Scene Entities", nullptr, ImGuiWindowFlags_None); + if (ImGui::BeginMenu("Window")) + { + if (ImGui::MenuItem("Scene Entities", nullptr, SCENE_GRAPH_WINDOW.bVisible)) + { + SCENE_GRAPH_WINDOW.bVisible = !SCENE_GRAPH_WINDOW.bVisible; + } - ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor::ImColor(0.6f, 0.24f, 0.24f)); - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::ImColor(0.7f, 0.21f, 0.21f)); - ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::ImColor(0.8f, 0.16f, 0.16f)); + if (ImGui::MenuItem("Inspector", nullptr, INSPECTOR_WINDOW.bVisible)) + { + INSPECTOR_WINDOW.bVisible = !INSPECTOR_WINDOW.bVisible; + } - if (ImGui::Button("Enter game mode", ImVec2(220, 0))) - { - FEEditor::getInstance().SetGameMode(true); - } + if (ImGui::MenuItem("Content Browser", nullptr, CONTENT_BROWSER_WINDOW.bVisible)) + { + CONTENT_BROWSER_WINDOW.bVisible = !CONTENT_BROWSER_WINDOW.bVisible; + } - ImGui::PopStyleColor(); - ImGui::PopStyleColor(); - ImGui::PopStyleColor(); + if (ImGui::MenuItem("Effects", nullptr, bEditorCamerasWindowVisible)) + { + bEditorCamerasWindowVisible = !bEditorCamerasWindowVisible; + } - const std::vector EntityList = SCENE.GetEntityList(); - std::vector SceneObjectsList; - for (size_t i = 0; i < EntityList.size(); i++) - { - if (EDITOR_INTERNAL_RESOURCES.IsInInternalEditorList(SCENE.GetEntity(EntityList[i]))) - continue; - SceneObjectsList.push_back(EntityList[i]); - } + if (ImGui::MenuItem("Log", nullptr, bLogWindowVisible)) + { + bLogWindowVisible = !bLogWindowVisible; + } - const std::vector LightList = SCENE.GetLightsList(); - for (size_t i = 0; i < LightList.size(); i++) - { - SceneObjectsList.push_back(LightList[i]); - } + if (ImGui::BeginMenu("Debug")) + { + auto PossibleWindows = RENDERER.GetDebugOutputTextures(); - const std::vector TerrainList = SCENE.GetTerrainList(); - for (size_t i = 0; i < TerrainList.size(); i++) - { - SceneObjectsList.push_back(TerrainList[i]); - } - - SceneObjectsList.push_back(ENGINE.GetCamera()->GetObjectID()); - - // Filtering. - ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 5.0f); - ImGui::Text("Filter: "); - ImGui::SameLine(); - - ImGui::SetCursorPosY(ImGui::GetCursorPosY() - 5.0f); - ImGui::InputText("##selectFEObjectPopUpFilter", FilterForSceneEntities, IM_ARRAYSIZE(FilterForSceneEntities)); - - std::vector FilteredSceneObjectsList; - if (strlen(FilterForSceneEntities) == 0) - { - FilteredSceneObjectsList = SceneObjectsList; - } - else - { - FilteredSceneObjectsList.clear(); - for (size_t i = 0; i < SceneObjectsList.size(); i++) - { - if (OBJECT_MANAGER.GetFEObject(SceneObjectsList[i])->GetName().find(FilterForSceneEntities) != -1) - { - FilteredSceneObjectsList.push_back(SceneObjectsList[i]); - } - } - } - - if (!bShouldOpenContextMenuInSceneEntities) - SceneObjectHoveredIndex = -1; - - for (size_t i = 0; i < FilteredSceneObjectsList.size(); i++) - { - DrawCorrectSceneBrowserIcon(OBJECT_MANAGER.GetFEObject(FilteredSceneObjectsList[i])); - - ImGuiTreeNodeFlags node_flags = ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen; - if (SELECTED.GetSelected() != nullptr) - { - if (SELECTED.GetSelected()->GetObjectID() == FilteredSceneObjectsList[i]) - { - node_flags |= ImGuiTreeNodeFlags_Selected; - } - } - - SetCorrectSceneBrowserColor(OBJECT_MANAGER.GetFEObject(FilteredSceneObjectsList[i])); - ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags, OBJECT_MANAGER.GetFEObject(FilteredSceneObjectsList[i])->GetName().c_str(), i); - PopCorrectSceneBrowserColor(OBJECT_MANAGER.GetFEObject(FilteredSceneObjectsList[i])); - - if (ImGui::IsItemClicked()) - { - SELECTED.SetSelected(OBJECT_MANAGER.GetFEObject(FilteredSceneObjectsList[i])); - SELECTED.SetDirtyFlag(false); - } - - if (ImGui::IsItemHovered()) - { - SceneObjectHoveredIndex = int(i); - } - } - - bool open_context_menu = false; - if (ImGui::IsWindowHovered() && ImGui::IsMouseClicked(1)) - open_context_menu = true; - - if (open_context_menu) - ImGui::OpenPopup("##context_menu"); - - bShouldOpenContextMenuInSceneEntities = false; - - if (ImGui::BeginPopup("##context_menu")) - { - bShouldOpenContextMenuInSceneEntities = true; - - if (SceneObjectHoveredIndex == -1) - { - if (ImGui::BeginMenu("Add")) - { - if (ImGui::MenuItem("Entity")) - { - SelectFeObjectPopUp::getInstance().Show(FE_PREFAB, CreateNewEntityCallBack); - //selectGameModelPopUp::getInstance().show(nullptr, true); - } - - if (ImGui::MenuItem("Instanced entity")) - { - SelectFeObjectPopUp::getInstance().Show(FE_PREFAB, CreateNewInstancedEntityCallBack); - //selectGameModelPopUp::getInstance().show(nullptr, true, true); - } - - if (ImGui::MenuItem("Terrain")) - { - const std::vector TerrainList = SCENE.GetTerrainList(); - const size_t NextId = TerrainList.size(); - size_t index = 0; - std::string NewName = "terrain_" + std::to_string(NextId + index); - - while (true) - { - bool bCorrectName = true; - for (size_t i = 0; i < TerrainList.size(); i++) - { - if (TerrainList[i] == NewName) - { - bCorrectName = false; - break; - } - } - - if (bCorrectName) - break; - - index++; - NewName = "terrain_" + std::to_string(NextId + index); - } - - FETerrain* NewTerrain = RESOURCE_MANAGER.CreateTerrain(true, NewName); - SCENE.AddTerrain(NewTerrain); - NewTerrain->HeightMap->SetDirtyFlag(true); - PROJECT_MANAGER.GetCurrent()->SetModified(true); - } - - if (ImGui::BeginMenu("Light")) - { - if (ImGui::MenuItem("Directional")) - { - SCENE.AddLight(FE_DIRECTIONAL_LIGHT, ""); - } - - if (ImGui::MenuItem("Spot")) - { - SCENE.AddLight(FE_SPOT_LIGHT, ""); - } - - if (ImGui::MenuItem("Point")) - { - SCENE.AddLight(FE_POINT_LIGHT, ""); - } - - ImGui::EndMenu(); - } - - ImGui::EndMenu(); - } - } - else - { - if (ImGui::MenuItem("Rename")) - { - if (SCENE.GetEntity(FilteredSceneObjectsList[SceneObjectHoveredIndex]) != nullptr) - { - renamePopUp::getInstance().Show(SCENE.GetEntity(FilteredSceneObjectsList[SceneObjectHoveredIndex])); - } - else if (SCENE.GetTerrain(FilteredSceneObjectsList[SceneObjectHoveredIndex]) != nullptr) - { - renamePopUp::getInstance().Show(SCENE.GetTerrain(FilteredSceneObjectsList[SceneObjectHoveredIndex])); - } - else if (SCENE.GetLight(FilteredSceneObjectsList[SceneObjectHoveredIndex]) != nullptr) - { - renamePopUp::getInstance().Show(SCENE.GetLight(FilteredSceneObjectsList[SceneObjectHoveredIndex])); - //renameLightWindow.show(SCENE.getLight(filteredSceneObjectsList[sceneObjectHoveredIndex])); - } - } - - if (ImGui::MenuItem("Delete")) - { - if (SCENE.GetEntity(FilteredSceneObjectsList[SceneObjectHoveredIndex]) != nullptr) - { - const FEEntity* Entity = SCENE.GetEntity(FilteredSceneObjectsList[SceneObjectHoveredIndex]); - if (SELECTED.GetEntity() == Entity) - SELECTED.Clear(); - - SCENE.DeleteEntity(Entity->GetObjectID()); - } - else if (SCENE.GetTerrain(FilteredSceneObjectsList[SceneObjectHoveredIndex]) != nullptr) - { - const FETerrain* Terrain = SCENE.GetTerrain(FilteredSceneObjectsList[SceneObjectHoveredIndex]); - if (SELECTED.GetTerrain() == Terrain) - SELECTED.Clear(); - - SCENE.DeleteTerrain(Terrain->GetObjectID()); - } - else if (SCENE.GetLight(FilteredSceneObjectsList[SceneObjectHoveredIndex]) != nullptr) - { - const FELight* Light = SCENE.GetLight(FilteredSceneObjectsList[SceneObjectHoveredIndex]); - if (SELECTED.GetLight() == Light) - SELECTED.Clear(); - - SCENE.DeleteLight(Light->GetObjectID()); - } - } - - if (ImGui::MenuItem("*DEBUG* Test model camera on this")) - { - FEModelViewCamera* NewCamera = new FEModelViewCamera("New ModelViewCamera"); - NewCamera->SetAspectRatio(static_cast(ENGINE.GetRenderTargetWidth()) / static_cast(ENGINE.GetRenderTargetHeight())); - - glm::vec3 Position = glm::vec3(0.0f); - if (SCENE.GetEntity(FilteredSceneObjectsList[SceneObjectHoveredIndex]) != nullptr) - { - const FEEntity* Entity = SCENE.GetEntity(FilteredSceneObjectsList[SceneObjectHoveredIndex]); - Position = Entity->Transform.GetPosition(); - } - else if (SCENE.GetTerrain(FilteredSceneObjectsList[SceneObjectHoveredIndex]) != nullptr) - { - const FETerrain* Terrain = SCENE.GetTerrain(FilteredSceneObjectsList[SceneObjectHoveredIndex]); - Position = Terrain->Transform.GetPosition(); - } - else if (SCENE.GetLight(FilteredSceneObjectsList[SceneObjectHoveredIndex]) != nullptr) - { - const FELight* Light = SCENE.GetLight(FilteredSceneObjectsList[SceneObjectHoveredIndex]); - Position = Light->Transform.GetPosition(); - } - - NewCamera->SetTrackingObjectPosition(Position); - NewCamera->SetOnUpdate(OnCameraUpdate); - ENGINE.SetCamera(NewCamera); - } - } - - ImGui::EndPopup(); - } - - static bool bDisplayGrid = true; - ImGui::Checkbox("Display grid", &bDisplayGrid); - - static glm::vec3 color = glm::vec3(0.2f, 0.3f, 0.4f); - - const float BasicW = 0.1f; - float width = BasicW * 4.0f; - if (bDisplayGrid) - { - const int GridSize = 200; - for (int i = -GridSize / 2; i < GridSize / 2; i++) - { - color = glm::vec3(0.4f, 0.65f, 0.73f); - width = BasicW * 4.0f; - if (i % 2 != 0 && i != 0) - { - color = color / 4.0f; - width = width / 4.0f; - } - else if (i == 0) - { - color = glm::vec3(0.9f, 0.9f, 0.9f); - width = BasicW * 4.0f; - } - - RENDERER.DrawLine(glm::vec3(i, 0.0f, -GridSize / 2), glm::vec3(i, 0.0f, GridSize / 2), color, width); - RENDERER.DrawLine(glm::vec3(-GridSize / 2, 0.0f, i), glm::vec3(GridSize / 2, 0.0f, i), color, width); - } - } - - static float FavgTime = 0.0f; - static std::vector AvgTime; - static int counter = 0; - - ImGui::Text((std::string("Time : ") + std::to_string(RENDERER.LastTestTime)).c_str()); - - if (AvgTime.size() < 100) - { - AvgTime.push_back(RENDERER.LastTestTime); - } - else if (AvgTime.size() >= 100) - { - AvgTime[counter++ % 100] = RENDERER.LastTestTime; - } - - for (size_t i = 0; i < AvgTime.size(); i++) - { - FavgTime += AvgTime[i]; - } - FavgTime /= AvgTime.size(); - - - if (counter > 1000000) - counter = 0; - - ImGui::Text((std::string("avg Time : ") + std::to_string(FavgTime)).c_str()); - - bool bFreezeCulling = RENDERER.bFreezeCulling; - ImGui::Checkbox("bFreezeCulling", &bFreezeCulling); - RENDERER.bFreezeCulling = bFreezeCulling; - - bool bFreezeOcclusionCulling = !RENDERER.IsOcclusionCullingEnabled(); - ImGui::Checkbox("freezeOcclusionCulling", &bFreezeOcclusionCulling); - RENDERER.SetOcclusionCullingEnabled(!bFreezeOcclusionCulling); - - static bool bDisplaySelectedObjAABB = false; - ImGui::Checkbox("Display AABB of selected object", &bDisplaySelectedObjAABB); - - // draw AABB - if (SELECTED.GetSelected() != nullptr && - (SELECTED.GetSelected()->GetType() == FE_ENTITY || SELECTED.GetSelected()->GetType() == FE_ENTITY_INSTANCED || SELECTED.GetSelected()->GetType() == FE_TERRAIN) && - bDisplaySelectedObjAABB) - { - const FEAABB SelectedAabb = SELECTED.GetEntity() != nullptr ? SELECTED.GetEntity()->GetAABB() : SELECTED.GetTerrain()->GetAABB(); - RENDERER.DrawAABB(SelectedAabb); - - if (SELECTED.GetSelected()->GetType() == FE_ENTITY_INSTANCED) - { - static bool bDisplaySubObjAABB = false; - ImGui::Checkbox("Display AABB of instanced entity subobjects", &bDisplaySubObjAABB); - - if (bDisplaySubObjAABB) - { - const FEEntityInstanced* EntityInstanced = reinterpret_cast (SELECTED.GetSelected()); - const int MaxIterations = EntityInstanced->InstancedAABB.size() * 8 >= FE_MAX_LINES ? FE_MAX_LINES : int(EntityInstanced->InstancedAABB.size()); - - for (size_t j = 0; j < MaxIterations; j++) - { - RENDERER.DrawAABB(EntityInstanced->InstancedAABB[j]); - } - } - } - } - - ImGui::PopStyleVar(); - ImGui::End(); -} - -void FEEditor::InitializeResources() -{ - ENGINE.AddKeyCallback(KeyButtonCallback); - ENGINE.AddMouseButtonCallback(MouseButtonCallback); - ENGINE.AddMouseMoveCallback(MouseMoveCallback); - ENGINE.AddRenderTargetResizeCallback(RenderTargetResizeCallback); - ENGINE.AddDropCallback(DropCallback); - - SELECTED.InitializeResources(); - ENGINE.GetCamera()->SetIsInputActive(bIsCameraInputActive); - PROJECT_MANAGER.InitializeResources(); - PREVIEW_MANAGER.InitializeResources(); - DRAG_AND_DROP_MANAGER.InitializeResources(); - SceneWindowTarget = DRAG_AND_DROP_MANAGER.AddTarget(FE_PREFAB, SceneWindowDragAndDropCallBack, nullptr, "Drop to add to scene"); - - // **************************** Gizmos **************************** - GIZMO_MANAGER.InitializeResources(); - - // hide all resources for gizmos from content browser - EDITOR_INTERNAL_RESOURCES.AddResourceToInternalEditorList(RESOURCE_MANAGER.GetMesh("45191B6F172E3B531978692E"/*"transformationGizmoMesh"*/)); - EDITOR_INTERNAL_RESOURCES.AddResourceToInternalEditorList(RESOURCE_MANAGER.GetMesh("637C784B2E5E5C6548190E1B"/*"scaleGizmoMesh"*/)); - EDITOR_INTERNAL_RESOURCES.AddResourceToInternalEditorList(RESOURCE_MANAGER.GetMesh("19622421516E5B317E1B5360"/*"rotateGizmoMesh"*/)); - - EDITOR_INTERNAL_RESOURCES.AddResourceToInternalEditorList(GIZMO_MANAGER.TransformationXGizmoEntity->Prefab->GetComponent(0)->GameModel); - EDITOR_INTERNAL_RESOURCES.AddResourceToInternalEditorList(GIZMO_MANAGER.TransformationXGizmoEntity); - EDITOR_INTERNAL_RESOURCES.AddResourceToInternalEditorList(GIZMO_MANAGER.TransformationYGizmoEntity->Prefab->GetComponent(0)->GameModel); - EDITOR_INTERNAL_RESOURCES.AddResourceToInternalEditorList(GIZMO_MANAGER.TransformationYGizmoEntity); - EDITOR_INTERNAL_RESOURCES.AddResourceToInternalEditorList(GIZMO_MANAGER.TransformationZGizmoEntity->Prefab->GetComponent(0)->GameModel); - EDITOR_INTERNAL_RESOURCES.AddResourceToInternalEditorList(GIZMO_MANAGER.TransformationZGizmoEntity); - EDITOR_INTERNAL_RESOURCES.AddResourceToInternalEditorList(GIZMO_MANAGER.TransformationXyGizmoEntity->Prefab->GetComponent(0)->GameModel); - EDITOR_INTERNAL_RESOURCES.AddResourceToInternalEditorList(GIZMO_MANAGER.TransformationXyGizmoEntity); - EDITOR_INTERNAL_RESOURCES.AddResourceToInternalEditorList(GIZMO_MANAGER.TransformationYzGizmoEntity->Prefab->GetComponent(0)->GameModel); - EDITOR_INTERNAL_RESOURCES.AddResourceToInternalEditorList(GIZMO_MANAGER.TransformationYzGizmoEntity); - EDITOR_INTERNAL_RESOURCES.AddResourceToInternalEditorList(GIZMO_MANAGER.TransformationXzGizmoEntity->Prefab->GetComponent(0)->GameModel); - EDITOR_INTERNAL_RESOURCES.AddResourceToInternalEditorList(GIZMO_MANAGER.TransformationXzGizmoEntity); - - EDITOR_INTERNAL_RESOURCES.AddResourceToInternalEditorList(GIZMO_MANAGER.ScaleXGizmoEntity->Prefab->GetComponent(0)->GameModel); - EDITOR_INTERNAL_RESOURCES.AddResourceToInternalEditorList(GIZMO_MANAGER.ScaleXGizmoEntity); - EDITOR_INTERNAL_RESOURCES.AddResourceToInternalEditorList(GIZMO_MANAGER.ScaleYGizmoEntity->Prefab->GetComponent(0)->GameModel); - EDITOR_INTERNAL_RESOURCES.AddResourceToInternalEditorList(GIZMO_MANAGER.ScaleYGizmoEntity); - EDITOR_INTERNAL_RESOURCES.AddResourceToInternalEditorList(GIZMO_MANAGER.ScaleZGizmoEntity->Prefab->GetComponent(0)->GameModel); - EDITOR_INTERNAL_RESOURCES.AddResourceToInternalEditorList(GIZMO_MANAGER.ScaleZGizmoEntity); - - EDITOR_INTERNAL_RESOURCES.AddResourceToInternalEditorList(GIZMO_MANAGER.RotateXGizmoEntity->Prefab->GetComponent(0)->GameModel); - EDITOR_INTERNAL_RESOURCES.AddResourceToInternalEditorList(GIZMO_MANAGER.RotateXGizmoEntity); - EDITOR_INTERNAL_RESOURCES.AddResourceToInternalEditorList(GIZMO_MANAGER.RotateYGizmoEntity->Prefab->GetComponent(0)->GameModel); - EDITOR_INTERNAL_RESOURCES.AddResourceToInternalEditorList(GIZMO_MANAGER.RotateYGizmoEntity); - EDITOR_INTERNAL_RESOURCES.AddResourceToInternalEditorList(GIZMO_MANAGER.RotateZGizmoEntity->Prefab->GetComponent(0)->GameModel); - EDITOR_INTERNAL_RESOURCES.AddResourceToInternalEditorList(GIZMO_MANAGER.RotateZGizmoEntity); - - EDITOR_INTERNAL_RESOURCES.AddResourceToInternalEditorList(PREVIEW_MANAGER.PreviewEntity); - - MouseCursorIcon = RESOURCE_MANAGER.LoadPNGTexture("Resources/Images/mouseCursorIcon.png", "mouseCursorIcon"); - RESOURCE_MANAGER.MakeTextureStandard(MouseCursorIcon); - ArrowToGroundIcon = RESOURCE_MANAGER.LoadPNGTexture("Resources/Images/arrowToGroundIcon.png", "arrowToGroundIcon"); - RESOURCE_MANAGER.MakeTextureStandard(ArrowToGroundIcon); - - EntitySceneBrowserIcon = RESOURCE_MANAGER.LoadPNGTexture("Resources/Images/entitySceneBrowserIcon.png", "entitySceneBrowserIcon"); - RESOURCE_MANAGER.MakeTextureStandard(EntitySceneBrowserIcon); - InstancedEntitySceneBrowserIcon = RESOURCE_MANAGER.LoadPNGTexture("Resources/Images/instancedEntitySceneBrowserIcon.png", "instancedEntitySceneBrowserIcon"); - RESOURCE_MANAGER.MakeTextureStandard(InstancedEntitySceneBrowserIcon); - - DirectionalLightSceneBrowserIcon = RESOURCE_MANAGER.LoadPNGTexture("Resources/Images/directionalLightSceneBrowserIcon.png", "directionalLightSceneBrowserIcon"); - RESOURCE_MANAGER.MakeTextureStandard(DirectionalLightSceneBrowserIcon); - SpotLightSceneBrowserIcon = RESOURCE_MANAGER.LoadPNGTexture("Resources/Images/spotLightSceneBrowserIcon.png", "spotLightSceneBrowserIcon"); - RESOURCE_MANAGER.MakeTextureStandard(SpotLightSceneBrowserIcon); - PointLightSceneBrowserIcon = RESOURCE_MANAGER.LoadPNGTexture("Resources/Images/pointLightSceneBrowserIcon.png", "pointLightSceneBrowserIcon"); - RESOURCE_MANAGER.MakeTextureStandard(PointLightSceneBrowserIcon); - - TerrainSceneBrowserIcon = RESOURCE_MANAGER.LoadPNGTexture("Resources/Images/terrainSceneBrowserIcon.png", "terrainSceneBrowserIcon"); - RESOURCE_MANAGER.MakeTextureStandard(TerrainSceneBrowserIcon); - - CameraSceneBrowserIcon = RESOURCE_MANAGER.LoadPNGTexture("Resources/Images/cameraSceneBrowserIcon.png", "cameraSceneBrowserIcon"); - RESOURCE_MANAGER.MakeTextureStandard(CameraSceneBrowserIcon); - - FolderIcon = RESOURCE_MANAGER.LoadPNGTexture("Resources/Images/folderIcon.png", "folderIcon"); - RESOURCE_MANAGER.MakeTextureStandard(FolderIcon); - - ShaderIcon = RESOURCE_MANAGER.LoadPNGTexture("Resources/Images/shaderIcon.png", "shaderIcon"); - RESOURCE_MANAGER.MakeTextureStandard(ShaderIcon); - - VFSBackIcon = RESOURCE_MANAGER.LoadPNGTexture("Resources/Images/VFSBackIcon.png", "VFSBackIcon"); - RESOURCE_MANAGER.MakeTextureStandard(VFSBackIcon); - - TextureContentBrowserIcon = RESOURCE_MANAGER.LoadPNGTexture("Resources/Images/textureContentBrowserIcon.png", "textureContentBrowserIcon"); - RESOURCE_MANAGER.MakeTextureStandard(TextureContentBrowserIcon); - - MeshContentBrowserIcon = RESOURCE_MANAGER.LoadPNGTexture("Resources/Images/meshContentBrowserIcon.png", "meshContentBrowserIcon"); - RESOURCE_MANAGER.MakeTextureStandard(MeshContentBrowserIcon); - - MaterialContentBrowserIcon = RESOURCE_MANAGER.LoadPNGTexture("Resources/Images/materialContentBrowserIcon.png", "materialContentBrowserIcon"); - RESOURCE_MANAGER.MakeTextureStandard(MaterialContentBrowserIcon); - - GameModelContentBrowserIcon = RESOURCE_MANAGER.LoadPNGTexture("Resources/Images/gameModelContentBrowserIcon.png", "gameModelContentBrowserIcon"); - RESOURCE_MANAGER.MakeTextureStandard(GameModelContentBrowserIcon); - - PrefabContentBrowserIcon = RESOURCE_MANAGER.LoadPNGTexture("Resources/Images/prefabContentBrowserIcon.png", "prefabContentBrowserIcon"); - RESOURCE_MANAGER.MakeTextureStandard(PrefabContentBrowserIcon); - - // ************** Terrain Settings ************** - ExportHeightMapButton = new ImGuiButton("Export HeightMap"); - ExportHeightMapButton->SetSize(ImVec2(200, 0)); - - ImportHeightMapButton = new ImGuiButton("Import HeightMap"); - ImportHeightMapButton->SetSize(ImVec2(200, 0)); - - SculptBrushIcon = RESOURCE_MANAGER.LoadPNGTexture("Resources/Images/sculptBrush.png", "sculptBrushIcon"); - RESOURCE_MANAGER.MakeTextureStandard(SculptBrushIcon); - SculptBrushButton = new ImGuiImageButton(SculptBrushIcon); - SculptBrushButton->SetSize(ImVec2(24, 24)); - - LevelBrushIcon = RESOURCE_MANAGER.LoadPNGTexture("Resources/Images/levelBrush.png", "levelBrushIcon"); - RESOURCE_MANAGER.MakeTextureStandard(LevelBrushIcon); - LevelBrushButton = new ImGuiImageButton(LevelBrushIcon); - LevelBrushButton->SetSize(ImVec2(24, 24)); - - SmoothBrushIcon = RESOURCE_MANAGER.LoadPNGTexture("Resources/Images/smoothBrush.png", "smoothBrushIcon"); - RESOURCE_MANAGER.MakeTextureStandard(SmoothBrushIcon); - SmoothBrushButton = new ImGuiImageButton(SmoothBrushIcon); - SmoothBrushButton->SetSize(ImVec2(24, 24)); - - DrawBrushIcon = RESOURCE_MANAGER.LoadPNGTexture("Resources/Images/paintbrush.png", "drawBrushIcon"); - RESOURCE_MANAGER.MakeTextureStandard(DrawBrushIcon); - LayerBrushButton = new ImGuiImageButton(DrawBrushIcon); - LayerBrushButton->SetSize(ImVec2(48, 48)); - - EntityChangePrefabTarget = DRAG_AND_DROP_MANAGER.AddTarget(FE_PREFAB, EntityChangePrefabTargetCallBack, nullptr, "Drop to assign prefab"); - // ************** Terrain Settings END ************** - - AllContentBrowserIcon = RESOURCE_MANAGER.LoadPNGTexture("Resources/Images/allContentBrowserIcon.png", "allIcon"); - FilterAllTypesButton = new ImGuiImageButton(AllContentBrowserIcon); - RESOURCE_MANAGER.MakeTextureStandard(AllContentBrowserIcon); - FilterAllTypesButton->SetSize(ImVec2(32, 32)); - - FilterTextureTypeButton = new ImGuiImageButton(TextureContentBrowserIcon); - FilterTextureTypeButton->SetSize(ImVec2(32, 32)); - - FilterMeshTypeButton = new ImGuiImageButton(MeshContentBrowserIcon); - FilterMeshTypeButton->SetSize(ImVec2(32, 32)); - - FilterMaterialTypeButton = new ImGuiImageButton(MaterialContentBrowserIcon); - FilterMaterialTypeButton->SetSize(ImVec2(32, 32)); - - FilterGameModelTypeButton = new ImGuiImageButton(GameModelContentBrowserIcon); - FilterGameModelTypeButton->SetSize(ImVec2(32, 32)); - - FilterPrefabTypeButton = new ImGuiImageButton(PrefabContentBrowserIcon); - FilterPrefabTypeButton->SetSize(ImVec2(32, 32)); - - ENGINE.GetCamera()->SetOnUpdate(OnCameraUpdate); - ENGINE.AddWindowCloseCallback(CloseWindowCallBack); - - SetUpImgui(); -} - -void FEEditor::MouseMoveCallback(double Xpos, double Ypos) -{ - EDITOR.SetLastMouseX(EDITOR.GetMouseX()); - EDITOR.SetLastMouseY(EDITOR.GetMouseY()); - - EDITOR.SetMouseX(Xpos); - EDITOR.SetMouseY(Ypos); - - DRAG_AND_DROP_MANAGER.MouseMove(); - - if (SELECTED.GetSelected() != nullptr) - { - if (SELECTED.GetTerrain() != nullptr) - { - if (SELECTED.GetTerrain()->GetBrushMode() != FE_TERRAIN_BRUSH_NONE) - return; - } - - GIZMO_MANAGER.MouseMove(EDITOR.GetLastMouseX(), EDITOR.GetLastMouseY(), EDITOR.GetMouseX(), EDITOR.GetMouseY()); - } -} - -void FEEditor::OnCameraUpdate(FEBasicCamera* Camera) -{ - SELECTED.OnCameraUpdate(); - GIZMO_MANAGER.Render(); -} - -void FEEditor::Render() -{ - DRAG_AND_DROP_MANAGER.Render(); - - if (PROJECT_MANAGER.GetCurrent()) - { - if (bGameMode) - return; - - ImGui::DockSpaceOverViewport(ImGui::GetMainViewport()); - - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(15, 15)); - if (ImGui::BeginMainMenuBar()) - { - if (ImGui::BeginMenu("File")) - { - if (ImGui::MenuItem("Save project")) - { - PROJECT_MANAGER.GetCurrent()->SaveScene(); - ENGINE.TakeScreenshot((PROJECT_MANAGER.GetCurrent()->GetProjectFolder() + "projectScreenShot.texture").c_str()); - } - - if (ImGui::MenuItem("Save project as...")) - { - std::string path; - FILE_SYSTEM.ShowFolderOpenDialog(path); - if (!path.empty()) - { - PROJECT_MANAGER.GetCurrent()->SaveSceneTo(path + "\\"); - } - } - - if (ImGui::MenuItem("Close project")) - { - if (PROJECT_MANAGER.GetCurrent()->IsModified()) - { - projectWasModifiedPopUp::getInstance().Show(PROJECT_MANAGER.GetCurrent(), false); - } - else - { - PROJECT_MANAGER.CloseCurrentProject(); - strcpy_s(FilterForResourcesContentBrowser, ""); - strcpy_s(FilterForSceneEntities, ""); - - ImGui::PopStyleVar(); - ImGui::EndMenu(); - ImGui::EndMainMenuBar(); - - return; - } - } - - if (ImGui::MenuItem("Exit")) - { - if (PROJECT_MANAGER.GetCurrent()->IsModified()) - { - APPLICATION.GetMainWindow()->CancelClose(); - projectWasModifiedPopUp::getInstance().Show(PROJECT_MANAGER.GetCurrent(), true); - } - else - { - PROJECT_MANAGER.CloseCurrentProject(); - ENGINE.Terminate(); - return; - } - } - - ImGui::EndMenu(); - } - - if (ImGui::BeginMenu("Window")) - { - if (ImGui::MenuItem("Scene Entities", nullptr, bSceneBrowserVisible)) - { - bSceneBrowserVisible = !bSceneBrowserVisible; - } - - if (ImGui::MenuItem("Inspector", nullptr, bInspectorVisible)) - { - bInspectorVisible = !bInspectorVisible; - } - - if (ImGui::MenuItem("Content Browser", nullptr, bContentBrowserVisible)) - { - bContentBrowserVisible = !bContentBrowserVisible; - } - - if (ImGui::MenuItem("Effects", nullptr, bEffectsWindowVisible)) - { - bEffectsWindowVisible = !bEffectsWindowVisible; - } - - if (ImGui::MenuItem("Log", nullptr, bLogWindowVisible)) - { - bLogWindowVisible = !bLogWindowVisible; - } - - if (ImGui::BeginMenu("Debug")) - { - auto PossibleWindows = RENDERER.GetDebugOutputTextures(); - - auto iterator = PossibleWindows.begin(); - while (iterator != PossibleWindows.end()) - { - if (iterator->second != nullptr) - { - FEImGuiWindow* CurrentWindow = FE_IMGUI_WINDOW_MANAGER.GetWindowByCaption(iterator->first.c_str()); - bool bVisible = false; - if (CurrentWindow != nullptr) - bVisible = CurrentWindow->IsVisible(); - - if (ImGui::MenuItem(iterator->first.c_str(), nullptr, bVisible)) - { - bVisible = !bVisible; - - if (bVisible) - { - if (CurrentWindow == nullptr) - { - CurrentWindow = new debugTextureViewWindow(iterator->second); - CurrentWindow->SetCaption(iterator->first); - CurrentWindow->Show(); - } - else - { - CurrentWindow->Show(); - } - } - else - { - if (CurrentWindow != nullptr) - CurrentWindow->SetVisible(false); - } - } - } - iterator++; - } - - ImGui::EndMenu(); - } - - ImGui::EndMenu(); - } - - ImGui::EndMainMenuBar(); - } - ImGui::PopStyleVar(); - //ImGui::PopStyleVar(); - - ImGui::Begin("Scene", nullptr, ImGuiWindowFlags_None | ImGuiWindowFlags_NoScrollbar); - - SceneWindow = ImGui::GetCurrentWindow(); - SceneWindowTarget->StickToCurrentWindow(); - - ENGINE.SetRenderTargetSize((size_t)SceneWindow->ContentRegionRect.GetWidth(), (size_t)SceneWindow->ContentRegionRect.GetHeight()); - - ENGINE.SetRenderTargetXShift((int)SceneWindow->ContentRegionRect.GetTL().x); - ENGINE.SetRenderTargetYShift((int)SceneWindow->ContentRegionRect.GetTL().y); - - if (ENGINE.GetCamera()->GetCameraType() == 1) - ENGINE.RenderTargetCenterForCamera(reinterpret_cast(ENGINE.GetCamera())); - - ImGuiStyle& style = ImGui::GetStyle(); - style.WindowBorderSize = 0.0f; - style.WindowPadding = ImVec2(0.0f, 0.0f); - - if (RENDERER.FinalScene != nullptr) - { - ImGui::Image((void*)(intptr_t)RENDERER.FinalScene->GetTextureID(), ImVec2(ImGui::GetCurrentWindow()->ContentRegionRect.GetWidth(), ImGui::GetCurrentWindow()->ContentRegionRect.GetHeight()), ImVec2(0.0f, 1.0f), ImVec2(1.0f, 0.0f)); - } - else if (RENDERER.SceneToTextureFB->GetColorAttachment() != nullptr) - { - ImGui::Image((void*)(intptr_t)RENDERER.SceneToTextureFB->GetColorAttachment()->GetTextureID(), ImVec2(ImGui::GetCurrentWindow()->ContentRegionRect.GetWidth(), ImGui::GetCurrentWindow()->ContentRegionRect.GetHeight()), ImVec2(0.0f, 1.0f), ImVec2(1.0f, 0.0f)); - } - // Something went terribly wrong! - else - { - - } - - ImGui::End(); - - DisplaySceneBrowser(); - DisplayContentBrowser(); - DisplayInspector(); - DisplayEffectsWindow(); - DisplayLogWindow(); - if (!GyzmosSettingsWindowObject.IsVisible()) - GyzmosSettingsWindowObject.Show(); - GyzmosSettingsWindowObject.Render(); - - const int index = SELECTED.GetIndexOfObjectUnderMouse(EDITOR.GetMouseX(), EDITOR.GetMouseY()); - if (index >= 0) - { - if (!GIZMO_MANAGER.WasSelected(index)) - { - SELECTED.SetSelectedByIndex(index); - } - } - - RenderAllSubWindows(); - } - else - { - PROJECT_MANAGER.DisplayProjectSelection(); - } -} - -void FEEditor::CloseWindowCallBack() -{ - if (PROJECT_MANAGER.GetCurrent() == nullptr) - { - ENGINE.Terminate(); - return; - } - - if (PROJECT_MANAGER.GetCurrent()->IsModified()) - { - APPLICATION.GetMainWindow()->CancelClose(); - projectWasModifiedPopUp::getInstance().Show(PROJECT_MANAGER.GetCurrent(), true); - } - else - { - PROJECT_MANAGER.CloseCurrentProject(); - ENGINE.Terminate(); - return; - } -} - -void FEEditor::RenderTargetResizeCallback(int NewW, int NewH) -{ - if (ENGINE.GetCamera()->GetCameraType() == 1) - ENGINE.RenderTargetCenterForCamera(reinterpret_cast(ENGINE.GetCamera())); - SELECTED.ReInitializeResources(); -} - -void FEEditor::DropCallback(const int Count, const char** Paths) -{ - for (size_t i = 0; i < size_t(Count); i++) - { - if (FILE_SYSTEM.CheckDirectory(Paths[i]) && Count == 1) - { - if (PROJECT_MANAGER.GetCurrent() == nullptr) - { - PROJECT_MANAGER.SetProjectsFolder(Paths[i]); - } - } - - if (PROJECT_MANAGER.GetCurrent() != nullptr) - { - std::vector LoadedObjects = RESOURCE_MANAGER.ImportAsset(Paths[i]); - for (size_t j = 0; j < LoadedObjects.size(); j++) - { - if (LoadedObjects[j] != nullptr) - { - if (LoadedObjects[j]->GetType() == FE_ENTITY) - { - SCENE.AddEntity(reinterpret_cast(LoadedObjects[j])); - } - else - { - VIRTUAL_FILE_SYSTEM.CreateFile(LoadedObjects[j], VIRTUAL_FILE_SYSTEM.GetCurrentPath()); - PROJECT_MANAGER.GetCurrent()->SetModified(true); - PROJECT_MANAGER.GetCurrent()->AddUnSavedObject(LoadedObjects[j]); - } - } - } - } - } -} - -bool FEEditor::IsInGameMode() const -{ - return bGameMode; -} - -void FEEditor::SetGameMode(const bool GameMode) -{ - this->bGameMode = GameMode; - if (this->bGameMode) - { - ENGINE.SetRenderTargetMode(FE_GLFW_MODE); - if (ENGINE.GetCamera()->GetCameraType() == 1) - ENGINE.RenderTargetCenterForCamera(reinterpret_cast(ENGINE.GetCamera())); - } - else - { - ENGINE.SetRenderTargetMode(FE_CUSTOM_MODE); - if (ENGINE.GetCamera()->GetCameraType() == 1) - ENGINE.RenderTargetCenterForCamera(reinterpret_cast(ENGINE.GetCamera())); - } -} - -bool FEEditor::EntityChangePrefabTargetCallBack(FEObject* Object, void** EntityPointer) -{ - FEEntity* entity = SELECTED.GetEntity(); - if (entity == nullptr) - return false; - - entity->Prefab = (RESOURCE_MANAGER.GetPrefab(Object->GetObjectID())); - return true; -} - -bool FEEditor::TerrainChangeMaterialTargetCallBack(FEObject* Object, void** LayerIndex) -{ - FETerrain* terrain = SELECTED.GetTerrain(); - if (terrain == nullptr) - return false; - - FEMaterial* MaterialToAssign = RESOURCE_MANAGER.GetMaterial(Object->GetObjectID()); - if (!MaterialToAssign->IsCompackPacking()) - return false; - - const int TempLayerIndex = *(int*)LayerIndex; - if (TempLayerIndex >= 0 && TempLayerIndex < FE_TERRAIN_MAX_LAYERS) - terrain->GetLayerInSlot(TempLayerIndex)->SetMaterial(MaterialToAssign); - - return true; -} - -void FEEditor::ShowInFolderItem(FEObject* Object) -{ - VIRTUAL_FILE_SYSTEM.SetCurrentPath(VIRTUAL_FILE_SYSTEM.LocateFile(Object)); - ImGui::SetWindowFocus("Content Browser"); - strcpy_s(FilterForResourcesContentBrowser, ""); - ItemInFocus = Object; - - const auto Content = VIRTUAL_FILE_SYSTEM.GetDirectoryContent(VIRTUAL_FILE_SYSTEM.GetCurrentPath()); - size_t TotalItemCount = Content.size(); - - size_t ItemIndex = 0; - for (size_t i = 0; i < Content.size(); i++) - { - if (Content[i]->GetObjectID() == Object->GetObjectID()) - { - ItemIndex = i; - break; - } - } - - ImGuiWindow* ContentBrowserWindow = ImGui::FindWindowByName("Content Browser"); - const int IconsPerWindowWidth = (int)(ContentBrowserWindow->Rect().GetWidth() / (ContentBrowserItemIconSize + 8 + 32)); - const size_t ItemRow = ItemIndex / IconsPerWindowWidth; - - if (ContentBrowserWindow != nullptr) - { - ContentBrowserWindow->Scroll.y = float(ItemRow * (ContentBrowserItemIconSize + 8 + 8 + 32)); - } -} - -void FEEditor::DisplayInspector() -{ - if (!bInspectorVisible) - return; - - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(15, 15)); - ImGui::Begin("Inspector", nullptr, ImGuiWindowFlags_None); - - if (SELECTED.GetSelected() == nullptr) - { - ImGui::PopStyleVar(); - ImGui::End(); - return; - } - - if (SELECTED.GetEntity() != nullptr) - { - FEEntity* entity = SELECTED.GetEntity(); - - if (entity->GetType() == FE_ENTITY) - { - ShowTransformConfiguration(entity, &entity->Transform); - - ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor(0.5f, 0.5f, 0.5f)); - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::ImColor(0.95f, 0.90f, 0.0f)); - ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::ImColor(0.1f, 1.0f, 0.1f, 1.0f)); - - bool bActive = entity->IsWireframeMode(); - ImGui::Checkbox("WireframeMode", &bActive); - entity->SetWireframeMode(bActive); - - ImGui::Separator(); - ImGui::Text("Prefab : "); - FETexture* PreviewTexture = PREVIEW_MANAGER.GetPrefabPreview(entity->Prefab->GetObjectID()); - - if (ImGui::ImageButton((void*)(intptr_t)PreviewTexture->GetTextureID(), ImVec2(128, 128), ImVec2(0.0f, 1.0f), ImVec2(1.0f, 0.0f), 8, ImColor(0.0f, 0.0f, 0.0f, 0.0f), ImColor(1.0f, 1.0f, 1.0f, 1.0f))) - { - EntityToModify = entity; - SelectFeObjectPopUp::getInstance().Show(FE_PREFAB, ChangePrefabOfEntityCallBack, entity->Prefab); - - } - EntityChangePrefabTarget->StickToItem(); - - bool open_context_menu = false; - if (ImGui::IsItemHovered() && ImGui::IsMouseClicked(1)) - open_context_menu = true; - - if (open_context_menu) - ImGui::OpenPopup("##Inspector_context_menu"); - - bShouldOpenContextMenuInContentBrowser = false; - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(15, 15)); - if (ImGui::BeginPopup("##Inspector_context_menu")) - { - bShouldOpenContextMenuInContentBrowser = true; - - if (ImGui::MenuItem("Show in folder")) - { - ShowInFolderItem(entity->Prefab); - } - - ImGui::EndPopup(); - } - ImGui::PopStyleVar(); - - ImGui::Separator(); - - ImGui::PopStyleColor(); - ImGui::PopStyleColor(); - ImGui::PopStyleColor(); - } - else if (entity->GetType() == FE_ENTITY_INSTANCED) - { - FEEntityInstanced* InstancedEntity = reinterpret_cast(entity); - - if (SELECTED.InstancedSubObjectIndexSelected != -1) - { - std::string InstancedSubObjectInfo = "index: "; - - ImGui::Text("Selected instance info:"); - InstancedSubObjectInfo = "index: " + std::to_string(SELECTED.InstancedSubObjectIndexSelected); - ImGui::Text(InstancedSubObjectInfo.c_str()); - - FETransformComponent TempTransform = FETransformComponent(InstancedEntity->GetTransformedInstancedMatrix(SELECTED.InstancedSubObjectIndexSelected)); - ShowTransformConfiguration("selected instance", &TempTransform); - InstancedEntity->ModifyInstance(SELECTED.InstancedSubObjectIndexSelected, TempTransform.GetTransformMatrix()); - - ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor(0.55f, 0.55f, 0.95f)); - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::ImColor(0.75f, 0.75f, 0.95f)); - ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::ImColor(0.75f, 0.75f, 0.95f)); - - if (ImGui::ImageButton((void*)(intptr_t)ArrowToGroundIcon->GetTextureID(), ImVec2(64, 64), ImVec2(0.0f, 0.0f), ImVec2(1.0f, 1.0f), 8, ImColor(0.0f, 0.0f, 0.0f, 0.0f), ImColor(1.0f, 1.0f, 1.0f, 1.0f))) - { - InstancedEntity->TryToSnapInstance(SELECTED.InstancedSubObjectIndexSelected); - } - ShowToolTip("Selected instance will attempt to snap to the terrain."); - - ImGui::PopStyleColor(); - ImGui::PopStyleColor(); - ImGui::PopStyleColor(); - } - else - { - ShowTransformConfiguration(entity, &entity->Transform); - - ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor(0.5f, 0.5f, 0.5f)); - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::ImColor(0.95f, 0.90f, 0.0f)); - ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::ImColor(0.1f, 1.0f, 0.1f, 1.0f)); - - ImGui::Separator(); - - ImGui::Text("Prefab : "); - FETexture* PreviewTexture = PREVIEW_MANAGER.GetPrefabPreview(entity->Prefab->GetObjectID()); - if (ImGui::ImageButton((void*)(intptr_t)PreviewTexture->GetTextureID(), ImVec2(128, 128), ImVec2(0.0f, 1.0f), ImVec2(1.0f, 0.0f), 8, ImColor(0.0f, 0.0f, 0.0f, 0.0f), ImColor(1.0f, 1.0f, 1.0f, 1.0f))) - { - EntityToModify = entity; - SelectFeObjectPopUp::getInstance().Show(FE_PREFAB, ChangePrefabOfEntityCallBack, entity->Prefab); - } - EntityChangePrefabTarget->StickToItem(); - - bool open_context_menu = false; - if (ImGui::IsItemHovered() && ImGui::IsMouseClicked(1)) - open_context_menu = true; - - if (open_context_menu) - ImGui::OpenPopup("##Inspector_context_menu"); - - bShouldOpenContextMenuInContentBrowser = false; - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(15, 15)); - if (ImGui::BeginPopup("##Inspector_context_menu")) - { - bShouldOpenContextMenuInContentBrowser = true; - - if (ImGui::MenuItem("Show in folder")) - { - ShowInFolderItem(entity->Prefab); - } - - ImGui::EndPopup(); - } - ImGui::PopStyleVar(); - ImGui::Separator(); - - ImGui::PopStyleColor(); - ImGui::PopStyleColor(); - ImGui::PopStyleColor(); - - ImGui::Text("Snapped to: "); - ImGui::SameLine(); - - const std::vector TerrainList = SCENE.GetTerrainList(); - static std::string CurrentTerrain = "none"; - - if (InstancedEntity->GetSnappedToTerrain() == nullptr) - { - CurrentTerrain = "none"; - } - else - { - CurrentTerrain = InstancedEntity->GetSnappedToTerrain()->GetName(); - } - - ImGui::SetNextItemWidth(220); - if (ImGui::BeginCombo("##Terrain", CurrentTerrain.c_str(), ImGuiWindowFlags_None)) - { - const bool is_selected = (CurrentTerrain == "none"); - if (ImGui::Selectable("none", is_selected)) - { - if (InstancedEntity->GetSnappedToTerrain() != nullptr) - InstancedEntity->GetSnappedToTerrain()->UnSnapInstancedEntity(InstancedEntity); - } - - if (is_selected) - ImGui::SetItemDefaultFocus(); - - for (size_t i = 0; i < TerrainList.size(); i++) - { - const bool is_selected = (CurrentTerrain == TerrainList[i]); - if (ImGui::Selectable(SCENE.GetTerrain(TerrainList[i])->GetName().c_str(), is_selected)) - { - SCENE.GetTerrain(TerrainList[i])->SnapInstancedEntity(InstancedEntity); - } - - if (is_selected) - ImGui::SetItemDefaultFocus(); - } - ImGui::EndCombo(); - } - - if (InstancedEntity->GetSnappedToTerrain() != nullptr) - { - ImGui::Text("Terrain layer: "); - ImGui::SameLine(); - - const int CurrentLayer = InstancedEntity->GetTerrainLayer(); - FETerrain* CurrentTerrain = InstancedEntity->GetSnappedToTerrain(); - - std::string caption = "none"; - const auto layer = CurrentTerrain->GetLayerInSlot(CurrentLayer); - if (layer != nullptr) - caption = layer->GetName(); - - ImGui::SetNextItemWidth(220); - if (ImGui::BeginCombo("##TerrainLayers", caption.c_str(), ImGuiWindowFlags_None)) + auto iterator = PossibleWindows.begin(); + while (iterator != PossibleWindows.end()) { - const bool is_selected = (CurrentLayer == -1); - ImGui::PushID("none_TerrainLayers_entity"); - if (ImGui::Selectable("none", is_selected)) - { - if (CurrentTerrain != nullptr) - CurrentTerrain->UnConnectInstancedEntityFromLayer(InstancedEntity); - } - ImGui::PopID(); - - if (is_selected) - ImGui::SetItemDefaultFocus(); - - for (size_t i = 0; i < FE_TERRAIN_MAX_LAYERS; i++) + if (iterator->second != nullptr) { - FETerrainLayer* layer = CurrentTerrain->GetLayerInSlot(i); - if (layer == nullptr) - break; - - const bool is_selected = (CurrentLayer == i); - ImGui::PushID(layer->GetObjectID().c_str()); - if (ImGui::Selectable(layer->GetName().c_str(), is_selected)) + FEImGuiWindow* CurrentWindow = FE_IMGUI_WINDOW_MANAGER.GetWindowByCaption(iterator->first.c_str()); + bool bVisible = false; + if (CurrentWindow != nullptr) + bVisible = CurrentWindow->IsVisible(); + + if (ImGui::MenuItem(iterator->first.c_str(), nullptr, bVisible)) { - CurrentTerrain->ConnectInstancedEntityToLayer(InstancedEntity, int(i)); - } - ImGui::PopID(); - - if (is_selected) - ImGui::SetItemDefaultFocus(); - } - ImGui::EndCombo(); - } - - if (CurrentLayer != -1) - { - ImGui::Text("Minimal layer intensity:"); - float MinLevel = InstancedEntity->GetMinimalLayerIntensity(); - ImGui::SameLine(); - ImGui::SetNextItemWidth(80); - ImGui::DragFloat("##minLevel", &MinLevel); - InstancedEntity->SetMinimalLayerIntensity(MinLevel); - } - } - - ImGui::Separator(); - - ImGui::Text("Seed:"); - int seed = InstancedEntity->SpawnInfo.Seed; - ImGui::SameLine(); - ImGui::SetNextItemWidth(200); - ImGui::DragInt("##Seed", &seed); - InstancedEntity->SpawnInfo.Seed = seed; - - ImGui::Text("Object count:"); - int ObjectCount = InstancedEntity->SpawnInfo.ObjectCount; - ImGui::SameLine(); - ImGui::SetNextItemWidth(200); - ImGui::DragInt("##Object count", &ObjectCount); - if (ObjectCount <= 0) - ObjectCount = 1; - InstancedEntity->SpawnInfo.ObjectCount = ObjectCount; - - ImGui::Text("Radius:"); - float radius = InstancedEntity->SpawnInfo.Radius; - ImGui::SameLine(); - ImGui::SetNextItemWidth(200); - ImGui::DragFloat("##Radius", &radius); - if (radius < 0.0f) - radius = 0.1f; - InstancedEntity->SpawnInfo.Radius = radius; - - // Scale deviation. - ImGui::Text("Scale: "); - - ImGui::SameLine(); - ImGui::Text("min "); - - ImGui::SameLine(); - ImGui::SetNextItemWidth(100); - float MinScale = InstancedEntity->SpawnInfo.GetMinScale(); - ImGui::DragFloat("##minScale", &MinScale, 0.01f); - InstancedEntity->SpawnInfo.SetMinScale(MinScale); - - ImGui::SameLine(); - ImGui::Text("max "); - - ImGui::SameLine(); - float MaxScale = InstancedEntity->SpawnInfo.GetMaxScale(); - ImGui::SetNextItemWidth(100); - ImGui::DragFloat("##maxScale", &MaxScale, 0.01f); - InstancedEntity->SpawnInfo.SetMaxScale(MaxScale); - - ImGui::Text("Rotation deviation:"); - float RotationDeviationX = InstancedEntity->SpawnInfo.RotationDeviation.x; - ImGui::Text("X:"); - ImGui::SameLine(); - ImGui::DragFloat("##Rotation deviation X", &RotationDeviationX, 0.01f); - if (RotationDeviationX < 0.01f) - RotationDeviationX = 0.01f; - if (RotationDeviationX > 1.0f) - RotationDeviationX = 1.0f; - InstancedEntity->SpawnInfo.RotationDeviation.x = RotationDeviationX; - - float RotationDeviationY = InstancedEntity->SpawnInfo.RotationDeviation.y; - ImGui::Text("Y:"); - ImGui::SameLine(); - ImGui::DragFloat("##Rotation deviation Y", &RotationDeviationY, 0.01f); - if (RotationDeviationY < 0.01f) - RotationDeviationY = 0.01f; - if (RotationDeviationY > 1.0f) - RotationDeviationY = 1.0f; - InstancedEntity->SpawnInfo.RotationDeviation.y = RotationDeviationY; - - float RotationDeviationZ = InstancedEntity->SpawnInfo.RotationDeviation.z; - ImGui::Text("Z:"); - ImGui::SameLine(); - ImGui::DragFloat("##Rotation deviation z", &RotationDeviationZ, 0.01f); - if (RotationDeviationZ < 0.01f) - RotationDeviationZ = 0.01f; - if (RotationDeviationZ > 1.0f) - RotationDeviationZ = 1.0f; - InstancedEntity->SpawnInfo.RotationDeviation.z = RotationDeviationZ; - - if (ImGui::Button("Spawn/Re-Spawn")) - { - InstancedEntity->Clear(); - InstancedEntity->Populate(InstancedEntity->SpawnInfo); - } - - if (ImGui::Button("Add instance")) - { - glm::mat4 NewInstanceMatrix = glm::identity(); - NewInstanceMatrix = glm::translate(NewInstanceMatrix, ENGINE.GetCamera()->GetPosition() + ENGINE.GetCamera()->GetForward() * 10.0f); - InstancedEntity->AddInstance(NewInstanceMatrix); - - PROJECT_MANAGER.GetCurrent()->SetModified(true); - } - - if (InstancedEntity->IsSelectMode()) - { - ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor(0.0f, 0.75f, 0.0f)); - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::ImColor(0.0f, 1.0f, 0.0f)); - ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::ImColor(0.0f, 1.0f, 0.0f)); - } - else - { - ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor(0.55f, 0.55f, 0.95f)); - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::ImColor(0.75f, 0.75f, 0.95f)); - ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::ImColor(0.75f, 0.75f, 0.95f)); - } - - ImGui::Separator(); - if (ImGui::ImageButton((void*)(intptr_t)MouseCursorIcon->GetTextureID(), ImVec2(64, 64), ImVec2(0.0f, 0.0f), ImVec2(1.0f, 1.0f), 8, ImColor(0.0f, 0.0f, 0.0f, 0.0f), ImColor(1.0f, 1.0f, 1.0f, 1.0f))) - { - SCENE.SetSelectMode(InstancedEntity, !InstancedEntity->IsSelectMode()); - if (!InstancedEntity->IsSelectMode()) - { - SELECTED.Clear(); - SELECTED.SetSelected(InstancedEntity); - } - } - ShowToolTip("Individual selection mode - Used to select individual instances."); - - ImGui::PopStyleColor(); - ImGui::PopStyleColor(); - ImGui::PopStyleColor(); - } - } - } - else if (SELECTED.GetTerrain() != nullptr) - { - FETerrain* CurrentTerrain = SELECTED.GetTerrain(); - DisplayTerrainSettings(CurrentTerrain); - - if (CurrentTerrain->GetBrushMode() != FE_TERRAIN_BRUSH_NONE) - { - // to hide gizmos - if (SELECTED.GetTerrain() != nullptr) - SELECTED.SetSelected(SELECTED.GetTerrain()); - - CurrentTerrain->SetBrushActive(EDITOR.bLeftMousePressed); - - if (EDITOR.bShiftPressed) - { - if (CurrentTerrain->GetBrushMode() == FE_TERRAIN_BRUSH_SCULPT_DRAW) - CurrentTerrain->SetBrushMode(FE_TERRAIN_BRUSH_SCULPT_DRAW_INVERSED); - } - else - { - if (CurrentTerrain->GetBrushMode() == FE_TERRAIN_BRUSH_SCULPT_DRAW_INVERSED) - CurrentTerrain->SetBrushMode(FE_TERRAIN_BRUSH_SCULPT_DRAW); - } - - /*if (EDITOR.bLeftMousePressed) - { - if (EDITOR.bShiftPressed) - { - currentTerrain->setBrushMode(FE_TERRAIN_BRUSH_SCULPT_DRAW_INVERSED); - } - else - { - currentTerrain->setBrushMode(FE_TERRAIN_BRUSH_SCULPT_DRAW); - } - } - else - { - currentTerrain->setBrushMode(FE_TERRAIN_BRUSH_NONE); - }*/ - - //currentTerrain->setBrushActive(EDITOR.bLeftMousePressed); - //currentTerrain->setBrushInversed(EDITOR.bShiftPressed); - } - else - { - // to show gizmos - if (SELECTED.GetTerrain() != nullptr) - SELECTED.SetSelected(SELECTED.GetTerrain()); - } - } - else if (SELECTED.GetLight() != nullptr) - { - DisplayLightProperties(SELECTED.GetLight()); - } - else if (SELECTED.GetSelected()->GetType() == FE_CAMERA) - { - FEBasicCamera* camera = ENGINE.GetCamera(); - - // ********* POSITION ********* - glm::vec3 CameraPosition = camera->GetPosition(); - - ImGui::Text("Position : "); - ImGui::SameLine(); - ImGui::SetNextItemWidth(90); - ImGui::DragFloat("##X pos", &CameraPosition[0], 0.1f); - ShowToolTip("X position"); - - ImGui::SameLine(); - ImGui::SetNextItemWidth(90); - ImGui::DragFloat("##Y pos", &CameraPosition[1], 0.1f); - ShowToolTip("Y position"); - - ImGui::SameLine(); - ImGui::SetNextItemWidth(90); - ImGui::DragFloat("##Z pos", &CameraPosition[2], 0.1f); - ShowToolTip("Z position"); - - camera->SetPosition(CameraPosition); - - // ********* ROTATION ********* - glm::vec3 CameraRotation = glm::vec3(camera->GetYaw(), camera->GetPitch(), camera->GetRoll()); - - ImGui::Text("Rotation : "); - ImGui::SameLine(); - ImGui::SetNextItemWidth(90); - ImGui::DragFloat("##X rot", &CameraRotation[0], 0.1f); - ShowToolTip("X rotation"); - - ImGui::SameLine(); - ImGui::SetNextItemWidth(90); - ImGui::DragFloat("##Y rot", &CameraRotation[1], 0.1f); - ShowToolTip("Y rotation"); - - ImGui::SameLine(); - ImGui::SetNextItemWidth(90); - ImGui::DragFloat("##Z rot", &CameraRotation[2], 0.1f); - ShowToolTip("Z rotation"); - - camera->SetYaw(CameraRotation[0]); - camera->SetPitch(CameraRotation[1]); - camera->SetRoll(CameraRotation[2]); - - float CameraSpeed = camera->GetMovementSpeed(); - ImGui::Text("Camera speed in m/s : "); - ImGui::SameLine(); - ImGui::SetNextItemWidth(70); - ImGui::DragFloat("##Camera_speed", &CameraSpeed, 0.01f, 0.01f, 100.0f); - camera->SetMovementSpeed(CameraSpeed); - } - - ImGui::PopStyleVar(); - ImGui::End(); -} - -void FEEditor::DisplayEffectsWindow() const -{ - if (!bEffectsWindowVisible) - return; - - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(15, 15)); - ImGui::Begin("Effects settings", nullptr, ImGuiWindowFlags_None); - - int GUIID = 0; - static float ButtonWidth = 80.0f; - static float FieldWidth = 250.0f; - - static ImGuiButton* ResetButton = new ImGuiButton("Reset"); - static bool bFirstCall = true; - if (bFirstCall) - { - ResetButton->SetSize(ImVec2(ButtonWidth, 28.0f)); - bFirstCall = false; - } - - if (ImGui::CollapsingHeader("Gamma Correction & Exposure", 0)) - { - ImGui::Text("Gamma Correction:"); - float Gamma = ENGINE.GetCamera()->GetGamma(); - ImGui::SetNextItemWidth(FieldWidth); - ImGui::DragFloat("##Gamma Correction", &Gamma, 0.01f, 0.001f, 10.0f); - ENGINE.GetCamera()->SetGamma(Gamma); - - ImGui::PushID(GUIID++); - ImGui::SameLine(); - ResetButton->Render(); - if (ResetButton->IsClicked()) - { - ENGINE.GetCamera()->SetGamma(2.2f); - } - ImGui::PopID(); - - ImGui::Text("Exposure:"); - float Exposure = ENGINE.GetCamera()->GetExposure(); - ImGui::SetNextItemWidth(FieldWidth); - ImGui::DragFloat("##Exposure", &Exposure, 0.01f, 0.001f, 100.0f); - ENGINE.GetCamera()->SetExposure(Exposure); - - ImGui::PushID(GUIID++); - ImGui::SameLine(); - ResetButton->Render(); - if (ResetButton->IsClicked()) - { - ENGINE.GetCamera()->SetExposure(1.0f); - } - ImGui::PopID(); - } - - if (ImGui::CollapsingHeader("Anti-Aliasing(FXAA)", 0)) - { - static const char* options[5] = { "none", "1x", "2x", "4x", "8x" }; - static std::string SelectedOption = "1x"; - - static bool bFirstLook = true; - if (bFirstLook) - { - const float FXAASpanMax = RENDERER.GetFXAASpanMax(); - if (FXAASpanMax == 0.0f) - { - SelectedOption = options[0]; - } - else if (FXAASpanMax > 0.1f && FXAASpanMax < 1.1f) - { - SelectedOption = options[1]; - } - else if (FXAASpanMax > 1.1f && FXAASpanMax < 2.1f) - { - SelectedOption = options[2]; - } - else if (FXAASpanMax > 2.1f && FXAASpanMax < 4.1f) - { - SelectedOption = options[3]; - } - else if (FXAASpanMax > 4.1f && FXAASpanMax < 8.1f) - { - SelectedOption = options[4]; - } - else - { - SelectedOption = options[5]; - } - - bFirstLook = false; - } - - static bool bDebugSettings = false; - if (ImGui::Checkbox("debug view", &bDebugSettings)) - { - const float FXAASpanMax = RENDERER.GetFXAASpanMax(); - if (FXAASpanMax == 0.0f) - { - SelectedOption = options[0]; - } - else if (FXAASpanMax > 0.1f && FXAASpanMax < 1.1f) - { - SelectedOption = options[1]; - } - else if (FXAASpanMax > 1.1f && FXAASpanMax < 2.1f) - { - SelectedOption = options[2]; - } - else if (FXAASpanMax > 2.1f && FXAASpanMax < 4.1f) - { - SelectedOption = options[3]; - } - else if (FXAASpanMax > 4.1f && FXAASpanMax < 8.1f) - { - SelectedOption = options[4]; - } - else - { - SelectedOption = options[5]; - } - } - - if (!bDebugSettings) - { - ImGui::Text("Anti Aliasing Strength:"); - if (ImGui::BeginCombo("##Anti Aliasing Strength", SelectedOption.c_str(), ImGuiWindowFlags_None)) - { - for (size_t i = 0; i < 5; i++) - { - const bool is_selected = (SelectedOption == options[i]); - if (ImGui::Selectable(options[i], is_selected)) - { - RENDERER.SetFXAASpanMax(float(pow(2.0, (i - 1)))); - if (i == 0) - RENDERER.SetFXAASpanMax(0.0f); - SelectedOption = options[i]; - } - - if (is_selected) - ImGui::SetItemDefaultFocus(); - } - ImGui::EndCombo(); - } - } - else - { - ImGui::Text("FXAASpanMax:"); - ImGui::SetNextItemWidth(FieldWidth); - float FXAASpanMax = RENDERER.GetFXAASpanMax(); - ImGui::DragFloat("##FXAASpanMax", &FXAASpanMax, 0.0f, 0.001f, 32.0f); - RENDERER.SetFXAASpanMax(FXAASpanMax); - - ImGui::PushID(GUIID++); - ImGui::SameLine(); - ResetButton->Render(); - if (ResetButton->IsClicked()) - { - RENDERER.SetFXAASpanMax(8.0f); - } - ImGui::PopID(); - - ImGui::Text("FXAAReduceMin:"); - ImGui::SetNextItemWidth(FieldWidth); - float FXAAReduceMin = RENDERER.GetFXAAReduceMin(); - ImGui::DragFloat("##FXAAReduceMin", &FXAAReduceMin, 0.01f, 0.001f, 100.0f); - RENDERER.SetFXAAReduceMin(FXAAReduceMin); - - ImGui::PushID(GUIID++); - ImGui::SameLine(); - ResetButton->Render(); - if (ResetButton->IsClicked()) - { - RENDERER.SetFXAAReduceMin(0.008f); - } - ImGui::PopID(); - - ImGui::Text("FXAAReduceMul:"); - ImGui::SetNextItemWidth(FieldWidth); - float FXAAReduceMul = RENDERER.GetFXAAReduceMul(); - ImGui::DragFloat("##FXAAReduceMul", &FXAAReduceMul, 0.01f, 0.001f, 100.0f); - RENDERER.SetFXAAReduceMul(FXAAReduceMul); - - ImGui::PushID(GUIID++); - ImGui::SameLine(); - ResetButton->Render(); - if (ResetButton->IsClicked()) - { - RENDERER.SetFXAAReduceMul(0.400f); - } - ImGui::PopID(); - } - } - - if (ImGui::CollapsingHeader("Bloom", 0)) - { - ImGui::Text("Threshold:"); - float Threshold = RENDERER.GetBloomThreshold(); - ImGui::SetNextItemWidth(FieldWidth); - ImGui::DragFloat("##Threshold", &Threshold, 0.01f, 0.001f, 30.0f); - RENDERER.SetBloomThreshold(Threshold); - - ImGui::PushID(GUIID++); - ImGui::SameLine(); - ResetButton->Render(); - if (ResetButton->IsClicked()) - { - RENDERER.SetBloomThreshold(1.5f); - } - ImGui::PopID(); - - ImGui::Text("Size:"); - float Size = RENDERER.GetBloomSize(); - ImGui::SetNextItemWidth(FieldWidth); - ImGui::DragFloat("##BloomSize", &Size, 0.01f, 0.001f, 100.0f); - RENDERER.SetBloomSize(Size); - - ImGui::PushID(GUIID++); - ImGui::SameLine(); - ResetButton->Render(); - if (ResetButton->IsClicked()) - { - RENDERER.SetBloomSize(5.0f); - } - ImGui::PopID(); - } + bVisible = !bVisible; - if (ImGui::CollapsingHeader("Depth of Field", 0)) - { - ImGui::Text("Near distance:"); - ImGui::SetNextItemWidth(FieldWidth); - float DepthThreshold = RENDERER.GetDOFNearDistance(); - ImGui::DragFloat("##depthThreshold", &DepthThreshold, 0.0f, 0.001f, 100.0f); - RENDERER.SetDOFNearDistance(DepthThreshold); - - ImGui::Text("Far distance:"); - ImGui::SetNextItemWidth(FieldWidth); - float DepthThresholdFar = RENDERER.GetDOFFarDistance(); - ImGui::DragFloat("##depthThresholdFar", &DepthThresholdFar, 0.0f, 0.001f, 100.0f); - RENDERER.SetDOFFarDistance(DepthThresholdFar); - - ImGui::Text("Strength:"); - ImGui::SetNextItemWidth(FieldWidth); - float Strength = RENDERER.GetDOFStrength(); - ImGui::DragFloat("##Strength", &Strength, 0.0f, 0.001f, 10.0f); - RENDERER.SetDOFStrength(Strength); - - ImGui::Text("Distance dependent strength:"); - ImGui::SetNextItemWidth(FieldWidth); - float IntMult = RENDERER.GetDOFDistanceDependentStrength(); - ImGui::DragFloat("##Distance dependent strength", &IntMult, 0.0f, 0.001f, 100.0f); - RENDERER.SetDOFDistanceDependentStrength(IntMult); - } + if (bVisible) + { + if (CurrentWindow == nullptr) + { + CurrentWindow = new DebugTextureViewWindow(iterator->second); + CurrentWindow->SetCaption(iterator->first); + CurrentWindow->Show(); + } + else + { + CurrentWindow->Show(); + } + } + else + { + if (CurrentWindow != nullptr) + CurrentWindow->SetVisible(false); + } + } + } + iterator++; + } - if (ImGui::CollapsingHeader("Distance fog", 0)) - { - bool bEnabledFog = RENDERER.IsDistanceFogEnabled(); - if (ImGui::Checkbox("Enable fog", &bEnabledFog)) - { - RENDERER.SetDistanceFogEnabled(bEnabledFog); - } + ImGui::EndMenu(); + } - if (bEnabledFog) - { - ImGui::Text("Density:"); - ImGui::SetNextItemWidth(FieldWidth); - float FogDensity = RENDERER.GetDistanceFogDensity(); - ImGui::DragFloat("##fogDensity", &FogDensity, 0.0001f, 0.0f, 5.0f); - RENDERER.SetDistanceFogDensity(FogDensity); - - ImGui::PushID(GUIID++); - ImGui::SameLine(); - ResetButton->Render(); - if (ResetButton->IsClicked()) - { - RENDERER.SetDistanceFogDensity(0.007f); - } - ImGui::PopID(); - - ImGui::Text("Gradient:"); - ImGui::SetNextItemWidth(FieldWidth); - float FogGradient = RENDERER.GetDistanceFogGradient(); - ImGui::DragFloat("##fogGradient", &FogGradient, 0.001f, 0.0f, 5.0f); - RENDERER.SetDistanceFogGradient(FogGradient); - - ImGui::PushID(GUIID++); - ImGui::SameLine(); - ResetButton->Render(); - if (ResetButton->IsClicked()) - { - RENDERER.SetDistanceFogGradient(2.5f); + ImGui::EndMenu(); } - ImGui::PopID(); - } - } - if (ImGui::CollapsingHeader("Chromatic Aberration", 0)) - { - ImGui::Text("Shift strength:"); - ImGui::SetNextItemWidth(FieldWidth); - float intensity = RENDERER.GetChromaticAberrationIntensity(); - ImGui::DragFloat("##intensity", &intensity, 0.01f, 0.0f, 30.0f); - RENDERER.SetChromaticAberrationIntensity(intensity); - - ImGui::PushID(GUIID++); - ImGui::SameLine(); - ResetButton->Render(); - if (ResetButton->IsClicked()) - { - RENDERER.SetChromaticAberrationIntensity(1.0f); + ImGui::EndMainMenuBar(); } - ImGui::PopID(); - } + ImGui::PopStyleVar(); - if (ImGui::CollapsingHeader("Sky", 0)) - { - bool bEnabledSky = RENDERER.IsSkyEnabled(); - if (ImGui::Checkbox("enable sky", &bEnabledSky)) + bool bFocusedSceneCouldBeUsedForGameMode = false; + if (EDITOR.GetFocusedScene() != nullptr) { - RENDERER.SetSkyEnabled(bEnabledSky); + FEEditorSceneWindow* SceneWindow = GetEditorSceneWindow(EDITOR.GetFocusedScene()->GetObjectID()); + // Focused scene could be prefab scene + if (!PREFAB_EDITOR_MANAGER.IsEditorWindowIsPrefabWindow(SceneWindow)) + bFocusedSceneCouldBeUsedForGameMode = true; } - ImGui::Text("Sphere size:"); - ImGui::SetNextItemWidth(FieldWidth); - float size = RENDERER.GetDistanceToSky(); - ImGui::DragFloat("##Sphere size", &size, 0.01f, 0.0f, 200.0f); - RENDERER.SetDistanceToSky(size); - ImGui::PushID(GUIID++); - ImGui::SameLine(); - ResetButton->Render(); - if (ResetButton->IsClicked()) + std::string ButtonText = "Run game mode"; + + if (EDITOR.IsInGameMode()) { - RENDERER.SetDistanceToSky(50.0f); + ButtonText = "Exit game mode"; } - ImGui::PopID(); - } - - if (ImGui::CollapsingHeader("SSAO", 0)) - { - static const char* options[5] = { "Off", "Low", "Medium", "High", "Custom"}; - static std::string SelectedOption = "Medium"; - - static bool bFirstLook = true; - if (bFirstLook) + else { - const int SampleCount = RENDERER.GetSSAOSampleCount(); - - if (!RENDERER.IsSSAOEnabled()) + if (!bFocusedSceneCouldBeUsedForGameMode) { - SelectedOption = options[0]; + ButtonText = "Can not run game mode (focused scene is prefab scene)."; } - else if (SampleCount == 4) - { - SelectedOption = options[1]; - } - else if (SampleCount == 16 && RENDERER.GetSSAORadiusSmallDetails()) - { - SelectedOption = options[2]; - } - else if (SampleCount == 32 && RENDERER.GetSSAORadiusSmallDetails()) - { - SelectedOption = options[3]; - } - else - { - SelectedOption = options[4]; - } - - //bFirstLook = false; } - static bool bDebugSettings = false; - if (ImGui::Checkbox("Debug view", &bDebugSettings)) - { + if (!bFocusedSceneCouldBeUsedForGameMode) + ImGui::BeginDisabled(); + if (ImGui::Button(ButtonText.c_str(), ImVec2(220, 0))) + { + EDITOR.SetGameMode(!EDITOR.IsInGameMode()); } - - if (!bDebugSettings) + + if (!bFocusedSceneCouldBeUsedForGameMode) + ImGui::EndDisabled(); + + for (size_t i = 0; i < EditorSceneWindows.size(); i++) { - ImGui::Text("SSAO Quality:"); - ImGui::SetNextItemWidth(150); - if (ImGui::BeginCombo("##SSAO Quality", SelectedOption.c_str(), ImGuiWindowFlags_None)) + // Rendeting would be done by RenderAllSubWindows(). + // + // Check if some window is waiting for removal + if (EditorSceneWindows[i]->bWaitingForRemoval) { - for (size_t i = 0; i < 5; i++) + if (FocusedEditorSceneID == EditorSceneWindows[i]->Scene->GetObjectID()) { - const bool is_selected = (SelectedOption == options[i]); - if (ImGui::Selectable(options[i], is_selected)) + FocusedEditorSceneID = ""; + for (size_t j = 0; j < EditorSceneWindows.size(); j++) { - RENDERER.SetSSAOResultBlured(true); - RENDERER.SetSSAOBias(0.013f); - RENDERER.SetSSAORadius(10.0f); - RENDERER.SetSSAORadiusSmallDetails(0.4f); - RENDERER.SetSSAOSmallDetailsWeight(0.2f); - - if (i == 0) - { - RENDERER.SetSSAOEnabled(false); - } - else if (i == 1) - { - RENDERER.SetSSAOEnabled(true); - - RENDERER.SetSSAOSampleCount(4); - RENDERER.SetSSAOSmallDetailsEnabled(false); - } - else if (i == 2) - { - RENDERER.SetSSAOEnabled(true); - - RENDERER.SetSSAOSampleCount(16); - RENDERER.SetSSAOSmallDetailsEnabled(true); - } - else if (i == 3) + if (EditorSceneWindows[j] != EditorSceneWindows[i]) { - RENDERER.SetSSAOEnabled(true); - - RENDERER.SetSSAOSampleCount(32); - RENDERER.SetSSAOSmallDetailsEnabled(true); + SetFocusedScene(EditorSceneWindows[j]->Scene->GetObjectID()); + break; } - - SelectedOption = options[i]; } - - if (is_selected) - ImGui::SetItemDefaultFocus(); } - ImGui::EndCombo(); + + FEScene* Scene = EditorSceneWindows[i]->Scene; + delete EditorSceneWindows[i]; + EditorSceneWindows.erase(EditorSceneWindows.begin() + i); + i--; + continue; } } - else - { - bool TempBool = RENDERER.IsSSAOEnabled(); - ImGui::Checkbox("SSAO active", &TempBool); - RENDERER.SetSSAOEnabled(TempBool); - - TempBool = RENDERER.IsSSAOSmallDetailsEnabled(); - ImGui::Checkbox("SSAO small details", &TempBool); - RENDERER.SetSSAOSmallDetailsEnabled(TempBool); - - TempBool = RENDERER.IsSSAOResultBlured(); - ImGui::Checkbox("SSAO blured", &TempBool); - RENDERER.SetSSAOResultBlured(TempBool); - - int TempInt = RENDERER.GetSSAOSampleCount(); - ImGui::SetNextItemWidth(100); - ImGui::DragInt("SSAO sample count", &TempInt); - RENDERER.SetSSAOSampleCount(TempInt); - - float TempFloat = RENDERER.GetSSAOBias(); - ImGui::SetNextItemWidth(100); - ImGui::DragFloat("SSAO bias", &TempFloat, 0.1f); - RENDERER.SetSSAOBias(TempFloat); - - TempFloat = RENDERER.GetSSAORadius(); - ImGui::SetNextItemWidth(100); - ImGui::DragFloat("SSAO radius", &TempFloat, 0.1f); - RENDERER.SetSSAORadius(TempFloat); - - TempFloat = RENDERER.GetSSAORadiusSmallDetails(); - ImGui::SetNextItemWidth(100); - ImGui::DragFloat("SSAO radius small details", &TempFloat, 0.1f); - RENDERER.SetSSAORadiusSmallDetails(TempFloat); - - TempFloat = RENDERER.GetSSAOSmallDetailsWeight(); - ImGui::SetNextItemWidth(100); - ImGui::DragFloat("SSAO small details weight", &TempFloat, 0.01f); - RENDERER.SetSSAOSmallDetailsWeight(TempFloat); - } - - /*bool bEnabledSky = RENDERER.IsSkyEnabled(); - if (ImGui::Checkbox("enable sky", &bEnabledSky)) - { - RENDERER.SetSkyEnabld(bEnabledSky); - } - - ImGui::Text("Sphere size:"); - ImGui::SetNextItemWidth(FieldWidth); - float size = RENDERER.GetDistanceToSky(); - ImGui::DragFloat("##Sphere size", &size, 0.01f, 0.0f, 200.0f); - RENDERER.SetDistanceToSky(size); - - ImGui::PushID(GUIID++); - ImGui::SameLine(); - ResetButton->Render(); - if (ResetButton->IsClicked()) - { - RENDERER.SetDistanceToSky(50.0f); - } - ImGui::PopID();*/ - } - - ImGui::PopStyleVar(); - ImGui::End(); -} - -void FEEditor::DisplayLogWindow() const -{ - if (!bLogWindowVisible) - return; - const auto TopicList = LOG.GetTopicList(); + SCENE_GRAPH_WINDOW.Render(); + CONTENT_BROWSER_WINDOW.Render(); + INSPECTOR_WINDOW.Render(); + DisplayEditorCamerasWindow(); + DisplayLogWindow(); + if (!GyzmosSettingsWindowObject.IsVisible()) + GyzmosSettingsWindowObject.Show(); + GyzmosSettingsWindowObject.Render(); - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(15, 15)); - ImGui::Begin("Log", nullptr, ImGuiWindowFlags_None); - - static std::string SelectedChannel = "FE_LOG_GENERAL"; - ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 3); - ImGui::Text("Channel:"); - ImGui::SameLine(); - ImGui::SetCursorPosY(ImGui::GetCursorPosY() - 5); - if (ImGui::BeginCombo("##Channel", (SelectedChannel == "" ? "ALL" : SelectedChannel).c_str(), ImGuiWindowFlags_None)) - { - for (int i = -1; i < int(TopicList.size()); i++) + for (size_t i = 0; i < EditorSceneWindows.size(); i++) { - ImGui::PushID(i); - - if (i == -1) - { - const bool is_selected = (SelectedChannel == ""); + if (EditorSceneWindows[i]->Scene != EDITOR.GetFocusedScene()) + continue; - if (ImGui::Selectable("ALL", is_selected)) - { - SelectedChannel = ""; - } - - if (is_selected) - ImGui::SetItemDefaultFocus(); - } - else + const int ObjectIndex = SELECTED.GetIndexOfObjectUnderMouse(EDITOR.GetMouseX(), EDITOR.GetMouseY(), EditorSceneWindows[i]->Scene); + if (ObjectIndex >= 0) { - const bool is_selected = (SelectedChannel == TopicList[i]); - if (ImGui::Selectable(TopicList[i].c_str(), is_selected)) + if (!GIZMO_MANAGER.WasSelected(ObjectIndex, EditorSceneWindows[i]->Scene)) { - SelectedChannel = TopicList[i]; + SELECTED.SetSelectedByIndex(ObjectIndex, EditorSceneWindows[i]->Scene); } - - if (is_selected) - ImGui::SetItemDefaultFocus(); } - - ImGui::PopID(); } - ImGui::EndCombo(); - } - - std::string LogMessages; - std::vector LogItems; - if (SelectedChannel == "") - { - std::vector TempItems; - for (int i = 0; i < int(TopicList.size()); i++) - { - TempItems = LOG.GetLogItems(TopicList[i]); - for (size_t j = 0; j < TempItems.size(); j++) - { - LogItems.push_back(TempItems[j]); - } - } + RenderAllSubWindows(); } else { - LogItems = LOG.GetLogItems(SelectedChannel); - } - - std::sort(LogItems.begin(), LogItems.end(), - [](const LogItem& A, const LogItem& B) -> bool - { - return A.TimeStamp < B.TimeStamp; - }); - - for (size_t i = 0; i < LogItems.size(); i++) - { - LogMessages += LogItems[i].Text; - - if (LogItems[i].Count < 1000) - { - LogMessages += " | COUNT: " + std::to_string(LogItems[i].Count); - } - else - { - LogMessages += " | COUNT: 1000+(Suppressed)"; - } - - LogMessages += " | SEVERITY: " + LOG.SeverityLevelToString(LogItems[i].Severity); - - if (SelectedChannel == "") - { - LogMessages += " | CHANNEL: " + LogItems[i].Topic; - } - - if (i < LogItems.size() - 1) - LogMessages += "\n"; - } - - static TextEditor LogEditor; - LogEditor.SetReadOnly(true); - LogEditor.SetShowWhitespaces(false); - LogEditor.SetText(LogMessages); - LogEditor.Render("Log messages"); - - ImGui::PopStyleVar(); - ImGui::End(); -} - -//static FEMaterial* tempMaterial = nullptr; -static FETerrain* TerrainToWorkWith = nullptr; -static void CreateNewTerrainLayerWithMaterialCallBack(std::vector SelectionsResult) -{ - if (SelectionsResult.size() == 1 && SelectionsResult[0]->GetType() == FE_MATERIAL) - { - if (TerrainToWorkWith == nullptr) - return; - - FEMaterial* SelectedMaterial = RESOURCE_MANAGER.GetMaterial(SelectionsResult[0]->GetObjectID()); - if (SelectedMaterial == nullptr) - return; - - RESOURCE_MANAGER.ActivateTerrainVacantLayerSlot(TerrainToWorkWith, SelectedMaterial); - } - - TerrainToWorkWith = nullptr; -} - -static size_t TempLayerIndex = -1; -static void ChangeMaterialInTerrainLayerCallBack(std::vector SelectionsResult) -{ - if (SelectionsResult.size() == 1 && SelectionsResult[0]->GetType() == FE_MATERIAL) - { - if (TempLayerIndex == -1) - return; - - FEMaterial* SelectedMaterial = RESOURCE_MANAGER.GetMaterial(SelectionsResult[0]->GetObjectID()); - if (SelectedMaterial == nullptr) - return; - - TerrainToWorkWith->GetLayerInSlot(TempLayerIndex)->SetMaterial(SelectedMaterial); + PROJECT_MANAGER.DisplayProjectSelection(); } - - TerrainToWorkWith = nullptr; - TempLayerIndex = -1; } -void FEEditor::DisplayTerrainSettings(FETerrain* Terrain) +void FEEditor::CloseWindowCallBack() { - if (TerrainChangeLayerMaterialTargets.size() != Terrain->LayersUsed()) - { - for (size_t i = 0; i < TerrainChangeLayerMaterialTargets.size(); i++) - { - delete TerrainChangeLayerMaterialTargets[i]; - } - - TerrainChangeLayerMaterialTargets.resize(Terrain->LayersUsed()); - TerrainChangeMaterialIndecies.resize(Terrain->LayersUsed()); - for (size_t i = 0; i < size_t(Terrain->LayersUsed()); i++) - { - TerrainChangeMaterialIndecies[i] = int(i); - TerrainChangeLayerMaterialTargets[i] = DRAG_AND_DROP_MANAGER.AddTarget(FE_MATERIAL, TerrainChangeMaterialTargetCallBack, (void**)&TerrainChangeMaterialIndecies[i], "Drop to assing material to " + Terrain->GetLayerInSlot(i)->GetName()); - } - } - - if (ImGui::BeginTabBar("##terrainSettings", ImGuiTabBarFlags_None)) + if (PROJECT_MANAGER.GetCurrent() == nullptr) { - if (ImGui::BeginTabItem("General")) - { - bool bActive = Terrain->IsWireframeMode(); - ImGui::Checkbox("WireframeMode", &bActive); - Terrain->SetWireframeMode(bActive); - - int IData = *(int*)RESOURCE_MANAGER.GetShader("0800253C242B05321A332D09"/*"FEPBRShader"*/)->GetParameterData("debugFlag"); - ImGui::SliderInt("debugFlag", &IData, 0, 10); - RESOURCE_MANAGER.GetShader("0800253C242B05321A332D09"/*"FEPBRShader"*/)->UpdateParameterData("debugFlag", IData); - - float DisplacementScale = Terrain->GetDisplacementScale(); - ImGui::DragFloat("displacementScale", &DisplacementScale, 0.02f, -10.0f, 10.0f); - Terrain->SetDisplacementScale(DisplacementScale); - - float LODLevel = Terrain->GetLODLevel(); - ImGui::DragFloat("LODlevel", &LODLevel, 2.0f, 2.0f, 128.0f); - Terrain->SetLODLevel(LODLevel); - ShowToolTip("Bigger LODlevel more details terraine will have and less performance you will get."); - - float ChunkPerSide = Terrain->GetChunkPerSide(); - ImGui::DragFloat("chunkPerSide", &ChunkPerSide, 2.0f, 1.0f, 16.0f); - Terrain->SetChunkPerSide(ChunkPerSide); - - // ********************* REAL WORLD COMPARISON SCALE ********************* - FEAABB RealAABB = Terrain->GetAABB(); - glm::vec3 min = RealAABB.GetMin(); - glm::vec3 max = RealAABB.GetMax(); - - float XSize = sqrt((max.x - min.x) * (max.x - min.x)); - float YSize = sqrt((max.y - min.y) * (max.y - min.y)); - float ZSize = sqrt((max.z - min.z) * (max.z - min.z)); - - std::string SizeInM = "Approximate terrain size: "; - SizeInM += std::to_string(std::max(XSize, std::max(YSize, ZSize))); - SizeInM += " m"; - ImGui::Text(SizeInM.c_str()); - // ********************* REAL WORLD COMPARISON SCALE END ********************* - - ShowTransformConfiguration(Terrain, &Terrain->Transform); - - ImGui::EndTabItem(); - } - if (ImGui::BeginTabItem("Sculpt")) - { - ExportHeightMapButton->Render(); - if (ExportHeightMapButton->IsClicked()) - { - std::string filePath = ""; - FILE_SYSTEM.ShowFileSaveDialog(filePath, TEXTURE_LOAD_FILTER, 1); - - if (!filePath.empty()) - { - filePath += ".png"; - RESOURCE_MANAGER.ExportFETextureToPNG(Terrain->HeightMap, filePath.c_str()); - } - } - - ImGui::SameLine(); - ImportHeightMapButton->Render(); - if (ImportHeightMapButton->IsClicked()) - { - std::string FilePath; - FILE_SYSTEM.ShowFileOpenDialog(FilePath, TEXTURE_LOAD_FILTER, 1); - - if (!FilePath.empty()) - { - FETexture* LoadedTexture = RESOURCE_MANAGER.LoadPNGHeightmap(FilePath.c_str(), Terrain); - if (LoadedTexture == RESOURCE_MANAGER.NoTexture) - { - LOG.Add(std::string("can't load height map: ") + FilePath, "FE_LOG_LOADING", FE_LOG_ERROR); - } - else - { - LoadedTexture->SetDirtyFlag(true); - PROJECT_MANAGER.GetCurrent()->SetModified(true); - } - } - } - - float HighScale = Terrain->GetHightScale(); - ImGui::DragFloat("hight range in m", &HighScale); - Terrain->SetHightScale(HighScale); - - float CurrentBrushSize = Terrain->GetBrushSize(); - ImGui::DragFloat("brushSize", &CurrentBrushSize, 0.1f, 0.01f, 100.0f); - Terrain->SetBrushSize(CurrentBrushSize); - - float CurrentBrushIntensity = Terrain->GetBrushIntensity(); - ImGui::DragFloat("brushIntensity", &CurrentBrushIntensity, 0.0001f, 0.0001f, 10.0f); - Terrain->SetBrushIntensity(CurrentBrushIntensity); - - SetDefaultStyle(SculptBrushButton); - if (Terrain->GetBrushMode() == FE_TERRAIN_BRUSH_SCULPT_DRAW || - Terrain->GetBrushMode() == FE_TERRAIN_BRUSH_SCULPT_DRAW_INVERSED) - SetSelectedStyle(SculptBrushButton); - - SculptBrushButton->Render(); - ShowToolTip("Sculpt Brush. Left mouse to increase height, hold shift to decrease height."); - - if (SculptBrushButton->IsClicked()) - { - if (Terrain->GetBrushMode() == FE_TERRAIN_BRUSH_SCULPT_DRAW || - Terrain->GetBrushMode() == FE_TERRAIN_BRUSH_SCULPT_DRAW_INVERSED) - { - Terrain->SetBrushMode(FE_TERRAIN_BRUSH_NONE); - } - else - { - Terrain->SetBrushMode(FE_TERRAIN_BRUSH_SCULPT_DRAW); - } - } - - SetDefaultStyle(LevelBrushButton); - if (Terrain->GetBrushMode() == FE_TERRAIN_BRUSH_SCULPT_LEVEL) - SetSelectedStyle(LevelBrushButton); - - ImGui::SameLine(); - LevelBrushButton->Render(); - ShowToolTip("Level Brush."); - - if (LevelBrushButton->IsClicked()) - { - if (Terrain->GetBrushMode() == FE_TERRAIN_BRUSH_SCULPT_LEVEL) - { - Terrain->SetBrushMode(FE_TERRAIN_BRUSH_NONE); - } - else - { - Terrain->SetBrushMode(FE_TERRAIN_BRUSH_SCULPT_LEVEL); - } - } - - SetDefaultStyle(SmoothBrushButton); - if (Terrain->GetBrushMode() == FE_TERRAIN_BRUSH_SCULPT_SMOOTH) - SetSelectedStyle(SmoothBrushButton); - - ImGui::SameLine(); - SmoothBrushButton->Render(); - ShowToolTip("Smooth Brush."); - - if (SmoothBrushButton->IsClicked()) - { - if (Terrain->GetBrushMode() == FE_TERRAIN_BRUSH_SCULPT_SMOOTH) - { - Terrain->SetBrushMode(FE_TERRAIN_BRUSH_NONE); - } - else - { - Terrain->SetBrushMode(FE_TERRAIN_BRUSH_SCULPT_SMOOTH); - } - } - - ImGui::EndTabItem(); - } - if (ImGui::BeginTabItem("Paint")) - { - glm::vec2 TileMult = Terrain->GetTileMult(); - ImGui::DragFloat2("all layers tile factors", &TileMult[0], 0.1f, 1.0f, 100.0f); - Terrain->SetTileMult(TileMult); - - float CurrentBrushSize = Terrain->GetBrushSize(); - ImGui::DragFloat("brushSize", &CurrentBrushSize, 0.1f, 0.01f, 100.0f); - Terrain->SetBrushSize(CurrentBrushSize); - - float CurrentBrushIntensity = Terrain->GetBrushIntensity(); - ImGui::DragFloat("brushIntensity", &CurrentBrushIntensity, 0.0001f, 0.0001f, 10.0f); - Terrain->SetBrushIntensity(CurrentBrushIntensity); - - SetDefaultStyle(LayerBrushButton); - if (Terrain->GetBrushMode() == FE_TERRAIN_BRUSH_LAYER_DRAW) - SetSelectedStyle(LayerBrushButton); - - LayerBrushButton->Render(); - ShowToolTip("Layer draw brush. Left mouse to paint currently selected layer, hold shift to decrease layer influence."); - static int SelectedLayer = -1; - if (SelectedLayer != -1 && Terrain->GetLayerInSlot(SelectedLayer) == nullptr) - SelectedLayer = -1; - - if (LayerBrushButton->IsClicked()) - { - if (SelectedLayer != -1) - { - if (Terrain->GetBrushMode() == FE_TERRAIN_BRUSH_LAYER_DRAW) - { - Terrain->SetBrushMode(FE_TERRAIN_BRUSH_NONE); - } - else - { - Terrain->SetBrushMode(FE_TERRAIN_BRUSH_LAYER_DRAW); - } - } - - } - - ImGui::PushFont(ImGui::GetIO().Fonts->Fonts[1]); - static bool bContextMenuOpened = false; - - ImGui::Text("Layers:"); - - ImGui::BeginChildFrame(ImGui::GetID("Layers ListBox Child"), ImVec2(ImGui::GetContentRegionAvail().x - 10.0f, 500.0f), ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse); - bool bListBoxHovered = false; - if (ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows)) - bListBoxHovered = true; - - static bool bShouldOpenContextMenu = false; - if (ImGui::IsMouseClicked(1)) - { - if (bListBoxHovered) - { - bShouldOpenContextMenu = true; - } - } - - ImGui::BeginListBox("##Layers ListBox", ImVec2(ImGui::GetContentRegionAvail().x - 10.0f, 500.0f)); - - for (size_t i = 0; i < FE_TERRAIN_MAX_LAYERS; i++) - { - FETerrainLayer* layer = Terrain->GetLayerInSlot(i); - if (layer == nullptr) - break; - - ImVec2 PostionBeforeDraw = ImGui::GetCursorPos(); - - ImVec2 TextSize = ImGui::CalcTextSize(layer->GetName().c_str()); - ImGui::SetCursorPos(PostionBeforeDraw + ImVec2(ImGui::GetContentRegionAvail().x / 2.0f - TextSize.x / 2.0f, 16)); - - if (TerrainLayerRenameIndex == i) - { - if (!bLastFrameTerrainLayerRenameEditWasVisiable) - { - ImGui::SetKeyboardFocusHere(0); - ImGui::SetFocusID(ImGui::GetID("##newNameTerrainLayerEditor"), ImGui::GetCurrentWindow()); - ImGui::SetItemDefaultFocus(); - bLastFrameTerrainLayerRenameEditWasVisiable = true; - } - - ImGui::SetNextItemWidth(350.0f); - ImGui::SetCursorPos(ImVec2(PostionBeforeDraw.x + 64.0f + (ImGui::GetContentRegionAvail().x- 64.0f) / 2.0f - 350.0f / 2.0f, PostionBeforeDraw.y + 12)); - if (ImGui::InputText("##newNameTerrainLayerEditor", TerrainLayerRename, IM_ARRAYSIZE(TerrainLayerRename), ImGuiInputTextFlags_EnterReturnsTrue) || - ImGui::IsMouseClicked(0) && !ImGui::IsItemHovered() || ImGui::GetFocusID() != ImGui::GetID("##newNameTerrainLayerEditor")) - { - PROJECT_MANAGER.GetCurrent()->SetModified(true); - layer->SetName(TerrainLayerRename); - - TerrainLayerRenameIndex = -1; - } - } - else - { - ImGui::Text(layer->GetName().c_str()); - } - ImGui::SetCursorPos(PostionBeforeDraw); + ENGINE.Terminate(); + return; + } - ImGui::PushID(int(i)); - if (ImGui::Selectable("##item", SelectedLayer == i ? true : false, ImGuiSelectableFlags_None, ImVec2(ImGui::GetContentRegionAvail().x - 0, 64))) - { - SelectedLayer = int(i); - Terrain->SetBrushLayerIndex(SelectedLayer); - } - TerrainChangeLayerMaterialTargets[i]->StickToItem(); - ImGui::PopID(); + if (PROJECT_MANAGER.GetCurrent()->IsModified()) + { + APPLICATION.GetMainWindow()->CancelClose(); + ProjectWasModifiedPopUp::GetInstance().Show(PROJECT_MANAGER.GetCurrent(), true); + } + else + { + EDITOR.OnProjectClose(); + ENGINE.Terminate(); + return; + } +} + +void FEEditor::OnViewportResize(std::string ViewportID) +{ + if (PROJECT_MANAGER.GetCurrent() == nullptr) + return; - if (ImGui::IsItemHovered()) - HoveredTerrainLayerItem = int(i); + for (size_t i = 0; i < EDITOR.EditorSceneWindows.size(); i++) + { + FEProject* CurrentProject = PROJECT_MANAGER.GetCurrent(); + if (CurrentProject == nullptr) + return; - ImGui::SetCursorPos(PostionBeforeDraw); - ImColor ImageTint = ImGui::IsItemHovered() ? ImColor(1.0f, 1.0f, 1.0f, 0.5f) : ImColor(1.0f, 1.0f, 1.0f, 1.0f); - FETexture* PreviewTexture = PREVIEW_MANAGER.GetMaterialPreview(layer->GetMaterial()->GetObjectID()); - ImGui::Image((void*)(intptr_t)PreviewTexture->GetTextureID(), ImVec2(64, 64), ImVec2(0.0f, 0.0f), ImVec2(1.0f, 1.0f), ImageTint); - } + FEEntity* CameraEntity = nullptr; + if (EDITOR.EditorSceneWindows[i]->Scene->HasFlag(FESceneFlag::EditorMode)) + { + std::string EditorCameraID = CurrentProject->GetEditorCameraIDBySceneID(EDITOR.EditorSceneWindows[i]->Scene->GetObjectID()); + CameraEntity = EDITOR.EditorSceneWindows[i]->Scene->GetEntity(EditorCameraID); + } + else if (EDITOR.EditorSceneWindows[i]->Scene->HasFlag(FESceneFlag::GameMode)) + { + CameraEntity = CAMERA_SYSTEM.GetMainCamera(EDITOR.EditorSceneWindows[i]->Scene); + } - ImGui::EndListBox(); - ImGui::PopFont(); + if (CameraEntity == nullptr) + continue; - ImGui::EndChildFrame(); - ImGui::EndTabItem(); + FECameraComponent& CameraComponent = CameraEntity->GetComponent(); + if (CameraComponent.GetViewport()->GetID() == ViewportID) + { + SELECTED.UpdateResources(EDITOR.EditorSceneWindows[i]->Scene); + } + } +} - if (bShouldOpenContextMenu) +void FEEditor::DropCallback(const int Count, const char** Paths) +{ + for (size_t i = 0; i < size_t(Count); i++) + { + if (FILE_SYSTEM.DoesDirectoryExist(Paths[i]) && Count == 1) + { + if (PROJECT_MANAGER.GetCurrent() == nullptr) { - bShouldOpenContextMenu = false; - ImGui::OpenPopup("##layers_listBox_context_menu"); + PROJECT_MANAGER.SetProjectsFolder(Paths[i]); } + } - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(15, 15)); - if (ImGui::BeginPopup("##layers_listBox_context_menu")) + if (PROJECT_MANAGER.GetCurrent() != nullptr) + { + if (EDITOR.GetFocusedScene() != nullptr) { - bContextMenuOpened = true; - - if (Terrain->GetLayerInSlot(FE_TERRAIN_MAX_LAYERS - 1) != nullptr) - ImGui::BeginDisabled(); - - if (ImGui::MenuItem("Add layer...")) - { - std::vector TempMaterialList = RESOURCE_MANAGER.GetMaterialList(); - std::vector FinalMaterialList; - for (size_t i = 0; i < TempMaterialList.size(); i++) - { - if (RESOURCE_MANAGER.GetMaterial(TempMaterialList[i])->IsCompackPacking()) - { - FinalMaterialList.push_back(RESOURCE_MANAGER.GetMaterial(TempMaterialList[i])); - } - } - - if (FinalMaterialList.empty()) - { - MessagePopUp::getInstance().Show("No suitable material", "There are no materials with compack packing."); - } - else - { - TerrainToWorkWith = Terrain; - SelectFeObjectPopUp::getInstance().Show(FE_MATERIAL, CreateNewTerrainLayerWithMaterialCallBack, nullptr, FinalMaterialList); - } - } - - if (Terrain->GetLayerInSlot(FE_TERRAIN_MAX_LAYERS - 1) != nullptr) - ImGui::EndDisabled(); - - if (HoveredTerrainLayerItem != -1) + std::vector LoadedObjects = EDITOR.GetFocusedScene()->ImportAsset(Paths[i]); + for (size_t j = 0; j < LoadedObjects.size(); j++) { - FETerrainLayer* layer = Terrain->GetLayerInSlot(HoveredTerrainLayerItem); - if (layer != nullptr) + if (LoadedObjects[j] != nullptr) { - ImGui::Separator(); - std::string LayerName = layer->GetName(); - ImGui::Text((std::string("Actions with ") + LayerName).c_str()); - ImGui::Separator(); - - if (ImGui::MenuItem("Rename")) - { - TerrainLayerRenameIndex = HoveredTerrainLayerItem; - - strcpy_s(TerrainLayerRename, layer->GetName().size() + 1, layer->GetName().c_str()); - bLastFrameTerrainLayerRenameEditWasVisiable = false; - } - - if (ImGui::MenuItem("Fill")) + if (LoadedObjects[j]->GetType() == FE_ENTITY) { - RESOURCE_MANAGER.FillTerrainLayerMask(Terrain, HoveredTerrainLayerItem); + //SCENE.CreateEntity(reinterpret_cast(LoadedObjects[j])); } - - if (ImGui::MenuItem("Clear")) + else { - RESOURCE_MANAGER.ClearTerrainLayerMask(Terrain, HoveredTerrainLayerItem); + VIRTUAL_FILE_SYSTEM.CreateFile(LoadedObjects[j], VIRTUAL_FILE_SYSTEM.GetCurrentPath()); + PROJECT_MANAGER.GetCurrent()->SetModified(true); + PROJECT_MANAGER.GetCurrent()->AddUnSavedObject(LoadedObjects[j]); } + } + } + } + } + } +} - if (ImGui::MenuItem("Delete")) - { - RESOURCE_MANAGER.DeleteTerrainLayerMask(Terrain, HoveredTerrainLayerItem); - } +void FEEditor::DisplayEditorCamerasWindow() const +{ + if (!bEditorCamerasWindowVisible) + return; - ImGui::Separator(); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(15, 15)); + ImGui::Begin("Editor Cameras", nullptr, ImGuiWindowFlags_None); - if (ImGui::MenuItem("Change material...")) - { - std::vector TempMaterialList = RESOURCE_MANAGER.GetMaterialList(); - std::vector FinalMaterialList; - for (size_t i = 0; i < TempMaterialList.size(); i++) - { - if (RESOURCE_MANAGER.GetMaterial(TempMaterialList[i])->IsCompackPacking()) - { - FinalMaterialList.push_back(RESOURCE_MANAGER.GetMaterial(TempMaterialList[i])); - } - } + auto EditorCameraIterator = PROJECT_MANAGER.GetCurrent()->SceneIDToEditorCameraID.begin(); + while (EditorCameraIterator != PROJECT_MANAGER.GetCurrent()->SceneIDToEditorCameraID.end()) + { + FEScene* Scene = SCENE_MANAGER.GetScene(EditorCameraIterator->first); + if (Scene == nullptr) + { + EditorCameraIterator++; + continue; + } - if (FinalMaterialList.empty()) - { - MessagePopUp::getInstance().Show("No suitable material", "There are no materials with compack packing."); - } - else - { - TerrainToWorkWith = Terrain; - TempLayerIndex = HoveredTerrainLayerItem; - SelectFeObjectPopUp::getInstance().Show(FE_MATERIAL, ChangeMaterialInTerrainLayerCallBack, Terrain->GetLayerInSlot(HoveredTerrainLayerItem)->GetMaterial(), FinalMaterialList); - } - } + FEEntity* CameraEntity = Scene->GetEntity(EditorCameraIterator->second); + if (CameraEntity == nullptr) + { + EditorCameraIterator++; + continue; + } - if (ImGui::MenuItem("Export mask...")) - { - std::string filePath = ""; - FILE_SYSTEM.ShowFileSaveDialog(filePath, TEXTURE_LOAD_FILTER, 1); - if (!filePath.empty()) - { - filePath += ".png"; - RESOURCE_MANAGER.SaveTerrainLayerMask(filePath.c_str(), Terrain, HoveredTerrainLayerItem); - } - } + if (!CameraEntity->HasComponent()) + { + EditorCameraIterator++; + continue; + } - if (ImGui::MenuItem("Import mask...")) - { - std::string filePath = ""; - FILE_SYSTEM.ShowFileOpenDialog(filePath, TEXTURE_LOAD_FILTER, 1); - if (!filePath.empty()) - { - RESOURCE_MANAGER.LoadTerrainLayerMask(filePath.c_str(), Terrain, HoveredTerrainLayerItem); - PROJECT_MANAGER.GetCurrent()->SetModified(true); - } - } - } - } + if (ImGui::CollapsingHeader(CameraEntity->GetObjectID().c_str(), 0)) + { + ImGui::Indent(); - ImGui::EndPopup(); + if (ImGui::CollapsingHeader("Transform", ImGuiTreeNodeFlags_DefaultOpen)) + { + FETransformComponent& Transform = CameraEntity->GetComponent(); + INSPECTOR_WINDOW.ShowTransformConfiguration(CameraEntity->GetName(), &Transform); + } + + if (ImGui::CollapsingHeader("Camera", ImGuiTreeNodeFlags_DefaultOpen)) + { + INSPECTOR_WINDOW.DisplayCameraProperties(CameraEntity); } - ImGui::PopStyleVar(); - - if (!bContextMenuOpened) - HoveredTerrainLayerItem = -1; - - bContextMenuOpened = false; } - ImGui::EndTabBar(); + + EditorCameraIterator++; } + + ImGui::PopStyleVar(); + ImGui::End(); } void FEEditor::RenderAllSubWindows() { - SelectFeObjectPopUp::getInstance().Render(); + SELECT_FEOBJECT_POPUP.Render(); - DeleteTexturePopup::getInstance().Render(); - DeleteMeshPopup::getInstance().Render(); - DeleteGameModelPopup::getInstance().Render(); - DeleteMaterialPopup::getInstance().Render(); - DeletePrefabPopup::getInstance().Render(); - DeleteDirectoryPopup::getInstance().Render(); + DeleteTexturePopup::GetInstance().Render(); + DeleteMeshPopup::GetInstance().Render(); + DeleteGameModelPopup::GetInstance().Render(); + DeleteMaterialPopup::GetInstance().Render(); + DeletePrefabPopup::GetInstance().Render(); + DeleteDirectoryPopup::GetInstance().Render(); - resizeTexturePopup::getInstance().Render(); + ResizeTexturePopup::GetInstance().Render(); JustTextWindowObj.Render(); - renamePopUp::getInstance().Render(); - renameFailedPopUp::getInstance().Render(); - MessagePopUp::getInstance().Render(); + RenamePopUp::GetInstance().Render(); + RenameFailedPopUp::GetInstance().Render(); + MessagePopUp::GetInstance().Render(); - projectWasModifiedPopUp::getInstance().Render(); + ProjectWasModifiedPopUp::GetInstance().Render(); FE_IMGUI_WINDOW_MANAGER.RenderAllWindows(); } -void FEEditor::SetCorrectSceneBrowserColor(FEObject* SceneObject) const -{ - if (SceneObject->GetType() == FE_DIRECTIONAL_LIGHT || - SceneObject->GetType() == FE_SPOT_LIGHT || - SceneObject->GetType() == FE_POINT_LIGHT) - { - ImGui::PushStyleColor(ImGuiCol_Text, LightColorSceneBrowser); - } - else if (SceneObject->GetType() == FE_CAMERA) - { - ImGui::PushStyleColor(ImGuiCol_Text, CameraColorSceneBrowser); - } - else if (SceneObject->GetType() == FE_TERRAIN) - { - ImGui::PushStyleColor(ImGuiCol_Text, TerrainColorSceneBrowser); - } - else if (SceneObject->GetType() == FE_ENTITY) - { - ImGui::PushStyleColor(ImGuiCol_Text, EntityColorSceneBrowser); - } - else if (SceneObject->GetType() == FE_ENTITY_INSTANCED) - { - ImGui::PushStyleColor(ImGuiCol_Text, InstancedEntityColorSceneBrowser); - } -} - -void FEEditor::PopCorrectSceneBrowserColor(FEObject* SceneObject) -{ - if (SceneObject->GetType() == FE_DIRECTIONAL_LIGHT || - SceneObject->GetType() == FE_SPOT_LIGHT || - SceneObject->GetType() == FE_POINT_LIGHT || - SceneObject->GetType() == FE_CAMERA || - SceneObject->GetType() == FE_TERRAIN || - SceneObject->GetType() == FE_ENTITY || - SceneObject->GetType() == FE_ENTITY_INSTANCED) - { - ImGui::PopStyleColor(); - } -} - void FEEditor::SetImguiStyle() { ImGuiStyle* style = &ImGui::GetStyle(); @@ -3224,8 +774,231 @@ void FEEditor::SetUpImgui() int TexW, TexH; io.Fonts->GetTexDataAsRGBA32(&TexPixels, &TexW, &TexH); - io.DisplaySize = ImVec2(static_cast(ENGINE.GetWindowWidth()), static_cast(ENGINE.GetWindowHeight())); + io.DisplaySize = ImVec2(static_cast(APPLICATION.GetMainWindow()->GetWidth()), static_cast(APPLICATION.GetMainWindow()->GetHeight())); ImGui::StyleColorsDark(); SetImguiStyle(); +} + +void FEEditor::OnProjectClose() +{ + EDITOR_MATERIAL_WINDOW.Stop(); + EditorSceneWindows.clear(); + SetFocusedScene(nullptr); + + PROJECT_MANAGER.CloseCurrentProject(); + CONTENT_BROWSER_WINDOW.Clear(); + SCENE_GRAPH_WINDOW.Clear(); + PREFAB_EDITOR_MANAGER.Clear(); +} + +FEEditorSceneWindow* FEEditor::GetEditorSceneWindow(std::string SceneID) +{ + for (size_t i = 0; i < EditorSceneWindows.size(); i++) + { + if (EditorSceneWindows[i]->Scene->GetObjectID() == SceneID) + return EditorSceneWindows[i]; + } + + return nullptr; +} + +void FEEditor::AddEditorScene(FEScene* Scene) +{ + FEEditorSceneWindow* NewSceneWindow = new FEEditorSceneWindow(Scene); + NewSceneWindow->SetVisible(true); + EditorSceneWindows.push_back(NewSceneWindow); +} + +void FEEditor::AddCustomEditorScene(FEEditorSceneWindow* SceneWindow) +{ + if (SceneWindow == nullptr) + return; + + SceneWindow->SetVisible(true); + EditorSceneWindows.push_back(SceneWindow); +} + +void FEEditor::BeforeChangeOfFocusedScene(FEScene* NewSceneInFocus) +{ + if (!FocusedEditorSceneID.empty() && NewSceneInFocus != EDITOR.GetFocusedScene()) + { + SELECTED.Clear(EDITOR.GetFocusedScene()); + GIZMO_MANAGER.HideAllGizmo(EDITOR.GetFocusedScene()); + } +} + +bool FEEditor::IsInGameMode() const +{ + return bGameMode; +} + +void FEEditor::SetGameMode(const bool GameMode) +{ + if (SetGameModeInternal(GameMode)) + bGameMode = GameMode; +} + +bool FEEditor::DuplicateScenesForGameMode() +{ + if (EDITOR.GetFocusedScene() == nullptr) + { + LOG.Add("FEEditor::DuplicateScenesForGameMode: No scene to duplicate for game mode.", "FE_EDITOR_GAME_MODE", FE_LOG_ERROR); + return false; + } + + // Here we are setting flag right away, because we want to make sure that scripts are started. + FEScene* GameModeScene = SCENE_MANAGER.DuplicateScene(EDITOR.GetFocusedScene()->GetObjectID(), "GameMode", [](FEEntity* EntityToCheck) { + return !(EntityToCheck->GetTag() == EDITOR_RESOURCE_TAG); + }, FESceneFlag::Active | FESceneFlag::GameMode | FESceneFlag::Renderable); + + if (GameModeScene == nullptr) + { + LOG.Add("FEEditor::DuplicateScenesForGameMode: Failed to duplicate scene for game mode.", "FE_EDITOR_GAME_MODE", FE_LOG_ERROR); + return false; + } + + ParentIDToScenesInGameMode[EDITOR.GetFocusedScene()->GetObjectID()] = GameModeScene; + + EDITOR.AddEditorScene(GameModeScene); + + return true; +} + +bool FEEditor::SetGameModeInternal(bool GameMode) +{ + if (EDITOR.IsInGameMode() == GameMode) + return false; + + if (EDITOR.GetFocusedScene() == nullptr) + { + LOG.Add("FEEditor::SetGameModeInternal: No scene to duplicate for game mode.", "FE_EDITOR_GAME_MODE", FE_LOG_ERROR); + return false; + } + + if (GameMode) + { + if (!DuplicateScenesForGameMode()) + { + LOG.Add("FEEditor::SetGameModeInternal: Failed to set game mode.", "FE_EDITOR_GAME_MODE", FE_LOG_ERROR); + return false; + } + } + else + { + auto SceneIterator = ParentIDToScenesInGameMode.begin(); + while (SceneIterator != ParentIDToScenesInGameMode.end()) + { + DeleteScene(SceneIterator->second->GetObjectID()); + SceneIterator = ParentIDToScenesInGameMode.erase(SceneIterator); + } + } + + return true; +} + +void FEEditor::DeleteScene(std::string SceneID) +{ + FEScene* SceneToDelete = SCENE_MANAGER.GetScene(SceneID); + if (SceneToDelete == nullptr) + { + LOG.Add("FEEditor::DeleteScene: Scene to delete not found.", "FE_EDITOR", FE_LOG_ERROR); + return; + } + + FEEditorSceneWindow* SceneWindow = GetEditorSceneWindow(SceneToDelete->GetObjectID()); + if (SceneWindow != nullptr) + { + if (EDITOR.FocusedEditorSceneID == SceneToDelete->GetObjectID()) + EDITOR.FocusedEditorSceneID = ""; + + for (size_t i = 0; i < EditorSceneWindows.size(); i++) + { + if (EditorSceneWindows[i] == SceneWindow) + { + EditorSceneWindows.erase(EditorSceneWindows.begin() + i); + delete SceneWindow; + break; + } + } + } + + if (SELECTED.PerSceneData.find(SceneToDelete->GetObjectID()) != SELECTED.PerSceneData.end()) + SELECTED.PerSceneData.erase(SceneToDelete->GetObjectID()); + + if (GIZMO_MANAGER.PerSceneData.find(SceneToDelete->GetObjectID()) != GIZMO_MANAGER.PerSceneData.end()) + GIZMO_MANAGER.PerSceneData.erase(SceneToDelete->GetObjectID()); + + SCENE_MANAGER.DeleteScene(SceneToDelete->GetObjectID()); +} + +std::vector FEEditor::GetEditorOpenedScenesIDs() const +{ + std::vector OpenedScenesIDs; + for (size_t i = 0; i < EditorSceneWindows.size(); i++) + { + OpenedScenesIDs.push_back(EditorSceneWindows[i]->Scene->GetObjectID()); + } + + return OpenedScenesIDs; +} + +FEScene* FEEditor::GetFocusedScene() const +{ + return SCENE_MANAGER.GetScene(FocusedEditorSceneID); +} + +bool FEEditor::SetFocusedScene(FEScene* NewSceneInFocus) +{ + if (NewSceneInFocus == nullptr) + { + FocusedEditorSceneID = ""; + return true; + } + + BeforeChangeOfFocusedScene(NewSceneInFocus); + + return SetFocusedScene(NewSceneInFocus->GetObjectID()); +} + +bool FEEditor::SetFocusedScene(std::string NewSceneInFocusID) +{ + if (SCENE_MANAGER.GetScene(NewSceneInFocusID) == nullptr) + { + LOG.Add("FEEditor::SetFocusedEditorScene: Scene not found.", "FE_EDITOR", FE_LOG_ERROR); + return false; + } + + if (GetEditorSceneWindow(NewSceneInFocusID) == nullptr) + { + LOG.Add("FEEditor::SetFocusedEditorScene: Scene window not found.", "FE_EDITOR", FE_LOG_ERROR); + return false; + } + + FocusedEditorSceneID = NewSceneInFocusID; + return true; +} + +void FEEditor::UpdateBeforeRender() +{ + // Before rendering, we need to ensure that if scene is in editor mode, it's main camera would be editor camera. + FEProject* CurrentProject = PROJECT_MANAGER.GetCurrent(); + if (CurrentProject != nullptr) + { + std::vector Scenes = SCENE_MANAGER.GetScenesByFlagMask(FESceneFlag::Active | FESceneFlag::Renderable | FESceneFlag::EditorMode); + for (size_t i = 0; i < Scenes.size(); i++) + { + FEEntity* CurrentMainCameraEntity = CAMERA_SYSTEM.GetMainCamera(Scenes[i]); + std::string EditorCameraID = CurrentProject->GetEditorCameraIDBySceneID(Scenes[i]->GetObjectID()); + if (!EditorCameraID.empty()) + { + if (CurrentMainCameraEntity != nullptr && CurrentMainCameraEntity->GetObjectID() != EditorCameraID) + { + //SceneIDToOldMainCameraID[Scenes[i]->GetObjectID()] = CurrentMainCameraEntity->GetObjectID(); + //CurrentProject->SceneIDToProperMainCameraID[Scenes[i]->GetObjectID()] = EditorCameraID; + CAMERA_SYSTEM.SetMainCamera(Scenes[i]->GetEntity(EditorCameraID)); + } + } + } + } } \ No newline at end of file diff --git a/FEEditor.h b/FEEditor.h index d265a06..8995dba 100644 --- a/FEEditor.h +++ b/FEEditor.h @@ -1,233 +1,109 @@ #pragma once -#include "FEEditorSubWindows/projectWasModifiedPopUp.h" +#include "EditorWindows/InspectorWindow.h" +#include "EditorWindows/EditorBaseWindowClasses/FEEditorSceneWindow.h" #include -using namespace FocalEngine; -#ifdef FE_WIN_32 -const COMDLG_FILTERSPEC OBJ_LOAD_FILTER[] = +class FEEditor { - { L"Wavefront OBJ files (*.obj)", L"*.obj" } -}; + friend class FEEditorSceneWindow; + friend class FEProjectManager; + friend class FEPrefabEditorManager; +public: + SINGLETON_PUBLIC_PART(FEEditor) -const COMDLG_FILTERSPEC TEXTURE_LOAD_FILTER[] = -{ - { L"Image files (*.png; *.jpg; *.bmp)", L"*.png;*.jpg;*.bmp" } -}; + // Initialization and rendering + void InitializeResources(); + void Render(); -const COMDLG_FILTERSPEC ALL_IMPORT_LOAD_FILTER[] = -{ - { L"All files (*.png; *.jpg; *.bmp; *.obj)", L"*.png;*.jpg;*.bmp;*.obj" }, - { L"Image files (*.png; *.jpg; *.bmp)", L"*.png;*.jpg;*.bmp" }, - { L"Wavefront OBJ files (*.obj)", L"*.obj" } -}; -#endif + // Mouse and input + double GetLastMouseX() const; + void SetLastMouseX(double NewValue); + double GetLastMouseY() const; + void SetLastMouseY(double NewValue); + double GetMouseX() const; + void SetMouseX(double NewValue); + double GetMouseY() const; + void SetMouseY(double NewValue); -class DragAndDropTarget; -class FEEditor -{ -public: - SINGLETON_PUBLIC_PART(FEEditor) + // Clipboard + std::string GetSceneEntityIDInClipboard(); + void SetSceneEntityIDInClipboard(std::string NewValue); - void InitializeResources(); + void AddEditorScene(FEScene* Scene); + void AddCustomEditorScene(FEEditorSceneWindow* SceneWindow); + FEEditorSceneWindow* GetEditorSceneWindow(std::string SceneID); - double GetLastMouseX() const; - void SetLastMouseX(double NewValue); - double GetLastMouseY() const; - void SetLastMouseY(double NewValue); + std::vector GetEditorOpenedScenesIDs() const; - double GetMouseX() const; - void SetMouseX(double NewValue); - double GetMouseY() const; - void SetMouseY(double NewValue); + bool SetFocusedScene(FEScene* NewSceneInFocus); + bool SetFocusedScene(std::string NewSceneInFocusID); + FEScene* GetFocusedScene() const; - std::string GetObjectNameInClipboard(); - void SetObjectNameInClipboard(std::string NewValue); + bool IsInGameMode() const; + void SetGameMode(bool GameMode); - void Render(); - bool bLeftMousePressed = false; - bool bShiftPressed = false; + void UpdateBeforeRender(); private: - SINGLETON_PRIVATE_PART(FEEditor) - - double LastMouseX, LastMouseY; - double MouseX, MouseY; - std::string ObjectNameInClipboard; - static ImGuiWindow* SceneWindow; - bool bSceneWindowHovered; - - bool bIsCameraInputActive = false; - - FETexture* SculptBrushIcon = nullptr; - FETexture* LevelBrushIcon = nullptr; - FETexture* SmoothBrushIcon = nullptr; - FETexture* MouseCursorIcon = nullptr; - FETexture* ArrowToGroundIcon = nullptr; - FETexture* DrawBrushIcon = nullptr; - - void SetCorrectSceneBrowserColor(FEObject* SceneObject) const; - void PopCorrectSceneBrowserColor(FEObject* SceneObject); - ImVec4 TerrainColorSceneBrowser = ImVec4(67.0f / 255.0f, 155.0f / 255.0f, 60.0f / 255.0f, 1.0f); - ImVec4 EntityColorSceneBrowser = ImVec4(141.0f / 255.0f, 141.0f / 255.0f, 233.0f / 255.0f, 1.0f); - ImVec4 InstancedEntityColorSceneBrowser = ImVec4(80.0f / 255.0f, 72.0f / 255.0f, 1.0f, 1.0f); - ImVec4 CameraColorSceneBrowser = ImVec4(0.0f, 215.0f / 255.0f, 201.0f / 255.0f, 1.0f); - ImVec4 LightColorSceneBrowser = ImVec4(243.0f / 255.0f, 230.0f / 255.0f, 31.0f / 255.0f, 1.0f); - - void DrawCorrectSceneBrowserIcon(const FEObject* SceneObject) const; - FETexture* EntitySceneBrowserIcon = nullptr; - FETexture* InstancedEntitySceneBrowserIcon = nullptr; - FETexture* DirectionalLightSceneBrowserIcon = nullptr; - FETexture* SpotLightSceneBrowserIcon = nullptr; - FETexture* PointLightSceneBrowserIcon = nullptr; - FETexture* TerrainSceneBrowserIcon = nullptr; - FETexture* CameraSceneBrowserIcon = nullptr; - - DragAndDropTarget* SceneWindowTarget = nullptr; - - static void OnCameraUpdate(FEBasicCamera* Camera); - static void MouseButtonCallback(int Button, int Action, int Mods); - static void MouseMoveCallback(double Xpos, double Ypos); - static void KeyButtonCallback(int Key, int Scancode, int Action, int Mods); - static void RenderTargetResizeCallback(int NewW, int NewH); - static void DropCallback(int Count, const char** Paths); - - void DisplaySceneBrowser(); - bool bSceneBrowserVisible = true; - void DisplayInspector(); - bool bInspectorVisible = true; - bool bEffectsWindowVisible = true; - void DisplayEffectsWindow() const; - bool bLogWindowVisible = true; - void DisplayLogWindow() const; - - static void CloseWindowCallBack(); - - void ShowTransformConfiguration(FEObject* Object, FETransformComponent* Transform) const; - void ShowTransformConfiguration(std::string Name, FETransformComponent* Transform) const; - - void DisplayLightProperties(FELight* Light) const; - void DisplayLightsProperties() const; - - void ShowInFolderItem(FEObject* Object); - - // ************** Terrain Settings ************** - ImGuiButton* ExportHeightMapButton = nullptr; - ImGuiButton* ImportHeightMapButton = nullptr; - ImGuiImageButton* SculptBrushButton = nullptr; - ImGuiImageButton* LevelBrushButton = nullptr; - ImGuiImageButton* SmoothBrushButton = nullptr; - - ImGuiImageButton* LayerBrushButton = nullptr; - - static bool EntityChangePrefabTargetCallBack(FEObject* Object, void** EntityPointer); - static bool TerrainChangeMaterialTargetCallBack(FEObject* Object, void** LayerIndex); - - static FEEntity* EntityToModify; - static void ChangePrefabOfEntityCallBack(std::vector SelectionsResult); - - DragAndDropTarget* EntityChangePrefabTarget = nullptr; - std::vector TerrainChangeMaterialIndecies; - std::vector TerrainChangeLayerMaterialTargets; - - int HoveredTerrainLayerItem = -1; - void DisplayTerrainSettings(FETerrain* Terrain); - - int TerrainLayerRenameIndex = -1; - char TerrainLayerRename[1024]; - bool bLastFrameTerrainLayerRenameEditWasVisiable = false; - // ************** Terrain Settings END ************** - // - // ************** Content Browser ************** - - FETexture* FolderIcon = nullptr; - FETexture* ShaderIcon = nullptr; - FETexture* VFSBackIcon = nullptr; - - FETexture* TextureContentBrowserIcon = nullptr; - FETexture* MeshContentBrowserIcon = nullptr; - FETexture* MaterialContentBrowserIcon = nullptr; - FETexture* GameModelContentBrowserIcon = nullptr; - FETexture* PrefabContentBrowserIcon = nullptr; - - void DisplayContentBrowser(); - bool bContentBrowserVisible = true; - void ChooseTexturesForContentBrowserItem(FETexture*& PreviewTexture, FETexture*& SmallAdditionTypeIcon, ImVec2& UV0, ImVec2& UV1, FEObject* Item); - void DisplayContentBrowserItems(); - - float ContentBrowserItemIconSize = 128.0; - int ContentBrowserItemUnderMouse = -1; - int ContentBrowserRenameIndex = -1; - char ContentBrowserRename[1024]; - bool bLastFrameRenameEditWasVisiable = false; - - std::vector AllResourcesContentBrowser; - std::vector FilteredResourcesContentBrowser; - char FilterForResourcesContentBrowser[512]; - static FEObject* ItemInFocus; - std::string ObjTypeFilterForResourcesContentBrowser; - void UpdateFilterForResourcesContentBrowser(); - FETexture* AllContentBrowserIcon = nullptr; - ImGuiImageButton* FilterAllTypesButton = nullptr; - ImGuiImageButton* FilterTextureTypeButton = nullptr; - ImGuiImageButton* FilterMeshTypeButton = nullptr; - ImGuiImageButton* FilterMaterialTypeButton = nullptr; - ImGuiImageButton* FilterGameModelTypeButton = nullptr; - ImGuiImageButton* FilterPrefabTypeButton = nullptr; - - char FilterForSceneEntities[512]; - bool bShouldOpenContextMenuInContentBrowser = false; - bool bShouldOpenContextMenuInSceneEntities = false; - - // ************** Drag&Drop ************** - struct DirectoryDragAndDropCallbackInfo - { - std::string DirectoryPath; - }; - std::vector DirectoryDragAndDropInfo; - std::vector ContentBrowserDirectoriesTargets; - DragAndDropTarget* VFSBackButtonTarget = nullptr; - DirectoryDragAndDropCallbackInfo VFSBackButtoninfo; - - static bool DirectoryDragAndDropCallback(FEObject* Object, void** Directory) - { - const DirectoryDragAndDropCallbackInfo* info = reinterpret_cast(Directory); - if (Object->GetType() == FE_NULL) - { - std::string OldPath = VIRTUAL_FILE_SYSTEM.GetCurrentPath(); - if (OldPath.back() != '/') - OldPath += "/"; - - VIRTUAL_FILE_SYSTEM.MoveDirectory(OldPath + Object->GetName(), info->DirectoryPath); - } - else - { - VIRTUAL_FILE_SYSTEM.MoveFile(Object, VIRTUAL_FILE_SYSTEM.GetCurrentPath(), info->DirectoryPath); - } - - return true; - } - - void UpdateDirectoryDragAndDropTargets(); - - // ************** Drag&Drop END ************** - - // ************** Content Browser END ************** - - int TextureUnderMouse = -1; - int MeshUnderMouse = -1; - std::string ShaderIdUnderMouse; - int MaterialUnderMouse = -1; - int GameModelUnderMouse = -1; - int EntityUnderMouse = -1; - - bool bGameMode = false; - bool IsInGameMode() const; - void SetGameMode(bool GameMode); - - void RenderAllSubWindows(); - - void SetUpImgui(); - void SetImguiStyle(); + SINGLETON_PRIVATE_PART(FEEditor) + + // Mouse and input + double LastMouseX, LastMouseY; + double MouseX, MouseY; + + std::string FocusedEditorSceneID = ""; + ImGuiID DockspaceID = 0; + + std::vector EditorSceneWindows; + + void DeleteScene(std::string SceneID); + + // Clipboard + std::string SceneEntityIDInClipboard; + + // Callbacks + static void AfterEngineUpdate(); + static void MouseButtonCallback(int Button, int Action, int Mods); + static void MouseMoveCallback(double Xpos, double Ypos); + static void KeyButtonCallback(int Key, int Scancode, int Action, int Mods); + static void OnViewportResize(std::string ViewportID); + static void DropCallback(int Count, const char** Paths); + static void CloseWindowCallBack(); + + // Effects window + bool bEditorCamerasWindowVisible = true; + void DisplayEditorCamerasWindow() const; + + // Log window + bool bLogWindowVisible = true; + void DisplayLogWindow() const; + + // Resource under mouse + int TextureUnderMouse = -1; + int MeshUnderMouse = -1; + std::string ShaderIdUnderMouse; + int MaterialUnderMouse = -1; + int GameModelUnderMouse = -1; + int EntityUnderMouse = -1; + + // Game mode + bool bGameMode = false; + bool SetGameModeInternal(bool GameMode); + std::unordered_map ParentIDToScenesInGameMode; + bool DuplicateScenesForGameMode(); + + // Sub-windows + void RenderAllSubWindows(); + + // ImGui setup + void SetUpImgui(); + void SetImguiStyle(); + + void OnProjectClose(); + + void BeforeChangeOfFocusedScene(FEScene* NewSceneInFocus); + + std::unordered_map SceneIDToOldMainCameraID; }; -#define EDITOR FEEditor::getInstance() \ No newline at end of file +#define EDITOR FEEditor::GetInstance() \ No newline at end of file diff --git a/FEEditorContentBrowser.cpp b/FEEditorContentBrowser.cpp deleted file mode 100644 index 0f30607..0000000 --- a/FEEditorContentBrowser.cpp +++ /dev/null @@ -1,762 +0,0 @@ -#include "FEEditor.h" - -static FETexture* TempTexture = nullptr; -static void AddTransparencyToTextureCallBack(const std::vector SelectionsResult) -{ - if (TempTexture == nullptr) - return; - - if (SelectionsResult.size() == 1 && SelectionsResult[0]->GetType() == FE_TEXTURE) - { - FETexture* OriginalTexture = TempTexture; - - FETexture* NewTexture = RESOURCE_MANAGER.CreateTextureWithTransparency(OriginalTexture, reinterpret_cast(SelectionsResult[0])); - if (NewTexture == nullptr) - { - TempTexture = nullptr; - return; - } - - unsigned char* NewRawData = NewTexture->GetRawData(); - const int MaxDimention = std::max(OriginalTexture->GetWidth(), OriginalTexture->GetHeight()); - const size_t MipCount = size_t(floor(log2(MaxDimention)) + 1); - OriginalTexture->UpdateRawData(NewRawData, MipCount); - FE_GL_ERROR(glGenerateMipmap(GL_TEXTURE_2D)); - FE_GL_ERROR(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 16.0f)); - FE_GL_ERROR(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, 0.0f)); - PROJECT_MANAGER.GetCurrent()->AddUnSavedObject(OriginalTexture); - - delete[] NewRawData; - RESOURCE_MANAGER.DeleteFETexture(NewTexture); - } - - TempTexture = nullptr; -} - -static void CreateNewPrefabCallBack(const std::vector SelectionsResult) -{ - if (!SelectionsResult.empty() && SelectionsResult[0]->GetType() == FE_GAMEMODEL) - { - FEPrefab* NewPrefab = RESOURCE_MANAGER.CreatePrefab(reinterpret_cast(SelectionsResult[0])); - - if (SelectionsResult.size() > 1) - { - for (int i = 1; i < SelectionsResult.size(); i++) - { - if (SelectionsResult[i]->GetType() == FE_GAMEMODEL) - NewPrefab->AddComponent(reinterpret_cast(SelectionsResult[i])); - } - } - - PROJECT_MANAGER.GetCurrent()->SetModified(true); - VIRTUAL_FILE_SYSTEM.CreateFile(NewPrefab, VIRTUAL_FILE_SYSTEM.GetCurrentPath()); - } - - SelectFeObjectPopUp::getInstance().SetOneObjectSelectonMode(true); -} - -void FEEditor::DisplayContentBrowser() -{ - if (!bContentBrowserVisible) - return; - - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(15, 15)); - ImGui::Begin("Content Browser", nullptr, ImGuiWindowFlags_None); - - DisplayContentBrowserItems(); - - bool open_context_menu = false; - if (ImGui::IsWindowHovered() && ImGui::IsMouseClicked(1)) - open_context_menu = true; - - if (open_context_menu) - ImGui::OpenPopup("##context_menu"); - - bShouldOpenContextMenuInContentBrowser = false; - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(15, 15)); - if (ImGui::BeginPopup("##context_menu")) - { - bShouldOpenContextMenuInContentBrowser = true; - - if (ContentBrowserItemUnderMouse == -1) - { - if (ImGui::MenuItem("Import Asset...")) - { - std::string FilePath; - FILE_SYSTEM.ShowFileOpenDialog(FilePath, ALL_IMPORT_LOAD_FILTER, 3); - if (!FilePath.empty()) - { - const std::vector LoadedObjects = RESOURCE_MANAGER.ImportAsset(FilePath.c_str()); - for (size_t i = 0; i < LoadedObjects.size(); i++) - { - if (LoadedObjects[i] != nullptr) - { - VIRTUAL_FILE_SYSTEM.CreateFile(LoadedObjects[i], VIRTUAL_FILE_SYSTEM.GetCurrentPath()); - PROJECT_MANAGER.GetCurrent()->SetModified(true); - PROJECT_MANAGER.GetCurrent()->AddUnSavedObject(LoadedObjects[i]); - } - } - } - } - - if (ImGui::MenuItem("*DEPRECATED*Import Tree...")) - { - std::string FilePath; - FILE_SYSTEM.ShowFileOpenDialog(FilePath, OBJ_LOAD_FILTER, 1); - if (!FilePath.empty()) - { - const std::vector LoadedObjects = RESOURCE_MANAGER.ImportOBJ(FilePath.c_str(), true); - for (size_t i = 0; i < LoadedObjects.size(); i++) - { - if (LoadedObjects[i] != nullptr) - { - VIRTUAL_FILE_SYSTEM.CreateFile(LoadedObjects[i], VIRTUAL_FILE_SYSTEM.GetCurrentPath()); - PROJECT_MANAGER.GetCurrent()->SetModified(true); - PROJECT_MANAGER.GetCurrent()->AddUnSavedObject(LoadedObjects[i]); - } - } - } - } - - if (ImGui::BeginMenu("Add")) - { - if (ImGui::MenuItem("Add folder")) - { - const std::string NewDirectoryName = VIRTUAL_FILE_SYSTEM.CreateDirectory(VIRTUAL_FILE_SYSTEM.GetCurrentPath()); - UpdateDirectoryDragAndDropTargets(); - - for (size_t i = 0; i < FilteredResourcesContentBrowser.size(); i++) - { - if (FilteredResourcesContentBrowser[i]->GetName() == NewDirectoryName) - { - ContentBrowserRenameIndex = int(i); - strcpy_s(ContentBrowserRename, FilteredResourcesContentBrowser[i]->GetName().size() + 1, FilteredResourcesContentBrowser[i]->GetName().c_str()); - bLastFrameRenameEditWasVisiable = false; - break; - } - } - } - - if (ImGui::BeginMenu("Texture")) - { - if (ImGui::MenuItem("Combine channels...")) - CombineChannelsToTexturePopUp::getInstance().Show(); - - ImGui::EndMenu(); - } - - if (ImGui::MenuItem("Create new material")) - { - FEMaterial* NewMat = RESOURCE_MANAGER.CreateMaterial(""); - if (NewMat) - { - PROJECT_MANAGER.GetCurrent()->SetModified(true); - NewMat->Shader = RESOURCE_MANAGER.GetShader("0800253C242B05321A332D09"/*"FEPBRShader"*/); - - NewMat->SetAlbedoMap(RESOURCE_MANAGER.NoTexture); - - VIRTUAL_FILE_SYSTEM.CreateFile(NewMat, VIRTUAL_FILE_SYSTEM.GetCurrentPath()); - } - } - - if (ImGui::MenuItem("Create new game model")) - { - FEGameModel* NewGameModel = RESOURCE_MANAGER.CreateGameModel(); - PROJECT_MANAGER.GetCurrent()->SetModified(true); - VIRTUAL_FILE_SYSTEM.CreateFile(NewGameModel, VIRTUAL_FILE_SYSTEM.GetCurrentPath()); - } - - if (ImGui::MenuItem("Create new prefab")) - { - SelectFeObjectPopUp::getInstance().SetOneObjectSelectonMode(false); - SelectFeObjectPopUp::getInstance().Show(FE_GAMEMODEL, CreateNewPrefabCallBack); - } - - ImGui::EndMenu(); - } - } - else - { - std::string FullPath = VIRTUAL_FILE_SYSTEM.GetCurrentPath(); - if (FullPath.back() != '/') - FullPath += '/'; - FullPath += FilteredResourcesContentBrowser[ContentBrowserItemUnderMouse]->GetName(); - - const bool ReadOnlyItem = VIRTUAL_FILE_SYSTEM.IsReadOnly(FilteredResourcesContentBrowser[ContentBrowserItemUnderMouse], FullPath); - - if (ReadOnlyItem) - ImGui::MenuItem("Read Only"); - - if (!ReadOnlyItem) - { - if (ImGui::MenuItem("Rename")) - { - ContentBrowserRenameIndex = ContentBrowserItemUnderMouse; - - strcpy_s(ContentBrowserRename, FilteredResourcesContentBrowser[ContentBrowserItemUnderMouse]->GetName().size() + 1, FilteredResourcesContentBrowser[ContentBrowserItemUnderMouse]->GetName().c_str()); - bLastFrameRenameEditWasVisiable = false; - } - } - - if (FilteredResourcesContentBrowser[ContentBrowserItemUnderMouse]->GetType() == FE_MATERIAL) - { - if (ImGui::MenuItem("Edit")) - { - EditMaterialPopup::getInstance().Show(RESOURCE_MANAGER.GetMaterial(FilteredResourcesContentBrowser[ContentBrowserItemUnderMouse]->GetObjectID())); - } - } - - if (FilteredResourcesContentBrowser[ContentBrowserItemUnderMouse]->GetType() == FE_GAMEMODEL) - { - if (ImGui::MenuItem("Edit")) - { - EditGameModelPopup::getInstance().Show(RESOURCE_MANAGER.GetGameModel(FilteredResourcesContentBrowser[ContentBrowserItemUnderMouse]->GetObjectID())); - } - - if (ImGui::MenuItem("Create Prefab out of this Game Model")) - { - FEPrefab* NewPrefab = RESOURCE_MANAGER.CreatePrefab(RESOURCE_MANAGER.GetGameModel(FilteredResourcesContentBrowser[ContentBrowserItemUnderMouse]->GetObjectID())); - PROJECT_MANAGER.GetCurrent()->SetModified(true); - VIRTUAL_FILE_SYSTEM.CreateFile(NewPrefab, VIRTUAL_FILE_SYSTEM.GetCurrentPath()); - } - } - - if (FilteredResourcesContentBrowser[ContentBrowserItemUnderMouse]->GetType() == FE_PREFAB) - { - if (ImGui::MenuItem("Edit")) - { - PrefabEditorWindow::getInstance().Show(RESOURCE_MANAGER.GetPrefab(FilteredResourcesContentBrowser[ContentBrowserItemUnderMouse]->GetObjectID())); - } - } - - if (FilteredResourcesContentBrowser[ContentBrowserItemUnderMouse]->GetType() == FE_SHADER) - { - if (ImGui::MenuItem("Edit")) - { - shaderEditorWindow::getInstance().Show(RESOURCE_MANAGER.GetShader(FilteredResourcesContentBrowser[ContentBrowserItemUnderMouse]->GetObjectID())); - } - } - - if (!ReadOnlyItem) - { - if (ImGui::MenuItem("Delete")) - { - if (FilteredResourcesContentBrowser[ContentBrowserItemUnderMouse]->GetType() == FE_NULL) - { - DeleteDirectoryPopup::getInstance().Show(FilteredResourcesContentBrowser[ContentBrowserItemUnderMouse]->GetName()); - } - else if (FilteredResourcesContentBrowser[ContentBrowserItemUnderMouse]->GetType() == FE_MESH) - { - DeleteMeshPopup::getInstance().Show(RESOURCE_MANAGER.GetMesh(FilteredResourcesContentBrowser[ContentBrowserItemUnderMouse]->GetObjectID())); - } - else if (FilteredResourcesContentBrowser[ContentBrowserItemUnderMouse]->GetType() == FE_TEXTURE) - { - DeleteTexturePopup::getInstance().Show(RESOURCE_MANAGER.GetTexture(FilteredResourcesContentBrowser[ContentBrowserItemUnderMouse]->GetObjectID())); - } - else if (FilteredResourcesContentBrowser[ContentBrowserItemUnderMouse]->GetType() == FE_MATERIAL) - { - DeleteMaterialPopup::getInstance().Show(RESOURCE_MANAGER.GetMaterial(FilteredResourcesContentBrowser[ContentBrowserItemUnderMouse]->GetObjectID())); - } - else if (FilteredResourcesContentBrowser[ContentBrowserItemUnderMouse]->GetType() == FE_GAMEMODEL) - { - DeleteGameModelPopup::getInstance().Show(RESOURCE_MANAGER.GetGameModel(FilteredResourcesContentBrowser[ContentBrowserItemUnderMouse]->GetObjectID())); - } - else if (FilteredResourcesContentBrowser[ContentBrowserItemUnderMouse]->GetType() == FE_PREFAB) - { - DeletePrefabPopup::getInstance().Show(RESOURCE_MANAGER.GetPrefab(FilteredResourcesContentBrowser[ContentBrowserItemUnderMouse]->GetObjectID())); - } - } - } - - if (FilteredResourcesContentBrowser[ContentBrowserItemUnderMouse]->GetType() == FE_TEXTURE) - { - if (ImGui::BeginMenu("Convert")) - { - if (ImGui::MenuItem("Texture channels to individual textures")) - { - const std::vector NewTextures = RESOURCE_MANAGER.ChannelsToFETextures(RESOURCE_MANAGER.GetTexture(FilteredResourcesContentBrowser[ContentBrowserItemUnderMouse]->GetObjectID())); - - PROJECT_MANAGER.GetCurrent()->AddUnSavedObject(NewTextures[0]); - PROJECT_MANAGER.GetCurrent()->AddUnSavedObject(NewTextures[1]); - PROJECT_MANAGER.GetCurrent()->AddUnSavedObject(NewTextures[2]); - PROJECT_MANAGER.GetCurrent()->AddUnSavedObject(NewTextures[3]); - - PROJECT_MANAGER.GetCurrent()->SetModified(true); - - VIRTUAL_FILE_SYSTEM.CreateFile(NewTextures[0], VIRTUAL_FILE_SYSTEM.GetCurrentPath()); - VIRTUAL_FILE_SYSTEM.CreateFile(NewTextures[1], VIRTUAL_FILE_SYSTEM.GetCurrentPath()); - VIRTUAL_FILE_SYSTEM.CreateFile(NewTextures[2], VIRTUAL_FILE_SYSTEM.GetCurrentPath()); - VIRTUAL_FILE_SYSTEM.CreateFile(NewTextures[3], VIRTUAL_FILE_SYSTEM.GetCurrentPath()); - } - - if (ImGui::MenuItem("Resize")) - { - FETexture* TextureToResize = RESOURCE_MANAGER.GetTexture(FilteredResourcesContentBrowser[ContentBrowserItemUnderMouse]->GetObjectID()); - resizeTexturePopup::getInstance().Show(TextureToResize); - } - - ImGui::EndMenu(); - } - - if (ImGui::BeginMenu("Add transparency")) - { - if (ImGui::MenuItem("Choose transparency mask")) - { - TempTexture = reinterpret_cast(FilteredResourcesContentBrowser[ContentBrowserItemUnderMouse]); - SelectFeObjectPopUp::getInstance().Show(FE_TEXTURE, AddTransparencyToTextureCallBack); - } - - ImGui::EndMenu(); - } - - if (ImGui::BeginMenu("Export")) - { - FETexture* TextureToExport = RESOURCE_MANAGER.GetTexture(FilteredResourcesContentBrowser[ContentBrowserItemUnderMouse]->GetObjectID()); - - if (ImGui::MenuItem("as PNG")) - { - std::string FilePath; - FILE_SYSTEM.ShowFileSaveDialog(FilePath, TEXTURE_LOAD_FILTER, 1); - - if (!FilePath.empty()) - { - FilePath += ".png"; - RESOURCE_MANAGER.ExportFETextureToPNG(TextureToExport, FilePath.c_str()); - } - } - - ImGui::EndMenu(); - } - } - } - - ImGui::EndPopup(); - } - - ImGui::PopStyleVar(); - ImGui::PopStyleVar(); - ImGui::End(); -} - -void FEEditor::ChooseTexturesForContentBrowserItem(FETexture*& PreviewTexture, FETexture*& SmallAdditionTypeIcon, ImVec2& UV0, ImVec2& UV1, FEObject* Item) -{ - if (Item->GetType() == FE_NULL) - { - UV0 = ImVec2(0.0f, 0.0f); - UV1 = ImVec2(1.0f, 1.0f); - - PreviewTexture = FolderIcon; - - ImGui::PopStyleColor(); - ImGui::PopStyleColor(); - ImGui::PopStyleColor(); - - ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor(0.5f, 0.5f, 0.5f, 0.0f)); - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor(0.95f, 0.90f, 0.0f)); - ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor(0.1f, 1.0f, 0.1f, 1.0f)); - } - else if (Item->GetType() == FE_SHADER) - { - UV0 = ImVec2(0.0f, 0.0f); - UV1 = ImVec2(1.0f, 1.0f); - - PreviewTexture = ShaderIcon; - - ImGui::PopStyleColor(); - ImGui::PopStyleColor(); - ImGui::PopStyleColor(); - - ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor(0.5f, 0.5f, 0.5f, 0.0f)); - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor(0.95f, 0.90f, 0.0f)); - ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor(0.1f, 1.0f, 0.1f, 1.0f)); - } - else if (Item->GetType() == FE_MESH) - { - UV0 = ImVec2(0.0f, 1.0f); - UV1 = ImVec2(1.0f, 0.0f); - - PreviewTexture = PREVIEW_MANAGER.GetMeshPreview(Item->GetObjectID()); - SmallAdditionTypeIcon = MeshContentBrowserIcon; - } - else if (Item->GetType() == FE_TEXTURE) - { - PreviewTexture = RESOURCE_MANAGER.GetTexture(Item->GetObjectID()); - SmallAdditionTypeIcon = TextureContentBrowserIcon; - } - else if (Item->GetType() == FE_MATERIAL) - { - UV0 = ImVec2(0.0f, 1.0f); - UV1 = ImVec2(1.0f, 0.0f); - - PreviewTexture = PREVIEW_MANAGER.GetMaterialPreview(Item->GetObjectID()); - SmallAdditionTypeIcon = MaterialContentBrowserIcon; - } - else if (Item->GetType() == FE_GAMEMODEL) - { - UV0 = ImVec2(0.0f, 1.0f); - UV1 = ImVec2(1.0f, 0.0f); - - PreviewTexture = PREVIEW_MANAGER.GetGameModelPreview(Item->GetObjectID()); - SmallAdditionTypeIcon = GameModelContentBrowserIcon; - } - else if (Item->GetType() == FE_PREFAB) - { - UV0 = ImVec2(0.0f, 1.0f); - UV1 = ImVec2(1.0f, 0.0f); - - PreviewTexture = PREVIEW_MANAGER.GetPrefabPreview(Item->GetObjectID()); - SmallAdditionTypeIcon = PrefabContentBrowserIcon; - } -} - -void FEEditor::DisplayContentBrowserItems() -{ - ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor(0.5f, 0.5f, 0.5f, 0.0f)); - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::ImColor(0.95f, 0.90f, 0.0f)); - ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::ImColor(0.1f, 1.0f, 0.1f, 1.0f)); - - float CurrentY = ImGui::GetCursorPosY(); - ImGui::SetCursorPosY(CurrentY); - if (ImGui::ImageButton((void*)(intptr_t)VFSBackIcon->GetTextureID(), ImVec2(64, 64), ImVec2(0.0f, 0.0f), ImVec2(1.0f, 1.0f), 8, ImColor(0.0f, 0.0f, 0.0f, 0.0f), ImColor(1.0f, 1.0f, 1.0f, 1.0f))) - { - VIRTUAL_FILE_SYSTEM.SetCurrentPath(VIRTUAL_FILE_SYSTEM.GetDirectoryParent(VIRTUAL_FILE_SYSTEM.GetCurrentPath())); - strcpy_s(FilterForResourcesContentBrowser, ""); - } - VFSBackButtonTarget->StickToItem(); - - ImGui::PopStyleColor(); - ImGui::PopStyleColor(); - ImGui::PopStyleColor(); - - static std::string LastFramePath; - AllResourcesContentBrowser.clear(); - AllResourcesContentBrowser = VIRTUAL_FILE_SYSTEM.GetDirectoryContent(VIRTUAL_FILE_SYSTEM.GetCurrentPath()); - - ImGui::SetCursorPosX(100); - ImGui::SetCursorPosY(CurrentY + 5); - ImGui::Text("Filter by type: "); - - ImGui::SetCursorPosX(120 + 140); - ImGui::SetCursorPosY(CurrentY - 5); - ObjTypeFilterForResourcesContentBrowser.empty() ? SetSelectedStyle(FilterAllTypesButton) : SetDefaultStyle(FilterAllTypesButton); - FilterAllTypesButton->Render(); - if (FilterAllTypesButton->IsClicked()) - ObjTypeFilterForResourcesContentBrowser = ""; - - ImGui::SetCursorPosX(120 + 140 + 48); - ImGui::SetCursorPosY(CurrentY - 5); - ObjTypeFilterForResourcesContentBrowser == FEObjectTypeToString(FE_TEXTURE) ? SetSelectedStyle(FilterTextureTypeButton) : SetDefaultStyle(FilterTextureTypeButton); - FilterTextureTypeButton->Render(); - if (FilterTextureTypeButton->IsClicked()) - ObjTypeFilterForResourcesContentBrowser = FEObjectTypeToString(FE_TEXTURE); - - ImGui::SetCursorPosX(120 + 140 + 48 + 48); - ImGui::SetCursorPosY(CurrentY - 5); - ObjTypeFilterForResourcesContentBrowser == FEObjectTypeToString(FE_MESH) ? SetSelectedStyle(FilterMeshTypeButton) : SetDefaultStyle(FilterMeshTypeButton); - FilterMeshTypeButton->Render(); - if (FilterMeshTypeButton->IsClicked()) - ObjTypeFilterForResourcesContentBrowser = FEObjectTypeToString(FE_MESH); - - ImGui::SetCursorPosX(120 + 140 + 48 + 48 + 48); - ImGui::SetCursorPosY(CurrentY - 5); - ObjTypeFilterForResourcesContentBrowser == FEObjectTypeToString(FE_MATERIAL) ? SetSelectedStyle(FilterMaterialTypeButton) : SetDefaultStyle(FilterMaterialTypeButton); - FilterMaterialTypeButton->Render(); - if (FilterMaterialTypeButton->IsClicked()) - ObjTypeFilterForResourcesContentBrowser = FEObjectTypeToString(FE_MATERIAL); - - ImGui::SetCursorPosX(120 + 140 + 48 + 48 + 48 + 48); - ImGui::SetCursorPosY(CurrentY - 5); - ObjTypeFilterForResourcesContentBrowser == FEObjectTypeToString(FE_GAMEMODEL) ? SetSelectedStyle(FilterGameModelTypeButton) : SetDefaultStyle(FilterGameModelTypeButton); - FilterGameModelTypeButton->Render(); - if (FilterGameModelTypeButton->IsClicked()) - ObjTypeFilterForResourcesContentBrowser = FEObjectTypeToString(FE_GAMEMODEL); - - ImGui::SetCursorPosX(120 + 140 + 48 + 48 + 48 + 48 + 48); - ImGui::SetCursorPosY(CurrentY - 5); - ObjTypeFilterForResourcesContentBrowser == FEObjectTypeToString(FE_PREFAB) ? SetSelectedStyle(FilterPrefabTypeButton) : SetDefaultStyle(FilterPrefabTypeButton); - FilterPrefabTypeButton->Render(); - if (FilterPrefabTypeButton->IsClicked()) - ObjTypeFilterForResourcesContentBrowser = FEObjectTypeToString(FE_PREFAB); - - ImGui::SetCursorPosX(100); - ImGui::SetCursorPosY(CurrentY + 50); - ImGui::Text("Filter by name: "); - - ImGui::SetCursorPosX(120 + 140); - ImGui::SetCursorPosY(CurrentY + 47); - ImGui::InputText("##filter", FilterForResourcesContentBrowser, IM_ARRAYSIZE(FilterForResourcesContentBrowser)); - - ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 25); - ImGui::Separator(); - - UpdateFilterForResourcesContentBrowser(); - UpdateDirectoryDragAndDropTargets(); - - // ************** Drag&Drop ************** - if (VIRTUAL_FILE_SYSTEM.GetCurrentPath() != LastFramePath) - { - LastFramePath = VIRTUAL_FILE_SYSTEM.GetCurrentPath(); - UpdateDirectoryDragAndDropTargets(); - } - int DirectoryIndex = 0; - // ************** Drag&Drop END ************** - - int IconsPerWindowWidth = (int)(ImGui::GetCurrentContext()->CurrentWindow->Rect().GetWidth() / (ContentBrowserItemIconSize + 8 + 32)); - // Possibly window is minimized anyway ImGui::Columns can't take 0 as columns count! - if (IconsPerWindowWidth == 0) - return; - - if (!bShouldOpenContextMenuInContentBrowser) ContentBrowserItemUnderMouse = -1; - ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 5); - ImGui::Columns(IconsPerWindowWidth, "mycolumns3", false); - - for (size_t i = 0; i < FilteredResourcesContentBrowser.size(); i++) - { - ImGui::PushID(int(std::hash{}(FilteredResourcesContentBrowser[i]->GetObjectID()))); - - if (ItemInFocus != nullptr && ItemInFocus->GetObjectID() == FilteredResourcesContentBrowser[i]->GetObjectID()) - { - ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor(0.1f, 1.0f, 0.1f, 1.0f)); - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor(0.1f, 1.0f, 0.1f, 1.0f)); - ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor(0.1f, 1.0f, 0.1f, 1.0f)); - } - else - { - ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor(0.5f, 0.5f, 0.5f)); - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor(0.95f, 0.90f, 0.0f)); - ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor(0.1f, 1.0f, 0.1f, 1.0f)); - } - - ImVec2 uv0 = ImVec2(0.0f, 0.0f); - ImVec2 uv1 = ImVec2(1.0f, 1.0f); - - FETexture* PreviewTexture = nullptr; - FETexture* SmallAdditionTypeIcon = nullptr; - - ChooseTexturesForContentBrowserItem(PreviewTexture, SmallAdditionTypeIcon, uv0, uv1, FilteredResourcesContentBrowser[i]); - - if (PreviewTexture != nullptr) - ImGui::ImageButton((void*)(intptr_t)PreviewTexture->GetTextureID(), ImVec2(ContentBrowserItemIconSize, ContentBrowserItemIconSize), uv0, uv1, 8, ImColor(0.0f, 0.0f, 0.0f, 0.0f), ImColor(1.0f, 1.0f, 1.0f, 1.0f)); - - if (FilteredResourcesContentBrowser[i]->GetType() == FE_NULL && ContentBrowserDirectoriesTargets.size() > (size_t)DirectoryIndex) - ContentBrowserDirectoriesTargets[DirectoryIndex++]->StickToItem(); - - if (ImGui::IsItemHovered()) - { - if (!bShouldOpenContextMenuInContentBrowser && !DRAG_AND_DROP_MANAGER.ObjectIsDraged()) - { - std::string AdditionalTypeInfo; - if (FilteredResourcesContentBrowser[i]->GetType() == FE_TEXTURE) - { - AdditionalTypeInfo += "\nTexture type: "; - AdditionalTypeInfo += FETexture::TextureInternalFormatToString(RESOURCE_MANAGER.GetTexture(FilteredResourcesContentBrowser[i]->GetObjectID())->GetInternalFormat()); - } - - ImGui::BeginTooltip(); - ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f); - ImGui::TextUnformatted(("Name: " + FilteredResourcesContentBrowser[i]->GetName() + - "\nType: " + FEObjectTypeToString(FilteredResourcesContentBrowser[i]->GetType()) + - AdditionalTypeInfo + - "\nPath: " + VIRTUAL_FILE_SYSTEM.GetCurrentPath() - ).c_str()); - ImGui::PopTextWrapPos(); - ImGui::EndTooltip(); - - ContentBrowserItemUnderMouse = int(i); - - if (ImGui::IsMouseDragging(0)) - DRAG_AND_DROP_MANAGER.SetObject(FilteredResourcesContentBrowser[i], PreviewTexture, uv0, uv1); - } - } - - if (SmallAdditionTypeIcon != nullptr) - { - ImVec2 CursorPosBefore = ImGui::GetCursorPos(); - ImGui::SetCursorPos(ImVec2(CursorPosBefore.x + 10, CursorPosBefore.y - 48)); - ImGui::Image((void*)(intptr_t)SmallAdditionTypeIcon->GetTextureID(), ImVec2(32, 32)); - ImGui::SetCursorPos(CursorPosBefore); - } - - ImGui::PopStyleColor(); - ImGui::PopStyleColor(); - ImGui::PopStyleColor(); - - ImGui::PopID(); - - if (ContentBrowserRenameIndex == i) - { - if (!bLastFrameRenameEditWasVisiable) - { - ImGui::SetKeyboardFocusHere(0); - ImGui::SetFocusID(ImGui::GetID("##newNameEditor"), ImGui::GetCurrentWindow()); - ImGui::SetItemDefaultFocus(); - bLastFrameRenameEditWasVisiable = true; - } - - ImGui::SetNextItemWidth(ContentBrowserItemIconSize + 8.0f + 8.0f); - if (ImGui::InputText("##newNameEditor", ContentBrowserRename, IM_ARRAYSIZE(ContentBrowserRename), ImGuiInputTextFlags_EnterReturnsTrue) || - ImGui::IsMouseClicked(0) && !ImGui::IsItemHovered() || ImGui::GetFocusID() != ImGui::GetID("##newNameEditor")) - { - if (FilteredResourcesContentBrowser[ContentBrowserRenameIndex]->GetType() == FE_NULL) - { - std::string PathToDirectory = VIRTUAL_FILE_SYSTEM.GetCurrentPath(); - if (PathToDirectory.back() != '/') - PathToDirectory += '/'; - - PathToDirectory += FilteredResourcesContentBrowser[ContentBrowserRenameIndex]->GetName(); - VIRTUAL_FILE_SYSTEM.RenameDirectory(ContentBrowserRename, PathToDirectory); - - UpdateDirectoryDragAndDropTargets(); - } - else - { - FilteredResourcesContentBrowser[ContentBrowserRenameIndex]->SetDirtyFlag(true); - PROJECT_MANAGER.GetCurrent()->SetModified(true); - FilteredResourcesContentBrowser[ContentBrowserRenameIndex]->SetName(ContentBrowserRename); - } - - ContentBrowserRenameIndex = -1; - } - } - else - { - ImVec2 TextSize = ImGui::CalcTextSize(FilteredResourcesContentBrowser[i]->GetName().c_str()); - if (TextSize.x < ContentBrowserItemIconSize + 8 + 8) - { - ImGui::SetCursorPosX(ImGui::GetCursorPosX() + (ContentBrowserItemIconSize + 8.0f + 8.0f) / 2.0f - TextSize.x / 2.0f); - ImGui::Text(FilteredResourcesContentBrowser[i]->GetName().c_str()); - } - else - { - ImGui::Text(FilteredResourcesContentBrowser[i]->GetName().c_str()); - } - } - - ImGui::NextColumn(); - } - - if (ImGui::IsMouseDoubleClicked(0) && ContentBrowserItemUnderMouse != -1) - { - if (FilteredResourcesContentBrowser[ContentBrowserItemUnderMouse]->GetType() == FE_NULL) - { - std::string CurrentPath = VIRTUAL_FILE_SYSTEM.GetCurrentPath(); - if (CurrentPath.back() != '/') - CurrentPath += '/'; - - CurrentPath += FilteredResourcesContentBrowser[ContentBrowserItemUnderMouse]->GetName(); - VIRTUAL_FILE_SYSTEM.SetCurrentPath(CurrentPath); - } - else if (FilteredResourcesContentBrowser[ContentBrowserItemUnderMouse]->GetType() == FE_MESH) - { - std::string MeshInfo = "Vertex count: "; - MeshInfo += std::to_string(RESOURCE_MANAGER.GetMesh(FilteredResourcesContentBrowser[ContentBrowserItemUnderMouse]->GetObjectID())->GetVertexCount()); - MeshInfo += "\n"; - MeshInfo += "Sub material socket: "; - MeshInfo += RESOURCE_MANAGER.GetMesh(FilteredResourcesContentBrowser[ContentBrowserItemUnderMouse]->GetObjectID())->GetMaterialCount() == 2 ? "Yes" : "No"; - MessagePopUp::getInstance().Show("Mesh info", MeshInfo.c_str()); - } - else if (FilteredResourcesContentBrowser[ContentBrowserItemUnderMouse]->GetType() == FE_MATERIAL) - { - EditMaterialPopup::getInstance().Show(RESOURCE_MANAGER.GetMaterial(FilteredResourcesContentBrowser[ContentBrowserItemUnderMouse]->GetObjectID())); - } - else if (FilteredResourcesContentBrowser[ContentBrowserItemUnderMouse]->GetType() == FE_GAMEMODEL) - { - if (!bShouldOpenContextMenuInContentBrowser && !EditGameModelPopup::getInstance().IsVisible()) - { - EditGameModelPopup::getInstance().Show(RESOURCE_MANAGER.GetGameModel(FilteredResourcesContentBrowser[ContentBrowserItemUnderMouse]->GetObjectID())); - } - } - else if (FilteredResourcesContentBrowser[ContentBrowserItemUnderMouse]->GetType() == FE_PREFAB) - { - if (!bShouldOpenContextMenuInContentBrowser && !PrefabEditorWindow::getInstance().IsVisible()) - { - PrefabEditorWindow::getInstance().Show(RESOURCE_MANAGER.GetPrefab(FilteredResourcesContentBrowser[ContentBrowserItemUnderMouse]->GetObjectID())); - } - } - } - - ImGui::Columns(1); -} - -void FEEditor::UpdateDirectoryDragAndDropTargets() -{ - ContentBrowserDirectoriesTargets.clear(); - DirectoryDragAndDropInfo.clear(); - AllResourcesContentBrowser.clear(); - AllResourcesContentBrowser = VIRTUAL_FILE_SYSTEM.GetDirectoryContent(VIRTUAL_FILE_SYSTEM.GetCurrentPath()); - - UpdateFilterForResourcesContentBrowser(); - - DirectoryDragAndDropInfo.resize(VIRTUAL_FILE_SYSTEM.SubDirectoriesCount(VIRTUAL_FILE_SYSTEM.GetCurrentPath())); - int SubDirectoryIndex = 0; - for (size_t i = 0; i < FilteredResourcesContentBrowser.size(); i++) - { - if (FilteredResourcesContentBrowser[i]->GetType() == FE_NULL) - { - DirectoryDragAndDropCallbackInfo info; - - info.DirectoryPath = VIRTUAL_FILE_SYSTEM.GetCurrentPath(); - if (VIRTUAL_FILE_SYSTEM.GetCurrentPath().back() != '/') - info.DirectoryPath += "/"; - - info.DirectoryPath += FilteredResourcesContentBrowser[i]->GetName() + "/"; - DirectoryDragAndDropInfo[SubDirectoryIndex] = info; - - ContentBrowserDirectoriesTargets.push_back(DRAG_AND_DROP_MANAGER.AddTarget(std::vector { FE_NULL, FE_SHADER, FE_TEXTURE, FE_MESH, FE_MATERIAL, FE_GAMEMODEL, FE_PREFAB }, - DirectoryDragAndDropCallback, reinterpret_cast(&DirectoryDragAndDropInfo[SubDirectoryIndex]), - std::vector { "Drop to move to folder", "Drop to move to folder", "Drop to move to folder", "Drop to move to folder", "Drop to move to folder", "Drop to move to folder", "Drop to move to folder" })); - SubDirectoryIndex++; - } - } - - if (VFSBackButtonTarget == nullptr) - { - VFSBackButtoninfo.DirectoryPath = VIRTUAL_FILE_SYSTEM.GetDirectoryParent(VIRTUAL_FILE_SYSTEM.GetCurrentPath()); - VFSBackButtonTarget = DRAG_AND_DROP_MANAGER.AddTarget(std::vector { FE_NULL, FE_SHADER, FE_TEXTURE, FE_MESH, FE_MATERIAL, FE_GAMEMODEL, FE_PREFAB }, - DirectoryDragAndDropCallback, reinterpret_cast(&VFSBackButtoninfo), - std::vector { "Drop to move to parent folder", "Drop to move to parent folder", "Drop to move to parent folder", "Drop to move to parent folder", "Drop to move to parent folder", "Drop to move to parent folder", "Drop to move to parent folder" }); - } - else - { - VFSBackButtoninfo.DirectoryPath = VIRTUAL_FILE_SYSTEM.GetDirectoryParent(VIRTUAL_FILE_SYSTEM.GetCurrentPath()); - //VFSBackButton->setNewUserData(); - } -} - -void FEEditor::UpdateFilterForResourcesContentBrowser() -{ - FilteredResourcesContentBrowser.clear(); - - // Filter by name. - if (strlen(FilterForResourcesContentBrowser) == 0) - { - FilteredResourcesContentBrowser = AllResourcesContentBrowser; - } - else - { - for (size_t i = 0; i < AllResourcesContentBrowser.size(); i++) - { - if (AllResourcesContentBrowser[i]->GetName().find(FilterForResourcesContentBrowser) != -1) - { - FilteredResourcesContentBrowser.push_back(AllResourcesContentBrowser[i]); - } - } - } - - // Filter by type. - if (!ObjTypeFilterForResourcesContentBrowser.empty()) - { - std::vector FinalFilteredList; - for (size_t i = 0; i < FilteredResourcesContentBrowser.size(); i++) - { - if (FEObjectTypeToString(FilteredResourcesContentBrowser[i]->GetType()) == ObjTypeFilterForResourcesContentBrowser || - // Add folders - FilteredResourcesContentBrowser[i]->GetType() == FE_NULL) - { - FinalFilteredList.push_back(FilteredResourcesContentBrowser[i]); - } - } - - FilteredResourcesContentBrowser = FinalFilteredList; - } -} \ No newline at end of file diff --git a/FEEditorDragAndDropManager.cpp b/FEEditorDragAndDropManager.cpp index a846c43..4f408b6 100644 --- a/FEEditorDragAndDropManager.cpp +++ b/FEEditorDragAndDropManager.cpp @@ -1,26 +1,25 @@ #include "FEEditorDragAndDropManager.h" using namespace FocalEngine; -DragAndDropManager* DragAndDropManager::Instance = nullptr; DragAndDropManager::DragAndDropManager() {} DragAndDropManager::~DragAndDropManager() {} void DragAndDropManager::InitializeResources() { HandCursor = RESOURCE_MANAGER.LoadPNGTexture("Resources/Images/handCursor.png", "handCursor"); - RESOURCE_MANAGER.MakeTextureStandard(HandCursor); + RESOURCE_MANAGER.SetTag(HandCursor, EDITOR_RESOURCE_TAG); HandCursorUnavailable = RESOURCE_MANAGER.LoadPNGTexture("Resources/Images/handCursorUnavailable.png", "handCursorUnavailable"); - RESOURCE_MANAGER.MakeTextureStandard(HandCursorUnavailable); + RESOURCE_MANAGER.SetTag(HandCursorUnavailable, EDITOR_RESOURCE_TAG); } -DragAndDropTarget* DragAndDropManager::AddTarget(const FE_OBJECT_TYPE AcceptedType, bool (*Callback)(FEObject*, void**), void** UserData, const std::string ToolTipText) +DragAndDropTarget* DragAndDropManager::AddTarget(const FE_OBJECT_TYPE AcceptedType, std::function Callback, void** UserData, const std::string ToolTipText) { Targets.push_back(new DragAndDropTarget(AcceptedType, Callback, UserData, ToolTipText)); return Targets.back(); } -DragAndDropTarget* DragAndDropManager::AddTarget(std::vector& AcceptedTypes, bool (*Callback)(FEObject*, void**), void** UserData, std::vector& ToolTipTexts) +DragAndDropTarget* DragAndDropManager::AddTarget(std::vector& AcceptedTypes, std::function Callback, void** UserData, std::vector& ToolTipTexts) { Targets.push_back(new DragAndDropTarget(AcceptedTypes, Callback, UserData, ToolTipTexts)); return Targets.back(); @@ -165,9 +164,9 @@ void DragAndDropManager::MouseMove() } } -void DragAndDropManager::SetObject(FEObject* Obj, FETexture* Texture, ImVec2 UV0, ImVec2 UV1) +void DragAndDropManager::SetObjectToDrag(FEObject* Object, FETexture* Texture, ImVec2 UV0, ImVec2 UV1) { - Object = Obj; + this->Object = Object; PreviewTexture = Texture; this->UV0 = UV0; this->UV1 = UV1; @@ -188,7 +187,7 @@ DragAndDropTarget::DragAndDropTarget() this->Callback = nullptr; } -DragAndDropTarget::DragAndDropTarget(const FE_OBJECT_TYPE AcceptedType, bool (*Callback)(FEObject*, void**), void** UserData, const std::string ToolTipText) +DragAndDropTarget::DragAndDropTarget(const FE_OBJECT_TYPE AcceptedType, std::function Callback, void** UserData, const std::string ToolTipText) { AcceptedTypes.push_back(AcceptedType); this->Callback = Callback; @@ -196,7 +195,7 @@ DragAndDropTarget::DragAndDropTarget(const FE_OBJECT_TYPE AcceptedType, bool (*C ToolTipTexts.push_back(ToolTipText); } -DragAndDropTarget::DragAndDropTarget(std::vector& AcceptedTypes, bool (*Callback)(FEObject*, void**), void** UserData, std::vector& ToolTipTexts) +DragAndDropTarget::DragAndDropTarget(std::vector& AcceptedTypes, std::function Callback, void** UserData, std::vector& ToolTipTexts) { this->AcceptedTypes = AcceptedTypes; this->Callback = Callback; diff --git a/FEEditorDragAndDropManager.h b/FEEditorDragAndDropManager.h index 28b48d2..d5bcd81 100644 --- a/FEEditorDragAndDropManager.h +++ b/FEEditorDragAndDropManager.h @@ -1,24 +1,25 @@ #pragma once #include "../FEngine.h" +#include using namespace FocalEngine; -class DragAndDropManager; +#define EDITOR_RESOURCE_TAG "EDITOR_PRIVATE_RESOURCE" class DragAndDropTarget { - friend DragAndDropManager; + friend class DragAndDropManager; private: std::vector AcceptedTypes; std::vector ToolTipTexts; - bool (*Callback)(FEObject*, void**); + std::function Callback; + void** UserData = nullptr; bool bActive = false; public: DragAndDropTarget(); - DragAndDropTarget(FE_OBJECT_TYPE AcceptedType, bool (*Callback)(FEObject*, void**), void** UserData = nullptr, std::string ToolTipText = ""); - DragAndDropTarget(std::vector& AcceptedTypes, bool (*Callback)(FEObject*, void**), void** UserData, std::vector& ToolTipTexts); - + DragAndDropTarget(FE_OBJECT_TYPE AcceptedType, std::function Callback, void** UserData = nullptr, std::string ToolTipText = ""); + DragAndDropTarget(std::vector& AcceptedTypes, std::function Callback, void** UserData, std::vector& ToolTipTexts); ~DragAndDropTarget(); void SetActive(bool Active); @@ -40,15 +41,15 @@ class DragAndDropManager SINGLETON_PUBLIC_PART(DragAndDropManager) void InitializeResources(); - DragAndDropTarget* AddTarget(FE_OBJECT_TYPE AcceptedType, bool (*Callback)(FEObject*, void**), void** UserData = nullptr, std::string ToolTipText = ""); - DragAndDropTarget* AddTarget(std::vector& AcceptedTypes, bool (*Callback)(FEObject*, void**), void** UserData, std::vector& ToolTipTexts); + DragAndDropTarget* AddTarget(FE_OBJECT_TYPE AcceptedType, std::function Callback, void** UserData = nullptr, std::string ToolTipText = ""); + DragAndDropTarget* AddTarget(std::vector& AcceptedTypes, std::function Callback, void** UserData, std::vector& ToolTipTexts); DragAndDropTarget* AddTarget(DragAndDropTarget* NewTarget); void Render() const; void DropAction(); void MouseMove(); - void SetObject(FEObject* Obj, FETexture* Texture = nullptr, ImVec2 UV0 = ImVec2(0.0f, 1.0f), ImVec2 UV1 = ImVec2(0.0f, 1.0f)); + void SetObjectToDrag(FEObject* Object, FETexture* Texture = nullptr, ImVec2 UV0 = ImVec2(0.0f, 1.0f), ImVec2 UV1 = ImVec2(0.0f, 1.0f)); bool ObjectIsDraged() const; FETexture* GetToolTipTexture() const; @@ -71,4 +72,4 @@ class DragAndDropManager bool ObjectCanBeDroped() const; }; -#define DRAG_AND_DROP_MANAGER DragAndDropManager::getInstance() \ No newline at end of file +#define DRAG_AND_DROP_MANAGER DragAndDropManager::GetInstance() \ No newline at end of file diff --git a/FEEditorGizmoManager.cpp b/FEEditorGizmoManager.cpp index a2b2bfd..0c40fd1 100644 --- a/FEEditorGizmoManager.cpp +++ b/FEEditorGizmoManager.cpp @@ -1,278 +1,243 @@ #include "FEEditorGizmoManager.h" using namespace FocalEngine; -//using namespace GizmoManager; +#include "FEEditor.h" -GizmoManager* GizmoManager::Instance = nullptr; GizmoManager::GizmoManager() {} GizmoManager::~GizmoManager() {} void GizmoManager::InitializeResources() { - SELECTED.SetOnUpdateFunc(OnSelectedObjectUpdate); + SELECTED.SetOnUpdateFunction(OnSelectedObjectUpdate); FEMesh* TransformationGizmoMesh = RESOURCE_MANAGER.LoadFEMesh((RESOURCE_MANAGER.GetDefaultResourcesFolder() + "45191B6F172E3B531978692E.model").c_str(), "transformationGizmoMesh"); - RESOURCE_MANAGER.MakeMeshStandard(TransformationGizmoMesh); + RESOURCE_MANAGER.SetTag(TransformationGizmoMesh, EDITOR_RESOURCE_TAG); - // transformationXGizmo + // TransformationXGizmo FEMaterial* CurrentMaterial = RESOURCE_MANAGER.CreateMaterial("transformationXGizmoMaterial"); CurrentMaterial->SetAlbedoMap(RESOURCE_MANAGER.NoTexture); CurrentMaterial->Shader = RESOURCE_MANAGER.GetShader("6917497A5E0C05454876186F"/*"FESolidColorShader"*/); - CurrentMaterial->AddParameter(FEShaderParam(glm::vec3(0.9f, 0.1f, 0.1f), "baseColor")); - RESOURCE_MANAGER.MakeMaterialStandard(CurrentMaterial); - TransformationXGizmoEntity = SCENE.AddEntity(new FEGameModel(TransformationGizmoMesh, CurrentMaterial, "TransformationXGizmoGM"), "transformationXGizmoEntity"); - RESOURCE_MANAGER.MakePrefabStandard(TransformationXGizmoEntity->Prefab); - RESOURCE_MANAGER.MakeGameModelStandard(TransformationXGizmoEntity->Prefab->GetComponent(0)->GameModel); - TransformationXGizmoEntity->SetCastShadows(false); - TransformationXGizmoEntity->Transform.SetScale(glm::vec3(GizmosScale)); - TransformationXGizmoEntity->Transform.SetRotation(glm::vec3(0.0f, 0.0f, -90.0f)); - TransformationXGizmoEntity->SetIsPostprocessApplied(false); - - // transformationYGizmo + CurrentMaterial->SetBaseColor(glm::vec3(0.9f, 0.1f, 0.1f)); + RESOURCE_MANAGER.SetTag(CurrentMaterial, EDITOR_RESOURCE_TAG); + + TransformationXGizmoGM = RESOURCE_MANAGER.CreateGameModel(TransformationGizmoMesh, CurrentMaterial, "TransformationXGizmoGM"); + RESOURCE_MANAGER.SetTag(TransformationXGizmoGM, EDITOR_RESOURCE_TAG); + + // TransformationYGizmo CurrentMaterial = RESOURCE_MANAGER.CreateMaterial("transformationYGizmoMaterial"); CurrentMaterial->SetAlbedoMap(RESOURCE_MANAGER.NoTexture); CurrentMaterial->Shader = RESOURCE_MANAGER.GetShader("6917497A5E0C05454876186F"/*"FESolidColorShader"*/); - CurrentMaterial->AddParameter(FEShaderParam(glm::vec3(0.1f, 0.9f, 0.1f), "baseColor")); - RESOURCE_MANAGER.MakeMaterialStandard(CurrentMaterial); - TransformationYGizmoEntity = SCENE.AddEntity(new FEGameModel(TransformationGizmoMesh, CurrentMaterial, "TransformationYGizmoGM"), "transformationYGizmoEntity"); - RESOURCE_MANAGER.MakePrefabStandard(TransformationYGizmoEntity->Prefab); - RESOURCE_MANAGER.MakeGameModelStandard(TransformationYGizmoEntity->Prefab->GetComponent(0)->GameModel); - TransformationYGizmoEntity->SetCastShadows(false); - TransformationYGizmoEntity->Transform.SetScale(glm::vec3(GizmosScale)); - TransformationYGizmoEntity->Transform.SetRotation(glm::vec3(0.0f)); - TransformationYGizmoEntity->SetIsPostprocessApplied(false); - - // transformationZGizmo + CurrentMaterial->SetBaseColor(glm::vec3(0.1f, 0.9f, 0.1f)); + RESOURCE_MANAGER.SetTag(CurrentMaterial, EDITOR_RESOURCE_TAG); + + TransformationYGizmoGM = RESOURCE_MANAGER.CreateGameModel(TransformationGizmoMesh, CurrentMaterial, "TransformationYGizmoGM"); + RESOURCE_MANAGER.SetTag(TransformationYGizmoGM, EDITOR_RESOURCE_TAG); + + // TransformationZGizmo CurrentMaterial = RESOURCE_MANAGER.CreateMaterial("transformationZGizmoMaterial"); CurrentMaterial->SetAlbedoMap(RESOURCE_MANAGER.NoTexture); CurrentMaterial->Shader = RESOURCE_MANAGER.GetShader("6917497A5E0C05454876186F"/*"FESolidColorShader"*/); - CurrentMaterial->AddParameter(FEShaderParam(glm::vec3(0.1f, 0.1f, 0.9f), "baseColor")); - RESOURCE_MANAGER.MakeMaterialStandard(CurrentMaterial); - TransformationZGizmoEntity = SCENE.AddEntity(new FEGameModel(TransformationGizmoMesh, CurrentMaterial, "TransformationZGizmoGM"), "transformationZGizmoEntity"); - RESOURCE_MANAGER.MakePrefabStandard(TransformationZGizmoEntity->Prefab); - RESOURCE_MANAGER.MakeGameModelStandard(TransformationZGizmoEntity->Prefab->GetComponent(0)->GameModel); - TransformationZGizmoEntity->SetCastShadows(false); - TransformationZGizmoEntity->Transform.SetScale(glm::vec3(GizmosScale)); - TransformationZGizmoEntity->Transform.SetRotation(glm::vec3(90.0f, 0.0f, 90.0f)); - TransformationZGizmoEntity->SetIsPostprocessApplied(false); - - // plane gizmos + CurrentMaterial->SetBaseColor(glm::vec3(0.1f, 0.1f, 0.9f)); + RESOURCE_MANAGER.SetTag(CurrentMaterial, EDITOR_RESOURCE_TAG); + + TransformationZGizmoGM = RESOURCE_MANAGER.CreateGameModel(TransformationGizmoMesh, CurrentMaterial, "TransformationZGizmoGM"); + RESOURCE_MANAGER.SetTag(TransformationZGizmoGM, EDITOR_RESOURCE_TAG); + + // Plane gizmos CurrentMaterial = RESOURCE_MANAGER.CreateMaterial("transformationXYGizmoMaterial"); CurrentMaterial->SetAlbedoMap(RESOURCE_MANAGER.NoTexture); CurrentMaterial->Shader = RESOURCE_MANAGER.GetShader("6917497A5E0C05454876186F"/*"FESolidColorShader"*/); - CurrentMaterial->AddParameter(FEShaderParam(glm::vec3(1.0f, 1.0f, 1.0f), "baseColor")); - RESOURCE_MANAGER.MakeMaterialStandard(CurrentMaterial); - TransformationXyGizmoEntity = SCENE.AddEntity(new FEGameModel(RESOURCE_MANAGER.GetMesh("84251E6E0D0801363579317R"/*"cube"*/), CurrentMaterial, "TransformationXYGizmoGM"), "transformationXYGizmoEntity"); - RESOURCE_MANAGER.MakePrefabStandard(TransformationXyGizmoEntity->Prefab); - RESOURCE_MANAGER.MakeGameModelStandard(TransformationXyGizmoEntity->Prefab->GetComponent(0)->GameModel); - TransformationXyGizmoEntity->SetCastShadows(false); - TransformationXyGizmoEntity->Transform.SetScale(glm::vec3(GizmosScale, GizmosScale, GizmosScale * 0.02f)); - TransformationXyGizmoEntity->Transform.SetRotation(glm::vec3(0.0f, 0.0f, -90.0f)); - TransformationXyGizmoEntity->SetIsPostprocessApplied(false); + CurrentMaterial->SetBaseColor(glm::vec3(1.0f, 1.0f, 1.0f)); + RESOURCE_MANAGER.SetTag(CurrentMaterial, EDITOR_RESOURCE_TAG); + + TransformationXYGizmoGM = RESOURCE_MANAGER.CreateGameModel(RESOURCE_MANAGER.GetMesh("84251E6E0D0801363579317R"/*"cube"*/), CurrentMaterial, "TransformationXYGizmoGM"); + RESOURCE_MANAGER.SetTag(TransformationXYGizmoGM, EDITOR_RESOURCE_TAG); CurrentMaterial = RESOURCE_MANAGER.CreateMaterial("transformationYZGizmoMaterial"); CurrentMaterial->SetAlbedoMap(RESOURCE_MANAGER.NoTexture); CurrentMaterial->Shader = RESOURCE_MANAGER.GetShader("6917497A5E0C05454876186F"/*"FESolidColorShader"*/); - CurrentMaterial->AddParameter(FEShaderParam(glm::vec3(1.0f, 1.0f, 1.0f), "baseColor")); - RESOURCE_MANAGER.MakeMaterialStandard(CurrentMaterial); - TransformationYzGizmoEntity = SCENE.AddEntity(new FEGameModel(RESOURCE_MANAGER.GetMesh("84251E6E0D0801363579317R"/*"cube"*/), CurrentMaterial, "TransformationYZGizmoGM"), "transformationYZGizmoEntity"); - RESOURCE_MANAGER.MakePrefabStandard(TransformationYzGizmoEntity->Prefab); - RESOURCE_MANAGER.MakeGameModelStandard(TransformationYzGizmoEntity->Prefab->GetComponent(0)->GameModel); - TransformationYzGizmoEntity->SetCastShadows(false); - TransformationYzGizmoEntity->Transform.SetScale(glm::vec3(GizmosScale * 0.02f, GizmosScale, GizmosScale)); - TransformationYzGizmoEntity->Transform.SetRotation(glm::vec3(0.0f, 0.0f, 0.0f)); - TransformationYzGizmoEntity->SetIsPostprocessApplied(false); + CurrentMaterial->SetBaseColor(glm::vec3(1.0f, 1.0f, 1.0f)); + RESOURCE_MANAGER.SetTag(CurrentMaterial, EDITOR_RESOURCE_TAG); + + TransformationYZGizmoGM = RESOURCE_MANAGER.CreateGameModel(RESOURCE_MANAGER.GetMesh("84251E6E0D0801363579317R"/*"cube"*/), CurrentMaterial, "TransformationYZGizmoGM"); + RESOURCE_MANAGER.SetTag(TransformationYZGizmoGM, EDITOR_RESOURCE_TAG); CurrentMaterial = RESOURCE_MANAGER.CreateMaterial("transformationXZGizmoMaterial"); CurrentMaterial->SetAlbedoMap(RESOURCE_MANAGER.NoTexture); CurrentMaterial->Shader = RESOURCE_MANAGER.GetShader("6917497A5E0C05454876186F"/*"FESolidColorShader"*/); - CurrentMaterial->AddParameter(FEShaderParam(glm::vec3(1.0f, 1.0f, 1.0f), "baseColor")); - RESOURCE_MANAGER.MakeMaterialStandard(CurrentMaterial); - TransformationXzGizmoEntity = SCENE.AddEntity(new FEGameModel(RESOURCE_MANAGER.GetMesh("84251E6E0D0801363579317R"/*"cube"*/), CurrentMaterial, "TransformationXZGizmoGM"), "transformationXZGizmoEntity"); - RESOURCE_MANAGER.MakePrefabStandard(TransformationXzGizmoEntity->Prefab); - RESOURCE_MANAGER.MakeGameModelStandard(TransformationXzGizmoEntity->Prefab->GetComponent(0)->GameModel); - TransformationXzGizmoEntity->SetCastShadows(false); - TransformationXzGizmoEntity->Transform.SetScale(glm::vec3(GizmosScale, GizmosScale * 0.02f, GizmosScale)); - TransformationXzGizmoEntity->Transform.SetRotation(glm::vec3(0.0f, 0.0f, 0.0f)); - TransformationXzGizmoEntity->SetIsPostprocessApplied(false); - - // scale gizmos + CurrentMaterial->SetBaseColor(glm::vec3(1.0f, 1.0f, 1.0f)); + RESOURCE_MANAGER.SetTag(CurrentMaterial, EDITOR_RESOURCE_TAG); + + TransformationXZGizmoGM = RESOURCE_MANAGER.CreateGameModel(RESOURCE_MANAGER.GetMesh("84251E6E0D0801363579317R"/*"cube"*/), CurrentMaterial, "TransformationXZGizmoGM"); + RESOURCE_MANAGER.SetTag(TransformationXZGizmoGM, EDITOR_RESOURCE_TAG); + + // Scale gizmos. FEMesh* ScaleGizmoMesh = RESOURCE_MANAGER.LoadFEMesh((RESOURCE_MANAGER.GetDefaultResourcesFolder() + "637C784B2E5E5C6548190E1B.model").c_str(), "scaleGizmoMesh"); - RESOURCE_MANAGER.MakeMeshStandard(ScaleGizmoMesh); + RESOURCE_MANAGER.SetTag(ScaleGizmoMesh, EDITOR_RESOURCE_TAG); - // scaleXGizmo + // ScaleXGizmo CurrentMaterial = RESOURCE_MANAGER.CreateMaterial("scaleXGizmoMaterial"); CurrentMaterial->SetAlbedoMap(RESOURCE_MANAGER.NoTexture); CurrentMaterial->Shader = RESOURCE_MANAGER.GetShader("6917497A5E0C05454876186F"/*"FESolidColorShader"*/); - CurrentMaterial->AddParameter(FEShaderParam(glm::vec3(0.9f, 0.1f, 0.1f), "baseColor")); - RESOURCE_MANAGER.MakeMaterialStandard(CurrentMaterial); - ScaleXGizmoEntity = SCENE.AddEntity(new FEGameModel(ScaleGizmoMesh, CurrentMaterial, "scaleXGizmoGM"), "scaleXGizmoEntity"); - RESOURCE_MANAGER.MakePrefabStandard(ScaleXGizmoEntity->Prefab); - RESOURCE_MANAGER.MakeGameModelStandard(ScaleXGizmoEntity->Prefab->GetComponent(0)->GameModel); - ScaleXGizmoEntity->SetCastShadows(false); - ScaleXGizmoEntity->Transform.SetScale(glm::vec3(GizmosScale)); - ScaleXGizmoEntity->Transform.SetRotation(glm::vec3(0.0f, 0.0f, -90.0f)); - ScaleXGizmoEntity->SetIsPostprocessApplied(false); - - // scaleYGizmo + CurrentMaterial->SetBaseColor(glm::vec3(0.9f, 0.1f, 0.1f)); + RESOURCE_MANAGER.SetTag(CurrentMaterial, EDITOR_RESOURCE_TAG); + + ScaleXGizmoGM = RESOURCE_MANAGER.CreateGameModel(ScaleGizmoMesh, CurrentMaterial, "ScaleXGizmoGM"); + RESOURCE_MANAGER.SetTag(ScaleXGizmoGM, EDITOR_RESOURCE_TAG); + + // ScaleYGizmo CurrentMaterial = RESOURCE_MANAGER.CreateMaterial("scaleYGizmoMaterial"); CurrentMaterial->SetAlbedoMap(RESOURCE_MANAGER.NoTexture); CurrentMaterial->Shader = RESOURCE_MANAGER.GetShader("6917497A5E0C05454876186F"/*"FESolidColorShader"*/); - CurrentMaterial->AddParameter(FEShaderParam(glm::vec3(0.1f, 0.9f, 0.1f), "baseColor")); - RESOURCE_MANAGER.MakeMaterialStandard(CurrentMaterial); - ScaleYGizmoEntity = SCENE.AddEntity(new FEGameModel(ScaleGizmoMesh, CurrentMaterial, "scaleYGizmoGM"), "scaleYGizmoEntity"); - RESOURCE_MANAGER.MakePrefabStandard(ScaleYGizmoEntity->Prefab); - RESOURCE_MANAGER.MakeGameModelStandard(ScaleYGizmoEntity->Prefab->GetComponent(0)->GameModel); - ScaleYGizmoEntity->SetCastShadows(false); - ScaleYGizmoEntity->Transform.SetScale(glm::vec3(GizmosScale)); - ScaleYGizmoEntity->Transform.SetRotation(glm::vec3(0.0f)); - ScaleYGizmoEntity->SetIsPostprocessApplied(false); - - // scaleZGizmo + CurrentMaterial->SetBaseColor(glm::vec3(0.1f, 0.9f, 0.1f)); + RESOURCE_MANAGER.SetTag(CurrentMaterial, EDITOR_RESOURCE_TAG); + + ScaleYGizmoGM = RESOURCE_MANAGER.CreateGameModel(ScaleGizmoMesh, CurrentMaterial, "ScaleYGizmoGM"); + RESOURCE_MANAGER.SetTag(ScaleYGizmoGM, EDITOR_RESOURCE_TAG); + + // ScaleZGizmo CurrentMaterial = RESOURCE_MANAGER.CreateMaterial("scaleZGizmoMaterial"); CurrentMaterial->SetAlbedoMap(RESOURCE_MANAGER.NoTexture); CurrentMaterial->Shader = RESOURCE_MANAGER.GetShader("6917497A5E0C05454876186F"/*"FESolidColorShader"*/); - CurrentMaterial->AddParameter(FEShaderParam(glm::vec3(0.1f, 0.1f, 0.9f), "baseColor")); - RESOURCE_MANAGER.MakeMaterialStandard(CurrentMaterial); - ScaleZGizmoEntity = SCENE.AddEntity(new FEGameModel(ScaleGizmoMesh, CurrentMaterial, "scaleZGizmoGM"), "scaleZGizmoEntity"); - RESOURCE_MANAGER.MakePrefabStandard(ScaleZGizmoEntity->Prefab); - RESOURCE_MANAGER.MakeGameModelStandard(ScaleZGizmoEntity->Prefab->GetComponent(0)->GameModel); - ScaleZGizmoEntity->SetCastShadows(false); - ScaleZGizmoEntity->Transform.SetScale(glm::vec3(GizmosScale)); - ScaleZGizmoEntity->Transform.SetRotation(glm::vec3(90.0f, 0.0f, 90.0f)); - ScaleZGizmoEntity->SetIsPostprocessApplied(false); - - // rotate gizmos + CurrentMaterial->SetBaseColor(glm::vec3(0.1f, 0.1f, 0.9f)); + RESOURCE_MANAGER.SetTag(CurrentMaterial, EDITOR_RESOURCE_TAG); + + ScaleZGizmoGM = RESOURCE_MANAGER.CreateGameModel(ScaleGizmoMesh, CurrentMaterial, "ScaleZGizmoGM"); + RESOURCE_MANAGER.SetTag(ScaleZGizmoGM, EDITOR_RESOURCE_TAG); + + // RotateAroundAxis gizmos FEMesh* RotateGizmoMesh = RESOURCE_MANAGER.LoadFEMesh((RESOURCE_MANAGER.GetDefaultResourcesFolder() + "19622421516E5B317E1B5360.model").c_str(), "rotateGizmoMesh"); - RESOURCE_MANAGER.MakeMeshStandard(RotateGizmoMesh); + RESOURCE_MANAGER.SetTag(RotateGizmoMesh, EDITOR_RESOURCE_TAG); - // rotateXGizmo + // RotateXGizmo CurrentMaterial = RESOURCE_MANAGER.CreateMaterial("rotateXGizmoMaterial"); CurrentMaterial->SetAlbedoMap(RESOURCE_MANAGER.NoTexture); CurrentMaterial->Shader = RESOURCE_MANAGER.GetShader("6917497A5E0C05454876186F"/*"FESolidColorShader"*/); - CurrentMaterial->AddParameter(FEShaderParam(glm::vec3(0.9f, 0.1f, 0.1f), "baseColor")); - RESOURCE_MANAGER.MakeMaterialStandard(CurrentMaterial); - RotateXGizmoEntity = SCENE.AddEntity(new FEGameModel(RotateGizmoMesh, CurrentMaterial, "rotateXGizmoGM"), "rotateXGizmoEntity"); - RESOURCE_MANAGER.MakePrefabStandard(RotateXGizmoEntity->Prefab); - RESOURCE_MANAGER.MakeGameModelStandard(RotateXGizmoEntity->Prefab->GetComponent(0)->GameModel); - RotateXGizmoEntity->SetCastShadows(false); - RotateXGizmoEntity->Transform.SetScale(glm::vec3(GizmosScale * 2.0f)); - RotateXGizmoEntity->Transform.SetRotation(RotateXStandardRotation); - RotateXGizmoEntity->SetIsPostprocessApplied(false); - - // rotateYGizmo + CurrentMaterial->SetBaseColor(glm::vec3(0.9f, 0.1f, 0.1f)); + RESOURCE_MANAGER.SetTag(CurrentMaterial, EDITOR_RESOURCE_TAG); + + RotateXGizmoGM = RESOURCE_MANAGER.CreateGameModel(RotateGizmoMesh, CurrentMaterial, "RotateXGizmoGM"); + RESOURCE_MANAGER.SetTag(RotateXGizmoGM, EDITOR_RESOURCE_TAG); + + // RotateYGizmo CurrentMaterial = RESOURCE_MANAGER.CreateMaterial("rotateYGizmoMaterial"); CurrentMaterial->SetAlbedoMap(RESOURCE_MANAGER.NoTexture); CurrentMaterial->Shader = RESOURCE_MANAGER.GetShader("6917497A5E0C05454876186F"/*"FESolidColorShader"*/); - CurrentMaterial->AddParameter(FEShaderParam(glm::vec3(0.1f, 0.9f, 0.1f), "baseColor")); - RESOURCE_MANAGER.MakeMaterialStandard(CurrentMaterial); - RotateYGizmoEntity = SCENE.AddEntity(new FEGameModel(RotateGizmoMesh, CurrentMaterial, "rotateYGizmoGM"), "rotateYGizmoEntity"); - RESOURCE_MANAGER.MakePrefabStandard(RotateYGizmoEntity->Prefab); - RESOURCE_MANAGER.MakeGameModelStandard(RotateYGizmoEntity->Prefab->GetComponent(0)->GameModel); - RotateYGizmoEntity->SetCastShadows(false); - RotateYGizmoEntity->Transform.SetScale(glm::vec3(GizmosScale * 2.0f)); - RotateYGizmoEntity->Transform.SetRotation(RotateYStandardRotation); - RotateYGizmoEntity->SetIsPostprocessApplied(false); - - // rotateZGizmo + CurrentMaterial->SetBaseColor(glm::vec3(0.1f, 0.9f, 0.1f)); + RESOURCE_MANAGER.SetTag(CurrentMaterial, EDITOR_RESOURCE_TAG); + + RotateYGizmoGM = RESOURCE_MANAGER.CreateGameModel(RotateGizmoMesh, CurrentMaterial, "RotateYGizmoGM"); + RESOURCE_MANAGER.SetTag(RotateYGizmoGM, EDITOR_RESOURCE_TAG); + + // RotateZGizmo CurrentMaterial = RESOURCE_MANAGER.CreateMaterial("rotateZGizmoMaterial"); CurrentMaterial->SetAlbedoMap(RESOURCE_MANAGER.NoTexture); CurrentMaterial->Shader = RESOURCE_MANAGER.GetShader("6917497A5E0C05454876186F"/*"FESolidColorShader"*/); - CurrentMaterial->AddParameter(FEShaderParam(glm::vec3(0.1f, 0.1f, 0.9f), "baseColor")); - RESOURCE_MANAGER.MakeMaterialStandard(CurrentMaterial); - RotateZGizmoEntity = SCENE.AddEntity(new FEGameModel(RotateGizmoMesh, CurrentMaterial, "rotateZGizmoGM"), "rotateZGizmoEntity"); - RESOURCE_MANAGER.MakePrefabStandard(RotateZGizmoEntity->Prefab); - RESOURCE_MANAGER.MakeGameModelStandard(RotateZGizmoEntity->Prefab->GetComponent(0)->GameModel); - RotateZGizmoEntity->SetCastShadows(false); - RotateZGizmoEntity->Transform.SetScale(glm::vec3(GizmosScale * 2.0f)); - RotateZGizmoEntity->Transform.SetRotation(RotateZStandardRotation); - RotateZGizmoEntity->SetIsPostprocessApplied(false); + CurrentMaterial->SetBaseColor(glm::vec3(0.1f, 0.1f, 0.9f)); + RESOURCE_MANAGER.SetTag(CurrentMaterial, EDITOR_RESOURCE_TAG); + + RotateZGizmoGM = RESOURCE_MANAGER.CreateGameModel(RotateGizmoMesh, CurrentMaterial, "RotateZGizmoGM"); + RESOURCE_MANAGER.SetTag(RotateZGizmoGM, EDITOR_RESOURCE_TAG); TransformationGizmoIcon = RESOURCE_MANAGER.LoadFETexture((RESOURCE_MANAGER.GetDefaultResourcesFolder() + "456A31026A1C3152181A6064.texture").c_str(), "transformationGizmoIcon"); - RESOURCE_MANAGER.MakeTextureStandard(TransformationGizmoIcon); + RESOURCE_MANAGER.SetTag(TransformationGizmoIcon, EDITOR_RESOURCE_TAG); ScaleGizmoIcon = RESOURCE_MANAGER.LoadFETexture((RESOURCE_MANAGER.GetDefaultResourcesFolder() + "3F2118296C1E4533506A472E.texture").c_str(), "scaleGizmoIcon"); - RESOURCE_MANAGER.MakeTextureStandard(ScaleGizmoIcon); + RESOURCE_MANAGER.SetTag(ScaleGizmoIcon, EDITOR_RESOURCE_TAG); RotateGizmoIcon = RESOURCE_MANAGER.LoadFETexture((RESOURCE_MANAGER.GetDefaultResourcesFolder() + "7F6057403249580D73311B54.texture").c_str(), "rotateGizmoIcon"); - RESOURCE_MANAGER.MakeTextureStandard(RotateGizmoIcon); + RESOURCE_MANAGER.SetTag(RotateGizmoIcon, EDITOR_RESOURCE_TAG); } -void GizmoManager::HideAllGizmo() +void GizmoManager::HideAllGizmo(FEScene* Scene) { - TransformationXGizmoEntity->SetVisibility(false); - TransformationYGizmoEntity->SetVisibility(false); - TransformationZGizmoEntity->SetVisibility(false); + if (Scene == nullptr) + return; + + FEGizmoSceneData* GizmoSceneData = GIZMO_MANAGER.GetSceneData(Scene->GetObjectID()); + if (GizmoSceneData == nullptr) + return; + + GizmoSceneData->TransformationXGizmoEntity->GetComponent().SetVisibility(false); + GizmoSceneData->TransformationYGizmoEntity->GetComponent().SetVisibility(false); + GizmoSceneData->TransformationZGizmoEntity->GetComponent().SetVisibility(false); - TransformationXyGizmoEntity->SetVisibility(false); - TransformationYzGizmoEntity->SetVisibility(false); - TransformationXzGizmoEntity->SetVisibility(false); + GizmoSceneData->TransformationXYGizmoEntity->GetComponent().SetVisibility(false); + GizmoSceneData->TransformationYZGizmoEntity->GetComponent().SetVisibility(false); + GizmoSceneData->TransformationXZGizmoEntity->GetComponent().SetVisibility(false); - bTransformationXGizmoActive = false; - bTransformationYGizmoActive = false; - bTransformationZGizmoActive = false; + GizmoSceneData->bTransformationXGizmoActive = false; + GizmoSceneData->bTransformationYGizmoActive = false; + GizmoSceneData->bTransformationZGizmoActive = false; - bTransformationXYGizmoActive = false; - bTransformationYZGizmoActive = false; - bTransformationXZGizmoActive = false; + GizmoSceneData->bTransformationXYGizmoActive = false; + GizmoSceneData->bTransformationYZGizmoActive = false; + GizmoSceneData->bTransformationXZGizmoActive = false; - ScaleXGizmoEntity->SetVisibility(false); - ScaleYGizmoEntity->SetVisibility(false); - ScaleZGizmoEntity->SetVisibility(false); + GizmoSceneData->ScaleXGizmoEntity->GetComponent().SetVisibility(false); + GizmoSceneData->ScaleYGizmoEntity->GetComponent().SetVisibility(false); + GizmoSceneData->ScaleZGizmoEntity->GetComponent().SetVisibility(false); - bScaleXGizmoActive = false; - bScaleYGizmoActive = false; - bScaleZGizmoActive = false; + GizmoSceneData->bScaleXGizmoActive = false; + GizmoSceneData->bScaleYGizmoActive = false; + GizmoSceneData->bScaleZGizmoActive = false; - RotateXGizmoEntity->SetVisibility(false); - RotateYGizmoEntity->SetVisibility(false); - RotateZGizmoEntity->SetVisibility(false); + GizmoSceneData->RotateXGizmoEntity->GetComponent().SetVisibility(false); + GizmoSceneData->RotateYGizmoEntity->GetComponent().SetVisibility(false); + GizmoSceneData->RotateZGizmoEntity->GetComponent().SetVisibility(false); - bRotateXGizmoActive = false; - bRotateYGizmoActive = false; - bRotateZGizmoActive = false; + GizmoSceneData->bRotateXGizmoActive = false; + GizmoSceneData->bRotateYGizmoActive = false; + GizmoSceneData->bRotateZGizmoActive = false; } -void GizmoManager::UpdateGizmoState(int NewState) +void GizmoManager::UpdateGizmoState(int NewState, FEScene* Scene) { - if (SELECTED.GetTerrain() != nullptr) + if (Scene == nullptr) + return; + + FEGizmoSceneData* GizmoSceneData = GetSceneData(Scene->GetObjectID()); + if (GizmoSceneData == nullptr) + return; + + if (SELECTED.GetSelected(Scene) != nullptr && SELECTED.GetSelected(Scene)->HasComponent()) { - if (SELECTED.GetTerrain()->GetBrushMode() != FE_TERRAIN_BRUSH_NONE) + if (TERRAIN_SYSTEM.GetBrushMode() != FE_TERRAIN_BRUSH_NONE) return; } if (NewState < 0 || NewState > 2) NewState = 0; - GizmosState = NewState; - HideAllGizmo(); + GizmoSceneData->GizmosState = NewState; + HideAllGizmo(Scene); - if (SELECTED.GetSelected() == nullptr || SELECTED.GetSelected()->GetType() == FE_CAMERA) + if (SELECTED.GetSelected(Scene) == nullptr) return; switch (NewState) { case TRANSFORM_GIZMOS: { - TransformationXGizmoEntity->SetVisibility(true); - TransformationYGizmoEntity->SetVisibility(true); - TransformationZGizmoEntity->SetVisibility(true); + GizmoSceneData->TransformationXGizmoEntity->GetComponent().SetVisibility(true); + GizmoSceneData->TransformationYGizmoEntity->GetComponent().SetVisibility(true); + GizmoSceneData->TransformationZGizmoEntity->GetComponent().SetVisibility(true); - TransformationXyGizmoEntity->SetVisibility(true); - TransformationYzGizmoEntity->SetVisibility(true); - TransformationXzGizmoEntity->SetVisibility(true); + GizmoSceneData->TransformationXYGizmoEntity->GetComponent().SetVisibility(true); + GizmoSceneData->TransformationYZGizmoEntity->GetComponent().SetVisibility(true); + GizmoSceneData->TransformationXZGizmoEntity->GetComponent().SetVisibility(true); break; } case SCALE_GIZMOS: { - ScaleXGizmoEntity->SetVisibility(true); - ScaleYGizmoEntity->SetVisibility(true); - ScaleZGizmoEntity->SetVisibility(true); + GizmoSceneData->ScaleXGizmoEntity->GetComponent().SetVisibility(true); + GizmoSceneData->ScaleYGizmoEntity->GetComponent().SetVisibility(true); + GizmoSceneData->ScaleZGizmoEntity->GetComponent().SetVisibility(true); break; } case ROTATE_GIZMOS: { - RotateXGizmoEntity->SetVisibility(true); - RotateYGizmoEntity->SetVisibility(true); - RotateZGizmoEntity->SetVisibility(true); + GizmoSceneData->RotateXGizmoEntity->GetComponent().SetVisibility(true); + GizmoSceneData->RotateYGizmoEntity->GetComponent().SetVisibility(true); + GizmoSceneData->RotateZGizmoEntity->GetComponent().SetVisibility(true); break; } @@ -281,238 +246,241 @@ void GizmoManager::UpdateGizmoState(int NewState) } } -void GizmoManager::DeactivateAllGizmo() +void GizmoManager::DeactivateAllGizmo(FEScene* Scene) { - bTransformationXGizmoActive = false; - bTransformationYGizmoActive = false; - bTransformationZGizmoActive = false; + if (Scene == nullptr) + return; - bTransformationXYGizmoActive = false; - bTransformationYZGizmoActive = false; - bTransformationXZGizmoActive = false; + FEGizmoSceneData* GizmoSceneData = GetSceneData(Scene->GetObjectID()); + if (GizmoSceneData == nullptr) + return; + + GizmoSceneData->bTransformationXGizmoActive = false; + GizmoSceneData->bTransformationYGizmoActive = false; + GizmoSceneData->bTransformationZGizmoActive = false; + + GizmoSceneData->bTransformationXYGizmoActive = false; + GizmoSceneData->bTransformationYZGizmoActive = false; + GizmoSceneData->bTransformationXZGizmoActive = false; - bScaleXGizmoActive = false; - bScaleYGizmoActive = false; - bScaleZGizmoActive = false; + GizmoSceneData->bScaleXGizmoActive = false; + GizmoSceneData->bScaleYGizmoActive = false; + GizmoSceneData->bScaleZGizmoActive = false; - bRotateXGizmoActive = false; - bRotateYGizmoActive = false; - bRotateZGizmoActive = false; + GizmoSceneData->bRotateXGizmoActive = false; + GizmoSceneData->bRotateYGizmoActive = false; + GizmoSceneData->bRotateZGizmoActive = false; } -void GizmoManager::Render() +void GizmoManager::Update() { - if (SELECTED.GetSelected() == nullptr || SELECTED.GetSelected()->GetType() == FE_CAMERA) + auto PerSceneIterator = PerSceneData.begin(); + while (PerSceneIterator != PerSceneData.end()) { - HideAllGizmo(); - return; - } - - FETransformComponent ObjTransform = GetTransformComponentOfSelectedObject(); - const glm::vec3 ObjectSpaceOriginInWorldSpace = glm::vec3(ObjTransform.GetTransformMatrix() * glm::vec4(0.0f, 0.0f, 0.0f, 1.0f)); - glm::vec3 ToObject = ObjectSpaceOriginInWorldSpace - ENGINE.GetCamera()->GetPosition(); - ToObject = glm::normalize(ToObject); - - // This will center gizmos in AABB center, but it will produce bug while moving object under some circumstances. - /*if (SELECTED.getEntity() != nullptr && SELECTED.getEntity()->getType() == FE_ENTITY_INSTANCED && SELECTED.instancedSubObjectIndexSelected == -1) - { - FEAABB AABB = SELECTED.getEntity()->getAABB(); - glm::vec3 center = AABB.getMin() + ((AABB.getMax() - AABB.getMin()) / 2.0f); - toObject = glm::normalize(center - ENGINE.getCamera()->getPosition()); - }*/ - - if (GIZMO_MANAGER.GizmosState == TRANSFORM_GIZMOS) - { - GIZMO_MANAGER.TransformationXGizmoEntity->Transform.SetPosition((ENGINE.GetCamera()->GetPosition() + ToObject * 0.15f)); - GIZMO_MANAGER.TransformationYGizmoEntity->Transform.SetPosition((ENGINE.GetCamera()->GetPosition() + ToObject * 0.15f)); - GIZMO_MANAGER.TransformationZGizmoEntity->Transform.SetPosition((ENGINE.GetCamera()->GetPosition() + ToObject * 0.15f)); - - glm::vec3 NewP = ENGINE.GetCamera()->GetPosition() + ToObject * 0.15f; - NewP.x += 0.005f; - NewP.y += 0.005f; - GIZMO_MANAGER.TransformationXyGizmoEntity->Transform.SetPosition(NewP); - NewP = ENGINE.GetCamera()->GetPosition() + ToObject * 0.15f; - NewP.z += 0.005f; - NewP.y += 0.005f; - GIZMO_MANAGER.TransformationYzGizmoEntity->Transform.SetPosition(NewP); - NewP = ENGINE.GetCamera()->GetPosition() + ToObject * 0.15f; - NewP.x += 0.005f; - NewP.z += 0.005f; - GIZMO_MANAGER.TransformationXzGizmoEntity->Transform.SetPosition(NewP); - - // X Gizmos - GIZMO_MANAGER.TransformationXGizmoEntity->Prefab->GetComponent(0)->GameModel->Material->SetBaseColor(glm::vec3(0.9f, 0.1f, 0.1f)); - if (GIZMO_MANAGER.bTransformationXZGizmoActive || GIZMO_MANAGER.bTransformationXYGizmoActive || GIZMO_MANAGER.bTransformationXGizmoActive) - GIZMO_MANAGER.TransformationXGizmoEntity->Prefab->GetComponent(0)->GameModel->Material->SetBaseColor(glm::vec3(1.5f, 1.5f, 0.2f)); - - // Y Gizmos - GIZMO_MANAGER.TransformationYGizmoEntity->Prefab->GetComponent(0)->GameModel->Material->SetBaseColor(glm::vec3(0.1f, 0.9f, 0.1f)); - if (GIZMO_MANAGER.bTransformationYZGizmoActive || GIZMO_MANAGER.bTransformationXYGizmoActive || GIZMO_MANAGER.bTransformationYGizmoActive) - GIZMO_MANAGER.TransformationYGizmoEntity->Prefab->GetComponent(0)->GameModel->Material->SetBaseColor(glm::vec3(1.5f, 1.5f, 0.2f)); - - // Z Gizmos - GIZMO_MANAGER.TransformationZGizmoEntity->Prefab->GetComponent(0)->GameModel->Material->SetBaseColor(glm::vec3(0.1f, 0.1f, 0.9f)); - if (GIZMO_MANAGER.bTransformationYZGizmoActive || GIZMO_MANAGER.bTransformationXZGizmoActive || GIZMO_MANAGER.bTransformationZGizmoActive) - GIZMO_MANAGER.TransformationZGizmoEntity->Prefab->GetComponent(0)->GameModel->Material->SetBaseColor(glm::vec3(1.5f, 1.5f, 0.2f)); - - // XY Gizmos - GIZMO_MANAGER.TransformationXyGizmoEntity->Prefab->GetComponent(0)->GameModel->Material->SetBaseColor(glm::vec3(1.0f, 1.0f, 1.0f)); - if (GIZMO_MANAGER.bTransformationXYGizmoActive) - GIZMO_MANAGER.TransformationXyGizmoEntity->Prefab->GetComponent(0)->GameModel->Material->SetBaseColor(glm::vec3(1.5f, 1.5f, 0.2f)); - - // YZ Gizmos - GIZMO_MANAGER.TransformationYzGizmoEntity->Prefab->GetComponent(0)->GameModel->Material->SetBaseColor(glm::vec3(1.0f, 1.0f, 1.0f)); - if (GIZMO_MANAGER.bTransformationYZGizmoActive) - GIZMO_MANAGER.TransformationYzGizmoEntity->Prefab->GetComponent(0)->GameModel->Material->SetBaseColor(glm::vec3(1.5f, 1.5f, 0.2f)); - - // XZ Gizmos - GIZMO_MANAGER.TransformationXzGizmoEntity->Prefab->GetComponent(0)->GameModel->Material->SetBaseColor(glm::vec3(1.0f, 1.0f, 1.0f)); - if (GIZMO_MANAGER.bTransformationXZGizmoActive) - GIZMO_MANAGER.TransformationXzGizmoEntity->Prefab->GetComponent(0)->GameModel->Material->SetBaseColor(glm::vec3(1.5f, 1.5f, 0.2f)); - } - else if (GIZMO_MANAGER.GizmosState == SCALE_GIZMOS) - { - GIZMO_MANAGER.ScaleXGizmoEntity->Transform.SetPosition((ENGINE.GetCamera()->GetPosition() + ToObject * 0.15f)); - GIZMO_MANAGER.ScaleYGizmoEntity->Transform.SetPosition((ENGINE.GetCamera()->GetPosition() + ToObject * 0.15f)); - GIZMO_MANAGER.ScaleZGizmoEntity->Transform.SetPosition((ENGINE.GetCamera()->GetPosition() + ToObject * 0.15f)); - - // X Gizmos - GIZMO_MANAGER.ScaleXGizmoEntity->Prefab->GetComponent(0)->GameModel->Material->SetBaseColor(glm::vec3(0.9f, 0.1f, 0.1f)); - if (GIZMO_MANAGER.bScaleXGizmoActive) - GIZMO_MANAGER.ScaleXGizmoEntity->Prefab->GetComponent(0)->GameModel->Material->SetBaseColor(glm::vec3(1.5f, 1.5f, 0.2f)); - - // Y Gizmos - GIZMO_MANAGER.ScaleYGizmoEntity->Prefab->GetComponent(0)->GameModel->Material->SetBaseColor(glm::vec3(0.1f, 0.9f, 0.1f)); - if (GIZMO_MANAGER.bScaleYGizmoActive) - GIZMO_MANAGER.ScaleYGizmoEntity->Prefab->GetComponent(0)->GameModel->Material->SetBaseColor(glm::vec3(1.5f, 1.5f, 0.2f)); - - // Z Gizmos - GIZMO_MANAGER.ScaleZGizmoEntity->Prefab->GetComponent(0)->GameModel->Material->SetBaseColor(glm::vec3(0.1f, 0.1f, 0.9f)); - if (GIZMO_MANAGER.bScaleZGizmoActive) - GIZMO_MANAGER.ScaleZGizmoEntity->Prefab->GetComponent(0)->GameModel->Material->SetBaseColor(glm::vec3(1.5f, 1.5f, 0.2f)); - } - else if (GIZMO_MANAGER.GizmosState == ROTATE_GIZMOS) - { - GIZMO_MANAGER.RotateXGizmoEntity->Transform.SetPosition((ENGINE.GetCamera()->GetPosition() + ToObject * 0.15f)); - GIZMO_MANAGER.RotateYGizmoEntity->Transform.SetPosition((ENGINE.GetCamera()->GetPosition() + ToObject * 0.15f)); - GIZMO_MANAGER.RotateZGizmoEntity->Transform.SetPosition((ENGINE.GetCamera()->GetPosition() + ToObject * 0.15f)); - - if (SELECTED.SELECTED.GetSelected() != nullptr) + if (SCENE_MANAGER.GetScene(PerSceneIterator->first) == nullptr) { - GIZMO_MANAGER.RotateXGizmoEntity->SetVisibility(true); - GIZMO_MANAGER.RotateYGizmoEntity->SetVisibility(true); - GIZMO_MANAGER.RotateZGizmoEntity->SetVisibility(true); + PerSceneIterator = PerSceneData.erase(PerSceneIterator); + continue; } - // X Gizmos - GIZMO_MANAGER.RotateXGizmoEntity->Prefab->GetComponent(0)->GameModel->Material->SetBaseColor(glm::vec3(0.9f, 0.1f, 0.1f)); - if (GIZMO_MANAGER.bRotateXGizmoActive) + FEGizmoSceneData* GizmoSceneData = PerSceneIterator->second; + if (GizmoSceneData == nullptr) { - GIZMO_MANAGER.RotateXGizmoEntity->Prefab->GetComponent(0)->GameModel->Material->SetBaseColor(glm::vec3(1.5f, 1.5f, 0.2f)); - GIZMO_MANAGER.RotateYGizmoEntity->SetVisibility(false); - GIZMO_MANAGER.RotateZGizmoEntity->SetVisibility(false); + PerSceneIterator++; + continue; } - - // Y Gizmos - GIZMO_MANAGER.RotateYGizmoEntity->Prefab->GetComponent(0)->GameModel->Material->SetBaseColor(glm::vec3(0.1f, 0.9f, 0.1f)); - if (GIZMO_MANAGER.bRotateYGizmoActive) + + FEScene* Scene = SCENE_MANAGER.GetScene(GizmoSceneData->SceneID); + if (SELECTED.GetSelected(Scene) == nullptr || CAMERA_SYSTEM.GetMainCamera(Scene) == nullptr) { - GIZMO_MANAGER.RotateYGizmoEntity->Prefab->GetComponent(0)->GameModel->Material->SetBaseColor(glm::vec3(1.5f, 1.5f, 0.2f)); - GIZMO_MANAGER.RotateXGizmoEntity->SetVisibility(false); - GIZMO_MANAGER.RotateZGizmoEntity->SetVisibility(false); + HideAllGizmo(Scene); + PerSceneIterator++; + continue; } - // Z Gizmos - GIZMO_MANAGER.RotateZGizmoEntity->Prefab->GetComponent(0)->GameModel->Material->SetBaseColor(glm::vec3(0.1f, 0.1f, 0.9f)); - if (GIZMO_MANAGER.bRotateZGizmoActive) + FETransformComponent& CameraTransformComponent = CAMERA_SYSTEM.GetMainCamera(Scene)->GetComponent(); + FETransformComponent& ObjTransform = GetTransformComponentOfSelectedObject(Scene); + const glm::vec3 ObjectSpaceOriginInWorldSpace = glm::vec3(ObjTransform.GetWorldMatrix() * glm::vec4(0.0f, 0.0f, 0.0f, 1.0f)); + glm::vec3 ToObject = ObjectSpaceOriginInWorldSpace - CameraTransformComponent.GetPosition(FE_WORLD_SPACE); + ToObject = glm::normalize(ToObject); + + GizmoSceneData->ParentGizmoEntity->GetComponent().SetPosition((CameraTransformComponent.GetPosition(FE_WORLD_SPACE) + ToObject * 0.15f)); + if (GizmoSceneData->GizmosState == TRANSFORM_GIZMOS) + { + // X Gizmos + GizmoSceneData->TransformationXGizmoEntity->GetComponent().GetGameModel()->Material->SetBaseColor(glm::vec3(0.9f, 0.1f, 0.1f)); + if (GizmoSceneData->bTransformationXZGizmoActive || GizmoSceneData->bTransformationXYGizmoActive || GizmoSceneData->bTransformationXGizmoActive) + GizmoSceneData->TransformationXGizmoEntity->GetComponent().GetGameModel()->Material->SetBaseColor(glm::vec3(1.5f, 1.5f, 0.2f)); + + // Y Gizmos + GizmoSceneData->TransformationYGizmoEntity->GetComponent().GetGameModel()->Material->SetBaseColor(glm::vec3(0.1f, 0.9f, 0.1f)); + if (GizmoSceneData->bTransformationYZGizmoActive || GizmoSceneData->bTransformationXYGizmoActive || GizmoSceneData->bTransformationYGizmoActive) + GizmoSceneData->TransformationYGizmoEntity->GetComponent().GetGameModel()->Material->SetBaseColor(glm::vec3(1.5f, 1.5f, 0.2f)); + + // Z Gizmos + GizmoSceneData->TransformationZGizmoEntity->GetComponent().GetGameModel()->Material->SetBaseColor(glm::vec3(0.1f, 0.1f, 0.9f)); + if (GizmoSceneData->bTransformationYZGizmoActive || GizmoSceneData->bTransformationXZGizmoActive || GizmoSceneData->bTransformationZGizmoActive) + GizmoSceneData->TransformationZGizmoEntity->GetComponent().GetGameModel()->Material->SetBaseColor(glm::vec3(1.5f, 1.5f, 0.2f)); + + // XY Gizmos + GizmoSceneData->TransformationXYGizmoEntity->GetComponent().GetGameModel()->Material->SetBaseColor(glm::vec3(1.0f, 1.0f, 1.0f)); + if (GizmoSceneData->bTransformationXYGizmoActive) + GizmoSceneData->TransformationXYGizmoEntity->GetComponent().GetGameModel()->Material->SetBaseColor(glm::vec3(1.5f, 1.5f, 0.2f)); + + // YZ Gizmos + GizmoSceneData->TransformationYZGizmoEntity->GetComponent().GetGameModel()->Material->SetBaseColor(glm::vec3(1.0f, 1.0f, 1.0f)); + if (GizmoSceneData->bTransformationYZGizmoActive) + GizmoSceneData->TransformationYZGizmoEntity->GetComponent().GetGameModel()->Material->SetBaseColor(glm::vec3(1.5f, 1.5f, 0.2f)); + + // XZ Gizmos + GizmoSceneData->TransformationXZGizmoEntity->GetComponent().GetGameModel()->Material->SetBaseColor(glm::vec3(1.0f, 1.0f, 1.0f)); + if (GizmoSceneData->bTransformationXZGizmoActive) + GizmoSceneData->TransformationXZGizmoEntity->GetComponent().GetGameModel()->Material->SetBaseColor(glm::vec3(1.5f, 1.5f, 0.2f)); + } + else if (GizmoSceneData->GizmosState == SCALE_GIZMOS) { - GIZMO_MANAGER.RotateZGizmoEntity->Prefab->GetComponent(0)->GameModel->Material->SetBaseColor(glm::vec3(1.5f, 1.5f, 0.2f)); - GIZMO_MANAGER.RotateXGizmoEntity->SetVisibility(false); - GIZMO_MANAGER.RotateYGizmoEntity->SetVisibility(false); + // X Gizmos + GizmoSceneData->ScaleXGizmoEntity->GetComponent().GetGameModel()->Material->SetBaseColor(glm::vec3(0.9f, 0.1f, 0.1f)); + if (GizmoSceneData->bScaleXGizmoActive) + GizmoSceneData->ScaleXGizmoEntity->GetComponent().GetGameModel()->Material->SetBaseColor(glm::vec3(1.5f, 1.5f, 0.2f)); + + // Y Gizmos + GizmoSceneData->ScaleYGizmoEntity->GetComponent().GetGameModel()->Material->SetBaseColor(glm::vec3(0.1f, 0.9f, 0.1f)); + if (GizmoSceneData->bScaleYGizmoActive) + GizmoSceneData->ScaleYGizmoEntity->GetComponent().GetGameModel()->Material->SetBaseColor(glm::vec3(1.5f, 1.5f, 0.2f)); + + // Z Gizmos + GizmoSceneData->ScaleZGizmoEntity->GetComponent().GetGameModel()->Material->SetBaseColor(glm::vec3(0.1f, 0.1f, 0.9f)); + if (GizmoSceneData->bScaleZGizmoActive) + GizmoSceneData->ScaleZGizmoEntity->GetComponent().GetGameModel()->Material->SetBaseColor(glm::vec3(1.5f, 1.5f, 0.2f)); } + else if (GizmoSceneData->GizmosState == ROTATE_GIZMOS) + { + if (SELECTED.SELECTED.GetSelected(Scene) != nullptr) + { + GizmoSceneData->RotateXGizmoEntity->GetComponent().SetVisibility(true); + GizmoSceneData->RotateYGizmoEntity->GetComponent().SetVisibility(true); + GizmoSceneData->RotateZGizmoEntity->GetComponent().SetVisibility(true); + } + + // X Gizmos + GizmoSceneData->RotateXGizmoEntity->GetComponent().GetGameModel()->Material->SetBaseColor(glm::vec3(0.9f, 0.1f, 0.1f)); + if (GizmoSceneData->bRotateXGizmoActive) + { + GizmoSceneData->RotateXGizmoEntity->GetComponent().GetGameModel()->Material->SetBaseColor(glm::vec3(1.5f, 1.5f, 0.2f)); + GizmoSceneData->RotateYGizmoEntity->GetComponent().SetVisibility(false); + GizmoSceneData->RotateZGizmoEntity->GetComponent().SetVisibility(false); + } + + // Y Gizmos + GizmoSceneData->RotateYGizmoEntity->GetComponent().GetGameModel()->Material->SetBaseColor(glm::vec3(0.1f, 0.9f, 0.1f)); + if (GizmoSceneData->bRotateYGizmoActive) + { + GizmoSceneData->RotateYGizmoEntity->GetComponent().GetGameModel()->Material->SetBaseColor(glm::vec3(1.5f, 1.5f, 0.2f)); + GizmoSceneData->RotateXGizmoEntity->GetComponent().SetVisibility(false); + GizmoSceneData->RotateZGizmoEntity->GetComponent().SetVisibility(false); + } + + // Z Gizmos + GizmoSceneData->RotateZGizmoEntity->GetComponent().GetGameModel()->Material->SetBaseColor(glm::vec3(0.1f, 0.1f, 0.9f)); + if (GizmoSceneData->bRotateZGizmoActive) + { + GizmoSceneData->RotateZGizmoEntity->GetComponent().GetGameModel()->Material->SetBaseColor(glm::vec3(1.5f, 1.5f, 0.2f)); + GizmoSceneData->RotateXGizmoEntity->GetComponent().SetVisibility(false); + GizmoSceneData->RotateYGizmoEntity->GetComponent().SetVisibility(false); + } + } + + PerSceneIterator++; } } -bool GizmoManager::WasSelected(int Index) +bool GizmoManager::WasSelected(int Index, FEScene* Scene) { - DeactivateAllGizmo(); + if (Scene == nullptr) + return false; - if (SELECTED.ObjectsUnderMouse[Index]->GetType() == FE_CAMERA) - return true; + FEGizmoSceneData* GizmoSceneData = GIZMO_MANAGER.GetSceneData(Scene->GetObjectID()); + if (GizmoSceneData == nullptr) + return false; + + DeactivateAllGizmo(Scene); - FEEntity* SelectedEntity = nullptr; - if (SELECTED.ObjectsUnderMouse[Index]->GetType() == FE_ENTITY) - SelectedEntity = SCENE.GetEntity(SELECTED.ObjectsUnderMouse[Index]->GetObjectID()); + FESelectionData* CurrentSelectionData = SELECTED.GetSceneData(Scene->GetObjectID()); + if (CurrentSelectionData == nullptr) + return false; - const int EntityNameHash = SelectedEntity == nullptr ? -1 : SelectedEntity->GetNameHash(); - if (GizmosState == TRANSFORM_GIZMOS && EntityNameHash == TransformationXGizmoEntity->GetNameHash()) + FEEntity* SelectedEntity = CurrentSelectionData->SceneEntitiesUnderMouse[Index]; + FETransformComponent& CurrentTransform = SelectedEntity->GetComponent(); + + if (GizmoSceneData->GizmosState == TRANSFORM_GIZMOS && SelectedEntity->GetObjectID() == GizmoSceneData->TransformationXGizmoEntity->GetObjectID()) { - bTransformationXGizmoActive = true; + GizmoSceneData->bTransformationXGizmoActive = true; } - else if (GizmosState == TRANSFORM_GIZMOS && EntityNameHash == TransformationYGizmoEntity->GetNameHash()) + else if (GizmoSceneData->GizmosState == TRANSFORM_GIZMOS && SelectedEntity->GetObjectID() == GizmoSceneData->TransformationYGizmoEntity->GetObjectID()) { - bTransformationYGizmoActive = true; + GizmoSceneData->bTransformationYGizmoActive = true; } - else if (GizmosState == TRANSFORM_GIZMOS && EntityNameHash == TransformationZGizmoEntity->GetNameHash()) + else if (GizmoSceneData->GizmosState == TRANSFORM_GIZMOS && SelectedEntity->GetObjectID() == GizmoSceneData->TransformationZGizmoEntity->GetObjectID()) { - bTransformationZGizmoActive = true; + GizmoSceneData->bTransformationZGizmoActive = true; } - else if (GizmosState == TRANSFORM_GIZMOS && EntityNameHash == TransformationXyGizmoEntity->GetNameHash()) + else if (GizmoSceneData->GizmosState == TRANSFORM_GIZMOS && SelectedEntity->GetObjectID() == GizmoSceneData->TransformationXYGizmoEntity->GetObjectID()) { - bTransformationXYGizmoActive = true; + GizmoSceneData->bTransformationXYGizmoActive = true; } - else if (GizmosState == TRANSFORM_GIZMOS && EntityNameHash == TransformationYzGizmoEntity->GetNameHash()) + else if (GizmoSceneData->GizmosState == TRANSFORM_GIZMOS && SelectedEntity->GetObjectID() == GizmoSceneData->TransformationYZGizmoEntity->GetObjectID()) { - bTransformationYZGizmoActive = true; + GizmoSceneData->bTransformationYZGizmoActive = true; } - else if (GizmosState == TRANSFORM_GIZMOS && EntityNameHash == TransformationXzGizmoEntity->GetNameHash()) + else if (GizmoSceneData->GizmosState == TRANSFORM_GIZMOS && SelectedEntity->GetObjectID() == GizmoSceneData->TransformationXZGizmoEntity->GetObjectID()) { - bTransformationXZGizmoActive = true; + GizmoSceneData->bTransformationXZGizmoActive = true; } - else if (GizmosState == SCALE_GIZMOS && EntityNameHash == ScaleXGizmoEntity->GetNameHash()) + else if (GizmoSceneData->GizmosState == SCALE_GIZMOS && SelectedEntity->GetObjectID() == GizmoSceneData->ScaleXGizmoEntity->GetObjectID()) { - if (SelectedEntity != nullptr && SelectedEntity->Transform.IsUniformScalingSet()) + if (SelectedEntity != nullptr && CurrentTransform.IsUniformScalingSet()) { - bScaleXGizmoActive = true; - bScaleYGizmoActive = true; - bScaleZGizmoActive = true; + GizmoSceneData->bScaleXGizmoActive = true; + GizmoSceneData->bScaleYGizmoActive = true; + GizmoSceneData->bScaleZGizmoActive = true; } - bScaleXGizmoActive = true; + GizmoSceneData->bScaleXGizmoActive = true; } - else if (GizmosState == SCALE_GIZMOS && EntityNameHash == ScaleYGizmoEntity->GetNameHash()) + else if (GizmoSceneData->GizmosState == SCALE_GIZMOS && SelectedEntity->GetObjectID() == GizmoSceneData->ScaleYGizmoEntity->GetObjectID()) { - if (SelectedEntity != nullptr && SelectedEntity->Transform.IsUniformScalingSet()) + if (SelectedEntity != nullptr && CurrentTransform.IsUniformScalingSet()) { - bScaleXGizmoActive = true; - bScaleYGizmoActive = true; - bScaleZGizmoActive = true; + GizmoSceneData->bScaleXGizmoActive = true; + GizmoSceneData->bScaleYGizmoActive = true; + GizmoSceneData->bScaleZGizmoActive = true; } - bScaleYGizmoActive = true; + GizmoSceneData->bScaleYGizmoActive = true; } - else if (GizmosState == SCALE_GIZMOS && EntityNameHash == ScaleZGizmoEntity->GetNameHash()) + else if (GizmoSceneData->GizmosState == SCALE_GIZMOS && SelectedEntity->GetObjectID() == GizmoSceneData->ScaleZGizmoEntity->GetObjectID()) { - if (SelectedEntity != nullptr && SelectedEntity->Transform.IsUniformScalingSet()) + if (SelectedEntity != nullptr && CurrentTransform.IsUniformScalingSet()) { - bScaleXGizmoActive = true; - bScaleYGizmoActive = true; - bScaleZGizmoActive = true; + GizmoSceneData->bScaleXGizmoActive = true; + GizmoSceneData->bScaleYGizmoActive = true; + GizmoSceneData->bScaleZGizmoActive = true; } - bScaleZGizmoActive = true; + GizmoSceneData->bScaleZGizmoActive = true; } - else if (GizmosState == ROTATE_GIZMOS && EntityNameHash == RotateXGizmoEntity->GetNameHash()) + else if (GizmoSceneData->GizmosState == ROTATE_GIZMOS && SelectedEntity->GetObjectID() == GizmoSceneData->RotateXGizmoEntity->GetObjectID()) { - bRotateXGizmoActive = true; + GizmoSceneData->bRotateXGizmoActive = true; } - else if (GizmosState == ROTATE_GIZMOS && EntityNameHash == RotateYGizmoEntity->GetNameHash()) + else if (GizmoSceneData->GizmosState == ROTATE_GIZMOS && SelectedEntity->GetObjectID() == GizmoSceneData->RotateYGizmoEntity->GetObjectID()) { - bRotateYGizmoActive = true; + GizmoSceneData->bRotateYGizmoActive = true; } - else if (GizmosState == ROTATE_GIZMOS && EntityNameHash == RotateZGizmoEntity->GetNameHash()) + else if (GizmoSceneData->GizmosState == ROTATE_GIZMOS && SelectedEntity->GetObjectID() == GizmoSceneData->RotateZGizmoEntity->GetObjectID()) { - bRotateZGizmoActive = true; + GizmoSceneData->bRotateZGizmoActive = true; } else { @@ -522,21 +490,38 @@ bool GizmoManager::WasSelected(int Index) return true; } -glm::vec3 GizmoManager::GetMousePositionDifferenceOnPlane(glm::vec3 PlaneNormal) +glm::vec3 GizmoManager::GetMousePositionDifferenceOnPlane(glm::vec3 PlaneNormal, FEScene* Scene) { - FETransformComponent ObjTransform = GetTransformComponentOfSelectedObject(); - const glm::vec3 EntitySpaceOriginInWorldSpace = glm::vec3(ObjTransform.GetTransformMatrix() * glm::vec4(0.0f, 0.0f, 0.0f, 1.0f)); + if (Scene == nullptr) + return glm::vec3(); + + FEGizmoSceneData* GizmoSceneData = GIZMO_MANAGER.GetSceneData(Scene->GetObjectID()); + if (GizmoSceneData == nullptr) + return glm::vec3(); - const glm::vec3 LastMouseRayVector = SELECTED.MouseRay(LastMouseX, LastMouseY); + FETransformComponent& CameraTransformComponent = CAMERA_SYSTEM.GetMainCamera(Scene)->GetComponent(); + FECameraComponent& CameraComponent = CAMERA_SYSTEM.GetMainCamera(Scene)->GetComponent(); + FEViewport* CurrentViewport = CAMERA_SYSTEM.GetMainCameraViewport(Scene); + glm::ivec2 ViewportPosition = glm::ivec2(CurrentViewport->GetX(), CurrentViewport->GetY()); + glm::ivec2 ViewportSize = glm::ivec2(CurrentViewport->GetWidth(), CurrentViewport->GetHeight()); - const glm::vec3 MouseRayVector = SELECTED.MouseRay(MouseX, MouseY); - const glm::vec3 CameraPosition = ENGINE.GetCamera()->GetPosition(); + FETransformComponent& ObjTransform = GetTransformComponentOfSelectedObject(Scene); + const glm::vec3 EntitySpaceOriginInWorldSpace = glm::vec3(ObjTransform.GetWorldMatrix() * glm::vec4(0.0f, 0.0f, 0.0f, 1.0f)); + + const glm::vec3 LastFrameMouseRay = GEOMETRY.CreateMouseRayToWorld(LastMouseX, LastMouseY, + CameraComponent.GetViewMatrix(), CameraComponent.GetProjectionMatrix(), + ViewportPosition, ViewportSize); + const glm::vec3 MouseRay = GEOMETRY.CreateMouseRayToWorld(MouseX, MouseY, + CameraComponent.GetViewMatrix(), CameraComponent.GetProjectionMatrix(), + ViewportPosition, ViewportSize); + + const glm::vec3 CameraPosition = CameraTransformComponent.GetPosition(FE_WORLD_SPACE); const float SignedDistanceToOrigin = glm::dot(PlaneNormal, EntitySpaceOriginInWorldSpace); const float Nominator = SignedDistanceToOrigin - glm::dot(CameraPosition, PlaneNormal); - const float LastDenominator = glm::dot(LastMouseRayVector, PlaneNormal); - const float Denominator = glm::dot(MouseRayVector, PlaneNormal); + const float LastDenominator = glm::dot(LastFrameMouseRay, PlaneNormal); + const float Denominator = glm::dot(MouseRay, PlaneNormal); if (Denominator == 0 || LastDenominator == 0) return glm::vec3(0.0f); @@ -544,27 +529,44 @@ glm::vec3 GizmoManager::GetMousePositionDifferenceOnPlane(glm::vec3 PlaneNormal) const float LastIntersectionT = Nominator / LastDenominator; const float IntersectionT = Nominator / Denominator; - const glm::vec3 LastPointOnPlane = CameraPosition + LastIntersectionT * LastMouseRayVector; - const glm::vec3 PointOnPlane = CameraPosition + IntersectionT * MouseRayVector; + const glm::vec3 LastPointOnPlane = CameraPosition + LastIntersectionT * LastFrameMouseRay; + const glm::vec3 PointOnPlane = CameraPosition + IntersectionT * MouseRay; return PointOnPlane - LastPointOnPlane; } -glm::vec3 GizmoManager::GetMousePositionDifferenceOnPlane(glm::vec3 PlaneNormal, glm::vec3& LastMousePointOnPlane) +glm::vec3 GizmoManager::GetMousePositionDifferenceOnPlane(glm::vec3 PlaneNormal, glm::vec3& LastMousePointOnPlane, FEScene* Scene) { - FETransformComponent ObjTransform = GetTransformComponentOfSelectedObject(); - const glm::vec3 EntitySpaceOriginInWorldSpace = glm::vec3(ObjTransform.GetTransformMatrix() * glm::vec4(0.0f, 0.0f, 0.0f, 1.0f)); + if (Scene == nullptr) + return glm::vec3(); + + FEGizmoSceneData* GizmoSceneData = GIZMO_MANAGER.GetSceneData(Scene->GetObjectID()); + if (GizmoSceneData == nullptr) + return glm::vec3(); + + FETransformComponent& CameraTransformComponent = CAMERA_SYSTEM.GetMainCamera(Scene)->GetComponent(); + FECameraComponent& CameraComponent = CAMERA_SYSTEM.GetMainCamera(Scene)->GetComponent(); + FEViewport* CurrentViewport = CAMERA_SYSTEM.GetMainCameraViewport(Scene); + glm::ivec2 ViewportPosition = glm::ivec2(CurrentViewport->GetX(), CurrentViewport->GetY()); + glm::ivec2 ViewportSize = glm::ivec2(CurrentViewport->GetWidth(), CurrentViewport->GetHeight()); + + FETransformComponent& ObjTransform = GetTransformComponentOfSelectedObject(Scene); + const glm::vec3 EntitySpaceOriginInWorldSpace = glm::vec3(ObjTransform.GetWorldMatrix() * glm::vec4(0.0f, 0.0f, 0.0f, 1.0f)); - const glm::vec3 LastMouseRayVector = SELECTED.MouseRay(LastMouseX, LastMouseY); + const glm::vec3 LastFrameMouseRay = GEOMETRY.CreateMouseRayToWorld(LastMouseX, LastMouseY, + CameraComponent.GetViewMatrix(), CameraComponent.GetProjectionMatrix(), + ViewportPosition, ViewportSize); + const glm::vec3 MouseRay = GEOMETRY.CreateMouseRayToWorld(MouseX, MouseY, + CameraComponent.GetViewMatrix(), CameraComponent.GetProjectionMatrix(), + ViewportPosition, ViewportSize); - const glm::vec3 MouseRayVector = SELECTED.MouseRay(MouseX, MouseY); - const glm::vec3 CameraPosition = ENGINE.GetCamera()->GetPosition(); + const glm::vec3 CameraPosition = CameraTransformComponent.GetPosition(FE_WORLD_SPACE); const float SignedDistanceToOrigin = glm::dot(PlaneNormal, EntitySpaceOriginInWorldSpace); const float Nominator = SignedDistanceToOrigin - glm::dot(CameraPosition, PlaneNormal); - const float LastDenominator = glm::dot(LastMouseRayVector, PlaneNormal); - const float Denominator = glm::dot(MouseRayVector, PlaneNormal); + const float LastDenominator = glm::dot(LastFrameMouseRay, PlaneNormal); + const float Denominator = glm::dot(MouseRay, PlaneNormal); if (Denominator == 0 || LastDenominator == 0) return glm::vec3(0.0f); @@ -572,422 +574,541 @@ glm::vec3 GizmoManager::GetMousePositionDifferenceOnPlane(glm::vec3 PlaneNormal, const float LastIntersectionT = Nominator / LastDenominator; const float IntersectionT = Nominator / Denominator; - const glm::vec3 LastPointOnPlane = CameraPosition + LastIntersectionT * LastMouseRayVector; - const glm::vec3 PointOnPlane = CameraPosition + IntersectionT * MouseRayVector; + const glm::vec3 LastPointOnPlane = CameraPosition + LastIntersectionT * LastFrameMouseRay; + const glm::vec3 PointOnPlane = CameraPosition + IntersectionT * MouseRay; LastMousePointOnPlane = LastPointOnPlane; return PointOnPlane; } -bool GizmoManager::RaysIntersection(const glm::vec3& FRayOrigin, const glm::vec3& FRayDirection, - const glm::vec3& SRayOrigin, const glm::vec3& SRayDirection, - float& Ft, float& St) const +void GizmoManager::MouseMoveTransformationGizmos(FEScene* Scene) { - const glm::vec3 DirectionsCross = glm::cross(FRayDirection, SRayDirection); - // two rays are parallel - if (DirectionsCross == glm::vec3(0.0f)) - return false; + if (Scene == nullptr) + return; - Ft = glm::dot(glm::cross((SRayOrigin - FRayOrigin), SRayDirection), DirectionsCross); - Ft /= glm::length(DirectionsCross) * glm::length(DirectionsCross); + FEGizmoSceneData* GizmoSceneData = GIZMO_MANAGER.GetSceneData(Scene->GetObjectID()); + if (GizmoSceneData == nullptr) + return; - St = glm::dot(glm::cross((SRayOrigin - FRayOrigin), FRayDirection), DirectionsCross); - St /= glm::length(DirectionsCross) * glm::length(DirectionsCross); + if (CAMERA_SYSTEM.GetMainCamera(Scene) == nullptr) + return; - return true; -} + FETransformComponent& CameraTransformComponent = CAMERA_SYSTEM.GetMainCamera(Scene)->GetComponent(); + FECameraComponent& CameraComponent = CAMERA_SYSTEM.GetMainCamera(Scene)->GetComponent(); + FEViewport* CurrentViewport = CAMERA_SYSTEM.GetMainCameraViewport(Scene); + glm::ivec2 ViewportPosition = glm::ivec2(CurrentViewport->GetX(), CurrentViewport->GetY()); + glm::ivec2 ViewportSize = glm::ivec2(CurrentViewport->GetWidth(), CurrentViewport->GetHeight()); -void GizmoManager::MouseMoveTransformationGizmos() -{ - FETransformComponent ObjTransform = GetTransformComponentOfSelectedObject(); + FETransformComponent& ObjTransform = GetTransformComponentOfSelectedObject(Scene); + + const glm::vec3 LastFrameMouseRay = GEOMETRY.CreateMouseRayToWorld(LastMouseX, LastMouseY, + CameraComponent.GetViewMatrix(), CameraComponent.GetProjectionMatrix(), + ViewportPosition, ViewportSize); + const glm::vec3 MouseRay = GEOMETRY.CreateMouseRayToWorld(MouseX, MouseY, + CameraComponent.GetViewMatrix(), CameraComponent.GetProjectionMatrix(), + ViewportPosition, ViewportSize); - float Ft = 0.0f; - float St = 0.0f; + float MouseRayParametricIntersection = 0.0f; + float GizmoRayParametricIntersection = 0.0f; - float LastFt = 0.0f; - float LastSt = 0.0f; + float LastFrameMouseRayParametricIntersection = 0.0f; + float LastFrameGizmoRayParametricIntersection = 0.0f; - if (GIZMO_MANAGER.bTransformationXGizmoActive) + bool bAppliedSomeChanges = false; + + if (GizmoSceneData->bTransformationXGizmoActive) { - const glm::vec3 LastMouseRayVector = SELECTED.MouseRay(LastMouseX, LastMouseY); - RaysIntersection(ENGINE.GetCamera()->GetPosition(), LastMouseRayVector, - glm::vec3(ObjTransform.GetTransformMatrix() * glm::vec4(0.0f, 0.0f, 0.0f, 1.0f)), glm::vec3(1.0f, 0.0f, 0.0f), - LastFt, LastSt); + GEOMETRY.RaysIntersection(CameraTransformComponent.GetPosition(FE_WORLD_SPACE), LastFrameMouseRay, + glm::vec3(ObjTransform.GetWorldMatrix() * glm::vec4(0.0f, 0.0f, 0.0f, 1.0f)), glm::vec3(1.0f, 0.0f, 0.0f), + LastFrameMouseRayParametricIntersection, LastFrameGizmoRayParametricIntersection); - const glm::vec3 MouseRayVector = SELECTED.MouseRay(MouseX, MouseY); - RaysIntersection(ENGINE.GetCamera()->GetPosition(), MouseRayVector, - glm::vec3(ObjTransform.GetTransformMatrix() * glm::vec4(0.0f, 0.0f, 0.0f, 1.0f)), glm::vec3(1.0f, 0.0f, 0.0f), - Ft, St); + GEOMETRY.RaysIntersection(CameraTransformComponent.GetPosition(FE_WORLD_SPACE), MouseRay, + glm::vec3(ObjTransform.GetWorldMatrix() * glm::vec4(0.0f, 0.0f, 0.0f, 1.0f)), glm::vec3(1.0f, 0.0f, 0.0f), + MouseRayParametricIntersection, GizmoRayParametricIntersection); - const float TDifference = St - LastSt; - glm::vec3 NewPosition = ObjTransform.GetPosition(); - NewPosition.x += TDifference; - ObjTransform.SetPosition(NewPosition); + const float Difference = GizmoRayParametricIntersection - LastFrameGizmoRayParametricIntersection; + if (abs(Difference) > FLT_EPSILON) + { + bAppliedSomeChanges = true; + ObjTransform.SetPosition(ObjTransform.GetPosition(FE_WORLD_SPACE) + glm::vec3(Difference, 0.0f, 0.0f), FE_WORLD_SPACE); + } } - if (GIZMO_MANAGER.bTransformationYGizmoActive) + if (GizmoSceneData->bTransformationYGizmoActive) { - const glm::vec3 LastMouseRayVector = SELECTED.MouseRay(LastMouseX, LastMouseY); - RaysIntersection(ENGINE.GetCamera()->GetPosition(), LastMouseRayVector, - glm::vec3(ObjTransform.GetTransformMatrix() * glm::vec4(0.0f, 0.0f, 0.0f, 1.0f)), glm::vec3(0.0f, 1.0f, 0.0f), - LastFt, LastSt); + GEOMETRY.RaysIntersection(CameraTransformComponent.GetPosition(FE_WORLD_SPACE), LastFrameMouseRay, + glm::vec3(ObjTransform.GetWorldMatrix() * glm::vec4(0.0f, 0.0f, 0.0f, 1.0f)), glm::vec3(0.0f, 1.0f, 0.0f), + LastFrameMouseRayParametricIntersection, LastFrameGizmoRayParametricIntersection); - const glm::vec3 MouseRayVector = SELECTED.MouseRay(MouseX, MouseY); - RaysIntersection(ENGINE.GetCamera()->GetPosition(), MouseRayVector, - glm::vec3(ObjTransform.GetTransformMatrix() * glm::vec4(0.0f, 0.0f, 0.0f, 1.0f)), glm::vec3(0.0f, 1.0f, 0.0f), - Ft, St); + GEOMETRY.RaysIntersection(CameraTransformComponent.GetPosition(FE_WORLD_SPACE), MouseRay, + glm::vec3(ObjTransform.GetWorldMatrix() * glm::vec4(0.0f, 0.0f, 0.0f, 1.0f)), glm::vec3(0.0f, 1.0f, 0.0f), + MouseRayParametricIntersection, GizmoRayParametricIntersection); - const float TDifference = St - LastSt; - glm::vec3 NewPosition = ObjTransform.GetPosition(); - NewPosition.y += TDifference; - ObjTransform.SetPosition(NewPosition); + const float Difference = GizmoRayParametricIntersection - LastFrameGizmoRayParametricIntersection; + if (abs(Difference) > FLT_EPSILON) + { + bAppliedSomeChanges = true; + ObjTransform.SetPosition(ObjTransform.GetPosition(FE_WORLD_SPACE) + glm::vec3(0.0f, Difference, 0.0f), FE_WORLD_SPACE); + } } - if (GIZMO_MANAGER.bTransformationZGizmoActive) + if (GizmoSceneData->bTransformationZGizmoActive) { - const glm::vec3 LastMouseRayVector = SELECTED.MouseRay(LastMouseX, LastMouseY); - RaysIntersection(ENGINE.GetCamera()->GetPosition(), LastMouseRayVector, - glm::vec3(ObjTransform.GetTransformMatrix() * glm::vec4(0.0f, 0.0f, 0.0f, 1.0f)), glm::vec3(0.0f, 0.0f, 1.0f), - LastFt, LastSt); + GEOMETRY.RaysIntersection(CameraTransformComponent.GetPosition(FE_WORLD_SPACE), LastFrameMouseRay, + glm::vec3(ObjTransform.GetWorldMatrix() * glm::vec4(0.0f, 0.0f, 0.0f, 1.0f)), glm::vec3(0.0f, 0.0f, 1.0f), + LastFrameMouseRayParametricIntersection, LastFrameGizmoRayParametricIntersection); - const glm::vec3 MouseRayVector = SELECTED.MouseRay(MouseX, MouseY); - RaysIntersection(ENGINE.GetCamera()->GetPosition(), MouseRayVector, - glm::vec3(ObjTransform.GetTransformMatrix() * glm::vec4(0.0f, 0.0f, 0.0f, 1.0f)), glm::vec3(0.0f, 0.0f, 1.0f), - Ft, St); + GEOMETRY.RaysIntersection(CameraTransformComponent.GetPosition(FE_WORLD_SPACE), MouseRay, + glm::vec3(ObjTransform.GetWorldMatrix() * glm::vec4(0.0f, 0.0f, 0.0f, 1.0f)), glm::vec3(0.0f, 0.0f, 1.0f), + MouseRayParametricIntersection, GizmoRayParametricIntersection); - const float TDifference = St - LastSt; - glm::vec3 NewPosition = ObjTransform.GetPosition(); - NewPosition.z += TDifference; - ObjTransform.SetPosition(NewPosition); + const float Difference = GizmoRayParametricIntersection - LastFrameGizmoRayParametricIntersection; + if (abs(Difference) > FLT_EPSILON) + { + bAppliedSomeChanges = true; + ObjTransform.SetPosition(ObjTransform.GetPosition(FE_WORLD_SPACE) + glm::vec3(0.0f, 0.0f, Difference), FE_WORLD_SPACE); + } } - if (GIZMO_MANAGER.bTransformationXYGizmoActive) + if (GizmoSceneData->bTransformationXYGizmoActive) { - const glm::vec3 Difference = GetMousePositionDifferenceOnPlane(glm::vec3(0.0f, 0.0f, 1.0f)); - glm::vec3 NewPosition = ObjTransform.GetPosition(); - NewPosition.x += Difference.x; - NewPosition.y += Difference.y; - ObjTransform.SetPosition(NewPosition); + const glm::vec3 Difference = GetMousePositionDifferenceOnPlane(glm::vec3(0.0f, 0.0f, 1.0f), Scene); + if (!GEOMETRY.IsEpsilonEqual(Difference, glm::vec3(0.0f))) + { + bAppliedSomeChanges = true; + ObjTransform.SetPosition(ObjTransform.GetPosition(FE_WORLD_SPACE) + Difference, FE_WORLD_SPACE); + } } - if (GIZMO_MANAGER.bTransformationYZGizmoActive) + if (GizmoSceneData->bTransformationYZGizmoActive) { - const glm::vec3 Difference = GetMousePositionDifferenceOnPlane(glm::vec3(1.0f, 0.0f, 0.0f)); - glm::vec3 NewPosition = ObjTransform.GetPosition(); - NewPosition.y += Difference.y; - NewPosition.z += Difference.z; - ObjTransform.SetPosition(NewPosition); + const glm::vec3 Difference = GetMousePositionDifferenceOnPlane(glm::vec3(1.0f, 0.0f, 0.0f), Scene); + if (!GEOMETRY.IsEpsilonEqual(Difference, glm::vec3(0.0f))) + { + bAppliedSomeChanges = true; + ObjTransform.SetPosition(ObjTransform.GetPosition(FE_WORLD_SPACE) + Difference, FE_WORLD_SPACE); + } } - if (GIZMO_MANAGER.bTransformationXZGizmoActive) + if (GizmoSceneData->bTransformationXZGizmoActive) { - const glm::vec3 Difference = GetMousePositionDifferenceOnPlane(glm::vec3(0.0f, 1.0f, 0.0f)); - glm::vec3 NewPosition = ObjTransform.GetPosition(); - NewPosition.x += Difference.x; - NewPosition.z += Difference.z; - ObjTransform.SetPosition(NewPosition); + const glm::vec3 Difference = GetMousePositionDifferenceOnPlane(glm::vec3(0.0f, 1.0f, 0.0f), Scene); + if (!GEOMETRY.IsEpsilonEqual(Difference, glm::vec3(0.0f))) + { + bAppliedSomeChanges = true; + ObjTransform.SetPosition(ObjTransform.GetPosition(FE_WORLD_SPACE) + Difference, FE_WORLD_SPACE); + } } - ApplyChangesToSelectedObject(ObjTransform); + if (bAppliedSomeChanges) + ApplyChangesToSelectedObject(ObjTransform, Scene); } -void GizmoManager::MouseMoveScaleGizmos() +void GizmoManager::MouseMoveScaleGizmos(FEScene* Scene) { - FETransformComponent ObjTransform = GetTransformComponentOfSelectedObject(); + if (Scene == nullptr) + return; - if (GIZMO_MANAGER.bScaleXGizmoActive && GIZMO_MANAGER.bScaleYGizmoActive && GIZMO_MANAGER.bScaleZGizmoActive) - { - const glm::vec3 Difference = GetMousePositionDifferenceOnPlane(-ENGINE.GetCamera()->GetForward()); - const float Magnitude = Difference.x + Difference.y + Difference.z; + FEGizmoSceneData* GizmoSceneData = GIZMO_MANAGER.GetSceneData(Scene->GetObjectID()); + if (GizmoSceneData == nullptr) + return; + FECameraComponent& CameraComponent = CAMERA_SYSTEM.GetMainCamera(Scene)->GetComponent(); + FETransformComponent& ObjTransform = GetTransformComponentOfSelectedObject(Scene); + + if (GizmoSceneData->bScaleXGizmoActive && GizmoSceneData->bScaleYGizmoActive && GizmoSceneData->bScaleZGizmoActive) + { + const glm::vec3 Difference = GetMousePositionDifferenceOnPlane(-CameraComponent.GetForward(), Scene); + float Magnitude = Difference.x + Difference.y + Difference.z; + glm::vec3 EntityScale = ObjTransform.GetScale(); + // Calculate the average current scale + float AverageScale = (EntityScale.x + EntityScale.y + EntityScale.z) / 3.0f; + + // Adjust the magnitude based on the current scale + // to prevent the object from scaling too fast or too slow + float ScaleFactor = glm::clamp(1.0f / AverageScale, 0.001f, 1000.0f); + Magnitude /= ScaleFactor; EntityScale += Magnitude; ObjTransform.SetScale(EntityScale); } - else if (GIZMO_MANAGER.bScaleXGizmoActive || GIZMO_MANAGER.bScaleYGizmoActive || GIZMO_MANAGER.bScaleZGizmoActive) + else if (GizmoSceneData->bScaleXGizmoActive || GizmoSceneData->bScaleYGizmoActive || GizmoSceneData->bScaleZGizmoActive) { - if (GIZMO_MANAGER.bScaleXGizmoActive) + if (GizmoSceneData->bScaleXGizmoActive) { - const glm::vec3 Difference = GetMousePositionDifferenceOnPlane(glm::vec3(0.0f, 0.0f, 1.0f)); + const glm::vec3 Difference = GetMousePositionDifferenceOnPlane(glm::vec3(0.0f, 0.0f, 1.0f), Scene); glm::vec3 EntityScale = ObjTransform.GetScale(); EntityScale.x += Difference.x; ObjTransform.SetScale(EntityScale); } - if (GIZMO_MANAGER.bScaleYGizmoActive) + if (GizmoSceneData->bScaleYGizmoActive) { - const glm::vec3 Difference = GetMousePositionDifferenceOnPlane(glm::vec3(0.0f, 0.0f, 1.0f)); + const glm::vec3 Difference = GetMousePositionDifferenceOnPlane(glm::vec3(0.0f, 0.0f, 1.0f), Scene); glm::vec3 EntityScale = ObjTransform.GetScale(); EntityScale.y += Difference.y; ObjTransform.SetScale(EntityScale); } - if (GIZMO_MANAGER.bScaleZGizmoActive) + if (GizmoSceneData->bScaleZGizmoActive) { - const glm::vec3 Difference = GetMousePositionDifferenceOnPlane(glm::vec3(0.0f, 1.0f, 0.0f)); + const glm::vec3 Difference = GetMousePositionDifferenceOnPlane(glm::vec3(0.0f, 1.0f, 0.0f), Scene); glm::vec3 EntityScale = ObjTransform.GetScale(); EntityScale.z += Difference.z; ObjTransform.SetScale(EntityScale); } } - ApplyChangesToSelectedObject(ObjTransform); + ApplyChangesToSelectedObject(ObjTransform, Scene); } -void GizmoManager::MouseMoveRotateGizmos() +void GizmoManager::MouseMoveRotateGizmos(FEScene* Scene) { - FETransformComponent ObjTransform = GetTransformComponentOfSelectedObject(); - - const float DifferenceX = static_cast(MouseX - LastMouseX); - const float DifferenceY = static_cast(MouseY - LastMouseY); - - const float Difference = (DifferenceX + DifferenceY) / 2.0f; + if (Scene == nullptr) + return; - if (GIZMO_MANAGER.bRotateXGizmoActive) - { - const glm::vec3 XVector = glm::vec3(1.0f, 0.0f, 0.0f); + FEGizmoSceneData* GizmoSceneData = GIZMO_MANAGER.GetSceneData(Scene->GetObjectID()); + if (GizmoSceneData == nullptr) + return; - const glm::quat RotationQuaternion1 = glm::quat(cos(Difference * ANGLE_TORADIANS_COF / 2), - XVector.x * sin(Difference * ANGLE_TORADIANS_COF / 2), - XVector.y * sin(Difference * ANGLE_TORADIANS_COF / 2), - XVector.z * sin(Difference * ANGLE_TORADIANS_COF / 2)); + if (!GizmoSceneData->bRotateXGizmoActive && + !GizmoSceneData->bRotateYGizmoActive && + !GizmoSceneData->bRotateZGizmoActive) + return; - ObjTransform.RotateByQuaternion(RotationQuaternion1); - } + FETransformComponent& ObjTransform = GetTransformComponentOfSelectedObject(Scene); - if (GIZMO_MANAGER.bRotateYGizmoActive) - { - const glm::vec3 YVector = glm::vec3(0.0f, 1.0f, 0.0f); + const float DifferenceX = static_cast(MouseX - LastMouseX); + const float DifferenceY = static_cast(MouseY - LastMouseY); - const glm::quat RotationQuaternion1 = glm::quat(cos(Difference * ANGLE_TORADIANS_COF / 2), - YVector.x * sin(Difference * ANGLE_TORADIANS_COF / 2), - YVector.y * sin(Difference * ANGLE_TORADIANS_COF / 2), - YVector.z * sin(Difference * ANGLE_TORADIANS_COF / 2)); + const float Difference = (DifferenceX + DifferenceY) / 2.0f; - ObjTransform.RotateByQuaternion(RotationQuaternion1); - } + glm::vec3 AxisOfRotation = glm::vec3(0.0f, 0.0f, 0.0f); - if (GIZMO_MANAGER.bRotateZGizmoActive) - { - const glm::vec3 ZVector = glm::vec3(0.0f, 0.0f, 1.0f); + if (GizmoSceneData->bRotateXGizmoActive) + AxisOfRotation = glm::vec3(1.0f, 0.0f, 0.0f); - const glm::quat RotationQuaternion1 = glm::quat(cos(Difference * ANGLE_TORADIANS_COF / 2), - ZVector.x * sin(Difference * ANGLE_TORADIANS_COF / 2), - ZVector.y * sin(Difference * ANGLE_TORADIANS_COF / 2), - ZVector.z * sin(Difference * ANGLE_TORADIANS_COF / 2)); + if (GizmoSceneData->bRotateYGizmoActive) + AxisOfRotation = glm::vec3(0.0f, 1.0f, 0.0f); - ObjTransform.RotateByQuaternion(RotationQuaternion1); - } + if (GizmoSceneData->bRotateZGizmoActive) + AxisOfRotation = glm::vec3(0.0f, 0.0f, 1.0f); - ApplyChangesToSelectedObject(ObjTransform); + ObjTransform.RotateAroundAxis(AxisOfRotation, Difference, FE_WORLD_SPACE); + ApplyChangesToSelectedObject(ObjTransform, Scene); } -void GizmoManager::MouseMove(const double LastMouseX, const double LastMouseY, const double MouseX, const double MouseY) +void GizmoManager::MouseMove(const double LastMouseX, const double LastMouseY, const double MouseX, const double MouseY, FEScene* Scene) { + if (Scene == nullptr) + return; + + FEGizmoSceneData* GizmoSceneData = GIZMO_MANAGER.GetSceneData(Scene->GetObjectID()); + if (GizmoSceneData == nullptr) + return; + this->LastMouseX = LastMouseX; this->LastMouseY = LastMouseY; this->MouseX = MouseX; this->MouseY = MouseY; - if (GizmosState == TRANSFORM_GIZMOS) + if (GizmoSceneData->GizmosState == TRANSFORM_GIZMOS) { - MouseMoveTransformationGizmos(); + MouseMoveTransformationGizmos(Scene); } - else if (GizmosState == SCALE_GIZMOS) + else if (GizmoSceneData->GizmosState == SCALE_GIZMOS) { - MouseMoveScaleGizmos(); + MouseMoveScaleGizmos(Scene); } - else if (GizmosState == ROTATE_GIZMOS) + else if (GizmoSceneData->GizmosState == ROTATE_GIZMOS) { - MouseMoveRotateGizmos(); + MouseMoveRotateGizmos(Scene); } } -void GizmoManager::OnSelectedObjectUpdate() +void GizmoManager::OnSelectedObjectUpdate(FEScene* Scene) { - if (SELECTED.GetSelected() == nullptr) + if (Scene == nullptr) + return; + + FEGizmoSceneData* GizmoSceneData = GIZMO_MANAGER.GetSceneData(Scene->GetObjectID()); + if (GizmoSceneData == nullptr) + return; + + if (SELECTED.GetSelected(Scene) == nullptr) { - GIZMO_MANAGER.HideAllGizmo(); + GIZMO_MANAGER.HideAllGizmo(Scene); } else { - if (SELECTED.GetTerrain() != nullptr) + if (SELECTED.GetSelected(Scene) != nullptr && SELECTED.GetSelected(Scene)->HasComponent()) { - if (SELECTED.GetTerrain()->GetBrushMode() != FE_TERRAIN_BRUSH_NONE) + if (TERRAIN_SYSTEM.GetBrushMode() != FE_TERRAIN_BRUSH_NONE) { - GIZMO_MANAGER.HideAllGizmo(); + GIZMO_MANAGER.HideAllGizmo(Scene); return; } } - if (GIZMO_MANAGER.GizmosState == TRANSFORM_GIZMOS) + if (GizmoSceneData->GizmosState == TRANSFORM_GIZMOS) { - GIZMO_MANAGER.TransformationXGizmoEntity->SetVisibility(true); - GIZMO_MANAGER.TransformationYGizmoEntity->SetVisibility(true); - GIZMO_MANAGER.TransformationZGizmoEntity->SetVisibility(true); - GIZMO_MANAGER.TransformationXyGizmoEntity->SetVisibility(true); - GIZMO_MANAGER.TransformationYzGizmoEntity->SetVisibility(true); - GIZMO_MANAGER.TransformationXzGizmoEntity->SetVisibility(true); + GizmoSceneData->TransformationXGizmoEntity->GetComponent().SetVisibility(true); + GizmoSceneData->TransformationYGizmoEntity->GetComponent().SetVisibility(true); + GizmoSceneData->TransformationZGizmoEntity->GetComponent().SetVisibility(true); + GizmoSceneData->TransformationXYGizmoEntity->GetComponent().SetVisibility(true); + GizmoSceneData->TransformationYZGizmoEntity->GetComponent().SetVisibility(true); + GizmoSceneData->TransformationXZGizmoEntity->GetComponent().SetVisibility(true); } - else if (GIZMO_MANAGER.GizmosState == SCALE_GIZMOS) + else if (GizmoSceneData->GizmosState == SCALE_GIZMOS) { - GIZMO_MANAGER.ScaleXGizmoEntity->SetVisibility(true); - GIZMO_MANAGER.ScaleYGizmoEntity->SetVisibility(true); - GIZMO_MANAGER.ScaleZGizmoEntity->SetVisibility(true); + GizmoSceneData->ScaleXGizmoEntity->GetComponent().SetVisibility(true); + GizmoSceneData->ScaleYGizmoEntity->GetComponent().SetVisibility(true); + GizmoSceneData->ScaleZGizmoEntity->GetComponent().SetVisibility(true); } - else if (GIZMO_MANAGER.GizmosState == ROTATE_GIZMOS) + else if (GizmoSceneData->GizmosState == ROTATE_GIZMOS) { - GIZMO_MANAGER.RotateXGizmoEntity->SetVisibility(true); - GIZMO_MANAGER.RotateYGizmoEntity->SetVisibility(true); - GIZMO_MANAGER.RotateZGizmoEntity->SetVisibility(true); + GizmoSceneData->RotateXGizmoEntity->GetComponent().SetVisibility(true); + GizmoSceneData->RotateYGizmoEntity->GetComponent().SetVisibility(true); + GizmoSceneData->RotateZGizmoEntity->GetComponent().SetVisibility(true); } } } -FETransformComponent GizmoManager::GetTransformComponentOfSelectedObject() +FETransformComponent& GizmoManager::GetTransformComponentOfSelectedObject(FEScene* Scene) { - if (SELECTED.GetSelected() == nullptr) - FETransformComponent(); + if (Scene == nullptr) + return DummyTransformComponent; - if (SELECTED.GetSelected()->GetType() == FE_ENTITY) - { - return SELECTED.GetEntity()->Transform; - } - else if (SELECTED.GetSelected()->GetType() == FE_ENTITY_INSTANCED) - { - if (SELECTED.InstancedSubObjectIndexSelected != -1) - { - return reinterpret_cast(SELECTED.GetEntity())->GetTransformedInstancedMatrix(SELECTED.InstancedSubObjectIndexSelected); - } - else - { - return SELECTED.GetEntity()->Transform; - } - } - else if (SELECTED.GetSelected()->GetType() == FE_TERRAIN) + if (SELECTED.GetSelected(Scene) == nullptr) + return DummyTransformComponent; + + FESelectionData* CurrentSelectionData = SELECTED.GetSceneData(Scene->GetObjectID()); + if (CurrentSelectionData->InstancedSubObjectIndexSelected != -1 && SELECTED.GetSelected(Scene)->HasComponent()) { - return SELECTED.GetTerrain()->Transform; + FEInstancedComponent& InstancedComponent = SELECTED.GetSelected(Scene)->GetComponent(); + + glm::dvec3 Position, Scale; + glm::dquat Rotation; + GEOMETRY.DecomposeMatrixToTranslationRotationScale(InstancedComponent.GetTransformedInstancedMatrix(CurrentSelectionData->InstancedSubObjectIndexSelected), Position, Rotation, Scale); + + DummyTransformComponent.SetPosition(Position); + DummyTransformComponent.SetQuaternion(Rotation); + DummyTransformComponent.SetScale(Scale); + + DummyTransformComponent.SetSceneIndependent(true); + return DummyTransformComponent; } - else if (SELECTED.GetSelected()->GetType() == FE_DIRECTIONAL_LIGHT || SELECTED.GetSelected()->GetType() == FE_SPOT_LIGHT || SELECTED.GetSelected()->GetType() == FE_POINT_LIGHT) + else { - return SELECTED.GetLight()->Transform; + return SELECTED.GetSelected(Scene)->GetComponent(); } - - return FETransformComponent(); } -void GizmoManager::ApplyChangesToSelectedObject(FETransformComponent Changes) +void GizmoManager::ApplyChangesToSelectedObject(FETransformComponent& Changes, FEScene* Scene) { - if (SELECTED.GetSelected() == nullptr) - FETransformComponent(); + if (Scene == nullptr) + return; - if (SELECTED.GetSelected()->GetType() == FE_ENTITY) - { - SELECTED.GetEntity()->Transform = Changes; - } - else if (SELECTED.GetSelected()->GetType() == FE_ENTITY_INSTANCED) + if (SELECTED.GetSelected(Scene) == nullptr) + return; + + FESelectionData* CurrentSelectionData = SELECTED.GetSceneData(Scene->GetObjectID()); + if (CurrentSelectionData->InstancedSubObjectIndexSelected != -1) { - if (SELECTED.InstancedSubObjectIndexSelected != -1) - { - reinterpret_cast(SELECTED.GetEntity())->ModifyInstance(SELECTED.InstancedSubObjectIndexSelected, Changes.GetTransformMatrix()); - } - else - { - SELECTED.GetEntity()->Transform = Changes; - } + INSTANCED_RENDERING_SYSTEM.ModifyIndividualInstance(SELECTED.GetSelected(Scene), CurrentSelectionData->InstancedSubObjectIndexSelected, Changes.GetWorldMatrix()); } - else if (SELECTED.GetSelected()->GetType() == FE_TERRAIN) +} + +void GizmoManager::ClearAllSceneData() +{ + auto PerSceneIterator = PerSceneData.begin(); + while (PerSceneIterator != PerSceneData.end()) { - SELECTED.GetTerrain()->Transform = Changes; + delete PerSceneIterator->second; + PerSceneIterator++; } - else if (SELECTED.GetSelected()->GetType() == FE_DIRECTIONAL_LIGHT || SELECTED.GetSelected()->GetType() == FE_SPOT_LIGHT || SELECTED.GetSelected()->GetType() == FE_POINT_LIGHT) + + PerSceneData.clear(); +} + +void GizmoManager::ClearSceneData(const std::string& SceneID) +{ + auto FoundSceneData = PerSceneData.find(SceneID); + if (FoundSceneData != PerSceneData.end()) { - SELECTED.GetLight()->Transform = Changes; + delete FoundSceneData->second; + PerSceneData.erase(FoundSceneData); } } -void GizmoManager::ReInitializeEntities() +void GizmoManager::AddSceneData(const std::string& SceneID) { - // transformationXGizmo - TransformationXGizmoEntity = SCENE.AddEntity(RESOURCE_MANAGER.GetPrefabByName("TransformationXGizmoGM")[0], "transformationXGizmoEntity"); - TransformationXGizmoEntity->SetCastShadows(false); - TransformationXGizmoEntity->Transform.SetScale(glm::vec3(GizmosScale)); - TransformationXGizmoEntity->Transform.SetRotation(glm::vec3(0.0f, 0.0f, -90.0f)); - TransformationXGizmoEntity->SetIsPostprocessApplied(false); - - // transformationYGizmo - TransformationYGizmoEntity = SCENE.AddEntity(RESOURCE_MANAGER.GetPrefabByName("TransformationYGizmoGM")[0], "transformationYGizmoEntity"); - TransformationYGizmoEntity->SetCastShadows(false); - TransformationYGizmoEntity->Transform.SetScale(glm::vec3(GizmosScale)); - TransformationYGizmoEntity->Transform.SetRotation(glm::vec3(0.0f)); - TransformationYGizmoEntity->SetIsPostprocessApplied(false); - - // transformationZGizmo - TransformationZGizmoEntity = SCENE.AddEntity(RESOURCE_MANAGER.GetPrefabByName("TransformationZGizmoGM")[0], "transformationZGizmoEntity"); - TransformationZGizmoEntity->SetCastShadows(false); - TransformationZGizmoEntity->Transform.SetScale(glm::vec3(GizmosScale)); - TransformationZGizmoEntity->Transform.SetRotation(glm::vec3(90.0f, 0.0f, 90.0f)); - TransformationZGizmoEntity->SetIsPostprocessApplied(false); - - // plane gizmos - TransformationXyGizmoEntity = SCENE.AddEntity(RESOURCE_MANAGER.GetPrefabByName("TransformationXYGizmoGM")[0], "transformationXYGizmoEntity"); - TransformationXyGizmoEntity->SetCastShadows(false); - TransformationXyGizmoEntity->Transform.SetScale(glm::vec3(GizmosScale, GizmosScale, GizmosScale * 0.02f)); - TransformationXyGizmoEntity->Transform.SetRotation(glm::vec3(0.0f, 0.0f, -90.0f)); - TransformationXyGizmoEntity->SetIsPostprocessApplied(false); - - - TransformationYzGizmoEntity = SCENE.AddEntity(RESOURCE_MANAGER.GetPrefabByName("TransformationYZGizmoGM")[0], "transformationYZGizmoEntity"); - TransformationYzGizmoEntity->SetCastShadows(false); - TransformationYzGizmoEntity->Transform.SetScale(glm::vec3(GizmosScale * 0.02f, GizmosScale, GizmosScale)); - TransformationYzGizmoEntity->Transform.SetRotation(glm::vec3(0.0f, 0.0f, 0.0f)); - TransformationYzGizmoEntity->SetIsPostprocessApplied(false); - - TransformationXzGizmoEntity = SCENE.AddEntity(RESOURCE_MANAGER.GetPrefabByName("TransformationXZGizmoGM")[0], "transformationXZGizmoEntity"); - TransformationXzGizmoEntity->SetCastShadows(false); - TransformationXzGizmoEntity->Transform.SetScale(glm::vec3(GizmosScale, GizmosScale * 0.02f, GizmosScale)); - TransformationXzGizmoEntity->Transform.SetRotation(glm::vec3(0.0f, 0.0f, 0.0f)); - TransformationXzGizmoEntity->SetIsPostprocessApplied(false); - - // scaleXGizmo - ScaleXGizmoEntity = SCENE.AddEntity(RESOURCE_MANAGER.GetPrefabByName("scaleXGizmoGM")[0], "scaleXGizmoEntity"); - ScaleXGizmoEntity->SetCastShadows(false); - ScaleXGizmoEntity->Transform.SetScale(glm::vec3(GizmosScale)); - ScaleXGizmoEntity->Transform.SetRotation(glm::vec3(0.0f, 0.0f, -90.0f)); - ScaleXGizmoEntity->SetIsPostprocessApplied(false); - - // scaleYGizmo - ScaleYGizmoEntity = SCENE.AddEntity(RESOURCE_MANAGER.GetPrefabByName("scaleYGizmoGM")[0], "scaleYGizmoEntity"); - ScaleYGizmoEntity->SetCastShadows(false); - ScaleYGizmoEntity->Transform.SetScale(glm::vec3(GizmosScale)); - ScaleYGizmoEntity->Transform.SetRotation(glm::vec3(0.0f)); - ScaleYGizmoEntity->SetIsPostprocessApplied(false); - - // scaleZGizmo - ScaleZGizmoEntity = SCENE.AddEntity(RESOURCE_MANAGER.GetPrefabByName("scaleZGizmoGM")[0], "scaleZGizmoEntity"); - ScaleZGizmoEntity->SetCastShadows(false); - ScaleZGizmoEntity->Transform.SetScale(glm::vec3(GizmosScale)); - ScaleZGizmoEntity->Transform.SetRotation(glm::vec3(90.0f, 0.0f, 90.0f)); - ScaleZGizmoEntity->SetIsPostprocessApplied(false); - - // rotateXGizmo - RotateXGizmoEntity = SCENE.AddEntity(RESOURCE_MANAGER.GetPrefabByName("rotateXGizmoGM")[0], "rotateXGizmoEntity"); - RotateXGizmoEntity->SetCastShadows(false); - RotateXGizmoEntity->Transform.SetScale(glm::vec3(GizmosScale * 2.0f)); - RotateXGizmoEntity->Transform.SetRotation(RotateXStandardRotation); - RotateXGizmoEntity->SetIsPostprocessApplied(false); - - // rotateYGizmo - RotateYGizmoEntity = SCENE.AddEntity(RESOURCE_MANAGER.GetPrefabByName("rotateYGizmoGM")[0], "rotateYGizmoEntity"); - RotateYGizmoEntity->SetCastShadows(false); - RotateYGizmoEntity->Transform.SetScale(glm::vec3(GizmosScale * 2.0f)); - RotateYGizmoEntity->Transform.SetRotation(RotateYStandardRotation); - RotateYGizmoEntity->SetIsPostprocessApplied(false); - - // rotateZGizmo - RotateZGizmoEntity = SCENE.AddEntity(RESOURCE_MANAGER.GetPrefabByName("rotateZGizmoGM")[0], "rotateZGizmoEntity"); - RotateZGizmoEntity->SetCastShadows(false); - RotateZGizmoEntity->Transform.SetScale(glm::vec3(GizmosScale * 2.0f)); - RotateZGizmoEntity->Transform.SetRotation(RotateZStandardRotation); - RotateZGizmoEntity->SetIsPostprocessApplied(false); + FEScene* CurrentScene = SCENE_MANAGER.GetScene(SceneID); + if (CurrentScene == nullptr) + return; + + PerSceneData[SceneID] = new FEGizmoSceneData(); + PerSceneData[SceneID]->SceneID = SceneID; + + PerSceneData[SceneID]->ParentGizmoEntity = CurrentScene->CreateEntity("ParentGizmoEntity"); + RESOURCE_MANAGER.SetTag(PerSceneData[SceneID]->ParentGizmoEntity, EDITOR_RESOURCE_TAG); + PerSceneData[SceneID]->ParentGizmoGraphNode = CurrentScene->SceneGraph.GetNodeByEntityID(PerSceneData[SceneID]->ParentGizmoEntity->GetObjectID()); + + // TransformationXGizmo + PerSceneData[SceneID]->TransformationXGizmoEntity = CurrentScene->CreateEntity("TransformationXGizmoEntity"); + RESOURCE_MANAGER.SetTag(PerSceneData[SceneID]->TransformationXGizmoEntity, EDITOR_RESOURCE_TAG); + PerSceneData[SceneID]->TransformationXGizmoEntity->AddComponent(RESOURCE_MANAGER.GetGameModelByName("TransformationXGizmoGM")[0]); + PerSceneData[SceneID]->TransformationXGizmoEntity->SetName("TransformationXGizmoEntity"); + PerSceneData[SceneID]->TransformationXGizmoEntity->GetComponent().SetCastShadows(false); + PerSceneData[SceneID]->TransformationXGizmoEntity->GetComponent().SetReceivingShadows(false); + PerSceneData[SceneID]->TransformationXGizmoEntity->GetComponent().SetIsPostprocessApplied(false); + PerSceneData[SceneID]->TransformationXGizmoEntity->GetComponent().SetScale(glm::vec3(GizmosScale)); + PerSceneData[SceneID]->TransformationXGizmoEntity->GetComponent().SetRotation(glm::vec3(0.0f, 0.0f, -90.0f)); + CurrentScene->SceneGraph.MoveNode(CurrentScene->SceneGraph.GetNodeByEntityID(PerSceneData[SceneID]->TransformationXGizmoEntity->GetObjectID())->GetObjectID(), PerSceneData[SceneID]->ParentGizmoGraphNode->GetObjectID(), false); + + // TransformationYGizmo + PerSceneData[SceneID]->TransformationYGizmoEntity = CurrentScene->CreateEntity("TransformationYGizmoEntity"); + RESOURCE_MANAGER.SetTag(PerSceneData[SceneID]->TransformationYGizmoEntity, EDITOR_RESOURCE_TAG); + PerSceneData[SceneID]->TransformationYGizmoEntity->AddComponent(RESOURCE_MANAGER.GetGameModelByName("TransformationYGizmoGM")[0]); + PerSceneData[SceneID]->TransformationYGizmoEntity->SetName("TransformationYGizmoEntity"); + PerSceneData[SceneID]->TransformationYGizmoEntity->GetComponent().SetCastShadows(false); + PerSceneData[SceneID]->TransformationYGizmoEntity->GetComponent().SetReceivingShadows(false); + PerSceneData[SceneID]->TransformationYGizmoEntity->GetComponent().SetIsPostprocessApplied(false); + PerSceneData[SceneID]->TransformationYGizmoEntity->GetComponent().SetScale(glm::vec3(GizmosScale)); + PerSceneData[SceneID]->TransformationYGizmoEntity->GetComponent().SetRotation(glm::vec3(0.0f)); + CurrentScene->SceneGraph.MoveNode(CurrentScene->SceneGraph.GetNodeByEntityID(PerSceneData[SceneID]->TransformationYGizmoEntity->GetObjectID())->GetObjectID(), PerSceneData[SceneID]->ParentGizmoGraphNode->GetObjectID(), false); + + // TransformationZGizmo + PerSceneData[SceneID]->TransformationZGizmoEntity = CurrentScene->CreateEntity("TransformationZGizmoEntity"); + RESOURCE_MANAGER.SetTag(PerSceneData[SceneID]->TransformationZGizmoEntity, EDITOR_RESOURCE_TAG); + PerSceneData[SceneID]->TransformationZGizmoEntity->AddComponent(RESOURCE_MANAGER.GetGameModelByName("TransformationZGizmoGM")[0]); + PerSceneData[SceneID]->TransformationZGizmoEntity->SetName("TransformationZGizmoEntity"); + PerSceneData[SceneID]->TransformationZGizmoEntity->GetComponent().SetCastShadows(false); + PerSceneData[SceneID]->TransformationZGizmoEntity->GetComponent().SetReceivingShadows(false); + PerSceneData[SceneID]->TransformationZGizmoEntity->GetComponent().SetIsPostprocessApplied(false); + PerSceneData[SceneID]->TransformationZGizmoEntity->GetComponent().SetScale(glm::vec3(GizmosScale)); + PerSceneData[SceneID]->TransformationZGizmoEntity->GetComponent().SetRotation(glm::vec3(90.0f, 0.0f, 90.0f)); + CurrentScene->SceneGraph.MoveNode(CurrentScene->SceneGraph.GetNodeByEntityID(PerSceneData[SceneID]->TransformationZGizmoEntity->GetObjectID())->GetObjectID(), PerSceneData[SceneID]->ParentGizmoGraphNode->GetObjectID(), false); + + // Plane gizmos + PerSceneData[SceneID]->TransformationXYGizmoEntity = CurrentScene->CreateEntity("TransformationXYGizmoEntity"); + RESOURCE_MANAGER.SetTag(PerSceneData[SceneID]->TransformationXYGizmoEntity, EDITOR_RESOURCE_TAG); + PerSceneData[SceneID]->TransformationXYGizmoEntity->AddComponent(RESOURCE_MANAGER.GetGameModelByName("TransformationXYGizmoGM")[0]); + PerSceneData[SceneID]->TransformationXYGizmoEntity->SetName("TransformationXYGizmoEntity"); + PerSceneData[SceneID]->TransformationXYGizmoEntity->GetComponent().SetCastShadows(false); + PerSceneData[SceneID]->TransformationXYGizmoEntity->GetComponent().SetReceivingShadows(false); + PerSceneData[SceneID]->TransformationXYGizmoEntity->GetComponent().SetIsPostprocessApplied(false); + PerSceneData[SceneID]->TransformationXYGizmoEntity->GetComponent().SetPosition(glm::vec3(0.005f, 0.005f, 0.0f)); + PerSceneData[SceneID]->TransformationXYGizmoEntity->GetComponent().SetScale(glm::vec3(GizmosScale, GizmosScale, GizmosScale * 0.02f)); + PerSceneData[SceneID]->TransformationXYGizmoEntity->GetComponent().SetRotation(glm::vec3(0.0f, 0.0f, -90.0f)); + + CurrentScene->SceneGraph.MoveNode(CurrentScene->SceneGraph.GetNodeByEntityID(PerSceneData[SceneID]->TransformationXYGizmoEntity->GetObjectID())->GetObjectID(), PerSceneData[SceneID]->ParentGizmoGraphNode->GetObjectID(), false); + + PerSceneData[SceneID]->TransformationYZGizmoEntity = CurrentScene->CreateEntity("TransformationYZGizmoEntity"); + RESOURCE_MANAGER.SetTag(PerSceneData[SceneID]->TransformationYZGizmoEntity, EDITOR_RESOURCE_TAG); + PerSceneData[SceneID]->TransformationYZGizmoEntity->AddComponent(RESOURCE_MANAGER.GetGameModelByName("TransformationYZGizmoGM")[0]); + PerSceneData[SceneID]->TransformationYZGizmoEntity->SetName("TransformationYZGizmoEntity"); + PerSceneData[SceneID]->TransformationYZGizmoEntity->GetComponent().SetCastShadows(false); + PerSceneData[SceneID]->TransformationYZGizmoEntity->GetComponent().SetReceivingShadows(false); + PerSceneData[SceneID]->TransformationYZGizmoEntity->GetComponent().SetIsPostprocessApplied(false); + PerSceneData[SceneID]->TransformationYZGizmoEntity->GetComponent().SetPosition(glm::vec3(0.0f, 0.005f, 0.005f)); + PerSceneData[SceneID]->TransformationYZGizmoEntity->GetComponent().SetScale(glm::vec3(GizmosScale * 0.02f, GizmosScale, GizmosScale)); + PerSceneData[SceneID]->TransformationYZGizmoEntity->GetComponent().SetRotation(glm::vec3(0.0f, 0.0f, 0.0f)); + + CurrentScene->SceneGraph.MoveNode(CurrentScene->SceneGraph.GetNodeByEntityID(PerSceneData[SceneID]->TransformationYZGizmoEntity->GetObjectID())->GetObjectID(), PerSceneData[SceneID]->ParentGizmoGraphNode->GetObjectID(), false); + + PerSceneData[SceneID]->TransformationXZGizmoEntity = CurrentScene->CreateEntity("TransformationXZGizmoEntity"); + RESOURCE_MANAGER.SetTag(PerSceneData[SceneID]->TransformationXZGizmoEntity, EDITOR_RESOURCE_TAG); + PerSceneData[SceneID]->TransformationXZGizmoEntity->AddComponent(RESOURCE_MANAGER.GetGameModelByName("TransformationXZGizmoGM")[0]); + PerSceneData[SceneID]->TransformationXZGizmoEntity->SetName("TransformationXZGizmoEntity"); + PerSceneData[SceneID]->TransformationXZGizmoEntity->GetComponent().SetCastShadows(false); + PerSceneData[SceneID]->TransformationXZGizmoEntity->GetComponent().SetReceivingShadows(false); + PerSceneData[SceneID]->TransformationXZGizmoEntity->GetComponent().SetIsPostprocessApplied(false); + PerSceneData[SceneID]->TransformationXZGizmoEntity->GetComponent().SetPosition(glm::vec3(0.005f, 0.0f, 0.005f)); + PerSceneData[SceneID]->TransformationXZGizmoEntity->GetComponent().SetScale(glm::vec3(GizmosScale, GizmosScale * 0.02f, GizmosScale)); + PerSceneData[SceneID]->TransformationXZGizmoEntity->GetComponent().SetRotation(glm::vec3(0.0f, 0.0f, 0.0f)); + CurrentScene->SceneGraph.MoveNode(CurrentScene->SceneGraph.GetNodeByEntityID(PerSceneData[SceneID]->TransformationXZGizmoEntity->GetObjectID())->GetObjectID(), PerSceneData[SceneID]->ParentGizmoGraphNode->GetObjectID(), false); + + // ScaleXGizmo + PerSceneData[SceneID]->ScaleXGizmoEntity = CurrentScene->CreateEntity("ScaleXGizmoEntity"); + RESOURCE_MANAGER.SetTag(PerSceneData[SceneID]->ScaleXGizmoEntity, EDITOR_RESOURCE_TAG); + PerSceneData[SceneID]->ScaleXGizmoEntity->AddComponent(RESOURCE_MANAGER.GetGameModelByName("ScaleXGizmoGM")[0]); + PerSceneData[SceneID]->ScaleXGizmoEntity->SetName("ScaleXGizmoEntity"); + PerSceneData[SceneID]->ScaleXGizmoEntity->GetComponent().SetCastShadows(false); + PerSceneData[SceneID]->ScaleXGizmoEntity->GetComponent().SetReceivingShadows(false); + PerSceneData[SceneID]->ScaleXGizmoEntity->GetComponent().SetIsPostprocessApplied(false); + PerSceneData[SceneID]->ScaleXGizmoEntity->GetComponent().SetScale(glm::vec3(GizmosScale)); + PerSceneData[SceneID]->ScaleXGizmoEntity->GetComponent().SetRotation(glm::vec3(0.0f, 0.0f, -90.0f)); + CurrentScene->SceneGraph.MoveNode(CurrentScene->SceneGraph.GetNodeByEntityID(PerSceneData[SceneID]->ScaleXGizmoEntity->GetObjectID())->GetObjectID(), PerSceneData[SceneID]->ParentGizmoGraphNode->GetObjectID(), false); + + // ScaleYGizmo + PerSceneData[SceneID]->ScaleYGizmoEntity = CurrentScene->CreateEntity("ScaleYGizmoEntity"); + RESOURCE_MANAGER.SetTag(PerSceneData[SceneID]->ScaleYGizmoEntity, EDITOR_RESOURCE_TAG); + PerSceneData[SceneID]->ScaleYGizmoEntity->AddComponent(RESOURCE_MANAGER.GetGameModelByName("ScaleYGizmoGM")[0]); + PerSceneData[SceneID]->ScaleYGizmoEntity->SetName("ScaleYGizmoEntity"); + PerSceneData[SceneID]->ScaleYGizmoEntity->GetComponent().SetCastShadows(false); + PerSceneData[SceneID]->ScaleYGizmoEntity->GetComponent().SetReceivingShadows(false); + PerSceneData[SceneID]->ScaleYGizmoEntity->GetComponent().SetIsPostprocessApplied(false); + PerSceneData[SceneID]->ScaleYGizmoEntity->GetComponent().SetScale(glm::vec3(GizmosScale)); + PerSceneData[SceneID]->ScaleYGizmoEntity->GetComponent().SetRotation(glm::vec3(0.0f)); + CurrentScene->SceneGraph.MoveNode(CurrentScene->SceneGraph.GetNodeByEntityID(PerSceneData[SceneID]->ScaleYGizmoEntity->GetObjectID())->GetObjectID(), PerSceneData[SceneID]->ParentGizmoGraphNode->GetObjectID(), false); + + // ScaleZGizmo + PerSceneData[SceneID]->ScaleZGizmoEntity = CurrentScene->CreateEntity("ScaleZGizmoEntity"); + RESOURCE_MANAGER.SetTag(PerSceneData[SceneID]->ScaleZGizmoEntity, EDITOR_RESOURCE_TAG); + PerSceneData[SceneID]->ScaleZGizmoEntity->AddComponent(RESOURCE_MANAGER.GetGameModelByName("ScaleZGizmoGM")[0]); + PerSceneData[SceneID]->ScaleZGizmoEntity->SetName("ScaleZGizmoEntity"); + PerSceneData[SceneID]->ScaleZGizmoEntity->GetComponent().SetCastShadows(false); + PerSceneData[SceneID]->ScaleZGizmoEntity->GetComponent().SetReceivingShadows(false); + PerSceneData[SceneID]->ScaleZGizmoEntity->GetComponent().SetIsPostprocessApplied(false); + PerSceneData[SceneID]->ScaleZGizmoEntity->GetComponent().SetScale(glm::vec3(GizmosScale)); + PerSceneData[SceneID]->ScaleZGizmoEntity->GetComponent().SetRotation(glm::vec3(90.0f, 0.0f, 90.0f)); + CurrentScene->SceneGraph.MoveNode(CurrentScene->SceneGraph.GetNodeByEntityID(PerSceneData[SceneID]->ScaleZGizmoEntity->GetObjectID())->GetObjectID(), PerSceneData[SceneID]->ParentGizmoGraphNode->GetObjectID(), false); + + // RotateXGizmo + PerSceneData[SceneID]->RotateXGizmoEntity = CurrentScene->CreateEntity("RotateXGizmoEntity"); + RESOURCE_MANAGER.SetTag(PerSceneData[SceneID]->RotateXGizmoEntity, EDITOR_RESOURCE_TAG); + PerSceneData[SceneID]->RotateXGizmoEntity->AddComponent(RESOURCE_MANAGER.GetGameModelByName("RotateXGizmoGM")[0]); + PerSceneData[SceneID]->RotateXGizmoEntity->SetName("RotateXGizmoEntity"); + PerSceneData[SceneID]->RotateXGizmoEntity->GetComponent().SetCastShadows(false); + PerSceneData[SceneID]->RotateXGizmoEntity->GetComponent().SetReceivingShadows(false); + PerSceneData[SceneID]->RotateXGizmoEntity->GetComponent().SetIsPostprocessApplied(false); + PerSceneData[SceneID]->RotateXGizmoEntity->GetComponent().SetScale(glm::vec3(GizmosScale * 2.0f)); + PerSceneData[SceneID]->RotateXGizmoEntity->GetComponent().SetRotation(RotateXStandardRotation); + CurrentScene->SceneGraph.MoveNode(CurrentScene->SceneGraph.GetNodeByEntityID(PerSceneData[SceneID]->RotateXGizmoEntity->GetObjectID())->GetObjectID(), PerSceneData[SceneID]->ParentGizmoGraphNode->GetObjectID(), false); + + // RotateYGizmo + PerSceneData[SceneID]->RotateYGizmoEntity = CurrentScene->CreateEntity("RotateYGizmoEntity"); + RESOURCE_MANAGER.SetTag(PerSceneData[SceneID]->RotateYGizmoEntity, EDITOR_RESOURCE_TAG); + PerSceneData[SceneID]->RotateYGizmoEntity->AddComponent(RESOURCE_MANAGER.GetGameModelByName("RotateYGizmoGM")[0]); + PerSceneData[SceneID]->RotateYGizmoEntity->SetName("RotateYGizmoEntity"); + PerSceneData[SceneID]->RotateYGizmoEntity->GetComponent().SetCastShadows(false); + PerSceneData[SceneID]->RotateYGizmoEntity->GetComponent().SetReceivingShadows(false); + PerSceneData[SceneID]->RotateYGizmoEntity->GetComponent().SetIsPostprocessApplied(false); + PerSceneData[SceneID]->RotateYGizmoEntity->GetComponent().SetScale(glm::vec3(GizmosScale * 2.0f)); + PerSceneData[SceneID]->RotateYGizmoEntity->GetComponent().SetRotation(RotateYStandardRotation); + CurrentScene->SceneGraph.MoveNode(CurrentScene->SceneGraph.GetNodeByEntityID(PerSceneData[SceneID]->RotateYGizmoEntity->GetObjectID())->GetObjectID(), PerSceneData[SceneID]->ParentGizmoGraphNode->GetObjectID(), false); + + // RotateZGizmo + PerSceneData[SceneID]->RotateZGizmoEntity = CurrentScene->CreateEntity("RotateZGizmoEntity"); + RESOURCE_MANAGER.SetTag(PerSceneData[SceneID]->RotateZGizmoEntity, EDITOR_RESOURCE_TAG); + PerSceneData[SceneID]->RotateZGizmoEntity->AddComponent(RESOURCE_MANAGER.GetGameModelByName("RotateZGizmoGM")[0]); + PerSceneData[SceneID]->RotateZGizmoEntity->SetName("RotateZGizmoEntity"); + PerSceneData[SceneID]->RotateZGizmoEntity->GetComponent().SetCastShadows(false); + PerSceneData[SceneID]->RotateZGizmoEntity->GetComponent().SetReceivingShadows(false); + PerSceneData[SceneID]->RotateZGizmoEntity->GetComponent().SetIsPostprocessApplied(false); + PerSceneData[SceneID]->RotateZGizmoEntity->GetComponent().SetScale(glm::vec3(GizmosScale * 2.0f)); + PerSceneData[SceneID]->RotateZGizmoEntity->GetComponent().SetRotation(RotateZStandardRotation); + CurrentScene->SceneGraph.MoveNode(CurrentScene->SceneGraph.GetNodeByEntityID(PerSceneData[SceneID]->RotateZGizmoEntity->GetObjectID())->GetObjectID(), PerSceneData[SceneID]->ParentGizmoGraphNode->GetObjectID(), false); +} + +FEGizmoSceneData* GizmoManager::GetSceneData(const std::string& SceneID) +{ + auto FoundScene = PerSceneData.find(SceneID); + if (FoundScene != PerSceneData.end()) + { + return FoundScene->second; + } + + return nullptr; } \ No newline at end of file diff --git a/FEEditorGizmoManager.h b/FEEditorGizmoManager.h index 9b72216..3d15b96 100644 --- a/FEEditorGizmoManager.h +++ b/FEEditorGizmoManager.h @@ -4,23 +4,26 @@ #include "FEEditorSelectedObject.h" using namespace FocalEngine; -class FEEditor; -struct SelectedObject; - const int TRANSFORM_GIZMOS = 0; const int SCALE_GIZMOS = 1; const int ROTATE_GIZMOS = 2; -class GizmoManager +class FEGizmoSceneData { - friend FEEditor; - friend SelectedObject; -public: - SINGLETON_PUBLIC_PART(GizmoManager) - - float GizmosScale = 0.00175f; + friend class FEEditor; + friend class FEEditorSelectedObject; + friend class GizmoManager; + friend class FEEditorInspectorWindow; + friend class GyzmosSettingsWindow; + + std::string SceneID = ""; + int GizmosState = TRANSFORM_GIZMOS; + // Parent Gizmo Entity + FEEntity* ParentGizmoEntity = nullptr; + FENaiveSceneGraphNode* ParentGizmoGraphNode = nullptr; + FEEntity* TransformationXGizmoEntity = nullptr; FEEntity* TransformationYGizmoEntity = nullptr; FEEntity* TransformationZGizmoEntity = nullptr; @@ -29,15 +32,15 @@ class GizmoManager bool bTransformationYGizmoActive = false; bool bTransformationZGizmoActive = false; - FEEntity* TransformationXyGizmoEntity = nullptr; - FEEntity* TransformationYzGizmoEntity = nullptr; - FEEntity* TransformationXzGizmoEntity = nullptr; + FEEntity* TransformationXYGizmoEntity = nullptr; + FEEntity* TransformationYZGizmoEntity = nullptr; + FEEntity* TransformationXZGizmoEntity = nullptr; bool bTransformationXYGizmoActive = false; bool bTransformationYZGizmoActive = false; bool bTransformationXZGizmoActive = false; - // scale part + // Scale part. FEEntity* ScaleXGizmoEntity = nullptr; FEEntity* ScaleYGizmoEntity = nullptr; FEEntity* ScaleZGizmoEntity = nullptr; @@ -46,7 +49,7 @@ class GizmoManager bool bScaleYGizmoActive = false; bool bScaleZGizmoActive = false; - // rotate part + // Rotate part. FEEntity* RotateXGizmoEntity = nullptr; FEEntity* RotateYGizmoEntity = nullptr; FEEntity* RotateZGizmoEntity = nullptr; @@ -62,36 +65,76 @@ class GizmoManager FETexture* TransformationGizmoIcon = nullptr; FETexture* ScaleGizmoIcon = nullptr; FETexture* RotateGizmoIcon = nullptr; +}; + +class GizmoManager +{ + friend class FEEditor; + friend class FEProjectManager; + friend class GyzmosSettingsWindow; + friend class FEEditorSceneWindow; +public: + SINGLETON_PUBLIC_PART(GizmoManager) + + float GizmosScale = 0.00175f; + + glm::vec3 RotateXStandardRotation = glm::vec3(0.0f, 0.0f, -90.0f); + glm::vec3 RotateYStandardRotation = glm::vec3(0.0f); + glm::vec3 RotateZStandardRotation = glm::vec3(90.0f, 0.0f, 90.0f); + + FETexture* TransformationGizmoIcon = nullptr; + FETexture* ScaleGizmoIcon = nullptr; + FETexture* RotateGizmoIcon = nullptr; void InitializeResources(); - void ReInitializeEntities(); - void DeactivateAllGizmo(); - void HideAllGizmo(); - void UpdateGizmoState(int NewState); - void Render(); - bool WasSelected(int Index); + void DeactivateAllGizmo(FEScene* Scene); + void HideAllGizmo(FEScene* Scene); + void UpdateGizmoState(int NewState, FEScene* Scene); + void Update(); + bool WasSelected(int Index, FEScene* Scene); - void MouseMove(double LastMouseX, double LastMouseY, double MouseX, double MouseY); + void MouseMove(double LastMouseX, double LastMouseY, double MouseX, double MouseY, FEScene* Scene); private: SINGLETON_PRIVATE_PART(GizmoManager) double LastMouseX = 0, LastMouseY = 0, MouseX = 0, MouseY = 0; - glm::vec3 GetMousePositionDifferenceOnPlane(glm::vec3 PlaneNormal); - glm::vec3 GetMousePositionDifferenceOnPlane(glm::vec3 PlaneNormal, glm::vec3& LastMousePointOnPlane); - bool RaysIntersection(const glm::vec3& FRayOrigin, const glm::vec3& FRayDirection, - const glm::vec3& SRayOrigin, const glm::vec3& SRayDirection, - float& Ft, float& St) const; + FEGameModel* TransformationXGizmoGM = nullptr; + FEGameModel* TransformationYGizmoGM = nullptr; + FEGameModel* TransformationZGizmoGM = nullptr; + + FEGameModel* TransformationXYGizmoGM = nullptr; + FEGameModel* TransformationYZGizmoGM = nullptr; + FEGameModel* TransformationXZGizmoGM = nullptr; + + FEGameModel* ScaleXGizmoGM = nullptr; + FEGameModel* ScaleYGizmoGM = nullptr; + FEGameModel* ScaleZGizmoGM = nullptr; + + FEGameModel* RotateXGizmoGM = nullptr; + FEGameModel* RotateYGizmoGM = nullptr; + FEGameModel* RotateZGizmoGM = nullptr; + + glm::vec3 GetMousePositionDifferenceOnPlane(glm::vec3 PlaneNormal, FEScene* Scene); + glm::vec3 GetMousePositionDifferenceOnPlane(glm::vec3 PlaneNormal, glm::vec3& LastMousePointOnPlane, FEScene* Scene); + + void MouseMoveTransformationGizmos(FEScene* Scene); + void MouseMoveScaleGizmos(FEScene* Scene); + void MouseMoveRotateGizmos(FEScene* Scene); + + static void OnSelectedObjectUpdate(FEScene* Scene); - void MouseMoveTransformationGizmos(); - void MouseMoveScaleGizmos(); - void MouseMoveRotateGizmos(); + FETransformComponent& GetTransformComponentOfSelectedObject(FEScene* Scene); + void ApplyChangesToSelectedObject(FETransformComponent& Changes, FEScene* Scene); - static void OnSelectedObjectUpdate(); + std::unordered_map PerSceneData; + void ClearAllSceneData(); + void ClearSceneData(const std::string& SceneID); + void AddSceneData(const std::string& SceneID); + FEGizmoSceneData* GetSceneData(const std::string& SceneID); - FETransformComponent GetTransformComponentOfSelectedObject(); - void ApplyChangesToSelectedObject(FETransformComponent Changes); + FETransformComponent DummyTransformComponent; }; -#define GIZMO_MANAGER GizmoManager::getInstance() \ No newline at end of file +#define GIZMO_MANAGER GizmoManager::GetInstance() \ No newline at end of file diff --git a/FEEditorHaloSelectionEffect.cpp b/FEEditorHaloSelectionEffect.cpp index 779cc55..ba5b429 100644 --- a/FEEditorHaloSelectionEffect.cpp +++ b/FEEditorHaloSelectionEffect.cpp @@ -1,16 +1,14 @@ #include "FEEditorHaloSelectionEffect.h" +#include "FEEditor.h" using namespace FocalEngine; -FEEditorHaloSelectionEffect* FEEditorHaloSelectionEffect::Instance = nullptr; FEEditorHaloSelectionEffect::FEEditorHaloSelectionEffect() {} FEEditorHaloSelectionEffect::~FEEditorHaloSelectionEffect() {} void FEEditorHaloSelectionEffect::InitializeResources() { - HaloObjectsFb = RESOURCE_MANAGER.CreateFramebuffer(FE_COLOR_ATTACHMENT, ENGINE.GetRenderTargetWidth(), ENGINE.GetRenderTargetHeight()); - HaloMaterial = RESOURCE_MANAGER.CreateMaterial("haloMaterial"); - RESOURCE_MANAGER.MakeMaterialStandard(HaloMaterial); + RESOURCE_MANAGER.SetTag(HaloMaterial, EDITOR_RESOURCE_TAG); HaloDrawObjectShader = RESOURCE_MANAGER.CreateShader("HaloDrawObjectShader", RESOURCE_MANAGER.LoadGLSL("Resources//Materials//FE_HaloDrawObject_VS.glsl").c_str(), RESOURCE_MANAGER.LoadGLSL("Resources//Materials//FE_HaloDrawObject_FS.glsl").c_str(), @@ -20,8 +18,7 @@ void FEEditorHaloSelectionEffect::InitializeResources() nullptr, "E4F5165B2E1B05321A182C77"/*"HaloDrawObjectShader"*/); - - RESOURCE_MANAGER.MakeShaderStandard(HaloDrawObjectShader); + RESOURCE_MANAGER.SetTag(HaloDrawObjectShader, EDITOR_RESOURCE_TAG); HaloMaterial->Shader = HaloDrawObjectShader; HaloDrawInstancedObjectShader = RESOURCE_MANAGER.CreateShader("HaloDrawInstancedObjectShader", RESOURCE_MANAGER.LoadGLSL("Resources//Materials//FE_HaloDrawObject_INSTANCED_VS.glsl").c_str(), @@ -31,35 +28,7 @@ void FEEditorHaloSelectionEffect::InitializeResources() nullptr, nullptr, "16A2A65B2C1B013217219C67"/*"HaloDrawInstancedObjectShader"*/); - RESOURCE_MANAGER.MakeShaderStandard(HaloDrawInstancedObjectShader); - - PostProcess = ENGINE.CreatePostProcess("selectionHaloEffect", ENGINE.GetRenderTargetWidth() / 4, ENGINE.GetRenderTargetHeight() / 4); - - FEShader* BlurShader = RESOURCE_MANAGER.GetShader("7F3E4F5C130B537F0846274F"/*"FEBloomBlur"*/); - PostProcess->AddStage(new FEPostProcessStage(FE_POST_PROCESS_OWN_TEXTURE, BlurShader)); - PostProcess->Stages.back()->StageSpecificUniforms.push_back(FEShaderParam(glm::vec2(1.0f, 0.0f), "FEBlurDirection")); - // because input texture at first stage is full resolution, we should blur harder to get simular blur on both sides. - PostProcess->Stages.back()->StageSpecificUniforms.push_back(FEShaderParam(1.5f * 4.0f, "BloomSize")); - PostProcess->Stages.back()->InTexture.push_back(HaloObjectsFb->GetColorAttachment()); - PostProcess->Stages.back()->OutTexture = RESOURCE_MANAGER.CreateSameFormatTexture(RENDERER.SceneToTextureFB->GetColorAttachment(), ENGINE.GetRenderTargetWidth() / 4, ENGINE.GetRenderTargetHeight() / 4); - - PostProcess->AddStage(new FEPostProcessStage(FE_POST_PROCESS_PREVIOUS_STAGE_RESULT0, BlurShader)); - PostProcess->Stages.back()->StageSpecificUniforms.push_back(FEShaderParam(glm::vec2(0.0f, 1.0f), "FEBlurDirection")); - PostProcess->Stages.back()->StageSpecificUniforms.push_back(FEShaderParam(1.5f, "BloomSize")); - PostProcess->Stages.back()->InTexture.push_back(PostProcess->Stages[0]->OutTexture); - PostProcess->Stages.back()->OutTexture = RESOURCE_MANAGER.CreateSameFormatTexture(RENDERER.SceneToTextureFB->GetColorAttachment(), ENGINE.GetRenderTargetWidth() / 4, ENGINE.GetRenderTargetHeight() / 4); - - PostProcess->AddStage(new FEPostProcessStage(FE_POST_PROCESS_PREVIOUS_STAGE_RESULT0, BlurShader)); - PostProcess->Stages.back()->StageSpecificUniforms.push_back(FEShaderParam(glm::vec2(1.0f, 0.0f), "FEBlurDirection")); - PostProcess->Stages.back()->StageSpecificUniforms.push_back(FEShaderParam(1.0f, "BloomSize")); - PostProcess->Stages.back()->InTexture.push_back(PostProcess->Stages[0]->OutTexture); - PostProcess->Stages.back()->OutTexture = RESOURCE_MANAGER.CreateSameFormatTexture(RENDERER.SceneToTextureFB->GetColorAttachment(), ENGINE.GetRenderTargetWidth() / 4, ENGINE.GetRenderTargetHeight() / 4); - - PostProcess->AddStage(new FEPostProcessStage(FE_POST_PROCESS_PREVIOUS_STAGE_RESULT0, BlurShader)); - PostProcess->Stages.back()->StageSpecificUniforms.push_back(FEShaderParam(glm::vec2(0.0f, 1.0f), "FEBlurDirection")); - PostProcess->Stages.back()->StageSpecificUniforms.push_back(FEShaderParam(1.0f, "BloomSize")); - PostProcess->Stages.back()->InTexture.push_back(PostProcess->Stages[0]->OutTexture); - PostProcess->Stages.back()->OutTexture = RESOURCE_MANAGER.CreateSameFormatTexture(RENDERER.SceneToTextureFB->GetColorAttachment(), ENGINE.GetRenderTargetWidth() / 4, ENGINE.GetRenderTargetHeight() / 4); + RESOURCE_MANAGER.SetTag(HaloDrawInstancedObjectShader, EDITOR_RESOURCE_TAG); HaloFinalShader = RESOURCE_MANAGER.CreateShader("HaloFinalShader", RESOURCE_MANAGER.LoadGLSL("SubSystems//FocalEngine//CoreExtensions//PostProcessEffects//FE_ScreenQuad_VS.glsl").c_str(), RESOURCE_MANAGER.LoadGLSL("Resources//Materials//FE_HaloSelectionEffect_FS.glsl").c_str(), @@ -69,57 +38,154 @@ void FEEditorHaloSelectionEffect::InitializeResources() nullptr, "4AC7365B2C1B07324721A127"/*"HaloFinalShader"*/); - PostProcess->AddStage(new FEPostProcessStage(FE_POST_PROCESS_OWN_TEXTURE, HaloFinalShader)); - RESOURCE_MANAGER.MakeShaderStandard(HaloFinalShader); - PostProcess->Stages.back()->InTexture.push_back(RENDERER.PostProcessEffects[RENDERER.PostProcessEffects.size() - 1]->Stages.back()->OutTexture); - PostProcess->Stages.back()->InTextureSource.push_back(FE_POST_PROCESS_OWN_TEXTURE); - PostProcess->Stages.back()->InTexture.push_back(PostProcess->Stages[3]->OutTexture); - PostProcess->Stages.back()->InTextureSource.push_back(FE_POST_PROCESS_OWN_TEXTURE); - PostProcess->Stages.back()->InTexture.push_back(PostProcess->Stages[0]->InTexture[0]); - PostProcess->Stages.back()->OutTexture = RESOURCE_MANAGER.CreateSameFormatTexture(RENDERER.SceneToTextureFB->GetColorAttachment(), ENGINE.GetRenderTargetWidth(), ENGINE.GetRenderTargetHeight()); + RESOURCE_MANAGER.SetTag(HaloFinalShader, EDITOR_RESOURCE_TAG); +} - RENDERER.AddPostProcess(PostProcess, true); +void FEEditorHaloSelectionEffect::UpdateResources(FEScene* Scene) +{ + if (Scene == nullptr) + return; + + FEHaloSelectionData* CurrentHaloSelectionData = GetSceneData(Scene->GetObjectID()); + if (CurrentHaloSelectionData == nullptr) + return; + + FECameraRenderingData* CameraData = RENDERER.GetCameraRenderingData(CAMERA_SYSTEM.GetMainCamera(Scene)); + if (CameraData == nullptr) + return; + + std::vector& PostProcesses = CameraData->PostProcessEffects; + + delete CurrentHaloSelectionData->HaloObjectsFB; + CurrentHaloSelectionData->HaloObjectsFB = RESOURCE_MANAGER.CreateFramebuffer(FE_COLOR_ATTACHMENT, CameraData->SceneToTextureFB->GetWidth(), CameraData->SceneToTextureFB->GetHeight()); + CurrentHaloSelectionData->PostProcess = ENGINE.CreatePostProcess("selectionHaloEffect", CameraData->SceneToTextureFB->GetWidth() / 4, CameraData->SceneToTextureFB->GetHeight() / 4); + + FEShader* BlurShader = RESOURCE_MANAGER.GetShader("7F3E4F5C130B537F0846274F"/*"FEBloomBlur"*/); + CurrentHaloSelectionData->PostProcess->AddStage(new FEPostProcessStage(FE_POST_PROCESS_OWN_TEXTURE, BlurShader)); + CurrentHaloSelectionData->PostProcess->Stages.back()->StageSpecificUniformValues.push_back(FEShaderUniformValue("FEBlurDirection", glm::vec2(1.0f, 0.0f))); + // because input texture at first stage is full resolution, we should blur harder to get simular blur on both sides. + CurrentHaloSelectionData->PostProcess->Stages.back()->StageSpecificUniformValues.push_back(FEShaderUniformValue("BloomSize", 1.5f * 4.0f)); + CurrentHaloSelectionData->PostProcess->Stages.back()->InTexture.push_back(CurrentHaloSelectionData->HaloObjectsFB->GetColorAttachment()); + CurrentHaloSelectionData->PostProcess->ReplaceOutTexture(0, RESOURCE_MANAGER.CreateSameFormatTexture(CameraData->SceneToTextureFB->GetColorAttachment(), CameraData->SceneToTextureFB->GetWidth() / 4, CameraData->SceneToTextureFB->GetHeight() / 4)); + + CurrentHaloSelectionData->PostProcess->AddStage(new FEPostProcessStage(FE_POST_PROCESS_PREVIOUS_STAGE_RESULT0, BlurShader)); + CurrentHaloSelectionData->PostProcess->Stages.back()->StageSpecificUniformValues.push_back(FEShaderUniformValue("FEBlurDirection", glm::vec2(0.0f, 1.0f))); + CurrentHaloSelectionData->PostProcess->Stages.back()->StageSpecificUniformValues.push_back(FEShaderUniformValue("BloomSize", 1.5f)); + CurrentHaloSelectionData->PostProcess->Stages.back()->InTexture.push_back(CurrentHaloSelectionData->PostProcess->Stages[0]->OutTexture); + CurrentHaloSelectionData->PostProcess->ReplaceOutTexture(1, RESOURCE_MANAGER.CreateSameFormatTexture(CameraData->SceneToTextureFB->GetColorAttachment(), CameraData->SceneToTextureFB->GetWidth() / 4, CameraData->SceneToTextureFB->GetHeight() / 4)); + + CurrentHaloSelectionData->PostProcess->AddStage(new FEPostProcessStage(FE_POST_PROCESS_PREVIOUS_STAGE_RESULT0, BlurShader)); + CurrentHaloSelectionData->PostProcess->Stages.back()->StageSpecificUniformValues.push_back(FEShaderUniformValue("FEBlurDirection", glm::vec2(1.0f, 0.0f))); + CurrentHaloSelectionData->PostProcess->Stages.back()->StageSpecificUniformValues.push_back(FEShaderUniformValue("BloomSize", 1.0f)); + CurrentHaloSelectionData->PostProcess->Stages.back()->InTexture.push_back(CurrentHaloSelectionData->PostProcess->Stages[0]->OutTexture); + CurrentHaloSelectionData->PostProcess->ReplaceOutTexture(2, RESOURCE_MANAGER.CreateSameFormatTexture(CameraData->SceneToTextureFB->GetColorAttachment(), CameraData->SceneToTextureFB->GetWidth() / 4, CameraData->SceneToTextureFB->GetHeight() / 4)); + + CurrentHaloSelectionData->PostProcess->AddStage(new FEPostProcessStage(FE_POST_PROCESS_PREVIOUS_STAGE_RESULT0, BlurShader)); + CurrentHaloSelectionData->PostProcess->Stages.back()->StageSpecificUniformValues.push_back(FEShaderUniformValue("FEBlurDirection", glm::vec2(0.0f, 1.0f))); + CurrentHaloSelectionData->PostProcess->Stages.back()->StageSpecificUniformValues.push_back(FEShaderUniformValue("BloomSize", 1.0f)); + CurrentHaloSelectionData->PostProcess->Stages.back()->InTexture.push_back(CurrentHaloSelectionData->PostProcess->Stages[0]->OutTexture); + CurrentHaloSelectionData->PostProcess->ReplaceOutTexture(3, RESOURCE_MANAGER.CreateSameFormatTexture(CameraData->SceneToTextureFB->GetColorAttachment(), CameraData->SceneToTextureFB->GetWidth() / 4, CameraData->SceneToTextureFB->GetHeight() / 4)); + + CurrentHaloSelectionData->PostProcess->AddStage(new FEPostProcessStage(FE_POST_PROCESS_OWN_TEXTURE, HaloFinalShader)); + + CurrentHaloSelectionData->PostProcess->Stages.back()->InTexture.push_back(PostProcesses[PostProcesses.size() - 1]->Stages.back()->OutTexture); + CurrentHaloSelectionData->PostProcess->Stages.back()->InTextureSource.push_back(FE_POST_PROCESS_OWN_TEXTURE); + CurrentHaloSelectionData->PostProcess->Stages.back()->InTexture.push_back(CurrentHaloSelectionData->PostProcess->Stages[3]->OutTexture); + CurrentHaloSelectionData->PostProcess->Stages.back()->InTextureSource.push_back(FE_POST_PROCESS_OWN_TEXTURE); + CurrentHaloSelectionData->PostProcess->Stages.back()->InTexture.push_back(CurrentHaloSelectionData->PostProcess->Stages[0]->InTexture[0]); + CurrentHaloSelectionData->PostProcess->ReplaceOutTexture(4, RESOURCE_MANAGER.CreateSameFormatTexture(CameraData->SceneToTextureFB->GetColorAttachment(), CameraData->SceneToTextureFB->GetWidth(), CameraData->SceneToTextureFB->GetHeight())); + + RENDERER.AddPostProcess(CameraData, CurrentHaloSelectionData->PostProcess, true); } -void FEEditorHaloSelectionEffect::ReInitializeResources() +void FEEditorHaloSelectionEffect::ClearAllSceneData() { - delete HaloObjectsFb; - HaloObjectsFb = RESOURCE_MANAGER.CreateFramebuffer(FE_COLOR_ATTACHMENT, ENGINE.GetRenderTargetWidth(), ENGINE.GetRenderTargetHeight()); - PostProcess = ENGINE.CreatePostProcess("selectionHaloEffect", ENGINE.GetRenderTargetWidth() / 4, ENGINE.GetRenderTargetHeight() / 4); + auto PerSceneIterator = PerSceneData.begin(); + while (PerSceneIterator != PerSceneData.end()) + { + delete PerSceneIterator->second; + PerSceneIterator++; + } + + PerSceneData.clear(); +} + +void FEEditorHaloSelectionEffect::ClearSceneData(const std::string& SceneID) +{ + auto FoundSceneData = PerSceneData.find(SceneID); + if (FoundSceneData != PerSceneData.end()) + { + delete FoundSceneData->second; + PerSceneData.erase(FoundSceneData); + } +} + +void FEEditorHaloSelectionEffect::AddSceneData(const std::string& SceneID) +{ + FEScene* CurrentScene = SCENE_MANAGER.GetScene(SceneID); + if (CurrentScene == nullptr) + return; + + if (PerSceneData.find(SceneID) != PerSceneData.end()) + return; + + PerSceneData[SceneID] = new FEHaloSelectionData(); + PerSceneData[SceneID]->SceneID = SceneID; + + FEEntity* MainCamera = CAMERA_SYSTEM.GetMainCamera(CurrentScene); + FECameraRenderingData* CameraData = RENDERER.GetCameraRenderingData(MainCamera); + if (CameraData == nullptr) + return; + std::vector& PostProcesses = CameraData->PostProcessEffects; + + PerSceneData[SceneID]->HaloObjectsFB = RESOURCE_MANAGER.CreateFramebuffer(FE_COLOR_ATTACHMENT, CameraData->SceneToTextureFB->GetWidth(), CameraData->SceneToTextureFB->GetHeight()); + PerSceneData[SceneID]->PostProcess = ENGINE.CreatePostProcess("selectionHaloEffect", CameraData->SceneToTextureFB->GetWidth() / 4, CameraData->SceneToTextureFB->GetHeight() / 4); FEShader* BlurShader = RESOURCE_MANAGER.GetShader("7F3E4F5C130B537F0846274F"/*"FEBloomBlur"*/); - PostProcess->AddStage(new FEPostProcessStage(FE_POST_PROCESS_OWN_TEXTURE, BlurShader)); - PostProcess->Stages.back()->StageSpecificUniforms.push_back(FEShaderParam(glm::vec2(1.0f, 0.0f), "FEBlurDirection")); + PerSceneData[SceneID]->PostProcess->AddStage(new FEPostProcessStage(FE_POST_PROCESS_OWN_TEXTURE, BlurShader)); + PerSceneData[SceneID]->PostProcess->Stages.back()->StageSpecificUniformValues.push_back(FEShaderUniformValue("FEBlurDirection", glm::vec2(1.0f, 0.0f))); // because input texture at first stage is full resolution, we should blur harder to get simular blur on both sides. - PostProcess->Stages.back()->StageSpecificUniforms.push_back(FEShaderParam(1.5f * 4.0f, "BloomSize")); - PostProcess->Stages.back()->InTexture.push_back(HaloObjectsFb->GetColorAttachment()); - PostProcess->ReplaceOutTexture(0, RESOURCE_MANAGER.CreateSameFormatTexture(RENDERER.SceneToTextureFB->GetColorAttachment(), ENGINE.GetRenderTargetWidth() / 4, ENGINE.GetRenderTargetHeight() / 4)); - - PostProcess->AddStage(new FEPostProcessStage(FE_POST_PROCESS_PREVIOUS_STAGE_RESULT0, BlurShader)); - PostProcess->Stages.back()->StageSpecificUniforms.push_back(FEShaderParam(glm::vec2(0.0f, 1.0f), "FEBlurDirection")); - PostProcess->Stages.back()->StageSpecificUniforms.push_back(FEShaderParam(1.5f, "BloomSize")); - PostProcess->Stages.back()->InTexture.push_back(PostProcess->Stages[0]->OutTexture); - PostProcess->ReplaceOutTexture(1, RESOURCE_MANAGER.CreateSameFormatTexture(RENDERER.SceneToTextureFB->GetColorAttachment(), ENGINE.GetRenderTargetWidth() / 4, ENGINE.GetRenderTargetHeight() / 4)); - - PostProcess->AddStage(new FEPostProcessStage(FE_POST_PROCESS_PREVIOUS_STAGE_RESULT0, BlurShader)); - PostProcess->Stages.back()->StageSpecificUniforms.push_back(FEShaderParam(glm::vec2(1.0f, 0.0f), "FEBlurDirection")); - PostProcess->Stages.back()->StageSpecificUniforms.push_back(FEShaderParam(1.0f, "BloomSize")); - PostProcess->Stages.back()->InTexture.push_back(PostProcess->Stages[0]->OutTexture); - PostProcess->ReplaceOutTexture(2, RESOURCE_MANAGER.CreateSameFormatTexture(RENDERER.SceneToTextureFB->GetColorAttachment(), ENGINE.GetRenderTargetWidth() / 4, ENGINE.GetRenderTargetHeight() / 4)); - - PostProcess->AddStage(new FEPostProcessStage(FE_POST_PROCESS_PREVIOUS_STAGE_RESULT0, BlurShader)); - PostProcess->Stages.back()->StageSpecificUniforms.push_back(FEShaderParam(glm::vec2(0.0f, 1.0f), "FEBlurDirection")); - PostProcess->Stages.back()->StageSpecificUniforms.push_back(FEShaderParam(1.0f, "BloomSize")); - PostProcess->Stages.back()->InTexture.push_back(PostProcess->Stages[0]->OutTexture); - PostProcess->ReplaceOutTexture(3, RESOURCE_MANAGER.CreateSameFormatTexture(RENDERER.SceneToTextureFB->GetColorAttachment(), ENGINE.GetRenderTargetWidth() / 4, ENGINE.GetRenderTargetHeight() / 4)); - - PostProcess->AddStage(new FEPostProcessStage(FE_POST_PROCESS_OWN_TEXTURE, HaloFinalShader)); - PostProcess->Stages.back()->InTexture.push_back(RENDERER.PostProcessEffects[RENDERER.PostProcessEffects.size() - 1]->Stages.back()->OutTexture); - PostProcess->Stages.back()->InTextureSource.push_back(FE_POST_PROCESS_OWN_TEXTURE); - PostProcess->Stages.back()->InTexture.push_back(PostProcess->Stages[3]->OutTexture); - PostProcess->Stages.back()->InTextureSource.push_back(FE_POST_PROCESS_OWN_TEXTURE); - PostProcess->Stages.back()->InTexture.push_back(PostProcess->Stages[0]->InTexture[0]); - PostProcess->ReplaceOutTexture(4, RESOURCE_MANAGER.CreateSameFormatTexture(RENDERER.SceneToTextureFB->GetColorAttachment(), ENGINE.GetRenderTargetWidth(), ENGINE.GetRenderTargetHeight())); - - RENDERER.AddPostProcess(PostProcess, true); + PerSceneData[SceneID]->PostProcess->Stages.back()->StageSpecificUniformValues.push_back(FEShaderUniformValue("BloomSize", 1.5f * 4.0f)); + PerSceneData[SceneID]->PostProcess->Stages.back()->InTexture.push_back(PerSceneData[SceneID]->HaloObjectsFB->GetColorAttachment()); + PerSceneData[SceneID]->PostProcess->ReplaceOutTexture(0, RESOURCE_MANAGER.CreateSameFormatTexture(CameraData->SceneToTextureFB->GetColorAttachment(), CameraData->SceneToTextureFB->GetWidth() / 4, CameraData->SceneToTextureFB->GetHeight() / 4)); + + PerSceneData[SceneID]->PostProcess->AddStage(new FEPostProcessStage(FE_POST_PROCESS_PREVIOUS_STAGE_RESULT0, BlurShader)); + PerSceneData[SceneID]->PostProcess->Stages.back()->StageSpecificUniformValues.push_back(FEShaderUniformValue("FEBlurDirection", glm::vec2(0.0f, 1.0f))); + PerSceneData[SceneID]->PostProcess->Stages.back()->StageSpecificUniformValues.push_back(FEShaderUniformValue("BloomSize", 1.5f)); + PerSceneData[SceneID]->PostProcess->Stages.back()->InTexture.push_back(PerSceneData[SceneID]->PostProcess->Stages[0]->OutTexture); + PerSceneData[SceneID]->PostProcess->ReplaceOutTexture(1, RESOURCE_MANAGER.CreateSameFormatTexture(CameraData->SceneToTextureFB->GetColorAttachment(), CameraData->SceneToTextureFB->GetWidth() / 4, CameraData->SceneToTextureFB->GetHeight() / 4)); + + PerSceneData[SceneID]->PostProcess->AddStage(new FEPostProcessStage(FE_POST_PROCESS_PREVIOUS_STAGE_RESULT0, BlurShader)); + PerSceneData[SceneID]->PostProcess->Stages.back()->StageSpecificUniformValues.push_back(FEShaderUniformValue("FEBlurDirection", glm::vec2(1.0f, 0.0f))); + PerSceneData[SceneID]->PostProcess->Stages.back()->StageSpecificUniformValues.push_back(FEShaderUniformValue("BloomSize", 1.0f)); + PerSceneData[SceneID]->PostProcess->Stages.back()->InTexture.push_back(PerSceneData[SceneID]->PostProcess->Stages[0]->OutTexture); + PerSceneData[SceneID]->PostProcess->ReplaceOutTexture(2, RESOURCE_MANAGER.CreateSameFormatTexture(CameraData->SceneToTextureFB->GetColorAttachment(), CameraData->SceneToTextureFB->GetWidth() / 4, CameraData->SceneToTextureFB->GetHeight() / 4)); + + PerSceneData[SceneID]->PostProcess->AddStage(new FEPostProcessStage(FE_POST_PROCESS_PREVIOUS_STAGE_RESULT0, BlurShader)); + PerSceneData[SceneID]->PostProcess->Stages.back()->StageSpecificUniformValues.push_back(FEShaderUniformValue("FEBlurDirection", glm::vec2(0.0f, 1.0f))); + PerSceneData[SceneID]->PostProcess->Stages.back()->StageSpecificUniformValues.push_back(FEShaderUniformValue("BloomSize", 1.0f)); + PerSceneData[SceneID]->PostProcess->Stages.back()->InTexture.push_back(PerSceneData[SceneID]->PostProcess->Stages[0]->OutTexture); + PerSceneData[SceneID]->PostProcess->ReplaceOutTexture(3, RESOURCE_MANAGER.CreateSameFormatTexture(CameraData->SceneToTextureFB->GetColorAttachment(), CameraData->SceneToTextureFB->GetWidth() / 4, CameraData->SceneToTextureFB->GetHeight() / 4)); + + PerSceneData[SceneID]->PostProcess->AddStage(new FEPostProcessStage(FE_POST_PROCESS_OWN_TEXTURE, HaloFinalShader)); + + PerSceneData[SceneID]->PostProcess->Stages.back()->InTexture.push_back(PostProcesses[PostProcesses.size() - 1]->Stages.back()->OutTexture); + PerSceneData[SceneID]->PostProcess->Stages.back()->InTextureSource.push_back(FE_POST_PROCESS_OWN_TEXTURE); + PerSceneData[SceneID]->PostProcess->Stages.back()->InTexture.push_back(PerSceneData[SceneID]->PostProcess->Stages[3]->OutTexture); + PerSceneData[SceneID]->PostProcess->Stages.back()->InTextureSource.push_back(FE_POST_PROCESS_OWN_TEXTURE); + PerSceneData[SceneID]->PostProcess->Stages.back()->InTexture.push_back(PerSceneData[SceneID]->PostProcess->Stages[0]->InTexture[0]); + PerSceneData[SceneID]->PostProcess->ReplaceOutTexture(4, RESOURCE_MANAGER.CreateSameFormatTexture(CameraData->SceneToTextureFB->GetColorAttachment(), CameraData->SceneToTextureFB->GetWidth(), CameraData->SceneToTextureFB->GetHeight())); + + RENDERER.AddPostProcess(CameraData, PerSceneData[SceneID]->PostProcess, true); +} + +FEHaloSelectionData* FEEditorHaloSelectionEffect::GetSceneData(const std::string& SceneID) +{ + auto FoundScene = PerSceneData.find(SceneID); + if (FoundScene != PerSceneData.end()) + { + return FoundScene->second; + } + + return nullptr; } \ No newline at end of file diff --git a/FEEditorHaloSelectionEffect.h b/FEEditorHaloSelectionEffect.h index 2ed5b70..ccd7e81 100644 --- a/FEEditorHaloSelectionEffect.h +++ b/FEEditorHaloSelectionEffect.h @@ -3,27 +3,43 @@ #include "../FEngine.h" using namespace FocalEngine; -class FEEditorSelectedObject; -class FEEditor; +class FEHaloSelectionData +{ + friend class FEEditor; + friend class FEEditorSelectedObject; + friend class FEEditorHaloSelectionEffect; + + std::string SceneID = ""; + FEFramebuffer* HaloObjectsFB = nullptr; + FEPostProcess* PostProcess = nullptr; + + ~FEHaloSelectionData() + { + delete HaloObjectsFB; + } +}; class FEEditorHaloSelectionEffect { - friend FEEditorSelectedObject; - friend FEEditor; + friend class FEEditorSelectedObject; + friend class FEEditor; private: SINGLETON_PUBLIC_PART(FEEditorHaloSelectionEffect) SINGLETON_PRIVATE_PART(FEEditorHaloSelectionEffect) void InitializeResources(); - void ReInitializeResources(); + void UpdateResources(FEScene* Scene); - FEFramebuffer* HaloObjectsFb = nullptr; FEMaterial* HaloMaterial = nullptr; - FEPostProcess* PostProcess = nullptr; - FEShader* HaloDrawInstancedObjectShader = nullptr; FEShader* HaloDrawObjectShader = nullptr; FEShader* HaloFinalShader = nullptr; + + std::unordered_map PerSceneData; + void ClearAllSceneData(); + void ClearSceneData(const std::string& SceneID); + void AddSceneData(const std::string& SceneID); + FEHaloSelectionData* GetSceneData(const std::string& SceneID); }; -#define HALO_SELECTION_EFFECT FEEditorHaloSelectionEffect::getInstance() \ No newline at end of file +#define HALO_SELECTION_EFFECT FEEditorHaloSelectionEffect::GetInstance() \ No newline at end of file diff --git a/FEEditorInternalResources.cpp b/FEEditorInternalResources.cpp deleted file mode 100644 index a85876b..0000000 --- a/FEEditorInternalResources.cpp +++ /dev/null @@ -1,46 +0,0 @@ -#include "FEEditorInternalResources.h" -using namespace FocalEngine; - -FEEditorInternalResources* FEEditorInternalResources::Instance = nullptr; -FEEditorInternalResources::FEEditorInternalResources() {} -FEEditorInternalResources::~FEEditorInternalResources() {} - -void FEEditorInternalResources::AddResourceToInternalEditorList(FEObject* Object) -{ - if (Object == nullptr) - { - LOG.Add("object is nullptr in function FEEditorInternalResources::addResourceToInternalEditorList.", "FE_LOG_GENERAL", FE_LOG_ERROR); - return; - } - - InternalEditorObjects[Object->GetObjectID()] = Object; -} - -bool FEEditorInternalResources::IsInInternalEditorList(const FEObject* Object) -{ - if (Object == nullptr) - { - LOG.Add("object is nullptr in function FEEditorInternalResources::isInInternalEditorList.", "FE_LOG_GENERAL", FE_LOG_ERROR); - return false; - } - - return !(InternalEditorObjects.find(Object->GetObjectID()) == InternalEditorObjects.end()); -} - -void FEEditorInternalResources::ClearListByType(const FE_OBJECT_TYPE Type) -{ - auto it = InternalEditorObjects.begin(); - while (it != InternalEditorObjects.end()) - { - if (it->second->GetType() == Type) - { - auto temp = it->second; - it++; - InternalEditorObjects.erase(temp->GetObjectID()); - } - else - { - it++; - } - } -} diff --git a/FEEditorInternalResources.h b/FEEditorInternalResources.h deleted file mode 100644 index 287b8ae..0000000 --- a/FEEditorInternalResources.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#include "FEDearImguiWrapper/FEDearImguiWrapper.h" - -class FEEditorInternalResources -{ -public: - SINGLETON_PUBLIC_PART(FEEditorInternalResources) - SINGLETON_PRIVATE_PART(FEEditorInternalResources) - - std::unordered_map InternalEditorObjects; - - void AddResourceToInternalEditorList(FEObject* Object); - bool IsInInternalEditorList(const FEObject* Object); - - void ClearListByType(FE_OBJECT_TYPE Type); -}; - -#define EDITOR_INTERNAL_RESOURCES FEEditorInternalResources::getInstance() \ No newline at end of file diff --git a/FEEditorPreviewManager.cpp b/FEEditorPreviewManager.cpp index 19632f1..f8bf442 100644 --- a/FEEditorPreviewManager.cpp +++ b/FEEditorPreviewManager.cpp @@ -1,28 +1,21 @@ #include "FEEditorPreviewManager.h" +#include "FEEditor.h" using namespace FocalEngine; -FEEditorPreviewManager* FEEditorPreviewManager::Instance = nullptr; FEEditorPreviewManager::FEEditorPreviewManager() {} FEEditorPreviewManager::~FEEditorPreviewManager() {} glm::vec4 FEEditorPreviewManager::OriginalClearColor = glm::vec4(); -FETransformComponent FEEditorPreviewManager::OriginalMeshTransform = FETransformComponent(); -glm::vec3 FEEditorPreviewManager::OriginalCameraPosition = glm::vec3(); -float FEEditorPreviewManager::OriginalAspectRation = 0.0f; -float FEEditorPreviewManager::OriginalCameraPitch = 0.0f; -float FEEditorPreviewManager::OriginalCameraRoll = 0.0f; -float FEEditorPreviewManager::OriginalCameraYaw = 0.0f; -float FEEditorPreviewManager::OriginalExposure = 0.0f; +FETransformComponent FEEditorPreviewManager::OriginalTransform = FETransformComponent(); void FEEditorPreviewManager::InitializeResources() { - PreviewFB = RESOURCE_MANAGER.CreateFramebuffer(FE_COLOR_ATTACHMENT | FE_DEPTH_ATTACHMENT, 128, 128); + PreviewScene = SCENE_MANAGER.CreateScene("EditorPreviewScene", "", FESceneFlag::Active); + RESOURCE_MANAGER.SetTag(PreviewScene, EDITOR_RESOURCE_TAG); + PreviewGameModel = new FEGameModel(nullptr, nullptr, "editorPreviewGameModel"); - PreviewPrefab = new FEPrefab(PreviewGameModel, "editorPreviewPrefab"); - PreviewEntity = SCENE.AddEntity(PreviewPrefab, "editorPreviewEntity"); - PreviewEntity->SetVisibility(false); MeshPreviewMaterial = RESOURCE_MANAGER.CreateMaterial("meshPreviewMaterial"); - RESOURCE_MANAGER.MakeMaterialStandard(MeshPreviewMaterial); + RESOURCE_MANAGER.SetTag(MeshPreviewMaterial, EDITOR_RESOURCE_TAG); MeshPreviewMaterial->Shader = RESOURCE_MANAGER.CreateShader("FEMeshPreviewShader", RESOURCE_MANAGER.LoadGLSL("Resources//Materials//FE_MeshPreview_VS.glsl").c_str(), RESOURCE_MANAGER.LoadGLSL("Resources//Materials//FE_MeshPreview_FS.glsl").c_str(), nullptr, @@ -31,89 +24,78 @@ void FEEditorPreviewManager::InitializeResources() nullptr, "607A53601357077F03770357"/*"FEMeshPreviewShader"*/); - RESOURCE_MANAGER.MakeShaderStandard(MeshPreviewMaterial->Shader); -} - -void FEEditorPreviewManager::ReInitializeEntities() -{ - PreviewEntity = SCENE.AddEntity(PreviewPrefab, "editorPreviewEntity"); - PreviewEntity->SetVisibility(false); + RESOURCE_MANAGER.SetTag(MeshPreviewMaterial->Shader, EDITOR_RESOURCE_TAG); + + PreviewEntity = PreviewScene->CreateEntity("EditorPreviewEntity"); + PreviewEntity->AddComponent(PreviewGameModel); + PreviewEntity->GetComponent().SetVisibility(true); + RESOURCE_MANAGER.SetTag(PreviewEntity, EDITOR_RESOURCE_TAG); + + LocalCameraEntity = PreviewScene->CreateEntity("EditorPreview CameraEntity"); + LocalCameraEntity->AddComponent(); + FECameraComponent& CameraComponent = LocalCameraEntity->GetComponent(); + CameraComponent.TryToSetViewportSize(128, 128); + CameraComponent.SetDistanceFogEnabled(false); + CAMERA_SYSTEM.SetMainCamera(LocalCameraEntity); + + LocalSunEntity = PreviewScene->CreateEntity("EditorPreview LightEntity"); + LocalSunEntity->AddComponent(FE_DIRECTIONAL_LIGHT); + FELightComponent& LightComponent = LocalSunEntity->GetComponent(); + LocalSunEntity->GetComponent().SetRotation(glm::vec3(-40.0f, 10.0f, 0.0f)); + LightComponent.SetIntensity(10.0f); + LightComponent.SetCastShadows(false); + + FEEntity* SkyDome = PreviewScene->CreateEntity("SkyDome"); + SkyDome->GetComponent().SetScale(glm::vec3(150.0f)); + SkyDome->AddComponent(); + + PreviewScene->SetFlag(FESceneFlag::Active | FESceneFlag::Renderable, false); + PreviewScene->SetFlag(FESceneFlag::EditorMode, true); } void FEEditorPreviewManager::UpdateAll() { Clear(); - const std::vector MeshList = RESOURCE_MANAGER.GetMeshList(); + const std::vector MeshList = RESOURCE_MANAGER.GetMeshIDList(); for (size_t i = 0; i < MeshList.size(); i++) { CreateMeshPreview(MeshList[i]); } - const std::vector MaterialList = RESOURCE_MANAGER.GetMaterialList(); + const std::vector MaterialList = RESOURCE_MANAGER.GetMaterialIDList(); for (size_t i = 0; i < MaterialList.size(); i++) { - CreateMaterialPreview(MaterialList[i]); + FEObject* CurrentMaterial = OBJECT_MANAGER.GetFEObject(MaterialList[i]); + if (CurrentMaterial->GetTag() != EDITOR_RESOURCE_TAG) + CreateMaterialPreview(MaterialList[i]); } - const std::vector GameModelList = RESOURCE_MANAGER.GetGameModelList(); + const std::vector GameModelList = RESOURCE_MANAGER.GetGameModelIDList(); for (size_t i = 0; i < GameModelList.size(); i++) { - CreateGameModelPreview(GameModelList[i]); + FEObject* CurrentGameModel = OBJECT_MANAGER.GetFEObject(GameModelList[i]); + if (CurrentGameModel->GetTag() != EDITOR_RESOURCE_TAG) + CreateGameModelPreview(GameModelList[i]); } } void FEEditorPreviewManager::BeforePreviewActions() { - PreviewFB->Bind(); - // We use these values even with the deferred renderer because the final image will not undergo gamma correction. Therefore, values exceeding 1.0f will not function correctly. - OriginalClearColor = ENGINE.GetClearColor(); - ENGINE.SetClearColor(glm::vec4(0.55f, 0.73f, 0.87f, 1.0f)); - - FE_GL_ERROR(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)); - - // Saving currently used variables. - OriginalCameraPosition = ENGINE.GetCamera()->GetPosition(); - OriginalAspectRation = ENGINE.GetCamera()->GetAspectRatio(); - OriginalCameraPitch = ENGINE.GetCamera()->GetPitch(); - OriginalCameraRoll = ENGINE.GetCamera()->GetRoll(); - OriginalCameraYaw = ENGINE.GetCamera()->GetYaw(); - OriginalExposure = ENGINE.GetCamera()->GetExposure(); - ENGINE.GetCamera()->SetExposure(1.0f); - - OriginalMeshTransform = PreviewEntity->Transform; + PreviewScene->SetFlag(FESceneFlag::Active | FESceneFlag::Renderable, true); // The transform impacts the AABB. Therefore, the necessary values must be set prior to any calculations. - PreviewEntity->Transform.SetPosition(glm::vec3(0.0, 0.0, 0.0)); - PreviewEntity->Transform.SetScale(glm::vec3(1.0, 1.0, 1.0)); - PreviewEntity->Transform.SetRotation(glm::vec3(15.0, -15.0, 0.0)); - - ENGINE.GetCamera()->SetAspectRatio(1.0f); - FE_GL_ERROR(glViewport(0, 0, 128, 128)); - - ENGINE.GetCamera()->SetPitch(0.0f); - ENGINE.GetCamera()->SetRoll(0.0f); - ENGINE.GetCamera()->SetYaw(0.0f); - - PreviewEntity->SetVisibility(true); + PreviewEntity->GetComponent().SetPosition(glm::vec3(0.0, 0.0, 0.0)); + PreviewEntity->GetComponent().SetScale(glm::vec3(1.0, 1.0, 1.0)); + PreviewEntity->GetComponent().SetRotation(glm::vec3(15.0, -15.0, 0.0)); } void FEEditorPreviewManager::AfterPreviewActions() { - // We are reversing all of our previously applied transformations. - PreviewEntity->Transform = OriginalMeshTransform; - - ENGINE.GetCamera()->SetPosition(OriginalCameraPosition); - ENGINE.GetCamera()->SetAspectRatio(OriginalAspectRation); - ENGINE.GetCamera()->SetPitch(OriginalCameraPitch); - ENGINE.GetCamera()->SetRoll(OriginalCameraRoll); - ENGINE.GetCamera()->SetYaw(OriginalCameraYaw); - - PreviewFB->UnBind(); - - ENGINE.SetClearColor(OriginalClearColor); + PreviewScene->SetFlag(FESceneFlag::Active | FESceneFlag::Renderable, false); - PreviewEntity->SetVisibility(false); + PreviewGameModel->Mesh = nullptr; + PreviewGameModel->Material = nullptr; } void FEEditorPreviewManager::CreateMeshPreview(const std::string MeshID) @@ -127,39 +109,21 @@ void FEEditorPreviewManager::CreateMeshPreview(const std::string MeshID) BeforePreviewActions(); - FEAABB MeshAABB = PreviewEntity->GetAABB(); - const glm::vec3 min = MeshAABB.GetMin(); - const glm::vec3 max = MeshAABB.GetMax(); - - const float XSize = sqrt((max.x - min.x) * (max.x - min.x)); - const float YSize = sqrt((max.y - min.y) * (max.y - min.y)); - const float ZSize = sqrt((max.z - min.z) * (max.z - min.z)); - - FEDirectionalLight* CurrentDirectionalLight = nullptr; - const std::vector LightList = SCENE.GetLightsList(); - for (size_t i = 0; i < LightList.size(); i++) - { - if (SCENE.GetLight(LightList[i])->GetType() == FE_DIRECTIONAL_LIGHT) - { - CurrentDirectionalLight = reinterpret_cast(SCENE.GetLight(LightList[i])); - break; - } - } - const glm::vec3 RegularLightRotation = CurrentDirectionalLight->Transform.GetRotation(); - CurrentDirectionalLight->Transform.SetRotation(glm::vec3(-40.0f, 10.0f, 0.0f)); - - const float RegularLightIntensity = CurrentDirectionalLight->GetIntensity(); - CurrentDirectionalLight->SetIntensity(10.0f); + FEAABB MeshAABB = PreviewEntity->GetComponent().GetGameModel()->Mesh->GetAABB(); + MeshAABB.Transform(PreviewEntity->GetComponent().GetWorldMatrix()); + const glm::vec3 Min = MeshAABB.GetMin(); + const glm::vec3 Max = MeshAABB.GetMax(); - // invert center point and it will be exactly how much we need to translate mesh in order to place it in origin. - PreviewEntity->Transform.SetPosition(-glm::vec3(max.x - XSize / 2.0f, max.y - YSize / 2.0f, max.z - ZSize / 2.0f)); - ENGINE.GetCamera()->SetPosition(glm::vec3(0.0, 0.0, std::max(std::max(XSize, YSize), ZSize) * 1.75f)); + const float XSize = sqrt((Max.x - Min.x) * (Max.x - Min.x)); + const float YSize = sqrt((Max.y - Min.y) * (Max.y - Min.y)); + const float ZSize = sqrt((Max.z - Min.z) * (Max.z - Min.z)); - // rendering mesh to texture - RENDERER.RenderEntity(PreviewEntity, ENGINE.GetCamera()); + // Invert center point to get required translation vector for centering mesh at origin + PreviewEntity->GetComponent().SetPosition(-glm::vec3(Max.x - XSize / 2.0f, Max.y - YSize / 2.0f, Max.z - ZSize / 2.0f)); + LocalCameraEntity->GetComponent().SetPosition(glm::vec3(0.0, 0.0, std::max(std::max(XSize, YSize), ZSize) * 1.75f)); + CAMERA_SYSTEM.IndividualUpdate(LocalCameraEntity, 0.0); - CurrentDirectionalLight->Transform.SetRotation(RegularLightRotation); - CurrentDirectionalLight->SetIntensity(RegularLightIntensity); + RENDERER.Render(PreviewScene); AfterPreviewActions(); @@ -167,8 +131,9 @@ void FEEditorPreviewManager::CreateMeshPreview(const std::string MeshID) if (MeshPreviewTextures.find(MeshID) != MeshPreviewTextures.end()) delete MeshPreviewTextures[MeshID]; - MeshPreviewTextures[MeshID] = PreviewFB->GetColorAttachment(); - PreviewFB->SetColorAttachment(RESOURCE_MANAGER.CreateSameFormatTexture(PreviewFB->GetColorAttachment())); + FETexture* CameraResult = RENDERER.GetCameraResult(LocalCameraEntity); + if (CameraResult != nullptr) + MeshPreviewTextures[MeshID] = RESOURCE_MANAGER.CreateCopyOfTexture(CameraResult); } FETexture* FEEditorPreviewManager::GetMeshPreview(const std::string MeshID) @@ -177,8 +142,8 @@ FETexture* FEEditorPreviewManager::GetMeshPreview(const std::string MeshID) if (RESOURCE_MANAGER.GetMesh(MeshID)->IsDirty()) { CreateMeshPreview(MeshID); - // if some game model uses this mesh we should also update it's preview - const std::vector GameModelList = RESOURCE_MANAGER.GetGameModelList(); + // if some game model uses this mesh we should also update its preview + const std::vector GameModelList = RESOURCE_MANAGER.GetGameModelIDList(); for (size_t i = 0; i < GameModelList.size(); i++) { @@ -208,35 +173,15 @@ void FEEditorPreviewManager::CreateMaterialPreview(const std::string MaterialID) if (PreviewMaterial == nullptr) return; - FEDirectionalLight* CurrentDirectionalLight = nullptr; - const std::vector LightList = SCENE.GetLightsList(); - for (size_t i = 0; i < LightList.size(); i++) - { - if (SCENE.GetLight(LightList[i])->GetType() == FE_DIRECTIONAL_LIGHT) - { - CurrentDirectionalLight = reinterpret_cast(SCENE.GetLight(LightList[i])); - break; - } - } - const glm::vec3 RegularLightRotation = CurrentDirectionalLight->Transform.GetRotation(); - CurrentDirectionalLight->Transform.SetRotation(glm::vec3(-40.0f, 10.0f, 0.0f)); - - const float RegularLightIntensity = CurrentDirectionalLight->GetIntensity(); - CurrentDirectionalLight->SetIntensity(10.0f); - PreviewGameModel->Mesh = RESOURCE_MANAGER.GetMesh("7F251E3E0D08013E3579315F"/*"sphere"*/); PreviewGameModel->Material = PreviewMaterial; - PreviewEntity->SetReceivingShadows(false); - + PreviewEntity->GetComponent().SetReceivingShadows(false); BeforePreviewActions(); - ENGINE.GetCamera()->SetPosition(glm::vec3(0.0, 0.0, 70.0f)); - - // rendering material to texture - RENDERER.RenderEntityForward(PreviewEntity, ENGINE.GetCamera(), true); + LocalCameraEntity->GetComponent().SetPosition(glm::vec3(0.0, 0.0, 50.0f)); + CAMERA_SYSTEM.IndividualUpdate(LocalCameraEntity, 0.0); - CurrentDirectionalLight->Transform.SetRotation(RegularLightRotation); - CurrentDirectionalLight->SetIntensity(RegularLightIntensity); + RENDERER.Render(PreviewScene); AfterPreviewActions(); @@ -244,11 +189,14 @@ void FEEditorPreviewManager::CreateMaterialPreview(const std::string MaterialID) if (MaterialPreviewTextures.find(MaterialID) != MaterialPreviewTextures.end()) delete MaterialPreviewTextures[MaterialID]; - MaterialPreviewTextures[MaterialID] = PreviewFB->GetColorAttachment(); - PreviewFB->SetColorAttachment(RESOURCE_MANAGER.CreateSameFormatTexture(PreviewFB->GetColorAttachment())); + FETexture* CameraResult = RENDERER.GetCameraResult(LocalCameraEntity); + if (CameraResult != nullptr) + { + MaterialPreviewTextures[MaterialID] = RESOURCE_MANAGER.CreateCopyOfTexture(CameraResult); + } - // looking for all gameModels that uses this material to also update them - const std::vector GameModelList = RESOURCE_MANAGER.GetGameModelList(); + // Looking for all gameModels that uses this material to also update them. + const std::vector GameModelList = RESOURCE_MANAGER.GetGameModelIDList(); for (size_t i = 0; i < GameModelList.size(); i++) { const FEGameModel* CurrentGameModel = RESOURCE_MANAGER.GetGameModel(GameModelList[i]); @@ -256,12 +204,12 @@ void FEEditorPreviewManager::CreateMaterialPreview(const std::string MaterialID) CreateGameModelPreview(CurrentGameModel->GetObjectID()); } - // looking for all prefabs that uses this material to also update them - const std::vector PrefabList = RESOURCE_MANAGER.GetPrefabList(); + // Looking for all prefabs that uses this material to also update them. + const std::vector PrefabList = RESOURCE_MANAGER.GetPrefabIDList(); for (size_t i = 0; i < PrefabList.size(); i++) { FEPrefab* CurrentPrefab = RESOURCE_MANAGER.GetPrefab(PrefabList[i]); - if (CurrentPrefab->UsesMaterial(MaterialID)) + if (CurrentPrefab->IsUsingMaterial(MaterialID)) CreatePrefabPreview(CurrentPrefab->GetObjectID()); } } @@ -272,8 +220,8 @@ FETexture* FEEditorPreviewManager::GetMaterialPreview(const std::string Material if (RESOURCE_MANAGER.GetMaterial(MaterialID)->IsDirty()) { CreateMaterialPreview(MaterialID); - // if some game model uses this material we should also update it's preview - const std::vector GameModelList = RESOURCE_MANAGER.GetGameModelList(); + // if some game model uses this material we should also update its preview + const std::vector GameModelList = RESOURCE_MANAGER.GetGameModelIDList(); for (size_t i = 0; i < GameModelList.size(); i++) { const FEGameModel* CurrentGameModel = RESOURCE_MANAGER.GetGameModel(GameModelList[i]); @@ -282,17 +230,16 @@ FETexture* FEEditorPreviewManager::GetMaterialPreview(const std::string Material { CreateGameModelPreview(CurrentGameModel->GetObjectID()); - // if some prefab uses this game model we should also update it's preview - std::vector PrefabList = RESOURCE_MANAGER.GetPrefabList(); + // If some Prefab uses this game model we should also update its preview. + std::vector PrefabList = RESOURCE_MANAGER.GetPrefabIDList(); for (size_t j = 0; j < PrefabList.size(); j++) { FEPrefab* CurrentPrefab = RESOURCE_MANAGER.GetPrefab(PrefabList[j]); - if (CurrentPrefab->UsesGameModel(CurrentGameModel->GetObjectID())) + if (CurrentPrefab->IsUsingGameModel(CurrentGameModel->GetObjectID())) CreatePrefabPreview(CurrentPrefab->GetObjectID()); } } - } RESOURCE_MANAGER.GetMaterial(MaterialID)->SetDirtyFlag(false); @@ -312,36 +259,16 @@ FETexture* FEEditorPreviewManager::GetMaterialPreview(const std::string Material void FEEditorPreviewManager::CreateGameModelPreview(const std::string GameModelID) { const FEGameModel* GameModel = RESOURCE_MANAGER.GetGameModel(GameModelID); - - if (GameModel == nullptr) + if (GameModel == nullptr || GameModel->Mesh == nullptr || GameModel->Material == nullptr) return; - FEDirectionalLight* CurrentDirectionalLight = nullptr; - const std::vector LightList = SCENE.GetLightsList(); - for (size_t i = 0; i < LightList.size(); i++) - { - if (SCENE.GetLight(LightList[i])->GetType() == FE_DIRECTIONAL_LIGHT) - { - CurrentDirectionalLight = reinterpret_cast(SCENE.GetLight(LightList[i])); - break; - } - } - const glm::vec3 RegularLightRotation = CurrentDirectionalLight->Transform.GetRotation(); - CurrentDirectionalLight->Transform.SetRotation(glm::vec3(-40.0f, 10.0f, 0.0f)); - - const float RegularLightIntensity = CurrentDirectionalLight->GetIntensity(); - CurrentDirectionalLight->SetIntensity(10.0f); - - const bool RegularFog = RENDERER.IsDistanceFogEnabled(); - RENDERER.SetDistanceFogEnabled(false); - PreviewGameModel->Mesh = GameModel->Mesh; PreviewGameModel->Material = GameModel->Material; - PreviewEntity->SetReceivingShadows(false); - + PreviewEntity->GetComponent().SetReceivingShadows(false); BeforePreviewActions(); - FEAABB MeshAABB = PreviewEntity->GetAABB(); + FEAABB MeshAABB = PreviewEntity->GetComponent().GetGameModel()->Mesh->GetAABB(); + MeshAABB.Transform(PreviewEntity->GetComponent().GetWorldMatrix()); const glm::vec3 min = MeshAABB.GetMin(); const glm::vec3 max = MeshAABB.GetMax(); @@ -349,17 +276,12 @@ void FEEditorPreviewManager::CreateGameModelPreview(const std::string GameModelI const float YSize = sqrt((max.y - min.y) * (max.y - min.y)); const float ZSize = sqrt((max.z - min.z) * (max.z - min.z)); - // invert center point and it will be exactly how much we need to translate mesh in order to place it in origin. - PreviewEntity->Transform.SetPosition(-glm::vec3(max.x - XSize / 2.0f, max.y - YSize / 2.0f, max.z - ZSize / 2.0f)); - ENGINE.GetCamera()->SetPosition(glm::vec3(0.0, 0.0, std::max(std::max(XSize, YSize), ZSize) * 1.75f)); - - // rendering game model to texture - RENDERER.RenderEntityForward(PreviewEntity, ENGINE.GetCamera(), true); + // Invert center point to get required translation vector for centering mesh at origin + PreviewEntity->GetComponent().SetPosition(-glm::vec3(max.x - XSize / 2.0f, max.y - YSize / 2.0f, max.z - ZSize / 2.0f)); + LocalCameraEntity->GetComponent().SetPosition(glm::vec3(0.0, 0.0, std::max(std::max(XSize, YSize), ZSize) * 1.75f)); + CAMERA_SYSTEM.IndividualUpdate(LocalCameraEntity, 0.0); - CurrentDirectionalLight->Transform.SetRotation(RegularLightRotation); - CurrentDirectionalLight->SetIntensity(RegularLightIntensity); - - RENDERER.SetDistanceFogEnabled(RegularFog); + RENDERER.Render(PreviewScene); AfterPreviewActions(); @@ -367,8 +289,9 @@ void FEEditorPreviewManager::CreateGameModelPreview(const std::string GameModelI if (GameModelPreviewTextures.find(GameModelID) != GameModelPreviewTextures.end()) delete GameModelPreviewTextures[GameModelID]; - GameModelPreviewTextures[GameModelID] = PreviewFB->GetColorAttachment(); - PreviewFB->SetColorAttachment(RESOURCE_MANAGER.CreateSameFormatTexture(PreviewFB->GetColorAttachment())); + FETexture* CameraResult = RENDERER.GetCameraResult(LocalCameraEntity); + if (CameraResult != nullptr) + GameModelPreviewTextures[GameModelID] = RESOURCE_MANAGER.CreateCopyOfTexture(CameraResult); } void FEEditorPreviewManager::CreateGameModelPreview(const FEGameModel* GameModel, FETexture** ResultingTexture) @@ -376,34 +299,14 @@ void FEEditorPreviewManager::CreateGameModelPreview(const FEGameModel* GameModel if (GameModel == nullptr) return; - FEDirectionalLight* CurrentDirectionalLight = nullptr; - const std::vector LightList = SCENE.GetLightsList(); - for (size_t i = 0; i < LightList.size(); i++) - { - if (SCENE.GetLight(LightList[i])->GetType() == FE_DIRECTIONAL_LIGHT) - { - CurrentDirectionalLight = reinterpret_cast(SCENE.GetLight(LightList[i])); - break; - } - } - const glm::vec3 RegularLightRotation = CurrentDirectionalLight->Transform.GetRotation(); - CurrentDirectionalLight->Transform.SetRotation(glm::vec3(-40.0f, 10.0f, 0.0f)); - - const float RegularLightIntensity = CurrentDirectionalLight->GetIntensity(); - CurrentDirectionalLight->SetIntensity(10.0f); - PreviewGameModel->Mesh = GameModel->Mesh; PreviewGameModel->Material = GameModel->Material; - PreviewEntity->SetReceivingShadows(false); - - if (*ResultingTexture == nullptr) - *ResultingTexture = RESOURCE_MANAGER.CreateSameFormatTexture(PreviewFB->GetColorAttachment()); - FETexture* TempTexture = PreviewFB->GetColorAttachment(); - PreviewFB->SetColorAttachment(*ResultingTexture); + PreviewEntity->GetComponent().SetReceivingShadows(false); BeforePreviewActions(); - FEAABB MeshAABB = PreviewEntity->GetAABB(); + FEAABB MeshAABB = PreviewEntity->GetComponent().GetGameModel()->Mesh->GetAABB(); + MeshAABB.Transform(PreviewEntity->GetComponent().GetWorldMatrix()); const glm::vec3 min = MeshAABB.GetMin(); const glm::vec3 max = MeshAABB.GetMax(); @@ -411,23 +314,28 @@ void FEEditorPreviewManager::CreateGameModelPreview(const FEGameModel* GameModel const float YSize = sqrt((max.y - min.y) * (max.y - min.y)); const float ZSize = sqrt((max.z - min.z) * (max.z - min.z)); - // invert center point and it will be exactly how much we need to translate mesh in order to place it in origin. - PreviewEntity->Transform.SetPosition(-glm::vec3(max.x - XSize / 2.0f, max.y - YSize / 2.0f, max.z - ZSize / 2.0f)); - ENGINE.GetCamera()->SetPosition(glm::vec3(0.0, 0.0, std::max(std::max(XSize, YSize), ZSize) * 1.75f)); - - // rendering game model to texture - RENDERER.RenderEntityForward(PreviewEntity, ENGINE.GetCamera(), true); + // Invert center point to get required translation vector for centering mesh at origin + PreviewEntity->GetComponent().SetPosition(-glm::vec3(max.x - XSize / 2.0f, max.y - YSize / 2.0f, max.z - ZSize / 2.0f)); + LocalCameraEntity->GetComponent().SetPosition(glm::vec3(0.0, 0.0, std::max(std::max(XSize, YSize), ZSize) * 1.75f)); + CAMERA_SYSTEM.IndividualUpdate(LocalCameraEntity, 0.0); - CurrentDirectionalLight->Transform.SetRotation(RegularLightRotation); - CurrentDirectionalLight->SetIntensity(RegularLightIntensity); + RENDERER.Render(PreviewScene); AfterPreviewActions(); - PreviewFB->SetColorAttachment(TempTexture); + FETexture* CameraResult = RENDERER.GetCameraResult(LocalCameraEntity); + if (CameraResult != nullptr) + *ResultingTexture = RESOURCE_MANAGER.CreateCopyOfTexture(CameraResult); } FETexture* FEEditorPreviewManager::GetGameModelPreview(const std::string GameModelID) { + if (RESOURCE_MANAGER.GetGameModel(GameModelID) == nullptr) + { + LOG.Add("FEEditorPreviewManager::GetGameModelPreview could not find game model with ID: " + GameModelID, "FE_LOG_RENDERING", FE_LOG_ERROR); + return RESOURCE_MANAGER.NoTexture; + } + // if game model's dirty flag is set we need to update preview if (RESOURCE_MANAGER.GetGameModel(GameModelID)->IsDirty()) { @@ -459,7 +367,7 @@ FETexture* FEEditorPreviewManager::GetGameModelPreview(const std::string GameMod void FEEditorPreviewManager::UpdateAllGameModelPreviews() { // Getting list of all game models. - const auto GameModelsList = RESOURCE_MANAGER.GetGameModelList(); + const auto GameModelsList = RESOURCE_MANAGER.GetGameModelIDList(); for (size_t i = 0; i < GameModelsList.size(); i++) { CreateGameModelPreview(GameModelsList[i]); @@ -468,72 +376,75 @@ void FEEditorPreviewManager::UpdateAllGameModelPreviews() void FEEditorPreviewManager::CreatePrefabPreview(const std::string PrefabID) { - FEPrefab* prefab = RESOURCE_MANAGER.GetPrefab(PrefabID); - if (prefab == nullptr) - return; - - if (prefab->ComponentsCount() < 1) + FEPrefab* Prefab = RESOURCE_MANAGER.GetPrefab(PrefabID); + if (Prefab == nullptr || Prefab->GetScene() == nullptr) return; - const FEGameModel* GameModel = prefab->GetComponent(0)->GameModel; - if (GameModel == nullptr) - return; - - FEDirectionalLight* CurrentDirectionalLight = nullptr; - const std::vector LightList = SCENE.GetLightsList(); - for (size_t i = 0; i < LightList.size(); i++) - { - if (SCENE.GetLight(LightList[i])->GetType() == FE_DIRECTIONAL_LIGHT) - { - CurrentDirectionalLight = reinterpret_cast(SCENE.GetLight(LightList[i])); - break; - } - } - const glm::vec3 RegularLightRotation = CurrentDirectionalLight->Transform.GetRotation(); - CurrentDirectionalLight->Transform.SetRotation(glm::vec3(-40.0f, 10.0f, 0.0f)); - - const float RegularLightIntensity = CurrentDirectionalLight->GetIntensity(); - CurrentDirectionalLight->SetIntensity(10.0f); - - const bool RegularFog = RENDERER.IsDistanceFogEnabled(); - RENDERER.SetDistanceFogEnabled(false); - - PreviewEntity->Prefab = prefab; - PreviewEntity->SetReceivingShadows(false); - - BeforePreviewActions(); - - PreviewEntity->SetDirtyFlag(true); - FEAABB MeshAABB = PreviewEntity->GetAABB(); - const glm::vec3 min = MeshAABB.GetMin(); - const glm::vec3 max = MeshAABB.GetMax(); - - const float XSize = sqrt((max.x - min.x) * (max.x - min.x)); - const float YSize = sqrt((max.y - min.y) * (max.y - min.y)); - const float ZSize = sqrt((max.z - min.z) * (max.z - min.z)); - - // invert center point and it will be exactly how much we need to translate mesh in order to place it in origin. - PreviewEntity->Transform.SetPosition(-glm::vec3(max.x - XSize / 2.0f, max.y - YSize / 2.0f, max.z - ZSize / 2.0f)); - ENGINE.GetCamera()->SetPosition(glm::vec3(0.0, 0.0, std::max(std::max(XSize, YSize), ZSize) * 1.75f)); - - // rendering game model to texture - RENDERER.RenderEntityForward(PreviewEntity, ENGINE.GetCamera(), true); - - PreviewEntity->Prefab = PreviewPrefab; - - CurrentDirectionalLight->Transform.SetRotation(RegularLightRotation); - CurrentDirectionalLight->SetIntensity(RegularLightIntensity); - - RENDERER.SetDistanceFogEnabled(RegularFog); - - AfterPreviewActions(); - - // if we are updating preview we should delete old texture. + FEScene* CurrentPrefabScene = SCENE_MANAGER.DuplicateScene(Prefab->GetScene(), "Scene: " + Prefab->GetName(), nullptr, FESceneFlag::Active); + + // Because by default camera is looking at 0,0,0 we need to place "empty" entity at 0,0,0. + // To ensure that scene AABB would include some entity at 0,0,0. + CurrentPrefabScene->CreateEntity("Empty entity"); + + FEAABB SceneAABB = CurrentPrefabScene->GetSceneAABB([](FEEntity* Entity) -> bool { + if (Entity->GetTag() == EDITOR_RESOURCE_TAG) + return false; + + if (Entity->HasComponent()) + return false; + + if (Entity->HasComponent()) + return false; + + return true; + }); + + FEEntity* Camera = CurrentPrefabScene->CreateEntity("Prefab scene camera"); + RESOURCE_MANAGER.SetTag(Camera, EDITOR_RESOURCE_TAG); + Camera->AddComponent(); + Camera->GetComponent().SetPosition(glm::vec3(0.0, 0.0, SceneAABB.GetLongestAxisLength() * 2)); + FECameraComponent& CameraComponent = Camera->GetComponent(); + CameraComponent.TryToSetViewportSize(128, 128); + CameraComponent.SetDistanceFogEnabled(false); + CameraComponent.SetSSAOEnabled(false); + CAMERA_SYSTEM.SetMainCamera(Camera); + // To make sure that next scene FEAABB calculation will include correct camera position. + CAMERA_SYSTEM.IndividualUpdate(Camera, 0.0); + + FEEntity* SkyDomeEntity = CurrentPrefabScene->CreateEntity("Prefab scene skydome"); + RESOURCE_MANAGER.SetTag(SkyDomeEntity, EDITOR_RESOURCE_TAG); + SkyDomeEntity->GetComponent().SetScale(glm::vec3(100.0f)); + SkyDomeEntity->AddComponent(); + + FEEntity* LightEntity = CurrentPrefabScene->CreateEntity("Prefab scene light"); + RESOURCE_MANAGER.SetTag(LightEntity, EDITOR_RESOURCE_TAG); + LightEntity->AddComponent(FE_DIRECTIONAL_LIGHT); + FELightComponent& LightComponent = LightEntity->GetComponent(); + LightEntity->GetComponent().SetRotation(glm::vec3(-40.0f, 10.0f, 0.0f)); + LightComponent.SetIntensity(4.3f); + SceneAABB = CurrentPrefabScene->GetSceneAABB([](FEEntity* Entity) -> bool { + if (Entity->GetTag() == EDITOR_RESOURCE_TAG && !Entity->HasComponent()) + return false; + + if (Entity->HasComponent()) + return false; + + return true; + }); + LightComponent.SetShadowCoverage(SceneAABB.GetLongestAxisLength() * 2); + LightComponent.SetCastShadows(true); + + RENDERER.Render(CurrentPrefabScene); + + // If we are updating preview we should delete old texture. if (PrefabPreviewTextures.find(PrefabID) != PrefabPreviewTextures.end()) delete PrefabPreviewTextures[PrefabID]; - PrefabPreviewTextures[PrefabID] = PreviewFB->GetColorAttachment(); - PreviewFB->SetColorAttachment(RESOURCE_MANAGER.CreateSameFormatTexture(PreviewFB->GetColorAttachment())); + FETexture* CameraResult = RENDERER.GetCameraResult(Camera); + if (CameraResult != nullptr) + PrefabPreviewTextures[PrefabID] = RESOURCE_MANAGER.CreateCopyOfTexture(CameraResult); + + SCENE_MANAGER.DeleteScene(CurrentPrefabScene); } void CreatePrefabPreview(FEPrefab* Prefab, FETexture** ResultingTexture) @@ -550,28 +461,18 @@ FETexture* FEEditorPreviewManager::GetPrefabPreview(const std::string PrefabID) return RESOURCE_MANAGER.NoTexture; } - // if prefab's dirty flag is set we need to update preview + // If Prefab's dirty flag is set we need to update preview. if (CurrentPrefab->IsDirty()) { CreatePrefabPreview(PrefabID); CurrentPrefab->SetDirtyFlag(false); } - for (int i = 0; i < CurrentPrefab->ComponentsCount(); i++) - { - // if prefab's material dirty flag is set we need to update preview - if (CurrentPrefab->GetComponent(i)->GameModel->GetMaterial() != nullptr && CurrentPrefab->GetComponent(i)->GameModel->GetMaterial()->IsDirty()) - { - CreateMaterialPreview(CurrentPrefab->GetComponent(i)->GameModel->GetMaterial()->GetObjectID()); - CurrentPrefab->GetComponent(i)->GameModel->GetMaterial()->SetDirtyFlag(false); - } - } - - // if we somehow could not find preview, we will create it. + // If we somehow could not find preview, we will create it. if (PrefabPreviewTextures.find(PrefabID) == PrefabPreviewTextures.end()) CreatePrefabPreview(PrefabID); - // if still we don't have it + // If still we don't have it if (PrefabPreviewTextures.find(PrefabID) == PrefabPreviewTextures.end()) return RESOURCE_MANAGER.NoTexture; @@ -580,27 +481,27 @@ FETexture* FEEditorPreviewManager::GetPrefabPreview(const std::string PrefabID) void FEEditorPreviewManager::Clear() { - auto iterator = MeshPreviewTextures.begin(); - while (iterator != MeshPreviewTextures.end()) + auto MeshIterator = MeshPreviewTextures.begin(); + while (MeshIterator != MeshPreviewTextures.end()) { - delete iterator->second; - iterator++; + delete MeshIterator->second; + MeshIterator++; } MeshPreviewTextures.clear(); - iterator = MaterialPreviewTextures.begin(); - while (iterator != MaterialPreviewTextures.end()) + auto MaterialIterator = MaterialPreviewTextures.begin(); + while (MaterialIterator != MaterialPreviewTextures.end()) { - delete iterator->second; - iterator++; + delete MaterialIterator->second; + MaterialIterator++; } MaterialPreviewTextures.clear(); - iterator = GameModelPreviewTextures.begin(); - while (iterator != GameModelPreviewTextures.end()) + auto GameModelIterator = GameModelPreviewTextures.begin(); + while (GameModelIterator != GameModelPreviewTextures.end()) { - delete iterator->second; - iterator++; + delete GameModelIterator->second; + GameModelIterator++; } GameModelPreviewTextures.clear(); } diff --git a/FEEditorPreviewManager.h b/FEEditorPreviewManager.h index 3896bb5..cef1fc1 100644 --- a/FEEditorPreviewManager.h +++ b/FEEditorPreviewManager.h @@ -3,63 +3,50 @@ #include "../FEngine.h" using namespace FocalEngine; -class FEEditor; -class FEProjectManager; -class DeleteTexturePopup; -class RenameMeshPopUp; -class DeleteMeshPopup; -class SelectMeshPopUp; -class SelectMaterialPopUp; -class SelectGameModelPopUp; -class EditGameModelPopup; -class EditMaterialPopup; -class DeleteMaterialPopup; -class SelectFeObjectPopUp; -class PrefabEditorWindow; - class FEEditorPreviewManager { - friend FEEditor; - friend FEProjectManager; - friend DeleteTexturePopup; - friend RenameMeshPopUp; - friend DeleteMeshPopup; - friend SelectMeshPopUp; - friend SelectMaterialPopUp; - friend SelectGameModelPopUp; - friend EditGameModelPopup; - friend EditMaterialPopup; - friend DeleteMaterialPopup; - friend SelectFeObjectPopUp; - friend PrefabEditorWindow; + friend class FEEditor; + friend class FEEditorInspectorWindow; + friend class FEEditorContentBrowserWindow; + friend class FEProjectManager; + friend class DeleteTexturePopup; + friend class RenameMeshPopUp; + friend class DeleteMeshPopup; + friend class SelectMeshPopUp; + friend class SelectMaterialPopUp; + friend class SelectGameModelPopUp; + friend class EditGameModelPopup; + friend class EditMaterialWindow; + friend class DeleteMaterialPopup; + friend class SelectFEObjectPopUp; + friend class FEPrefabEditorManager; private: SINGLETON_PUBLIC_PART(FEEditorPreviewManager) SINGLETON_PRIVATE_PART(FEEditorPreviewManager) void InitializeResources(); - void ReInitializeEntities(); void UpdateAll(); - FEFramebuffer* PreviewFB; + FEScene* PreviewScene = nullptr; + FEEntity* PreviewEntity; - FEPrefab* PreviewPrefab; FEGameModel* PreviewGameModel; FEMaterial* MeshPreviewMaterial; + FEEntity* LocalSunEntity; + FEEntity* LocalCameraEntity; + + // Saved scene settings + bool bIsRegularFogEnabled = false; + std::unordered_map MeshPreviewTextures; std::unordered_map MaterialPreviewTextures; std::unordered_map GameModelPreviewTextures; std::unordered_map PrefabPreviewTextures; static glm::vec4 OriginalClearColor; - static FETransformComponent OriginalMeshTransform; - static glm::vec3 OriginalCameraPosition; - static float OriginalAspectRation; - static float OriginalCameraPitch; - static float OriginalCameraRoll; - static float OriginalCameraYaw; - static float OriginalExposure; + static FETransformComponent OriginalTransform; void BeforePreviewActions(); void AfterPreviewActions(); @@ -85,4 +72,4 @@ class FEEditorPreviewManager void Clear(); }; -#define PREVIEW_MANAGER FEEditorPreviewManager::getInstance() \ No newline at end of file +#define PREVIEW_MANAGER FEEditorPreviewManager::GetInstance() \ No newline at end of file diff --git a/FEEditorScriptingSystem.cpp b/FEEditorScriptingSystem.cpp new file mode 100644 index 0000000..5d56f2e --- /dev/null +++ b/FEEditorScriptingSystem.cpp @@ -0,0 +1,33 @@ +#include "FEEditorScriptingSystem.h" +using namespace FocalEngine; + +FEEditorScriptingSystem::FEEditorScriptingSystem() +{ + +} + +FEEditorScriptingSystem::~FEEditorScriptingSystem() +{ +} + +void FEEditorScriptingSystem::Update() +{ + FEProject* CurrentProject = PROJECT_MANAGER.GetCurrent(); + if (CurrentProject == nullptr) + return; + + std::vector IDList = RESOURCE_MANAGER.GetNativeScriptModuleIDList(); + for (size_t i = 0; i < IDList.size(); i++) + { + FENativeScriptModule* CurrentModule = RESOURCE_MANAGER.GetNativeScriptModule(IDList[i]); + if (CurrentModule == nullptr) + continue; + + if (CurrentModule->GetTag() == ENGINE_RESOURCE_TAG || + CurrentModule->GetTag() == EDITOR_RESOURCE_TAG) + continue; + + if (CurrentModule->GetProject() != nullptr) + CurrentModule->GetProject()->Update(); + } +} \ No newline at end of file diff --git a/FEEditorScriptingSystem.h b/FEEditorScriptingSystem.h new file mode 100644 index 0000000..b0608fc --- /dev/null +++ b/FEEditorScriptingSystem.h @@ -0,0 +1,16 @@ +#pragma once + +#include "FEEditor.h" +using namespace FocalEngine; + +class FEEditorScriptingSystem +{ +public: + SINGLETON_PUBLIC_PART(FEEditorScriptingSystem) + + void Update(); +private: + SINGLETON_PRIVATE_PART(FEEditorScriptingSystem) +}; + +#define EDITOR_SCRIPTING_SYSTEM FEEditorScriptingSystem::GetInstance() diff --git a/FEEditorSelectedObject.cpp b/FEEditorSelectedObject.cpp index 2674f70..cc6aa67 100644 --- a/FEEditorSelectedObject.cpp +++ b/FEEditorSelectedObject.cpp @@ -1,7 +1,8 @@ #include "FEEditorSelectedObject.h" +#include "SubSystems/ProjectManagment/FEProjectManager.h" +#include "FEEditor.h" using namespace FocalEngine; -FEEditorSelectedObject* FEEditorSelectedObject::Instance = nullptr; FEEditorSelectedObject::FEEditorSelectedObject() {} FEEditorSelectedObject::~FEEditorSelectedObject() {} @@ -9,12 +10,8 @@ void FEEditorSelectedObject::InitializeResources() { HALO_SELECTION_EFFECT.InitializeResources(); - PixelAccurateSelectionFB = RESOURCE_MANAGER.CreateFramebuffer(FE_COLOR_ATTACHMENT | FE_DEPTH_ATTACHMENT, ENGINE.GetRenderTargetWidth(), ENGINE.GetRenderTargetHeight()); - delete PixelAccurateSelectionFB->GetColorAttachment(); - PixelAccurateSelectionFB->SetColorAttachment(RESOURCE_MANAGER.CreateTexture(GL_RGB, GL_RGB, ENGINE.GetRenderTargetWidth(), ENGINE.GetRenderTargetHeight())); - PixelAccurateSelectionMaterial = RESOURCE_MANAGER.CreateMaterial("pixelAccurateSelectionMaterial"); - RESOURCE_MANAGER.MakeMaterialStandard(PixelAccurateSelectionMaterial); + RESOURCE_MANAGER.SetTag(PixelAccurateSelectionMaterial, EDITOR_RESOURCE_TAG); FEPixelAccurateSelection = RESOURCE_MANAGER.CreateShader("FEPixelAccurateSelection", RESOURCE_MANAGER.LoadGLSL("Resources//Materials//FE_PixelAccurateSelection_VS.glsl").c_str(), RESOURCE_MANAGER.LoadGLSL("Resources//Materials//FE_PixelAccurateSelection_FS.glsl").c_str(), @@ -23,7 +20,7 @@ void FEEditorSelectedObject::InitializeResources() nullptr, nullptr, "4279660C7D3D27360358354E"/*"FEPixelAccurateSelection"*/); - RESOURCE_MANAGER.MakeShaderStandard(FEPixelAccurateSelection); + RESOURCE_MANAGER.SetTag(FEPixelAccurateSelection, EDITOR_RESOURCE_TAG); PixelAccurateSelectionMaterial->Shader = FEPixelAccurateSelection; FEPixelAccurateInstancedSelection = RESOURCE_MANAGER.CreateShader("FEPixelAccurateInstancedSelection", RESOURCE_MANAGER.LoadGLSL("Resources//Materials//FE_PixelAccurateSelection_INSTANCED_VS.glsl").c_str(), @@ -34,155 +31,299 @@ void FEEditorSelectedObject::InitializeResources() nullptr, "0E213D3542135C15471F0D6B"/*"FEPixelAccurateInstancedSelection"*/); - RESOURCE_MANAGER.MakeShaderStandard(FEPixelAccurateInstancedSelection); - - const FEShaderParam ColorParam(glm::vec3(0.0f, 0.0f, 0.0f), "baseColor"); - PixelAccurateSelectionMaterial->AddParameter(ColorParam); + RESOURCE_MANAGER.SetTag(FEPixelAccurateInstancedSelection, EDITOR_RESOURCE_TAG); + PixelAccurateSelectionMaterial->SetBaseColor(glm::vec3(0.0f, 0.0f, 0.0f)); } -void FEEditorSelectedObject::ReInitializeResources() +void FEEditorSelectedObject::UpdateResources(FEScene* Scene) { - HALO_SELECTION_EFFECT.ReInitializeResources(); + HALO_SELECTION_EFFECT.UpdateResources(Scene); - delete PixelAccurateSelectionFB; - PixelAccurateSelectionFB = RESOURCE_MANAGER.CreateFramebuffer(FE_COLOR_ATTACHMENT | FE_DEPTH_ATTACHMENT, ENGINE.GetRenderTargetWidth(), ENGINE.GetRenderTargetHeight()); - delete PixelAccurateSelectionFB->GetColorAttachment(); - PixelAccurateSelectionFB->SetColorAttachment(RESOURCE_MANAGER.CreateTexture(GL_RGB, GL_RGB, ENGINE.GetRenderTargetWidth(), ENGINE.GetRenderTargetHeight())); -} + if (Scene == nullptr) + return; -void FEEditorSelectedObject::SetOnUpdateFunc(void(*Func)()) -{ - OnUpdateFunc = Func; -} + FESelectionData* CurrentSelectionData = GetSceneData(Scene->GetObjectID()); + if (CurrentSelectionData == nullptr) + return; -FEObject* FEEditorSelectedObject::GetSelected() const -{ - return Container; + FEEntity* CurrentCamera = CAMERA_SYSTEM.GetMainCamera(Scene); + FECameraComponent& CameraComponent = CurrentCamera->GetComponent(); + + delete CurrentSelectionData->PixelAccurateSelectionFB; + CurrentSelectionData->PixelAccurateSelectionFB = RESOURCE_MANAGER.CreateFramebuffer(FE_COLOR_ATTACHMENT | FE_DEPTH_ATTACHMENT, CameraComponent.GetRenderTargetWidth(), CameraComponent.GetRenderTargetHeight()); + delete CurrentSelectionData->PixelAccurateSelectionFB->GetColorAttachment(); + CurrentSelectionData->PixelAccurateSelectionFB->SetColorAttachment(RESOURCE_MANAGER.CreateTexture(GL_RGB, GL_RGB, CameraComponent.GetRenderTargetWidth(), CameraComponent.GetRenderTargetHeight())); } -bool FEEditorSelectedObject::GetDirtyFlag() const +void FEEditorSelectedObject::SetOnUpdateFunction(std::function Func) { - return bDirtyFlag; + OnUpdateFunction = Func; } -void FEEditorSelectedObject::SetDirtyFlag(const bool NewValue) +FEEntity* FEEditorSelectedObject::GetSelected(FEScene* Scene) { - bDirtyFlag = NewValue; + if (Scene == nullptr) + return nullptr; + + FESelectionData* CurrentSelectionData = GetSceneData(Scene->GetObjectID()); + if (CurrentSelectionData == nullptr) + return nullptr; + + return Scene->GetEntity(CurrentSelectionData->SelectedEntityID); } -void FEEditorSelectedObject::SetSelected(FEObject* SelectedObject) +void FEEditorSelectedObject::SetSelected(FEEntity* SelectedObject) { if (SelectedObject == nullptr) return; - - if (Container != SelectedObject) - bDirtyFlag = true; - if (Container != nullptr && Container->GetType() == FE_TERRAIN && Container != SelectedObject) + FEScene* CurrentScene = SelectedObject->GetParentScene(); + if (CurrentScene == nullptr) + return; + + FESelectionData* CurrentSelectionData = GetSceneData(CurrentScene->GetObjectID()); + if (CurrentSelectionData == nullptr) { - FETerrain* DeselectedTerrain = reinterpret_cast(Container); - DeselectedTerrain->SetBrushMode(FE_TERRAIN_BRUSH_NONE); + AddSceneData(CurrentScene->GetObjectID()); + CurrentSelectionData = GetSceneData(CurrentScene->GetObjectID()); + + // If the data is still null log error and return + if (CurrentSelectionData == nullptr) + { + LOG.Add("FEEditorSelectedObject::SetSelected: Could not create selection data for scene: " + CurrentScene->GetObjectID(), "FE_LOG_ERROR", FE_LOG_ERROR); + return; + } } - Container = SelectedObject; - if (OnUpdateFunc != nullptr) - OnUpdateFunc(); + FEEntity* CurrentlySelectedEntity = CurrentScene->GetEntity(CurrentSelectionData->SelectedEntityID); + + if (CurrentlySelectedEntity != nullptr && CurrentlySelectedEntity->HasComponent() && CurrentlySelectedEntity != SelectedObject) + TERRAIN_SYSTEM.SetBrushMode(CurrentlySelectedEntity, FE_TERRAIN_BRUSH_NONE); + + CurrentSelectionData->SelectedEntityID = SelectedObject->GetObjectID(); + if (OnUpdateFunction != nullptr) + OnUpdateFunction(CurrentScene); } -void FEEditorSelectedObject::Clear() +void FEEditorSelectedObject::Clear(FEScene* Scene) { - if (InstancedSubObjectIndexSelected != -1 && SCENE.GetEntityInstanced(Container->GetObjectID()) != nullptr) + if (Scene == nullptr) + return; + + FESelectionData* CurrentSelectionData = GetSceneData(Scene->GetObjectID()); + if (CurrentSelectionData == nullptr) + return; + + FEEntity* CurrentlySelectedEntity = Scene->GetEntity(CurrentSelectionData->SelectedEntityID); + if (CurrentSelectionData->InstancedSubObjectIndexSelected != -1 && CurrentlySelectedEntity->HasComponent()) { - SCENE.GetEntityInstanced(Container->GetObjectID())->SetSelectMode(false); + INSTANCED_RENDERING_SYSTEM.SetIndividualSelectMode(CurrentlySelectedEntity, false); } - InstancedSubObjectIndexSelected = -1; - Container = nullptr; - bDirtyFlag = true; - if (OnUpdateFunc != nullptr) - OnUpdateFunc(); -} + CurrentSelectionData->InstancedSubObjectIndexSelected = -1; + CurrentSelectionData->SelectedEntityID = ""; -glm::dvec3 FEEditorSelectedObject::MouseRay(const double MouseX, const double MouseY) const -{ - glm::dvec2 NormalizedMouseCoords; - NormalizedMouseCoords.x = (2.0f * MouseX) / ENGINE.GetRenderTargetWidth() - 1; - NormalizedMouseCoords.y = 1.0f - (2.0f * (MouseY)) / ENGINE.GetRenderTargetHeight(); - - const glm::dvec4 ClipCoords = glm::dvec4(NormalizedMouseCoords.x, NormalizedMouseCoords.y, -1.0, 1.0); - glm::dvec4 EyeCoords = glm::inverse(ENGINE.GetCamera()->GetProjectionMatrix()) * ClipCoords; - EyeCoords.z = -1.0f; - EyeCoords.w = 0.0f; - glm::dvec3 WorldRay = glm::inverse(ENGINE.GetCamera()->GetViewMatrix()) * EyeCoords; - WorldRay = glm::normalize(WorldRay); - - return WorldRay; + if (!SCENE_MANAGER.GetScenesByFlagMask(FESceneFlag::Active).empty()) + if (OnUpdateFunction != nullptr) + OnUpdateFunction(Scene); } -void FEEditorSelectedObject::DetermineEntityUnderMouse(const double MouseX, const double MouseY) +void FEEditorSelectedObject::DetermineEntityUnderMouse(const double MouseX, const double MouseY, FEScene* Scene) { - SELECTED.ObjectsUnderMouse.clear(); - SELECTED.InstancedSubObjectsInfo.clear(); + FESelectionData* CurrentSelectionData = GetSceneData(Scene->GetObjectID()); + if (CurrentSelectionData == nullptr) + return; + + CurrentSelectionData->SceneEntitiesUnderMouse.clear(); + CurrentSelectionData->InstancedSubObjectsInfo.clear(); + + FEEntity* MainCamera = CAMERA_SYSTEM.GetMainCamera(Scene); + FETransformComponent& CameraTransformComponent = MainCamera->GetComponent(); + FECameraComponent& CameraComponent = MainCamera->GetComponent(); + + FEViewport* CurrentViewport = CAMERA_SYSTEM.GetMainCameraViewport(Scene); + glm::ivec2 ViewportPosition = glm::ivec2(CurrentViewport->GetX(), CurrentViewport->GetY()); + glm::ivec2 ViewportSize = glm::ivec2(CurrentViewport->GetWidth(), CurrentViewport->GetHeight()); - const glm::vec3 MouseRayVector = MouseRay(MouseX, MouseY); - const std::vector EntityList = SCENE.GetEntityList(); + const glm::vec3 MouseRay = GEOMETRY.CreateMouseRayToWorld(MouseX, MouseY, + CameraComponent.GetViewMatrix(), CameraComponent.GetProjectionMatrix(), + ViewportPosition, ViewportSize); + + const std::vector EntityList = Scene->GetEntityIDList(); for (size_t i = 0; i < EntityList.size(); i++) { - float dis = 0; - FEAABB box = SCENE.GetEntity(EntityList[i])->GetAABB(); - if (box.RayIntersect(ENGINE.GetCamera()->GetPosition(), MouseRayVector, dis)) + float Distance = 0; + + FEEntity* CurrentEntity = Scene->GetEntity(EntityList[i]); + if (CurrentEntity != nullptr) { - if (SCENE.GetEntity(EntityList[i])->GetType() == FE_ENTITY_INSTANCED) + FEAABB Box = Scene->GetEntityAABB(CurrentEntity); + if (Box.RayIntersect(CameraTransformComponent.GetPosition(FE_WORLD_SPACE), MouseRay, Distance)) { - FEEntityInstanced* InstancedEntity = reinterpret_cast(SCENE.GetEntity(EntityList[i])); - if (InstancedEntity->IsSelectMode()) + if (CurrentEntity->HasComponent()) { - InstancedSubObjectsInfo[InstancedEntity] = std::vector(); - for (size_t j = 0; j < InstancedEntity->InstancedAABB.size(); j++) + FEInstancedComponent& InstancedComponent = CurrentEntity->GetComponent(); + if (INSTANCED_RENDERING_SYSTEM.IsIndividualSelectMode(CurrentEntity)) { - if(InstancedEntity->InstancedAABB[j].RayIntersect(ENGINE.GetCamera()->GetPosition(), MouseRayVector, dis)) + CurrentSelectionData->InstancedSubObjectsInfo[CurrentEntity] = std::vector(); + for (size_t j = 0; j < InstancedComponent.IndividualInstancedAABB.size(); j++) { - InstancedSubObjectsInfo[InstancedEntity].push_back(static_cast(j)); + if (InstancedComponent.IndividualInstancedAABB[j].RayIntersect(CameraTransformComponent.GetPosition(FE_WORLD_SPACE), MouseRay, Distance)) + { + CurrentSelectionData->InstancedSubObjectsInfo[CurrentEntity].push_back(static_cast(j)); + } } } } - SELECTED.ObjectsUnderMouse.push_back(InstancedEntity); + CurrentSelectionData->SceneEntitiesUnderMouse.push_back(CurrentEntity); } - else + } + } +} + +void FEEditorSelectedObject::RenderEntitySelectionColorID(FEEntity* Entity, glm::vec3 ColorID, FEEntity* CameraEntity, FESelectionData* CurrentSelectionData) +{ + if (Entity == nullptr || CameraEntity == nullptr) + return; + + if (Entity->HasComponent()) + { + FEGameModelComponent& GameModelComponent = Entity->GetComponent(); + if (!GameModelComponent.IsVisible()) + return; + + FEMaterial* RegularMaterial = GameModelComponent.GetGameModel()->Material; + GameModelComponent.GetGameModel()->Material = PixelAccurateSelectionMaterial; + PixelAccurateSelectionMaterial->SetBaseColor(ColorID); + PixelAccurateSelectionMaterial->ClearAllTexturesInfo(); + PixelAccurateSelectionMaterial->SetAlbedoMap(RegularMaterial->GetAlbedoMap()); + PixelAccurateSelectionMaterial->SetAlbedoMap(RegularMaterial->GetAlbedoMap(1), 1); + + if (!Entity->HasComponent()) + { + RENDERER.RenderGameModelComponent(Entity, CameraEntity); + } + else if (Entity->HasComponent()) + { + // Update instanced object only if it is not in individual select mode + if (!INSTANCED_RENDERING_SYSTEM.IsIndividualSelectMode(Entity)) { - SELECTED.ObjectsUnderMouse.push_back(SCENE.GetEntity(EntityList[i])); + PixelAccurateSelectionMaterial->Shader = FEPixelAccurateInstancedSelection; + FEMaterial* RegularBillboardMaterials = GameModelComponent.GetGameModel()->GetBillboardMaterial(); + GameModelComponent.GetGameModel()->SetBillboardMaterial(PixelAccurateSelectionMaterial); + + FEInstancedComponent& InstancedComponent = Entity->GetComponent(); + RENDERER.RenderGameModelComponentWithInstanced(Entity, CameraEntity); + + PixelAccurateSelectionMaterial->Shader = FEPixelAccurateSelection; + GameModelComponent.GetGameModel()->SetBillboardMaterial(RegularBillboardMaterials); } } - } - const std::vector TerrainList = SCENE.GetTerrainList(); - for (size_t i = 0; i < TerrainList.size(); i++) + GameModelComponent.GetGameModel()->Material = RegularMaterial; + PixelAccurateSelectionMaterial->SetAlbedoMap(nullptr); + PixelAccurateSelectionMaterial->SetAlbedoMap(nullptr, 1); + } + else if (Entity->HasComponent()) + { + FETerrainComponent& TerrainComponent = Entity->GetComponent(); + if (!TerrainComponent.IsVisible()) + return; + + TerrainComponent.Shader = RESOURCE_MANAGER.GetShader("50064D3C4D0B537F0846274F"/*"FESMTerrainShader"*/); + TerrainComponent.Shader->UpdateUniformData("baseColor", ColorID); + RENDERER.RenderTerrainComponent(Entity, CameraEntity); + TerrainComponent.Shader->UpdateUniformData("baseColor", glm::vec3(1.0f)); + TerrainComponent.Shader = RESOURCE_MANAGER.GetShader("5A3E4F5C13115856401F1D1C"/*"FETerrainShader"*/); + } + else if (Entity->HasComponent() && Entity->HasComponent()) { - float dis = 0; - FEAABB box = SCENE.GetTerrain(TerrainList[i])->GetAABB(); - if (box.RayIntersect(ENGINE.GetCamera()->GetPosition(), MouseRayVector, dis)) + PixelAccurateSelectionMaterial->Shader = FEPixelAccurateInstancedSelection; + + FEInstancedComponent& InstancedComponent = Entity->GetComponent(); + for (size_t i = 0; i < InstancedComponent.InstancedElementsData.size(); i++) { - SELECTED.ObjectsUnderMouse.push_back(SCENE.GetTerrain(TerrainList[i])); + FEEntity* EntityWithGameModel = INSTANCED_RENDERING_SYSTEM.GetEntityWithGameModelComponent(InstancedComponent.InstancedElementsData[i]->EntityIDWithGameModelComponent); + if (EntityWithGameModel == nullptr) + continue; + + FEGameModelComponent& GameModelComponent = EntityWithGameModel->GetComponent(); + if (!GameModelComponent.IsVisible()) + continue; + + FEMaterial* RegularMaterial = GameModelComponent.GetGameModel()->Material; + GameModelComponent.GetGameModel()->Material = PixelAccurateSelectionMaterial; + PixelAccurateSelectionMaterial->SetBaseColor(ColorID); + PixelAccurateSelectionMaterial->ClearAllTexturesInfo(); + PixelAccurateSelectionMaterial->SetAlbedoMap(RegularMaterial->GetAlbedoMap()); + PixelAccurateSelectionMaterial->SetAlbedoMap(RegularMaterial->GetAlbedoMap(1), 1); + + FEMaterial* RegularBillboardMaterials = GameModelComponent.GetGameModel()->GetBillboardMaterial(); + GameModelComponent.GetGameModel()->SetBillboardMaterial(PixelAccurateSelectionMaterial); + + RENDERER.RenderGameModelComponentWithInstanced(Entity, nullptr, false, false, i); + + GameModelComponent.GetGameModel()->SetBillboardMaterial(RegularBillboardMaterials); + GameModelComponent.GetGameModel()->Material = RegularMaterial; + PixelAccurateSelectionMaterial->SetAlbedoMap(nullptr); + PixelAccurateSelectionMaterial->SetAlbedoMap(nullptr, 1); } + + PixelAccurateSelectionMaterial->Shader = FEPixelAccurateSelection; } + else if (Entity->HasComponent()) + { + FEVirtualUIComponent& VirtualUIComponent = Entity->GetComponent(); + if (!VirtualUIComponent.IsVisible() || VirtualUIComponent.IsInputActive()) + return; + + PixelAccurateSelectionMaterial->SetBaseColor(ColorID); + PixelAccurateSelectionMaterial->ClearAllTexturesInfo(); + + VIRTUAL_UI_SYSTEM.RenderVirtualUIComponent(Entity, PixelAccurateSelectionMaterial); + + PixelAccurateSelectionMaterial->SetAlbedoMap(nullptr); + PixelAccurateSelectionMaterial->SetAlbedoMap(nullptr, 1); + } + + PixelAccurateSelectionMaterial->ClearAllTexturesInfo(); } -int FEEditorSelectedObject::GetIndexOfObjectUnderMouse(const double MouseX, const double MouseY) +int FEEditorSelectedObject::GetIndexOfObjectUnderMouse(const double MouseX, const double MouseY, FEScene* Scene) { + FESelectionData* CurrentSelectionData = GetSceneData(Scene->GetObjectID()); + if (CurrentSelectionData == nullptr) + return -1; + #ifndef EDITOR_SELECTION_DEBUG_MODE - if (!CheckForSelectionisNeeded) + if (!CurrentSelectionData->CheckForSelectionisNeeded) return -1; #endif - CheckForSelectionisNeeded = false; + CurrentSelectionData->CheckForSelectionisNeeded = false; + + int LocalMouseX = static_cast(MouseX); + int LocalMouseY = static_cast(MouseY); + + FEViewport* CurrentViewport = CAMERA_SYSTEM.GetMainCameraViewport(Scene); + glm::ivec2 ViewportPosition = glm::ivec2(CurrentViewport->GetX(), CurrentViewport->GetY()); + LocalMouseX -= ViewportPosition.x; + LocalMouseY -= ViewportPosition.y; - PixelAccurateSelectionFB->Bind(); - glm::vec4 OriginalClearColor = ENGINE.GetClearColor(); - ENGINE.SetClearColor(glm::vec4(0.0f, 0.0f, 0.0f, 0.0f)); + // If the mouse is out of the viewport, return -1 + if (LocalMouseY < 0) + return -1; + + CurrentSelectionData->PixelAccurateSelectionFB->Bind(); + glm::ivec4 OriginalViewport = RENDERER.GetGLViewport(); + RENDERER.SetGLViewport(0, 0, CurrentSelectionData->PixelAccurateSelectionFB->GetWidth(), CurrentSelectionData->PixelAccurateSelectionFB->GetHeight()); + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); FE_GL_ERROR(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)); - for (size_t i = 0; i < SELECTED.ObjectsUnderMouse.size(); i++) + FEEntity* CurrentCamera = CAMERA_SYSTEM.GetMainCamera(Scene); + + for (size_t i = 0; i < CurrentSelectionData->SceneEntitiesUnderMouse.size(); i++) { #ifdef EDITOR_SELECTION_DEBUG_MODE int r = (i + 1) * 50 & 255; @@ -193,366 +334,407 @@ int FEEditorSelectedObject::GetIndexOfObjectUnderMouse(const double MouseX, cons int g = ((i + 1) >> 8) & 255; int b = ((i + 1) >> 16) & 255; #endif - - if (SELECTED.ObjectsUnderMouse[i]->GetType() == FE_ENTITY) - { - PotentiallySelectedEntity = SCENE.GetEntity(SELECTED.ObjectsUnderMouse[i]->GetObjectID()); - if (!PotentiallySelectedEntity->IsVisible()) - continue; - - for (int j = 0; j < PotentiallySelectedEntity->Prefab->ComponentsCount(); j++) - { - FEMaterial* RegularMaterial = PotentiallySelectedEntity->Prefab->GetComponent(j)->GameModel->Material; - PotentiallySelectedEntity->Prefab->GetComponent(j)->GameModel->Material = PixelAccurateSelectionMaterial; - PixelAccurateSelectionMaterial->SetBaseColor(glm::vec3(static_cast(r) / 255.0f, static_cast(g) / 255.0f, static_cast(b) / 255.0f)); - PixelAccurateSelectionMaterial->ClearAllTexturesInfo(); - PixelAccurateSelectionMaterial->SetAlbedoMap(RegularMaterial->GetAlbedoMap()); - PixelAccurateSelectionMaterial->SetAlbedoMap(RegularMaterial->GetAlbedoMap(1), 1); - - RENDERER.RenderEntity(PotentiallySelectedEntity, ENGINE.GetCamera(), false, j); - - PotentiallySelectedEntity->Prefab->GetComponent(j)->GameModel->Material = RegularMaterial; - } - PixelAccurateSelectionMaterial->SetAlbedoMap(nullptr); - PixelAccurateSelectionMaterial->SetAlbedoMap(nullptr, 1); - } - else if (SELECTED.ObjectsUnderMouse[i]->GetType() == FE_ENTITY_INSTANCED) - { - FEEntityInstanced* PotentiallySelectedEntityInstanced = reinterpret_cast(SCENE.GetEntity((SELECTED.ObjectsUnderMouse[i]->GetObjectID()))); - if (!PotentiallySelectedEntityInstanced->IsVisible()) - continue; - if (InstancedSubObjectsInfo.find(PotentiallySelectedEntityInstanced) == InstancedSubObjectsInfo.end()) - { - for (int j = 0; j < PotentiallySelectedEntityInstanced->Prefab->ComponentsCount(); j++) - { - FEMaterial* RegularMaterial = PotentiallySelectedEntityInstanced->Prefab->GetComponent(j)->GameModel->Material; - PotentiallySelectedEntityInstanced->Prefab->GetComponent(j)->GameModel->Material = PixelAccurateSelectionMaterial; - - PixelAccurateSelectionMaterial->SetBaseColor(glm::vec3(static_cast(r) / 255.0f, static_cast(g) / 255.0f, static_cast(b) / 255.0f)); - PixelAccurateSelectionMaterial->ClearAllTexturesInfo(); - PixelAccurateSelectionMaterial->SetAlbedoMap(RegularMaterial->GetAlbedoMap()); - PixelAccurateSelectionMaterial->SetAlbedoMap(RegularMaterial->GetAlbedoMap(1), 1); - - PixelAccurateSelectionMaterial->Shader = FEPixelAccurateInstancedSelection; - FEMaterial* RegularBillboardMaterials = PotentiallySelectedEntityInstanced->Prefab->GetComponent(j)->GameModel->GetBillboardMaterial(); - PotentiallySelectedEntityInstanced->Prefab->GetComponent(j)->GameModel->SetBillboardMaterial(PixelAccurateSelectionMaterial); - - RENDERER.RenderEntityInstanced(PotentiallySelectedEntityInstanced, ENGINE.GetCamera(), nullptr, false, false, j); - - PixelAccurateSelectionMaterial->Shader = FEPixelAccurateSelection; - PotentiallySelectedEntityInstanced->Prefab->GetComponent(j)->GameModel->SetBillboardMaterial(RegularBillboardMaterials); - PotentiallySelectedEntityInstanced->Prefab->GetComponent(j)->GameModel->Material = RegularMaterial; - - PixelAccurateSelectionMaterial->SetAlbedoMap(nullptr); - PixelAccurateSelectionMaterial->SetAlbedoMap(nullptr, 1); - } - } - } - else if (SELECTED.ObjectsUnderMouse[i]->GetType() == FE_TERRAIN) - { - FETerrain* PotentiallySelectedTerrain = SCENE.GetTerrain(SELECTED.ObjectsUnderMouse[i]->GetObjectID()); - if (PotentiallySelectedTerrain != nullptr) - { - if (!PotentiallySelectedTerrain->IsVisible()) - continue; - - PotentiallySelectedTerrain->Shader = RESOURCE_MANAGER.GetShader("50064D3C4D0B537F0846274F"/*"FESMTerrainShader"*/); - PotentiallySelectedTerrain->Shader->UpdateParameterData("baseColor", glm::vec3(static_cast(r) / 255.0f, static_cast(g) / 255.0f, static_cast(b) / 255.0f)); - RENDERER.RenderTerrain(PotentiallySelectedTerrain, ENGINE.GetCamera()); - PotentiallySelectedTerrain->Shader->UpdateParameterData("baseColor", glm::vec3(1.0f)); - PotentiallySelectedTerrain->Shader = RESOURCE_MANAGER.GetShader("5A3E4F5C13115856401F1D1C"/*"FETerrainShader"*/); - } - } + RenderEntitySelectionColorID(CurrentSelectionData->SceneEntitiesUnderMouse[i], + glm::vec3(static_cast(r) / 255.0f, static_cast(g) / 255.0f, static_cast(b) / 255.0f), + CurrentCamera, CurrentSelectionData); } - int LastColorShiftIndex = static_cast(SELECTED.ObjectsUnderMouse.size() - 1); + int LastColorShiftIndex = static_cast(CurrentSelectionData->SceneEntitiesUnderMouse.size() - 1); - auto it = InstancedSubObjectsInfo.begin(); - while (it != InstancedSubObjectsInfo.end()) + auto InstancedSubObjectIterator = CurrentSelectionData->InstancedSubObjectsInfo.begin(); + while (InstancedSubObjectIterator != CurrentSelectionData->InstancedSubObjectsInfo.end()) { - for (size_t j = 0; j < it->second.size(); j++) + for (size_t j = 0; j < InstancedSubObjectIterator->second.size(); j++) { LastColorShiftIndex++; int r = (LastColorShiftIndex + 1) & 255; int g = ((LastColorShiftIndex + 1) >> 8) & 255; int b = ((LastColorShiftIndex + 1) >> 16) & 255; - static FEEntity* DummyEntity = SCENE.AddEntity(it->first->Prefab, "dummyEntity"); - DummyEntity->SetVisibility(true); - DummyEntity->Prefab = it->first->Prefab; - DummyEntity->Transform = FETransformComponent(it->first->GetTransformedInstancedMatrix(it->second[j])); - - for (int k = 0; k < DummyEntity->Prefab->ComponentsCount(); k++) - { - FEMaterial* RegularMaterial = it->first->Prefab->GetComponent(k)->GameModel->Material; - DummyEntity->Prefab->GetComponent(k)->GameModel->Material = PixelAccurateSelectionMaterial; - PixelAccurateSelectionMaterial->SetBaseColor(glm::vec3(static_cast(r) / 255.0f, static_cast(g) / 255.0f, static_cast(b) / 255.0f)); - PixelAccurateSelectionMaterial->ClearAllTexturesInfo(); - PixelAccurateSelectionMaterial->SetAlbedoMap(RegularMaterial->GetAlbedoMap()); - PixelAccurateSelectionMaterial->SetAlbedoMap(RegularMaterial->GetAlbedoMap(1), 1); - - RENDERER.RenderEntity(DummyEntity, ENGINE.GetCamera(), false, k); + static FEEntity* DummyEntity = Scene->CreateEntity("DummyEntity"); + RESOURCE_MANAGER.SetTag(DummyEntity, EDITOR_RESOURCE_TAG); + if (!DummyEntity->HasComponent()) + DummyEntity->AddComponent(); - it->first->Prefab->GetComponent(k)->GameModel->Material = RegularMaterial; - } - DummyEntity->SetVisibility(false); + FEGameModelComponent& DummyGameModelComponent = DummyEntity->GetComponent(); + FEGameModelComponent& OriginalGameModelComponent = InstancedSubObjectIterator->first->GetComponent(); + + DummyGameModelComponent.SetGameModel(OriginalGameModelComponent.GetGameModel()); + DummyGameModelComponent.SetVisibility(true); + + FEInstancedComponent& InstancedComponent = InstancedSubObjectIterator->first->GetComponent(); + FETransformComponent& DummyTransformComponent = DummyEntity->GetComponent(); + + glm::dvec3 Position, Scale; + glm::dquat Rotation; + GEOMETRY.DecomposeMatrixToTranslationRotationScale(InstancedComponent.GetTransformedInstancedMatrix(InstancedSubObjectIterator->second[j]), Position, Rotation, Scale); + + DummyTransformComponent.SetPosition(Position); + DummyTransformComponent.SetQuaternion(Rotation); + DummyTransformComponent.SetScale(Scale); + + RenderEntitySelectionColorID(DummyEntity, glm::vec3(static_cast(r) / 255.0f, static_cast(g) / 255.0f, static_cast(b) / 255.0f), CurrentCamera, CurrentSelectionData); + + DummyGameModelComponent.SetVisibility(false); } - it++; + InstancedSubObjectIterator++; } - FE_GL_ERROR(glReadPixels(static_cast(MouseX), GLint(ENGINE.GetRenderTargetHeight() - MouseY), 1, 1, GL_RGB, GL_UNSIGNED_BYTE, ColorUnderMouse)); - PixelAccurateSelectionFB->UnBind(); + FETransformComponent& CameraTransformComponent = CurrentCamera->GetComponent(); + FECameraComponent& CameraComponent = CurrentCamera->GetComponent(); - ENGINE.SetClearColor(OriginalClearColor); + FE_GL_ERROR(glReadPixels(static_cast(LocalMouseX), GLint(CameraComponent.GetRenderTargetHeight() - LocalMouseY), 1, 1, GL_RGB, GL_UNSIGNED_BYTE, CurrentSelectionData->ColorUnderMouse)); + CurrentSelectionData->PixelAccurateSelectionFB->UnBind(); + RENDERER.SetGLViewport(OriginalViewport); #ifndef EDITOR_SELECTION_DEBUG_MODE - if (!SELECTED.ObjectsUnderMouse.empty()) + if (!CurrentSelectionData->SceneEntitiesUnderMouse.empty()) { - ColorIndex = 0; - ColorIndex |= static_cast(ColorUnderMouse[2]); - ColorIndex <<= 8; - ColorIndex |= static_cast(ColorUnderMouse[1]); - ColorIndex <<= 8; - ColorIndex |= static_cast(ColorUnderMouse[0]); + CurrentSelectionData->ColorIndex = 0; + CurrentSelectionData->ColorIndex |= static_cast(CurrentSelectionData->ColorUnderMouse[2]); + CurrentSelectionData->ColorIndex <<= 8; + CurrentSelectionData->ColorIndex |= static_cast(CurrentSelectionData->ColorUnderMouse[1]); + CurrentSelectionData->ColorIndex <<= 8; + CurrentSelectionData->ColorIndex |= static_cast(CurrentSelectionData->ColorUnderMouse[0]); - ColorIndex -= 1; + CurrentSelectionData->ColorIndex -= 1; - if (ColorIndex != -1 && ColorIndex >= static_cast(SELECTED.ObjectsUnderMouse.size())) + if (CurrentSelectionData->ColorIndex != -1 && CurrentSelectionData->ColorIndex >= static_cast(CurrentSelectionData->SceneEntitiesUnderMouse.size())) { - ColorIndex -= static_cast(SELECTED.ObjectsUnderMouse.size()); + CurrentSelectionData->ColorIndex -= static_cast(CurrentSelectionData->SceneEntitiesUnderMouse.size()); - const FEEntityInstanced* SelectedSubObjectInInstance = nullptr; - auto it = InstancedSubObjectsInfo.begin(); - while (it != InstancedSubObjectsInfo.end()) + const FEEntity* SelectedSubObjectInInstance = nullptr; + auto InstancedSubObjectIterator = CurrentSelectionData->InstancedSubObjectsInfo.begin(); + while (InstancedSubObjectIterator != CurrentSelectionData->InstancedSubObjectsInfo.end()) { - if (ColorIndex < static_cast(it->second.size())) + if (CurrentSelectionData->ColorIndex < static_cast(InstancedSubObjectIterator->second.size())) { - InstancedSubObjectIndexSelected = it->second[ColorIndex]; - SelectedSubObjectInInstance = it->first; + CurrentSelectionData->InstancedSubObjectIndexSelected = InstancedSubObjectIterator->second[CurrentSelectionData->ColorIndex]; + SelectedSubObjectInInstance = InstancedSubObjectIterator->first; break; } - ColorIndex -= static_cast(it->second.size()); - it++; + CurrentSelectionData->ColorIndex -= static_cast(InstancedSubObjectIterator->second.size()); + InstancedSubObjectIterator++; } if (SelectedSubObjectInInstance != nullptr) { - for (size_t i = 0; i < SELECTED.ObjectsUnderMouse.size(); i++) + for (size_t i = 0; i < CurrentSelectionData->SceneEntitiesUnderMouse.size(); i++) { - if (SELECTED.ObjectsUnderMouse[i]->GetObjectID() == SelectedSubObjectInInstance->GetObjectID()) + if (CurrentSelectionData->SceneEntitiesUnderMouse[i]->GetObjectID() == SelectedSubObjectInInstance->GetObjectID()) { return static_cast(i); } } } } - else if (ColorIndex != -1) + else if (CurrentSelectionData->ColorIndex != -1) { - return ColorIndex; + return CurrentSelectionData->ColorIndex; } } - SELECTED.Clear(); + SELECTED.Clear(Scene); return -1; #else - ColorIndex = 0; - ColorIndex |= int(ColorUnderMouse[2]); - ColorIndex <<= 8; - ColorIndex |= int(ColorUnderMouse[1]); - ColorIndex <<= 8; - ColorIndex |= int(ColorUnderMouse[0]); + CurrentSelectionData->ColorIndex = 0; + CurrentSelectionData->ColorIndex |= int(CurrentSelectionData->ColorUnderMouse[2]); + CurrentSelectionData->ColorIndex <<= 8; + CurrentSelectionData->ColorIndex |= int(CurrentSelectionData->ColorUnderMouse[1]); + CurrentSelectionData->ColorIndex <<= 8; + CurrentSelectionData->ColorIndex |= int(CurrentSelectionData->ColorUnderMouse[0]); - ColorIndex /= 50; - ColorIndex -= 1; + CurrentSelectionData->ColorIndex /= 50; + CurrentSelectionData->ColorIndex -= 1; return -1; #endif } -void FEEditorSelectedObject::OnCameraUpdate() const +void FEEditorSelectedObject::RenderEntityHaloEffectInternal(FEEntity* Entity, glm::vec3 Color, FEEntity* CameraEntity, FESelectionData* CurrentSelectionData) { - HALO_SELECTION_EFFECT.HaloObjectsFb->Bind(); - HALO_SELECTION_EFFECT.HaloMaterial->ClearAllTexturesInfo(); - HALO_SELECTION_EFFECT.HaloMaterial->SetBaseColor(glm::vec3(1.0f, 0.25f, 0.0f)); - FE_GL_ERROR(glViewport(0, 0, RENDERER.SceneToTextureFB->GetWidth(), RENDERER.SceneToTextureFB->GetHeight())); - glm::vec4 OriginalClearColor = ENGINE.GetClearColor(); - ENGINE.SetClearColor(glm::vec4(0.0f, 0.0f, 0.0f, 0.0f)); - //FE_GL_ERROR(glClearColor(0.0f, 0.0f, 0.0f, 0.0f)); - FE_GL_ERROR(glClear(GL_COLOR_BUFFER_BIT)); - - if (Container == nullptr) - { - HALO_SELECTION_EFFECT.HaloObjectsFb->UnBind(); - ENGINE.SetClearColor(OriginalClearColor); - //FE_GL_ERROR(glClearColor(FE_CLEAR_COLOR.x, FE_CLEAR_COLOR.y, FE_CLEAR_COLOR.z, FE_CLEAR_COLOR.w)); - HALO_SELECTION_EFFECT.PostProcess->bActive = true; + if (Entity == nullptr) return; + + HALO_SELECTION_EFFECT.HaloMaterial->SetBaseColor(Color); + + if (Entity->HasComponent()) + { + FEGameModelComponent& GameModelComponent = Entity->GetComponent(); + FEMaterial* RegularMaterial = GameModelComponent.GetGameModel()->Material; + + GameModelComponent.GetGameModel()->Material = HALO_SELECTION_EFFECT.HaloMaterial; + HALO_SELECTION_EFFECT.HaloMaterial->SetAlbedoMap(RegularMaterial->GetAlbedoMap()); + HALO_SELECTION_EFFECT.HaloMaterial->SetAlbedoMap(RegularMaterial->GetAlbedoMap(1), 1); + + if (!Entity->HasComponent()) + { + RENDERER.RenderGameModelComponent(Entity, CameraEntity); + } + else if (Entity->HasComponent()) + { + HALO_SELECTION_EFFECT.HaloMaterial->Shader = HALO_SELECTION_EFFECT.HaloDrawInstancedObjectShader; + + FEMaterial* RegularBillboardMaterial = GameModelComponent.GetGameModel()->GetBillboardMaterial(); + GameModelComponent.GetGameModel()->SetBillboardMaterial(HALO_SELECTION_EFFECT.HaloMaterial); + + RENDERER.RenderGameModelComponentWithInstanced(Entity, CameraEntity); + + GameModelComponent.GetGameModel()->SetBillboardMaterial(RegularBillboardMaterial); + + HALO_SELECTION_EFFECT.HaloMaterial->Shader = HALO_SELECTION_EFFECT.HaloDrawObjectShader; + } + + GameModelComponent.GetGameModel()->Material = RegularMaterial; } - - if (Container->GetType() == FE_ENTITY) + else if (Entity->HasComponent()) + { + FETerrainComponent& TerrainComponent = Entity->GetComponent(); + TerrainComponent.Shader = RESOURCE_MANAGER.GetShader("50064D3C4D0B537F0846274F"/*"FESMTerrainShader"*/); + TerrainComponent.Shader->UpdateUniformData("baseColor", Color); + const float RegularLODLevel = TerrainComponent.GetLODLevel(); + TerrainComponent.SetLODLevel(0.0f); + + RENDERER.RenderTerrainComponent(Entity, CameraEntity); + + TerrainComponent.SetLODLevel(RegularLODLevel); + TerrainComponent.Shader->UpdateUniformData("baseColor", glm::vec3(1.0f)); + TerrainComponent.Shader = RESOURCE_MANAGER.GetShader("5A3E4F5C13115856401F1D1C"/*"FETerrainShader"*/); + } + else if (Entity->HasComponent() && Entity->HasComponent()) { - FEEntity* SelectedEntity = SCENE.GetEntity(Container->GetObjectID()); + HALO_SELECTION_EFFECT.HaloMaterial->Shader = HALO_SELECTION_EFFECT.HaloDrawInstancedObjectShader; - for (int i = 0; i < SelectedEntity->Prefab->ComponentsCount(); i++) + FEInstancedComponent& InstancedComponent = Entity->GetComponent(); + for (size_t i = 0; i < InstancedComponent.InstancedElementsData.size(); i++) { - FEMaterial* RegularMaterial = SelectedEntity->Prefab->GetComponent(i)->GameModel->Material; + FEEntity* EntityWithGameModel = INSTANCED_RENDERING_SYSTEM.GetEntityWithGameModelComponent(InstancedComponent.InstancedElementsData[i]->EntityIDWithGameModelComponent); + if (EntityWithGameModel == nullptr) + continue; - SelectedEntity->Prefab->GetComponent(i)->GameModel->Material = HALO_SELECTION_EFFECT.HaloMaterial; + FEGameModelComponent& GameModelComponent = EntityWithGameModel->GetComponent(); + + FEMaterial* RegularMaterial = GameModelComponent.GetGameModel()->Material; + + GameModelComponent.GetGameModel()->Material = HALO_SELECTION_EFFECT.HaloMaterial; HALO_SELECTION_EFFECT.HaloMaterial->SetAlbedoMap(RegularMaterial->GetAlbedoMap()); HALO_SELECTION_EFFECT.HaloMaterial->SetAlbedoMap(RegularMaterial->GetAlbedoMap(1), 1); - - RENDERER.RenderEntity(SelectedEntity, ENGINE.GetCamera(), false, i); - - SelectedEntity->Prefab->GetComponent(i)->GameModel->Material = RegularMaterial; + + FEMaterial* RegularBillboardMaterial = GameModelComponent.GetGameModel()->GetBillboardMaterial(); + GameModelComponent.GetGameModel()->SetBillboardMaterial(HALO_SELECTION_EFFECT.HaloMaterial); + + RENDERER.RenderGameModelComponentWithInstanced(Entity, nullptr, false, false, i); + + GameModelComponent.GetGameModel()->Material = RegularMaterial; + GameModelComponent.GetGameModel()->SetBillboardMaterial(RegularBillboardMaterial); } + + HALO_SELECTION_EFFECT.HaloMaterial->Shader = HALO_SELECTION_EFFECT.HaloDrawObjectShader; + } + else if (Entity->HasComponent()) + { + FEVirtualUIComponent& VirtualUIComponent = Entity->GetComponent(); + if (!VirtualUIComponent.IsVisible() || VirtualUIComponent.IsInputActive()) + return; + + VIRTUAL_UI_SYSTEM.RenderVirtualUIComponent(Entity, HALO_SELECTION_EFFECT.HaloMaterial); } - else if (Container->GetType() == FE_ENTITY_INSTANCED) + + HALO_SELECTION_EFFECT.HaloMaterial->ClearAllTexturesInfo(); +} + +void FEEditorSelectedObject::OnCameraUpdate() const +{ + auto SceneIterator = PerSceneData.begin(); + while (SceneIterator != PerSceneData.end()) { - FEEntityInstanced* SelectedEntity = reinterpret_cast(SCENE.GetEntity(Container->GetObjectID())); + FESelectionData* CurrentSelectionData = SceneIterator->second; - if (InstancedSubObjectIndexSelected != -1) + FEScene* CurrentScene = SCENE_MANAGER.GetScene(SceneIterator->first); + if (CurrentScene == nullptr) { - static FEEntity* DummyEntity = SCENE.AddEntity(SelectedEntity->Prefab, "dummyEntity"); - DummyEntity->SetVisibility(true); - DummyEntity->Prefab = SelectedEntity->Prefab; - DummyEntity->Transform = FETransformComponent(SelectedEntity->GetTransformedInstancedMatrix(InstancedSubObjectIndexSelected)); + SceneIterator++; + continue; + } - for (int i = 0; i < DummyEntity->Prefab->ComponentsCount(); i++) - { - FEMaterial* RegularMaterial = DummyEntity->Prefab->GetComponent(i)->GameModel->Material; + FEHaloSelectionData* HaloSelectionData = HALO_SELECTION_EFFECT.GetSceneData(CurrentScene->GetObjectID()); + FEEntity* CurrentCamera = CAMERA_SYSTEM.GetMainCamera(CurrentScene); + if (CurrentCamera == nullptr || HaloSelectionData->PostProcess == nullptr) + { + SceneIterator++; + continue; + } - DummyEntity->Prefab->GetComponent(i)->GameModel->Material = HALO_SELECTION_EFFECT.HaloMaterial; + HaloSelectionData->HaloObjectsFB->Bind(); + HALO_SELECTION_EFFECT.HaloMaterial->ClearAllTexturesInfo(); - HALO_SELECTION_EFFECT.HaloMaterial->SetBaseColor(glm::vec3(0.61f, 0.86f, 1.0f)); - HALO_SELECTION_EFFECT.HaloMaterial->SetAlbedoMap(RegularMaterial->GetAlbedoMap()); - HALO_SELECTION_EFFECT.HaloMaterial->SetAlbedoMap(RegularMaterial->GetAlbedoMap(1), 1); + FECameraComponent& CameraComponent = CurrentCamera->GetComponent(); + RENDERER.SetGLViewport(0, 0, CameraComponent.GetRenderTargetWidth(), CameraComponent.GetRenderTargetHeight()); - RENDERER.RenderEntity(DummyEntity, ENGINE.GetCamera(), false, i); + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + FE_GL_ERROR(glClear(GL_COLOR_BUFFER_BIT)); - SelectedEntity->Prefab->GetComponent(i)->GameModel->Material = RegularMaterial; - } + FEEntity* SelectedEntity = CurrentScene->GetEntity(CurrentSelectionData->SelectedEntityID); + if (SelectedEntity == nullptr) + { + HaloSelectionData->HaloObjectsFB->UnBind(); + HaloSelectionData->PostProcess->bActive = true; - DummyEntity->SetVisibility(false); + SceneIterator++; + continue; } - else + + // If selected entity is instanced and in individual select mode. + if (SelectedEntity->HasComponent() && CurrentSelectionData->InstancedSubObjectIndexSelected != -1) { - for (int i = 0; i < SelectedEntity->Prefab->ComponentsCount(); i++) - { - FEMaterial* RegularMaterial = SelectedEntity->Prefab->GetComponent(i)->GameModel->Material; - SelectedEntity->Prefab->GetComponent(i)->GameModel->Material = HALO_SELECTION_EFFECT.HaloMaterial; - HALO_SELECTION_EFFECT.HaloMaterial->SetAlbedoMap(RegularMaterial->GetAlbedoMap()); - HALO_SELECTION_EFFECT.HaloMaterial->SetAlbedoMap(RegularMaterial->GetAlbedoMap(1), 1); + FEGameModelComponent& GameModelComponent = SelectedEntity->GetComponent(); + + if (!CurrentSelectionData->DummyEntity->HasComponent()) + CurrentSelectionData->DummyEntity->AddComponent(); + + FEGameModelComponent& DummyGameModelComponent = CurrentSelectionData->DummyEntity->GetComponent(); + DummyGameModelComponent.SetGameModel(GameModelComponent.GetGameModel()); + DummyGameModelComponent.SetVisibility(true); - HALO_SELECTION_EFFECT.HaloMaterial->Shader = HALO_SELECTION_EFFECT.HaloDrawInstancedObjectShader; - FEMaterial* RegularBillboardMaterial = SelectedEntity->Prefab->GetComponent(i)->GameModel->GetBillboardMaterial(); - SelectedEntity->Prefab->GetComponent(i)->GameModel->SetBillboardMaterial(HALO_SELECTION_EFFECT.HaloMaterial); + FEInstancedComponent& InstancedComponent = SelectedEntity->GetComponent(); + FETransformComponent& DummyTransformComponent = CurrentSelectionData->DummyEntity->GetComponent(); - RENDERER.RenderEntityInstanced(SelectedEntity, ENGINE.GetCamera(), nullptr, false, false, i); + glm::dvec3 Position, Scale; + glm::dquat Rotation; + GEOMETRY.DecomposeMatrixToTranslationRotationScale(InstancedComponent.GetTransformedInstancedMatrix(CurrentSelectionData->InstancedSubObjectIndexSelected), Position, Rotation, Scale); - HALO_SELECTION_EFFECT.HaloMaterial->Shader = HALO_SELECTION_EFFECT.HaloDrawObjectShader; - SelectedEntity->Prefab->GetComponent(i)->GameModel->SetBillboardMaterial(RegularBillboardMaterial); - SelectedEntity->Prefab->GetComponent(i)->GameModel->Material = RegularMaterial; + DummyTransformComponent.SetPosition(Position); + DummyTransformComponent.SetQuaternion(Rotation); + DummyTransformComponent.SetScale(Scale); + + SELECTED.RenderEntityHaloEffectInternal(CurrentSelectionData->DummyEntity, glm::vec3(0.61f, 0.86f, 1.0f), CurrentCamera, CurrentSelectionData); + + DummyGameModelComponent.SetVisibility(false); + } + else + { + SELECTED.RenderEntityHaloEffectInternal(SelectedEntity, glm::vec3(1.0f, 0.25f, 0.0f), CurrentCamera, CurrentSelectionData); + FENaiveSceneGraphNode* SelectedEntityNode = CurrentScene->SceneGraph.GetNodeByEntityID(SelectedEntity->GetObjectID()); + std::vector AllChildren = SelectedEntityNode->GetRecursiveChildren(); + + for (size_t i = 0; i < AllChildren.size(); i++) + { + FEEntity* CurrentEntity = AllChildren[i]->GetEntity(); + SELECTED.RenderEntityHaloEffectInternal(CurrentEntity, glm::vec3(0.61f, 0.86f, 1.0f), CurrentCamera, CurrentSelectionData); } } - } - else if (Container->GetType() == FE_TERRAIN) - { - FETerrain* SelectedTerrain = SCENE.GetTerrain(Container->GetObjectID()); - - SelectedTerrain->Shader = RESOURCE_MANAGER.GetShader("50064D3C4D0B537F0846274F"/*"FESMTerrainShader"*/); - SelectedTerrain->Shader->UpdateParameterData("baseColor", glm::vec3(1.0f, 0.25f, 0.0f)); - const float RegularLODLevel = SelectedTerrain->GetLODLevel(); - SelectedTerrain->SetLODLevel(0.0f); - RENDERER.RenderTerrain(SelectedTerrain, ENGINE.GetCamera()); - SelectedTerrain->SetLODLevel(RegularLODLevel); - SelectedTerrain->Shader->UpdateParameterData("baseColor", glm::vec3(1.0f)); - SelectedTerrain->Shader = RESOURCE_MANAGER.GetShader("5A3E4F5C13115856401F1D1C"/*"FETerrainShader"*/); - } - HALO_SELECTION_EFFECT.HaloObjectsFb->UnBind(); - ENGINE.SetClearColor(OriginalClearColor); - HALO_SELECTION_EFFECT.PostProcess->bActive = true; + HaloSelectionData->HaloObjectsFB->UnBind(); + HaloSelectionData->PostProcess->bActive = true; + + SceneIterator++; + } } -int FEEditorSelectedObject::DebugGetLastColorIndex() const +int FEEditorSelectedObject::DebugGetLastColorIndex(FEScene* Scene) { - return ColorIndex; + FESelectionData* CurrentSelectionData = GetSceneData(Scene->GetObjectID()); + if (CurrentSelectionData == nullptr) + return -1; + + return CurrentSelectionData->ColorIndex; } -void FEEditorSelectedObject::SetSelectedByIndex(const size_t Index) +void FEEditorSelectedObject::SetSelectedByIndex(const size_t Index, FEScene* Scene) { - if (Index < 0 || Index >= ObjectsUnderMouse.size()) + FESelectionData* CurrentSelectionData = GetSceneData(Scene->GetObjectID()); + if (CurrentSelectionData == nullptr) + return; + + if (Index < 0 || Index >= CurrentSelectionData->SceneEntitiesUnderMouse.size()) return; - if (Container != nullptr) + FEEntity* CurrentlySelectedEntity = Scene->GetEntity(CurrentSelectionData->SelectedEntityID); + if (CurrentlySelectedEntity != nullptr) { - if (SCENE.GetEntityInstanced(Container->GetObjectID()) != nullptr) + if (CurrentlySelectedEntity->HasComponent()) { - if (ObjectsUnderMouse[Index]->GetObjectID() != Container->GetObjectID()) + if (CurrentSelectionData->SceneEntitiesUnderMouse[Index]->GetObjectID() != CurrentlySelectedEntity->GetObjectID()) { - SCENE.GetEntityInstanced(Container->GetObjectID())->SetSelectMode(false); - InstancedSubObjectIndexSelected = -1; + INSTANCED_RENDERING_SYSTEM.SetIndividualSelectMode(CurrentlySelectedEntity, false); + CurrentSelectionData->InstancedSubObjectIndexSelected = -1; } } } - Container = ObjectsUnderMouse[Index]; - if (OnUpdateFunc != nullptr) - OnUpdateFunc(); + CurrentSelectionData->SelectedEntityID = CurrentSelectionData->SceneEntitiesUnderMouse[Index]->GetObjectID(); + if (OnUpdateFunction != nullptr) + OnUpdateFunction(Scene); } -FEEntity* FEEditorSelectedObject::GetEntity() const +void FEEditorSelectedObject::ClearAllSceneData() { - if (Container == nullptr) - return nullptr; + auto PerSceneIterator = PerSceneData.begin(); + while (PerSceneIterator != PerSceneData.end()) + { + delete PerSceneIterator->second; + PerSceneIterator++; + } + PerSceneData.clear(); +} - if (Container->GetType() == FE_ENTITY || Container->GetType() == FE_ENTITY_INSTANCED) +void FEEditorSelectedObject::ClearSceneData(const std::string& SceneID) +{ + auto FoundSceneData = PerSceneData.find(SceneID); + if (FoundSceneData != PerSceneData.end()) { - return SCENE.GetEntity(Container->GetObjectID()); + delete FoundSceneData->second; + PerSceneData.erase(FoundSceneData); } - - return nullptr; } -FELight* FEEditorSelectedObject::GetLight() const +void FEEditorSelectedObject::AddSceneData(const std::string& SceneID) { - if (Container == nullptr) - return nullptr; + FEScene* CurrentScene = SCENE_MANAGER.GetScene(SceneID); + if (CurrentScene == nullptr) + return; + + if (PerSceneData.find(SceneID) != PerSceneData.end()) + return; + + FEEntity* MainCamera = CAMERA_SYSTEM.GetMainCamera(CurrentScene); + if (MainCamera == nullptr) + return; + + PerSceneData[SceneID] = new FESelectionData(); + PerSceneData[SceneID]->SceneID = SceneID; - if (Container->GetType() == FE_DIRECTIONAL_LIGHT || Container->GetType() == FE_SPOT_LIGHT || Container->GetType() == FE_POINT_LIGHT) + FETransformComponent& CameraTransformComponent = MainCamera->GetComponent(); + FECameraComponent& CameraComponent = MainCamera->GetComponent(); + + PerSceneData[SceneID]->PixelAccurateSelectionFB = RESOURCE_MANAGER.CreateFramebuffer(FE_COLOR_ATTACHMENT | FE_DEPTH_ATTACHMENT, CameraComponent.GetRenderTargetWidth(), CameraComponent.GetRenderTargetHeight()); + delete PerSceneData[SceneID]->PixelAccurateSelectionFB->GetColorAttachment(); + PerSceneData[SceneID]->PixelAccurateSelectionFB->SetColorAttachment(RESOURCE_MANAGER.CreateTexture(GL_RGB, GL_RGB, CameraComponent.GetRenderTargetWidth(), CameraComponent.GetRenderTargetHeight())); + + if (CurrentScene->GetEntityByName("Editor_Selection_Dummy_Entity").empty()) { - return SCENE.GetLight(Container->GetObjectID()); + PerSceneData[SceneID]->DummyEntity = CurrentScene->CreateEntity("Editor_Selection_Dummy_Entity"); + RESOURCE_MANAGER.SetTag(PerSceneData[SceneID]->DummyEntity, EDITOR_RESOURCE_TAG); } - return nullptr; + HALO_SELECTION_EFFECT.AddSceneData(SceneID); } -FETerrain* FEEditorSelectedObject::GetTerrain() const +FESelectionData* FEEditorSelectedObject::GetSceneData(const std::string& SceneID) { - if (Container == nullptr) - return nullptr; - - if (Container->GetType() == FE_TERRAIN) + auto FoundScene = PerSceneData.find(SceneID); + if (FoundScene != PerSceneData.end()) { - return SCENE.GetTerrain(Container->GetObjectID()); + return FoundScene->second; } return nullptr; } -//template -//T* FEEditorSelectedObject::getSelected(FEObjectType type) -//{ -// if (container == nullptr) -// return nullptr; -// -// if (type == FE_ENTITY || type == FE_ENTITY_INSTANCED) -// { -// return SCENE.getEntity(container->getObjectID()); -// } -// -// return nullptr; -//} \ No newline at end of file +void FEEditorSelectedObject::ClearAll() +{ + SELECTED.ClearAllSceneData(); +} \ No newline at end of file diff --git a/FEEditorSelectedObject.h b/FEEditorSelectedObject.h index a7ad793..59e5398 100644 --- a/FEEditorSelectedObject.h +++ b/FEEditorSelectedObject.h @@ -5,67 +5,82 @@ using namespace FocalEngine; //#define EDITOR_SELECTION_DEBUG_MODE -class FEEditor; +class FESelectionData +{ + friend class FEEditor; + friend class FEEditorSelectedObject; + friend class GizmoManager; + friend class FEEditorInspectorWindow; + + std::string SceneID = ""; +public: + FEFramebuffer* PixelAccurateSelectionFB = nullptr; + + std::vector SceneEntitiesUnderMouse; + FEEntity* PotentiallySelectedEntity = nullptr; + + std::string SelectedEntityID = ""; + FEEntity* DummyEntity = nullptr; + + bool CheckForSelectionisNeeded = false; + + std::unordered_map> InstancedSubObjectsInfo; + int InstancedSubObjectIndexSelected = -1; + + unsigned char* ColorUnderMouse = new unsigned char[3]; + int ColorIndex = -1; + + ~FESelectionData() + { + delete PixelAccurateSelectionFB; + delete[] ColorUnderMouse; + } +}; class FEEditorSelectedObject { - friend FEEditor; + friend class FEEditor; + friend class GizmoManager; + friend class FEEditorInspectorWindow; + friend class FEEditorSceneWindow; + SINGLETON_PRIVATE_PART(FEEditorSelectedObject) public: SINGLETON_PUBLIC_PART(FEEditorSelectedObject) void InitializeResources(); - void ReInitializeResources(); - void SetOnUpdateFunc(void(*Func)()); - - FEObject* GetSelected() const; + void UpdateResources(FEScene* Scene); + void SetOnUpdateFunction(std::function Func); - FEEntity* GetEntity() const; - FETerrain* GetTerrain() const; - FELight* GetLight() const; + FEEntity* GetSelected(FEScene* Scene); - /*template - T* getSelected(FEObjectType type);*/ + void SetSelected(FEEntity* SelectedObject); + void Clear(FEScene* Scene); + void ClearAll(); - bool GetDirtyFlag() const; - void SetDirtyFlag(bool NewValue); + void DetermineEntityUnderMouse(double MouseX, double MouseY, FEScene* Scene); + int GetIndexOfObjectUnderMouse(double MouseX, double MouseY, FEScene* Scene); + void SetSelectedByIndex(size_t Index, FEScene* Scene); - void SetSelected(FEObject* SelectedObject); - void Clear(); - - glm::dvec3 MouseRay(double MouseX, double MouseY) const; - void DetermineEntityUnderMouse(double MouseX, double MouseY); - std::vector ObjectsUnderMouse; + void OnCameraUpdate() const; - bool CheckForSelectionisNeeded = false; - int GetIndexOfObjectUnderMouse(double MouseX, double MouseY); + FESelectionData* GetSceneData(const std::string& SceneID); +private: + FEShader* FEPixelAccurateInstancedSelection = nullptr; + FEShader* FEPixelAccurateSelection = nullptr; + FEMaterial* PixelAccurateSelectionMaterial = nullptr; - void OnCameraUpdate() const; + std::function OnUpdateFunction = nullptr; - int DebugGetLastColorIndex() const; - std::unordered_map> InstancedSubObjectsInfo; - int InstancedSubObjectIndexSelected = -1; - void SetSelectedByIndex(size_t Index); + int DebugGetLastColorIndex(FEScene* Scene); - FEShader* FEPixelAccurateInstancedSelection = nullptr; - FEShader* FEPixelAccurateSelection = nullptr; -private: - FEObject* Container = nullptr; - - bool bDirtyFlag = false; + std::unordered_map PerSceneData; + void ClearAllSceneData(); + void ClearSceneData(const std::string& SceneID); + void AddSceneData(const std::string& SceneID); - void(*OnUpdateFunc)() = nullptr; -#ifdef EDITOR_SELECTION_DEBUG_MODE -public: -#endif - unsigned char* ColorUnderMouse = new unsigned char[3]; - FEFramebuffer* PixelAccurateSelectionFB; - int ColorIndex = -1; -#ifdef EDITOR_SELECTION_DEBUG_MODE -private: -#endif - FEEntity* PotentiallySelectedEntity = nullptr; - FEMaterial* PixelAccurateSelectionMaterial = nullptr; + void RenderEntitySelectionColorID(FEEntity* Entity, glm::vec3 ColorID, FEEntity* CameraEntity, FESelectionData* CurrentSelectionData); + void RenderEntityHaloEffectInternal(FEEntity* Entity, glm::vec3 Color, FEEntity* CameraEntity, FESelectionData* CurrentSelectionData); }; -#define SELECTED FEEditorSelectedObject::getInstance() \ No newline at end of file +#define SELECTED FEEditorSelectedObject::GetInstance() \ No newline at end of file diff --git a/FEEditorSubWindows/debugTextureViewWindow.h b/FEEditorSubWindows/debugTextureViewWindow.h deleted file mode 100644 index b142be5..0000000 --- a/FEEditorSubWindows/debugTextureViewWindow.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "prefabEditorWindow.h" - -class debugTextureViewWindow : public FEImGuiWindow -{ - ImGuiButton* CloseButton = nullptr; - std::function TextureToView; -public: - debugTextureViewWindow(std::function Func); - ~debugTextureViewWindow(); - - void Render() override; -}; \ No newline at end of file diff --git a/FEEditorSubWindows/gyzmosSettingsWindow.h b/FEEditorSubWindows/gyzmosSettingsWindow.h deleted file mode 100644 index 92029f8..0000000 --- a/FEEditorSubWindows/gyzmosSettingsWindow.h +++ /dev/null @@ -1,106 +0,0 @@ -#pragma once - -#include "shaderEditorWindow.h" - -class gyzmosSettingsWindow : public FEImGuiWindow -{ - ImGuiImageButton* TransformationGizmoButton = nullptr; - ImGuiImageButton* ScaleGizmoButton = nullptr; - ImGuiImageButton* RotateGizmoButton = nullptr; -public: - gyzmosSettingsWindow() - { - Flags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoScrollbar; - } - - ~gyzmosSettingsWindow() override - { - delete TransformationGizmoButton; - delete ScaleGizmoButton; - delete RotateGizmoButton; - } - - void Show() override - { - const std::string TempCaption = "##GizmosSettingsWindow"; - strcpy_s(Caption, TempCaption.size() + 1, TempCaption.c_str()); - Size = ImVec2(146.0f, 48.0f); - Position = ImVec2(FEngine::getInstance().GetWindowWidth() / 2.0f - 150.0f / 2.0f, 10.0f); - FEImGuiWindow::Show(); - - if (TransformationGizmoButton == nullptr) - TransformationGizmoButton = new ImGuiImageButton(GIZMO_MANAGER.TransformationGizmoIcon); - - if (ScaleGizmoButton == nullptr) - ScaleGizmoButton = new ImGuiImageButton(GIZMO_MANAGER.ScaleGizmoIcon); - - if (RotateGizmoButton == nullptr) - RotateGizmoButton = new ImGuiImageButton(GIZMO_MANAGER.RotateGizmoIcon); - - float CurrentX = 5.0f; - TransformationGizmoButton->SetPosition(ImVec2(CurrentX, 5.0f)); - CurrentX += 32.0f + 16.0f; - ScaleGizmoButton->SetPosition(ImVec2(CurrentX, 5.0f)); - CurrentX += 32.0f + 16.0f; - RotateGizmoButton->SetPosition(ImVec2(CurrentX, 5.0f)); - } - - void Render() override - { - FEImGuiWindow::Render(); - - if (!IsVisible()) - return; - - GIZMO_MANAGER.GizmosState == TRANSFORM_GIZMOS ? SetSelectedStyle(TransformationGizmoButton) : SetDefaultStyle(TransformationGizmoButton); - ImGui::PushID(0); - TransformationGizmoButton->Render(); - if (TransformationGizmoButton->IsClicked()) - { - if (GIZMO_MANAGER.GizmosState != TRANSFORM_GIZMOS) - { - GIZMO_MANAGER.UpdateGizmoState(TRANSFORM_GIZMOS); - ImGui::PopID(); - FEImGuiWindow::OnRenderEnd(); - return; - } - } - ImGui::PopID(); - ShowToolTip("Translate objects. key = shift"); - - GIZMO_MANAGER.GizmosState == SCALE_GIZMOS ? SetSelectedStyle(ScaleGizmoButton) : SetDefaultStyle(ScaleGizmoButton); - ImGui::PushID(1); - ScaleGizmoButton->Render(); - if (ScaleGizmoButton->IsClicked()) - { - if (GIZMO_MANAGER.GizmosState != SCALE_GIZMOS) - { - GIZMO_MANAGER.UpdateGizmoState(SCALE_GIZMOS); - ImGui::PopID(); - FEImGuiWindow::OnRenderEnd(); - return; - } - } - ImGui::PopID(); - ShowToolTip("Scale objects. key = shift"); - - GIZMO_MANAGER.GizmosState == ROTATE_GIZMOS ? SetSelectedStyle(RotateGizmoButton) : SetDefaultStyle(RotateGizmoButton); - ImGui::PushID(2); - RotateGizmoButton->Render(); - if (RotateGizmoButton->IsClicked()) - { - if (GIZMO_MANAGER.GizmosState != ROTATE_GIZMOS) - { - GIZMO_MANAGER.UpdateGizmoState(ROTATE_GIZMOS); - ImGui::PopID(); - FEImGuiWindow::OnRenderEnd(); - return; - } - } - ImGui::PopID(); - ShowToolTip("Rotate objects. key = shift"); - - FEImGuiWindow::OnRenderEnd(); - } -}; -static gyzmosSettingsWindow GyzmosSettingsWindowObject; \ No newline at end of file diff --git a/FEEditorSubWindows/prefabEditorWindow.cpp b/FEEditorSubWindows/prefabEditorWindow.cpp deleted file mode 100644 index 953e328..0000000 --- a/FEEditorSubWindows/prefabEditorWindow.cpp +++ /dev/null @@ -1,247 +0,0 @@ -#include "prefabEditorWindow.h" - -PrefabEditorWindow* PrefabEditorWindow::Instance = nullptr; -FEPrefab* PrefabEditorWindow::ObjToWorkWith = nullptr; - -bool PrefabEditorWindow::AddGameModelTargetCallBack(FEObject* Object, void** EntityPointer) -{ - if (Object == nullptr) - return false; - - FEGameModel* NewGameModel = reinterpret_cast(Object); - ObjToWorkWith->AddComponent(NewGameModel); - - return true; -} - -void PrefabEditorWindow::ShowTransformConfiguration(FETransformComponent* Transform, const int Index) -{ - // ********************* POSITION ********************* - glm::vec3 position = Transform->GetPosition(); - ImGui::Text("Position : "); - ImGui::SameLine(); - ImGui::SetNextItemWidth(50); - ImGui::DragFloat((std::string("##X pos : ") + std::to_string(Index)).c_str(), &position[0], 0.1f); - ShowToolTip("X position"); - - ImGui::SameLine(); - ImGui::SetNextItemWidth(50); - ImGui::DragFloat((std::string("##Y pos : ") + std::to_string(Index)).c_str(), &position[1], 0.1f); - ShowToolTip("Y position"); - - ImGui::SameLine(); - ImGui::SetNextItemWidth(50); - ImGui::DragFloat((std::string("##Z pos : ") + std::to_string(Index)).c_str(), &position[2], 0.1f); - ShowToolTip("Z position"); - Transform->SetPosition(position); - - // ********************* ROTATION ********************* - glm::vec3 rotation = Transform->GetRotation(); - ImGui::Text("Rotation : "); - ImGui::SameLine(); - ImGui::SetNextItemWidth(50); - ImGui::DragFloat((std::string("##X rot : ") + std::to_string(Index)).c_str(), &rotation[0], 0.1f, -360.0f, 360.0f); - ShowToolTip("X rotation"); - - ImGui::SameLine(); - ImGui::SetNextItemWidth(50); - ImGui::DragFloat((std::string("##Y rot : ") + std::to_string(Index)).c_str(), &rotation[1], 0.1f, -360.0f, 360.0f); - ShowToolTip("Y rotation"); - - ImGui::SameLine(); - ImGui::SetNextItemWidth(50); - ImGui::DragFloat((std::string("##Z rot : ") + std::to_string(Index)).c_str(), &rotation[2], 0.1f, -360.0f, 360.0f); - ShowToolTip("Z rotation"); - Transform->SetRotation(rotation); - - // ********************* SCALE ********************* - bool bUniformScaling = Transform->IsUniformScalingSet(); - ImGui::Checkbox("Uniform scaling", &bUniformScaling); - Transform->SetUniformScaling(bUniformScaling); - - glm::vec3 scale = Transform->GetScale(); - ImGui::Text("Scale : "); - ImGui::SameLine(); - ImGui::SetNextItemWidth(50); - ImGui::DragFloat((std::string("##X scale : ") + std::to_string(Index)).c_str(), &scale[0], 0.01f, 0.01f, 1000.0f); - ShowToolTip("X scale"); - - ImGui::SameLine(); - ImGui::SetNextItemWidth(50); - ImGui::DragFloat((std::string("##Y scale : ") + std::to_string(Index)).c_str(), &scale[1], 0.01f, 0.01f, 1000.0f); - ShowToolTip("Y scale"); - - ImGui::SameLine(); - ImGui::SetNextItemWidth(50); - ImGui::DragFloat((std::string("##Z scale : ") + std::to_string(Index)).c_str(), &scale[2], 0.01f, 0.01f, 1000.0f); - ShowToolTip("Z scale"); - - glm::vec3 OldScale = Transform->GetScale(); - Transform->ChangeXScaleBy(scale[0] - OldScale[0]); - Transform->ChangeYScaleBy(scale[1] - OldScale[1]); - Transform->ChangeZScaleBy(scale[2] - OldScale[2]); -} - -void PrefabEditorWindow::AddNewGameModelCallBack(const std::vector SelectionsResult) -{ - for (int i = 0; i < SelectionsResult.size(); i++) - { - if (SelectionsResult[i]->GetType() == FE_GAMEMODEL) - ObjToWorkWith->AddComponent(reinterpret_cast(SelectionsResult[i])); - } -} - -PrefabEditorWindow::PrefabEditorWindow() -{ - const std::string TempCaption = "Edit Prefab"; - strcpy_s(Caption, TempCaption.size() + 1, TempCaption.c_str()); - - CloseButton = new ImGuiButton("Close"); - CloseButton->SetSize(ImVec2(140, 24)); - CloseButton->SetPosition(ImVec2(800.0 / 2.0 - 140.0 / 2.0, 800.0 - 35.0)); - - //addGameModelTarget = DRAG_AND_DROP_MANAGER.addTarget(FE_GAMEMODEL, addGameModelTargetCallBack, nullptr, "Drop to add Game model"); -} - -PrefabEditorWindow::~PrefabEditorWindow() -{ - delete CloseButton; -} - -void PrefabEditorWindow::Show(FEPrefab* Prefab) -{ - Size = ImVec2(800, 800); - Position = ImVec2(FEngine::getInstance().GetWindowWidth() / 2 - Size.x / 2, FEngine::getInstance().GetWindowHeight() / 2 - Size.y / 2); - - Flags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoCollapse; - - ObjToWorkWith = Prefab; - - FEImGuiWindow::Show(); -} - -void PrefabEditorWindow::Render() -{ - FEImGuiWindow::Render(); - - if (!IsVisible()) - return; - - if (ImGui::BeginTabBar("##prefabSettings", ImGuiTabBarFlags_None)) - { - if (ImGui::BeginTabItem("Game Models")) - { - static bool ContextMenuOpened = false; - - ImGui::BeginChildFrame(ImGui::GetID("GameModels ListBox Child"), ImVec2(ImGui::GetContentRegionAvail().x - 10.0f, 500.0f), ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse); - bool bListBoxHovered = false; - if (ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows)) - { - bListBoxHovered = true; - //addGameModelTarget->setActive(true); - } - - static bool bOpenContextMenu = false; - if (ImGui::IsMouseClicked(1)) - { - if (bListBoxHovered) - { - bOpenContextMenu = true; - } - } - - if (ImGui::BeginListBox("##GameModels ListBox", ImVec2(ImGui::GetContentRegionAvail().x - 10.0f, 500.0f))) - { - ImGui::PushFont(ImGui::GetIO().Fonts->Fonts[1]); - - for (int i = 0; i < ObjToWorkWith->ComponentsCount(); i++) - { - FEGameModel* GameModel = ObjToWorkWith->GetComponent(i)->GameModel; - if (GameModel == nullptr) - break; - - ImVec2 PostionBeforeDraw = ImGui::GetCursorPos(); - - const ImVec2 TextSize = ImGui::CalcTextSize(GameModel->GetName().c_str()); - ImGui::SetCursorPos(PostionBeforeDraw + ImVec2(ImGui::GetContentRegionAvail().x / 2.0f - TextSize.x / 2.0f, 16)); - ImGui::Text(GameModel->GetName().c_str()); - ImGui::SetCursorPos(PostionBeforeDraw); - - ImGui::PushID(i); - if (ImGui::Selectable("##item", SelectedGameModel == i ? true : false, ImGuiSelectableFlags_None, ImVec2(ImGui::GetContentRegionAvail().x - 0, 64))) - { - SelectedGameModel = i; - } - ImGui::PopID(); - - if (ImGui::IsItemHovered()) - HoveredGameModelItem = i; - - ImGui::SetCursorPos(PostionBeforeDraw); - ImColor ImageTint = ImGui::IsItemHovered() ? ImColor(1.0f, 1.0f, 1.0f, 0.5f) : ImColor(1.0f, 1.0f, 1.0f, 1.0f); - FETexture* PreviewTexture = PREVIEW_MANAGER.GetPreview(GameModel->GetObjectID()); - ImGui::Image((void*)static_cast(PreviewTexture->GetTextureID()), ImVec2(64, 64), ImVec2(0.0f, 1.0f), ImVec2(1.0f, 0.0f), ImageTint); - - - ShowTransformConfiguration(&ObjToWorkWith->GetComponent(i)->Transform, i); - } - - ImGui::PopFont(); - ImGui::EndListBox(); - } - - - ImGui::EndChildFrame(); - ImGui::EndTabItem(); - - if (bOpenContextMenu) - { - bOpenContextMenu = false; - ImGui::OpenPopup("##layers_listBox_context_menu"); - } - - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(15, 15)); - if (ImGui::BeginPopup("##layers_listBox_context_menu")) - { - ContextMenuOpened = true; - - if (ImGui::MenuItem("Add game model...")) - { - SelectFeObjectPopUp::getInstance().Show(FE_GAMEMODEL, AddNewGameModelCallBack); - } - - if (HoveredGameModelItem != -1) - { - FEGameModel* GameModel = ObjToWorkWith->GetComponent(HoveredGameModelItem)->GameModel; - if (GameModel != nullptr) - { - ImGui::Separator(); - const std::string LayerName = GameModel->GetName(); - ImGui::Text((std::string("Actions with ") + LayerName).c_str()); - ImGui::Separator(); - - if (ImGui::MenuItem("Remove")) - { - ObjToWorkWith->RemoveComponent(HoveredGameModelItem); - } - } - } - - ImGui::EndPopup(); - } - ImGui::PopStyleVar(); - - if (!ContextMenuOpened) - HoveredGameModelItem = -1; - - ContextMenuOpened = false; - } - ImGui::EndTabBar(); - } - - CloseButton->Render(); - if (CloseButton->IsClicked()) - Close(); - - FEImGuiWindow::OnRenderEnd(); -} \ No newline at end of file diff --git a/FEEditorSubWindows/prefabEditorWindow.h b/FEEditorSubWindows/prefabEditorWindow.h deleted file mode 100644 index 719c1bf..0000000 --- a/FEEditorSubWindows/prefabEditorWindow.h +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once - -#include "combineChannelsToTexturePopUp.h" - -class PrefabEditorWindow : public FEImGuiWindow -{ - SINGLETON_PRIVATE_PART(PrefabEditorWindow) - - // ************** Drag&Drop ************** - DragAndDropTarget* AddGameModelTarget = nullptr; - static bool AddGameModelTargetCallBack(FEObject* Object, void** EntityPointer); - // ************** Drag&Drop END ************** - - ImGuiButton* CloseButton = nullptr; - - static FEPrefab* ObjToWorkWith; - int HoveredGameModelItem = -1; - int SelectedGameModel = -1; - - void ShowTransformConfiguration(FETransformComponent* Transform, int Index); - static void AddNewGameModelCallBack(std::vector SelectionsResult); -public: - SINGLETON_PUBLIC_PART(PrefabEditorWindow) - - void Show(FEPrefab* Prefab); - void Render() override; -}; \ No newline at end of file diff --git a/FEEditorSubWindows/projectWasModifiedPopUp.h b/FEEditorSubWindows/projectWasModifiedPopUp.h deleted file mode 100644 index 2147968..0000000 --- a/FEEditorSubWindows/projectWasModifiedPopUp.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include "debugTextureViewWindow.h" - -class projectWasModifiedPopUp : public ImGuiModalPopup -{ - FEProject* ObjToWorkWith; - bool bShouldTerminate = false; -public: - SINGLETON_PUBLIC_PART(projectWasModifiedPopUp) - - void Show(FEProject* Project, bool FullyCloseApplication); - void Render() override; - -private: - SINGLETON_PRIVATE_PART(projectWasModifiedPopUp) -}; \ No newline at end of file diff --git a/FEEditorSubWindows/renamePopups.h b/FEEditorSubWindows/renamePopups.h deleted file mode 100644 index 0e9efd6..0000000 --- a/FEEditorSubWindows/renamePopups.h +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -#include "deletePopups.h" - -class renameFailedPopUp : public ImGuiModalPopup -{ - ImGuiButton* OkButton = nullptr; -public: - SINGLETON_PUBLIC_PART(renameFailedPopUp) - void Render() override; -private: - SINGLETON_PRIVATE_PART(renameFailedPopUp) -}; - -class renamePopUp : public ImGuiModalPopup -{ - FEObject* ObjToWorkWith; - char NewName[512]; -public: - SINGLETON_PUBLIC_PART(renamePopUp) - - void Show(FEObject* ObjToWorkWith); - void Render() override; -private: - SINGLETON_PRIVATE_PART(renamePopUp) -}; \ No newline at end of file diff --git a/FEEditorVirtualFileSystem.cpp b/FEEditorVirtualFileSystem.cpp index a23e1d4..0657d8d 100644 --- a/FEEditorVirtualFileSystem.cpp +++ b/FEEditorVirtualFileSystem.cpp @@ -43,7 +43,7 @@ bool FEVFSDirectory::HasFile(const FEObject* File) { if (File == nullptr) { - LOG.Add("file is nullptr in function FEVFSDirectory::hasFile.", "FE_LOG_GENERAL", FE_LOG_ERROR); + LOG.Add("File is nullptr in function FEVFSDirectory::HasFile.", "FE_VIRTUAL_FILE_SYSTEM", FE_LOG_ERROR); return false; } @@ -114,7 +114,7 @@ bool FEVFSDirectory::DeleteFile(const FEObject* File) { if (File == nullptr) { - LOG.Add("file is nullptr in function FEVFSDirectory::deleteFile.", "FE_LOG_GENERAL", FE_LOG_ERROR); + LOG.Add("File is nullptr in function FEVFSDirectory::deleteFile.", "FE_VIRTUAL_FILE_SYSTEM", FE_LOG_ERROR); return false; } @@ -134,7 +134,7 @@ bool FEVFSDirectory::AddFile(FEObject* File) { if (File == nullptr) { - LOG.Add("file is nullptr in function FEVFSDirectory::addFile.", "FE_LOG_GENERAL", FE_LOG_ERROR); + LOG.Add("File is nullptr in function FEVFSDirectory::addFile.", "FE_VIRTUAL_FILE_SYSTEM", FE_LOG_ERROR); return false; } @@ -152,7 +152,6 @@ void FEVFSDirectory::SetReadOnly(const bool NewValue) bReadOnly = NewValue; } -FEVirtualFileSystem* FEVirtualFileSystem::Instance = nullptr; FEVirtualFileSystem::FEVirtualFileSystem() { Root = new FEVFSDirectory(); @@ -258,7 +257,7 @@ bool FEVirtualFileSystem::CreateFile(FEObject* Data, const std::string Path) { if (Data == nullptr) { - LOG.Add("data is nullptr in function FEVirtualFileSystem::createFile.", "FE_LOG_GENERAL", FE_LOG_ERROR); + LOG.Add("Data is nullptr in function FEVirtualFileSystem::CreateFile.", "FE_VIRTUAL_FILE_SYSTEM", FE_LOG_ERROR); return false; } @@ -267,21 +266,29 @@ bool FEVirtualFileSystem::CreateFile(FEObject* Data, const std::string Path) Data->GetType() != FE_MESH && Data->GetType() != FE_MATERIAL && Data->GetType() != FE_GAMEMODEL && - Data->GetType() != FE_PREFAB) + Data->GetType() != FE_PREFAB && + Data->GetType() != FE_SCENE && + Data->GetType() != FE_ASSET_PACKAGE && + Data->GetType() != FE_NATIVE_SCRIPT_MODULE) { - LOG.Add("data type is not supported in function FEVirtualFileSystem::createFile.", "FE_LOG_GENERAL", FE_LOG_ERROR); + LOG.Add("Data type is not supported in function FEVirtualFileSystem::CreateFile.", "FE_VIRTUAL_FILE_SYSTEM", FE_LOG_ERROR); return false; } if (!IsPathCorrect(Path)) + { + LOG.Add("Path is not correct in function FEVirtualFileSystem::CreateFile.", "FE_VIRTUAL_FILE_SYSTEM", FE_LOG_ERROR); return false; + } - FEVFSDirectory* directory = PathToDirectory(Path); - if (directory->HasFile(Data)) + FEVFSDirectory* Directory = PathToDirectory(Path); + if (Directory->HasFile(Data)) + { + LOG.Add("File already exists in function FEVirtualFileSystem::CreateFile.", "FE_VIRTUAL_FILE_SYSTEM", FE_LOG_WARNING); return false; + } - directory->Files.push_back(FEVFSFile(Data, directory)); - + Directory->Files.push_back(FEVFSFile(Data, Directory)); return true; } @@ -398,7 +405,7 @@ bool FEVirtualFileSystem::MoveFile(FEObject* Data, const std::string OldPath, co { if (Data == nullptr) { - LOG.Add("data is nullptr in function FEVirtualFileSystem::moveFile.", "FE_LOG_GENERAL", FE_LOG_ERROR); + LOG.Add("Data is nullptr in function FEVirtualFileSystem::MoveFile.", "FE_VIRTUAL_FILE_SYSTEM", FE_LOG_ERROR); return false; } @@ -467,7 +474,7 @@ void FEVirtualFileSystem::DeleteDirectory(FEVFSDirectory* Directory) { if (Directory == nullptr) { - LOG.Add("directory is nullptr in function FEVirtualFileSystem::deleteDirectory.", "FE_LOG_GENERAL", FE_LOG_ERROR); + LOG.Add("Directory is nullptr in function FEVirtualFileSystem::DeleteDirectory.", "FE_VIRTUAL_FILE_SYSTEM", FE_LOG_ERROR); return; } @@ -523,32 +530,32 @@ std::string FEVirtualFileSystem::DirectoryToPath(FEVFSDirectory* Directory) std::string FEVirtualFileSystem::GetDirectoryParent(const std::string Path) { - const FEVFSDirectory* directory = PathToDirectory(Path); - if (directory == nullptr) + const FEVFSDirectory* Directory = PathToDirectory(Path); + if (Directory == nullptr) return "/"; - return DirectoryToPath(directory->Parent); + return DirectoryToPath(Directory->Parent); } bool FEVirtualFileSystem::DeleteFile(const FEObject* Data, const std::string Path) { if (Data == nullptr) { - LOG.Add("data is nullptr in function FEVirtualFileSystem::deleteFile.", "FE_LOG_GENERAL", FE_LOG_ERROR); + LOG.Add("Data is nullptr in function FEVirtualFileSystem::DeleteFile.", "FE_VIRTUAL_FILE_SYSTEM", FE_LOG_ERROR); return false; } - FEVFSDirectory* directory = PathToDirectory(Path); - if (directory == nullptr) + FEVFSDirectory* Directory = PathToDirectory(Path); + if (Directory == nullptr) return false; - if (!directory->HasFile(Data)) + if (!Directory->HasFile(Data)) return false; - if (directory->IsReadOnly()) + if (Directory->IsReadOnly()) return false; - directory->DeleteFile(Data); + Directory->DeleteFile(Data); return true; } @@ -559,13 +566,13 @@ std::string FEVirtualFileSystem::LocateFileRecursive(FEVFSDirectory* Directory, if (Directory == nullptr) { - LOG.Add("Directory is nullptr in function FEVirtualFileSystem::LocateFileRecursive.", "FE_LOG_GENERAL", FE_LOG_ERROR); + LOG.Add("Directory is nullptr in function FEVirtualFileSystem::LocateFileRecursive.", "FE_VIRTUAL_FILE_SYSTEM", FE_LOG_ERROR); return Path; } if (File == nullptr) { - LOG.Add("File is nullptr in function FEVirtualFileSystem::LocateFileRecursive.", "FE_LOG_GENERAL", FE_LOG_ERROR); + LOG.Add("File is nullptr in function FEVirtualFileSystem::LocateFileRecursive.", "FE_VIRTUAL_FILE_SYSTEM", FE_LOG_ERROR); return Path; } @@ -592,7 +599,7 @@ std::string FEVirtualFileSystem::LocateFile(FEObject* File) { if (File == nullptr) { - LOG.Add("File is nullptr in function FEVirtualFileSystem::LocateFile.", "FE_LOG_GENERAL", FE_LOG_ERROR); + LOG.Add("File is nullptr in function FEVirtualFileSystem::LocateFile.", "FE_VIRTUAL_FILE_SYSTEM", FE_LOG_ERROR); return ""; } @@ -603,7 +610,7 @@ void FEVirtualFileSystem::LocateAndDeleteFile(FEObject* File) { if (File == nullptr) { - LOG.Add("File is nullptr in function FEVirtualFileSystem::LocateAndDeleteFile.", "FE_LOG_GENERAL", FE_LOG_ERROR); + LOG.Add("File is nullptr in function FEVirtualFileSystem::LocateAndDeleteFile.", "FE_VIRTUAL_FILE_SYSTEM", FE_LOG_ERROR); return; } @@ -621,12 +628,12 @@ void FEVirtualFileSystem::SaveStateRecursive(Json::Value* LocalRoot, FEVFSDirect { LocalRoot->operator[](Directory->GetObjectID())["name"] = Directory->GetName(); - Json::Value files; + Json::Value Files; for (size_t i = 0; i < Directory->Files.size(); i++) { - files[Directory->Files[i].Data->GetObjectID()]; + Files[Directory->Files[i].Data->GetObjectID()]; } - LocalRoot->operator[](Directory->GetObjectID())["files"] = files; + LocalRoot->operator[](Directory->GetObjectID())["files"] = Files; Json::Value SubDirectories; for (size_t i = 0; i < Directory->SubDirectories.size(); i++) @@ -659,10 +666,10 @@ void FEVirtualFileSystem::LoadStateRecursive(Json::Value* LocalRoot, FEVFSDirect Directory->SetName(LocalRoot->operator[]("name").asCString()); Directory->Parent = Parent; - const std::vector files = LocalRoot->operator[]("files").getMemberNames(); - for (size_t j = 0; j < files.size(); j++) + const std::vector Files = LocalRoot->operator[]("files").getMemberNames(); + for (size_t j = 0; j < Files.size(); j++) { - Directory->AddFile(OBJECT_MANAGER.GetFEObject(files[j])); + Directory->AddFile(OBJECT_MANAGER.GetFEObject(Files[j])); } const std::vector SubDirectories = LocalRoot->operator[]("subDirectories").getMemberNames(); @@ -744,7 +751,6 @@ bool FEVirtualFileSystem::IsReadOnly(const FEObject* Data, const std::string Pat void FEVirtualFileSystem::SetDirectoryReadOnly(const bool NewValue, const std::string Path) { FEVFSDirectory* Directory = PathToDirectory(Path); - if (Directory == nullptr) return; @@ -754,7 +760,6 @@ void FEVirtualFileSystem::SetDirectoryReadOnly(const bool NewValue, const std::s void FEVirtualFileSystem::SetFileReadOnly(const bool NewValue, const FEObject* Data, const std::string Path) { FEVFSDirectory* Directory = PathToDirectory(Path); - if (Directory == nullptr) return; @@ -766,4 +771,21 @@ void FEVirtualFileSystem::SetFileReadOnly(const bool NewValue, const FEObject* D return; } } +} + +bool FEVirtualFileSystem::DoesFileExist(FEObject* Data, std::string Path) +{ + FEVFSDirectory* Directory = PathToDirectory(Path); + if (Directory == nullptr) + { + LOG.Add("Directory is nullptr in function FEVirtualFileSystem::DoesFileExist.", "FE_VIRTUAL_FILE_SYSTEM", FE_LOG_ERROR); + return false; + } + + return Directory->HasFile(Data); +} + +bool FEVirtualFileSystem::DoesFileExistAnywhere(FEObject* Data) +{ + return !LocateFile(Data).empty(); } \ No newline at end of file diff --git a/FEEditorVirtualFileSystem.h b/FEEditorVirtualFileSystem.h index 320bbaf..e2193a0 100644 --- a/FEEditorVirtualFileSystem.h +++ b/FEEditorVirtualFileSystem.h @@ -51,6 +51,10 @@ class FEVirtualFileSystem bool MoveFile(FEObject* Data, std::string OldPath, std::string NewPath); bool DeleteFile(const FEObject* Data, std::string Path); void SetFileReadOnly(bool NewValue, const FEObject* Data, std::string Path); + std::string LocateFile(FEObject* File); + void LocateAndDeleteFile(FEObject* File); + bool DoesFileExist(FEObject* Data, std::string Path); + bool DoesFileExistAnywhere(FEObject* Data); bool CreateDirectory(std::string Name, std::string Path); std::string CreateDirectory(std::string Path); @@ -68,9 +72,6 @@ class FEVirtualFileSystem std::string GetCurrentPath(); bool SetCurrentPath(std::string Path); - std::string LocateFile(FEObject* File); - void LocateAndDeleteFile(FEObject* File); - void SaveState(std::string FileName); void LoadState(std::string FileName); @@ -89,4 +90,4 @@ class FEVirtualFileSystem }; #define VIRTUAL_FILE_SYSTEM_VERSION 0.01f -#define VIRTUAL_FILE_SYSTEM FEVirtualFileSystem::getInstance() +#define VIRTUAL_FILE_SYSTEM FEVirtualFileSystem::GetInstance() diff --git a/FEProject.cpp b/FEProject.cpp deleted file mode 100644 index 67ffe9e..0000000 --- a/FEProject.cpp +++ /dev/null @@ -1,1780 +0,0 @@ -#include "FEProject.h" - -FEProjectManager* FEProjectManager::Instance = nullptr; -FEProjectManager::FEProjectManager() {} -FEProjectManager::~FEProjectManager() {} - -void FEProjectManager::InitializeResources() -{ - IndexChosen = -1; - LoadProjectList(); -} - -FEProject* FEProjectManager::GetCurrent() -{ - return Current; -} - -void FEProjectManager::SetCurrent(FEProject* Project) -{ - Current = Project; -} - -std::vector FEProjectManager::GetList() -{ - return List; -} - -void FEProjectManager::LoadProjectList() -{ - if (!FILE_SYSTEM.CheckDirectory(PROJECTS_FOLDER)) - CustomProjectFolder = ""; - - const std::vector ProjectNameList = FILE_SYSTEM.GetDirectoryList(PROJECTS_FOLDER); - - for (size_t i = 0; i < ProjectNameList.size(); i++) - { - if (ContainProject(std::string(PROJECTS_FOLDER) + std::string("/") + ProjectNameList[i])) - List.push_back(new FEProject(ProjectNameList[i].c_str(), std::string(PROJECTS_FOLDER) + std::string("/") + ProjectNameList[i].c_str() + "/")); - } -} - -void FEProjectManager::CloseCurrentProject() -{ - //closing all windows or popups. - WindowsManager::getInstance().CloseAllWindows(); - WindowsManager::getInstance().CloseAllPopups(); - - SELECTED.Clear(); - for (size_t i = 0; i < List.size(); i++) - { - delete List[i]; - } - List.clear(); - PROJECT_MANAGER.SetCurrent(nullptr); - PREVIEW_MANAGER.Clear(); - - LoadProjectList(); - - VIRTUAL_FILE_SYSTEM.SetCurrentPath("/"); -} - -void FEProjectManager::OpenProject(const int ProjectIndex) -{ - PROJECT_MANAGER.SetCurrent(List[ProjectIndex]); - PROJECT_MANAGER.GetCurrent()->LoadScene(); - IndexChosen = -1; - - GIZMO_MANAGER.ReInitializeEntities(); - - EDITOR_INTERNAL_RESOURCES.AddResourceToInternalEditorList(GIZMO_MANAGER.TransformationXGizmoEntity); - EDITOR_INTERNAL_RESOURCES.AddResourceToInternalEditorList(GIZMO_MANAGER.TransformationYGizmoEntity); - EDITOR_INTERNAL_RESOURCES.AddResourceToInternalEditorList(GIZMO_MANAGER.TransformationZGizmoEntity); - EDITOR_INTERNAL_RESOURCES.AddResourceToInternalEditorList(GIZMO_MANAGER.TransformationXyGizmoEntity); - EDITOR_INTERNAL_RESOURCES.AddResourceToInternalEditorList(GIZMO_MANAGER.TransformationYzGizmoEntity); - EDITOR_INTERNAL_RESOURCES.AddResourceToInternalEditorList(GIZMO_MANAGER.TransformationXzGizmoEntity); - - EDITOR_INTERNAL_RESOURCES.AddResourceToInternalEditorList(GIZMO_MANAGER.ScaleXGizmoEntity); - EDITOR_INTERNAL_RESOURCES.AddResourceToInternalEditorList(GIZMO_MANAGER.ScaleYGizmoEntity); - EDITOR_INTERNAL_RESOURCES.AddResourceToInternalEditorList(GIZMO_MANAGER.ScaleZGizmoEntity); - - EDITOR_INTERNAL_RESOURCES.AddResourceToInternalEditorList(GIZMO_MANAGER.RotateXGizmoEntity); - EDITOR_INTERNAL_RESOURCES.AddResourceToInternalEditorList(GIZMO_MANAGER.RotateYGizmoEntity); - EDITOR_INTERNAL_RESOURCES.AddResourceToInternalEditorList(GIZMO_MANAGER.RotateZGizmoEntity); - - PREVIEW_MANAGER.ReInitializeEntities(); - EDITOR_INTERNAL_RESOURCES.AddResourceToInternalEditorList(PREVIEW_MANAGER.PreviewEntity); - - // all parts of Gizmos are standard resources except entities, so we need to register them again. - // if it is first start and those entities are already registered these calls just returns false. - auto it = EDITOR_INTERNAL_RESOURCES.InternalEditorObjects.begin(); - while (it != EDITOR_INTERNAL_RESOURCES.InternalEditorObjects.end()) - { - if (it->second->GetType() == FE_ENTITY) - SCENE.AddEntity(reinterpret_cast(it->second)); - - it++; - } - - // after loading project we should update our previews - PREVIEW_MANAGER.UpdateAll(); - SELECTED.Clear(); - - // cleaning dirty flag of entities - const std::vector EntityList = SCENE.GetEntityList(); - for (size_t i = 0; i < EntityList.size(); i++) - { - FEEntity* Entity = SCENE.GetEntity(EntityList[i]); - // but before that update AABB - Entity->GetAABB(); - Entity->Transform.SetDirtyFlag(false); - } -} - -void FEProjectManager::DisplayProjectSelection() -{ - static float LowerPanelHight = 90.0f; - const float MainWindowW = static_cast(ENGINE.GetWindowWidth()); - const float MainWindowH = static_cast(ENGINE.GetWindowHeight()); - - ImGui::PushStyleVar(ImGuiStyleVar_Alpha, 1.0f); - ImGui::SetNextWindowPos(ImVec2(0.0f, 0.0f)); - ImGui::SetNextWindowSize(ImVec2(MainWindowW, MainWindowH - LowerPanelHight)); - ImGui::Begin("Project Browser", nullptr, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse); - { - ImGui::SetWindowFontScale(2.0f); - ImGui::Text("CHOOSE WHAT PROJECT TO LOAD :"); - ImGui::SetWindowFontScale(1.0f); - - ImGui::PushStyleColor(ImGuiCol_Button, static_cast(ImColor(0.5f, 0.5f, 0.5f))); - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, static_cast(ImColor::ImColor(0.95f, 0.90f, 0.0f))); - ImGui::PushStyleColor(ImGuiCol_ButtonActive, static_cast(ImColor::ImColor(0.1f, 1.0f, 0.1f, 1.0f))); - - const int ColumnCount = static_cast(MainWindowW / (512.0f + 32.0f)); - ImGui::Columns(ColumnCount, "projectColumns", false); - static bool bPushedStyle = false; - for (size_t i = 0; i < List.size(); i++) - { - ImGui::PushID(static_cast(i)); - bPushedStyle = false; - if (IndexChosen == i) - { - bPushedStyle = true; - ImGui::PushStyleColor(ImGuiCol_Button, static_cast(ImColor(0.1f, 1.0f, 0.1f, 1.0f))); - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, static_cast(ImColor::ImColor(0.1f, 1.0f, 0.1f, 1.0f))); - ImGui::PushStyleColor(ImGuiCol_ButtonActive, static_cast(ImColor::ImColor(0.1f, 1.0f, 0.1f, 1.0f))); - } - - if (ImGui::IsMouseDoubleClicked(0)) - { - if (IndexChosen != -1) - { - OpenProject(IndexChosen); - } - } - - if (ImGui::ImageButton((void*)static_cast(List[i]->SceneScreenshot->GetTextureID()), ImVec2(512.0f, 288.0f), ImVec2(0.0f, 1.0f), ImVec2(1.0f, 0.0f), 8, ImColor(0.0f, 0.0f, 0.0f, 0.0f), ImColor(1.0f, 1.0f, 1.0f, 1.0f))) - { - IndexChosen = static_cast(i); - } - - ImGui::Text(List[i]->GetName().c_str()); - - if (bPushedStyle) - { - ImGui::PopStyleColor(); - ImGui::PopStyleColor(); - ImGui::PopStyleColor(); - } - - ImGui::PopID(); - ImGui::NextColumn(); - } - - ImGui::Columns(1); - - ImGui::PopStyleColor(); - ImGui::PopStyleColor(); - ImGui::PopStyleColor(); - } - ImGui::End(); - ImGui::PopStyleVar(); - - ImGui::PushStyleVar(ImGuiStyleVar_Alpha, 1.0f); - ImGui::SetNextWindowPos(ImVec2(0.0f, MainWindowH - LowerPanelHight)); - ImGui::SetNextWindowSize(ImVec2(MainWindowW, LowerPanelHight)); - ImGui::Begin("##create project", nullptr, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar); - { - ImGui::PushStyleColor(ImGuiCol_Button, static_cast(ImColor(0.0f, 162.0f / 255.0f, 232.0f / 255.0f, 1.0f))); - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, static_cast(ImColor::ImColor(23.0f / 255.0f, 186.0f / 255.0f, 1.0f, 1.0f))); - ImGui::PushStyleColor(ImGuiCol_ButtonActive, static_cast(ImColor::ImColor(0.0f, 125.0f / 255.0f, 179.0f / 255.0f, 1.0f))); - - if (ImGui::Button("Create New Project", ImVec2(200.0f, 64.0f))) - ImGui::OpenPopup("New Project"); - - ImGui::SameLine(); - if (ImGui::Button("Open Project", ImVec2(200.0f, 64.0f)) && IndexChosen != -1) - { - OpenProject(IndexChosen); - } - - ImGui::SameLine(); - if (ImGui::Button("Delete Project", ImVec2(200.0f, 64.0f)) && IndexChosen != -1 && IndexChosen < static_cast(List.size())) - { - std::string ProjectFolder = List[IndexChosen]->GetProjectFolder(); - ProjectFolder.erase(ProjectFolder.begin() + ProjectFolder.size() - 1); - - // Getting list of all files in project folder. - const auto FileList = FILE_SYSTEM.GetFileList(List[IndexChosen]->GetProjectFolder().c_str()); - // We would delete all files in project folder, editor would not create folders there - // so we are deleting only files. - for (size_t i = 0; i < FileList.size(); i++) - { - FILE_SYSTEM.DeleteFile((List[IndexChosen]->GetProjectFolder() + FileList[i]).c_str()); - } - // Then we can try to delete project folder, but if user created some folders in it we will fail. - FILE_SYSTEM.DeleteDirectory(ProjectFolder.c_str()); - - for (size_t i = 0; i < List.size(); i++) - { - delete List[i]; - } - List.clear(); - PROJECT_MANAGER.SetCurrent(nullptr); - - LoadProjectList(); - } - - ImGui::PopStyleColor(); - ImGui::PopStyleColor(); - ImGui::PopStyleColor(); - ImGui::PushStyleColor(ImGuiCol_Button, static_cast(ImColor(0.0f, 242.0f / 255.0f, 79.0f / 255.0f, 1.0f))); - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, static_cast(ImColor::ImColor(34.0f / 255.0f, 1.0f, 106.0f / 255.0f, 1.0f))); - ImGui::PushStyleColor(ImGuiCol_ButtonActive, static_cast(ImColor::ImColor(0.0f, 202.0f / 255.0f, 66.0f / 255.0f, 1.0f))); - - ImGui::SameLine(); - ImGui::SetCursorPos(ImVec2(ImGui::GetContentRegionAvail().x + 280.0f + 64.0f, ImGui::GetCursorPos().y)); - if (ImGui::Button("Choose projects directory", ImVec2(280.0f, 64.0f))) - { - std::string path; - FILE_SYSTEM.ShowFolderOpenDialog(path); - SetProjectsFolder(path); - } - - ImGui::PopStyleColor(); - ImGui::PopStyleColor(); - ImGui::PopStyleColor(); - - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(15, 15)); - if (ImGui::BeginPopupModal("New Project", nullptr, ImGuiWindowFlags_AlwaysAutoResize)) - { - ImGui::SetWindowPos(ImVec2(ENGINE.GetWindowWidth() / 2.0f - ImGui::GetWindowWidth() / 2.0f, ENGINE.GetWindowHeight() / 2.0f - ImGui::GetWindowHeight() / 2.0f)); - ImGui::Text("Insert name of new project :"); - static char ProjectName[512] = ""; - - ImGui::InputText("##newProjectName", ProjectName, IM_ARRAYSIZE(ProjectName)); - - ImGui::SetCursorPosX(ImGui::GetWindowWidth() / 4.0f - 120.0f / 2.0f); - ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 10.0f); - if (ImGui::Button("Create", ImVec2(120, 0))) - { - bool bAlreadyCreated = false; - for (size_t i = 0; i < List.size(); i++) - { - if (List[i]->GetName() == std::string(ProjectName)) - { - bAlreadyCreated = true; - break; - } - } - - if (strlen(ProjectName) != 0 && !bAlreadyCreated) - { - FILE_SYSTEM.CreateDirectory((std::string(PROJECTS_FOLDER) + std::string("/") + ProjectName + "/").c_str()); - List.push_back(new FEProject(ProjectName, std::string(PROJECTS_FOLDER) + std::string("/") + ProjectName + "/")); - List.back()->CreateDummyScreenshot(); - //SCENE.addLight(FE_DIRECTIONAL_LIGHT, "sun"); - std::fstream File; - File.open((std::string(PROJECTS_FOLDER) + std::string("/") + ProjectName + "/" + "scene.txt").c_str(), std::ios::out); - File.write(BASIC_SCENE, strlen(BASIC_SCENE)); - File.close(); - - //openProject(indexChosen); - //current->saveScene(); - - ImGui::CloseCurrentPopup(); - strcpy_s(ProjectName, ""); - } - } - - ImGui::SetItemDefaultFocus(); - ImGui::SameLine(); - ImGui::SetCursorPosX(ImGui::GetWindowWidth() / 2.0f + ImGui::GetWindowWidth() / 4.0f - 120.0f / 2.0f); - if (ImGui::Button("Cancel", ImVec2(120, 0))) - { - ImGui::CloseCurrentPopup(); - } - - ImGui::EndPopup(); - } - } - - ImGui::PopStyleVar(); - ImGui::End(); - ImGui::PopStyleVar(); -} - -bool FEProjectManager::ContainProject(const std::string Path) -{ - if (!FILE_SYSTEM.CheckDirectory(Path.c_str())) - return false; - - if (!FILE_SYSTEM.CheckFile((Path + "/scene.txt").c_str())) - return false; - - return true; -} - -void FEProjectManager::SetProjectsFolder(const std::string FolderPath) -{ - if (FolderPath != "") - { - CustomProjectFolder = FolderPath; - for (size_t i = 0; i < List.size(); i++) - { - delete List[i]; - } - List.clear(); - LoadProjectList(); - } -} - -FEProject::FEProject(const std::string Name, const std::string ProjectFolder) -{ - this->Name = Name; - this->ProjectFolder = ProjectFolder; - - std::ifstream ScreenshotFile((this->GetProjectFolder() + "projectScreenShot.texture").c_str()); - - if (!ScreenshotFile.good()) - { - SceneScreenshot = RESOURCE_MANAGER.NoTexture; - } - else - { - SceneScreenshot = RESOURCE_MANAGER.LoadFETextureUnmanaged((this->GetProjectFolder() + "projectScreenShot.texture").c_str()); - } - - ScreenshotFile.close(); -} - -FEProject::~FEProject() -{ - if (SceneScreenshot != RESOURCE_MANAGER.NoTexture) - delete SceneScreenshot; - - EDITOR_INTERNAL_RESOURCES.ClearListByType(FE_ENTITY); - SCENE.Clear(); - RESOURCE_MANAGER.Clear(); - ENGINE.ResetCamera(); - VIRTUAL_FILE_SYSTEM.Clear(); -} - -std::string FEProject::GetName() -{ - return Name; -} - -void FEProject::SetName(const std::string NewValue) -{ - Name = NewValue; -} - -std::string FEProject::GetProjectFolder() -{ - return ProjectFolder; -} - -void FEProject::WriteTransformToJson(Json::Value& Root, const FETransformComponent* Transform) -{ - Root["position"]["X"] = Transform->GetPosition()[0]; - Root["position"]["Y"] = Transform->GetPosition()[1]; - Root["position"]["Z"] = Transform->GetPosition()[2]; - Root["rotation"]["X"] = Transform->GetRotation()[0]; - Root["rotation"]["Y"] = Transform->GetRotation()[1]; - Root["rotation"]["Z"] = Transform->GetRotation()[2]; - Root["scale"]["uniformScaling"] = Transform->IsUniformScalingSet(); - Root["scale"]["X"] = Transform->GetScale()[0]; - Root["scale"]["Y"] = Transform->GetScale()[1]; - Root["scale"]["Z"] = Transform->GetScale()[2]; -} - -void FEProject::SaveScene(bool bFullSave) -{ - Json::Value Root; - std::ofstream SceneFile; - - Root["version"] = PROJECTS_FILE_VER; - - if (!bFullSave) - { - // saving all unSaved objects - for (size_t i = 0; i < UnSavedObjects.size(); i++) - { - switch (UnSavedObjects[i]->GetType()) - { - case FE_MESH: - { - FEMesh* MeshToSave = RESOURCE_MANAGER.GetMesh(UnSavedObjects[i]->GetObjectID()); - if (MeshToSave != nullptr) - RESOURCE_MANAGER.SaveFEMesh(MeshToSave, (GetProjectFolder() + MeshToSave->GetObjectID() + std::string(".model")).c_str()); - break; - } - - case FE_TEXTURE: - { - FETexture* TextureToSave = RESOURCE_MANAGER.GetTexture(UnSavedObjects[i]->GetObjectID()); - if (TextureToSave != nullptr) - RESOURCE_MANAGER.SaveFETexture(TextureToSave, (GetProjectFolder() + TextureToSave->GetObjectID() + std::string(".texture")).c_str()); - break; - } - } - } - } - - // saving Meshes - std::vector MeshList = RESOURCE_MANAGER.GetMeshList(); - Json::Value MeshData; - for (size_t i = 0; i < MeshList.size(); i++) - { - FEMesh* Mesh = RESOURCE_MANAGER.GetMesh(MeshList[i]); - MeshData[Mesh->GetObjectID()]["ID"] = Mesh->GetObjectID(); - MeshData[Mesh->GetObjectID()]["name"] = Mesh->GetName(); - MeshData[Mesh->GetObjectID()]["fileName"] = Mesh->GetObjectID() + ".model"; - - if (bFullSave) - RESOURCE_MANAGER.SaveFEMesh(Mesh, (GetProjectFolder() + Mesh->GetObjectID() + std::string(".model")).c_str()); - - Mesh->SetDirtyFlag(false); - } - Root["meshes"] = MeshData; - - // saving Textures - std::vector TexturesList = RESOURCE_MANAGER.GetTextureList(); - Json::Value TexturesData; - for (size_t i = 0; i < TexturesList.size(); i++) - { - FETexture* Texture = RESOURCE_MANAGER.GetTexture(TexturesList[i]); - if (!ShouldIncludeInSceneFile(Texture)) - continue; - - TexturesData[Texture->GetObjectID()]["ID"] = Texture->GetObjectID(); - TexturesData[Texture->GetObjectID()]["name"] = Texture->GetName(); - TexturesData[Texture->GetObjectID()]["fileName"] = Texture->GetObjectID() + ".texture"; - TexturesData[Texture->GetObjectID()]["type"] = Texture->GetInternalFormat(); - - if (bFullSave) - RESOURCE_MANAGER.SaveFETexture(Texture, (GetProjectFolder() + Texture->GetObjectID() + std::string(".texture")).c_str()); - - Texture->SetDirtyFlag(false); - } - Root["textures"] = TexturesData; - - // saving Materials - std::vector MaterialList = RESOURCE_MANAGER.GetMaterialList(); - Json::Value MaterialData; - for (size_t i = 0; i < MaterialList.size(); i++) - { - FEMaterial* Material = RESOURCE_MANAGER.GetMaterial(MaterialList[i]); - - for (size_t j = 0; j < FE_MAX_TEXTURES_PER_MATERIAL; j++) - { - if (Material->Textures[j] != nullptr) - MaterialData[Material->GetObjectID()]["textures"][std::to_string(j).c_str()] = Material->Textures[j]->GetObjectID(); - - if (Material->TextureBindings[j] != -1) - MaterialData[Material->GetObjectID()]["textureBindings"][std::to_string(j).c_str()] = Material->TextureBindings[j]; - - if (Material->TextureChannels[j] != -1) - MaterialData[Material->GetObjectID()]["textureChannels"][std::to_string(j).c_str()] = Material->TextureChannels[j]; - } - - MaterialData[Material->GetObjectID()]["ID"] = Material->GetObjectID(); - MaterialData[Material->GetObjectID()]["name"] = Material->GetName(); - MaterialData[Material->GetObjectID()]["metalness"] = Material->GetMetalness(); - MaterialData[Material->GetObjectID()]["roughness"] = Material->GetRoughness(); - MaterialData[Material->GetObjectID()]["normalMapIntensity"] = Material->GetNormalMapIntensity(); - MaterialData[Material->GetObjectID()]["ambientOcclusionIntensity"] = Material->GetAmbientOcclusionIntensity(); - MaterialData[Material->GetObjectID()]["ambientOcclusionMapIntensity"] = Material->GetAmbientOcclusionMapIntensity(); - MaterialData[Material->GetObjectID()]["roughnessMapIntensity"] = Material->GetRoughnessMapIntensity(); - MaterialData[Material->GetObjectID()]["metalnessMapIntensity"] = Material->GetMetalnessMapIntensity(); - MaterialData[Material->GetObjectID()]["tiling"] = Material->GetTiling(); - MaterialData[Material->GetObjectID()]["compackPacking"] = Material->IsCompackPacking(); - - Material->SetDirtyFlag(false); - } - Root["materials"] = MaterialData; - - // saving gameModels - std::vector GameModelList = RESOURCE_MANAGER.GetGameModelList(); - Json::Value GameModelData; - for (size_t i = 0; i < GameModelList.size(); i++) - { - FEGameModel* GameModel = RESOURCE_MANAGER.GetGameModel(GameModelList[i]); - GameModelData[GameModel->GetObjectID()]["ID"] = GameModel->GetObjectID(); - GameModelData[GameModel->GetObjectID()]["name"] = GameModel->GetName(); - GameModelData[GameModel->GetObjectID()]["mesh"] = GameModel->Mesh->GetObjectID(); - GameModelData[GameModel->GetObjectID()]["material"] = GameModel->Material->GetObjectID(); - GameModelData[GameModel->GetObjectID()]["scaleFactor"] = GameModel->GetScaleFactor(); - - GameModelData[GameModel->GetObjectID()]["LODs"]["haveLODlevels"] = GameModel->IsUsingLOD(); - if (GameModel->IsUsingLOD()) - { - GameModelData[GameModel->GetObjectID()]["LODs"]["cullDistance"] = GameModel->GetCullDistance(); - GameModelData[GameModel->GetObjectID()]["LODs"]["billboardZeroRotaion"] = GameModel->GetBillboardZeroRotaion(); - GameModelData[GameModel->GetObjectID()]["LODs"]["LODCount"] = GameModel->GetLODCount(); - for (size_t j = 0; j < GameModel->GetLODCount(); j++) - { - GameModelData[GameModel->GetObjectID()]["LODs"][std::to_string(j)]["mesh"] = GameModel->GetLODMesh(j)->GetObjectID(); - GameModelData[GameModel->GetObjectID()]["LODs"][std::to_string(j)]["maxDrawDistance"] = GameModel->GetLODMaxDrawDistance(j); - GameModelData[GameModel->GetObjectID()]["LODs"][std::to_string(j)]["isBillboard"] = GameModel->IsLODBillboard(j); - if (GameModel->IsLODBillboard(j)) - GameModelData[GameModel->GetObjectID()]["LODs"][std::to_string(j)]["billboardMaterial"] = GameModel->GetBillboardMaterial()->GetObjectID(); - } - } - - GameModel->SetDirtyFlag(false); - } - Root["gameModels"] = GameModelData; - - // saving prefabs - std::vector PrefabList = RESOURCE_MANAGER.GetPrefabList(); - Json::Value PrefabData; - for (size_t i = 0; i < PrefabList.size(); i++) - { - FEPrefab* Prefab = RESOURCE_MANAGER.GetPrefab(PrefabList[i]); - PrefabData[Prefab->GetObjectID()]["ID"] = Prefab->GetObjectID(); - PrefabData[Prefab->GetObjectID()]["name"] = Prefab->GetName(); - - Json::Value ComponentsData; - for (int j = 0; j < Prefab->ComponentsCount(); j++) - { - ComponentsData[j]["gameModel"]["ID"] = Prefab->GetComponent(j)->GameModel->GetObjectID(); - WriteTransformToJson(ComponentsData[j]["transformation"], &Prefab->GetComponent(j)->Transform); - } - - PrefabData[Prefab->GetObjectID()]["components"] = ComponentsData; - } - Root["prefabs"] = PrefabData; - - // saving Entities - std::vector EntityList = SCENE.GetEntityList(); - Json::Value EntityData; - for (size_t i = 0; i < EntityList.size(); i++) - { - FEEntity* Entity = SCENE.GetEntity(EntityList[i]); - if (EDITOR_INTERNAL_RESOURCES.IsInInternalEditorList(Entity)) - continue; - - EntityData[Entity->GetObjectID()]["ID"] = Entity->GetObjectID(); - EntityData[Entity->GetObjectID()]["type"] = FEObjectTypeToString(Entity->GetType()); - EntityData[Entity->GetObjectID()]["name"] = Entity->GetName(); - EntityData[Entity->GetObjectID()]["prefab"] = Entity->Prefab->GetObjectID(); - WriteTransformToJson(EntityData[Entity->GetObjectID()]["transformation"], &Entity->Transform); - - if (Entity->GetType() == FE_ENTITY_INSTANCED) - { - FEEntityInstanced* InstancedEntity = reinterpret_cast(Entity); - EntityData[Entity->GetObjectID()]["modificationsToSpawn"] = InstancedEntity->GetSpawnModificationCount() == 0 ? false : true; - if (InstancedEntity->GetSpawnModificationCount()) - { - std::ofstream InfoFile; - Json::Value EntityFileRoot; - InfoFile.open(ProjectFolder + Entity->GetObjectID() + ".txt"); - - Json::Value ModificationsData; - auto ModificationList = InstancedEntity->GetSpawnModifications(); - for (int j = 0; j < ModificationList.size(); j++) - { - ModificationsData[j]["type"] = static_cast(ModificationList[j].Type); - ModificationsData[j]["index"] = ModificationList[j].Index; - if (ModificationList[j].Type != FE_CHANGE_DELETED) - { - for (int k = 0; k < 4; k++) - { - for (int p = 0; p < 4; p++) - { - ModificationsData[j]["modification"][k][p] = ModificationList[j].Modification[k][p]; - } - } - } - } - EntityFileRoot["modifications"] = ModificationsData; - - InfoFile << EntityFileRoot; - InfoFile.close(); - } - - EntityData[Entity->GetObjectID()]["spawnInfo"]["seed"] = InstancedEntity->SpawnInfo.Seed; - EntityData[Entity->GetObjectID()]["spawnInfo"]["objectCount"] = InstancedEntity->SpawnInfo.ObjectCount; - EntityData[Entity->GetObjectID()]["spawnInfo"]["radius"] = InstancedEntity->SpawnInfo.Radius; - EntityData[Entity->GetObjectID()]["spawnInfo"]["minScale"] = InstancedEntity->SpawnInfo.GetMinScale(); - EntityData[Entity->GetObjectID()]["spawnInfo"]["maxScale"] = InstancedEntity->SpawnInfo.GetMaxScale(); - EntityData[Entity->GetObjectID()]["spawnInfo"]["rotationDeviation.x"] = InstancedEntity->SpawnInfo.RotationDeviation.x; - EntityData[Entity->GetObjectID()]["spawnInfo"]["rotationDeviation.y"] = InstancedEntity->SpawnInfo.RotationDeviation.y; - EntityData[Entity->GetObjectID()]["spawnInfo"]["rotationDeviation.z"] = InstancedEntity->SpawnInfo.RotationDeviation.z; - if (InstancedEntity->GetSnappedToTerrain() == nullptr) - { - EntityData[Entity->GetObjectID()]["snappedToTerrain"] = "none"; - } - else - { - EntityData[Entity->GetObjectID()]["snappedToTerrain"] = InstancedEntity->GetSnappedToTerrain()->GetObjectID(); - EntityData[Entity->GetObjectID()]["terrainLayer"] = InstancedEntity->GetTerrainLayer(); - EntityData[Entity->GetObjectID()]["minimalLayerIntensity"] = InstancedEntity->GetMinimalLayerIntensity(); - } - } - - Entity->SetDirtyFlag(false); - } - Root["entities"] = EntityData; - - // saving Terrains - std::vector TerrainList = SCENE.GetTerrainList(); - Json::Value TerrainData; - for (size_t i = 0; i < TerrainList.size(); i++) - { - FETerrain* Terrain = SCENE.GetTerrain(TerrainList[i]); - - TerrainData[Terrain->GetObjectID()]["ID"] = Terrain->GetObjectID(); - TerrainData[Terrain->GetObjectID()]["name"] = Terrain->GetName(); - - TerrainData[Terrain->GetObjectID()]["heightMap"]["ID"] = Terrain->HeightMap->GetObjectID(); - TerrainData[Terrain->GetObjectID()]["heightMap"]["name"] = Terrain->HeightMap->GetName(); - TerrainData[Terrain->GetObjectID()]["heightMap"]["fileName"] = Terrain->HeightMap->GetObjectID() + ".texture"; - RESOURCE_MANAGER.SaveFETexture(Terrain->HeightMap, (GetProjectFolder() + Terrain->HeightMap->GetObjectID() + std::string(".texture")).c_str()); - - TerrainData[Terrain->GetObjectID()]["hightScale"] = Terrain->GetHightScale(); - TerrainData[Terrain->GetObjectID()]["displacementScale"] = Terrain->GetDisplacementScale(); - TerrainData[Terrain->GetObjectID()]["tileMult"]["X"] = Terrain->GetTileMult().x; - TerrainData[Terrain->GetObjectID()]["tileMult"]["Y"] = Terrain->GetTileMult().y; - TerrainData[Terrain->GetObjectID()]["LODlevel"] = Terrain->GetLODLevel(); - TerrainData[Terrain->GetObjectID()]["chunkPerSide"] = Terrain->GetChunkPerSide(); - - WriteTransformToJson(TerrainData[Terrain->GetObjectID()]["transformation"], &Terrain->Transform); - - // Saving terrains Layers. - for (int j = 0; j < Terrain->LayerMaps.size(); j++) - { - if (Terrain->LayerMaps[j] != nullptr) - { - TerrainData[Terrain->GetObjectID()]["layerMaps"][j]["ID"] = Terrain->LayerMaps[j]->GetObjectID(); - TerrainData[Terrain->GetObjectID()]["layerMaps"][j]["name"] = Terrain->LayerMaps[j]->GetName(); - TerrainData[Terrain->GetObjectID()]["layerMaps"][j]["fileName"] = Terrain->LayerMaps[j]->GetObjectID() + ".texture"; - RESOURCE_MANAGER.SaveFETexture(Terrain->LayerMaps[j], (GetProjectFolder() + Terrain->LayerMaps[j]->GetObjectID() + std::string(".texture")).c_str()); - } - } - - for (int j = 0; j < FE_TERRAIN_MAX_LAYERS; j++) - { - FETerrainLayer* CurrentLayer = Terrain->GetLayerInSlot(j); - if (CurrentLayer == nullptr) - { - TerrainData[Terrain->GetObjectID()]["layers"][j]["acive"] = false; - break; - } - - TerrainData[Terrain->GetObjectID()]["layers"][j]["acive"] = true; - TerrainData[Terrain->GetObjectID()]["layers"][j]["name"] = CurrentLayer->GetMaterial()->GetName(); - TerrainData[Terrain->GetObjectID()]["layers"][j]["materialID"] = CurrentLayer->GetMaterial()->GetObjectID(); - } - - Terrain->SetDirtyFlag(false); - } - Root["terrains"] = TerrainData; - - // saving Lights - std::vector LightList = SCENE.GetLightsList(); - Json::Value LightData; - for (size_t i = 0; i < LightList.size(); i++) - { - FELight* Light = SCENE.GetLight(LightList[i]); - - // general light information - LightData[Light->GetObjectID()]["ID"] = Light->GetObjectID(); - LightData[Light->GetObjectID()]["type"] = Light->GetType(); - LightData[Light->GetObjectID()]["name"] = Light->GetName(); - LightData[Light->GetObjectID()]["intensity"] = Light->GetIntensity(); - WriteTransformToJson(LightData[Light->GetObjectID()]["transformation"], &Light->Transform); - LightData[Light->GetObjectID()]["castShadows"] = Light->IsCastShadows(); - LightData[Light->GetObjectID()]["enabled"] = Light->IsLightEnabled(); - LightData[Light->GetObjectID()]["color"]["R"] = Light->GetColor()[0]; - LightData[Light->GetObjectID()]["color"]["G"] = Light->GetColor()[1]; - LightData[Light->GetObjectID()]["color"]["B"] = Light->GetColor()[2]; - LightData[Light->GetObjectID()]["staticShadowBias"] = Light->IsStaticShadowBias(); - LightData[Light->GetObjectID()]["shadowBias"] = Light->GetShadowBias(); - LightData[Light->GetObjectID()]["shadowBiasVariableIntensity"] = Light->GetShadowBiasVariableIntensity(); - LightData[Light->GetObjectID()]["shadowBlurFactor"] = Light->GetShadowBlurFactor(); - - // type specific information - if (Light->GetType() == FE_DIRECTIONAL_LIGHT) - { - FEDirectionalLight* DirectionalLight = reinterpret_cast(Light); - - LightData[DirectionalLight->GetObjectID()]["direction"]["X"] = DirectionalLight->GetDirection()[0]; - LightData[DirectionalLight->GetObjectID()]["direction"]["Y"] = DirectionalLight->GetDirection()[1]; - LightData[DirectionalLight->GetObjectID()]["direction"]["Z"] = DirectionalLight->GetDirection()[2]; - LightData[DirectionalLight->GetObjectID()]["CSM"]["activeCascades"] = DirectionalLight->GetActiveCascades(); - LightData[DirectionalLight->GetObjectID()]["CSM"]["shadowCoverage"] = DirectionalLight->GetShadowCoverage(); - LightData[DirectionalLight->GetObjectID()]["CSM"]["CSMZDepth"] = DirectionalLight->GetCSMZDepth(); - LightData[DirectionalLight->GetObjectID()]["CSM"]["CSMXYDepth"] = DirectionalLight->GetCSMXYDepth(); - } - else if (Light->GetType() == FE_SPOT_LIGHT) - { - FESpotLight* SpotLight = reinterpret_cast(Light); - - LightData[SpotLight->GetObjectID()]["spotAngle"] = SpotLight->GetSpotAngle(); - LightData[SpotLight->GetObjectID()]["spotAngleOuter"] = SpotLight->GetSpotAngleOuter(); - LightData[SpotLight->GetObjectID()]["direction"]["X"] = SpotLight->GetDirection()[0]; - LightData[SpotLight->GetObjectID()]["direction"]["Y"] = SpotLight->GetDirection()[1]; - LightData[SpotLight->GetObjectID()]["direction"]["Z"] = SpotLight->GetDirection()[2]; - } - else if (Light->GetType() == FE_POINT_LIGHT) - { - FEPointLight* PointLight = reinterpret_cast(Light); - - LightData[PointLight->GetObjectID()]["range"] = PointLight->GetRange(); - } - } - Root["lights"] = LightData; - - // saving Effects settings - Json::Value EffectsData; - // *********** Gamma Correction & Exposure *********** - EffectsData["Gamma Correction & Exposure"]["Gamma"] = ENGINE.GetCamera()->GetGamma(); - EffectsData["Gamma Correction & Exposure"]["Exposure"] = ENGINE.GetCamera()->GetExposure(); - // *********** Anti-Aliasing(FXAA) *********** - EffectsData["Anti-Aliasing(FXAA)"]["FXAASpanMax"] = RENDERER.GetFXAASpanMax(); - EffectsData["Anti-Aliasing(FXAA)"]["FXAAReduceMin"] = RENDERER.GetFXAAReduceMin(); - EffectsData["Anti-Aliasing(FXAA)"]["FXAAReduceMul"] = RENDERER.GetFXAAReduceMul(); - // *********** Bloom *********** - EffectsData["Bloom"]["thresholdBrightness"] = RENDERER.GetBloomThreshold(); - EffectsData["Bloom"]["BloomSize"] = RENDERER.GetBloomSize(); - // *********** Depth of Field *********** - EffectsData["Depth of Field"]["Near distance"] = RENDERER.GetDOFNearDistance(); - EffectsData["Depth of Field"]["Far distance"] = RENDERER.GetDOFFarDistance(); - EffectsData["Depth of Field"]["Strength"] = RENDERER.GetDOFStrength(); - EffectsData["Depth of Field"]["Distance dependent strength"] = RENDERER.GetDOFDistanceDependentStrength(); - // *********** Distance fog *********** - EffectsData["Distance fog"]["isDistanceFogEnabled"] = RENDERER.IsDistanceFogEnabled(); - EffectsData["Distance fog"]["Density"] = RENDERER.GetDistanceFogDensity(); - EffectsData["Distance fog"]["Gradient"] = RENDERER.GetDistanceFogGradient(); - // *********** Chromatic Aberration *********** - EffectsData["Chromatic Aberration"]["Shift strength"] = RENDERER.GetChromaticAberrationIntensity(); - // *********** Sky *********** - EffectsData["Sky"]["Enabled"] = RENDERER.IsSkyEnabled() ? 1.0f : 0.0f; - EffectsData["Sky"]["Sphere size"] = RENDERER.GetDistanceToSky(); - - Root["effects"] = EffectsData; - - // saving Camera settings - Json::Value CameraData; - - CameraData["position"]["X"] = ENGINE.GetCamera()->GetPosition()[0]; - CameraData["position"]["Y"] = ENGINE.GetCamera()->GetPosition()[1]; - CameraData["position"]["Z"] = ENGINE.GetCamera()->GetPosition()[2]; - - CameraData["fov"] = ENGINE.GetCamera()->GetFov(); - CameraData["nearPlane"] = ENGINE.GetCamera()->GetNearPlane(); - CameraData["farPlane"] = ENGINE.GetCamera()->GetFarPlane(); - - CameraData["yaw"] = ENGINE.GetCamera()->GetYaw(); - CameraData["pitch"] = ENGINE.GetCamera()->GetPitch(); - CameraData["roll"] = ENGINE.GetCamera()->GetRoll(); - - CameraData["aspectRatio"] = ENGINE.GetCamera()->GetAspectRatio(); - - CameraData["movementSpeed"] = ENGINE.GetCamera()->GetMovementSpeed(); - - Root["camera"] = CameraData; - - // saving into file - Json::StreamWriterBuilder Builder; - const std::string JsonFile = Json::writeString(Builder, Root); - - SceneFile.open(ProjectFolder + "scene.txt"); - SceneFile << JsonFile; - SceneFile.close(); - - for (size_t i = 0; i < FilesToDelete.size(); i++) - { - FILE_SYSTEM.DeleteFile(FilesToDelete[i].c_str()); - } - - // VFS - VIRTUAL_FILE_SYSTEM.SaveState(ProjectFolder + "VFS.txt"); - - bModified = false; -} - -void FEProject::ReadTransformToJson(Json::Value& Root, FETransformComponent* Transform) -{ - Transform->SetPosition(glm::vec3(Root["position"]["X"].asFloat(), - Root["position"]["Y"].asFloat(), - Root["position"]["Z"].asFloat())); - - Transform->SetRotation(glm::vec3(Root["rotation"]["X"].asFloat(), - Root["rotation"]["Y"].asFloat(), - Root["rotation"]["Z"].asFloat())); - - Transform->SetUniformScaling(Root["scale"]["uniformScaling"].asBool()); - - Transform->SetScale(glm::vec3(Root["scale"]["X"].asFloat(), - Root["scale"]["Y"].asFloat(), - Root["scale"]["Z"].asFloat())); -} - -void FEProject::LoadScene() -{ - std::ifstream SceneFile; - SceneFile.open(ProjectFolder + "scene.txt"); - - std::string FileData((std::istreambuf_iterator(SceneFile)), std::istreambuf_iterator()); - SceneFile.close(); - - Json::Value Root; - JSONCPP_STRING Err; - Json::CharReaderBuilder Builder; - - const std::unique_ptr Reader(Builder.newCharReader()); - if (!Reader->parse(FileData.c_str(), FileData.c_str() + FileData.size(), &Root, &Err)) - return; - - // read project file version - float ProjectVersion = Root["version"].asFloat(); - - // project file was created before any version was written to project files. - if (ProjectVersion != PROJECTS_FILE_VER) - { - if (ProjectVersion == 0.0f) - { - LOG.Add("Can't find version in scene file of project from " + ProjectFolder, "FE_LOG_LOADING", FE_LOG_WARNING); - LOG.Add("Trying to load project with old version of loader.", "FE_LOG_LOADING", FE_LOG_WARNING); - LoadSceneVer0(); - return; - } - else if (ProjectVersion == 0.01f) - { - // Do nothing. - } - } - - // loading Meshes - std::vector MeshList = Root["meshes"].getMemberNames(); - for (size_t i = 0; i < MeshList.size(); i++) - { - RESOURCE_MANAGER.LoadFEMesh((ProjectFolder + Root["meshes"][MeshList[i]]["fileName"].asCString()).c_str(), Root["meshes"][MeshList[i]]["name"].asCString()); - } - - // loading Textures - std::vector TexturesList = Root["textures"].getMemberNames(); - for (size_t i = 0; i < TexturesList.size(); i++) - { - // read type of texture if it is not standard then skip it. - if (Root["textures"][TexturesList[i]]["type"] == 33322) - { - continue; - } - - RESOURCE_MANAGER.LoadFETextureAsync((ProjectFolder + Root["textures"][TexturesList[i]]["fileName"].asCString()).c_str(), Root["textures"][TexturesList[i]]["name"].asString(), nullptr, Root["textures"][TexturesList[i]]["ID"].asString()); - } - - // loading Materials - std::vector MaterialsList = Root["materials"].getMemberNames(); - for (size_t i = 0; i < MaterialsList.size(); i++) - { - FEMaterial* NewMaterial = RESOURCE_MANAGER.CreateMaterial(Root["materials"][MaterialsList[i]]["name"].asString(), Root["materials"][MaterialsList[i]]["ID"].asString()); - - //newMat->shader = RESOURCE_MANAGER.getShader("FEPhongShader"); - //newMat->shader = RESOURCE_MANAGER.getShader("FESolidColorShader"); - NewMaterial->Shader = RESOURCE_MANAGER.GetShader("0800253C242B05321A332D09"/*"FEPBRShader"*/); - - std::vector MembersList = Root["materials"][MaterialsList[i]].getMemberNames(); - for (size_t j = 0; j < MembersList.size(); j++) - { - if (MembersList[j] == "textures") - { - for (size_t k = 0; k < FE_MAX_TEXTURES_PER_MATERIAL; k++) - { - if (Root["materials"][MaterialsList[i]]["textures"].isMember(std::to_string(k).c_str())) - { - std::string TextureID = Root["materials"][MaterialsList[i]]["textures"][std::to_string(k).c_str()].asCString(); - NewMaterial->Textures[k] = RESOURCE_MANAGER.GetTexture(TextureID); - if (NewMaterial->Textures[k] == nullptr) - NewMaterial->Textures[k] = RESOURCE_MANAGER.NoTexture; - } - } - } - - if (MembersList[j] == "textureBindings") - { - for (size_t k = 0; k < FE_MAX_TEXTURES_PER_MATERIAL; k++) - { - if (Root["materials"][MaterialsList[i]]["textureBindings"].isMember(std::to_string(k).c_str())) - { - int Binding = Root["materials"][MaterialsList[i]]["textureBindings"][std::to_string(k).c_str()].asInt(); - NewMaterial->TextureBindings[k] = Binding; - } - } - } - - if (MembersList[j] == "textureChannels") - { - for (size_t k = 0; k < FE_MAX_TEXTURES_PER_MATERIAL; k++) - { - if (Root["materials"][MaterialsList[i]]["textureChannels"].isMember(std::to_string(k).c_str())) - { - int binding = Root["materials"][MaterialsList[i]]["textureChannels"][std::to_string(k).c_str()].asInt(); - NewMaterial->TextureChannels[k] = binding; - } - } - } - } - - NewMaterial->SetMetalness(Root["materials"][MaterialsList[i]]["metalness"].asFloat()); - NewMaterial->SetRoughness(Root["materials"][MaterialsList[i]]["roughness"].asFloat()); - NewMaterial->SetNormalMapIntensity(Root["materials"][MaterialsList[i]]["normalMapIntensity"].asFloat()); - NewMaterial->SetAmbientOcclusionIntensity(Root["materials"][MaterialsList[i]]["ambientOcclusionIntensity"].asFloat()); - NewMaterial->SetAmbientOcclusionMapIntensity(Root["materials"][MaterialsList[i]]["ambientOcclusionMapIntensity"].asFloat()); - NewMaterial->SetRoughnessMapIntensity(Root["materials"][MaterialsList[i]]["roughnessMapIntensity"].asFloat()); - NewMaterial->SetMetalnessMapIntensity(Root["materials"][MaterialsList[i]]["metalnessMapIntensity"].asFloat()); - - if (ProjectVersion >= 0.02f) - { - if (Root["materials"][MaterialsList[i]].isMember("tiling")) - NewMaterial->SetTiling(Root["materials"][MaterialsList[i]]["tiling"].asFloat()); - NewMaterial->SetCompackPacking(Root["materials"][MaterialsList[i]]["compackPacking"].asBool()); - } - } - - // loading gameModels - std::vector GameModelList = Root["gameModels"].getMemberNames(); - for (size_t i = 0; i < GameModelList.size(); i++) - { - FEGameModel* NewGameModel = RESOURCE_MANAGER.CreateGameModel(RESOURCE_MANAGER.GetMesh(Root["gameModels"][GameModelList[i]]["mesh"].asCString()), - RESOURCE_MANAGER.GetMaterial(Root["gameModels"][GameModelList[i]]["material"].asCString()), - Root["gameModels"][GameModelList[i]]["name"].asString(), Root["gameModels"][GameModelList[i]]["ID"].asString()); - - NewGameModel->SetScaleFactor(Root["gameModels"][GameModelList[i]]["scaleFactor"].asFloat()); - - bool bHaveLODLevels = Root["gameModels"][GameModelList[i]]["LODs"]["haveLODlevels"].asBool(); - NewGameModel->SetUsingLOD(bHaveLODLevels); - if (bHaveLODLevels) - { - NewGameModel->SetCullDistance(Root["gameModels"][GameModelList[i]]["LODs"]["cullDistance"].asFloat()); - NewGameModel->SetBillboardZeroRotaion(Root["gameModels"][GameModelList[i]]["LODs"]["billboardZeroRotaion"].asFloat()); - - size_t LODCount = Root["gameModels"][GameModelList[i]]["LODs"]["LODCount"].asInt(); - for (size_t j = 0; j < LODCount; j++) - { - NewGameModel->SetLODMesh(j, RESOURCE_MANAGER.GetMesh(Root["gameModels"][GameModelList[i]]["LODs"][std::to_string(j)]["mesh"].asString())); - NewGameModel->SetLODMaxDrawDistance(j, Root["gameModels"][GameModelList[i]]["LODs"][std::to_string(j)]["maxDrawDistance"].asFloat()); - - bool bLODBillboard = Root["gameModels"][GameModelList[i]]["LODs"][std::to_string(j)]["isBillboard"].asBool(); - NewGameModel->SetIsLODBillboard(j, bLODBillboard); - if (bLODBillboard) - NewGameModel->SetBillboardMaterial(RESOURCE_MANAGER.GetMaterial(Root["gameModels"][GameModelList[i]]["LODs"][std::to_string(j)]["billboardMaterial"].asString())); - } - } - } - - // loading prefabs - std::vector PrefabList = Root["prefabs"].getMemberNames(); - for (size_t i = 0; i < PrefabList.size(); i++) - { - FEPrefab* NewPrefab = RESOURCE_MANAGER.CreatePrefab(nullptr, Root["prefabs"][PrefabList[i]]["name"].asString(), Root["prefabs"][PrefabList[i]]["ID"].asString()); - - if (Root["prefabs"][PrefabList[i]].isMember("components")) - { - Json::Value Components = Root["prefabs"][PrefabList[i]]["components"]; - for (int j = 0; j < static_cast(Components.size()); j++) - { - FETransformComponent ComponentTransform; - ReadTransformToJson(Components[j]["transformation"], &ComponentTransform); - - NewPrefab->AddComponent(RESOURCE_MANAGER.GetGameModel(Components[j]["gameModel"]["ID"].asCString()), ComponentTransform); - } - } - } - - // loading Terrains - std::vector TerrainList = Root["terrains"].getMemberNames(); - for (size_t i = 0; i < TerrainList.size(); i++) - { - FETerrain* NewTerrain = RESOURCE_MANAGER.CreateTerrain(false, Root["terrains"][TerrainList[i]]["name"].asString(), Root["terrains"][TerrainList[i]]["ID"].asString()); - NewTerrain->HeightMap = RESOURCE_MANAGER.LoadFEHeightmap((ProjectFolder + Root["terrains"][TerrainList[i]]["heightMap"]["fileName"].asCString()).c_str(), NewTerrain, Root["terrains"][TerrainList[i]]["heightMap"]["name"].asCString()); - - NewTerrain->SetHightScale(Root["terrains"][TerrainList[i]]["hightScale"].asFloat()); - NewTerrain->SetDisplacementScale(Root["terrains"][TerrainList[i]]["displacementScale"].asFloat()); - glm::vec2 TileMult; - TileMult.x = Root["terrains"][TerrainList[i]]["tileMult"]["X"].asFloat(); - TileMult.y = Root["terrains"][TerrainList[i]]["tileMult"]["Y"].asFloat(); - NewTerrain->SetTileMult(TileMult); - NewTerrain->SetLODLevel(Root["terrains"][TerrainList[i]]["LODlevel"].asFloat()); - NewTerrain->SetChunkPerSide(Root["terrains"][TerrainList[i]]["chunkPerSide"].asFloat()); - NewTerrain->SetHightScale(Root["terrains"][TerrainList[i]]["hightScale"].asFloat()); - NewTerrain->SetHightScale(Root["terrains"][TerrainList[i]]["hightScale"].asFloat()); - ReadTransformToJson(Root["terrains"][TerrainList[i]]["transformation"], &NewTerrain->Transform); - - if (ProjectVersion >= 0.02f) - { - for (int j = 0; j < FE_TERRAIN_MAX_LAYERS / FE_TERRAIN_LAYER_PER_TEXTURE; j++) - { - if (Root["terrains"][TerrainList[i]].isMember("layerMaps")) - { - // Not using LoadFETextureAsync because these textures could be used for instanced entities initialization. - //FETexture* loadedTexture = RESOURCE_MANAGER.LoadFETextureAsync((projectFolder + root["terrains"][terrainList[i]]["layerMaps"][j]["fileName"].asCString()).c_str(), root["terrains"][terrainList[i]]["layerMaps"][j]["name"].asString(), nullptr, root["terrains"][terrainList[i]]["layerMaps"][j]["ID"].asString()); - FETexture* LoadedTexture = RESOURCE_MANAGER.LoadFETexture((ProjectFolder + Root["terrains"][TerrainList[i]]["layerMaps"][j]["fileName"].asCString()).c_str(), Root["terrains"][TerrainList[i]]["layerMaps"][j]["name"].asString()); - NewTerrain->LayerMaps[j] = LoadedTexture; - } - } - - for (int j = 0; j < FE_TERRAIN_MAX_LAYERS; j++) - { - if (Root["terrains"][TerrainList[i]]["layers"][j]["acive"].asBool()) - { - RESOURCE_MANAGER.ActivateTerrainVacantLayerSlot(NewTerrain, RESOURCE_MANAGER.GetMaterial(Root["terrains"][TerrainList[i]]["layers"][j]["materialID"].asCString())); - NewTerrain->GetLayerInSlot(j)->SetName(Root["terrains"][TerrainList[i]]["layers"][j]["name"].asCString()); - } - } - } - - SCENE.AddTerrain(NewTerrain); - } - - // loading Entities - std::vector EntityList = Root["entities"].getMemberNames(); - for (size_t i = 0; i < EntityList.size(); i++) - { - if (Root["entities"][EntityList[i]].isMember("type")) - { - if (Root["entities"][EntityList[i]]["type"] == "FE_ENTITY_INSTANCED") - { - FEEntityInstanced* InstancedEntity = nullptr; - InstancedEntity = SCENE.AddEntityInstanced(RESOURCE_MANAGER.GetPrefab(Root["entities"][EntityList[i]]["prefab"].asCString()), - Root["entities"][EntityList[i]]["name"].asString(), - Root["entities"][EntityList[i]]["ID"].asString()); - - ReadTransformToJson(Root["entities"][EntityList[i]]["transformation"], &SCENE.GetEntity(EntityList[i])->Transform); - - InstancedEntity->SpawnInfo.Seed = Root["entities"][EntityList[i]]["spawnInfo"]["seed"].asInt(); - InstancedEntity->SpawnInfo.ObjectCount = Root["entities"][EntityList[i]]["spawnInfo"]["objectCount"].asInt(); - InstancedEntity->SpawnInfo.Radius = Root["entities"][EntityList[i]]["spawnInfo"]["radius"].asFloat(); - InstancedEntity->SpawnInfo.SetMinScale(Root["entities"][EntityList[i]]["spawnInfo"]["minScale"].asFloat()); - InstancedEntity->SpawnInfo.SetMaxScale(Root["entities"][EntityList[i]]["spawnInfo"]["maxScale"].asFloat()); - InstancedEntity->SpawnInfo.RotationDeviation.x = Root["entities"][EntityList[i]]["spawnInfo"]["rotationDeviation.x"].asFloat(); - InstancedEntity->SpawnInfo.RotationDeviation.y = Root["entities"][EntityList[i]]["spawnInfo"]["rotationDeviation.y"].asFloat(); - InstancedEntity->SpawnInfo.RotationDeviation.z = Root["entities"][EntityList[i]]["spawnInfo"]["rotationDeviation.z"].asFloat(); - - if (Root["entities"][EntityList[i]]["snappedToTerrain"].asString() != "none") - { - FETerrain* Terrain = SCENE.GetTerrain(Root["entities"][EntityList[i]]["snappedToTerrain"].asString()); - Terrain->SnapInstancedEntity(InstancedEntity); - - if (Root["entities"][EntityList[i]].isMember("terrainLayer")) - { - if (Root["entities"][EntityList[i]]["terrainLayer"].asInt() != -1) - { - Terrain->ConnectInstancedEntityToLayer(InstancedEntity, Root["entities"][EntityList[i]]["terrainLayer"].asInt()); - } - - InstancedEntity->SetMinimalLayerIntensity(Root["entities"][EntityList[i]]["minimalLayerIntensity"].asFloat()); - } - } - - InstancedEntity->Populate(InstancedEntity->SpawnInfo); - - if (Root["entities"][EntityList[i]]["modificationsToSpawn"].asBool()) - { - std::ifstream InfoFile; - InfoFile.open(ProjectFolder + InstancedEntity->GetObjectID() + ".txt"); - - std::string InfoFileData((std::istreambuf_iterator(InfoFile)), std::istreambuf_iterator()); - - Json::Value EntityFileRoot; - JSONCPP_STRING Err; - Json::CharReaderBuilder Builder; - - const std::unique_ptr Reader(Builder.newCharReader()); - if (!Reader->parse(InfoFileData.c_str(), InfoFileData.c_str() + InfoFileData.size(), &EntityFileRoot, &Err)) - return; - - size_t Count = EntityFileRoot["modifications"].size(); - for (int j = 0; j < Count; j++) - { - if (EntityFileRoot["modifications"][j]["type"].asInt() == FE_CHANGE_DELETED) - { - InstancedEntity->DeleteInstance(EntityFileRoot["modifications"][j]["index"].asInt()); - } - else if (EntityFileRoot["modifications"][j]["type"].asInt() == FE_CHANGE_MODIFIED) - { - glm::mat4 ModifedMatrix; - for (int k = 0; k < 4; k++) - { - for (int p = 0; p < 4; p++) - { - ModifedMatrix[k][p] = EntityFileRoot["modifications"][j]["modification"][k][p].asFloat(); - } - } - - InstancedEntity->ModifyInstance(EntityFileRoot["modifications"][static_cast(j)]["index"].asInt(), ModifedMatrix); - } - else if (EntityFileRoot["modifications"][j]["type"].asInt() == FE_CHANGE_ADDED) - { - glm::mat4 ModifedMatrix; - for (int k = 0; k < 4; k++) - { - for (int p = 0; p < 4; p++) - { - ModifedMatrix[k][p] = EntityFileRoot["modifications"][j]["modification"][k][p].asFloat(); - } - } - - InstancedEntity->AddInstance(ModifedMatrix); - } - } - } - } - else - { - if (Root["entities"][EntityList[i]].isMember("gameModel")) - { - FEPrefab* TempPrefab = RESOURCE_MANAGER.CreatePrefab(RESOURCE_MANAGER.GetGameModel(Root["entities"][EntityList[i]]["gameModel"].asCString())); - SCENE.AddEntity(TempPrefab, Root["entities"][EntityList[i]]["name"].asString(), Root["entities"][EntityList[i]]["ID"].asString()); - } - else - { - SCENE.AddEntity(RESOURCE_MANAGER.GetPrefab(Root["entities"][EntityList[i]]["prefab"].asCString()), - Root["entities"][EntityList[i]]["name"].asString(), - Root["entities"][EntityList[i]]["ID"].asString()); - } - - ReadTransformToJson(Root["entities"][EntityList[i]]["transformation"], &SCENE.GetEntity(EntityList[i])->Transform); - } - } - else - { - SCENE.AddEntity(RESOURCE_MANAGER.GetPrefab(Root["entities"][EntityList[i]]["prefab"].asCString()), - EntityList[i], - Root["entities"][EntityList[i]]["ID"].asString()); - ReadTransformToJson(Root["entities"][EntityList[i]]["transformation"], &SCENE.GetEntity(EntityList[i])->Transform); - } - } - - // loading Lights - std::vector LightList = Root["lights"].getMemberNames(); - for (size_t i = 0; i < LightList.size(); i++) - { - SCENE.AddLight(static_cast(Root["lights"][LightList[i]]["type"].asInt()), Root["lights"][LightList[i]]["name"].asCString(), Root["lights"][LightList[i]]["ID"].asCString()); - FELight* Light = SCENE.GetLight(LightList[i]); - - // general light information - Light->SetIntensity(Root["lights"][LightList[i]]["intensity"].asFloat()); - ReadTransformToJson(Root["lights"][LightList[i]]["transformation"], &Light->Transform); - Light->SetCastShadows(Root["lights"][LightList[i]]["castShadows"].asBool()); - Light->SetLightEnabled(Root["lights"][LightList[i]]["enabled"].asBool()); - Light->SetColor(glm::vec3(Root["lights"][LightList[i]]["color"]["R"].asFloat(), - Root["lights"][LightList[i]]["color"]["G"].asFloat(), - Root["lights"][LightList[i]]["color"]["B"].asFloat())); - Light->SetIsStaticShadowBias(Root["lights"][LightList[i]]["staticShadowBias"].asBool()); - Light->SetShadowBias(Root["lights"][LightList[i]]["shadowBias"].asFloat()); - Light->SetShadowBiasVariableIntensity(Root["lights"][LightList[i]]["shadowBiasVariableIntensity"].asFloat()); - if (ProjectVersion >= 0.02f && Root["lights"][LightList[i]].isMember("shadowBlurFactor")) - Light->SetShadowBlurFactor(Root["lights"][LightList[i]]["shadowBlurFactor"].asFloat()); - - if (Light->GetType() == FE_POINT_LIGHT) - { - reinterpret_cast(Light)->SetRange(Root["lights"][LightList[i]]["range"].asFloat()); - } - else if (Light->GetType() == FE_SPOT_LIGHT) - { - reinterpret_cast(Light)->SetSpotAngle(Root["lights"][LightList[i]]["spotAngle"].asFloat()); - reinterpret_cast(Light)->SetSpotAngleOuter(Root["lights"][LightList[i]]["spotAngleOuter"].asFloat()); - - reinterpret_cast(Light)->SetDirection(glm::vec3(Root["lights"][LightList[i]]["direction"]["X"].asFloat(), - Root["lights"][LightList[i]]["direction"]["Y"].asFloat(), - Root["lights"][LightList[i]]["direction"]["Z"].asFloat())); - } - else if (Light->GetType() == FE_DIRECTIONAL_LIGHT) - { - FEDirectionalLight* DirectionalLight = reinterpret_cast(Light); - - DirectionalLight->SetDirection(glm::vec3(Root["lights"][LightList[i]]["direction"]["X"].asFloat(), - Root["lights"][LightList[i]]["direction"]["Y"].asFloat(), - Root["lights"][LightList[i]]["direction"]["Z"].asFloat())); - - DirectionalLight->SetActiveCascades(Root["lights"][LightList[i]]["CSM"]["activeCascades"].asInt()); - DirectionalLight->SetShadowCoverage(Root["lights"][LightList[i]]["CSM"]["shadowCoverage"].asFloat()); - DirectionalLight->SetCSMZDepth(Root["lights"][LightList[i]]["CSM"]["CSMZDepth"].asFloat()); - DirectionalLight->SetCSMXYDepth(Root["lights"][LightList[i]]["CSM"]["CSMXYDepth"].asFloat()); - } - } - - // loading Effects settings - // *********** Gamma Correction & Exposure *********** - ENGINE.GetCamera()->SetGamma(Root["effects"]["Gamma Correction & Exposure"]["Gamma"].asFloat()); - ENGINE.GetCamera()->SetExposure(Root["effects"]["Gamma Correction & Exposure"]["Exposure"].asFloat()); - // *********** Anti-Aliasing(FXAA) *********** - RENDERER.SetFXAASpanMax(Root["effects"]["Anti-Aliasing(FXAA)"]["FXAASpanMax"].asFloat()); - RENDERER.SetFXAAReduceMin(Root["effects"]["Anti-Aliasing(FXAA)"]["FXAAReduceMin"].asFloat()); - RENDERER.SetFXAAReduceMul(Root["effects"]["Anti-Aliasing(FXAA)"]["FXAAReduceMul"].asFloat()); - // *********** Bloom *********** - //PPEffect = RENDERER.getPostProcessEffect("bloom"); - RENDERER.SetBloomThreshold(Root["effects"]["Bloom"]["thresholdBrightness"].asFloat()); - RENDERER.SetBloomSize(Root["effects"]["Bloom"]["BloomSize"].asFloat()); - // *********** Depth of Field *********** - RENDERER.SetDOFNearDistance(Root["effects"]["Depth of Field"]["Near distance"].asFloat()); - RENDERER.SetDOFFarDistance(Root["effects"]["Depth of Field"]["Far distance"].asFloat()); - RENDERER.SetDOFStrength(Root["effects"]["Depth of Field"]["Strength"].asFloat()); - RENDERER.SetDOFDistanceDependentStrength(Root["effects"]["Depth of Field"]["Distance dependent strength"].asFloat()); - // *********** Distance fog *********** - if (Root["effects"]["Distance fog"].isMember("isDistanceFogEnabled")) - { - RENDERER.SetDistanceFogEnabled(Root["effects"]["Distance fog"]["isDistanceFogEnabled"].asBool()); - } - else - { - RENDERER.SetDistanceFogEnabled(Root["effects"]["Distance fog"]["Density"].asFloat() > -1.0f ? true : false); - } - RENDERER.SetDistanceFogDensity(Root["effects"]["Distance fog"]["Density"].asFloat()); - RENDERER.SetDistanceFogGradient(Root["effects"]["Distance fog"]["Gradient"].asFloat()); - // *********** Chromatic Aberration *********** - RENDERER.SetChromaticAberrationIntensity(Root["effects"]["Chromatic Aberration"]["Shift strength"].asFloat()); - // *********** Sky *********** - RENDERER.SetSkyEnabled(Root["effects"]["Sky"]["Enabled"].asFloat() > 0.0f ? true : false); - RENDERER.SetDistanceToSky(Root["effects"]["Sky"]["Sphere size"].asFloat()); - - // loading Camera settings - ENGINE.GetCamera()->SetPosition(glm::vec3(Root["camera"]["position"]["X"].asFloat(), - Root["camera"]["position"]["Y"].asFloat(), - Root["camera"]["position"]["Z"].asFloat())); - - ENGINE.GetCamera()->SetFov(Root["camera"]["fov"].asFloat()); - ENGINE.GetCamera()->SetNearPlane(Root["camera"]["nearPlane"].asFloat()); - ENGINE.GetCamera()->SetFarPlane(Root["camera"]["farPlane"].asFloat()); - - ENGINE.GetCamera()->SetYaw(Root["camera"]["yaw"].asFloat()); - ENGINE.GetCamera()->SetPitch(Root["camera"]["pitch"].asFloat()); - ENGINE.GetCamera()->SetRoll(Root["camera"]["roll"].asFloat()); - - ENGINE.GetCamera()->SetAspectRatio(Root["camera"]["aspectRatio"].asFloat()); - - if (ProjectVersion >= 0.02f && Root["camera"].isMember("movementSpeed")) - ENGINE.GetCamera()->SetMovementSpeed(Root["camera"]["movementSpeed"].asFloat()); - - // VFS - if (FILE_SYSTEM.CheckFile((ProjectFolder + "VFS.txt").c_str())) - { - VIRTUAL_FILE_SYSTEM.LoadState(ProjectFolder + "VFS.txt"); - - VIRTUAL_FILE_SYSTEM.SetDirectoryReadOnly(false, "/Shaders"); - - auto Files = VIRTUAL_FILE_SYSTEM.GetDirectoryContent("/Shaders"); - for (size_t i = 0; i < Files.size(); i++) - { - VIRTUAL_FILE_SYSTEM.DeleteFile(Files[i], "/Shaders"); - } - - std::vector ShaderList = RESOURCE_MANAGER.GetShadersList(); - for (size_t i = 0; i < ShaderList.size(); i++) - { - if (OBJECT_MANAGER.GetFEObject(ShaderList[i]) == nullptr) - continue; - VIRTUAL_FILE_SYSTEM.CreateFile(OBJECT_MANAGER.GetFEObject(ShaderList[i]), "/Shaders"); - } - - std::vector StandardShaderList = RESOURCE_MANAGER.GetStandardShadersList(); - for (size_t i = 0; i < StandardShaderList.size(); i++) - { - if (OBJECT_MANAGER.GetFEObject(StandardShaderList[i]) == nullptr) - continue; - VIRTUAL_FILE_SYSTEM.CreateFile(OBJECT_MANAGER.GetFEObject(StandardShaderList[i]), "/Shaders"); - } - - VIRTUAL_FILE_SYSTEM.SetDirectoryReadOnly(true, "/Shaders"); - } - else - { - LOG.Add("Can't find VIRTUAL_FILE_SYSTEM file in project folder. Creating basic VIRTUAL_FILE_SYSTEM layout.", "FE_LOG_LOADING", FE_LOG_WARNING); - VIRTUAL_FILE_SYSTEM.CreateDirectory("Shaders", "/"); - - std::vector ShaderList = RESOURCE_MANAGER.GetShadersList(); - for (size_t i = 0; i < ShaderList.size(); i++) - { - if (OBJECT_MANAGER.GetFEObject(ShaderList[i]) == nullptr) - continue; - VIRTUAL_FILE_SYSTEM.CreateFile(OBJECT_MANAGER.GetFEObject(ShaderList[i]), "/Shaders"); - } - - std::vector StandardShaderList = RESOURCE_MANAGER.GetStandardShadersList(); - for (size_t i = 0; i < StandardShaderList.size(); i++) - { - if (OBJECT_MANAGER.GetFEObject(StandardShaderList[i]) == nullptr) - continue; - VIRTUAL_FILE_SYSTEM.CreateFile(OBJECT_MANAGER.GetFEObject(StandardShaderList[i]), "/Shaders"); - } - - std::vector MeshListForVirtualFileSystem = RESOURCE_MANAGER.GetMeshList(); - for (size_t i = 0; i < MeshListForVirtualFileSystem.size(); i++) - { - VIRTUAL_FILE_SYSTEM.CreateFile(OBJECT_MANAGER.GetFEObject(MeshListForVirtualFileSystem[i]), "/"); - } - - std::vector TextureList = RESOURCE_MANAGER.GetTextureList(); - for (size_t i = 0; i < TextureList.size(); i++) - { - bool bShouldAdd = true; - FETexture* TextureToAdd = RESOURCE_MANAGER.GetTexture(TextureList[i]); - //if (textureToAdd->getInternalFormat() == GL_R16) - //{ - // // Potentially it could be texture hight map. - // std::vector terrainList = SCENE.getTerrainList(); - // for (size_t j = 0; j < terrainList.size(); j++) - // { - // if (SCENE.getTerrain(terrainList[j])->heightMap == textureToAdd) - // { - // shouldAdd = false; - // break; - // } - // } - //} - - if (bShouldAdd) - VIRTUAL_FILE_SYSTEM.CreateFile(OBJECT_MANAGER.GetFEObject(TextureList[i]), "/"); - } - - std::vector MaterialList = RESOURCE_MANAGER.GetMaterialList(); - for (size_t i = 0; i < MaterialList.size(); i++) - { - VIRTUAL_FILE_SYSTEM.CreateFile(OBJECT_MANAGER.GetFEObject(MaterialList[i]), "/"); - } - - std::vector GameModelListForVirtualFileSystem = RESOURCE_MANAGER.GetGameModelList(); - for (size_t i = 0; i < GameModelListForVirtualFileSystem.size(); i++) - { - VIRTUAL_FILE_SYSTEM.CreateFile(OBJECT_MANAGER.GetFEObject(GameModelListForVirtualFileSystem[i]), "/"); - } - } -} - -void FEProject::CreateDummyScreenshot() -{ - const size_t Width = ENGINE.GetRenderTargetWidth(); - const size_t Height = ENGINE.GetRenderTargetHeight(); - - unsigned char* Pixels = new unsigned char[4 * Width * Height]; - for (size_t j = 0; j < Height; j++) - { - for (size_t i = 0; i < 4 * Width; i += 4) - { - Pixels[i + (j * 4 * Width)] = 0; - Pixels[i + 1 + (j * 4 * Width)] = static_cast(162); - Pixels[i + 2 + (j * 4 * Width)] = static_cast(232); - Pixels[i + 3 + (j * 4 * Width)] = static_cast(255); - } - } - - FETexture* TempTexture = RESOURCE_MANAGER.RawDataToFETexture(Pixels, static_cast(Width), static_cast(Height)); - RESOURCE_MANAGER.SaveFETexture(TempTexture, (GetProjectFolder() + "/projectScreenShot.texture").c_str()); - RESOURCE_MANAGER.DeleteFETexture(TempTexture); - delete[] Pixels; -} - -void FEProject::AddFileToDeleteList(const std::string FileName) -{ - FilesToDelete.push_back(FileName); -} - -void FEProject::LoadSceneVer0() -{ - std::ifstream SceneFile; - SceneFile.open(ProjectFolder + "scene.txt"); - - std::string FileData((std::istreambuf_iterator(SceneFile)), std::istreambuf_iterator()); - - Json::Value Root; - JSONCPP_STRING Err; - Json::CharReaderBuilder Builder; - - const std::unique_ptr Reader(Builder.newCharReader()); - if (!Reader->parse(FileData.c_str(), FileData.c_str() + FileData.size(), &Root, &Err)) - return; - - // correction for loading Meshes - std::unordered_map MeshNameToID; - MeshNameToID["sphere"] = RESOURCE_MANAGER.GetMesh("7F251E3E0D08013E3579315F")->GetObjectID(); - MeshNameToID["cube"] = RESOURCE_MANAGER.GetMesh("84251E6E0D0801363579317R")->GetObjectID(); - MeshNameToID["plane"] = RESOURCE_MANAGER.GetMesh("1Y251E6E6T78013635793156")->GetObjectID(); - // loading Meshes - std::vector MeshList = Root["meshes"].getMemberNames(); - for (size_t i = 0; i < MeshList.size(); i++) - { - RESOURCE_MANAGER.LoadFEMesh((ProjectFolder + Root["meshes"][MeshList[i]]["fileName"].asCString()).c_str(), Root["meshes"][MeshList[i]]["name"].asCString()); - MeshNameToID[Root["meshes"][MeshList[i]]["name"].asCString()] = Root["meshes"][MeshList[i]]["ID"].asCString(); - } - // correction for loading Textures - std::unordered_map TextureNameToID; - // loading Textures - std::vector TexturesList = Root["textures"].getMemberNames(); - for (size_t i = 0; i < TexturesList.size(); i++) - { - // read type of texture if it is not standard then skip it. - if (Root["textures"][TexturesList[i]]["type"] == 33322) - { - continue; - } - - FETexture* LoadedTexture = RESOURCE_MANAGER.LoadFETextureAsync((ProjectFolder + Root["textures"][TexturesList[i]]["fileName"].asCString()).c_str(), Root["textures"][TexturesList[i]]["name"].asString()); - TextureNameToID[Root["textures"][TexturesList[i]]["name"].asString()] = LoadedTexture->GetObjectID(); - } - - // correction for loading Materials - std::unordered_map MaterialNameToID; - // loading Materials - std::vector MaterialsList = Root["materials"].getMemberNames(); - for (size_t i = 0; i < MaterialsList.size(); i++) - { - FEMaterial* NewMaterial = RESOURCE_MANAGER.CreateMaterial(MaterialsList[i], Root["materials"][MaterialsList[i]]["ID"].asString()); - MaterialNameToID[MaterialsList[i]] = NewMaterial->GetObjectID(); - - //newMat->shader = RESOURCE_MANAGER.getShader("FEPhongShader"); - //newMat->shader = RESOURCE_MANAGER.getShader("FESolidColorShader"); - NewMaterial->Shader = RESOURCE_MANAGER.GetShader("0800253C242B05321A332D09"/*"FEPBRShader"*/); - - std::vector MembersList = Root["materials"][MaterialsList[i]].getMemberNames(); - for (size_t j = 0; j < MembersList.size(); j++) - { - if (MembersList[j] == "textures") - { - for (size_t k = 0; k < FE_MAX_TEXTURES_PER_MATERIAL; k++) - { - if (Root["materials"][MaterialsList[i]]["textures"].isMember(std::to_string(k).c_str())) - { - std::string TextureID = TextureNameToID[Root["materials"][MaterialsList[i]]["textures"][std::to_string(k).c_str()].asCString()]; - NewMaterial->Textures[k] = RESOURCE_MANAGER.GetTexture(TextureID); - } - } - } - - if (MembersList[j] == "textureBindings") - { - for (size_t k = 0; k < FE_MAX_TEXTURES_PER_MATERIAL; k++) - { - if (Root["materials"][MaterialsList[i]]["textureBindings"].isMember(std::to_string(k).c_str())) - { - int Binding = Root["materials"][MaterialsList[i]]["textureBindings"][std::to_string(k).c_str()].asInt(); - NewMaterial->TextureBindings[k] = Binding; - } - } - } - - if (MembersList[j] == "textureChannels") - { - for (size_t k = 0; k < FE_MAX_TEXTURES_PER_MATERIAL; k++) - { - if (Root["materials"][MaterialsList[i]]["textureChannels"].isMember(std::to_string(k).c_str())) - { - int Binding = Root["materials"][MaterialsList[i]]["textureChannels"][std::to_string(k).c_str()].asInt(); - NewMaterial->TextureChannels[k] = Binding; - } - } - } - } - - NewMaterial->SetMetalness(Root["materials"][MaterialsList[i]]["metalness"].asFloat()); - NewMaterial->SetRoughness(Root["materials"][MaterialsList[i]]["roughness"].asFloat()); - NewMaterial->SetNormalMapIntensity(Root["materials"][MaterialsList[i]]["normalMapIntensity"].asFloat()); - NewMaterial->SetAmbientOcclusionIntensity(Root["materials"][MaterialsList[i]]["ambientOcclusionIntensity"].asFloat()); - NewMaterial->SetAmbientOcclusionMapIntensity(Root["materials"][MaterialsList[i]]["ambientOcclusionMapIntensity"].asFloat()); - NewMaterial->SetRoughnessMapIntensity(Root["materials"][MaterialsList[i]]["roughnessMapIntensity"].asFloat()); - NewMaterial->SetMetalnessMapIntensity(Root["materials"][MaterialsList[i]]["metalnessMapIntensity"].asFloat()); - } - - // correction for loading gameModels - std::unordered_map GameModelNameToID; - // loading gameModels - std::vector GameModelList = Root["gameModels"].getMemberNames(); - for (size_t i = 0; i < GameModelList.size(); i++) - { - FEGameModel* NewGameModel = RESOURCE_MANAGER.CreateGameModel(RESOURCE_MANAGER.GetMesh(MeshNameToID[Root["gameModels"][GameModelList[i]]["mesh"].asCString()]), - RESOURCE_MANAGER.GetMaterial(MaterialNameToID[Root["gameModels"][GameModelList[i]]["material"].asCString()]), - GameModelList[i], Root["gameModels"][GameModelList[i]]["ID"].asString()); - GameModelNameToID[GameModelList[i]] = Root["gameModels"][GameModelList[i]]["ID"].asString(); - - NewGameModel->SetScaleFactor(Root["gameModels"][GameModelList[i]]["scaleFactor"].asFloat()); - - bool bHaveLODLevels = Root["gameModels"][GameModelList[i]]["LODs"]["haveLODlevels"].asBool(); - NewGameModel->SetUsingLOD(bHaveLODLevels); - if (bHaveLODLevels) - { - NewGameModel->SetCullDistance(Root["gameModels"][GameModelList[i]]["LODs"]["cullDistance"].asFloat()); - NewGameModel->SetBillboardZeroRotaion(Root["gameModels"][GameModelList[i]]["LODs"]["billboardZeroRotaion"].asFloat()); - - size_t LODCount = Root["gameModels"][GameModelList[i]]["LODs"]["LODCount"].asInt(); - for (size_t j = 0; j < LODCount; j++) - { - NewGameModel->SetLODMesh(j, RESOURCE_MANAGER.GetMesh(MeshNameToID[Root["gameModels"][GameModelList[i]]["LODs"][std::to_string(j)]["mesh"].asString()])); - NewGameModel->SetLODMaxDrawDistance(j, Root["gameModels"][GameModelList[i]]["LODs"][std::to_string(j)]["maxDrawDistance"].asFloat()); - - bool bLODBillboard = Root["gameModels"][GameModelList[i]]["LODs"][std::to_string(j)]["isBillboard"].asBool(); - NewGameModel->SetIsLODBillboard(j, bLODBillboard); - if (bLODBillboard) - NewGameModel->SetBillboardMaterial(RESOURCE_MANAGER.GetMaterial(MaterialNameToID[Root["gameModels"][GameModelList[i]]["LODs"][std::to_string(j)]["billboardMaterial"].asString()])); - } - } - } - - // correction for loading Terrains - std::unordered_map TerrainNameToID; - // loading Terrains - std::vector TerrainList = Root["terrains"].getMemberNames(); - for (size_t i = 0; i < TerrainList.size(); i++) - { - FETerrain* NewTerrain = RESOURCE_MANAGER.CreateTerrain(false, TerrainList[i], Root["terrains"][TerrainList[i]]["ID"].asString()); - TerrainNameToID[NewTerrain->GetName()] = NewTerrain->GetObjectID(); - NewTerrain->HeightMap = RESOURCE_MANAGER.LoadFEHeightmap((ProjectFolder + Root["terrains"][TerrainList[i]]["heightMap"]["fileName"].asCString()).c_str(), NewTerrain, Root["terrains"][TerrainList[i]]["heightMap"]["name"].asCString()); - - NewTerrain->SetHightScale(Root["terrains"][TerrainList[i]]["hightScale"].asFloat()); - NewTerrain->SetDisplacementScale(Root["terrains"][TerrainList[i]]["displacementScale"].asFloat()); - glm::vec2 TileMult; - TileMult.x = Root["terrains"][TerrainList[i]]["tileMult"]["X"].asFloat(); - TileMult.y = Root["terrains"][TerrainList[i]]["tileMult"]["Y"].asFloat(); - NewTerrain->SetTileMult(TileMult); - NewTerrain->SetLODLevel(Root["terrains"][TerrainList[i]]["LODlevel"].asFloat()); - NewTerrain->SetChunkPerSide(Root["terrains"][TerrainList[i]]["chunkPerSide"].asFloat()); - NewTerrain->SetHightScale(Root["terrains"][TerrainList[i]]["hightScale"].asFloat()); - NewTerrain->SetHightScale(Root["terrains"][TerrainList[i]]["hightScale"].asFloat()); - ReadTransformToJson(Root["terrains"][TerrainList[i]]["transformation"], &NewTerrain->Transform); - - SCENE.AddTerrain(NewTerrain); - } - - // loading Entities - std::vector EntityList = Root["entities"].getMemberNames(); - std::string EntityID; - for (size_t i = 0; i < EntityList.size(); i++) - { - if (Root["entities"][EntityList[i]].isMember("type")) - { - if (Root["entities"][EntityList[i]]["type"] == "FE_ENTITY_INSTANCED") - { - EntityID = Root["entities"][EntityList[i]]["ID"].asString(); - FEEntityInstanced* InstancedEntity = SCENE.AddEntityInstanced(RESOURCE_MANAGER.GetGameModel(GameModelNameToID[Root["entities"][EntityList[i]]["gameModel"].asCString()]), EntityList[i], EntityID); - ReadTransformToJson(Root["entities"][EntityList[i]]["transformation"], &SCENE.GetEntity(EntityID)->Transform); - - InstancedEntity->SpawnInfo.Seed = Root["entities"][EntityList[i]]["spawnInfo"]["seed"].asInt(); - InstancedEntity->SpawnInfo.ObjectCount = Root["entities"][EntityList[i]]["spawnInfo"]["objectCount"].asInt(); - InstancedEntity->SpawnInfo.Radius = Root["entities"][EntityList[i]]["spawnInfo"]["radius"].asFloat(); - InstancedEntity->SpawnInfo.SetMinScale(Root["entities"][EntityList[i]]["spawnInfo"]["minScale"].asFloat()); - InstancedEntity->SpawnInfo.SetMaxScale(Root["entities"][EntityList[i]]["spawnInfo"]["maxScale"].asFloat()); - InstancedEntity->SpawnInfo.RotationDeviation.x = Root["entities"][EntityList[i]]["spawnInfo"]["rotationDeviation.x"].asFloat(); - InstancedEntity->SpawnInfo.RotationDeviation.y = Root["entities"][EntityList[i]]["spawnInfo"]["rotationDeviation.y"].asFloat(); - InstancedEntity->SpawnInfo.RotationDeviation.z = Root["entities"][EntityList[i]]["spawnInfo"]["rotationDeviation.z"].asFloat(); - - if (Root["entities"][EntityList[i]]["snappedToTerrain"].asString() != "none") - { - FETerrain* Terrain = SCENE.GetTerrain(TerrainNameToID[Root["entities"][EntityList[i]]["snappedToTerrain"].asString()]); - Terrain->SnapInstancedEntity(InstancedEntity); - } - - InstancedEntity->Populate(InstancedEntity->SpawnInfo); - - if (Root["entities"][EntityList[i]]["modificationsToSpawn"].asBool()) - { - std::ifstream InfoFile; - InfoFile.open(ProjectFolder + InstancedEntity->GetObjectID() + ".txt"); - - std::string InfoFileData((std::istreambuf_iterator(InfoFile)), std::istreambuf_iterator()); - - Json::Value EntityFileRoot; - JSONCPP_STRING Err; - Json::CharReaderBuilder Builder; - - const std::unique_ptr Reader(Builder.newCharReader()); - if (!Reader->parse(InfoFileData.c_str(), InfoFileData.c_str() + InfoFileData.size(), &EntityFileRoot, &Err)) - return; - - size_t Count = EntityFileRoot["modifications"].size(); - for (int j = 0; j < Count; j++) - { - if (EntityFileRoot["modifications"][j]["type"].asInt() == FE_CHANGE_DELETED) - { - InstancedEntity->DeleteInstance(EntityFileRoot["modifications"][j]["index"].asInt()); - } - else if (EntityFileRoot["modifications"][j]["type"].asInt() == FE_CHANGE_MODIFIED) - { - glm::mat4 ModifedMatrix; - for (int k = 0; k < 4; k++) - { - for (int p = 0; p < 4; p++) - { - ModifedMatrix[k][p] = EntityFileRoot["modifications"][j]["modification"][k][p].asFloat(); - } - } - - InstancedEntity->ModifyInstance(EntityFileRoot["modifications"][j]["index"].asInt(), ModifedMatrix); - } - else if (EntityFileRoot["modifications"][j]["type"].asInt() == FE_CHANGE_ADDED) - { - glm::mat4 ModifedMatrix; - for (int k = 0; k < 4; k++) - { - for (int p = 0; p < 4; p++) - { - ModifedMatrix[k][p] = EntityFileRoot["modifications"][j]["modification"][k][p].asFloat(); - } - } - - InstancedEntity->AddInstance(ModifedMatrix); - } - } - } - } - else - { - SCENE.AddEntity(RESOURCE_MANAGER.GetGameModel(GameModelNameToID[Root["entities"][EntityList[i]]["gameModel"].asCString()]), EntityList[i], Root["entities"][EntityList[i]]["ID"].asString()); - ReadTransformToJson(Root["entities"][EntityList[i]]["transformation"], &SCENE.GetEntity(Root["entities"][EntityList[i]]["ID"].asString())->Transform); - } - } - else - { - SCENE.AddEntity(RESOURCE_MANAGER.GetGameModel(GameModelNameToID[Root["entities"][EntityList[i]]["gameModel"].asCString()]), EntityList[i], Root["entities"][EntityList[i]]["ID"].asString()); - ReadTransformToJson(Root["entities"][EntityList[i]]["transformation"], &SCENE.GetEntity(Root["entities"][EntityList[i]]["ID"].asString())->Transform); - } - } - - // loading Lights - std::vector LightList = Root["lights"].getMemberNames(); - for (size_t i = 0; i < LightList.size(); i++) - { - FELight* LightTest = SCENE.AddLight(static_cast(Root["lights"][LightList[i]]["type"].asInt() + 9), LightList[i]); - FELight* Light = SCENE.GetLight(LightTest->GetObjectID()); - - // general light information - Light->SetIntensity(Root["lights"][LightList[i]]["intensity"].asFloat()); - ReadTransformToJson(Root["lights"][LightList[i]]["transformation"], &Light->Transform); - Light->SetCastShadows(Root["lights"][LightList[i]]["castShadows"].asBool()); - Light->SetLightEnabled(Root["lights"][LightList[i]]["enabled"].asBool()); - Light->SetColor(glm::vec3(Root["lights"][LightList[i]]["color"]["R"].asFloat(), - Root["lights"][LightList[i]]["color"]["G"].asFloat(), - Root["lights"][LightList[i]]["color"]["B"].asFloat())); - Light->SetIsStaticShadowBias(Root["lights"][LightList[i]]["staticShadowBias"].asBool()); - Light->SetShadowBias(Root["lights"][LightList[i]]["shadowBias"].asFloat()); - Light->SetShadowBiasVariableIntensity(Root["lights"][LightList[i]]["shadowBiasVariableIntensity"].asFloat()); - - if (Light->GetType() == FE_POINT_LIGHT) - { - reinterpret_cast(Light)->SetRange(Root["lights"][LightList[i]]["range"].asFloat()); - } - else if (Light->GetType() == FE_SPOT_LIGHT) - { - reinterpret_cast(Light)->SetSpotAngle(Root["lights"][LightList[i]]["spotAngle"].asFloat()); - reinterpret_cast(Light)->SetSpotAngleOuter(Root["lights"][LightList[i]]["spotAngleOuter"].asFloat()); - - reinterpret_cast(Light)->SetDirection(glm::vec3(Root["lights"][LightList[i]]["direction"]["X"].asFloat(), - Root["lights"][LightList[i]]["direction"]["Y"].asFloat(), - Root["lights"][LightList[i]]["direction"]["Z"].asFloat())); - } - else if (Light->GetType() == FE_DIRECTIONAL_LIGHT) - { - FEDirectionalLight* DirectionalLight = reinterpret_cast(Light); - - DirectionalLight->SetDirection(glm::vec3(Root["lights"][LightList[i]]["direction"]["X"].asFloat(), - Root["lights"][LightList[i]]["direction"]["Y"].asFloat(), - Root["lights"][LightList[i]]["direction"]["Z"].asFloat())); - - DirectionalLight->SetActiveCascades(Root["lights"][LightList[i]]["CSM"]["activeCascades"].asInt()); - DirectionalLight->SetShadowCoverage(Root["lights"][LightList[i]]["CSM"]["shadowCoverage"].asFloat()); - DirectionalLight->SetCSMZDepth(Root["lights"][LightList[i]]["CSM"]["CSMZDepth"].asFloat()); - DirectionalLight->SetCSMXYDepth(Root["lights"][LightList[i]]["CSM"]["CSMXYDepth"].asFloat()); - } - } - - // loading Effects settings - // *********** Gamma Correction & Exposure *********** - ENGINE.GetCamera()->SetGamma(Root["effects"]["Gamma Correction & Exposure"]["Gamma"].asFloat()); - ENGINE.GetCamera()->SetExposure(Root["effects"]["Gamma Correction & Exposure"]["Exposure"].asFloat()); - // *********** Anti-Aliasing(FXAA) *********** - RENDERER.SetFXAASpanMax(Root["effects"]["Anti-Aliasing(FXAA)"]["FXAASpanMax"].asFloat()); - RENDERER.SetFXAAReduceMin(Root["effects"]["Anti-Aliasing(FXAA)"]["FXAAReduceMin"].asFloat()); - RENDERER.SetFXAAReduceMul(Root["effects"]["Anti-Aliasing(FXAA)"]["FXAAReduceMul"].asFloat()); - // *********** Bloom *********** - //PPEffect = RENDERER.getPostProcessEffect("bloom"); - RENDERER.SetBloomThreshold(Root["effects"]["Bloom"]["thresholdBrightness"].asFloat()); - RENDERER.SetBloomSize(Root["effects"]["Bloom"]["BloomSize"].asFloat()); - // *********** Depth of Field *********** - RENDERER.SetDOFNearDistance(Root["effects"]["Depth of Field"]["Near distance"].asFloat()); - RENDERER.SetDOFFarDistance(Root["effects"]["Depth of Field"]["Far distance"].asFloat()); - RENDERER.SetDOFStrength(Root["effects"]["Depth of Field"]["Strength"].asFloat()); - RENDERER.SetDOFDistanceDependentStrength(Root["effects"]["Depth of Field"]["Distance dependent strength"].asFloat()); - // *********** Distance fog *********** - RENDERER.SetDistanceFogEnabled(Root["effects"]["Distance fog"]["Density"].asFloat() > -1.0f ? true : false); - RENDERER.SetDistanceFogDensity(Root["effects"]["Distance fog"]["Density"].asFloat()); - RENDERER.SetDistanceFogGradient(Root["effects"]["Distance fog"]["Gradient"].asFloat()); - // *********** Chromatic Aberration *********** - RENDERER.SetChromaticAberrationIntensity(Root["effects"]["Chromatic Aberration"]["Shift strength"].asFloat()); - // *********** Sky *********** - RENDERER.SetSkyEnabled(Root["effects"]["Sky"]["Enabled"].asFloat() > 0.0f ? true : false); - RENDERER.SetDistanceToSky(Root["effects"]["Sky"]["Sphere size"].asFloat()); - - // loading Camera settings - ENGINE.GetCamera()->SetPosition(glm::vec3(Root["camera"]["position"]["X"].asFloat(), - Root["camera"]["position"]["Y"].asFloat(), - Root["camera"]["position"]["Z"].asFloat())); - - ENGINE.GetCamera()->SetFov(Root["camera"]["fov"].asFloat()); - ENGINE.GetCamera()->SetNearPlane(Root["camera"]["nearPlane"].asFloat()); - ENGINE.GetCamera()->SetFarPlane(Root["camera"]["farPlane"].asFloat()); - - ENGINE.GetCamera()->SetYaw(Root["camera"]["yaw"].asFloat()); - ENGINE.GetCamera()->SetPitch(Root["camera"]["pitch"].asFloat()); - ENGINE.GetCamera()->SetRoll(Root["camera"]["roll"].asFloat()); - - ENGINE.GetCamera()->SetAspectRatio(Root["camera"]["aspectRatio"].asFloat()); - - SceneFile.close(); -} - -bool FEProject::IsModified() -{ - return bModified; -} - -void FEProject::SetModified(const bool NewValue) -{ - bModified = NewValue; -} - -void FEProject::AddUnSavedObject(FEObject* Object) -{ - UnSavedObjects.push_back(Object); -} - -bool FEProject::ShouldIncludeInSceneFile(const FETexture* Texture) -{ - // Terrain should manage it's textures in a different way. - const std::vector TerrainList = SCENE.GetTerrainList(); - Json::Value TerrainData; - for (size_t i = 0; i < TerrainList.size(); i++) - { - const FETerrain* Terrain = SCENE.GetTerrain(TerrainList[i]); - if (Terrain->HeightMap->GetObjectID() == Texture->GetObjectID()) - return false; - - if (Terrain->LayerMaps[0] != nullptr && Terrain->LayerMaps[0]->GetObjectID() == Texture->GetObjectID()) - return false; - - if (Terrain->LayerMaps[1] != nullptr && Terrain->LayerMaps[1]->GetObjectID() == Texture->GetObjectID()) - return false; - } - - return true; -} - -void FEProject::SetProjectFolder(const std::string NewValue) -{ - if (!FILE_SYSTEM.CheckDirectory(NewValue.c_str())) - return; - - ProjectFolder = NewValue; -} - -void FEProject::SaveSceneTo(const std::string NewPath) -{ - if (!FILE_SYSTEM.CheckDirectory(NewPath.c_str())) - return; - - SetProjectFolder(NewPath); - ENGINE.TakeScreenshot((GetProjectFolder() + "projectScreenShot.texture").c_str()); - SaveScene(true); -} \ No newline at end of file diff --git a/FEProject.h b/FEProject.h deleted file mode 100644 index 33bd8b1..0000000 --- a/FEProject.h +++ /dev/null @@ -1,211 +0,0 @@ -#pragma once - -#include "../FEngine.h" -#include "FEEditorDragAndDropManager.h" -#include "FEDearImguiWrapper/FEDearImguiWrapper.h" -#include "FEEditorGizmoManager.h" -#include "FEEditorPreviewManager.h" -#include "FEEditorInternalResources.h" -#include "FEEditorVirtualFileSystem.h" - -using namespace FocalEngine; - -class FEProject -{ -public: - FEProject(std::string Name, std::string ProjectFolder); - ~FEProject(); - - std::string GetName(); - void SetName(std::string NewValue); - - std::string GetProjectFolder(); - void SaveScene(bool bFullSave = false); - void SaveSceneTo(std::string NewPath); - void LoadScene(); - void LoadSceneVer0(); - - FETexture* SceneScreenshot; - void CreateDummyScreenshot(); - - void AddFileToDeleteList(std::string FileName); - - bool IsModified(); - void SetModified(bool NewValue); - - void AddUnSavedObject(FEObject* Object); -private: - std::string Name; - std::string ProjectFolder; - bool bModified = false; - std::vector UnSavedObjects; - - void WriteTransformToJson(Json::Value& Root, const FETransformComponent* Transform); - void ReadTransformToJson(Json::Value& Root, FETransformComponent* Transform); - - std::vector FilesToDelete; - - bool ShouldIncludeInSceneFile(const FETexture* Texture); - void SetProjectFolder(std::string NewValue); -}; - -//#define PROJECTS_FOLDER "../FocalEngineProjects" -//#define PROJECTS_FOLDER "C:/Users/Kindr/Downloads/FocalEngineProjects-master" -//#define PROJECTS_FOLDER "C:/Users/Anastasiia/Desktop/FocalEngine/FEProjects" -#define PROJECTS_FILE_VER 0.02f - -class FEProjectManager -{ - std::vector List; - int IndexChosen = -1; - FEProject* Current = nullptr; - std::string CustomProjectFolder = "../FocalEngineProjects-master"; -public: - SINGLETON_PUBLIC_PART(FEProjectManager) - SINGLETON_PRIVATE_PART(FEProjectManager) - - void InitializeResources(); - - FEProject* GetCurrent(); - void SetCurrent(FEProject* Project); - - std::vector GetList(); - - void OpenProject(int ProjectIndex); - void LoadProjectList(); - void CloseCurrentProject(); - - void DisplayProjectSelection(); - - bool ContainProject(std::string Path); - void SetProjectsFolder(std::string FolderPath); -}; - -#define PROJECTS_FOLDER PROJECT_MANAGER.CustomProjectFolder.c_str() -#define PROJECT_MANAGER FEProjectManager::getInstance() - -static const char* const BASIC_SCENE = R"( - { - "camera" : - { - "aspectRatio" : 2.1216442584991455, - "farPlane" : 5000.0, - "fov" : 70.0, - "movementSpeed" : 10.0, - "nearPlane" : 0.10000000149011612, - "pitch" : 0.0, - "position" : - { - "X" : 0.0, - "Y" : 0.0, - "Z" : 0.0 - }, - "roll" : 0.0, - "yaw" : 0.0 - }, - "effects" : - { - "Anti-Aliasing_FXAA_" : - { - "FXAAReduceMin" : 0.0078125, - "FXAAReduceMul" : 0.40000000596046448, - "FXAASpanMax" : 8.0 - }, - "Bloom" : - { - "BloomSize" : 5.0, - "thresholdBrightness" : 1.0 - }, - "Chromatic Aberration" : - { - "Shift strength" : 1.0 - }, - "Depth of Field" : - { - "Distance dependent strength" : 100.0, - "Far distance" : 9000.0, - "Near distance" : 0.0, - "Strength" : 2.0 - }, - "Distance fog" : - { - "Density" : 0.0070000002160668373, - "Gradient" : 2.5 - }, - "Gamma Correction & Exposure" : - { - "Exposure" : 1.0, - "Gamma" : 2.2000000476837158 - }, - "Sky" : - { - "Enabled" : 0.0, - "Sphere size" : 50.0 - } - }, - "entities" : null, - "gameModels" : null, - "lights" : - { - "732E010E566C183C7968160F" : - { - "CSM" : - { - "CSMXYDepth" : 1.0, - "CSMZDepth" : 3.0, - "activeCascades" : 4, - "shadowCoverage" : 50.0 - }, - "ID" : "732E010E566C183C7968160F", - "castShadows" : true, - "color" : - { - "B" : 1.0, - "G" : 1.0, - "R" : 1.0 - }, - "direction" : - { - "X" : 0.0, - "Y" : 0.0, - "Z" : -1.0 - }, - "enabled" : true, - "intensity" : 1.0, - "name" : "sun", - "shadowBias" : 0.0010000000474974513, - "shadowBiasVariableIntensity" : 1.0, - "shadowBlurFactor" : 1.0, - "staticShadowBias" : false, - "transformation" : - { - "position" : - { - "X" : 0.0, - "Y" : 0.0, - "Z" : 0.0 - }, - "rotation" : - { - "X" : 0.0, - "Y" : 0.0, - "Z" : 0.0 - }, - "scale" : - { - "X" : 1.0, - "Y" : 1.0, - "Z" : 1.0, - "uniformScaling" : true - } - }, - "type" : 9 - } - }, - "materials" : null, - "meshes" : null, - "terrains" : null, - "textures" : null, - "version" : 0.019999999552965164 -} -)"; \ No newline at end of file diff --git a/FEProjectBuildSystem.cpp b/FEProjectBuildSystem.cpp new file mode 100644 index 0000000..fa831d8 --- /dev/null +++ b/FEProjectBuildSystem.cpp @@ -0,0 +1,489 @@ +#include "FEProjectBuildSystem.h" +using namespace FocalEngine; + +FEProjectBuildSystem::FEProjectBuildSystem() +{ + +} + +FEProjectBuildSystem::~FEProjectBuildSystem() +{ +} + +std::string FEProjectBuildSystem::GetVSProjectName(FEProject* ProjectToBuild) +{ + if (ProjectToBuild == nullptr) + { + LOG.Add("FEProjectBuildSystem::GetVSProjectName: ProjectToBuild is nullptr!", "FE_LOG_LOADING", FE_LOG_ERROR); + return ""; + } + + std::string AppropriateProjectName = ProjectToBuild->GetName(); + for (size_t i = 0; i < AppropriateProjectName.size(); i++) + { + if (AppropriateProjectName[i] == ' ') + AppropriateProjectName[i] = '_'; + } + + if (AppropriateProjectName.empty()) + AppropriateProjectName = "UntitledProject"; + + return AppropriateProjectName; +} + +bool FEProjectBuildSystem::CopyVisualNodeSystemSubProjectFiles(const std::string& OutputPath) +{ + if (!FILE_SYSTEM.DoesDirectoryExist(OutputPath)) + { + LOG.Add("FEProjectBuildSystem::CopyVisualNodeSystemSubProjectFiles: OutputPath does not exist!", "FE_BUILD_EXECUTABLE", FE_LOG_ERROR); + return false; + } + + // Create all needed folders. + std::vector FoldersToCreate = { "VisualNodeSystem/"}; + for (size_t i = 0; i < FoldersToCreate.size(); i++) + { + if (!FILE_SYSTEM.CreateDirectory(OutputPath + FoldersToCreate[i])) + { + LOG.Add("FEProjectBuildSystem::CopyVisualNodeSystemSubProjectFiles: Error creating " + FoldersToCreate[i] + " directory", "FE_BUILD_EXECUTABLE", FE_LOG_ERROR); + return false; + } + } + + // Place required files in the destination directory. + std::string EditorPath = FILE_SYSTEM.GetCurrentWorkingPath() + "/"; + std::string VisualNodeSystemPath = EditorPath + "SubSystems/NodeSystem/VisualNodeSystem/"; + std::vector> FilesToCopy; + FilesToCopy.push_back({ VisualNodeSystemPath + "CMakeLists.txt", OutputPath + "VisualNodeSystem/CMakeLists.txt" }); + + // Add all source files to the list. + std::vector FilesInMainFolder = FILE_SYSTEM.GetFileList(VisualNodeSystemPath); + for (size_t i = 0; i < FilesInMainFolder.size(); i++) + { + if (FilesInMainFolder[i].substr(FilesInMainFolder[i].size() - 2) == ".h" || + FilesInMainFolder[i].substr(FilesInMainFolder[i].size() - 4) == ".hpp" || + FilesInMainFolder[i].substr(FilesInMainFolder[i].size() - 4) == ".inl" || + FilesInMainFolder[i].substr(FilesInMainFolder[i].size() - 4) == ".cpp" || + FilesInMainFolder[i].substr(FilesInMainFolder[i].size() - 2) == ".c") + { + FilesToCopy.push_back({ VisualNodeSystemPath + FilesInMainFolder[i], OutputPath + "VisualNodeSystem/" + FilesInMainFolder[i] }); + } + } + + for (size_t i = 0; i < FilesToCopy.size(); i++) + { + if (!FILE_SYSTEM.CopyFile(FilesToCopy[i].first, FilesToCopy[i].second)) + { + LOG.Add("FEProjectBuildSystem::CopyVisualNodeSystemSubProjectFiles: Error copying file " + FilesToCopy[i].first + " to " + FilesToCopy[i].second, "FE_BUILD_EXECUTABLE", FE_LOG_ERROR); + return false; + } + } + + if (!FILE_SYSTEM.CopyDirectory(VisualNodeSystemPath + "SubSystems/", + OutputPath + "VisualNodeSystem/SubSystems/")) + { + LOG.Add("FEProjectBuildSystem::CopyVisualNodeSystemSubProjectFiles: Error copying directory", "FE_BUILD_EXECUTABLE", FE_LOG_ERROR); + return false; + } + + if (!FILE_SYSTEM.CopyDirectory(VisualNodeSystemPath + "ThirdParty/", + OutputPath + "VisualNodeSystem/ThirdParty/")) + { + LOG.Add("FEProjectBuildSystem::CopyVisualNodeSystemSubProjectFiles: Error copying directory", "FE_BUILD_EXECUTABLE", FE_LOG_ERROR); + return false; + } + + return true; +} + +bool FEProjectBuildSystem::BuildExecutable(FEProject* ProjectToBuild) +{ + if (ProjectToBuild == nullptr) + { + LOG.Add("FEProjectBuildSystem::BuildExecutable: ProjectToBuild is nullptr!", "FE_BUILD_EXECUTABLE", FE_LOG_ERROR); + return false; + } + + std::string VSProjectDirectory = FILE_SYSTEM.GetCurrentWorkingPath() + "/BuildProjects_Temporary/"; + if (FILE_SYSTEM.DoesDirectoryExist(VSProjectDirectory)) + { + if (!FILE_SYSTEM.DeleteDirectory(VSProjectDirectory)) + { + LOG.Add("FEProjectBuildSystem::BuildExecutable: Error deleting BuildProjects_Temporary directory", "FE_BUILD_EXECUTABLE", FE_LOG_ERROR); + return false; + } + } + + if (!FILE_SYSTEM.CreateDirectory(VSProjectDirectory)) + { + LOG.Add("FEProjectBuildSystem::BuildExecutable: Error creating BuildProjects_Temporary directory", "FE_BUILD_EXECUTABLE", FE_LOG_ERROR); + return false; + } + + VSProjectDirectory += ProjectToBuild->GetID() + "/"; + if (!FILE_SYSTEM.CreateDirectory(VSProjectDirectory)) + { + LOG.Add("FEProjectBuildSystem::BuildExecutable: Error creating project directory", "FE_BUILD_EXECUTABLE", FE_LOG_ERROR); + return false; + } + + if (!FILE_SYSTEM.DoesDirectoryExist(VSProjectDirectory)) + { + LOG.Add("FEProjectBuildSystem::BuildExecutable: VSProjectDirectory does not exist!", "FE_BUILD_EXECUTABLE", FE_LOG_ERROR); + return false; + } + + FEAssetPackage* Resources = ProjectToBuild->SaveResourcesToAssetPackage(); + Resources->SaveToFile(VSProjectDirectory + "/Resources.fepackage"); + + // Create all needed folders. + std::vector FoldersToCreate = { "SubSystems/", + "SubSystems/FocalEngine", + "ScriptModules/", + "SubSystems/FocalEngine/ResourceManager", + "SubSystems/FocalEngine/SubSystems", + "SubSystems/FocalEngine/ThirdParty", + "SubSystems/FocalEngine/ThirdParty/openxr", + "SubSystems/FocalEngine/SubSystems/FEBasicApplication", + "SubSystems/FocalEngine/SubSystems/FEBasicApplication/ThirdParty", + "SubSystems/FocalEngine/SubSystems/FEBasicApplication/ThirdParty/GLFW", + "SubSystems/FocalEngine/SubSystems/FEBasicApplication/ThirdParty/glew2" }; + + for (size_t i = 0; i < FoldersToCreate.size(); i++) + { + if (!FILE_SYSTEM.CreateDirectory(VSProjectDirectory + FoldersToCreate[i])) + { + LOG.Add("FEProjectBuildSystem::InitializeProject: Error creating " + FoldersToCreate[i] + " directory", "FE_BUILD_EXECUTABLE", FE_LOG_ERROR); + return false; + } + } + + // Place required files in the destination directory. + std::string EditorPath = FILE_SYSTEM.GetCurrentWorkingPath() + "/"; + std::vector> FilesToCopy; + FilesToCopy.push_back({ EditorPath + "/Resources/BuildScripts/Main_Template.cpp", VSProjectDirectory + "Main.cpp" }); + FilesToCopy.push_back({ EditorPath + "/Resources/BuildScripts/Main_Template.h", VSProjectDirectory + "Main.h" }); + FilesToCopy.push_back({ EditorPath + "/Resources/BuildScripts/CMakeLists_Template.txt", VSProjectDirectory + "CMakeLists.txt" }); + std::string EnginePath = FILE_SYSTEM.GetCurrentWorkingPath() + "/" + std::string(ENGINE_FOLDER) + "/"; + FilesToCopy.push_back({ EnginePath + "CMakeLists.txt", VSProjectDirectory + "SubSystems/FocalEngine/CMakeLists.txt" }); + FilesToCopy.push_back({ EnginePath + "UpdateTimestamp.cmake", VSProjectDirectory + "SubSystems/FocalEngine/UpdateTimestamp.cmake" }); + FilesToCopy.push_back({ EnginePath + "ResourceManager/Config.h.in", VSProjectDirectory + "SubSystems/FocalEngine/ResourceManager/Config.h.in" }); + FilesToCopy.push_back({ EnginePath + "ResourceManager/Timestamp.h.in", VSProjectDirectory + "SubSystems/FocalEngine/ResourceManager/Timestamp.h.in" }); + FilesToCopy.push_back({ EnginePath + "SubSystems/FEBasicApplication/CMakeLists.txt", VSProjectDirectory + "SubSystems/FocalEngine/SubSystems/FEBasicApplication/CMakeLists.txt" }); + + for (size_t i = 0; i < FilesToCopy.size(); i++) + { + if (!FILE_SYSTEM.CopyFile(FilesToCopy[i].first, FilesToCopy[i].second)) + { + LOG.Add("FEProjectBuildSystem::BuildExecutable: Error copying file " + FilesToCopy[i].first + " to " + FilesToCopy[i].second, "FE_BUILD_EXECUTABLE", FE_LOG_ERROR); + return false; + } + } + + if (!FILE_SYSTEM.CopyDirectory(EnginePath + "/SubSystems/FEBasicApplication/ThirdParty/GLFW/lib", + VSProjectDirectory + "SubSystems/FocalEngine/SubSystems/FEBasicApplication/ThirdParty/GLFW/lib")) + { + LOG.Add("FEProjectBuildSystem::InitializeProject: Error copying directory", "FE_BUILD_EXECUTABLE", FE_LOG_ERROR); + return false; + } + + if (!FILE_SYSTEM.CopyDirectory(EnginePath + "/SubSystems/FEBasicApplication/ThirdParty/glew2/lib", + VSProjectDirectory + "SubSystems/FocalEngine/SubSystems/FEBasicApplication/ThirdParty/glew2/lib")) + { + LOG.Add("FEProjectBuildSystem::InitializeProject: Error copying directory", "FE_BUILD_EXECUTABLE", FE_LOG_ERROR); + return false; + } + + if (!FILE_SYSTEM.CopyDirectory(EnginePath + "/ThirdParty/openxr/Lib", + VSProjectDirectory + "SubSystems/FocalEngine/ThirdParty/openxr/Lib")) + { + LOG.Add("FEProjectBuildSystem::InitializeProject: Error copying directory", "FE_BUILD_EXECUTABLE", FE_LOG_ERROR); + return false; + } + + if (!CopyVisualNodeSystemSubProjectFiles(VSProjectDirectory + "/SubSystems/")) + { + LOG.Add("FEProjectBuildSystem::BuildExecutable: Error copying VisualNodeSystem sub project files", "FE_BUILD_EXECUTABLE", FE_LOG_ERROR); + return false; + } + + FEAssetPackage* EngineResources = RESOURCE_MANAGER.CreatePrivateEngineAssetPackage(); + if (EngineResources == nullptr) + { + LOG.Add("FEProjectBuildSystem::BuildExecutable: Error creating private engine asset package", "FE_BUILD_EXECUTABLE", FE_LOG_ERROR); + return false; + } + EngineResources->SaveToFile(VSProjectDirectory + "/EngineResources.fepackage"); + + if (!InitializeCMakeFileAndScriptFiles(ProjectToBuild, VSProjectDirectory)) + { + LOG.Add("FEProjectBuildSystem::InitializeProject: Error initializing CMakeLists.txt", "FE_BUILD_EXECUTABLE", FE_LOG_ERROR); + return false; + } + + // Copy the engine files to the temporary directory + if (!RESOURCE_MANAGER.CopyEngineFiles(true, true, false, VSProjectDirectory)) + { + LOG.Add("FEProjectBuildSystem::BuildExecutable: Error copying engine files", "FE_BUILD_EXECUTABLE", FE_LOG_ERROR); + return false; + } + + // Build the executable + if (!ConfigureAndBuildCMake(VSProjectDirectory)) + { + LOG.Add("FEProjectBuildSystem::BuildExecutable: Error configuring and building VS Project", "FE_BUILD_EXECUTABLE", FE_LOG_ERROR); + return false; + } + + if (!CreateFinalExecutableDirectory(ProjectToBuild)) + { + LOG.Add("FEProjectBuildSystem::BuildExecutable: Error creating final executable directory", "FE_BUILD_EXECUTABLE", FE_LOG_ERROR); + return false; + } + + // Delete the temporary directory + if (!FILE_SYSTEM.DeleteDirectory(VSProjectDirectory)) + { + LOG.Add("FEProjectBuildSystem::BuildExecutable: Error deleting temporary directory", "FE_BUILD_EXECUTABLE", FE_LOG_ERROR); + return false; + } + + return true; +} + +bool FEProjectBuildSystem::InitializeCMakeFileAndScriptFiles(FEProject* ProjectToBuild, const std::string& VSProjectDirectory) +{ + if (ProjectToBuild == nullptr) + { + LOG.Add("FEProjectBuildSystem::InitializeCMakeFileAndScriptFiles: ProjectToBuild is nullptr!", "FE_BUILD_EXECUTABLE", FE_LOG_ERROR); + return false; + } + + if (VSProjectDirectory.empty()) + { + LOG.Add("FEProjectBuildSystem::InitializeCMakeFileAndScriptFiles: path is empty", "FE_BUILD_EXECUTABLE", FE_LOG_WARNING); + return false; + } + + std::vector NativeScriptModuleIDList = RESOURCE_MANAGER.GetNativeScriptModuleIDList(); + + std::string CMakeFilePath = VSProjectDirectory + "CMakeLists.txt"; + + std::vector Instructions; + FEFileSystem::TextReplacementRule CurrentInstruction; + CurrentInstruction.ContextPattern = "set(PROJECT_NAME PLACE_HOLDER)"; + CurrentInstruction.TargetText = "PLACE_HOLDER"; + CurrentInstruction.ReplacementText = GetVSProjectName(ProjectToBuild); + Instructions.push_back(CurrentInstruction); + + std::string SourceFileListString = ""; + std::string ExecutableListString = ""; + std::string FolderListInVSProjectString = ""; + + for (size_t i = 0; i < NativeScriptModuleIDList.size(); i++) + { + FENativeScriptModule* CurrentModule = RESOURCE_MANAGER.GetNativeScriptModule(NativeScriptModuleIDList[i]); + if (CurrentModule == nullptr) + { + LOG.Add("FEProjectBuildSystem::InitializeCMakeFileAndScriptFiles: Error getting native script module with ID: " + NativeScriptModuleIDList[i], "FE_BUILD_EXECUTABLE", FE_LOG_WARNING); + continue; + } + + if (CurrentModule->GetProject() == nullptr) + { + LOG.Add("FEProjectBuildSystem::InitializeCMakeFileAndScriptFiles: Error getting project of native script module with ID: " + NativeScriptModuleIDList[i], "FE_BUILD_EXECUTABLE", FE_LOG_WARNING); + continue; + } + + if (!CurrentModule->GetProject()->HasRecoverableVSProjectData()) + { + LOG.Add("FEProjectBuildSystem::InitializeCMakeFileAndScriptFiles: Project of native script module with ID: " + NativeScriptModuleIDList[i] + " does not have recoverable VS project data", "FE_BUILD_EXECUTABLE", FE_LOG_WARNING); + continue; + } + + std::vector SourceFileList = CurrentModule->GetProject()->GetSourceFileList(); + if (SourceFileList.empty()) + { + LOG.Add("FEProjectBuildSystem::InitializeCMakeFileAndScriptFiles: SourceFileList is empty for native script module with ID: " + NativeScriptModuleIDList[i], "FE_BUILD_EXECUTABLE", FE_LOG_WARNING); + continue; + } + + std::string CurrentString = "file(GLOB Script_Module_" + CurrentModule->GetObjectID() + "_SRC\n"; + for (size_t i = 0; i < SourceFileList.size(); i++) + { + CurrentString += std::string("\t\"") + "ScriptModules/" + CurrentModule->GetObjectID() + "/" + SourceFileList[i] + "\"\n"; + } + + CurrentString += ")\n"; + CurrentString += "\n"; + + SourceFileListString += CurrentString; + + // Replace the placeholder in add_executable list. + CurrentString = std::string("\t\t") + "${Script_Module_" + CurrentModule->GetObjectID() + "_SRC}\n"; + ExecutableListString += CurrentString; + + // Add the folder to the list of folders in VS project. + FolderListInVSProjectString += "source_group(\"Source Files/ScriptModules/" + CurrentModule->GetObjectID() + "/\" FILES ${Script_Module_" + CurrentModule->GetObjectID() + "_SRC})\n"; + + // Now we will create the directories and copy the files to the destination directory. + std::string ScriptModuleDirectory = VSProjectDirectory + "ScriptModules/" + CurrentModule->GetObjectID() + "/"; + if (!FILE_SYSTEM.CreateDirectory(ScriptModuleDirectory)) + { + LOG.Add("FEProjectBuildSystem::InitializeCMakeFileAndScriptFiles: Error creating directory " + ScriptModuleDirectory, "FE_BUILD_EXECUTABLE", FE_LOG_ERROR); + return false; + } + + if (!CurrentModule->GetProject()->ExtractSourceFilesTo(ScriptModuleDirectory)) + { + LOG.Add("FEProjectBuildSystem::InitializeCMakeFileAndScriptFiles: Error extracting source files to " + ScriptModuleDirectory, "FE_BUILD_EXECUTABLE", FE_LOG_ERROR); + return false; + } + } + + CurrentInstruction.ContextPattern = "#(PLACE_HOLDER) Here should be list of all script modules sources."; + CurrentInstruction.TargetText = "#(PLACE_HOLDER) Here should be list of all script modules sources."; + CurrentInstruction.ReplacementText = SourceFileListString; + Instructions.push_back(CurrentInstruction); + + CurrentInstruction.ContextPattern = " #(PLACE_HOLDER) Here should be list of all script modules."; + CurrentInstruction.TargetText = " #(PLACE_HOLDER) Here should be list of all script modules."; + CurrentInstruction.ReplacementText = ExecutableListString; + Instructions.push_back(CurrentInstruction); + + CurrentInstruction.ContextPattern = "#(PLACE_HOLDER) Here should be list of all script modules and where to place them in VS project."; + CurrentInstruction.TargetText = "#(PLACE_HOLDER) Here should be list of all script modules and where to place them in VS project."; + CurrentInstruction.ReplacementText = FolderListInVSProjectString; + Instructions.push_back(CurrentInstruction); + + if (!FILE_SYSTEM.PerformTextReplacements(CMakeFilePath, Instructions)) + { + LOG.Add("FEProjectBuildSystem::InitializeCMakeFileAndScriptFiles: Error initializing CMakeLists.txt", "FE_BUILD_EXECUTABLE", FE_LOG_ERROR); + return false; + } + Instructions.clear(); + + return true; +} + +bool FEProjectBuildSystem::ConfigureAndBuildCMake(const std::string& VSProjectDirectory) +{ + if (VSProjectDirectory.empty()) + { + LOG.Add("FEProjectBuildSystem::ConfigureAndBuildCMake: VSProjectDirectory is empty", "FE_BUILD_EXECUTABLE", FE_LOG_WARNING); + return false; + } + + std::string Generator = "Visual Studio 17 2022"; + + // CMake configure command. + std::string ConfigureCommand = "cmake -S \"" + VSProjectDirectory + "\" -B \"" + VSProjectDirectory + "\" -G \"" + Generator + "\""; + + // Execute CMake configure command. + int ConfigureResult = std::system(ConfigureCommand.c_str()); + if (ConfigureResult != 0) + { + LOG.Add("FEProjectBuildSystem::ConfigureAndBuildCMake: Error running CMake configure command", "FE_BUILD_EXECUTABLE", FE_LOG_ERROR); + return false; + } + + // Construct the CMake build command + std::string BuildCommand = "cmake --build \"" + VSProjectDirectory + "\" --config Release"; + + // Execute CMake build command + int BuildResult = std::system(BuildCommand.c_str()); + if (BuildResult != 0) + { + LOG.Add("FEProjectBuildSystem::ConfigureAndBuildCMake: Error running CMake build command", "FE_BUILD_EXECUTABLE", FE_LOG_ERROR); + return false; + } + + return true; +} + +std::string NormalizePathToWindows(const std::string& Path) +{ + std::filesystem::path FSPath(Path); + std::string Normalized = FSPath.make_preferred().string(); + + // Replace remaining forward slashes with backslashes + std::replace(Normalized.begin(), Normalized.end(), '/', '\\'); + + // Remove trailing backslash if present + if (!Normalized.empty() && Normalized.back() == '\\') + Normalized.pop_back(); + + return Normalized; +} + +bool FEProjectBuildSystem::CreateFinalExecutableDirectory(FEProject* ProjectToBuild) +{ + std::string ProjectFolder = ProjectToBuild->GetProjectFolder(); + if (!FILE_SYSTEM.DoesDirectoryExist(ProjectFolder)) + { + LOG.Add("FEProjectBuildSystem::CreateFinalExecutableDirectory: ProjectFolder does not exist!", "FE_BUILD_EXECUTABLE", FE_LOG_ERROR); + return false; + } + + std::string ExecutablePath = FILE_SYSTEM.GetCurrentWorkingPath() + "/BuildProjects_Temporary/" + ProjectToBuild->GetID() + "/Release/" + GetVSProjectName(ProjectToBuild) + ".exe"; + if (!FILE_SYSTEM.DoesFileExist(ExecutablePath)) + { + LOG.Add("FEProjectBuildSystem::CreateFinalExecutableDirectory: Executable does not exist!", "FE_BUILD_EXECUTABLE", FE_LOG_ERROR); + return false; + } + + std::string EngineResourcesPath = FILE_SYSTEM.GetCurrentWorkingPath() + "/BuildProjects_Temporary/" + ProjectToBuild->GetID() + "/EngineResources.fepackage"; + if (!FILE_SYSTEM.DoesFileExist(EngineResourcesPath)) + { + LOG.Add("FEProjectBuildSystem::CreateFinalExecutableDirectory: EngineResources.fepackage does not exist!", "FE_BUILD_EXECUTABLE", FE_LOG_ERROR); + return false; + } + + std::string ProjectResourcesPath = FILE_SYSTEM.GetCurrentWorkingPath() + "/BuildProjects_Temporary/" + ProjectToBuild->GetID() + "/Resources.fepackage"; + if (!FILE_SYSTEM.DoesFileExist(ProjectResourcesPath)) + { + LOG.Add("FEProjectBuildSystem::CreateFinalExecutableDirectory: ProjectResources.fepackage does not exist!", "FE_BUILD_EXECUTABLE", FE_LOG_ERROR); + return false; + } + + std::string FinalDirectory = ProjectFolder + "Build/"; + if (FILE_SYSTEM.DoesDirectoryExist(FinalDirectory)) + { + if (!FILE_SYSTEM.DeleteDirectory(FinalDirectory)) + { + LOG.Add("FEProjectBuildSystem::CreateFinalExecutableDirectory: Error deleting Build directory", "FE_BUILD_EXECUTABLE", FE_LOG_ERROR); + return false; + } + } + + if (!FILE_SYSTEM.CreateDirectory(FinalDirectory)) + { + LOG.Add("FEProjectBuildSystem::CreateFinalExecutableDirectory: Error creating Build directory", "FE_BUILD_EXECUTABLE", FE_LOG_ERROR); + return false; + } + + // Copy all files to the final directory. + if (!FILE_SYSTEM.CopyFile(ExecutablePath, FinalDirectory + GetVSProjectName(ProjectToBuild) + ".exe")) + { + LOG.Add("FEProjectBuildSystem::CreateFinalExecutableDirectory: Error copying executable", "FE_BUILD_EXECUTABLE", FE_LOG_ERROR); + return false; + } + + if (!FILE_SYSTEM.CopyFile(EngineResourcesPath, FinalDirectory + "EngineResources.fepackage")) + { + LOG.Add("FEProjectBuildSystem::CreateFinalExecutableDirectory: Error copying EngineResources.fepackage", "FE_BUILD_EXECUTABLE", FE_LOG_ERROR); + return false; + } + + if (!FILE_SYSTEM.CopyFile(ProjectResourcesPath, FinalDirectory + "Resources.fepackage")) + { + LOG.Add("FEProjectBuildSystem::CreateFinalExecutableDirectory: Error copying ProjectResources.fepackage", "FE_BUILD_EXECUTABLE", FE_LOG_ERROR); + return false; + } + + // Open the directory in file explorer. + std::string OpenCommand = "explorer \"" + NormalizePathToWindows(FinalDirectory) + "\""; + std::system(OpenCommand.c_str()); + + return true; +} \ No newline at end of file diff --git a/FEProjectBuildSystem.h b/FEProjectBuildSystem.h new file mode 100644 index 0000000..61b185e --- /dev/null +++ b/FEProjectBuildSystem.h @@ -0,0 +1,26 @@ +#pragma once + +#include "FEEditor.h" +using namespace FocalEngine; + +class FEProjectBuildSystem +{ +public: + SINGLETON_PUBLIC_PART(FEProjectBuildSystem) + + bool BuildExecutable(FEProject* ProjectToBuild); + bool CopyVisualNodeSystemSubProjectFiles(const std::string& OutputPath); + bool InitializeCMakeFileAndScriptFiles(FEProject* ProjectToBuild, const std::string& VSProjectDirectory); + + bool ConfigureAndBuildCMake(const std::string& VSProjectDirectory); + bool CreateFinalExecutableDirectory(FEProject* ProjectToBuild); + + // Space in project name is not allowed + std::string GetVSProjectName(FEProject* ProjectToBuild); + + //bool PackProjectResources(FEProject* ProjectToPack, const std::string& OutputPath); +private: + SINGLETON_PRIVATE_PART(FEProjectBuildSystem) +}; + +#define EDITOR_PROJECT_BUILD_SYSTEM FEProjectBuildSystem::GetInstance() diff --git a/README.md b/README.md index 8a59857..86bd096 100644 --- a/README.md +++ b/README.md @@ -2,34 +2,136 @@ ![build](https://github.com/Azzinoth/FocalEngineEditor/actions/workflows/Build.yml/badge.svg?branch=master) -The Focal Engine Editor is a comprehensive tool for the [Focal Engine](https://github.com/Azzinoth/FocalEngine/), providing a variety of utilities for creating and managing your scene. The engine has been designed to function independently from the editor, ensuring modularity. For this reason, the engine and editor are separate projects. - -Here are some images from scene created using the Focal Engine Editor: +The Focal Engine Editor is a creation environment for the [Focal Engine](https://github.com/Azzinoth/FocalEngine/), providing an suite of tools for developing 3D application/games. With an intuitive interface for scene design, entity management, and asset organization, the editor streamlines the entire development workflow from concept to deployment. It features a comprehensive project system, real-time shader editing, terrain creation tools and material editor. Importantly, the editor includes build functionality that allows developers to compile their projects into standalone executable applications with packaged resources. +⚠️ **Currently in Alpha**: Expect breaking changes and ongoing development. + ![3D scene in the Focal Engine](https://github.com/Azzinoth/FocalEngine/blob/media/1.png) ![3D scene in the Focal Engine](https://github.com/Azzinoth/FocalEngine/blob/media/2.png) -![3D scene in the Focal Engine](https://github.com/Azzinoth/FocalEngine/blob/media/3.png) ![3D scene in the Focal Engine](https://github.com/Azzinoth/FocalEngine/blob/media/4.png) -![3D scene in the Focal Engine](https://github.com/Azzinoth/FocalEngine/blob/media/5.png) +![3D scene in the Focal Engine](https://github.com/Azzinoth/FocalEngine/blob/media/6.png) + +## Table of Contents +- [Focal Engine Ecosystem](#focal-engine-ecosystem) +- [Projects Using Focal Engine](#projects-using-focal-engine) +- [Features](#features) + - [Graphical Features](#graphical-features) + - [Point Cloud Handling](#advanced-point-cloud-handling) + - [Terrain](#terrain) + - [Performance](#performance) + - [VR Support](#vr-support) + - [Entity Component System (ECS)](#entity-component-system-ecs) + - [Prefab System](#prefab-system) + - [C++ Scripting](#c-scripting) +- [Editor](#editor-overview) +- [Build and Setup](#build-system) +- [Testing](#testing) +- [Third-Party Licenses](#third-party-licenses) + +## Focal Engine Ecosystem + +The Focal Engine project consists of four modular components that work together to provide a complete development environment: + +[Basic Application Module](https://github.com/Azzinoth/FEBasicApplication) - A foundation layer for OpenGL and ImGui applications that provides essential utilities including time measurement, thread pooling, logging, TCP networking, and profiling capabilities. + +[Visual Node System](https://github.com/Azzinoth/VisualNodeSystem) - A framework for creating visual node-based interfaces with features like zoom, reroute nodes, group comments, and JSON serialization, ideal for material editors and visual scripting. + +[Focal Engine](https://github.com/Azzinoth/FocalEngine) - The engine with all core functionality. + +Focal Engine Editor (this repository) - A comprehensive editor for the engine. + +This modularity makes it easier to include just the engine in applications that don't need the editor's complexity. It also simplifies the implementation of export functionality in the editor, allowing users to compile their projects into standalone executable applications with all necessary resources. + +## Projects Using Focal Engine + +[HabiCAT 3D](https://github.com/Azzinoth/HabiCAT3D) - An open-source software that implements novel algorithms for generating multi-scale complexity metrics maps(like rugosity, fractal dimension, vector dispersion and others) for complex 3D habitat models. ## Features -The Focal Engine Editor provides the ability to load, save, create new projects, and delete existing ones through the Project Browser window: +### Graphical Features + +- Physically-based rendering +- High dynamic range (HDR) rendering internally +- Gamma correction +- Deferred shading +- Screen-Space Ambient Occlusion (SSAO) +- Cascaded soft shadows +- Sky with atmospheric scattering +- Compressed textures support with multi-threaded loading +- Fast Approximate Anti-Aliasing (FXAA) +- Dynamic render scale adjustment +- Camera temporal jitter and partial motion vector calculations, needed for future TAA and third-party upscalers +- Each camera has its own unique rendering pipeline with customizable settings + +### Advanced Point Cloud Handling + +The Focal Engine provides specialized capabilities for working with large-scale point cloud data: + +- LAS/LAZ File Format Support + + ⚠️ Work in progress ⚠️ + +- High-Performance Rendering: Support for real-time visualization of massive point clouds (hundreds of millions to billions of points) + ⚠️ Work in progress ⚠️ + +- GPU-Accelerated Editing: Tools for manipulating and editing huge point clouds directly in GPU memory + ⚠️ Work in progress ⚠️ + +### Terrain + +- Chunked terrain with tessellation for LOD +- Frustum culling of sub chunks +- Up to 8 terrain layer materials +- Each layer can define foliage spawn rules + +### VR Support + +The Focal Engine leverages OpenXR integration to provide support for a wide range of VR headsets and controllers. The engine has a virtual UI system specifically designed for comfortable and intuitive interaction in VR space. + +![3D scene in the Focal Engine](https://github.com/Azzinoth/FocalEngine/blob/media/8.png) + +### Entity Component System (ECS) + +Focal Engine employs EnTT ECS for optimized performance and flexible architecture. Easily compose entities from modular components, enabling scalable and maintainable code. + +#### Prefab System + +Easily define reusable entities or groups of entities as Prefabs. Prefabs encapsulate entities and their component configurations as scenes, allowing you to instantiate complex object setups multiple times efficiently. Prefabs simplify asset management and accelerate level design. + +### C++ Scripting: + +Attach custom scripts directly to entities for rapid prototyping, modular gameplay logic, and efficient runtime performance. + +## Performance + +Focal Engine features a GPU-driven rendering pipeline (⚠️ Work in progress ⚠️: currently not working with all entity components) that includes GPU Frustum Culling and GPU Occlusion Culling. The latter utilizes a custom Hierarchical Z-Buffer (HZB). Both culling techniques are implemented using compute shaders. These advanced optimization techniques enable the Focal Engine to render a substantial number of objects per scene (up to millions, depending on object types). + +### Profiling + +Engine submodule includes a profiling system that provides detailed analysis of CPU utilization across threads. This system is designed to handle complex, highly multithreaded workloads, allowing to identify and address performance bottlenecks. + +![3D scene in the Focal Engine](https://github.com/Azzinoth/FocalEngine/blob/media/7.png) + +## Editor Overview + +The Focal Engine Editor provides project management capabilities through its project browser window: ![Project Browser](https://github.com/Azzinoth/FocalEngineEditor/blob/media/Project%20Browser.png) -In the Editor, the following key windows are available: +The editor interface includes several key windows: -1. **Scene Entities**: Displays all objects, cameras, light sources, and terrains in the scene. -2. **Scene**: Presents the main in-game camera view. -3. **Inspector**: Provides the properties of the selected object. -4. **Content Browser**: Serves as an explorer window for the current project's virtual file system with all resources structured. +1. **Scene Entities**: Displays entities in a hierarchical graph structure. +2. **Scene/Scenes**: Supports multiple scene windows simultaneously. Prefabs are handled as simplified scenes for modular design. +3. **Inspector**: Provides list of components of the selected entity for viewing and editing. +4. **Content Browser**: Serves as an explorer for the project's virtual file system with structured access to all resources. +5. **Editor Cameras**: Provides settings for editor-specific cameras. While game cameras (entities with camera components) are only functional in game mode, editor cameras allow navigation through scenes even when no game camera is present. +6. **Log Window**: Displays filtered categories of warnings, errors, and informational messages for debugging. -![Editor](https://github.com/Azzinoth/FocalEngineEditor/blob/media/Editor.png) +![Log window](https://github.com/Azzinoth/FocalEngineEditor/blob/media/Log%20window.png) -5. **Effects Settings**: Allows adjustments of different effects available in the engine. +Standard editor layout: -![Effects Settings](https://github.com/Azzinoth/FocalEngineEditor/blob/media/Effects%20Settings.png) +![Editor](https://github.com/Azzinoth/FocalEngineEditor/blob/media/Editor.png) The Material Editor employs the [Visual Node System](https://github.com/Azzinoth/VisualNodeSystem) to enhance editing intuitiveness. @@ -39,23 +141,36 @@ Terrain editing is facilitated with different brushes (sculpt, smooth, paint lay ![Terrain](https://github.com/Azzinoth/FocalEngineEditor/blob/media/Terrain.png) -## Debugging +## Build System -Multiple additional debugging windows are available for users to toggle: +⚠️ Work in progress ⚠️ -![Debug Render Targets](https://github.com/Azzinoth/FocalEngineEditor/blob/media/Debug%20Render%20Targets.png) +The Focal Engine Editor includes functionality to compile projects into standalone executable (.exe) files, along with packaged resource files containing all necessary scripts, assets, and resources. This allows for easy distribution of completed applications without requiring the editor or engine development environment. + + +## Shader debugging Users can edit shaders on-the-fly in the built-in shader editor and debug compilation errors: ![Shader Compilation errors](https://github.com/Azzinoth/FocalEngineEditor/blob/media/Shader%20Compilation%20errors.png) +⚠️ Work in progress ⚠️ + In addition, the editor supports real-time retrieval of shader variable values from the GPU. (Please note that not all variables are supported and further testing is needed for this feature.) ![Shader values read back](https://github.com/Azzinoth/FocalEngineEditor/blob/media/Shader%20values%20read%20back.png) -The Log window will display chosen categories of warnings, errors, and info. +## Testing -![Log window](https://github.com/Azzinoth/FocalEngineEditor/blob/media/Log%20window.png) +During the development of the engine and its tools, inadequate testing was identified as a source of setbacks. To address this, a multi-layered testing approach has been implemented: + +1. **Continuous Integration** - GitHub Actions run on every push as a sanity check to ensure the engine compiles successfully. + +2. **Unit Testing** - Using Google Test framework to verify individual components. Currently limited to scene graph testing, with plans to expand coverage to more subsystems over time. + +3. **Visual Testing Platform** - Due to the graphical nature of the engine, unit tests and GitHub Actions are insufficient for comprehensive testing. A specialized testing platform is being developed that will evaluate the engine's visual output and UI functionality. + +This comprehensive testing strategy will enable more confident feature iteration and establish a proper regression testing pipeline. ## Building the Project for Visual Studio (Windows) diff --git a/Resources/BuildScripts/CMakeLists_Template.txt b/Resources/BuildScripts/CMakeLists_Template.txt new file mode 100644 index 0000000..6cd2503 --- /dev/null +++ b/Resources/BuildScripts/CMakeLists_Template.txt @@ -0,0 +1,93 @@ +cmake_minimum_required(VERSION 3.10) + +add_definitions(-DUNICODE) +add_definitions(-D_UNICODE) + +set(PROJECT_NAME PLACE_HOLDER) + +project(${PROJECT_NAME}) +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +# Set compiler flags based on USE_STATIC_RUNTIME +if(MSVC) + # Disable C4251 warning + add_compile_options(/wd4251) + + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT") + set(VISUAL_NODE_SYSTEM_USE_STATIC_RUNTIME ON CACHE BOOL "Use static runtime (/MT) instead of dynamic (/MD) for VisualNodeSystem" FORCE) + + # Always add /MP for multi-processor compilation + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP") +endif() + +# Turn on the ability to create folders to organize projects (.vcproj) +# It creates "CMakePredefinedTargets" folder by default and adds CMake +# defined projects like INSTALL.vcproj and ZERO_CHECK.vcproj +set_property(GLOBAL PROPERTY USE_FOLDERS ON) + +set(DEAR_IMGUI_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/SubSystems/FocalEngine/SubSystems/FEBasicApplication/ThirdParty/imgui CACHE PATH "Path to Dear ImGui directory." FORCE) +set(VISUAL_NODE_SYSTEM_BUILD_SHARED_LIBS OFF CACHE BOOL "Build VisualNodeSystem as a shared library" FORCE) +set(VISUAL_NODE_SYSTEM_GLFW_LIBRARY ${CMAKE_CURRENT_SOURCE_DIR}/SubSystems/FocalEngine/SubSystems/FEBasicApplication/ThirdParty/GLFW/lib/x64/glfw3_mt.lib CACHE PATH "Path to GLFW library." FORCE) + +if(NOT TARGET VisualNodeSystem) + add_subdirectory(SubSystems/VisualNodeSystem) +endif() + +if(NOT TARGET FocalEngine) + add_subdirectory(SubSystems/FocalEngine) +endif() + +# Extract the relative path of the engine folder +file(RELATIVE_PATH RELATIVE_PATH_TO_ENGINE_FOLDER "${CMAKE_CURRENT_SOURCE_DIR}" "${ENGINE_FOLDER}") +# We need to re-configure the Config.h file for the engine +# This is necessary for any project that will include FocalEngine +# to make sure that the engine can find its dependencies +set(ENGINE_FOLDER "${RELATIVE_PATH_TO_ENGINE_FOLDER}") +configure_file(${ENGINE_FOLDER}/ResourceManager/Config.h.in ${ENGINE_FOLDER}/ResourceManager/Config.h @ONLY) + +file(GLOB Main_SRC + "Main.h" + "Main.cpp" +) + +#(PLACE_HOLDER) Here should be list of all script modules sources. +link_directories(${GLEW_LIB_DIR}) +link_directories(${GLFW_LIB_DIR}) + +add_executable(${PROJECT_NAME} + WIN32 + ${Main_SRC} + #(PLACE_HOLDER) Here should be list of all script modules. +) + +target_link_libraries(${PROJECT_NAME} + PRIVATE + FEBasicApplication + VisualNodeSystem + FocalEngine + ${GLFW_LIBRARY} + ${GLEW_LIBRARY} + opengl32.lib +) + +# FocalEngine is headers-only, we need to add its include directories +target_include_directories(${PROJECT_NAME} PRIVATE ${FOCAL_ENGINE_INCLUDES}) +target_compile_definitions(${PROJECT_NAME} PRIVATE FOCAL_ENGINE_HEADERS_ONLY) + +source_group("Source Files/" FILES ${Main_SRC}) +#(PLACE_HOLDER) Here should be list of all script modules and where to place them in VS project. + +# set the startup project +set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME}) + +include_directories( + ${CMAKE_CURRENT_SOURCE_DIR} + ${GLEW_INCLUDE_DIR} + ${BASICAPP_THIRDPARTY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/SubSystems/FocalEngine/SubSystems/FEBasicApplication/ThirdParty/imgui + ${BASICAPP_DIR} + ${FOCAL_ENGINE_INCLUDES} + ${VISUAL_NODE_SYSTEM_DIR} +) \ No newline at end of file diff --git a/Resources/BuildScripts/Main_Template.cpp b/Resources/BuildScripts/Main_Template.cpp new file mode 100644 index 0000000..a74e67b --- /dev/null +++ b/Resources/BuildScripts/Main_Template.cpp @@ -0,0 +1,208 @@ +#include "Main.h" +using namespace FocalEngine; + +void LoadResources(std::string DirectoryPath) +{ + std::ifstream ResourcesFile; + ResourcesFile.open(DirectoryPath + "Resources.txt"); + + std::string FileData((std::istreambuf_iterator(ResourcesFile)), std::istreambuf_iterator()); + ResourcesFile.close(); + + Json::Value Root; + JSONCPP_STRING Error; + Json::CharReaderBuilder Builder; + + const std::unique_ptr Reader(Builder.newCharReader()); + if (!Reader->parse(FileData.c_str(), FileData.c_str() + FileData.size(), &Root, &Error)) + return; + + // Loading meshes. + std::vector MeshList = Root["Meshes"].getMemberNames(); + for (size_t i = 0; i < MeshList.size(); i++) + { + FEObjectLoadedData LoadedObjectData = RESOURCE_MANAGER.LoadFEObjectPart(Root["Meshes"][MeshList[i]]["FEObjectData"]); + RESOURCE_MANAGER.LoadFEMesh((DirectoryPath + Root["Meshes"][MeshList[i]]["FileName"].asCString()).c_str(), LoadedObjectData.Name); + } + + // Loading textures. + std::vector TexturesList = Root["Textures"].getMemberNames(); + for (size_t i = 0; i < TexturesList.size(); i++) + { + FEObjectLoadedData LoadedObjectData = RESOURCE_MANAGER.LoadFEObjectPart(Root["Textures"][TexturesList[i]]["FEObjectData"]); + // Terrain textures should be loaded right away, not async. + if (LoadedObjectData.Tag == TERRAIN_SYSTEM_RESOURCE_TAG) + { + RESOURCE_MANAGER.LoadFETexture((DirectoryPath + Root["Textures"][TexturesList[i]]["FileName"].asCString()).c_str()); + } + else + { + RESOURCE_MANAGER.LoadFETextureAsync((DirectoryPath + Root["Textures"][TexturesList[i]]["FileName"].asCString()).c_str(), LoadedObjectData.Name, nullptr, LoadedObjectData.ID); + } + } + + // Loading materials. + std::vector MaterialsList = Root["Materials"].getMemberNames(); + for (size_t i = 0; i < MaterialsList.size(); i++) + { + if (RESOURCE_MANAGER.LoadMaterialFromJSON(Root["Materials"][MaterialsList[i]]) == nullptr) + LOG.Add("FEProject::LoadResources: Error loading material " + MaterialsList[i], "FE_LOG_LOADING", FE_LOG_ERROR); + } + + // Loading game models. + std::vector GameModelList = Root["GameModels"].getMemberNames(); + for (size_t i = 0; i < GameModelList.size(); i++) + { + if (RESOURCE_MANAGER.LoadGameModelFromJSON(Root["GameModels"][GameModelList[i]]) == nullptr) + LOG.Add("FEProject::LoadResources: Error loading game model " + GameModelList[i], "FE_LOG_LOADING", FE_LOG_ERROR); + } + + // Loading NativeScriptModules. + std::vector NativeScriptModulesList = Root["NativeScriptModules"].getMemberNames(); + for (size_t i = 0; i < NativeScriptModulesList.size(); i++) + { + FENativeScriptModule* LoadedNativeScriptModule = RESOURCE_MANAGER.LoadFENativeScriptModule((DirectoryPath + Root["NativeScriptModules"][NativeScriptModulesList[i]]["FileName"].asCString()).c_str()); + if (LoadedNativeScriptModule == nullptr) + continue; + + NATIVE_SCRIPT_SYSTEM.ActivateNativeScriptModule(LoadedNativeScriptModule); + } + + // Prefabs and Scenes are interconnected so we need to load them in two steps. + // Currently Prefabs can not contain other Prefabs or Scenes, if it will change we need to change this code. + // First load all prefab scenes. + std::vector SceneList = Root["Scenes"].getMemberNames(); + for (size_t i = 0; i < SceneList.size(); i++) + { + FEObjectLoadedData LoadedObjectData = RESOURCE_MANAGER.LoadFEObjectPart(Root["Scenes"][SceneList[i]]["FEObjectData"]); + if (LoadedObjectData.Tag != PREFAB_SCENE_DESCRIPTION_TAG) + continue; + + if (SCENE_MANAGER.LoadSceneFromJSON(Root["Scenes"][SceneList[i]], FESceneFlag::PrefabDescription) == nullptr) + LOG.Add("FEProject::LoadResources: Error loading scene " + SceneList[i], "FE_LOG_LOADING", FE_LOG_ERROR); + } + + // Then load Prefabs and initialize them with corresponding scenes. + std::vector PrefabList = Root["Prefabs"].getMemberNames(); + for (size_t i = 0; i < PrefabList.size(); i++) + { + if (RESOURCE_MANAGER.LoadPrefabFromJSON(Root["Prefabs"][PrefabList[i]]) == nullptr) + LOG.Add("FEProject::LoadResources: Error loading prefab " + PrefabList[i], "FE_LOG_LOADING", FE_LOG_ERROR); + } + + for (size_t i = 0; i < SceneList.size(); i++) + { + FEObjectLoadedData LoadedObjectData = RESOURCE_MANAGER.LoadFEObjectPart(Root["Scenes"][SceneList[i]]["FEObjectData"]); + if (LoadedObjectData.Tag == PREFAB_SCENE_DESCRIPTION_TAG) + continue; + + if (SCENE_MANAGER.LoadSceneFromJSON(Root["Scenes"][SceneList[i]], FESceneFlag::Active) == nullptr) + LOG.Add("FEProject::LoadResources: Error loading scene " + SceneList[i], "FE_LOG_LOADING", FE_LOG_ERROR); + } +} + +void LoadResourcesFromAssetPackage(FEAssetPackage* AssetPackage) +{ + if (AssetPackage == nullptr) + { + LOG.Add("FEProject::LoadResourcesFromAssetPackage: AssetPackage is nullptr!", "FE_LOG_LOADING", FE_LOG_ERROR); + return; + } + + std::string TemporaryFolder = FILE_SYSTEM.GetCurrentWorkingPath() + "/Temporary_Project_Resources/"; + if (FILE_SYSTEM.DoesDirectoryExist(TemporaryFolder)) + { + LOG.Add("FEProject::LoadResourcesFromAssetPackage: Temporary_Project_Resources directory already exist, trying to delete it.", "FE_LOG_LOADING", FE_LOG_WARNING); + + if (!FILE_SYSTEM.DeleteDirectory(TemporaryFolder)) + { + LOG.Add("FEProject::LoadResourcesFromAssetPackage: Error deleting Temporary_Project_Resources directory", "FE_LOG_LOADING", FE_LOG_ERROR); + return; + } + } + + if (!FILE_SYSTEM.CreateDirectory(TemporaryFolder)) + { + LOG.Add("FEProject::LoadResourcesFromAssetPackage: Error creating Temporary_Project_Resources directory", "FE_LOG_LOADING", FE_LOG_ERROR); + return; + } + + // Exporting all assets to files. + std::vector AssetList = AssetPackage->GetEntryList(); + for (size_t i = 0; i < AssetList.size(); i++) + { + if (!AssetPackage->ExportAssetToFile(AssetList[i].ID, TemporaryFolder + AssetList[i].Name)) + { + LOG.Add("FEProject::LoadResourcesFromAssetPackage: Error exporting asset " + AssetList[i].Name + " to file", "FE_LOG_LOADING", FE_LOG_WARNING); + continue; + } + } + + LoadResources(TemporaryFolder); + + if (!FILE_SYSTEM.DeleteDirectory(TemporaryFolder)) + LOG.Add("FEProject::LoadResourcesFromAssetPackage: Error deleting Temporary_Project_Resources directory", "FE_LOG_LOADING", FE_LOG_WARNING); +} + +FEEntity* CameraEntity = nullptr; +void mouseButtonCallback(int Button, int Action, int Mods) +{ + if (Button == GLFW_MOUSE_BUTTON_2 && Action == GLFW_PRESS) + { + if (CameraEntity != nullptr) + CameraEntity->GetComponent().SetActive(true); + } + else if (Button == GLFW_MOUSE_BUTTON_2 && Action == GLFW_RELEASE) + { + if (CameraEntity != nullptr) + CameraEntity->GetComponent().SetActive(false); + } +} + +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) +{ + ENGINE.InitWindow(); + THREAD_POOL.SetConcurrentThreadCount(10); + + // Here we need to load all resources + // And then load main scene? + FEAssetPackage* AssetPackage = new FEAssetPackage(); + if (!AssetPackage->LoadFromFile("Resources.fepackage")) + { + LOG.Add("Error: loading asset package", "FE_STARTING_APPLICATION", FE_LOG_ERROR); + return 1; + } + + LoadResourcesFromAssetPackage(AssetPackage); + + FEScene* StartingScene = SCENE_MANAGER.GetStartingScene(); + if (StartingScene == nullptr) + { + LOG.Add("Error: no starting scene", "FE_STARTING_APPLICATION", FE_LOG_ERROR); + return 1; + } + + StartingScene->SetFlag(FESceneFlag::Active | FESceneFlag::Renderable | FESceneFlag::GameMode, true); + + CameraEntity = CAMERA_SYSTEM.GetMainCamera(StartingScene); + if (CameraEntity != nullptr) + { + FECameraComponent& CameraComponent = CameraEntity->GetComponent(); + CAMERA_SYSTEM.SetCameraViewport(CameraEntity, ENGINE.GetDefaultViewport()->GetID()); + } + else + { + LOG.Add("Error: no camera in starting scene", "FE_STARTING_APPLICATION", FE_LOG_ERROR); + } + + INPUT.AddMouseButtonCallback(mouseButtonCallback); + + while (ENGINE.IsNotTerminated()) + { + ENGINE.BeginFrame(); + ENGINE.Render(); + ENGINE.EndFrame(); + } + + return 0; +} \ No newline at end of file diff --git a/Resources/BuildScripts/Main_Template.h b/Resources/BuildScripts/Main_Template.h new file mode 100644 index 0000000..959b1f8 --- /dev/null +++ b/Resources/BuildScripts/Main_Template.h @@ -0,0 +1,9 @@ +#include "SubSystems/FocalEngine/FEngine.h" +using namespace FocalEngine; + +// FIX ME! Move that to a RESOURCE_MANAGER +void LoadResources(std::string DirectoryPath); + +// TO-DO: Make that process in memory, not involving creating temporary files. +//FEAssetPackage* SaveResourcesToAssetPackage(); +void LoadResourcesFromAssetPackage(FEAssetPackage* AssetPackage); \ No newline at end of file diff --git a/Resources/Images/AssetPackage_ContentBrowser_32_32_Icon.png b/Resources/Images/AssetPackage_ContentBrowser_32_32_Icon.png new file mode 100644 index 0000000..215bff3 Binary files /dev/null and b/Resources/Images/AssetPackage_ContentBrowser_32_32_Icon.png differ diff --git a/Resources/Images/AssetPackage_ContentBrowser_Icon.png b/Resources/Images/AssetPackage_ContentBrowser_Icon.png new file mode 100644 index 0000000..4cfe7c0 Binary files /dev/null and b/Resources/Images/AssetPackage_ContentBrowser_Icon.png differ diff --git a/Resources/Images/NativeScriptModule_ContentBrowser_32_32_Icon.png b/Resources/Images/NativeScriptModule_ContentBrowser_32_32_Icon.png new file mode 100644 index 0000000..b20691c Binary files /dev/null and b/Resources/Images/NativeScriptModule_ContentBrowser_32_32_Icon.png differ diff --git a/Resources/Images/NativeScriptModule_ContentBrowser_Icon.png b/Resources/Images/NativeScriptModule_ContentBrowser_Icon.png new file mode 100644 index 0000000..cb12103 Binary files /dev/null and b/Resources/Images/NativeScriptModule_ContentBrowser_Icon.png differ diff --git a/Resources/Images/Scene_ContentBrowser_Icon.png b/Resources/Images/Scene_ContentBrowser_Icon.png new file mode 100644 index 0000000..fbc9547 Binary files /dev/null and b/Resources/Images/Scene_ContentBrowser_Icon.png differ diff --git a/Resources/Images/Shader_ContentBrowser_32_32_Icon.png b/Resources/Images/Shader_ContentBrowser_32_32_Icon.png new file mode 100644 index 0000000..9dfc460 Binary files /dev/null and b/Resources/Images/Shader_ContentBrowser_32_32_Icon.png differ diff --git a/Resources/Images/originals/House.png b/Resources/Images/originals/House.png new file mode 100644 index 0000000..29a7d7e Binary files /dev/null and b/Resources/Images/originals/House.png differ diff --git a/Resources/Images/originals/Scene.png b/Resources/Images/originals/Scene.png new file mode 100644 index 0000000..4cfe7c0 Binary files /dev/null and b/Resources/Images/originals/Scene.png differ diff --git a/Resources/Images/originals/box-open.png b/Resources/Images/originals/box-open.png new file mode 100644 index 0000000..4dc5684 Binary files /dev/null and b/Resources/Images/originals/box-open.png differ diff --git a/Resources/Images/originals/box-open_2.png b/Resources/Images/originals/box-open_2.png new file mode 100644 index 0000000..2456144 Binary files /dev/null and b/Resources/Images/originals/box-open_2.png differ diff --git a/Resources/Images/originals/box-open_c++.png b/Resources/Images/originals/box-open_c++.png new file mode 100644 index 0000000..c963b4c Binary files /dev/null and b/Resources/Images/originals/box-open_c++.png differ diff --git a/Resources/Images/originals/c-.png b/Resources/Images/originals/c-.png new file mode 100644 index 0000000..4b952af Binary files /dev/null and b/Resources/Images/originals/c-.png differ diff --git a/Resources/Images/originals/script.png b/Resources/Images/originals/script.png new file mode 100644 index 0000000..cb12103 Binary files /dev/null and b/Resources/Images/originals/script.png differ diff --git a/Resources/imgui.ini b/Resources/imgui.ini index d781fa9..aa1f0ff 100644 --- a/Resources/imgui.ini +++ b/Resources/imgui.ini @@ -1,61 +1,61 @@ [Window][Debug##Default] Pos=2513,531 Size=1344,1062 -Collapsed=0 +Collapsed=1 [Window][Scene Entities] Pos=0,28 -Size=504,954 +Size=504,1604 Collapsed=0 DockId=0x00000001,0 [Window][Content Browser] -Pos=0,984 -Size=2564,437 +Pos=0,1634 +Size=3840,437 Collapsed=0 DockId=0x00000003,0 [Window][Scene] Pos=506,28 -Size=1590,954 +Size=2866,1604 Collapsed=0 DockId=0x0000000B,0 [Window][Inspector] -Pos=2098,28 -Size=466,954 +Pos=3374,28 +Size=466,1604 Collapsed=0 DockId=0x00000008,0 [Window][Effects settings] -Pos=0,984 -Size=2564,437 +Pos=0,1634 +Size=3840,437 Collapsed=0 DockId=0x00000003,1 [Window][Log] -Pos=0,984 -Size=2564,437 +Pos=0,1634 +Size=3840,437 Collapsed=0 DockId=0x00000003,2 [Window][DockSpaceViewport_11111111] Pos=0,28 -Size=2564,1393 +Size=3840,2043 Collapsed=0 [Window][##create project] -Pos=0,1331 -Size=2564,90 +Pos=0,1981 +Size=3840,90 Collapsed=0 [Window][Project Browser] Pos=0,0 -Size=2564,1331 +Size=3840,1981 Collapsed=0 [Window][##GizmosSettingsWindow] -Pos=1207,10 +Pos=1845,10 Size=146,48 Collapsed=0 @@ -74,8 +74,8 @@ Pos=2271,895 Collapsed=0 [Window][dragAndDrop info] -Pos=1688,1268 -Size=313,212 +Pos=119,511 +Size=271,80 Collapsed=0 [Window][Edit material: tree_stump] @@ -938,22 +938,34 @@ Pos=60,60 Size=241,88 Collapsed=0 +[Window][Main Scene] +Pos=506,28 +Size=2866,1604 +Collapsed=0 +DockId=0x0000000B,0 + +[Window][Editor Cameras] +Pos=0,1698 +Size=3840,437 +Collapsed=0 +DockId=0x00000003,1 + [Table][0xD0F0C6E3,2] Column 0 Weight=1.0000 Column 1 Weight=1.0000 [Docking][Data] -DockSpace ID=0x8B93E3BD Window=0xA787BDB4 Pos=0,28 Size=2564,1393 Split=Y +DockSpace ID=0x8B93E3BD Window=0xA787BDB4 Pos=0,28 Size=3840,2107 Split=Y DockNode ID=0x00000005 Parent=0x8B93E3BD SizeRef=2524,1357 Split=Y Selected=0x18B8C0DE DockNode ID=0x00000002 Parent=0x00000005 SizeRef=3319,1604 Split=Y DockNode ID=0x00000009 Parent=0x00000002 SizeRef=2691,835 Split=X Selected=0x18B8C0DE DockNode ID=0x00000001 Parent=0x00000009 SizeRef=504,1537 Selected=0xB364B046 DockNode ID=0x00000004 Parent=0x00000009 SizeRef=1418,1537 Split=X Selected=0x18B8C0DE DockNode ID=0x00000007 Parent=0x00000004 SizeRef=2866,1256 Split=Y Selected=0x18B8C0DE - DockNode ID=0x0000000B Parent=0x00000007 SizeRef=2430,663 CentralNode=1 Selected=0xE192E354 + DockNode ID=0x0000000B Parent=0x00000007 SizeRef=2430,663 CentralNode=1 Selected=0x0B02E23B DockNode ID=0x0000000C Parent=0x00000007 SizeRef=2430,661 Selected=0x1DE2844E DockNode ID=0x00000008 Parent=0x00000004 SizeRef=466,1256 Selected=0xE7039252 DockNode ID=0x0000000A Parent=0x00000002 SizeRef=2691,700 Selected=0xA36F5690 - DockNode ID=0x00000003 Parent=0x00000005 SizeRef=3319,437 Selected=0x64F50EE5 + DockNode ID=0x00000003 Parent=0x00000005 SizeRef=3319,437 Selected=0xBF096F38 DockNode ID=0x00000006 Parent=0x8B93E3BD SizeRef=2524,771 Selected=0x81459842 diff --git a/SubSystems/FocalEngine b/SubSystems/FocalEngine index 8090483..34dd4a5 160000 --- a/SubSystems/FocalEngine +++ b/SubSystems/FocalEngine @@ -1 +1 @@ -Subproject commit 80904837b1f47b77c04a9855901234f25ac3f120 +Subproject commit 34dd4a572bb18f0e7f9269ab8411cc2fd51d0ee1 diff --git a/SubSystems/NodeSystem/CustomNodes/FEEditorMaterialNode.cpp b/SubSystems/NodeSystem/CustomNodes/FEEditorMaterialNode.cpp index e8363f2..155f157 100644 --- a/SubSystems/NodeSystem/CustomNodes/FEEditorMaterialNode.cpp +++ b/SubSystems/NodeSystem/CustomNodes/FEEditorMaterialNode.cpp @@ -46,20 +46,20 @@ void FEEditorMaterialNode::Draw() ImGui::Text("Compact packing"); Data->SetCompackPacking(bCompactFlag); - FEShaderParam* DebugFlag = Data->GetParameter("debugFlag"); - if (DebugFlag != nullptr) + FEShaderUniformValue CurrentValue; + if (Data->Shader->GetUniformData("debugFlag", CurrentValue)) { CurrentPosition.y += FieldStep; ImGui::SetCursorScreenPos(CurrentPosition); ImGui::Text("Debug flag:"); - int IData = *static_cast(DebugFlag->Data); + int IData = CurrentValue.GetValue(); CurrentPosition.y += FieldStep; ImGui::SetCursorScreenPos(CurrentPosition); ImGui::SetNextItemWidth(FieldWidth); ImGui::SliderInt("##Debug flag", &IData, 0, 10); - Data->Shader->UpdateParameterData("debugFlag", &IData); + Data->Shader->UpdateUniformData("debugFlag", IData); } // ************* Normal ************* diff --git a/SubSystems/NodeSystem/CustomNodes/FEEditorTextureSourceNode.cpp b/SubSystems/NodeSystem/CustomNodes/FEEditorTextureSourceNode.cpp index 81e9d46..9ffd2f1 100644 --- a/SubSystems/NodeSystem/CustomNodes/FEEditorTextureSourceNode.cpp +++ b/SubSystems/NodeSystem/CustomNodes/FEEditorTextureSourceNode.cpp @@ -2,7 +2,7 @@ using namespace FocalEngine; using namespace VisNodeSys; -bool FEEditorTextureSourceNode::isRegistered = []() +bool FEEditorTextureSourceNode::IsRegistered = []() { NODE_FACTORY.RegisterNodeType("FEEditorTextureSourceNode", []() -> Node* { diff --git a/SubSystems/NodeSystem/CustomNodes/FEEditorTextureSourceNode.h b/SubSystems/NodeSystem/CustomNodes/FEEditorTextureSourceNode.h index 1ab5e1c..7d640d2 100644 --- a/SubSystems/NodeSystem/CustomNodes/FEEditorTextureSourceNode.h +++ b/SubSystems/NodeSystem/CustomNodes/FEEditorTextureSourceNode.h @@ -7,7 +7,7 @@ using namespace FocalEngine; class FEEditorTextureSourceNode : public VisNodeSys::Node { friend class NodeFactory; - static bool isRegistered; + static bool IsRegistered; FETexture* Texture = nullptr; diff --git a/SubSystems/NodeSystem/VisualNodeSystem b/SubSystems/NodeSystem/VisualNodeSystem index ff367bd..11e16ec 160000 --- a/SubSystems/NodeSystem/VisualNodeSystem +++ b/SubSystems/NodeSystem/VisualNodeSystem @@ -1 +1 @@ -Subproject commit ff367bda047c6583089c5698a091086fac4c924c +Subproject commit 11e16eca0e0d4e38816d4ee955f06442cb78e537 diff --git a/SubSystems/ProjectManagment/FEProject.cpp b/SubSystems/ProjectManagment/FEProject.cpp new file mode 100644 index 0000000..c47f35e --- /dev/null +++ b/SubSystems/ProjectManagment/FEProject.cpp @@ -0,0 +1,1004 @@ +#include "FEProject.h" +#include "../../FEEditor.h" + +FEProject::FEProject(const std::string Name, const std::string ProjectFolder) +{ + ID = APPLICATION.GetUniqueHexID(); + this->Name = Name; + this->ProjectFolder = ProjectFolder; + + std::ifstream ScreenshotFile((this->GetProjectFolder() + "Thumbnail.texture").c_str()); + + if (!ScreenshotFile.good()) + { + SceneScreenshot = RESOURCE_MANAGER.NoTexture; +} + else + { + SceneScreenshot = RESOURCE_MANAGER.LoadFETextureUnmanaged((this->GetProjectFolder() + "Thumbnail.texture").c_str()); + } + ScreenshotFile.close(); +} + +FEProject::~FEProject() +{ + if (SceneScreenshot != RESOURCE_MANAGER.NoTexture) + delete SceneScreenshot; + + RESOURCE_MANAGER.Clear(); + VIRTUAL_FILE_SYSTEM.Clear(); + SCENE_MANAGER.Clear(); +} + +std::string FEProject::GetName() +{ + return Name; +} + +void FEProject::SetName(const std::string NewValue) +{ + Name = NewValue; +} + +std::string FEProject::GetProjectFolder() +{ + return ProjectFolder; +} + +void FEProject::SaveResources(std::string DirectoryPath, bool bFullSave) +{ + Json::Value Root; + std::ofstream ResourcesFile; + + Root["Version"] = PROJECT_RESOURCE_FILE_VERSION; + Root["ProjectID"] = ID; + + if (!bFullSave) + { + // Saving all unsaved objects. + for (size_t i = 0; i < UnSavedObjects.size(); i++) + { + switch (UnSavedObjects[i]->GetType()) + { + case FE_MESH: + { + FEMesh* MeshToSave = RESOURCE_MANAGER.GetMesh(UnSavedObjects[i]->GetObjectID()); + if (MeshToSave != nullptr) + RESOURCE_MANAGER.SaveFEMesh(MeshToSave, (DirectoryPath + MeshToSave->GetObjectID() + std::string(".model")).c_str()); + break; + } + + case FE_TEXTURE: + { + FETexture* TextureToSave = RESOURCE_MANAGER.GetTexture(UnSavedObjects[i]->GetObjectID()); + if (TextureToSave != nullptr) + RESOURCE_MANAGER.SaveFETexture(TextureToSave, (DirectoryPath + TextureToSave->GetObjectID() + std::string(".texture")).c_str()); + break; + } + } + } + } + + // Saving Meshes. + std::vector MeshList = RESOURCE_MANAGER.GetMeshIDList(); + Json::Value MeshData; + for (size_t i = 0; i < MeshList.size(); i++) + { + FEMesh* Mesh = RESOURCE_MANAGER.GetMesh(MeshList[i]); + if (Mesh->GetTag() == ENGINE_RESOURCE_TAG || + Mesh->GetTag() == EDITOR_RESOURCE_TAG) + continue; + + MeshData[Mesh->GetObjectID()]["FEObjectData"] = RESOURCE_MANAGER.SaveFEObjectPart(Mesh); + MeshData[Mesh->GetObjectID()]["FileName"] = Mesh->GetObjectID() + ".model"; + + if (bFullSave) + RESOURCE_MANAGER.SaveFEMesh(Mesh, (DirectoryPath + Mesh->GetObjectID() + std::string(".model")).c_str()); + + Mesh->SetDirtyFlag(false); + } + Root["Meshes"] = MeshData; + + // Saving Textures. + std::vector TexturesList = RESOURCE_MANAGER.GetTextureIDList(); + Json::Value TexturesData; + for (size_t i = 0; i < TexturesList.size(); i++) + { + FETexture* Texture = RESOURCE_MANAGER.GetTexture(TexturesList[i]); + if (Texture->GetTag() == ENGINE_RESOURCE_TAG || + Texture->GetTag() == EDITOR_RESOURCE_TAG) + continue; + + TexturesData[Texture->GetObjectID()]["FEObjectData"] = RESOURCE_MANAGER.SaveFEObjectPart(Texture); + TexturesData[Texture->GetObjectID()]["FileName"] = Texture->GetObjectID() + ".texture"; + + if (bFullSave) + RESOURCE_MANAGER.SaveFETexture(Texture, (DirectoryPath + Texture->GetObjectID() + std::string(".texture")).c_str()); + + Texture->SetDirtyFlag(false); + } + Root["Textures"] = TexturesData; + + // Saving Materials. + std::vector MaterialList = RESOURCE_MANAGER.GetMaterialIDList(); + Json::Value MaterialData; + for (size_t i = 0; i < MaterialList.size(); i++) + { + FEMaterial* Material = RESOURCE_MANAGER.GetMaterial(MaterialList[i]); + if (Material->GetTag() == ENGINE_RESOURCE_TAG || + Material->GetTag() == EDITOR_RESOURCE_TAG) + continue; + + MaterialData[Material->GetObjectID()] = RESOURCE_MANAGER.SaveMaterialToJSON(Material); + Material->SetDirtyFlag(false); + } + Root["Materials"] = MaterialData; + + // Saving GameModels. + std::vector GameModelList = RESOURCE_MANAGER.GetGameModelIDList(); + Json::Value GameModelData; + for (size_t i = 0; i < GameModelList.size(); i++) + { + FEGameModel* GameModel = RESOURCE_MANAGER.GetGameModel(GameModelList[i]); + if (GameModel->GetTag() == ENGINE_RESOURCE_TAG || + GameModel->GetTag() == EDITOR_RESOURCE_TAG) + continue; + + GameModelData[GameModel->GetObjectID()] = RESOURCE_MANAGER.SaveGameModelToJSON(GameModel); + GameModel->SetDirtyFlag(false); + } + Root["GameModels"] = GameModelData; + + // Saving Prefabs. + std::vector PrefabList = RESOURCE_MANAGER.GetPrefabIDList(); + Json::Value PrefabData; + for (size_t i = 0; i < PrefabList.size(); i++) + { + FEPrefab* Prefab = RESOURCE_MANAGER.GetPrefab(PrefabList[i]); + if (Prefab->GetTag() == ENGINE_RESOURCE_TAG || + Prefab->GetTag() == EDITOR_RESOURCE_TAG) + continue; + + PrefabData[Prefab->GetObjectID()] = RESOURCE_MANAGER.SavePrefabToJSON(Prefab); + } + Root["Prefabs"] = PrefabData; + + // Saving NativeScriptModules. + Json::Value NativeScriptModulesData; + std::vector NativeScriptModulesList = RESOURCE_MANAGER.GetNativeScriptModuleIDList(); + for (size_t i = 0; i < NativeScriptModulesList.size(); i++) + { + FENativeScriptModule* NativeScriptModule = RESOURCE_MANAGER.GetNativeScriptModule(NativeScriptModulesList[i]); + if (NativeScriptModule->GetTag() == ENGINE_RESOURCE_TAG || + NativeScriptModule->GetTag() == EDITOR_RESOURCE_TAG) + continue; + + NativeScriptModulesData[NativeScriptModule->GetObjectID()]["FEObjectData"] = RESOURCE_MANAGER.SaveFEObjectPart(NativeScriptModule); + NativeScriptModulesData[NativeScriptModule->GetObjectID()]["FileName"] = NativeScriptModule->GetObjectID() + ".nativescriptmodule"; + + RESOURCE_MANAGER.SaveFENativeScriptModule(NativeScriptModule, DirectoryPath + NativeScriptModule->GetObjectID() + ".nativescriptmodule"); + } + Root["NativeScriptModules"] = NativeScriptModulesData; + + // Saving Scenes. + std::vector SceneList = SCENE_MANAGER.GetAllScenes(); + Json::Value SceneData; + for (size_t i = 0; i < SceneList.size(); i++) + { + bool bShouldProceed = true; + + std::vector Tags = RESOURCE_MANAGER.GetTagsThatWillPreventDeletion(); + for (size_t j = 0; j < Tags.size(); j++) + { + if (SceneList[i]->GetTag() == Tags[j]) + { + bShouldProceed = false; + break; + } + } + + if (SceneList[i]->GetTag() == PREFAB_SCENE_DESCRIPTION_TAG) + { + for (size_t j = 0; j < PrefabList.size(); j++) + { + FEPrefab* Prefab = RESOURCE_MANAGER.GetPrefab(PrefabList[j]); + if (Prefab->GetScene() != SceneList[i]) + continue; + + for (size_t k = 0; k < Tags.size(); k++) + { + if (Tags[k] == Prefab->GetTag()) + { + bShouldProceed = false; + break; + } + } + + if (!bShouldProceed) + break; + } + } + + if (!bShouldProceed) + continue; + + SceneData[SceneList[i]->GetObjectID()] = SCENE_MANAGER.SaveSceneToJSON(SceneList[i], [](FEEntity* Entity) -> bool { + if (Entity->GetTag() == EDITOR_RESOURCE_TAG) + return false; + + return true; + }); + } + Root["Scenes"] = SceneData; + + // Saving into file. + Json::StreamWriterBuilder Builder; + const std::string JsonFile = Json::writeString(Builder, Root); + + ResourcesFile.open(DirectoryPath + "Resources.txt"); + ResourcesFile << JsonFile; + ResourcesFile.close(); +} + +// TODO: Make that process in memory, not involving creating temporary files. +FEAssetPackage* FEProject::SaveResourcesToAssetPackage() +{ + FEAssetPackage* Result = new FEAssetPackage(); + + std::string TemporaryFolder = FILE_SYSTEM.GetCurrentWorkingPath() + "/Temporary_Project_Resources/"; + if (FILE_SYSTEM.DoesDirectoryExist(TemporaryFolder)) + { + LOG.Add("FEProject::SaveResourcesToAssetPackage: Temporary_Project_Resources directory already exist, trying to delete it.", "FE_LOG_LOADING", FE_LOG_WARNING); + + if (!FILE_SYSTEM.DeleteDirectory(TemporaryFolder)) + { + LOG.Add("FEProject::SaveResourcesToAssetPackage: Error deleting Temporary_Project_Resources directory", "FE_LOG_LOADING", FE_LOG_ERROR); + return nullptr; + } + } + + if (!FILE_SYSTEM.CreateDirectory(TemporaryFolder)) + { + LOG.Add("FEProject::SaveResourcesToAssetPackage: Error creating Temporary_Project_Resources directory", "FE_LOG_LOADING", FE_LOG_ERROR); + return nullptr; + } + + // Because of editor camera system, we need to adjust main camera for each scene before saving. + SetProperMainCamerasInsteadOfEditorCameras(); + + // Saving resources. + SaveResources(TemporaryFolder, true); + + // After saving resources we restore editor cameras as main cameras. + SetEditorCamerasInsteadOfProperMainCameras(); + + // Saving all files to package. + std::vector Files = FILE_SYSTEM.GetFileNamesInDirectory(TemporaryFolder); + for (size_t i = 0; i < Files.size(); i++) + { + if (Result->ImportAssetFromFile(TemporaryFolder + Files[i]).empty()) + { + LOG.Add("FEProject::SaveResourcesToAssetPackage: Error importing asset " + Files[i] + " to package", "FE_LOG_LOADING", FE_LOG_WARNING); + //return nullptr; + } + } + + if (!FILE_SYSTEM.DeleteDirectory(TemporaryFolder)) + LOG.Add("FEProject::SaveResourcesToAssetPackage: Error deleting Temporary_Project_Resources directory", "FE_LOG_LOADING", FE_LOG_WARNING); + + return Result; +} + +void FEProject::LoadResourcesFromAssetPackage(FEAssetPackage* AssetPackage) +{ + if (AssetPackage == nullptr) + { + LOG.Add("FEProject::LoadResourcesFromAssetPackage: AssetPackage is nullptr!", "FE_LOG_LOADING", FE_LOG_ERROR); + return; + } + + std::string TemporaryFolder = FILE_SYSTEM.GetCurrentWorkingPath() + "/Temporary_Project_Resources/"; + if (FILE_SYSTEM.DoesDirectoryExist(TemporaryFolder)) + { + LOG.Add("FEProject::LoadResourcesFromAssetPackage: Temporary_Project_Resources directory already exist, trying to delete it.", "FE_LOG_LOADING", FE_LOG_WARNING); + + if (!FILE_SYSTEM.DeleteDirectory(TemporaryFolder)) + { + LOG.Add("FEProject::LoadResourcesFromAssetPackage: Error deleting Temporary_Project_Resources directory", "FE_LOG_LOADING", FE_LOG_ERROR); + return; + } + } + + if (!FILE_SYSTEM.CreateDirectory(TemporaryFolder)) + { + LOG.Add("FEProject::LoadResourcesFromAssetPackage: Error creating Temporary_Project_Resources directory", "FE_LOG_LOADING", FE_LOG_ERROR); + return; + } + + // Exporting all assets to files. + std::vector AssetList = AssetPackage->GetEntryList(); + for (size_t i = 0; i < AssetList.size(); i++) + { + if (!AssetPackage->ExportAssetToFile(AssetList[i].ID, TemporaryFolder + AssetList[i].Name)) + { + LOG.Add("FEProject::LoadResourcesFromAssetPackage: Error exporting asset " + AssetList[i].Name + " to file", "FE_LOG_LOADING", FE_LOG_WARNING); + continue; + } + } + + LoadResources(TemporaryFolder); + + // Because of editor camera system, we need to save proper main camera for each scene. + SaveProperMainCameras(); + + if (!FILE_SYSTEM.DeleteDirectory(TemporaryFolder)) + LOG.Add("FEProject::LoadResourcesFromAssetPackage: Error deleting Temporary_Project_Resources directory", "FE_LOG_LOADING", FE_LOG_WARNING); +} + +void FEProject::SaveProject(bool bFullSave) +{ + Json::Value Root; + std::ofstream ProjectFile; + + Root["Version"] = PROJECTS_FILE_VER; + Root["ID"] = ID; + Root["Name"] = Name; + + FEScene* SceneForScreenshot = EDITOR.GetFocusedScene(); + if (SceneForScreenshot != nullptr) + { + ENGINE.SaveScreenshot((GetProjectFolder() + "Thumbnail.texture").c_str(), SceneForScreenshot); + } + else + { + CreateDummyScreenshot(); + } + + // Save starting scene. + FEScene* StartingScene = SCENE_MANAGER.GetStartingScene(); + if (StartingScene != nullptr) + Root["StartingScene"] = StartingScene->GetObjectID(); + + // Saving editor scenes information. + std::vector EditorSceneIDs = EDITOR.GetEditorOpenedScenesIDs(); + for (size_t i = 0; i < EditorSceneIDs.size(); i++) + { + FEScene* CurrentScene = SCENE_MANAGER.GetScene(EditorSceneIDs[i]); + if (CurrentScene == nullptr) + continue; + + // If scene is editor only it means it is prefab scene. + if (CurrentScene->GetTag() == EDITOR_RESOURCE_TAG) + { + // So we need to find corresponding prefab. + FEEditorSceneWindow* EditorWindow = EDITOR.GetEditorSceneWindow(CurrentScene->GetObjectID()); + if (EditorWindow == nullptr) + continue; + + FEPrefab* Prefab = PREFAB_EDITOR_MANAGER.GetPrefabFromEditorWindow(EditorWindow); + if (Prefab == nullptr) + continue; + + Root["EditorScenes"]["Opened"][std::to_string(i)]["ID"] = Prefab->GetScene()->GetObjectID(); + Root["EditorScenes"]["Opened"][std::to_string(i)]["IsPrefabDescription"] = true; + } + else + { + Root["EditorScenes"]["Opened"][std::to_string(i)]["ID"] = CurrentScene->GetObjectID(); + Root["EditorScenes"]["Opened"][std::to_string(i)]["IsPrefabDescription"] = false; + } + } + + FEScene* FocusedScene = EDITOR.GetFocusedScene(); + std::string FocusedSceneID = ""; + if (FocusedScene != nullptr) + FocusedSceneID = FocusedScene->GetObjectID(); + + Root["EditorScenes"]["FocusedSceneID"] = FocusedSceneID; + + // Because of editor camera system, we need to adjust main camera for each scene before saving. + SetProperMainCamerasInsteadOfEditorCameras(); + + // Saving resources. + SaveResources(ProjectFolder, bFullSave); + + // After saving resources we restore editor cameras as main cameras. + SetEditorCamerasInsteadOfProperMainCameras(); + + // All of editor cameras would not be saved because of editor only tag. + // But we need to save their state. + Json::Value EditorCamerasData; + int Index = 0; + auto EditorCameraIterator = SceneIDToEditorCameraID.begin(); + while (EditorCameraIterator != SceneIDToEditorCameraID.end()) + { + FEScene* Scene = SCENE_MANAGER.GetScene(EditorCameraIterator->first); + if (Scene == nullptr) + { + EditorCameraIterator++; + continue; + } + + FEEntity* CameraEntity = Scene->GetEntity(EditorCameraIterator->second); + if (CameraEntity == nullptr) + { + EditorCameraIterator++; + continue; + } + + if (!CameraEntity->HasComponent()) + { + EditorCameraIterator++; + continue; + } + + EditorCamerasData[Index]["SceneID"] = EditorCameraIterator->first; + EditorCamerasData[Index]["EntityData"] = CameraEntity->ToJson(); + + Index++; + EditorCameraIterator++; + } + Root["EditorCameras"] = EditorCamerasData; + + // Saving into file. + Json::StreamWriterBuilder Builder; + const std::string JsonFile = Json::writeString(Builder, Root); + + ProjectFile.open(ProjectFolder + "Project.txt"); + ProjectFile << JsonFile; + ProjectFile.close(); + + for (size_t i = 0; i < FilesToDelete.size(); i++) + { + FILE_SYSTEM.DeleteFile(FilesToDelete[i].c_str()); + } + + VIRTUAL_FILE_SYSTEM.SaveState(ProjectFolder + "VFS.txt"); + bModified = false; +} + +void FEProject::LoadResources(std::string DirectoryPath) +{ + std::ifstream ResourcesFile; + ResourcesFile.open(DirectoryPath + "Resources.txt"); + + std::string FileData((std::istreambuf_iterator(ResourcesFile)), std::istreambuf_iterator()); + ResourcesFile.close(); + + Json::Value Root; + JSONCPP_STRING Error; + Json::CharReaderBuilder Builder; + + const std::unique_ptr Reader(Builder.newCharReader()); + if (!Reader->parse(FileData.c_str(), FileData.c_str() + FileData.size(), &Root, &Error)) + return; + + // Read file version. + float FileVersion = Root["Version"].asFloat(); + if (FileVersion != PROJECT_RESOURCE_FILE_VERSION) + { + LOG.Add("FEProject::LoadResources: File version is not matching!", "FE_LOG_LOADING", FE_LOG_ERROR); + return; + } + + // Loading meshes. + std::vector MeshList = Root["Meshes"].getMemberNames(); + for (size_t i = 0; i < MeshList.size(); i++) + { + FEObjectLoadedData LoadedObjectData = RESOURCE_MANAGER.LoadFEObjectPart(Root["Meshes"][MeshList[i]]["FEObjectData"]); + RESOURCE_MANAGER.LoadFEMesh((DirectoryPath + Root["Meshes"][MeshList[i]]["FileName"].asCString()).c_str(), LoadedObjectData.Name); + } + + // Loading textures. + std::vector TexturesList = Root["Textures"].getMemberNames(); + for (size_t i = 0; i < TexturesList.size(); i++) + { + FEObjectLoadedData LoadedObjectData = RESOURCE_MANAGER.LoadFEObjectPart(Root["Textures"][TexturesList[i]]["FEObjectData"]); + // Terrain textures should be loaded right away, not async. + if (LoadedObjectData.Tag == TERRAIN_SYSTEM_RESOURCE_TAG) + { + RESOURCE_MANAGER.LoadFETexture((DirectoryPath + Root["Textures"][TexturesList[i]]["FileName"].asCString()).c_str()); + } + else + { + RESOURCE_MANAGER.LoadFETextureAsync((DirectoryPath + Root["Textures"][TexturesList[i]]["FileName"].asCString()).c_str(), LoadedObjectData.Name, nullptr, LoadedObjectData.ID); + } + } + + // Loading materials. + std::vector MaterialsList = Root["Materials"].getMemberNames(); + for (size_t i = 0; i < MaterialsList.size(); i++) + { + if (RESOURCE_MANAGER.LoadMaterialFromJSON(Root["Materials"][MaterialsList[i]]) == nullptr) + LOG.Add("FEProject::LoadResources: Error loading material " + MaterialsList[i], "FE_LOG_LOADING", FE_LOG_ERROR); + } + + // Loading game models. + std::vector GameModelList = Root["GameModels"].getMemberNames(); + for (size_t i = 0; i < GameModelList.size(); i++) + { + if (RESOURCE_MANAGER.LoadGameModelFromJSON(Root["GameModels"][GameModelList[i]]) == nullptr) + LOG.Add("FEProject::LoadResources: Error loading game model " + GameModelList[i], "FE_LOG_LOADING", FE_LOG_ERROR); + } + + // Loading NativeScriptModules. + std::vector NativeScriptModulesList = Root["NativeScriptModules"].getMemberNames(); + for (size_t i = 0; i < NativeScriptModulesList.size(); i++) + { + FENativeScriptModule* LoadedNativeScriptModule = RESOURCE_MANAGER.LoadFENativeScriptModule((DirectoryPath + Root["NativeScriptModules"][NativeScriptModulesList[i]]["FileName"].asCString()).c_str()); + if (LoadedNativeScriptModule == nullptr) + continue; + + NATIVE_SCRIPT_SYSTEM.ActivateNativeScriptModule(LoadedNativeScriptModule); + } + + // Prefabs and Scenes are interconnected so we need to load them in two steps. + // Currently Prefabs can not contain other Prefabs or Scenes, if it will change we need to change this code. + // First load all prefab scenes. + std::vector SceneList = Root["Scenes"].getMemberNames(); + for (size_t i = 0; i < SceneList.size(); i++) + { + FEObjectLoadedData LoadedObjectData = RESOURCE_MANAGER.LoadFEObjectPart(Root["Scenes"][SceneList[i]]["FEObjectData"]); + if (LoadedObjectData.Tag != PREFAB_SCENE_DESCRIPTION_TAG) + continue; + + if (SCENE_MANAGER.LoadSceneFromJSON(Root["Scenes"][SceneList[i]], FESceneFlag::PrefabDescription) == nullptr) + LOG.Add("FEProject::LoadResources: Error loading scene " + SceneList[i], "FE_LOG_LOADING", FE_LOG_ERROR); + } + + // Then load Prefabs and initialize them with corresponding scenes. + std::vector PrefabList = Root["Prefabs"].getMemberNames(); + for (size_t i = 0; i < PrefabList.size(); i++) + { + if (RESOURCE_MANAGER.LoadPrefabFromJSON(Root["Prefabs"][PrefabList[i]]) == nullptr) + LOG.Add("FEProject::LoadResources: Error loading prefab " + PrefabList[i], "FE_LOG_LOADING", FE_LOG_ERROR); + } + + for (size_t i = 0; i < SceneList.size(); i++) + { + FEObjectLoadedData LoadedObjectData = RESOURCE_MANAGER.LoadFEObjectPart(Root["Scenes"][SceneList[i]]["FEObjectData"]); + if (LoadedObjectData.Tag == PREFAB_SCENE_DESCRIPTION_TAG) + continue; + + if (SCENE_MANAGER.LoadSceneFromJSON(Root["Scenes"][SceneList[i]], FESceneFlag::Active) == nullptr) + LOG.Add("FEProject::LoadResources: Error loading scene " + SceneList[i], "FE_LOG_LOADING", FE_LOG_ERROR); + } +} + +void FEProject::LoadProject() +{ + std::ifstream ProjectFile; + ProjectFile.open(ProjectFolder + "Project.txt"); + + std::string FileData((std::istreambuf_iterator(ProjectFile)), std::istreambuf_iterator()); + ProjectFile.close(); + + Json::Value Root; + JSONCPP_STRING Error; + Json::CharReaderBuilder Builder; + + const std::unique_ptr Reader(Builder.newCharReader()); + if (!Reader->parse(FileData.c_str(), FileData.c_str() + FileData.size(), &Root, &Error)) + return; + + // Check file version. + float FileVersion = Root["Version"].asFloat(); + if (FileVersion != PROJECTS_FILE_VER) + { + LOG.Add("FEProject::LoadProject: File version is not matching!", "FE_LOG_LOADING", FE_LOG_ERROR); + return; + } + + ID = Root["ID"].asCString(); + Name = Root["Name"].asCString(); + + LoadResources(ProjectFolder); + + // Because of editor camera system, we need to save proper main camera for each scene. + SaveProperMainCameras(); + + // After we loaded all resources we can load editor cameras. + Json::Value EditorCamerasData = Root["EditorCameras"]; + for (size_t i = 0; i < EditorCamerasData.size(); i++) + { + std::string SceneID = EditorCamerasData[static_cast(i)]["SceneID"].asCString(); + FEScene* Scene = SCENE_MANAGER.GetScene(SceneID); + if (Scene == nullptr) + continue; + + FEEntity* EditorCameraEntity = Scene->CreateEntityFromJson(EditorCamerasData[static_cast(i)]["EntityData"]); + SceneIDToEditorCameraID[SceneID] = EditorCameraEntity->GetObjectID(); + CAMERA_SYSTEM.SetMainCamera(EditorCameraEntity); + } + + // Set starting scene. + if (Root.isMember("StartingScene")) + { + std::string StartingSceneID = Root["StartingScene"].asCString(); + SCENE_MANAGER.SetStartingScene(StartingSceneID); + } + + // Now we can restore editor scenes. + if (Root.isMember("EditorScenes")) + { + Json::Value OpenedScenes = Root["EditorScenes"]["Opened"]; + for (size_t i = 0; i < OpenedScenes.size(); i++) + { + FEScene* Scene = SCENE_MANAGER.GetScene(OpenedScenes[std::to_string(i)]["ID"].asCString()); + if (Scene == nullptr) + continue; + + bool bIsPrefabDescription = OpenedScenes[std::to_string(i)]["IsPrefabDescription"].asBool(); + if (bIsPrefabDescription) + { + FEPrefab* PrefabThatHaveThatScene = nullptr; + std::vector PrefabList = RESOURCE_MANAGER.GetPrefabIDList(); + for (size_t j = 0; j < PrefabList.size(); j++) + { + FEPrefab* Prefab = RESOURCE_MANAGER.GetPrefab(PrefabList[j]); + if (Prefab->GetScene() == Scene) + { + PrefabThatHaveThatScene = Prefab; + break; + } + } + + if (PrefabThatHaveThatScene != nullptr) + PREFAB_EDITOR_MANAGER.PrepareEditWinow(PrefabThatHaveThatScene); + } + else + { + Scene->SetFlag(FESceneFlag::Active, true); + Scene->SetFlag(FESceneFlag::Renderable, true); + Scene->SetFlag(FESceneFlag::EditorMode, true); + EDITOR.AddEditorScene(Scene); + } + } + + std::string FocusedSceneID = Root["EditorScenes"]["FocusedSceneID"].asCString(); + FEScene* FocusedScene = SCENE_MANAGER.GetScene(FocusedSceneID); + if (FocusedScene != nullptr) + EDITOR.SetFocusedScene(FocusedScene); + } + + if (!LoadVFSData(ProjectFolder + "VFS.txt")) + LOG.Add("Can't find VIRTUAL_FILE_SYSTEM file in project folder.", "FE_LOG_LOADING", FE_LOG_WARNING); + + AddMissingVFSData(); +} + +bool FEProject::LoadVFSData(std::string FilePath) +{ + if (!FILE_SYSTEM.DoesFileExist(FilePath)) + { + LOG.Add("FEProject::LoadVFSData: File " + FilePath + " does not exist!", "FE_LOG_LOADING", FE_LOG_WARNING); + return false; + } + + VIRTUAL_FILE_SYSTEM.LoadState(FilePath); + VIRTUAL_FILE_SYSTEM.SetDirectoryReadOnly(false, "/Shaders"); + + auto Files = VIRTUAL_FILE_SYSTEM.GetDirectoryContent("/Shaders"); + for (size_t i = 0; i < Files.size(); i++) + { + VIRTUAL_FILE_SYSTEM.DeleteFile(Files[i], "/Shaders"); + } + + std::vector ShaderList = RESOURCE_MANAGER.GetShaderIDList(); + for (size_t i = 0; i < ShaderList.size(); i++) + { + if (OBJECT_MANAGER.GetFEObject(ShaderList[i]) == nullptr) + continue; + VIRTUAL_FILE_SYSTEM.CreateFile(OBJECT_MANAGER.GetFEObject(ShaderList[i]), "/Shaders"); + } + + std::vector StandardShaderList = RESOURCE_MANAGER.GetEnginePrivateShaderIDList(); + for (size_t i = 0; i < StandardShaderList.size(); i++) + { + if (OBJECT_MANAGER.GetFEObject(StandardShaderList[i]) == nullptr) + continue; + VIRTUAL_FILE_SYSTEM.CreateFile(OBJECT_MANAGER.GetFEObject(StandardShaderList[i]), "/Shaders"); + } + + VIRTUAL_FILE_SYSTEM.SetDirectoryReadOnly(true, "/Shaders"); + + return true; +} + +void FEProject::AddMissingVFSData() +{ + std::vector ShaderList = RESOURCE_MANAGER.GetShaderIDList(); + for (size_t i = 0; i < ShaderList.size(); i++) + { + if (VIRTUAL_FILE_SYSTEM.DoesFileExistAnywhere(OBJECT_MANAGER.GetFEObject(ShaderList[i]))) + continue; + + VIRTUAL_FILE_SYSTEM.CreateFile(OBJECT_MANAGER.GetFEObject(ShaderList[i]), "/Shaders"); + } + + std::vector StandardShaderList = RESOURCE_MANAGER.GetEnginePrivateShaderIDList(); + for (size_t i = 0; i < StandardShaderList.size(); i++) + { + if (VIRTUAL_FILE_SYSTEM.DoesFileExistAnywhere(OBJECT_MANAGER.GetFEObject(StandardShaderList[i]))) + continue; + + VIRTUAL_FILE_SYSTEM.CreateFile(OBJECT_MANAGER.GetFEObject(StandardShaderList[i]), "/Shaders"); + VIRTUAL_FILE_SYSTEM.SetFileReadOnly(true, OBJECT_MANAGER.GetFEObject(StandardShaderList[i]), "/Shaders"); + } + + std::vector OtherResourceList = RESOURCE_MANAGER.GetMeshIDList(); + std::vector TextureList = RESOURCE_MANAGER.GetTextureIDList(); + OtherResourceList.insert(OtherResourceList.end(), TextureList.begin(), TextureList.end()); + std::vector MaterialList = RESOURCE_MANAGER.GetMaterialIDList(); + OtherResourceList.insert(OtherResourceList.end(), MaterialList.begin(), MaterialList.end()); + std::vector GameModelList = RESOURCE_MANAGER.GetGameModelIDList(); + OtherResourceList.insert(OtherResourceList.end(), GameModelList.begin(), GameModelList.end()); + std::vector PrefabList = RESOURCE_MANAGER.GetPrefabIDList(); + OtherResourceList.insert(OtherResourceList.end(), PrefabList.begin(), PrefabList.end()); + std::vector NativeScriptModuleList = RESOURCE_MANAGER.GetNativeScriptModuleIDList(); + OtherResourceList.insert(OtherResourceList.end(), NativeScriptModuleList.begin(), NativeScriptModuleList.end()); + std::vector SceneList = SCENE_MANAGER.GetSceneIDList(); + // Filter prefab scenes. + for (size_t i = 0; i < SceneList.size(); i++) + { + FEScene* Scene = SCENE_MANAGER.GetScene(SceneList[i]); + if (Scene->GetTag() == PREFAB_SCENE_DESCRIPTION_TAG) + continue; + + OtherResourceList.push_back(SceneList[i]); + } + + for (size_t i = 0; i < OtherResourceList.size(); i++) + { + if (VIRTUAL_FILE_SYSTEM.DoesFileExistAnywhere(OBJECT_MANAGER.GetFEObject(OtherResourceList[i]))) + continue; + + VIRTUAL_FILE_SYSTEM.CreateFile(OBJECT_MANAGER.GetFEObject(OtherResourceList[i]), "/"); + + if (OBJECT_MANAGER.GetFEObject(OtherResourceList[i])->GetTag() == ENGINE_RESOURCE_TAG || + OBJECT_MANAGER.GetFEObject(OtherResourceList[i])->GetTag() == EDITOR_RESOURCE_TAG) + { + VIRTUAL_FILE_SYSTEM.SetFileReadOnly(true, OBJECT_MANAGER.GetFEObject(OtherResourceList[i]), "/"); + } + } +} + +void FEProject::CreateDummyScreenshot() +{ + const size_t Width = ENGINE.GetDefaultViewport()->GetWidth(); + const size_t Height = ENGINE.GetDefaultViewport()->GetHeight(); + + unsigned char* Pixels = new unsigned char[4 * Width * Height]; + for (size_t j = 0; j < Height; j++) + { + for (size_t i = 0; i < 4 * Width; i += 4) + { + Pixels[i + (j * 4 * Width)] = 0; + Pixels[i + 1 + (j * 4 * Width)] = static_cast(162); + Pixels[i + 2 + (j * 4 * Width)] = static_cast(232); + Pixels[i + 3 + (j * 4 * Width)] = static_cast(255); + } + } + + FETexture* TempTexture = RESOURCE_MANAGER.RawDataToFETexture(Pixels, static_cast(Width), static_cast(Height)); + RESOURCE_MANAGER.SaveFETexture(TempTexture, (GetProjectFolder() + "/Thumbnail.texture").c_str()); + RESOURCE_MANAGER.DeleteFETexture(TempTexture); + delete[] Pixels; +} + +void FEProject::AddFileToDeleteList(const std::string FileName) +{ + FilesToDelete.push_back(FileName); +} + +bool FEProject::IsModified() +{ + return bModified; +} + +void FEProject::SetModified(const bool NewValue) +{ + bModified = NewValue; +} + +void FEProject::AddUnSavedObject(FEObject* Object) +{ + UnSavedObjects.push_back(Object); +} + +void FEProject::SetProjectFolder(const std::string NewValue) +{ + if (!FILE_SYSTEM.DoesDirectoryExist(NewValue.c_str())) + { + LOG.Add("FEProject::SetProjectFolder: Directory " + NewValue + " does not exist!", "FE_LOG_LOADING", FE_LOG_WARNING); + return; + } + + ProjectFolder = NewValue; +} + +void FEProject::SaveProjectTo(const std::string NewPath) +{ + if (!FILE_SYSTEM.DoesDirectoryExist(NewPath.c_str())) + { + LOG.Add("FEProject::SaveProjectTo: Directory " + NewPath + " does not exist!", "FE_LOG_SAVING", FE_LOG_WARNING); + return; + } + + SetProjectFolder(NewPath); + SaveProject(true); +} + +void FEProject::InjectEditorCamera(FEScene* Scene) +{ + if (Scene == nullptr) + { + LOG.Add("FEProject::InjectEditorCamera: Scene is nullptr!", "FE_LOG_LOADING", FE_LOG_WARNING); + return; + } + + if (SceneIDToEditorCameraID.find(Scene->GetObjectID()) != SceneIDToEditorCameraID.end()) + { + FEEntity* CameraEntity = Scene->GetEntity(SceneIDToEditorCameraID[Scene->GetObjectID()]); + if (CameraEntity != nullptr) + { + LOG.Add("FEProject::InjectEditorCamera: Editor camera already exists in scene " + Scene->GetName(), "FE_LOG_LOADING", FE_LOG_WARNING); + return; + } + else + { + SceneIDToEditorCameraID.erase(Scene->GetObjectID()); + } + } + + FEEntity* CameraEntity = nullptr; + std::vector CameraPrefab = RESOURCE_MANAGER.GetPrefabByName("Free camera prefab"); + if (CameraPrefab.size() == 0) + { + LOG.Add("FEProject::InjectEditorCamera: Camera prefab not found! Inserting camera manually.", "FE_LOG_LOADING", FE_LOG_WARNING); + + CameraEntity = Scene->CreateEntity("Camera"); + CameraEntity->AddComponent(); + } + else + { + FEPrefab* CameraPrefabToUse = CameraPrefab[0]; + std::vector AddedEntities = SCENE_MANAGER.InstantiatePrefab(CameraPrefabToUse, Scene, true); + if (AddedEntities.empty()) + { + LOG.Add("FEProject::InjectEditorCamera: Camera prefab was not instantiated correctly. Inserting camera manually.", "FE_LOG_LOADING", FE_LOG_WARNING); + + CameraEntity = Scene->CreateEntity("Camera"); + CameraEntity->AddComponent(); + } + else + { + CameraEntity = AddedEntities[0]; + } + + if (CameraEntity == nullptr) + { + LOG.Add("FEProject::InjectEditorCamera: Camera prefab was not instantiated correctly. Inserting camera manually.", "FE_LOG_LOADING", FE_LOG_WARNING); + + CameraEntity = Scene->CreateEntity("Camera"); + CameraEntity->AddComponent(); + } + } + + RESOURCE_MANAGER.SetTag(CameraEntity, EDITOR_RESOURCE_TAG); + FECameraComponent& CameraComponent = CameraEntity->GetComponent(); + CameraComponent.TryToSetViewportSize(128, 128); + CameraComponent.SetDistanceFogEnabled(false); + CAMERA_SYSTEM.SetMainCamera(CameraEntity); + FETransformComponent& CameraTransform = CameraEntity->GetComponent(); + CameraTransform.SetPosition(glm::vec3(-4.2269f, 15.7178f, 19.6429f)); + + SceneIDToEditorCameraID[Scene->GetObjectID()] = CameraEntity->GetObjectID(); +} + +std::string FEProject::GetEditorCameraIDBySceneID(std::string SceneID) +{ + if (SceneIDToEditorCameraID.find(SceneID) == SceneIDToEditorCameraID.end()) + { + LOG.Add("FEProject::GetEditorCameraIDBySceneID: Editor camera not found for scene " + SceneID, "FE_LOG_LOADING", FE_LOG_WARNING); + return ""; + } + + return SceneIDToEditorCameraID[SceneID]; +} + +std::string FEProject::GetProperMainCameraIDBySceneID(std::string SceneID) +{ + if (SceneIDToProperMainCameraID.find(SceneID) == SceneIDToProperMainCameraID.end()) + { + LOG.Add("FEProject::GetProperMainCameraIDBySceneID: Editor camera not found for scene " + SceneID, "FE_LOG_LOADING", FE_LOG_WARNING); + return ""; + } + + return SceneIDToProperMainCameraID[SceneID]; +} + +bool FEProject::SetProperMainCameraIDBySceneID(std::string SceneID, std::string CameraID) +{ + FEScene* Scene = SCENE_MANAGER.GetScene(SceneID); + if (Scene == nullptr) + { + LOG.Add("FEProject::SetProperMainCameraIDBySceneID: Scene " + SceneID + " not found!", "FE_LOG_LOADING", FE_LOG_WARNING); + return false; + } + + if (!CameraID.empty()) + { + FEEntity* CameraEntity = Scene->GetEntity(CameraID); + if (CameraEntity == nullptr) + { + LOG.Add("FEProject::SetProperMainCameraIDBySceneID: Camera " + CameraID + " not found in scene " + SceneID, "FE_LOG_LOADING", FE_LOG_WARNING); + return false; + } + + if (!CameraEntity->HasComponent()) + { + LOG.Add("FEProject::SetProperMainCameraIDBySceneID: Entity " + CameraID + " in scene " + SceneID + " does not have camera component!", "FE_LOG_LOADING", FE_LOG_WARNING); + return false; + } + } + + SceneIDToProperMainCameraID[SceneID] = CameraID; + return true; +} + +void FEProject::SetProperMainCamerasInsteadOfEditorCameras() +{ + auto Iterator = SceneIDToProperMainCameraID.begin(); + while (Iterator != SceneIDToProperMainCameraID.end()) + { + FEScene* Scene = SCENE_MANAGER.GetScene(Iterator->first); + if (Scene != nullptr) + { + FEEntity* CurrentMainCameraEntity = CAMERA_SYSTEM.GetMainCamera(Scene); + if (CurrentMainCameraEntity != nullptr && CurrentMainCameraEntity->GetObjectID() != SceneIDToProperMainCameraID[Scene->GetObjectID()]) + { + CAMERA_SYSTEM.SetMainCamera(Scene->GetEntity(Iterator->second)); + } + } + Iterator++; + } +} + +void FEProject::SetEditorCamerasInsteadOfProperMainCameras() +{ + auto Iterator = SceneIDToEditorCameraID.begin(); + while (Iterator != SceneIDToEditorCameraID.end()) + { + FEScene* Scene = SCENE_MANAGER.GetScene(Iterator->first); + if (Scene != nullptr) + { + FEEntity* CurrentMainCameraEntity = CAMERA_SYSTEM.GetMainCamera(Scene); + if (CurrentMainCameraEntity != nullptr && CurrentMainCameraEntity->GetObjectID() != SceneIDToEditorCameraID[Scene->GetObjectID()]) + { + CAMERA_SYSTEM.SetMainCamera(Scene->GetEntity(Iterator->second)); + } + } + Iterator++; + } +} + +void FEProject::SaveProperMainCameras() +{ + std::vector SceneList = SCENE_MANAGER.GetSceneIDList(); + for (size_t i = 0; i < SceneList.size(); i++) + { + FEScene* CurrentScene = SCENE_MANAGER.GetScene(SceneList[i]); + if (CurrentScene == nullptr) + continue; + + FEEntity* MainCameraEntity = CAMERA_SYSTEM.GetMainCamera(CurrentScene); + if (MainCameraEntity != nullptr) + SceneIDToProperMainCameraID[CurrentScene->GetObjectID()] = MainCameraEntity->GetObjectID(); + } +} + +std::string FEProject::GetID() +{ + return ID; +} \ No newline at end of file diff --git a/SubSystems/ProjectManagment/FEProject.h b/SubSystems/ProjectManagment/FEProject.h new file mode 100644 index 0000000..00c2729 --- /dev/null +++ b/SubSystems/ProjectManagment/FEProject.h @@ -0,0 +1,75 @@ +#pragma once + +#include "../../FEEditorDragAndDropManager.h" +#include "../../FEEditorVirtualFileSystem.h" + +class FEProject +{ + friend class FEProjectManager; + friend class FEEditor; + friend class FEProjectBuildSystem; + friend class FEPrefabEditorManager; +public: + FEProject(std::string Name, std::string ProjectFolder); + ~FEProject(); + + std::string GetID(); + + std::string GetName(); + void SetName(std::string NewValue); + + std::string GetProjectFolder(); + + void LoadProject(); + void SaveProject(bool bFullSave = false); + void SaveProjectTo(std::string NewPath); + + FETexture* SceneScreenshot; + void CreateDummyScreenshot(); + + void AddFileToDeleteList(std::string FileName); + + bool IsModified(); + void SetModified(bool NewValue); + + void AddUnSavedObject(FEObject* Object); + + std::string GetEditorCameraIDBySceneID(std::string SceneID); + + std::string GetProperMainCameraIDBySceneID(std::string SceneID); + bool SetProperMainCameraIDBySceneID(std::string SceneID, std::string CameraID); +private: + std::string ID; + std::string Name; + std::string ProjectFolder; + + bool bModified = false; + std::vector UnSavedObjects; + + std::vector FilesToDelete; + + void SetProjectFolder(std::string NewValue); + + std::unordered_map SceneIDToEditorCameraID; + void InjectEditorCamera(FEScene* Scene); + + std::unordered_map SceneIDToProperMainCameraID; + + // FIXME: Consider moving this to RESOURCE_MANAGER + void LoadResources(std::string DirectoryPath); + void SaveResources(std::string DirectoryPath, bool bFullSave = false); + // TODO: Implement in-memory processing instead of creating temporary files. + // FIXME: Consider moving this to RESOURCE_MANAGER + FEAssetPackage* SaveResourcesToAssetPackage(); + void LoadResourcesFromAssetPackage(FEAssetPackage* AssetPackage); + + bool LoadVFSData(std::string FilePath); + void AddMissingVFSData(); + + void SetProperMainCamerasInsteadOfEditorCameras(); + void SetEditorCamerasInsteadOfProperMainCameras(); + void SaveProperMainCameras(); +}; + +#define PROJECTS_FILE_VER 0.05f +#define PROJECT_RESOURCE_FILE_VERSION 0.01f \ No newline at end of file diff --git a/SubSystems/ProjectManagment/FEProjectManager.cpp b/SubSystems/ProjectManagment/FEProjectManager.cpp new file mode 100644 index 0000000..a0c8d6b --- /dev/null +++ b/SubSystems/ProjectManagment/FEProjectManager.cpp @@ -0,0 +1,325 @@ +#include "FEProjectManager.h" +#include "../../FEEditor.h" + +FEProjectManager::FEProjectManager() {} +FEProjectManager::~FEProjectManager() {} + +void FEProjectManager::InitializeResources() +{ + IndexChosen = -1; + LoadProjectList(); +} + +FEProject* FEProjectManager::GetCurrent() +{ + return Current; +} + +void FEProjectManager::SetCurrent(FEProject* Project) +{ + Current = Project; +} + +std::vector FEProjectManager::GetList() +{ + return List; +} + +void FEProjectManager::LoadProjectList() +{ + if (!FILE_SYSTEM.DoesDirectoryExist(PROJECTS_FOLDER)) + CustomProjectFolder = ""; + + const std::vector ProjectNameList = FILE_SYSTEM.GetDirectoryList(PROJECTS_FOLDER); + + for (size_t i = 0; i < ProjectNameList.size(); i++) + { + if (ContainProject(std::string(PROJECTS_FOLDER) + std::string("/") + ProjectNameList[i])) + List.push_back(new FEProject(ProjectNameList[i].c_str(), std::string(PROJECTS_FOLDER) + std::string("/") + ProjectNameList[i].c_str() + "/")); + } +} + +void FEProjectManager::CloseCurrentProject() +{ + // Closing all windows or popups. + WindowsManager::GetInstance().CloseAllWindows(); + WindowsManager::GetInstance().CloseAllPopups(); + + SELECTED.ClearAll(); + PREVIEW_MANAGER.Clear(); + for (size_t i = 0; i < List.size(); i++) + { + delete List[i]; + } + List.clear(); + PROJECT_MANAGER.SetCurrent(nullptr); + LoadProjectList(); + + VIRTUAL_FILE_SYSTEM.SetCurrentPath("/"); +} + +void FEProjectManager::OpenProject(const int ProjectIndex) +{ + if (ProjectIndex < 0 || ProjectIndex >= static_cast(List.size())) + { + LOG.Add("FEProjectManager::OpenProject: Project index is out of range!", "FE_LOG_LOADING", FE_LOG_ERROR); + return; + } + + PROJECT_MANAGER.SetCurrent(List[ProjectIndex]); + PROJECT_MANAGER.GetCurrent()->LoadProject(); + IndexChosen = -1; + + // After loading project we should update our previews + PREVIEW_MANAGER.UpdateAll(); + SELECTED.ClearAll(); +} + +void FEProjectManager::DisplayProjectSelection() +{ + static float LowerPanelHight = 90.0f; + const float MainWindowW = static_cast(APPLICATION.GetMainWindow()->GetWidth()); + const float MainWindowH = static_cast(APPLICATION.GetMainWindow()->GetHeight()); + + ImGui::PushStyleVar(ImGuiStyleVar_Alpha, 1.0f); + ImGui::SetNextWindowPos(ImVec2(0.0f, 0.0f)); + ImGui::SetNextWindowSize(ImVec2(MainWindowW, MainWindowH - LowerPanelHight)); + ImGui::Begin("Project Browser", nullptr, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse); + { + ImGui::SetWindowFontScale(2.0f); + ImGui::Text("CHOOSE WHAT PROJECT TO LOAD :"); + ImGui::SetWindowFontScale(1.0f); + + ImGui::PushStyleColor(ImGuiCol_Button, static_cast(ImColor(0.5f, 0.5f, 0.5f))); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, static_cast(ImColor::ImColor(0.95f, 0.90f, 0.0f))); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, static_cast(ImColor::ImColor(0.1f, 1.0f, 0.1f, 1.0f))); + + const int ColumnCount = static_cast(MainWindowW / (512.0f + 32.0f)); + ImGui::Columns(ColumnCount, "projectColumns", false); + static bool bPushedStyle = false; + for (size_t i = 0; i < List.size(); i++) + { + ImGui::PushID(static_cast(i)); + bPushedStyle = false; + if (IndexChosen == i) + { + bPushedStyle = true; + ImGui::PushStyleColor(ImGuiCol_Button, static_cast(ImColor(0.1f, 1.0f, 0.1f, 1.0f))); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, static_cast(ImColor::ImColor(0.1f, 1.0f, 0.1f, 1.0f))); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, static_cast(ImColor::ImColor(0.1f, 1.0f, 0.1f, 1.0f))); + } + + if (ImGui::IsMouseDoubleClicked(0)) + { + if (IndexChosen != -1) + { + OpenProject(IndexChosen); + } + } + + if (ImGui::ImageButton((void*)static_cast(List[i]->SceneScreenshot->GetTextureID()), ImVec2(512.0f, 288.0f), ImVec2(0.0f, 1.0f), ImVec2(1.0f, 0.0f), 8, ImColor(0.0f, 0.0f, 0.0f, 0.0f), ImColor(1.0f, 1.0f, 1.0f, 1.0f))) + { + IndexChosen = static_cast(i); + } + + ImGui::Text(List[i]->GetName().c_str()); + + if (bPushedStyle) + { + ImGui::PopStyleColor(); + ImGui::PopStyleColor(); + ImGui::PopStyleColor(); + } + + ImGui::PopID(); + ImGui::NextColumn(); + } + + ImGui::Columns(1); + + ImGui::PopStyleColor(); + ImGui::PopStyleColor(); + ImGui::PopStyleColor(); + } + ImGui::End(); + ImGui::PopStyleVar(); + + ImGui::PushStyleVar(ImGuiStyleVar_Alpha, 1.0f); + ImGui::SetNextWindowPos(ImVec2(0.0f, MainWindowH - LowerPanelHight)); + ImGui::SetNextWindowSize(ImVec2(MainWindowW, LowerPanelHight)); + ImGui::Begin("##create project", nullptr, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar); + { + ImGui::PushStyleColor(ImGuiCol_Button, static_cast(ImColor(0.0f, 162.0f / 255.0f, 232.0f / 255.0f, 1.0f))); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, static_cast(ImColor::ImColor(23.0f / 255.0f, 186.0f / 255.0f, 1.0f, 1.0f))); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, static_cast(ImColor::ImColor(0.0f, 125.0f / 255.0f, 179.0f / 255.0f, 1.0f))); + + if (ImGui::Button("Create New Project", ImVec2(200.0f, 64.0f))) + ImGui::OpenPopup("New Project"); + + ImGui::SameLine(); + if (ImGui::Button("Open Project", ImVec2(200.0f, 64.0f)) && IndexChosen != -1) + { + OpenProject(IndexChosen); + } + + ImGui::SameLine(); + if (ImGui::Button("Delete Project", ImVec2(200.0f, 64.0f)) && IndexChosen != -1 && IndexChosen < static_cast(List.size())) + { + std::string ProjectFolder = List[IndexChosen]->GetProjectFolder(); + ProjectFolder.erase(ProjectFolder.begin() + ProjectFolder.size() - 1); + + // Getting list of all files in project folder. + const auto FileList = FILE_SYSTEM.GetFileList(List[IndexChosen]->GetProjectFolder().c_str()); + // We would delete all files in project folder, editor would not create folders there + // so we are deleting only files. + for (size_t i = 0; i < FileList.size(); i++) + { + FILE_SYSTEM.DeleteFile((List[IndexChosen]->GetProjectFolder() + FileList[i]).c_str()); + } + // Then we can try to delete project folder, but if user created some folders in it we will fail. + FILE_SYSTEM.DeleteDirectory(ProjectFolder.c_str()); + + for (size_t i = 0; i < List.size(); i++) + { + delete List[i]; + } + List.clear(); + PROJECT_MANAGER.SetCurrent(nullptr); + + LoadProjectList(); + } + + ImGui::PopStyleColor(); + ImGui::PopStyleColor(); + ImGui::PopStyleColor(); + ImGui::PushStyleColor(ImGuiCol_Button, static_cast(ImColor(0.0f, 242.0f / 255.0f, 79.0f / 255.0f, 1.0f))); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, static_cast(ImColor::ImColor(34.0f / 255.0f, 1.0f, 106.0f / 255.0f, 1.0f))); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, static_cast(ImColor::ImColor(0.0f, 202.0f / 255.0f, 66.0f / 255.0f, 1.0f))); + + ImGui::SameLine(); + ImGui::SetCursorPos(ImVec2(ImGui::GetContentRegionAvail().x + 280.0f + 64.0f, ImGui::GetCursorPos().y)); + if (ImGui::Button("Choose projects directory", ImVec2(280.0f, 64.0f))) + { + std::string Path; + FILE_SYSTEM.ShowFolderOpenDialog(Path); + SetProjectsFolder(Path); + } + + ImGui::PopStyleColor(); + ImGui::PopStyleColor(); + ImGui::PopStyleColor(); + + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(15, 15)); + if (ImGui::BeginPopupModal("New Project", nullptr, ImGuiWindowFlags_AlwaysAutoResize)) + { + ImGui::SetWindowPos(ImVec2(APPLICATION.GetMainWindow()->GetWidth() / 2.0f - ImGui::GetWindowWidth() / 2.0f, APPLICATION.GetMainWindow()->GetHeight() / 2.0f - ImGui::GetWindowHeight() / 2.0f)); + ImGui::Text("Insert name of new project :"); + static char ProjectName[512] = ""; + + ImGui::InputText("##newProjectName", ProjectName, IM_ARRAYSIZE(ProjectName)); + + ImGui::SetCursorPosX(ImGui::GetWindowWidth() / 4.0f - 120.0f / 2.0f); + ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 10.0f); + if (ImGui::Button("Create", ImVec2(120, 0))) + { + bool bAlreadyCreated = false; + for (size_t i = 0; i < List.size(); i++) + { + if (List[i]->GetName() == std::string(ProjectName)) + { + bAlreadyCreated = true; + break; + } + } + + if (strlen(ProjectName) != 0 && !bAlreadyCreated) + { + FILE_SYSTEM.CreateDirectory((std::string(PROJECTS_FOLDER) + std::string("/") + ProjectName + "/").c_str()); + List.push_back(new FEProject(ProjectName, std::string(PROJECTS_FOLDER) + std::string("/") + ProjectName + "/")); + List.back()->CreateDummyScreenshot(); + + CreateNewProject(ProjectName, std::string(PROJECTS_FOLDER) + std::string("/") + ProjectName + "/"); + + ImGui::CloseCurrentPopup(); + strcpy_s(ProjectName, ""); + } + } + + ImGui::SetItemDefaultFocus(); + ImGui::SameLine(); + ImGui::SetCursorPosX(ImGui::GetWindowWidth() / 2.0f + ImGui::GetWindowWidth() / 4.0f - 120.0f / 2.0f); + if (ImGui::Button("Cancel", ImVec2(120, 0))) + { + ImGui::CloseCurrentPopup(); + } + + ImGui::EndPopup(); + } + } + + ImGui::PopStyleVar(); + ImGui::End(); + ImGui::PopStyleVar(); +} + +void FEProjectManager::CreateNewProject(std::string ProjectName, std::string ProjectPath) +{ + if (ProjectName.empty() || ProjectPath.empty()) + { + LOG.Add("FEProjectManager::CreateNewProject: Project name or path is empty!", "FE_LOG_LOADING", FE_LOG_ERROR); + return; + } + + if (ContainProject(ProjectPath)) + { + LOG.Add("FEProjectManager::CreateNewProject: Project already exists!", "FE_LOG_LOADING", FE_LOG_ERROR); + return; + } + + FEProject* NewProject = new FEProject(ProjectName, ProjectPath); + FEScene* NewScene = SCENE_MANAGER.CreateScene(ProjectName + "_main_scene", "", FESceneFlag::Active); + + FEEntity* SunEntity = NewScene->CreateEntity("Sun"); + SunEntity->AddComponent(FE_DIRECTIONAL_LIGHT); + FELightComponent& LightComponent = SunEntity->GetComponent(); + SunEntity->GetComponent().SetRotation(glm::vec3(-40.0f, 10.0f, 0.0f)); + LightComponent.SetIntensity(4.0f); + LightComponent.SetCastShadows(true); + + FEEntity* SkyDome = NewScene->CreateEntity("SkyDome"); + SkyDome->GetComponent().SetScale(glm::vec3(150.0f)); + SkyDome->AddComponent(); + + EDITOR.AddEditorScene(NewScene); + NewProject->InjectEditorCamera(NewScene); + NewProject->AddMissingVFSData(); + NewProject->SaveProject(true); + + CloseCurrentProject(); + delete NewProject; +} + +bool FEProjectManager::ContainProject(const std::string Path) +{ + if (!FILE_SYSTEM.DoesDirectoryExist(Path.c_str())) + return false; + + if (!FILE_SYSTEM.DoesFileExist((Path + "/Project.txt").c_str())) + return false; + + return true; +} + +void FEProjectManager::SetProjectsFolder(const std::string FolderPath) +{ + if (FolderPath != "") + { + CustomProjectFolder = FolderPath; + for (size_t i = 0; i < List.size(); i++) + { + delete List[i]; + } + List.clear(); + LoadProjectList(); + } +} \ No newline at end of file diff --git a/SubSystems/ProjectManagment/FEProjectManager.h b/SubSystems/ProjectManagment/FEProjectManager.h new file mode 100644 index 0000000..7549fb7 --- /dev/null +++ b/SubSystems/ProjectManagment/FEProjectManager.h @@ -0,0 +1,41 @@ +#pragma once + +#include "../../FEEditorDragAndDropManager.h" +#include "../../FEDearImguiWrapper/FEDearImguiWrapper.h" +#include "../../FEEditorGizmoManager.h" +#include "../../FEEditorPreviewManager.h" +#include "../../FEEditorVirtualFileSystem.h" + +#include "FEProject.h" + +class FEProjectManager +{ + std::vector List; + int IndexChosen = -1; + FEProject* Current = nullptr; + std::string CustomProjectFolder = "../FocalEngineProjects-master"; + + void CreateNewProject(std::string ProjectName, std::string ProjectPath); +public: + SINGLETON_PUBLIC_PART(FEProjectManager) + SINGLETON_PRIVATE_PART(FEProjectManager) + + void InitializeResources(); + + FEProject* GetCurrent(); + void SetCurrent(FEProject* Project); + + std::vector GetList(); + + void OpenProject(int ProjectIndex); + void LoadProjectList(); + void CloseCurrentProject(); + + void DisplayProjectSelection(); + + bool ContainProject(std::string Path); + void SetProjectsFolder(std::string FolderPath); +}; + +#define PROJECTS_FOLDER PROJECT_MANAGER.CustomProjectFolder.c_str() +#define PROJECT_MANAGER FEProjectManager::GetInstance() \ No newline at end of file diff --git a/main.cpp b/main.cpp index 457dadf..d080acd 100644 --- a/main.cpp +++ b/main.cpp @@ -15,21 +15,57 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine double AverageCpuFrameDuration = 0.0; double AverageGpuFrameDuration = 0.0; + bool bPutThisFrameToTimeline = false; + while (ENGINE.IsNotTerminated()) { + PROFILING.StartProfiling(); + ENGINE.BeginFrame(); + EDITOR.UpdateBeforeRender(); ENGINE.Render(); #ifdef EDITOR_SELECTION_DEBUG_MODE - std::string objectsUnderMouse = "objectsUnderMouse: " + std::to_string(SELECTED.ObjectsUnderMouse.size()); - ImGui::Text(objectsUnderMouse.c_str()); + if (EDITOR.GetFocusedScene() != nullptr) + { + FESelectionData* SelectedData = SELECTED.GetSceneData(EDITOR.GetFocusedScene()->GetObjectID()); + if (SelectedData != nullptr) + { + std::string ObjectsUnderMouse = "Count of considered entities: " + std::to_string(SelectedData->SceneEntitiesUnderMouse.size()); + ImGui::Text(ObjectsUnderMouse.c_str()); + + std::string ColorIndex = "ColorIndex: " + std::to_string(SelectedData->ColorIndex); + ImGui::Text(ColorIndex.c_str()); - std::string colorIndex = "colorIndex: " + std::to_string(SELECTED.ColorIndex); - ImGui::Text(colorIndex.c_str()); + std::string EntityUnderMouse = "Entity under mouse: "; + if (SelectedData->ColorIndex != -1 && SelectedData->ColorIndex < SelectedData->SceneEntitiesUnderMouse.size()) + { + EntityUnderMouse += SelectedData->SceneEntitiesUnderMouse[SelectedData->ColorIndex]->GetName(); + } + else + { + EntityUnderMouse += "None"; + } + ImGui::Text(EntityUnderMouse.c_str()); - ImGui::Image((void*)(intptr_t)SELECTED.PixelAccurateSelectionFB->GetColorAttachment()->GetTextureID(), ImVec2(256 * 4, 256 * 4), ImVec2(0.0f, 1.0f), ImVec2(1.0f, 0.0f)); + ImGui::Image((void*)(intptr_t)SelectedData->PixelAccurateSelectionFB->GetColorAttachment()->GetTextureID(), ImVec2(256 * 4, 256 * 4), ImVec2(0.0f, 1.0f), ImVec2(1.0f, 0.0f)); + } + } #endif + if (ImGui::Button("Put This Frame To Timeline")) + { + bPutThisFrameToTimeline = true; + } + + if (PROJECT_MANAGER.GetCurrent() != nullptr) + { + if (ImGui::Button("Build")) + { + EDITOR_PROJECT_BUILD_SYSTEM.BuildExecutable(PROJECT_MANAGER.GetCurrent()); + } + } + //ImGui::ShowDemoWindow(); EDITOR.Render(); ENGINE.EndFrame(); @@ -74,6 +110,13 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine caption += " ms"; ENGINE.SetWindowCaption(caption.c_str()); + + PROFILING.StopProfiling(); + if (bPutThisFrameToTimeline) + { + PROFILING.SaveTimelineToJSON("timeline.json"); + bPutThisFrameToTimeline = false; + } } return 0;