diff --git a/ExampleApp/Src/FPSPlayer.cs b/ExampleApp/Src/FPSPlayer.cs index a88a0f0..8d05e55 100644 --- a/ExampleApp/Src/FPSPlayer.cs +++ b/ExampleApp/Src/FPSPlayer.cs @@ -53,7 +53,7 @@ namespace FPSExample RaycastHit hitInfo; if (Input.IsKeyPressed(KeyCode.H) && - Physics.Raycast(m_CameraTransform.Position + (m_CameraTransform.Transform.Forward * 5.0f), + Physics.Raycast(m_CameraTransform.Position + (m_CameraTransform.Transform.Forward), m_CameraTransform.Transform.Forward, 20.0f, out hitInfo)) { FindEntityByID(hitInfo.EntityID).GetComponent().Mesh.GetMaterial(0).Set("u_AlbedoColor", new Vec3(1.0f ,0.0f, 0.0f)); diff --git a/Prism/src/Prism/Editor/SceneHierachyPanel.cpp b/Prism/src/Prism/Editor/SceneHierachyPanel.cpp index 19d9fde..9b72134 100644 --- a/Prism/src/Prism/Editor/SceneHierachyPanel.cpp +++ b/Prism/src/Prism/Editor/SceneHierachyPanel.cpp @@ -44,7 +44,96 @@ namespace Prism } } - void SceneHierarchyPanel::SetSelected(Entity entity) + static bool DrawVec3Control(const std::string& label, glm::vec3& values, const float resetValue = 0.0f, const float columnWidth = 100.0f) + { + const ImGuiIO& io = ImGui::GetIO(); + const auto boldFont = io.Fonts->Fonts[0]; + bool isChanged = false; + ImGui::PushID(label.c_str()); + + ImGui::Columns(2); + + ImGui::SetColumnWidth(0, columnWidth); + ImGui::Text(label.c_str()); + ImGui::NextColumn(); + + ImGui::PushMultiItemsWidths(3, ImGui::CalcItemWidth()); + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, {0.0f, 0.0f}); + + const float lineHeight = GImGui->Font->LegacySize + GImGui->Style.FramePadding.y * 2.0f; + + const ImVec2 buttonSize = {lineHeight + 3.0f, lineHeight}; + + ImGui::PushStyleColor(ImGuiCol_Button, ImVec4{0.8f, 0.1f, 0.15f, 1.0f}); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4{0.9f, 0.2f, 0.2f, 1.0f}); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4{0.8f, 0.1f, 0.15f, 1.0f}); + ImGui::PushFont(boldFont); + if (ImGui::Button("X", buttonSize)) + { + values.x = resetValue; + isChanged = true; + } + ImGui::PopFont(); + ImGui::PopStyleColor(3); + + ImGui::SameLine(); + if (ImGui::DragFloat("##X", &values.x, 0.1f)) + { + isChanged = true; + } + ImGui::PopItemWidth(); + ImGui::SameLine(); + + ImGui::PushStyleColor(ImGuiCol_Button, ImVec4{0.2f, 0.7f, 0.2f, 1.0f}); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4{0.3f, 0.8f, 0.3f, 1.0f}); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4{0.2f, 0.7f, 0.2f, 1.0f}); + ImGui::PushFont(boldFont); + if (ImGui::Button("Y", buttonSize)) + { + values.y = resetValue; + isChanged = true; + } + ImGui::PopFont(); + ImGui::PopStyleColor(3); + + ImGui::SameLine(); + if (ImGui::DragFloat("##Y", &values.y, 0.1f)) + { + isChanged = true; + } + ImGui::PopItemWidth(); + ImGui::SameLine(); + + ImGui::PushStyleColor(ImGuiCol_Button, ImVec4{0.1f, 0.25f, 0.8f, 1.0f}); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4{0.2f, 0.35f, 0.9f, 1.0f}); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4{0.1f, 0.25f, 0.8f, 1.0f}); + ImGui::PushFont(boldFont); + if (ImGui::Button("Z", buttonSize)) + { + values.z = resetValue; + isChanged = true; + } + ImGui::PopFont(); + ImGui::PopStyleColor(3); + + ImGui::SameLine(); + if (ImGui::DragFloat("##Z", &values.z, 0.1f)) + { + isChanged = true; + } + ImGui::PopItemWidth(); + + + ImGui::PopStyleVar(); + ImGui::Columns(1); + + ImGui::PopID(); + + return isChanged; + } + + + void SceneHierarchyPanel::SetSelected(const Entity entity) { m_SelectionContext = entity; } @@ -94,136 +183,6 @@ namespace Prism { DrawComponents(m_SelectionContext); - if (ImGui::Button("Add Component")) - ImGui::OpenPopup("AddComponentPanel"); - - if (ImGui::BeginPopup("AddComponentPanel")) - { - AddComponentPopup("Camera"); - AddComponentPopup("Mesh"); - AddComponentPopup("Script"); - AddComponentPopup("SpriteRenderer"); - AddComponentPopup("RigidBody2D"); - AddComponentPopup("BoxCollider2D"); - AddComponentPopup("CircleCollider2D"); - AddComponentPopup("RigidBody"); - AddComponentPopup("PhysicsMaterial"); - AddComponentPopup("BoxCollider"); - AddComponentPopup("SphereCollider"); - AddComponentPopup("CapsuleCollider"); - AddComponentPopup("MeshCollider"); - - /* - if (!m_SelectionContext.HasComponent()) - { - if (ImGui::Button("Camera")) - { - m_SelectionContext.AddComponent(); - ImGui::CloseCurrentPopup(); - } - } - if (!m_SelectionContext.HasComponent()) - { - if (ImGui::Button("Mesh")) - { - m_SelectionContext.AddComponent(); - ImGui::CloseCurrentPopup(); - } - } - if (!m_SelectionContext.HasComponent()) - { - if (ImGui::Button("Script")) - { - m_SelectionContext.AddComponent(); - ImGui::CloseCurrentPopup(); - } - } - if (!m_SelectionContext.HasComponent()) - { - if (ImGui::Button("Sprite Renderer")) - { - m_SelectionContext.AddComponent(); - ImGui::CloseCurrentPopup(); - } - } - if (!m_SelectionContext.HasComponent()) - { - if (ImGui::Button("Rigidbody 2D")) - { - m_SelectionContext.AddComponent(); - ImGui::CloseCurrentPopup(); - } - } - if (!m_SelectionContext.HasComponent()) - { - if (ImGui::Button("Box Collider 2D")) - { - m_SelectionContext.AddComponent(); - ImGui::CloseCurrentPopup(); - } - } - if (!m_SelectionContext.HasComponent()) - { - if (ImGui::Button("Circle Collider 2D")) - { - m_SelectionContext.AddComponent(); - ImGui::CloseCurrentPopup(); - } - } - if (!m_SelectionContext.HasComponent()) - { - if (ImGui::Button("Rigidbody")) - { - m_SelectionContext.AddComponent(); - ImGui::CloseCurrentPopup(); - } - } - if (!m_SelectionContext.HasComponent()) - { - if (ImGui::Button("Physics Material")) - { - m_SelectionContext.AddComponent(); - ImGui::CloseCurrentPopup(); - } - } - if (!m_SelectionContext.HasComponent()) - { - if (ImGui::Button("Box Collider")) - { - m_SelectionContext.AddComponent(); - ImGui::CloseCurrentPopup(); - } - } - if (!m_SelectionContext.HasComponent()) - { - if (ImGui::Button("Sphere Collider")) - { - m_SelectionContext.AddComponent(); - ImGui::CloseCurrentPopup(); - } - } - - if (!m_SelectionContext.HasComponent()) - { - if (ImGui::Button("Capsule Collider")) - { - m_SelectionContext.AddComponent(); - ImGui::CloseCurrentPopup(); - } - } - - if (!m_SelectionContext.HasComponent()) - { - if (ImGui::Button("Mesh Collider")) - { - m_SelectionContext.AddComponent(); - ImGui::CloseCurrentPopup(); - } - } - */ - - ImGui::EndPopup(); - } } } ImGui::End(); @@ -252,11 +211,12 @@ namespace Prism void SceneHierarchyPanel::DrawEntityNode(Entity entity) { - const char* name = "Unnamed Entity"; + auto name = "Unnamed Entity"; if (entity.HasComponent()) name = entity.GetComponent().Tag.c_str(); - const ImGuiTreeNodeFlags node_flags = (entity == m_SelectionContext ? ImGuiTreeNodeFlags_Selected : 0) | ImGuiTreeNodeFlags_OpenOnArrow; + ImGuiTreeNodeFlags node_flags = (entity == m_SelectionContext ? ImGuiTreeNodeFlags_Selected : 0) | ImGuiTreeNodeFlags_OpenOnArrow; + node_flags |= ImGuiTreeNodeFlags_SpanAvailWidth; const bool opened = ImGui::TreeNodeEx((const void*)(uintptr_t)(uint32_t)entity, node_flags, name); if (ImGui::IsItemClicked()) { @@ -275,12 +235,15 @@ namespace Prism } if (opened) { + // TODO: children + /* if (entity.HasComponent()) { auto mesh = entity.GetComponent().Mesh; // if (mesh) // DrawMeshNode(mesh); } + */ ImGui::TreePop(); } @@ -581,22 +544,29 @@ namespace Prism template static void DrawComponent(const std::string& name, Entity entity, UIFunction uiFunction) { + const ImGuiTreeNodeFlags treeNodeFlags = ImGuiTreeNodeFlags_DefaultOpen | + ImGuiTreeNodeFlags_Framed | + ImGuiTreeNodeFlags_SpanAvailWidth | + ImGuiTreeNodeFlags_AllowOverlap | + ImGuiTreeNodeFlags_FramePadding; if (entity.HasComponent()) { - bool removeComponent = false; - auto& component = entity.GetComponent(); - const bool open = ImGui::TreeNodeEx((void*)((uint32_t)entity | typeid(T).hash_code()), ImGuiTreeNodeFlags_DefaultOpen | ImGuiTreeNodeFlags_AllowOverlap, name.c_str()); - ImGui::SameLine(); - ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0)); - ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0, 0, 0, 0)); - if (ImGui::Button("+")) + + const ImVec2 contentRegionAvailable = ImGui::GetContentRegionAvail(); + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2{ 4, 4 }); + const float lineHeight = GImGui->Font->LegacySize + GImGui->Style.FramePadding.y * 2.0f; + ImGui::Separator(); + + const bool open = ImGui::TreeNodeEx((void*)typeid(T).hash_code(), treeNodeFlags, name.c_str()); + ImGui::PopStyleVar(); + ImGui::SameLine(contentRegionAvailable.x - lineHeight * 0.5f); + if (ImGui::Button("+", ImVec2{ lineHeight, lineHeight })) { ImGui::OpenPopup("ComponentSettings"); } - ImGui::PopStyleColor(); - ImGui::PopStyleColor(); + bool removeComponent = false; if (ImGui::BeginPopup("ComponentSettings")) { @@ -609,11 +579,8 @@ namespace Prism if (open) { uiFunction(component); - ImGui::NextColumn(); - ImGui::Columns(1); ImGui::TreePop(); } - ImGui::Separator(); if (removeComponent) entity.RemoveComponent(); @@ -626,63 +593,71 @@ namespace Prism auto id = entity.GetComponent().ID; + ImVec2 contentRegionAvailable = ImGui::GetContentRegionAvail(); + if (entity.HasComponent()) { - auto& tag = entity.GetComponent().Tag; - char buffer[256]; - memset(buffer, 0, 256); + auto& tag = entity.GetComponent().Tag; + char buffer[256] = {}; memcpy(buffer, tag.c_str(), tag.length()); + + ImGui::PushItemWidth(contentRegionAvailable.x * 0.5f); if (ImGui::InputText("##Tag", buffer, 256)) { tag = std::string(buffer); } + ImGui::PopItemWidth(); + } // ID ImGui::SameLine(); ImGui::TextDisabled("%llx", (uint64_t)id); + const ImVec2 textSize = ImGui::CalcTextSize("Add Component"); + ImGui::SameLine(contentRegionAvailable.x - (textSize.x + GImGui->Style.FramePadding.y)); + if (ImGui::Button("Add Component")) + ImGui::OpenPopup("AddComponentPanel"); - ImGui::Separator(); + if (ImGui::BeginPopup("AddComponentPanel")) + { + AddComponentPopup("Camera"); + AddComponentPopup("Mesh"); + AddComponentPopup("Script"); + AddComponentPopup("SpriteRenderer"); + AddComponentPopup("RigidBody2D"); + AddComponentPopup("BoxCollider2D"); + AddComponentPopup("CircleCollider2D"); + AddComponentPopup("RigidBody"); + AddComponentPopup("PhysicsMaterial"); + AddComponentPopup("BoxCollider"); + AddComponentPopup("SphereCollider"); + AddComponentPopup("CapsuleCollider"); + AddComponentPopup("MeshCollider"); + + + ImGui::EndPopup(); + } if (entity.HasComponent()) { + const ImGuiTreeNodeFlags treeNodeFlags = ImGuiTreeNodeFlags_DefaultOpen | + ImGuiTreeNodeFlags_Framed | + ImGuiTreeNodeFlags_SpanAvailWidth | + ImGuiTreeNodeFlags_AllowOverlap | + ImGuiTreeNodeFlags_FramePadding; + TransformComponent& transform = entity.GetComponent(); - if (ImGui::TreeNodeEx((void*)((uint32_t)entity | typeid(TransformComponent).hash_code()), ImGuiTreeNodeFlags_DefaultOpen, "Transform")) + if (ImGui::TreeNodeEx((void*)((uint32_t)entity | typeid(TransformComponent).hash_code()), treeNodeFlags, "Transform")) { - ImGui::Columns(2); - ImGui::Text("Translation"); - ImGui::NextColumn(); - ImGui::PushItemWidth(-1); + DrawVec3Control("Translation", transform.Translation); + DrawVec3Control("Rotation", transform.Rotation); + DrawVec3Control("Scale", transform.Scale, 1.0f); - ImGui::DragFloat3("##translation", glm::value_ptr(transform.Translation), 0.25f); - - ImGui::PopItemWidth(); - ImGui::NextColumn(); - - ImGui::Text("Rotation"); - ImGui::NextColumn(); - ImGui::PushItemWidth(-1); - - ImGui::DragFloat3("##rotation", glm::value_ptr(transform.Rotation), 0.25f); - - ImGui::PopItemWidth(); - ImGui::NextColumn(); - - ImGui::Text("Scale"); - ImGui::NextColumn(); - ImGui::PushItemWidth(-1); - - ImGui::DragFloat3("##scale", glm::value_ptr(transform.Scale), 0.05f); - - ImGui::PopItemWidth(); - ImGui::NextColumn(); - - ImGui::Columns(1); ImGui::TreePop(); } - ImGui::Separator(); + } DrawComponent("Mesh", entity, [](MeshComponent& meshComponent) { @@ -709,7 +684,6 @@ namespace Prism } }); - DrawComponent("Camera", entity, [](CameraComponent& cameraComponent) { // Projection Type const char* projTypeStrings[] = { "Perspective", "Orthographic" }; @@ -771,7 +745,7 @@ namespace Prism DrawComponent("Script", entity, [=](ScriptComponent& scriptComponent) mutable { BeginPropertyGrid(); - std::string oldName = scriptComponent.ModuleName; + const std::string oldName = scriptComponent.ModuleName; if (Property("Module Name", scriptComponent.ModuleName, !ScriptEngine::ModuleExists(scriptComponent.ModuleName))) // TODO: no live edit { // Shutdown old script @@ -869,7 +843,6 @@ namespace Prism #endif }); - DrawComponent("Rigidbody 2D", entity, [](RigidBody2DComponent& rb2dComponent) { // Rigidbody2D Type @@ -1055,7 +1028,6 @@ namespace Prism EndPropertyGrid(); }); - DrawComponent("Mesh Collider", entity, [](MeshColliderComponent& mcc) { ImGui::Columns(3);