#include "PropertiesPanel.h" #include "Scene/Components.h" #include "Utility/ResourceManager.h" #include #include #include #include namespace Light { void PropertiesPanel::OnUserInterfaceUpdate() { ImGui::Begin("Properties"); if (m_EntityContext.IsValid()) { if (m_EntityContext.HasComponent()) { auto& tagComponent = m_EntityContext.GetComponent(); char buffer[256]; memset(buffer, 0, sizeof(buffer)); std::strncpy(buffer, tagComponent.tag.c_str(), sizeof(buffer)); if (ImGui::InputText("##Tag", buffer, sizeof(buffer))) tagComponent.tag = std::string(buffer); } ImGui::SameLine(); ImGui::PushItemWidth(-1); if (ImGui::Button("Add component")) ImGui::OpenPopup("Components"); if (ImGui::BeginPopup("Components")) { if (ImGui::Selectable("SpriteRenderer", false, m_EntityContext.HasComponent() ? ImGuiSelectableFlags_Disabled : NULL)) m_EntityContext.AddComponent(Light::ResourceManager::GetTexture("awesomeface")); if (ImGui::Selectable("Camera", false, m_EntityContext.HasComponent() ? ImGuiSelectableFlags_Disabled : NULL)) m_EntityContext.AddComponent(); ImGui::EndPopup(); } ImGui::PopItemWidth(); DrawComponent("Transform Component", m_EntityContext, [&](auto& transformComponent) { DrawVec3Control("Translation", transformComponent.translation); }); DrawComponent("SpriteRenderer Component", m_EntityContext, [&](auto& spriteRendererComponent) { ImGui::ColorEdit4("Color", &spriteRendererComponent.tint[0]); }); DrawComponent("Camera Component", m_EntityContext, [&](auto& cameraComponent) { auto& camera = cameraComponent.camera; SceneCamera::ProjectionType projectionType = camera.GetProjectionType(); const char* projectionTypesString[] = { "Orthographic", "Perspective" }; if (ImGui::BeginCombo("ProjectionType", projectionTypesString[(int)projectionType])) { for (int i = 0; i < 2; i++) { const bool isSelected = (int)projectionType == i; if (ImGui::Selectable(projectionTypesString[i], isSelected)) { projectionType = (SceneCamera::ProjectionType)i; camera.SetProjectionType(projectionType); } if (isSelected) ImGui::SetItemDefaultFocus(); } ImGui::EndCombo(); } if (projectionType == SceneCamera::ProjectionType::Orthographic) { float orthoSize, nearPlane, farPlane; orthoSize = camera.GetOrthographicSize(); nearPlane = camera.GetOrthographicNearPlane(); farPlane = camera.GetOrthographicFarPlane(); if (ImGui::DragFloat("Orthographic Size", &orthoSize)) camera.SetOrthographicSize(orthoSize); if (ImGui::DragFloat("Near Plane", &nearPlane)) camera.SetOrthographicNearPlane(nearPlane); if (ImGui::DragFloat("Far Plane", &farPlane)) camera.SetOrthographicFarPlane(farPlane); } else // perspective { float verticalFOV, nearPlane, farPlane; verticalFOV = glm::degrees(camera.GetPerspectiveVerticalFOV()); nearPlane = camera.GetPerspectiveNearPlane(); farPlane = camera.GetPerspectiveFarPlane(); if (ImGui::DragFloat("Vertical FOV", &verticalFOV)) camera.SetPerspectiveVerticalFOV(glm::radians(verticalFOV)); if (ImGui::DragFloat("Near Plane", &nearPlane)) camera.SetPerspectiveNearPlane(nearPlane); if (ImGui::DragFloat("Far Plane", &farPlane)) camera.SetPerspectiveFarPlane(farPlane); } ImGui::Separator(); }); } ImGui::End(); } void PropertiesPanel::SetEntityContext(Entity entity) { m_EntityContext = entity; } void PropertiesPanel::DrawVec3Control(const std::string& label, glm::vec3& values, float resetValue /*= 0.0f*/, float columnWidth /*= 100.0f*/) { ImGuiIO& io = ImGui::GetIO(); auto boldFont = io.Fonts->Fonts[0]; ImGui::Columns(2); ImGui::SetColumnWidth(0, columnWidth); ImGui::Text(label.c_str()); ImGui::NextColumn(); ImGui::PushMultiItemsWidths(3, ImGui::CalcItemWidth()); ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2{ 0, 0 }); float lineHeight = GImGui->Font->FontSize + GImGui->Style.FramePadding.y * 2.0f; ImVec2 buttonSize = { lineHeight + 3.0f, lineHeight }; ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.8f, 0.1f, 0.15f, 1.0f)); ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.9f, 0.2f, 0.2f, 1.0f)); ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0.8f, 0.1f, 0.15f, 1.0f)); ImGui::PushFont(boldFont); if (ImGui::Button("X", buttonSize)) values.x = resetValue; ImGui::PopFont(); ImGui::PopStyleColor(3); ImGui::SameLine(); ImGui::DragFloat("##X", &values.x, 0.1f); ImGui::PopItemWidth(); ImGui::SameLine(); ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.2f, 0.7f, 0.2f, 1.0f)); ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.3f, 0.8f, 0.3f, 1.0f)); ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0.2f, 0.7f, 0.2f, 1.0f)); ImGui::PushFont(boldFont); if (ImGui::Button("Y", buttonSize)) values.y = resetValue; ImGui::PopFont(); ImGui::PopStyleColor(3); ImGui::SameLine(); ImGui::DragFloat("##Y", &values.y, 0.1f); ImGui::PopItemWidth(); ImGui::SameLine(); ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.1f, 0.25f, 0.8f, 1.0f)); ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.2f, 0.35f, 0.9f, 1.0f)); ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0.1f, 0.25f, 0.8f, 1.0f)); ImGui::PushFont(boldFont); if (ImGui::Button("Z", buttonSize)) values.z = resetValue; ImGui::PopFont(); ImGui::PopStyleColor(3); ImGui::SameLine(); ImGui::DragFloat("##Z", &values.z, 0.1f); ImGui::PopItemWidth(); ImGui::PopStyleVar(); ImGui::Columns(1); } template void PropertiesPanel::DrawComponent(const std::string& name, Entity entity, UIFunction userInterfaceFunction) { if (!entity.HasComponent()) return; auto& component = entity.GetComponent(); ImVec2 regionAvail = ImGui::GetContentRegionAvail(); ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_DefaultOpen | ImGuiTreeNodeFlags_SpanAvailWidth | ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_AllowItemOverlap | ImGuiTreeNodeFlags_FramePadding; ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, { 4, 4 }); float lineHeight = GImGui->Font->FontSize + GImGui->Style.FramePadding.y * 2.0f; ImGui::Separator(); if (ImGui::TreeNodeEx((void*)typeid(ComponentType).hash_code(), flags, name.c_str())) { ImGui::PopStyleVar(); ImGui::SameLine(regionAvail.x - lineHeight * .5f); if (ImGui::Button("+", { lineHeight, lineHeight })) ImGui::OpenPopup("ComponentSettings"); if (ImGui::BeginPopup("ComponentSettings")) { if (ImGui::Selectable("Remove component")) entity.RemoveComponent(); ImGui::EndPopup(); } userInterfaceFunction(component); ImGui::TreePop(); } else ImGui::PopStyleVar(); } }