light/modules/mirror/src/panel/properties.cpp

268 lines
7.5 KiB
C++
Raw Normal View History

2025-07-05 13:28:41 +03:30
#include <engine/scene/components.hpp>
#include <engine/utils/resource_manager.hpp>
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <imgui.h>
#include <imgui_internal.h>
#include <mirror/panel/properties.hpp>
namespace Light {
void PropertiesPanel::on_user_interface_update()
2025-07-05 13:28:41 +03:30
{
ImGui::Begin("Properties");
if (m_entity_context.is_valid())
2025-07-05 13:28:41 +03:30
{
if (m_entity_context.has_component<TagComponent>())
2025-07-05 13:28:41 +03:30
{
auto &tagComponent = m_entity_context.GetComponent<TagComponent>();
2025-07-05 13:28:41 +03:30
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_entity_context.has_component<SpriteRendererComponent>() ?
2025-07-05 13:28:41 +03:30
ImGuiSelectableFlags_Disabled :
NULL
))
m_entity_context.AddComponent<SpriteRendererComponent>(
Light::ResourceManager::get_texture("awesomeface")
2025-07-05 13:28:41 +03:30
);
if (ImGui::Selectable(
"Camera",
false,
m_entity_context.has_component<CameraComponent>() ?
2025-07-05 13:28:41 +03:30
ImGuiSelectableFlags_Disabled :
NULL
))
m_entity_context.AddComponent<CameraComponent>();
2025-07-05 13:28:41 +03:30
ImGui::EndPopup();
}
ImGui::PopItemWidth();
draw_component<TransformComponent>(
2025-07-05 13:28:41 +03:30
"Transform Component",
m_entity_context,
2025-07-05 13:28:41 +03:30
[&](auto &transformComponent) {
draw_vec3_control("Translation", transformComponent.translation);
2025-07-05 13:28:41 +03:30
}
);
draw_component<SpriteRendererComponent>(
2025-07-05 13:28:41 +03:30
"SpriteRenderer Component",
m_entity_context,
2025-07-05 13:28:41 +03:30
[&](auto &spriteRendererComponent) {
ImGui::ColorEdit4("Color", &spriteRendererComponent.tint[0]);
}
);
draw_component<CameraComponent>(
2025-07-05 13:28:41 +03:30
"Camera Component",
m_entity_context,
2025-07-05 13:28:41 +03:30
[&](auto &cameraComponent) {
auto &camera = cameraComponent.camera;
SceneCamera::ProjectionType projectionType = camera.get_projection_type();
2025-07-05 13:28:41 +03:30
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.set_projection_type(projectionType);
2025-07-05 13:28:41 +03:30
}
if (isSelected)
ImGui::SetItemDefaultFocus();
}
ImGui::EndCombo();
}
if (projectionType == SceneCamera::ProjectionType::Orthographic)
{
float orthoSize, nearPlane, farPlane;
orthoSize = camera.get_orthographic_size();
nearPlane = camera.get_orthographic_near_plane();
farPlane = camera.get_orthographic_far_plane();
2025-07-05 13:28:41 +03:30
if (ImGui::DragFloat("Orthographic Size", &orthoSize))
camera.set_orthographic_size(orthoSize);
2025-07-05 13:28:41 +03:30
if (ImGui::DragFloat("Near Plane", &nearPlane))
camera.set_orthographic_near_plane(nearPlane);
2025-07-05 13:28:41 +03:30
if (ImGui::DragFloat("Far Plane", &farPlane))
camera.set_orthographic_far_plane(farPlane);
2025-07-05 13:28:41 +03:30
}
else // perspective
{
float verticalFOV, nearPlane, farPlane;
verticalFOV = glm::degrees(camera.get_perspective_vertical_fov());
nearPlane = camera.get_perspective_near_plane();
farPlane = camera.get_perspective_far_plane();
2025-07-05 13:28:41 +03:30
if (ImGui::DragFloat("Vertical FOV", &verticalFOV))
camera.set_perspective_vertical_fov(glm::radians(verticalFOV));
2025-07-05 13:28:41 +03:30
if (ImGui::DragFloat("Near Plane", &nearPlane))
camera.set_perspective_near_plane(nearPlane);
2025-07-05 13:28:41 +03:30
if (ImGui::DragFloat("Far Plane", &farPlane))
camera.set_perspective_far_plane(farPlane);
2025-07-05 13:28:41 +03:30
}
ImGui::Separator();
}
);
}
ImGui::End();
}
void PropertiesPanel::set_entity_context(Entity entity)
2025-07-05 13:28:41 +03:30
{
m_entity_context = entity;
2025-07-05 13:28:41 +03:30
}
void PropertiesPanel::draw_vec3_control(
2025-07-05 13:28:41 +03:30
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<typename ComponentType, typename UIFunction>
void PropertiesPanel::draw_component(
2025-07-05 13:28:41 +03:30
const std::string &name,
Entity entity,
UIFunction userInterfaceFunction
)
{
if (!entity.has_component<ComponentType>())
2025-07-05 13:28:41 +03:30
return;
auto &component = entity.GetComponent<ComponentType>();
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.remove_component<ComponentType>();
2025-07-05 13:28:41 +03:30
ImGui::EndPopup();
}
userInterfaceFunction(component);
ImGui::TreePop();
}
else
ImGui::PopStyleVar();
}
} // namespace Light