diff --git a/Assets/Editor/Layouts/Default.ini b/Assets/Editor/Layouts/Default.ini index 4ddc46c2..d7a7bf69 100644 --- a/Assets/Editor/Layouts/Default.ini +++ b/Assets/Editor/Layouts/Default.ini @@ -4,13 +4,13 @@ Size=1920,20 Collapsed=0 [Window][SHEditorMenuBar] -Pos=0,24 -Size=1920,1036 +Pos=0,48 +Size=1920,1012 Collapsed=0 [Window][Hierarchy Panel] -Pos=0,120 -Size=225,940 +Pos=0,197 +Size=308,863 Collapsed=0 DockId=0x00000004,0 @@ -20,29 +20,96 @@ Size=400,400 Collapsed=0 [Window][Inspector] -Pos=1686,24 -Size=234,1036 +Pos=1528,48 +Size=392,1012 Collapsed=0 DockId=0x00000006,0 [Window][Profiler] -Pos=0,24 -Size=225,94 +Pos=0,48 +Size=308,147 Collapsed=0 DockId=0x00000003,0 [Window][Viewport] -Pos=227,24 -Size=1457,1036 +Pos=227,48 +Size=1457,1012 Collapsed=0 -DockId=0x00000002,0 +DockId=0x0000000B,0 + +[Window][面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面o] +Pos=60,60 +Size=32,64 +Collapsed=0 + +[Window][面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面] +Pos=60,60 +Size=999,581 +Collapsed=0 + +[Window][o] +Pos=60,60 +Size=32,64 +Collapsed=0 + +[Window][面面] +Pos=60,60 +Size=553,422 +Collapsed=0 + +[Window][] +Pos=60,60 +Size=770,394 +Collapsed=0 + +[Window][ Viewport] +Pos=227,48 +Size=1457,1012 +Collapsed=0 +DockId=0x0000000B,0 + +[Window][ Viewport] +Pos=227,48 +Size=1457,1012 +Collapsed=0 +DockId=0x0000000B,0 + +[Window][ Viewport] +Pos=310,48 +Size=1216,715 +Collapsed=0 +DockId=0x0000000B,0 + +[Window][V] +Pos=310,722 +Size=1501,338 +Collapsed=0 +DockId=0x00000008,0 + +[Window][p] +Pos=310,750 +Size=1501,310 +Collapsed=0 +DockId=0x0000000A,0 + +[Window][ Asset Browser] +Pos=310,765 +Size=1216,295 +Collapsed=0 +DockId=0x0000000C,0 [Docking][Data] -DockSpace ID=0xC5C9B8AB Window=0xBE4044E9 Pos=8,55 Size=1920,1036 Split=X - DockNode ID=0x00000005 Parent=0xC5C9B8AB SizeRef=1684,1036 Split=X - DockNode ID=0x00000001 Parent=0x00000005 SizeRef=225,1036 Split=Y Selected=0x1E6EB881 - DockNode ID=0x00000003 Parent=0x00000001 SizeRef=225,94 Selected=0x1E6EB881 - DockNode ID=0x00000004 Parent=0x00000001 SizeRef=225,940 Selected=0xE096E5AE - DockNode ID=0x00000002 Parent=0x00000005 SizeRef=1293,1036 CentralNode=1 Selected=0x13926F0B - DockNode ID=0x00000006 Parent=0xC5C9B8AB SizeRef=234,1036 Selected=0xE7039252 +DockSpace ID=0xC5C9B8AB Window=0xBE4044E9 Pos=8,79 Size=1920,1012 Split=X + DockNode ID=0x00000005 Parent=0xC5C9B8AB SizeRef=1526,1036 Split=X + DockNode ID=0x00000001 Parent=0x00000005 SizeRef=308,1036 Split=Y Selected=0x1E6EB881 + DockNode ID=0x00000003 Parent=0x00000001 SizeRef=225,147 Selected=0x1E6EB881 + DockNode ID=0x00000004 Parent=0x00000001 SizeRef=225,863 Selected=0xE096E5AE + DockNode ID=0x00000002 Parent=0x00000005 SizeRef=1216,1036 Split=Y Selected=0xB41284E7 + DockNode ID=0x00000007 Parent=0x00000002 SizeRef=1501,672 Split=Y Selected=0xB41284E7 + DockNode ID=0x00000009 Parent=0x00000007 SizeRef=1501,700 Split=Y Selected=0xB41284E7 + DockNode ID=0x0000000B Parent=0x00000009 SizeRef=1501,715 CentralNode=1 Selected=0xB41284E7 + DockNode ID=0x0000000C Parent=0x00000009 SizeRef=1501,295 Selected=0xB128252A + DockNode ID=0x0000000A Parent=0x00000007 SizeRef=1501,310 Selected=0xD446F7B6 + DockNode ID=0x00000008 Parent=0x00000002 SizeRef=1501,338 Selected=0xD9F31532 + DockNode ID=0x00000006 Parent=0xC5C9B8AB SizeRef=392,1036 Selected=0xE7039252 diff --git a/Assets/Editor/Layouts/UserLayout.ini b/Assets/Editor/Layouts/UserLayout.ini deleted file mode 100644 index baced6b8..00000000 --- a/Assets/Editor/Layouts/UserLayout.ini +++ /dev/null @@ -1,54 +0,0 @@ -[Window][MainStatusBar] -Pos=0,1060 -Size=1920,20 -Collapsed=0 - -[Window][SHEditorMenuBar] -Pos=0,48 -Size=1920,1012 -Collapsed=0 - -[Window][Hierarchy Panel] -Pos=0,142 -Size=387,918 -Collapsed=0 -DockId=0x00000004,0 - -[Window][Debug##Default] -Pos=60,60 -Size=400,400 -Collapsed=0 - -[Window][Inspector] -Pos=1649,48 -Size=271,1012 -Collapsed=0 -DockId=0x00000006,0 - -[Window][Profiler] -Pos=0,48 -Size=387,92 -Collapsed=0 -DockId=0x00000003,0 - -[Window][Viewport] -Pos=648,48 -Size=2519,1319 -Collapsed=0 -DockId=0x00000002,0 - -[Window][ Viewport] -Pos=389,48 -Size=1258,1012 -Collapsed=0 -DockId=0x00000002,0 - -[Docking][Data] -DockSpace ID=0xC5C9B8AB Window=0xBE4044E9 Pos=8,79 Size=1920,1012 Split=X - DockNode ID=0x00000005 Parent=0xC5C9B8AB SizeRef=1992,1036 Split=X - DockNode ID=0x00000001 Parent=0x00000005 SizeRef=387,1036 Split=Y Selected=0x1E6EB881 - DockNode ID=0x00000003 Parent=0x00000001 SizeRef=225,94 Selected=0x1E6EB881 - DockNode ID=0x00000004 Parent=0x00000001 SizeRef=225,940 Selected=0xE096E5AE - DockNode ID=0x00000002 Parent=0x00000005 SizeRef=1258,1036 CentralNode=1 Selected=0xB41284E7 - DockNode ID=0x00000006 Parent=0xC5C9B8AB SizeRef=271,1036 Selected=0xE7039252 - diff --git a/SHADE_Application/src/Application/SBApplication.cpp b/SHADE_Application/src/Application/SBApplication.cpp index a93148d5..54dc0ccf 100644 --- a/SHADE_Application/src/Application/SBApplication.cpp +++ b/SHADE_Application/src/Application/SBApplication.cpp @@ -56,8 +56,8 @@ namespace Sandbox _In_ INT nCmdShow ) { - // Set working directory - SHFileUtilities::SetWorkDirToExecDir(); + // Set working directory + SHFileUtilities::SetWorkDirToExecDir(); window.Create(hInstance, hPrevInstance, lpCmdLine, nCmdShow); @@ -152,16 +152,16 @@ namespace Sandbox SHSceneManager::SceneUpdate(0.016f); #endif SHSystemManager::RunRoutines(editor->editorState != SHEditor::State::PLAY, 0.016f); - //editor->PollPicking(); + editor->PollPicking(); } // Finish all graphics jobs first - graphicsSystem->AwaitGraphicsExecution(); + graphicsSystem->AwaitGraphicsExecution(); } void SBApplication::Exit(void) { - #ifdef SHEDITOR + #ifdef SHEDITOR SDL_DestroyWindow(sdlWindow); SDL_Quit(); #endif diff --git a/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.cpp b/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.cpp new file mode 100644 index 00000000..caad9b10 --- /dev/null +++ b/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.cpp @@ -0,0 +1,84 @@ +#include "SHpch.h" +#include "SHAssetBrowser.h" + +#include "Editor/IconsMaterialDesign.h" +#include "Editor/SHImGuiHelpers.hpp" +#include + +#include "Assets/SHAssetManager.h" +#include "Editor/DragDrop/SHDragDrop.hpp" + +namespace SHADE +{ + SHAssetBrowser::SHAssetBrowser() + :SHEditorWindow("\xee\x8b\x87 Asset Browser", ImGuiWindowFlags_MenuBar) + { + } + + void SHAssetBrowser::Init() + { + SHEditorWindow::Init(); + } + + void SHAssetBrowser::Update() + { + SHEditorWindow::Update(); + if(Begin()) + { + DrawMenuBar(); + auto const& assets = SHAssetManager::GetAllAssets(); + if(ImGui::BeginTable("AssetBrowserTable", 3)) + { + ImGui::TableNextColumn(); + ImGui::TableHeader("Asset ID"); + ImGui::TableNextColumn(); + ImGui::TableHeader("Name"); + ImGui::TableNextColumn(); + ImGui::TableHeader("Type"); + for(SHAsset const& asset : assets) + { + DrawAsset(asset); + } + ImGui::EndTable(); + } + } + ImGui::End(); + } + + void SHAssetBrowser::DrawMenuBar() + { + if(ImGui::BeginMenuBar()) + { + + ImGui::EndMenuBar(); + } + } + + void SHAssetBrowser::DrawAsset(SHAsset const& asset) + { + ImGui::PushID(asset.id); + ImGui::BeginGroup(); + + ImGui::TableNextColumn(); + ImGui::Selectable(std::format("{}", asset.id).data(), false, ImGuiSelectableFlags_SpanAllColumns); + if(SHDragDrop::BeginSource()) + { + auto id = asset.id; + ImGui::Text("Moving Asset: %zu", id); + SHDragDrop::SetPayload(DRAG_RESOURCE, &id); + SHDragDrop::EndSource(); + } + + ImGui::TableNextColumn(); + ImGui::Text("%s", asset.name.c_str()); + + ImGui::TableNextColumn(); + ImGui::Text("%s", "Type"); + + ImGui::EndGroup(); + ImGui::PopID(); + + + + } +} diff --git a/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.h b/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.h new file mode 100644 index 00000000..0e3053bc --- /dev/null +++ b/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.h @@ -0,0 +1,24 @@ +#pragma once + +#include "Assets/SHAsset.h" +#include "Editor/EditorWindow/SHEditorWindow.h" + +namespace SHADE +{ + class SHAssetBrowser final : public SHEditorWindow + { + public: + SHAssetBrowser(); + + void Init(); + void Update(); + + void Refresh(); + private: + void DrawMenuBar(); + void DrawAsset(SHAsset const& asset); + + float idColumnWidth, nameColumnWidth, typeColumnWidth; + + }; +} \ No newline at end of file diff --git a/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.cpp b/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.cpp index 27e46d98..f2f8d927 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.cpp +++ b/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.cpp @@ -93,8 +93,7 @@ namespace SHADE { if (ImGui::BeginMenuBar()) { - - ImGui::SetCursorPosX(ImGui::GetContentRegionAvail().x - 35.0f); + ImGui::SetCursorPosX(ImGui::GetContentRegionAvail().x * 0.75f); if(ImGui::SmallButton(ICON_MD_DESELECT)) { auto editor = SHSystemManager::GetSystem(); diff --git a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp index 08f5695b..7fa39d74 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp +++ b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp @@ -39,6 +39,10 @@ namespace SHADE { SHComponentManager::RemoveComponent(component->GetEID()); } + if (ImGui::Selectable(std::format("{} Reset {}", ICON_MD_RESTART_ALT, componentName.data()).data())) + { + *component = T(); + } ImGui::EndPopup(); } } @@ -48,7 +52,7 @@ namespace SHADE if (!component) return; const auto componentType = rttr::type::get(*component); - SHEditorWidgets::CheckBox("##IsActive", [component]() {return component->isActive; }, [component](bool const& active) {component->isActive = active; }); + SHEditorWidgets::CheckBox("##IsActive", [component]() {return component->isActive; }, [component](bool const& active) {component->isActive = active; }, "Is Component Active"); ImGui::SameLine(); if (ImGui::CollapsingHeader(componentType.get_name().data())) { @@ -89,7 +93,7 @@ namespace SHADE auto metaMax = property.get_metadata(META::max); if (metaMin && metaMax) { - SHEditorWidgets::SliderInt(property.get_name().data(), metaMin.template get_value(), metaMin.template get_value(), [component, property] {return property.get_value(component).to_int(); }, [component, property](int const& result) {property.set_value(component, result); }); + SHEditorWidgets::SliderInt(property.get_name().data(), metaMin.template get_value(), metaMax.template get_value(), [component, property] {return property.get_value(component).to_int(); }, [component, property](int const& result) {property.set_value(component, result); }); } else { @@ -115,7 +119,7 @@ namespace SHADE auto metaMax = property.get_metadata(META::max); if (metaMin.is_valid() && metaMax.is_valid()) { - SHEditorWidgets::SliderScalar(property.get_name().data(), ImGuiDataType_U16, metaMin.template get_value(), metaMin.template get_value(), [component, property] {return property.get_value(component).to_uint16(); }, [component, property](uint16_t const& result) {property.set_value(component, result); }, "%zu"); + SHEditorWidgets::SliderScalar(property.get_name().data(), ImGuiDataType_U16, metaMin.template get_value(), metaMax.template get_value(), [component, property] {return property.get_value(component).to_uint16(); }, [component, property](uint16_t const& result) {property.set_value(component, result); }, "%zu"); } else { @@ -128,7 +132,7 @@ namespace SHADE auto metaMax = property.get_metadata(META::max); if (metaMin.is_valid() && metaMax.is_valid()) { - SHEditorWidgets::SliderScalar(property.get_name().data(), ImGuiDataType_U32, metaMin.template get_value(), metaMin.template get_value(), [component, property] { return property.get_value(component).to_uint32(); }, [component, property](uint32_t const& result) {property.set_value(component, result); }, "%zu"); + SHEditorWidgets::SliderScalar(property.get_name().data(), ImGuiDataType_U32, metaMin.template get_value(), metaMax.template get_value(), [component, property] { return property.get_value(component).to_uint32(); }, [component, property](uint32_t const& result) {property.set_value(component, result); }, "%zu"); } else { @@ -141,7 +145,7 @@ namespace SHADE auto metaMax = property.get_metadata(META::max); if (metaMin.is_valid() && metaMax.is_valid()) { - SHEditorWidgets::SliderScalar(property.get_name().data(), ImGuiDataType_U64, metaMin.template get_value(), metaMin.template get_value(), [component, property] {return property.get_value(component).to_uint64(); }, [component, property](uint64_t const& result) {property.set_value(component, result); }, "%zu"); + SHEditorWidgets::SliderScalar(property.get_name().data(), ImGuiDataType_U64, metaMin.template get_value(), metaMax.template get_value(), [component, property] {return property.get_value(component).to_uint64(); }, [component, property](uint64_t const& result) {property.set_value(component, result); }, "%zu"); } else { @@ -152,13 +156,18 @@ namespace SHADE { auto metaMin = property.get_metadata(META::min); auto metaMax = property.get_metadata(META::max); + float min{}, max{}; + if(metaMin.is_valid()) + min = std::max(metaMin.template get_value(), -FLT_MAX * 0.5f); + if(metaMax.is_valid()) + max = std::min(metaMax.template get_value(), FLT_MAX * 0.5f); if (metaMin.is_valid() && metaMax.is_valid()) { - SHEditorWidgets::SliderFloat(property.get_name().data(), metaMin.template get_value(), metaMin.template get_value(), [component, property] {return property.get_value(component).to_float(); }, [component, property](float const& result) {property.set_value(component, result); }); + SHEditorWidgets::SliderFloat(property.get_name().data(), min, max, [component, property] {return property.get_value(component).to_float(); }, [component, property](float const& result) {property.set_value(component, result); }); } else { - SHEditorWidgets::DragFloat(property.get_name().data(), [component, property] {return property.get_value(component).to_float(); }, [component, property](float const& result) {property.set_value(component, result); }); + SHEditorWidgets::DragFloat(property.get_name().data(), [component, property] {return property.get_value(component).to_float(); }, [component, property](float const& result) {property.set_value(component, result); }, "Test"); } } else if (type == rttr::type::get()) @@ -167,7 +176,7 @@ namespace SHADE auto metaMax = property.get_metadata(META::max); if (metaMin.is_valid() && metaMax.is_valid()) { - SHEditorWidgets::SliderScalar(property.get_name().data(), ImGuiDataType_Double, metaMin.template get_value(), metaMin.template get_value(), [component, property] {return property.get_value(component).to_double(); }, [component, property](double const& result) {property.set_value(component, result); }); + SHEditorWidgets::SliderScalar(property.get_name().data(), ImGuiDataType_Double, metaMin.template get_value(), metaMax.template get_value(), [component, property] {return property.get_value(component).to_double(); }, [component, property](double const& result) {property.set_value(component, result); }); } else { diff --git a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorInspector.cpp b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorInspector.cpp index b59ce9cc..ada5a35a 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorInspector.cpp +++ b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorInspector.cpp @@ -84,8 +84,8 @@ namespace SHADE } ImGui::Separator(); // Render Scripts - SHScriptEngine* scriptEngine = static_cast(SHSystemManager::GetSystem()); - scriptEngine->RenderScriptsInInspector(eid); + SHScriptEngine* scriptEngine = static_cast(SHSystemManager::GetSystem()); + scriptEngine->RenderScriptsInInspector(eid); ImGui::Separator(); if(ImGui::BeginMenu(std::format("{} Add Component", ICON_MD_LIBRARY_ADD).data())) { diff --git a/SHADE_Engine/src/Editor/EditorWindow/SHEditorWindowIncludes.h b/SHADE_Engine/src/Editor/EditorWindow/SHEditorWindowIncludes.h index f0267b06..5208c6d9 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/SHEditorWindowIncludes.h +++ b/SHADE_Engine/src/Editor/EditorWindow/SHEditorWindowIncludes.h @@ -3,4 +3,5 @@ #include "HierarchyPanel/SHHierarchyPanel.h" //Hierarchy Panel #include "Inspector/SHEditorInspector.h" //Inspector #include "Profiling/SHEditorProfiler.h" //Profiler -#include "ViewportWindow/SHEditorViewport.h" //Editor Viewport \ No newline at end of file +#include "ViewportWindow/SHEditorViewport.h" //Editor Viewport +#include "AssetBrowser/SHAssetBrowser.h" //Asset Browser \ No newline at end of file diff --git a/SHADE_Engine/src/Editor/EditorWindow/ViewportWindow/SHEditorViewport.cpp b/SHADE_Engine/src/Editor/EditorWindow/ViewportWindow/SHEditorViewport.cpp index b06c37c7..f5170999 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/ViewportWindow/SHEditorViewport.cpp +++ b/SHADE_Engine/src/Editor/EditorWindow/ViewportWindow/SHEditorViewport.cpp @@ -24,12 +24,13 @@ namespace SHADE void SHEditorViewport::Init() { SHEditorWindow::Init(); - + transformGizmo.Init(); } void SHEditorViewport::Update() { SHEditorWindow::Update(); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f,0.0f)); if(Begin()) { ImGuizmo::SetDrawlist(); @@ -55,7 +56,7 @@ namespace SHADE ImGuizmo::SetRect(beginCursorPos.x , beginCursorPos.y, beginContentRegionAvailable.x, beginContentRegionAvailable.y); transformGizmo.Draw(); ImGui::End(); - + ImGui::PopStyleVar(); } void SHEditorViewport::Exit() diff --git a/SHADE_Engine/src/Editor/Gizmos/SHTransformGizmo.cpp b/SHADE_Engine/src/Editor/Gizmos/SHTransformGizmo.cpp index a53b8c10..3c984051 100644 --- a/SHADE_Engine/src/Editor/Gizmos/SHTransformGizmo.cpp +++ b/SHADE_Engine/src/Editor/Gizmos/SHTransformGizmo.cpp @@ -13,6 +13,12 @@ #include "Editor/EditorWindow/ViewportWindow/SHEditorViewport.h" namespace SHADE { + void SHTransformGizmo::Init() + { + auto& style = ImGuizmo::GetStyle(); + style.RotationLineThickness = 2.5f; + } + void SHTransformGizmo::Draw() { bool justChangedTfm = false; @@ -26,9 +32,12 @@ namespace SHADE SHMatrix view = SHMatrix::Transpose(editorCamera->GetViewMatrix()); SHMatrix proj = SHMatrix::Transpose(editorCamera->GetProjMatrix()); + + //Invert projection y-axis proj(1, 1) *= -1; + static SHMatrix gridMat = SHMatrix::Translate(0, -0.5f, 0.f) * SHMatrix::Identity; - //ImGuizmo::DrawGrid(&view._11, &proj._11, &gridMat._11, 100.f); + if (selectedEntityTransformComponent == nullptr) { SHEditor* editor = SHSystemManager::GetSystem(); @@ -55,31 +64,37 @@ namespace SHADE return; SHMatrix mat = selectedEntityTransformComponent->GetTRS(); - isManipulating = ImGuizmo::Manipulate(&view._11, &proj._11, static_cast(operation), ImGuizmo::MODE::WORLD, &mat._11); - if (!justChangedTfm) + useSnap = ImGui::IsKeyDown(ImGuiKey_LeftCtrl); + if(useSnap) { - if (ImGui::IsItemClicked()) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(selectedEntityTransformComponent->GetTRS(), mat, [tfm = std::move(selectedEntityTransformComponent)](SHMatrix const& mtx) - { - if (!tfm) - return; - SHVec3 translate{}, rotate{}, scale{}; - mtx.Decompose(translate, rotate, scale); - tfm->SetWorldPosition(translate); - tfm->SetWorldRotation(rotate); - tfm->SetWorldScale(scale); - }))); - else if (ImGui::IsItemHovered(ImGuiMouseButton_Left) && ImGui::IsMouseDown(ImGuiMouseButton_Left) && isManipulating) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(selectedEntityTransformComponent->GetTRS(), mat, [tfm = std::move(selectedEntityTransformComponent)](SHMatrix const& mtx) - { - if (!tfm) - return; - SHVec3 translate{}, rotate{}, scale{}; - mtx.Decompose(translate, rotate, scale); - tfm->SetWorldPosition(translate); - tfm->SetWorldRotation(rotate); - tfm->SetWorldScale(scale); - })), true); + switch (operation) + { + case Operation::TRANSLATE: snap = &translationSnap.x; break; + case Operation::ROTATE: snap = &rotationSnap; break; + case Operation::SCALE: snap = &scaleSnap; break; + default: snap = &translationSnap.x; + } } + ImGuizmo::Manipulate(&view._11, &proj._11, static_cast(operation), ImGuizmo::MODE::WORLD, &mat._11, nullptr, useSnap ? snap : nullptr); + static bool startRecording = false; + if (!justChangedTfm && ImGuizmo::IsUsing()) + { + + SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(selectedEntityTransformComponent->GetTRS(), mat, [tfm = (selectedEntityTransformComponent)](SHMatrix const& mtx) + { + if (!tfm) + return; + SHVec3 translate{}, rotate{}, scale{}; + mtx.Decompose(translate, rotate, scale); + tfm->SetWorldPosition(translate); + tfm->SetWorldRotation(rotate); + tfm->SetWorldScale(scale); + })), startRecording); + if(!startRecording) + startRecording = true; + } + isManipulating = ImGuizmo::IsUsing() || startRecording; + if(startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left)) + startRecording = false; } } diff --git a/SHADE_Engine/src/Editor/Gizmos/SHTransformGizmo.h b/SHADE_Engine/src/Editor/Gizmos/SHTransformGizmo.h index 2565575f..fd847335 100644 --- a/SHADE_Engine/src/Editor/Gizmos/SHTransformGizmo.h +++ b/SHADE_Engine/src/Editor/Gizmos/SHTransformGizmo.h @@ -37,11 +37,17 @@ namespace SHADE UNIVERSAL = TRANSLATE | ROTATE | SCALEU }; + void Init(); void Draw(); bool isManipulating = false; + bool useSnap = false; Mode mode = Mode::WORLD; Operation operation = Operation::TRANSLATE; private: + float scaleSnap = 0.25f; + float rotationSnap = 1.0f; + SHVec3 translationSnap = SHVec3(0.25f, 0.25f, 0.25f); + float* snap = nullptr; SHTransformComponent* selectedEntityTransformComponent{nullptr}; SHCameraComponent* editorCamera{nullptr}; }; diff --git a/SHADE_Engine/src/Editor/SHEditor.cpp b/SHADE_Engine/src/Editor/SHEditor.cpp index aff1eaad..06fadfee 100644 --- a/SHADE_Engine/src/Editor/SHEditor.cpp +++ b/SHADE_Engine/src/Editor/SHEditor.cpp @@ -92,6 +92,7 @@ namespace SHADE SHEditorWindowManager::CreateEditorWindow(); SHEditorWindowManager::CreateEditorWindow(); SHEditorWindowManager::CreateEditorWindow(); + SHEditorWindowManager::CreateEditorWindow(); SHEditorWindowManager::CreateEditorWindow(); io = &ImGui::GetIO(); @@ -134,7 +135,7 @@ namespace SHADE } } - PollPicking(); + //PollPicking(); if(ImGui::IsKeyDown(ImGuiKey_LeftShift) && ImGui::IsKeyDown(ImGuiKey_LeftCtrl) && ImGui::IsKeyReleased(ImGuiKey_Z)) { diff --git a/SHADE_Engine/src/Editor/SHEditorWidgets.hpp b/SHADE_Engine/src/Editor/SHEditorWidgets.hpp index 5788dc15..b54a6799 100644 --- a/SHADE_Engine/src/Editor/SHEditorWidgets.hpp +++ b/SHADE_Engine/src/Editor/SHEditorWidgets.hpp @@ -40,7 +40,6 @@ namespace SHADE { ImGui::BeginGroup(); - auto cursorPos = ImGui::GetCursorScreenPos(); auto itemSpacing = ImGui::GetStyle().ItemSpacing; ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.0f, 0.0f)); ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, 0.0f)); @@ -158,7 +157,7 @@ namespace SHADE } template - static bool DragN(const std::string& fieldLabel, std::vectorconst& componentLabels, + static bool DragN(const std::string& label, std::vectorconst& componentLabels, std::vector values, float speed = 0.1f, const char* displayFormat = "", T valueMin = T(), T valueMax = T(), ImGuiSliderFlags flags = 0, bool* isHovered = nullptr) { @@ -169,13 +168,13 @@ namespace SHADE const ImGuiContext& g = *GImGui; bool valueChanged = false; ImGui::BeginGroup(); - ImGui::PushID(fieldLabel.c_str()); + ImGui::PushID(label.c_str()); PushMultiItemsWidthsAndLabels(componentLabels, 0.0f); ImGui::BeginColumns("DragVecCol", 2, ImGuiOldColumnFlags_NoBorder | ImGuiOldColumnFlags_NoResize); ImGui::SetColumnWidth(-1, 80.0f); - ImGui::Text(fieldLabel.c_str()); + ImGui::Text(label.c_str()); if (isHovered) - *isHovered = ImGui::IsItemHovered(); + *isHovered = ImGui::IsItemHovered(); ImGui::NextColumn(); for (std::size_t i = 0; i < N; ++i) { @@ -203,75 +202,91 @@ namespace SHADE return valueChanged; } - static bool DragVec2(const std::string& fieldLabel, std::vectorconst& componentLabels, std::function get, - std::function set, float speed = 0.1f, const char* displayFormat = "%.3f", float valueMin = 0.0f, float valueMax = 0.0f, + static bool DragVec2(const std::string& label, std::vectorconst& componentLabels, std::function get, + std::function set, float speed = 0.1f, const char* displayFormat = "%.3f", std::string_view const& tooltip = {}, float valueMin = 0.0f, float valueMax = 0.0f, ImGuiSliderFlags flags = 0) { SHVec2 values = get(); - bool changed = false; - if (DragN(fieldLabel, componentLabels, { &values.x, &values.y }, speed, displayFormat, valueMin, valueMax, flags)) - { - changed = true; - } - + bool const changed = DragN(label, componentLabels, { &values.x, &values.y }, speed, displayFormat, valueMin, valueMax, flags); + static bool startRecording = false; if (changed) { - if (ImGui::IsMouseClicked(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), values, set)), false); - else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), values, set)), true); - else if (ImGui::IsItemDeactivatedAfterEdit()) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), values, set)), false); + SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), values, set)), startRecording); + if (!startRecording) + startRecording = true; + } + if (startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left)) + startRecording = false; + if(!tooltip.empty()) + { + if(ImGui::IsItemHovered()) + { + ImGui::BeginTooltip(); + ImGui::Text(tooltip.data()); + ImGui::EndTooltip(); + } } - return changed; } - static bool DragVec3(const std::string& fieldLabel, std::vectorconst& componentLabels, std::function get, - std::function set, float speed = 0.1f, const char* displayFormat = "%.3f", float valueMin = 0.0f, float valueMax = 0.0f, + static bool DragVec3(const std::string& label, std::vectorconst& componentLabels, std::function get, + std::function set, float speed = 0.1f, const char* displayFormat = "%.3f", std::string_view const& tooltip = {}, float valueMin = 0.0f, float valueMax = 0.0f, ImGuiSliderFlags flags = 0) { SHVec3 values = get(); - bool changed = false; - if (DragN(fieldLabel, componentLabels, { &values.x, &values.y, &values.z }, speed, displayFormat, valueMin, valueMax, flags)) - { - changed = true; - } + bool const changed = DragN(label, componentLabels, { &values.x, &values.y, &values.z }, speed, displayFormat, valueMin, valueMax, flags); + + static bool startRecording = false; if (changed) { - if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), values, set)), false); - else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), values, set)), true); - else if (ImGui::IsItemDeactivatedAfterEdit()) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), values, set)), false); + SHVec3 old = get(); + SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(old, values, set)), startRecording); + if (!startRecording) + startRecording = true; + } + if (startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left)) + { + startRecording = false; + } + if(!tooltip.empty()) + { + if(ImGui::IsItemHovered()) + { + ImGui::BeginTooltip(); + ImGui::Text(tooltip.data()); + ImGui::EndTooltip(); + } } - return changed; } - static bool DragVec4(const std::string& fieldLabel, std::vectorconst& componentLabels, std::function get, - std::function set, float speed = 0.1f, const char* displayFormat = "%.3f", float valueMin = 0.0f, float valueMax = 0.0f, + static bool DragVec4(const std::string& label, std::vectorconst& componentLabels, std::function get, + std::function set, float speed = 0.1f, const char* displayFormat = "%.3f", std::string_view const& tooltip = {}, float valueMin = 0.0f, float valueMax = 0.0f, ImGuiSliderFlags flags = 0) { SHVec4 values = get(); - bool changed = false; - if (DragN(fieldLabel, componentLabels, { &values.x, &values.y, &values.z, &values.w }, speed, displayFormat, valueMin, valueMax, flags)) - { - changed = true; - } - + bool const changed = DragN(label, componentLabels, { &values.x, &values.y, &values.z, &values.w }, speed, displayFormat, valueMin, valueMax, flags); + static bool startRecording = false; if (changed) { - if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), values, set)), false); - else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), values, set)), true); - else if (ImGui::IsItemDeactivatedAfterEdit()) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), values, set)), false); + SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), values, set)), startRecording); + if (!startRecording) + startRecording = true; + } + if (startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left)) + { + startRecording = false; + } + if(!tooltip.empty()) + { + if(ImGui::IsItemHovered()) + { + ImGui::BeginTooltip(); + ImGui::Text(tooltip.data()); + ImGui::EndTooltip(); + } } - return changed; } @@ -279,173 +294,325 @@ namespace SHADE //|| Widget Extensions || //#==============================================================# - static bool CheckBox(std::string const& label, std::function get, std::function set) + static void TextLabel(std::string_view const& text, bool sameLine = true) + { + const ImVec2 textSize = ImGui::CalcTextSize(text.data(), NULL, true); + if(textSize.x > 0.0f) + { + ImGui::Text(text.data()); + ImGui::SameLine(); + } + } + + static bool CheckBox(std::string_view const& label, std::function get, std::function set, std::string_view const& tooltip = {}) { bool value = get(); - if (ImGui::Checkbox(label.c_str(), &value)) + ImGui::BeginGroup(); + ImGui::PushID(label.data()); + TextLabel(label); + if (ImGui::Checkbox("##", &value)) { SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), false); return true; } + ImGui::PopID(); + ImGui::EndGroup(); + if(!tooltip.empty()) + { + if(ImGui::IsItemHovered()) + { + ImGui::BeginTooltip(); + ImGui::Text(tooltip.data()); + ImGui::EndTooltip(); + } + } return false; } template - static bool RadioButton(std::vector const& listLabels, std::vector const& listTypes, std::function get, std::function set) + static bool RadioButton(std::vector const& label, std::vector const& listTypes, std::function get, std::function set ,std::string_view const& tooltip = {}) { T type = get(); + ImGui::BeginGroup(); + ImGui::PushID(label.data()); + TextLabel(label); for (size_t i = 0; i < listTypes.size(); i++) { - if (ImGui::RadioButton(listLabels[i].c_str(), type == listTypes[i])) + if (ImGui::RadioButton(label[i].c_str(), type == listTypes[i])) { SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), listTypes[i], set)), false); } ImGui::SameLine(); } + ImGui::PopID(); + ImGui::EndGroup(); + if (!tooltip.empty()) + { + if (ImGui::IsItemHovered()) + { + ImGui::BeginTooltip(); + ImGui::Text(tooltip.data()); + ImGui::EndTooltip(); + } + } return true; } static bool InputText(const std::string& label, const std::function get, - const std::function set, ImGuiInputTextFlags flag = 0, - ImGuiInputTextCallback callback = (ImGuiInputTextCallback)0, void* userData = (void*)0) + const std::function set, std::string_view const& tooltip = {}, + ImGuiInputTextFlags flag = 0, ImGuiInputTextCallback callback = (ImGuiInputTextCallback)0, void* userData = (void*)0) { std::string text = get(); - if (ImGui::InputText(label.c_str(), &text, flag, callback, userData)) + ImGui::BeginGroup(); + ImGui::PushID(label.data()); + TextLabel(label); + if (ImGui::InputText("##", &text, flag, callback, userData)) { if (ImGui::IsItemDeactivatedAfterEdit()) SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), text, set)), false); return true; } - return false; - } - - template - static bool DragScalar(const std::string& fieldLabel, ImGuiDataType data_type, std::function get, std::function set, - float speed = 1.0f, T p_min = T(), T p_max = T(), const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0) - { - T value = get(); - std::cout << value << " \n"; - //bool hasChange = ImGui::DragScalar(fieldLabel.c_str(), data_type, &value, speed, &p_min, &p_max, displayFormat, flags); - - if (ImGui::DragScalar(fieldLabel.c_str(), data_type, &value, speed, &p_min, &p_max, displayFormat, flags)) + ImGui::PopID(); + ImGui::EndGroup(); + if (!tooltip.empty()) { - if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), false); - else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), true); - else if (ImGui::IsItemDeactivatedAfterEdit()) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), false); - - return true; + if (ImGui::IsItemHovered()) + { + ImGui::BeginTooltip(); + ImGui::Text(tooltip.data()); + ImGui::EndTooltip(); + } } return false; } - static bool DragFloat(const std::string& fieldLabel, std::function get, std::function set, + template + static bool DragScalar(const std::string& label, ImGuiDataType data_type, std::function get, std::function set, + float speed = 1.0f, T p_min = T(), T p_max = T(), const char* displayFormat = "%.3f", std::string_view const& tooltip = {}, ImGuiSliderFlags flags = 0) + { + T value = get(); + ImGui::BeginGroup(); + ImGui::PushID(label.data()); + TextLabel(label); + const bool hasChange = ImGui::DragScalar("##", data_type, &value, speed, &p_min, &p_max, displayFormat, flags); + static bool startRecording = false; + if (hasChange) + { + SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), startRecording); + if (!startRecording) + startRecording = true; + } + if (startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left)) + { + startRecording = false; + } + ImGui::PopID(); + ImGui::EndGroup(); + if (!tooltip.empty()) + { + if (ImGui::IsItemHovered()) + { + ImGui::BeginTooltip(); + ImGui::Text(tooltip.data()); + ImGui::EndTooltip(); + } + } + return hasChange; + } + + static bool DragFloat(const std::string_view& label, std::function get, std::function set, std::string_view const& tooltip = {}, float speed = 0.1f, float p_min = float(), float p_max = float(), const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0) { float value = get(); - //bool hasChange = ImGui::DragFloat(fieldLabel.c_str(), &value, speed, p_min, p_max, displayFormat, flags); - if (ImGui::DragFloat(fieldLabel.c_str(), &value, speed, p_min, p_max, displayFormat, flags)) + ImGui::BeginGroup(); + ImGui::PushID(label.data()); + TextLabel(label); + const bool hasChange = ImGui::DragFloat("##", &value, speed, p_min, p_max, displayFormat, flags); + static bool startRecording = false; + if (hasChange) { - if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), false); - else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), true); - else if (ImGui::IsItemDeactivatedAfterEdit()) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), false); - - return true; + SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), startRecording); + if (!startRecording) + startRecording = true; } - - return false; + if (startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left)) + { + startRecording = false; + } + ImGui::PopID(); + ImGui::EndGroup(); + if(!tooltip.empty()) + { + if(ImGui::IsItemHovered()) + { + ImGui::BeginTooltip(); + ImGui::Text(tooltip.data()); + ImGui::EndTooltip(); + } + } + return hasChange; } - static bool DragInt(const std::string& fieldLabel, std::function get, std::function set, + static bool DragInt(const std::string& label, std::function get, std::function set, std::string_view const& tooltip = {}, float speed = 1.0f, int p_min = int(), int p_max = int(), const char* displayFormat = "%d", ImGuiSliderFlags flags = 0) { int value = get(); - //bool hasChange = ImGui::DragFloat(fieldLabel.c_str(), &value, speed, p_min, p_max, displayFormat, flags); - if (ImGui::DragInt(fieldLabel.c_str(), &value, speed, p_min, p_max, displayFormat, flags)) + ImGui::BeginGroup(); + ImGui::PushID(label.data()); + TextLabel(label); + const bool hasChange = ImGui::DragInt("##", &value, speed, p_min, p_max, displayFormat, flags); + static bool startRecording = false; + if (hasChange) { - if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), false); - else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), true); - else if (ImGui::IsItemDeactivatedAfterEdit()) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), false); - - return true; + SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), startRecording); + if (!startRecording) + startRecording = true; } - - return false; + if (startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left)) + { + startRecording = false; + } + ImGui::PopID(); + ImGui::EndGroup(); + if (!tooltip.empty()) + { + if (ImGui::IsItemHovered()) + { + ImGui::BeginTooltip(); + ImGui::Text(tooltip.data()); + ImGui::EndTooltip(); + } + } + return hasChange; } template - static bool SliderScalar(const std::string& fieldLabel, ImGuiDataType data_type, T min, T max, std::function get, std::function set, + static bool SliderScalar(const std::string& label, ImGuiDataType data_type, T min, T max, std::function get, std::function set, std::string_view const& tooltip = {}, const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0) { T value = get(); - if (ImGui::SliderScalar(fieldLabel.c_str(), data_type, &value, &min, &max, displayFormat, flags)) + ImGui::BeginGroup(); + ImGui::PushID(label.data()); + TextLabel(label); + bool const hasChange = ImGui::SliderScalar("##", data_type, &value, &min, &max, displayFormat, flags); + static bool startRecording = false; + if (hasChange) { - if (ImGui::IsMouseClicked(ImGuiMouseButton_Left, false) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), false); - else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), true); + SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), startRecording); + if (!startRecording) + startRecording = true; - return true; } - - return false; + if (startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left)) + { + startRecording = false; + } + ImGui::PopID(); + ImGui::EndGroup(); + if (!tooltip.empty()) + { + if (ImGui::IsItemHovered()) + { + ImGui::BeginTooltip(); + ImGui::Text(tooltip.data()); + ImGui::EndTooltip(); + } + } + return hasChange; } - static bool SliderFloat(const std::string& fieldLabel, float min, float max, std::function get, std::function set, + static bool SliderFloat(const std::string& label, float const& min, float const& max, std::function get, std::function set, std::string_view const& tooltip = {}, const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0) { float value = get(); - if (ImGui::SliderFloat(fieldLabel.c_str(), &value, min, max, displayFormat, flags)) + ImGui::BeginGroup(); + ImGui::PushID(label.data()); + TextLabel(label); + bool const hasChange = ImGui::SliderFloat("##", &value, min, max, displayFormat, flags); + static bool startRecording = false; + if (hasChange) { - if (ImGui::IsMouseClicked(ImGuiMouseButton_Left, false) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), false); - else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), true); + SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), startRecording); + if (!startRecording) + startRecording = true; - - return true; } - - return false; + if (startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left)) + { + startRecording = false; + } + ImGui::PopID(); + ImGui::EndGroup(); + if (!tooltip.empty()) + { + if (ImGui::IsItemHovered()) + { + ImGui::BeginTooltip(); + ImGui::Text(tooltip.data()); + ImGui::EndTooltip(); + } + } + return hasChange; } - static bool SliderInt(const std::string& fieldLabel, int min, int max, std::function get, std::function set, + static bool SliderInt(const std::string& label, int min, int max, std::function get, std::function set, std::string_view const& tooltip = {}, const char* displayFormat = "%d", ImGuiSliderFlags flags = 0) { int value = get(); - if (ImGui::SliderInt(fieldLabel.c_str(), &value, min, max, displayFormat, flags)) + ImGui::BeginGroup(); + ImGui::PushID(label.data()); + TextLabel(label); + bool const hasChange = ImGui::SliderInt("##", &value, min, max, displayFormat, flags); + static bool startRecording = false; + if (hasChange) { - if (ImGui::IsMouseClicked(ImGuiMouseButton_Left, false) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), false); - else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), true); - return true; + SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), startRecording); + if (!startRecording) + startRecording = true; } - - return false; + if (startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left)) + { + startRecording = false; + } + ImGui::PopID(); + ImGui::EndGroup(); + if (!tooltip.empty()) + { + if (ImGui::IsItemHovered()) + { + ImGui::BeginTooltip(); + ImGui::Text(tooltip.data()); + ImGui::EndTooltip(); + } + } + return hasChange; } - static bool ComboBox(const std::string& fieldLabel, std::vector list, std::function get, std::function set) + static bool ComboBox(const std::string& label, std::vector list, std::function get, std::function set, std::string_view const& tooltip = {}) { bool edited = false; int selected = get(); - ImGui::PushID(fieldLabel.c_str()); - ImGui::Text(fieldLabel.c_str()); ImGui::SameLine(); + ImGui::BeginGroup(); + ImGui::PushID(label.c_str()); + TextLabel(label); + ImGui::SameLine(); if (edited = ImGui::Combo("##Combo", &selected, list.data(), static_cast(list.size()))) { SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), selected, set)), false); } ImGui::PopID(); + ImGui::EndGroup(); + if (!tooltip.empty()) + { + if (ImGui::IsItemHovered()) + { + ImGui::BeginTooltip(); + ImGui::Text(tooltip.data()); + ImGui::EndTooltip(); + } + } return edited; } };