327 lines
13 KiB
C++
327 lines
13 KiB
C++
#include "imgui.h"
|
|
#include "open_engine/renderer/renderer3d.hpp"
|
|
#include "open_engine/scene/components.hpp"
|
|
#include <Jolt/Physics/Body/MotionType.h>
|
|
#include <cstdint>
|
|
#include <editor_component.hpp>
|
|
#include <entt/entity/fwd.hpp>
|
|
#include <glm/gtc/type_ptr.hpp>
|
|
#include <open_engine.hpp>
|
|
|
|
namespace OpenEngine {
|
|
|
|
void DrawVec3Control(const char* label, glm::vec3& values,
|
|
float reset_value, float column_width,
|
|
const std::array<const char*, 3> labels)
|
|
{
|
|
ImGuiIO& io = ImGui::GetIO();
|
|
auto bold_font = io.Fonts->Fonts[0];
|
|
|
|
ImGui::PushID(label);
|
|
ImVec2 item_spacing = { 15.0f, 0.0f };
|
|
ImGui::Columns(2);
|
|
ImGui::SetColumnWidth(0, column_width);
|
|
ImGui::Text("%s", label);
|
|
if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left) && ImGui::IsItemHovered())
|
|
values = glm::vec3(reset_value);
|
|
ImGui::NextColumn();
|
|
|
|
ImGui::PushMultiItemsWidths(3, ImGui::CalcItemWidth());
|
|
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2{ 0, 0 });
|
|
|
|
float line_height = ImGui::GetFontSize() + ImGui::GetStyle().FramePadding.y * 2.0f;
|
|
ImVec2 button_size = { line_height + 3.0f, line_height };
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4{ 0.953f, 0.545f, 0.659f, 1.0f });
|
|
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4{ 1.0f, 0.8f, 0.9f, 1.0f });
|
|
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4{ 0.953f, 0.545f, 0.659f, 1.0f });
|
|
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4{ 0.0f, 0.0f, 0.0f, 1.0f });
|
|
ImGui::PushFont(bold_font);
|
|
if (ImGui::Button(labels[0], button_size))
|
|
values.x = reset_value;
|
|
ImGui::PopFont();
|
|
ImGui::PopStyleColor(4);
|
|
|
|
ImGui::SameLine();
|
|
ImGui::DragFloat("##X", &values.x, 0.1f, 0.0f, 0.0f, "%.2f");
|
|
ImGui::PopItemWidth();
|
|
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, item_spacing);
|
|
ImGui::SameLine();
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4{ 0.650f, 0.890f, 0.631f, 1.0f });
|
|
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4{ 0.9f, 1.0f, 0.9f, 1.0f });
|
|
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4{ 0.650f, 0.890f, 0.631f, 1.0f });
|
|
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4{ 0.0f, 0.0f, 0.0f, 1.0f });
|
|
ImGui::PushFont(bold_font);
|
|
if (ImGui::Button(labels[1], button_size))
|
|
values.y = reset_value;
|
|
ImGui::PopFont();
|
|
ImGui::PopStyleColor(4);
|
|
ImGui::PopStyleVar();
|
|
|
|
ImGui::SameLine();
|
|
ImGui::DragFloat("##Y", &values.y, 0.1f, 0.0f, 0.0f, "%.2f");
|
|
ImGui::PopItemWidth();
|
|
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, item_spacing);
|
|
ImGui::SameLine();
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4{ 0.533f, 0.698f, 0.976f, 1.0f });
|
|
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4{ 0.7f, 0.9f, 1.0f, 1.0f });
|
|
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4{ 0.533f, 0.698f, 0.976f, 1.0f });
|
|
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4{ 0.0f, 0.0f, 0.0f, 1.0f });
|
|
ImGui::PushFont(bold_font);
|
|
if (ImGui::Button(labels[2], button_size))
|
|
values.z = reset_value;
|
|
ImGui::PopFont();
|
|
ImGui::PopStyleColor(4);
|
|
ImGui::PopStyleVar(1);
|
|
|
|
ImGui::SameLine();
|
|
ImGui::DragFloat("##Z", &values.z, 0.1f, 0.0f, 0.0f, "%.2f");
|
|
ImGui::PopItemWidth();
|
|
|
|
ImGui::PopStyleVar();
|
|
|
|
ImGui::Columns(1);
|
|
ImGui::PopID();
|
|
}
|
|
|
|
void TagOnImGuiRender(entt::registry& registry, entt::entity entity)
|
|
{
|
|
char buffer[256];
|
|
|
|
auto& tag = registry.get<TagComponent>(entity).tag;
|
|
std::memset(buffer, 0, sizeof(buffer));
|
|
std::strncpy(buffer, tag.c_str(), sizeof(buffer));
|
|
|
|
if (ImGui::InputText("##tagEditor", buffer, sizeof(buffer), ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_AutoSelectAll)
|
|
|| (!ImGui::IsItemActive() && ImGui::IsMouseClicked(0)))
|
|
tag = buffer;
|
|
ImGui::Spacing();
|
|
};
|
|
|
|
void TransformOnImGuiRender(entt::registry& registry, entt::entity entity)
|
|
{
|
|
auto& transform = registry.get<TransformComponent>(entity);
|
|
DrawVec3Control("Position", transform.translation);
|
|
glm::vec3 rotation_comp = glm::degrees(transform.rotation);
|
|
DrawVec3Control("Rotation", rotation_comp);
|
|
transform.rotation = glm::radians(rotation_comp);
|
|
DrawVec3Control("Scale", transform.scale);
|
|
ImGui::Spacing();
|
|
};
|
|
|
|
void SpriteOnImGuiRender(entt::registry& registry, entt::entity entity)
|
|
{
|
|
auto& sprite = registry.get<SpriteRendererComponent>(entity);
|
|
ImGui::ColorEdit4("color", glm::value_ptr(sprite.color));
|
|
ImGui::Button("Texture", { 100, 0 });
|
|
|
|
if (ImGui::BeginDragDropTarget()) {
|
|
if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("CONTENT_BROWSER_PAYLOAD"))
|
|
sprite.texture = Texture2D::Create(((const char*)payload->Data));
|
|
|
|
ImGui::EndDragDropTarget();
|
|
}
|
|
|
|
ImGui::DragFloat("Tiling factor", &sprite.tiling_factor);
|
|
};
|
|
|
|
void CameraOnImGuiRender(entt::registry& registry, entt::entity entity)
|
|
{
|
|
auto& camera_comp = registry.get<CameraComponent>(entity);
|
|
auto& camera = camera_comp.camera;
|
|
ImGui::Checkbox("Is primary", &camera_comp.primary);
|
|
const char* projection_type_strings[] = {"Perspective", "Orthographic"};
|
|
const char* current_projection_type = projection_type_strings[(int)camera.GetProjectionType()];
|
|
|
|
if (ImGui::BeginCombo("Projection", current_projection_type)) {
|
|
for (int i = 0; i < 2; i++) {
|
|
bool is_selected = current_projection_type == projection_type_strings[i];
|
|
if (ImGui::Selectable(projection_type_strings[i], is_selected)) {
|
|
current_projection_type = projection_type_strings[i];
|
|
camera.SetProjectionType((SceneCamera::ProjectionType)i);
|
|
}
|
|
|
|
if (is_selected)
|
|
ImGui::SetItemDefaultFocus();
|
|
}
|
|
ImGui::EndCombo();
|
|
}
|
|
|
|
if (camera.GetProjectionType() == SceneCamera::ProjectionType::Perspective) {
|
|
float fov = camera.GetVerticalFov();
|
|
if (ImGui::DragFloat("Fov", &fov, 0.1f))
|
|
camera.SetVerticalFov(fov);
|
|
|
|
float near_clip = camera.GetPerspectiveNearClip();
|
|
if (ImGui::DragFloat("Near clip", &near_clip, 0.1f))
|
|
camera.SetPerspectiveNearClip(near_clip);
|
|
|
|
float far_clip = camera.GetPerspectiveFarClip();
|
|
if (ImGui::DragFloat("Far clip", &far_clip, 0.1f))
|
|
camera.SetPerspectiveFarClip(far_clip);
|
|
}
|
|
else if (camera.GetProjectionType() == SceneCamera::ProjectionType::Orthographic) {
|
|
ImGui::Checkbox("Has fixed aspect ratio", &camera_comp.fixed_aspect_ratio);
|
|
float ortho_size = camera.GetOrthographicSize();
|
|
if (ImGui::DragFloat("Orthographic size", &ortho_size, 0.1f))
|
|
camera.SetOrthographicSize(ortho_size);
|
|
|
|
float near_clip = camera.GetOrthographicNearClip();
|
|
if (ImGui::DragFloat("Near clip", &near_clip, 0.1f))
|
|
camera.SetOrthographicNearClip(near_clip);
|
|
|
|
float far_clip = camera.GetOrthographicFarClip();
|
|
if (ImGui::DragFloat("Far clip", &far_clip, 0.1f))
|
|
camera.SetOrthographicFarClip(far_clip);
|
|
}
|
|
|
|
};
|
|
|
|
void MeshOnImGuiRender(entt::registry& registry, entt::entity entity)
|
|
{
|
|
auto& mesh_component = registry.get<MeshComponent>(entity);
|
|
|
|
const char* items[] = { "None", "Quad", "Cube" };
|
|
|
|
int item_selected_idx = (int)mesh_component.primitive_type;
|
|
if (ImGui::BeginCombo("Mesh", items[item_selected_idx])) {
|
|
for (int n = 0; n < 3; n++) {
|
|
const bool is_selected = (item_selected_idx == n);
|
|
if (ImGui::Selectable(items[n], is_selected))
|
|
item_selected_idx = n;
|
|
|
|
// Set the initial focus when opening the combo (scrolling + keyboard navigation focus)
|
|
if (is_selected)
|
|
ImGui::SetItemDefaultFocus();
|
|
}
|
|
ImGui::EndCombo();
|
|
}
|
|
|
|
if ((int)mesh_component.primitive_type == (item_selected_idx))
|
|
return;
|
|
|
|
mesh_component.primitive_type = (PrimitiveType)(item_selected_idx);
|
|
switch (mesh_component.primitive_type) {
|
|
case OpenEngine::PrimitiveType::Quad:
|
|
{
|
|
mesh_component.mesh = CreateQuad((uint32_t)entity);
|
|
break;
|
|
}
|
|
case OpenEngine::PrimitiveType::Cube:
|
|
{
|
|
mesh_component.mesh = CreateCube((uint32_t)entity);
|
|
break;
|
|
}
|
|
default:
|
|
mesh_component.mesh = nullptr;
|
|
break;
|
|
}
|
|
}
|
|
|
|
void MaterialOnImGuiRender(entt::registry& registry, entt::entity entity)
|
|
{
|
|
auto& material = registry.get<MaterialComponent>(entity).material;
|
|
|
|
ImGui::SliderFloat4("Albedo", glm::value_ptr(material.albedo), 0, 1);
|
|
ImGui::SliderFloat("Roughness", &material.roughness, 0, 1);
|
|
ImGui::SliderFloat("Metallic", &material.metallic, 0, 1);
|
|
ImGui::SliderFloat("Ambient strength", &material.ambient_strength, 0, 1);
|
|
ImGui::SliderFloat("Specular strength", &material.specular_strength, 0, 10);
|
|
}
|
|
|
|
void BodyOnImGuiRender(entt::registry ®istry, entt::entity entity)
|
|
{
|
|
auto& body_comp = registry.get<PhysicsBodyComponent>(entity);
|
|
|
|
const char* items[] = { "Static", "Kinematic", "Dynamic" };
|
|
int item_selected_idx = body_comp.type;
|
|
|
|
if (ImGui::BeginCombo("Body type", items[item_selected_idx])) {
|
|
for (int n = 0; n < 3; n++)
|
|
{
|
|
const bool is_selected = (item_selected_idx == n);
|
|
if (ImGui::Selectable(items[n], is_selected))
|
|
item_selected_idx = n;
|
|
|
|
// Set the initial focus when opening the combo (scrolling + keyboard navigation focus)
|
|
if (is_selected)
|
|
ImGui::SetItemDefaultFocus();
|
|
}
|
|
ImGui::EndCombo();
|
|
}
|
|
|
|
body_comp.type = item_selected_idx;
|
|
|
|
ImGui::SliderFloat("Linear damping", &body_comp.linear_damping, 0, 1);
|
|
ImGui::SliderFloat("Angular damping", &body_comp.angular_damping, 0, 1);
|
|
ImGui::SliderFloat("Gravity factor", &body_comp.gravity_factor, 0, 1);
|
|
ImGui::SliderFloat("Bounciness", &body_comp.restitution, 0, 1);
|
|
ImGui::SliderFloat("Friction", &body_comp.friction, 0, 1);
|
|
}
|
|
|
|
void SphereShapeOnImGuiRender(entt::registry ®istry, entt::entity entity)
|
|
{
|
|
auto& sphere_comp = registry.get<SphereShapeComponent>(entity);
|
|
|
|
ImGui::DragFloat("Radius",
|
|
&sphere_comp.radius,
|
|
0.1f,
|
|
0.11f, FLT_MAX,
|
|
"%.2f",
|
|
ImGuiSliderFlags_AlwaysClamp);
|
|
}
|
|
|
|
void BoxShapeOnImGuiRender(entt::registry ®istry, entt::entity entity)
|
|
{
|
|
auto& box_comp = registry.get<BoxShapeComponent>(entity);
|
|
|
|
ImGui::DragFloat3("Size",
|
|
glm::value_ptr(box_comp.size),
|
|
0.1f,
|
|
0.11f, FLT_MAX,
|
|
"%.2f",
|
|
ImGuiSliderFlags_AlwaysClamp);
|
|
}
|
|
|
|
void PlaneShapeOnImGuiRender(entt::registry& registry, entt::entity entity)
|
|
{
|
|
auto& planed_comp = registry.get<PlaneShapeComponent>(entity);
|
|
|
|
ImGui::DragFloat("Size",
|
|
&planed_comp.extent,
|
|
0.1f,
|
|
0.01f, FLT_MAX,
|
|
"%.2f",
|
|
ImGuiSliderFlags_AlwaysClamp);
|
|
}
|
|
|
|
void ModelOnImGuiRender(entt::registry& registry, entt::entity entity)
|
|
{
|
|
auto& model_comp = registry.get<ModelComponent>(entity);
|
|
|
|
bool opened = ImGui::TreeNodeEx(
|
|
(void*)(intptr_t)entity,
|
|
ImGuiTreeNodeFlags_None,
|
|
"Meshes");
|
|
|
|
if (opened) {
|
|
unsigned int i = 0;
|
|
for (auto& mesh : model_comp.model->GetMeshes())
|
|
ImGui::Text("Mesh: %i", i++);
|
|
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_ChildBg, {1, 1, 1, 1});
|
|
if (ImGui::BeginChild("Material list")) {
|
|
for (auto& mesh : model_comp.model->GetMeshes())
|
|
ImGui::Text("Material: %s", mesh.material.name.c_str());
|
|
ImGui::EndChild();
|
|
}
|
|
ImGui::PopStyleColor();
|
|
|
|
ImGui::TreePop();
|
|
}
|
|
}
|
|
}
|