#include #include #include #include #include #include #include namespace lt { void PropertiesPanel::on_user_interface_update() { ImGui::Begin("Properties"); if (m_entity_context.is_valid()) { if (m_entity_context.has_component()) { auto &tagComponent = m_entity_context.get_component(); auto buffer = std::array {}; memset(buffer.data(), 0, buffer.size()); strncpy(buffer.data(), tagComponent.tag.c_str(), buffer.size()); if (ImGui::InputText("##Tag", buffer.data(), buffer.size())) { tagComponent.tag = buffer.data(); } } ImGui::SameLine(); ImGui::PushItemWidth(-1); if (ImGui::Button("Add component")) { ImGui::OpenPopup("Components"); } if (ImGui::BeginPopup("Components")) { if (ImGui::Selectable( "SpriteRenderer", false, m_entity_context.has_component() ? ImGuiSelectableFlags_Disabled : ImGuiSelectableFlags {} )) { m_entity_context.add_component( lt::AssetManager::get_texture("awesomeface") ); } if (ImGui::Selectable( "Camera", false, m_entity_context.has_component() ? ImGuiSelectableFlags_Disabled : ImGuiSelectableFlags {} )) { m_entity_context.add_component(); } ImGui::EndPopup(); } ImGui::PopItemWidth(); draw_component( "Transform Component", m_entity_context, [&](auto &transformComponent) { draw_vec3_control("Translation", transformComponent.translation); } ); draw_component( "SpriteRenderer Component", m_entity_context, [&](auto &spriteRendererComponent) { ImGui::ColorEdit4("Color", &spriteRendererComponent.tint[0]); } ); draw_component( "Camera Component", m_entity_context, [&](auto &cameraComponent) { auto &camera = cameraComponent.camera; auto projection_type = camera.get_projection_type(); auto projection_types_str = std::array { "Orthographic", "Perspective", }; if (ImGui::BeginCombo("ProjectionType", projection_types_str[(int)projection_type])) { for (auto idx = 0; idx < 2; idx++) { const auto is_selected = static_cast(projection_type) == idx; if (ImGui::Selectable(projection_types_str[idx], is_selected)) { projection_type = static_cast(idx); camera.set_projection_type(projection_type); } if (is_selected) { ImGui::SetItemDefaultFocus(); } } ImGui::EndCombo(); } if (projection_type == SceneCamera::ProjectionType::Orthographic) { auto ortho_size = float {}; auto near_plane = float {}; auto far_plane = float {}; ortho_size = camera.get_orthographic_size(); near_plane = camera.get_orthographic_near_plane(); far_plane = camera.get_orthographic_far_plane(); if (ImGui::DragFloat("Orthographic Size", &ortho_size)) { camera.set_orthographic_size(ortho_size); } if (ImGui::DragFloat("Near Plane", &near_plane)) { camera.set_orthographic_near_plane(near_plane); } if (ImGui::DragFloat("Far Plane", &far_plane)) { camera.set_orthographic_far_plane(far_plane); } } else // perspective { auto vertical_fov = float {}; auto near_plane = float {}; auto far_plane = float {}; vertical_fov = math::degrees(camera.get_perspective_vertical_fov()); near_plane = camera.get_perspective_near_plane(); far_plane = camera.get_perspective_far_plane(); if (ImGui::DragFloat("Vertical FOV", &vertical_fov)) { camera.set_perspective_vertical_fov(math::radians(vertical_fov)); } if (ImGui::DragFloat("Near Plane", &near_plane)) { camera.set_perspective_near_plane(near_plane); } if (ImGui::DragFloat("Far Plane", &far_plane)) { camera.set_perspective_far_plane(far_plane); } } ImGui::Separator(); } ); } ImGui::End(); } void PropertiesPanel::set_entity_context(const Entity &entity) { m_entity_context = entity; } void PropertiesPanel::draw_vec3_control( const std::string &label, math::vec3 &values, float reset_value, float column_width ) { auto &io = ImGui::GetIO(); auto *bold_font = io.Fonts->Fonts[0]; ImGui::Columns(2); ImGui::SetColumnWidth(0, column_width); ImGui::TextUnformatted(label.c_str()); ImGui::NextColumn(); ImGui::PushMultiItemsWidths(3, ImGui::CalcItemWidth()); ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2 { 0, 0 }); auto line_height = GImGui->Font->LegacySize + GImGui->Style.FramePadding.y * 2.0f; auto button_size = ImVec2 { line_height + 3.0f, line_height }; 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(bold_font); if (ImGui::Button("X", button_size)) { values.x = reset_value; } 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(bold_font); if (ImGui::Button("Y", button_size)) { values.y = reset_value; } 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(bold_font); if (ImGui::Button("Z", button_size)) { values.z = reset_value; } ImGui::PopFont(); ImGui::PopStyleColor(3); ImGui::SameLine(); ImGui::DragFloat("##Z", &values.z, 0.1f); ImGui::PopItemWidth(); ImGui::PopStyleVar(); ImGui::Columns(1); } template void PropertiesPanel::draw_component( const std::string &name, Entity entity, UIFunction user_interface_function ) { if (!entity.has_component()) { return; } auto &component = entity.get_component(); auto available_region = ImGui::GetContentRegionAvail(); // NOLINTNEXTLINE auto flags = ImGuiTreeNodeFlags_DefaultOpen | ImGuiTreeNodeFlags_SpanAvailWidth | ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_AllowItemOverlap | ImGuiTreeNodeFlags_FramePadding; ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, { 4, 4 }); auto lineHeight = GImGui->Font->LegacySize + GImGui->Style.FramePadding.y * 2.0f; ImGui::Separator(); // NOLINTNEXTLINE if (ImGui::TreeNodeEx((void *)typeid(ComponentType).hash_code(), flags, name.c_str())) { ImGui::PopStyleVar(); ImGui::SameLine(available_region.x - lineHeight * .5f); if (ImGui::Button("+", { lineHeight, lineHeight })) { ImGui::OpenPopup("ComponentSettings"); } if (ImGui::BeginPopup("ComponentSettings")) { if (ImGui::Selectable("Remove component")) { entity.remove_component(); } ImGui::EndPopup(); } user_interface_function(component); ImGui::TreePop(); } else { ImGui::PopStyleVar(); } } } // namespace lt