165 lines
4.7 KiB
C++
165 lines
4.7 KiB
C++
#include "inspector_panel.hpp"
|
|
|
|
#include <imgui.h>
|
|
|
|
#include <cstdio>
|
|
#include <sophia/components.hpp>
|
|
|
|
void InspectorPanel::onUpdate(const sophia::FrameInfo&) {
|
|
selected = context.selected;
|
|
if (!selected) {
|
|
ImGui::TextDisabled("No entity selected");
|
|
return;
|
|
}
|
|
|
|
drawTag();
|
|
ImGui::Separator();
|
|
drawTransform();
|
|
drawCamera();
|
|
drawSprite();
|
|
drawMesh();
|
|
|
|
ImGui::Separator();
|
|
drawAddComponent();
|
|
}
|
|
|
|
void InspectorPanel::drawTag() {
|
|
auto& tag = selected.getComponent<sophia::TagComponent>();
|
|
|
|
char nameBuf[128];
|
|
std::snprintf(nameBuf, sizeof(nameBuf), "%s", tag.tag.c_str());
|
|
if (ImGui::InputText("Name", nameBuf, sizeof(nameBuf))) {
|
|
tag.tag = nameBuf;
|
|
}
|
|
}
|
|
|
|
void InspectorPanel::drawTransform() {
|
|
if (!selected.hasComponent<sophia::TransformComponent>() ||
|
|
!ImGui::CollapsingHeader("Transform", ImGuiTreeNodeFlags_DefaultOpen)) {
|
|
return;
|
|
}
|
|
|
|
auto& transform = selected.getComponent<sophia::TransformComponent>();
|
|
ImGui::DragFloat3("Position", &transform.position.x, 0.1f);
|
|
|
|
// Euler angles in degrees, recomputed from the quaternion every frame.
|
|
// Near 90 degrees of pitch the angles can jump between equivalent values
|
|
// while dragging.
|
|
// TODO: keep each entity's edited angles, or replace with gizmo rotation.
|
|
glm::vec3 degrees = glm::degrees(glm::eulerAngles(transform.rotation));
|
|
if (ImGui::DragFloat3("Rotation", °rees.x, 1.0f)) {
|
|
transform.rotation = glm::quat{glm::radians(degrees)};
|
|
}
|
|
|
|
ImGui::DragFloat3("Scale", &transform.scale.x, 0.1f);
|
|
}
|
|
|
|
void InspectorPanel::drawCamera() {
|
|
if (!selected.hasComponent<sophia::CameraComponent>() ||
|
|
!ImGui::CollapsingHeader("Camera", ImGuiTreeNodeFlags_DefaultOpen)) {
|
|
return;
|
|
}
|
|
|
|
auto& camera = selected.getComponent<sophia::CameraComponent>();
|
|
int projection = static_cast<int>(camera.projection);
|
|
if (ImGui::Combo("Projection", &projection, "Orthographic\0Perspective\0")) {
|
|
camera.projection =
|
|
static_cast<sophia::CameraComponent::Projection>(projection);
|
|
}
|
|
|
|
if (camera.projection == sophia::CameraComponent::Projection::Orthographic) {
|
|
ImGui::DragFloat("Height", &camera.ortho.height, 0.1f, 0.01f, 10000.f);
|
|
} else {
|
|
float fov = glm::degrees(camera.perspective.fov);
|
|
if (ImGui::DragFloat("FOV", &fov, 0.5f, 1.f, 179.f)) {
|
|
camera.perspective.fov = glm::radians(fov);
|
|
}
|
|
}
|
|
}
|
|
|
|
void InspectorPanel::drawSprite() {
|
|
if (!selected.hasComponent<sophia::SpriteComponent>()) {
|
|
return;
|
|
}
|
|
|
|
bool open = true;
|
|
if (!ImGui::CollapsingHeader("Sprite", &open,
|
|
ImGuiTreeNodeFlags_DefaultOpen)) {
|
|
if (!open) {
|
|
selected.removeComponent<sophia::SpriteComponent>();
|
|
}
|
|
return;
|
|
}
|
|
|
|
auto& sprite = selected.getComponent<sophia::SpriteComponent>();
|
|
|
|
const char* current = "None";
|
|
for (const auto& [name, handle] : textures) {
|
|
if (handle == sprite.texture) {
|
|
current = name.c_str();
|
|
}
|
|
}
|
|
if (ImGui::BeginCombo("Texture", current)) {
|
|
if (ImGui::Selectable("None", !sprite.texture.isValid())) {
|
|
sprite.texture = sophia::INVALID_HANDLE;
|
|
}
|
|
for (const auto& [name, handle] : textures) {
|
|
if (ImGui::Selectable(name.c_str(), handle == sprite.texture)) {
|
|
sprite.texture = handle;
|
|
}
|
|
}
|
|
ImGui::EndCombo();
|
|
}
|
|
|
|
ImGui::ColorEdit4("Color", &sprite.color.x);
|
|
ImGui::DragFloat2("Size", &sprite.size.x, 0.05f);
|
|
ImGui::SliderFloat2("Pivot", &sprite.pivot.x, 0.f, 1.f);
|
|
ImGui::DragFloat4("UV Rect", &sprite.uvRect.x, 0.01f);
|
|
ImGui::DragInt("Sort Order", &sprite.sortOrder);
|
|
|
|
if (!open) {
|
|
selected.removeComponent<sophia::SpriteComponent>();
|
|
}
|
|
}
|
|
|
|
void InspectorPanel::drawMesh() {
|
|
if (!selected.hasComponent<sophia::MeshComponent>()) {
|
|
return;
|
|
}
|
|
|
|
bool open = true;
|
|
if (!ImGui::CollapsingHeader("Mesh", &open, ImGuiTreeNodeFlags_DefaultOpen)) {
|
|
if (!open) {
|
|
selected.removeComponent<sophia::MeshComponent>();
|
|
}
|
|
return;
|
|
}
|
|
|
|
auto& mesh = selected.getComponent<sophia::MeshComponent>();
|
|
// TODO: pick the mesh once assets have names.
|
|
ImGui::Text("Mesh: %u", static_cast<sophia::u32>(mesh.handle.index));
|
|
ImGui::ColorEdit3("Color", &mesh.color.x);
|
|
|
|
if (!open) {
|
|
selected.removeComponent<sophia::MeshComponent>();
|
|
}
|
|
}
|
|
|
|
void InspectorPanel::drawAddComponent() {
|
|
if (ImGui::Button("Add Component")) {
|
|
ImGui::OpenPopup("AddComponent");
|
|
}
|
|
|
|
if (ImGui::BeginPopup("AddComponent")) {
|
|
if (!selected.hasComponent<sophia::SpriteComponent>() &&
|
|
ImGui::MenuItem("Sprite")) {
|
|
selected.addComponent<sophia::SpriteComponent>();
|
|
}
|
|
if (!selected.hasComponent<sophia::CameraComponent>() &&
|
|
ImGui::MenuItem("Camera")) {
|
|
selected.addComponent<sophia::CameraComponent>();
|
|
}
|
|
ImGui::EndPopup();
|
|
}
|
|
}
|