643 lines
25 KiB
C++
Executable File
643 lines
25 KiB
C++
Executable File
#ifndef EDITOR_HPP
|
|
#define EDITOR_HPP
|
|
|
|
#include <open_engine.hpp>
|
|
|
|
#include "open_engine/fastgltf.hpp"
|
|
#include "open_engine/logging.hpp"
|
|
#include "open_engine/ref_scope.hpp"
|
|
#include "open_engine/renderer/model3d.hpp"
|
|
#include "open_engine/renderer/renderer3d.hpp"
|
|
#include "open_engine/scene/components.hpp"
|
|
#include "panels/content_browser.hpp"
|
|
#include "panels/scene_hierarchy.hpp"
|
|
|
|
#include <Jolt/Physics/Collision/Shape/Shape.h>
|
|
#include <Jolt/Math/Real.h>
|
|
#include <Jolt/Math/Vec3.h>
|
|
#include <Jolt/Physics/Body/BodyCreationSettings.h>
|
|
#include <glm/ext/matrix_transform.hpp>
|
|
#include <glm/gtc/type_ptr.hpp>
|
|
#include <glm/matrix.hpp>
|
|
#include <entt/entt.hpp>
|
|
#include <glad/glad.h>
|
|
#include <GLFW/glfw3.h>
|
|
#include <ImGuizmo.h>
|
|
#include <filesystem>
|
|
#include <cstdint>
|
|
#include <imgui.h>
|
|
#include <vector>
|
|
#include <string>
|
|
|
|
namespace OpenEngine {
|
|
|
|
enum class PlayState
|
|
{
|
|
Edit = 0,
|
|
Play = 1
|
|
};
|
|
|
|
class CameraController : public NativeScriptableEntity
|
|
{
|
|
public:
|
|
void OnCreate()
|
|
{
|
|
};
|
|
|
|
void OnUpdate()
|
|
{
|
|
auto delta = Time::DeltaTime();
|
|
|
|
if (HasComponent<TransformComponent>()) {
|
|
auto& position = GetComponent<TransformComponent>().translation;
|
|
|
|
if (Input::IsKeyPressed(KeyCode::Up))
|
|
position.y += 5.0 * delta;
|
|
if (Input::IsKeyPressed(KeyCode::Down))
|
|
position.y -= 5.0 * delta;
|
|
if (Input::IsKeyPressed(KeyCode::Right))
|
|
position.x += 5.0 * delta;
|
|
if (Input::IsKeyPressed(KeyCode::Left))
|
|
position.x -= 5.0 * delta;
|
|
}
|
|
};
|
|
|
|
void OnDestroy()
|
|
{
|
|
};
|
|
};
|
|
|
|
class EditorLayer : public Layer
|
|
{
|
|
public:
|
|
EditorLayer()
|
|
: Layer("editor_layer")
|
|
{
|
|
}
|
|
~EditorLayer() {};
|
|
|
|
void OnAttach() override
|
|
{
|
|
OE_PROFILE_FUNCTION();
|
|
|
|
FramebufferSpecification specs;
|
|
specs.attachments = { FramebufferTextureFormat::RGBA8, FramebufferTextureFormat::RED_INTEGER, FramebufferTextureFormat::Depth };
|
|
specs.width = 1280;
|
|
specs.height = 720;
|
|
|
|
framebuffer = FrameBuffer::Create(specs);
|
|
|
|
scene = CreateRef<Scene>();
|
|
|
|
auto command_line_args = Application::Get().GetCommandLineArgs();
|
|
if (command_line_args.count > 1) {
|
|
auto scene_path = command_line_args[1];
|
|
SceneSerializer serializer(scene);
|
|
serializer.Deserialize(scene_path);
|
|
}
|
|
|
|
editor_camera = EditorCamera(30.0f, 1920.0f/1080.0f, 0.1f, 1000.0f);
|
|
|
|
// TODO: Add license
|
|
icons["play"] = Texture2D::Create("resources/textures/icons/play.png");
|
|
icons["stop"] = Texture2D::Create("resources/textures/icons/stop.png");
|
|
|
|
// =============================================
|
|
Entity cube = scene->CreateEntity("cube");
|
|
|
|
auto& tc = cube.AddComponent<TransformComponent>();
|
|
|
|
Ref<Mesh> mesh = CreateCube(cube);
|
|
|
|
auto& mc = cube.AddComponent<MeshComponent>(mesh);
|
|
mc.primitive_type = PrimitiveType::Cube;
|
|
|
|
// =============================================
|
|
Entity quad = scene->CreateEntity("quad");
|
|
quad.AddComponent<TransformComponent>();
|
|
quad.GetComponents<TransformComponent>().translation = {0, 0, 0};
|
|
|
|
Ref<Mesh> quad_mesh = CreateQuad(quad, true);
|
|
|
|
auto& mc3 = quad.AddComponent<MeshComponent>(quad_mesh);
|
|
mc3.primitive_type = PrimitiveType::Quad;
|
|
|
|
// =============================================
|
|
Entity cube2 = scene->CreateEntity("cube2");
|
|
cube2.AddComponent<TransformComponent>();
|
|
cube2.GetComponents<TransformComponent>().translation = {2, 0, 0};
|
|
|
|
Ref<Mesh> mesh2 = CreateCube(cube2);
|
|
|
|
auto& mc2 = cube2.AddComponent<MeshComponent>(mesh2);
|
|
mc2.primitive_type = PrimitiveType::Cube;
|
|
|
|
// ============================================================
|
|
|
|
Entity cube3 = scene->CreateEntity("glb");
|
|
Entity cube4 = scene->CreateEntity("glb2");
|
|
Entity cube5 = scene->CreateEntity("glb2");
|
|
cube3.AddComponent<TransformComponent>();
|
|
cube4.AddComponent<TransformComponent>();
|
|
cube5.AddComponent<TransformComponent>();
|
|
|
|
Ref<Model3D> model = Model3D::Create("./assets/models/cubes.glb");
|
|
Ref<Model3D> model2 = Model3D::Create("./assets/models/cube_legs.glb");
|
|
Ref<Model3D> monkey = Model3D::Create("./assets/models/monkey.glb");
|
|
|
|
cube3.AddComponent<ModelComponent>(model);
|
|
cube4.AddComponent<ModelComponent>(model2);
|
|
cube5.AddComponent<ModelComponent>(monkey);
|
|
|
|
/*
|
|
auto view = scene->GetRegistry().view<TagComponent>();
|
|
|
|
for (auto& entity : view) {
|
|
auto tag = view->get(entity);
|
|
OE_DEBUG("entity: {}, tag: {}", (uint32_t)entity, tag.tag);
|
|
}
|
|
*/
|
|
|
|
//icons["folder"] = Texture2D::Create("resources/textures/icons/folder.png");
|
|
/*
|
|
for (float i = 0; i < 200; i++) {
|
|
for (float y = 0; y < 200; y++) {
|
|
Entity entity = scene->CreateEntity("entity");
|
|
entities.push_back(entity);
|
|
auto& tc = entity.AddComponents<TransformComponent>();
|
|
tc.translation = { i / 10, y / 10, 0.0f };
|
|
tc.scale = { 0.1f, 0.1f, 1.0f };
|
|
auto& sprite = entity.AddComponents<SpriteRendererComponent>();
|
|
sprite.color = { i / 100.0f, y / 100.0f, 1.0f, 1.0f };
|
|
}
|
|
}
|
|
*/
|
|
|
|
scene_hierarchy.Init(scene);
|
|
}
|
|
|
|
Ref<Texture2D> GetIcon(const char* name)
|
|
{
|
|
if (icons.contains(name))
|
|
return icons[name];
|
|
return nullptr;
|
|
}
|
|
|
|
void OnDetach() override
|
|
{
|
|
}
|
|
|
|
void OnUpdate() override
|
|
{
|
|
FramebufferSpecification spec = framebuffer->GetSpecification();
|
|
|
|
if (viewport_size.x > 0.0f && viewport_size.y > 0.0f &&
|
|
(spec.width != viewport_size.x || spec.height != viewport_size.y)) {
|
|
OE_PROFILE_SCOPE("Setting up Rendering");
|
|
|
|
framebuffer->Resize((uint32_t)viewport_size.x, (uint32_t)viewport_size.y);
|
|
|
|
editor_camera.SetViewportSize(viewport_size.x, viewport_size.y);
|
|
scene->OnViewportResize((uint32_t)viewport_size.x, (uint32_t)viewport_size.y);
|
|
}
|
|
|
|
framebuffer->Bind();
|
|
//Renderer2D::ResetStats();
|
|
RenderCommand::SetClearColor({0.11f, 0.11f, 0.15f, 1.0f});
|
|
RenderCommand::Clear();
|
|
framebuffer->ClearBufferI(1, -1);
|
|
|
|
switch (state) {
|
|
case PlayState::Play: {
|
|
scene->OnUpdateRuntime();
|
|
break;
|
|
}
|
|
case PlayState::Edit: {
|
|
if (viewport_focused)
|
|
editor_camera.OnUpdate();
|
|
scene->OnUpdateEditor(editor_camera);
|
|
break;
|
|
}
|
|
}
|
|
|
|
auto [mx, my] = ImGui::GetMousePos();
|
|
|
|
mx -= viewport_bounds[0].x;
|
|
my -= viewport_bounds[0].y;
|
|
auto viewport_size= viewport_bounds[1] - viewport_bounds[0];
|
|
my = viewport_size.y - my;
|
|
|
|
int mouse_x = (int)mx;
|
|
int mouse_y = (int)my;
|
|
|
|
static bool clicked = false;
|
|
// Mouse Picking
|
|
if (Input::IsMouseButtonPressed(MouseCode::ButtonLeft)
|
|
&& !Application::Get().GetImGuiLayer()->GetBlockEvents()
|
|
&& mouse_x >= 0 && mouse_y >= 0
|
|
&& mouse_x < (int)viewport_size.x
|
|
&& mouse_y < (int)viewport_size.y
|
|
&& !ImGuizmo::IsOver()
|
|
&& !Input::IsKeyPressed(KeyCode::LeftAlt)) {
|
|
if (!clicked) {
|
|
int id = framebuffer->ReadPixel(1, mouse_x, mouse_y);
|
|
|
|
selected_entity = id == -1 ?
|
|
Entity() : Entity((entt::entity)id, scene.get());
|
|
|
|
scene_hierarchy.SetSelectedEntity(selected_entity);
|
|
|
|
}
|
|
clicked = true;
|
|
} else {
|
|
clicked = false;
|
|
selected_entity = scene_hierarchy.GetSelectedEntity();
|
|
}
|
|
|
|
framebuffer->Unbind();
|
|
|
|
scene->UpdateEntities();
|
|
}
|
|
|
|
bool EditorKeyBinds(KeyPressedEvent& event)
|
|
{
|
|
if (event.GetRepeatCount() > 0)
|
|
return false;
|
|
bool control = Input::IsKeyPressed(Key::LeftControl) || Input::IsKeyPressed(Key::RightControl);
|
|
bool shift = Input::IsKeyPressed(Key::LeftShift) || Input::IsKeyPressed(Key::RightShift);
|
|
|
|
switch(event.GetKeyCode()) {
|
|
case KeyCode::S: {
|
|
if (control) {
|
|
std::string file = FileDialogs::SaveFile("useless");
|
|
OE_TRACE("saving to filename: {}", file);
|
|
SaveScene(file);
|
|
}
|
|
break;
|
|
}
|
|
case KeyCode::N: {
|
|
if (control) {
|
|
scene = CreateRef<Scene>();
|
|
scene->OnViewportResize((uint32_t)viewport_size.x, (uint32_t)viewport_size.y);
|
|
scene_hierarchy.Init(scene);
|
|
}
|
|
break;
|
|
}
|
|
case KeyCode::O: {
|
|
if (control) {
|
|
std::string file = FileDialogs::OpenFile("useless");
|
|
OE_DEBUG("loading scene: {}", file);
|
|
OpenScene(file);}
|
|
break;
|
|
}
|
|
case KeyCode::Q: {
|
|
guizmo_operation = -1;
|
|
break;
|
|
}
|
|
case KeyCode::W: {
|
|
guizmo_operation = ImGuizmo::OPERATION::TRANSLATE;
|
|
break;
|
|
}
|
|
case KeyCode::E: {
|
|
guizmo_operation = ImGuizmo::OPERATION::ROTATE;
|
|
break;
|
|
}
|
|
case KeyCode::R: {
|
|
guizmo_operation = ImGuizmo::OPERATION::SCALE;
|
|
break;
|
|
}
|
|
case KeyCode::T: {
|
|
guizmo_operation = ImGuizmo::OPERATION::UNIVERSAL;
|
|
break;
|
|
}
|
|
case KeyCode::Delete: {
|
|
scene->MarkEntityForDeletion(selected_entity);
|
|
scene_hierarchy.ClearSelection();
|
|
selected_entity = {};
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return true;
|
|
};
|
|
|
|
void OnEvent(Event& event) override
|
|
{
|
|
OE_PROFILE_FUNCTION();
|
|
|
|
editor_camera.OnEvent(event);
|
|
|
|
EventDispatcher dispatcher(event);
|
|
dispatcher.Dispatch<KeyPressedEvent>(BIND_EVENT_FN(EditorLayer::EditorKeyBinds));
|
|
};
|
|
|
|
float remap(float value, float minInput, float maxInput, float minOutput, float maxOutput) {
|
|
// 1. Normalize the input to a 0.0 - 1.0 range
|
|
float t = (value - minInput) / (maxInput - minInput);
|
|
|
|
// 2. Use glm::mix to interpolate between the output range
|
|
return glm::mix(minOutput, maxOutput, t);
|
|
};
|
|
|
|
glm::vec3 ScreenToWorld(
|
|
float screenX,
|
|
float screenY,
|
|
float screenZ, // depth value (0.0 = near plane, 1.0 = far plane)
|
|
const glm::mat4& view,
|
|
const glm::mat4& projection,
|
|
int viewportWidth,
|
|
int viewportHeight)
|
|
{
|
|
// 1. Convert screen coordinates to normalized device coordinates (NDC)
|
|
// Screen space: origin at top-left, Y points down
|
|
// NDC space: origin at center, range [-1, 1] for x and y
|
|
|
|
float x = (2.0f * screenX) / viewportWidth - 1.0f;
|
|
float y = 1.0f - (2.0f * screenY) / viewportHeight; // Flip Y
|
|
float z = 2.0f * screenZ - 1.0f; // [0,1] -> [-1,1]
|
|
|
|
glm::vec4 clipCoords(x, y, z, 1.0f);
|
|
|
|
// 2. Transform from clip space to view space
|
|
glm::mat4 invProjection = glm::inverse(projection);
|
|
glm::vec4 viewCoords = invProjection * clipCoords;
|
|
|
|
// 3. Transform from view space to world space
|
|
glm::mat4 invView = glm::inverse(view);
|
|
glm::vec4 worldCoords = invView * viewCoords;
|
|
|
|
// 4. Perspective divide
|
|
if (worldCoords.w != 0.0f) {
|
|
worldCoords /= worldCoords.w;
|
|
}
|
|
|
|
return glm::vec3(worldCoords);
|
|
};
|
|
|
|
void DrawViewport()
|
|
{
|
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2{ 0, 0 });
|
|
ImGui::Begin("Viewport");
|
|
|
|
bool was_focused = viewport_focused;
|
|
viewport_focused = ImGui::IsWindowFocused(ImGuiFocusedFlags_RootWindow);
|
|
viewport_hovered = ImGui::IsWindowHovered(ImGuiHoveredFlags_RootWindow);
|
|
Application::Get().GetImGuiLayer()->SetBlockEvents(ImGui::IsAnyItemActive());
|
|
|
|
if (viewport_focused && !was_focused)
|
|
editor_camera.ResetMousePosition();
|
|
|
|
ImVec2 viewport_panel_size = ImGui::GetContentRegionAvail();
|
|
|
|
viewport_size = { viewport_panel_size.x, viewport_panel_size.y };
|
|
|
|
ImVec2 imgui_cursor_position = ImGui::GetCursorScreenPos();
|
|
|
|
uint32_t texture_id = framebuffer->GetColorAttachmentRendererID();
|
|
ImGui::Image((void*)(uint64_t)texture_id, ImVec2{ viewport_size.x, viewport_size.y }, ImVec2{ 0, 1 }, ImVec2{ 1, 0 });
|
|
|
|
if (ImGui::BeginDragDropTarget()) {
|
|
if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("CONTENT_BROWSER_PAYLOAD")) {
|
|
std::filesystem::path path = (const char*)payload->Data;
|
|
if (path.extension() == ".oes")
|
|
OpenScene(path);
|
|
}
|
|
ImGui::EndDragDropTarget();
|
|
}
|
|
|
|
viewport_bounds[0] = { imgui_cursor_position.x, imgui_cursor_position.y };
|
|
viewport_bounds[1] = { imgui_cursor_position.x + viewport_size.x,
|
|
imgui_cursor_position.y + viewport_size.y };
|
|
|
|
DrawGuizmos();
|
|
|
|
ImGui::End();
|
|
ImGui::PopStyleVar();
|
|
};
|
|
|
|
void DrawStats()
|
|
{
|
|
//auto stats = Renderer2D::GetStats();
|
|
static float time = 0;
|
|
|
|
time += Time::DeltaTime();
|
|
|
|
if (time >= 1) {
|
|
time = 0;
|
|
}
|
|
|
|
ImGui::Begin("Statistics");
|
|
ImGui::SeparatorText("Performance");
|
|
ImGui::Text("FPS: %0.0f", 1 / Time::DeltaTime());
|
|
//ImGui::Text("Renderer2D:");
|
|
//ImGui::Text("\t\tDraw calls: %d", stats.draw_calls);
|
|
//ImGui::Text("\t\tQuad count: %d", stats.quad_count);
|
|
//ImGui::Text("\t\tVertices count: %d", stats.GetTotalVertexCount());
|
|
//ImGui::Text("\t\tIndices count: %d", stats.GetTotalIndexCount());
|
|
//if (selected_entity) {
|
|
// ImGui::SeparatorText("Entities");
|
|
// ImGui::Text("Selected entity:");
|
|
// ImGui::Text("\t\tname: %s", selected_entity.GetComponents<TagComponent>().tag.c_str());
|
|
// ImGui::Text("\t\tid: %d", (uint32_t)selected_entity);
|
|
//}
|
|
ImGui::End();
|
|
};
|
|
|
|
void DrawGuizmos()
|
|
{
|
|
Entity selected_entity = scene_hierarchy.GetSelectedEntity();
|
|
if (selected_entity && selected_entity.HasComponent<TransformComponent>() && guizmo_operation != -1) {
|
|
ImGuizmo::SetOrthographic(false);
|
|
ImGuizmo::SetDrawlist();
|
|
ImGuizmo::Enable(!editor_camera.GetMoving());
|
|
|
|
ImGuizmo::SetRect(viewport_bounds[0].x, viewport_bounds[0].y,
|
|
viewport_bounds[1].x - viewport_bounds[0].x,
|
|
viewport_bounds[1].y - viewport_bounds[0].y);
|
|
|
|
|
|
const glm::mat4& camera_projection = editor_camera.GetProjection();
|
|
glm::mat4 camera_view = editor_camera.GetViewMatrix();
|
|
|
|
auto& transform_comp = selected_entity.GetComponents<TransformComponent>();
|
|
glm::mat4 transform = GetTransformFromComp(transform_comp);
|
|
|
|
bool snap = Input::IsKeyPressed(KeyCode::LeftControl);
|
|
float snap_value = 0.1f;
|
|
if (guizmo_operation == ImGuizmo::OPERATION::ROTATE)
|
|
snap_value = 10.0f;
|
|
|
|
float snap_values[] = { snap_value, snap_value, snap_value };
|
|
|
|
ImGuizmo::Manipulate(glm::value_ptr(camera_view), glm::value_ptr(camera_projection),
|
|
(ImGuizmo::OPERATION)guizmo_operation, ImGuizmo::LOCAL,
|
|
glm::value_ptr(transform), nullptr,
|
|
snap ? snap_values : nullptr);
|
|
|
|
if (ImGuizmo::IsUsing()) {
|
|
glm::vec3 translation, rotation, scale;
|
|
Math::DecomposeTransform(transform, translation, rotation, scale);
|
|
|
|
glm::vec3 delta_rotation = rotation - transform_comp.rotation;
|
|
transform_comp.translation = translation;
|
|
transform_comp.rotation += delta_rotation;
|
|
transform_comp.scale = scale;
|
|
}
|
|
} else
|
|
guizmo_operation = -1;
|
|
};
|
|
|
|
void OpenScene(const std::string& file)
|
|
{
|
|
if (!file.empty()) {
|
|
scene = CreateRef<Scene>();
|
|
scene->OnViewportResize((uint32_t)viewport_size.x, (uint32_t)viewport_size.y);
|
|
scene_hierarchy.Init(scene);
|
|
|
|
SceneSerializer serializer(scene);
|
|
serializer.Deserialize(file);
|
|
}
|
|
}
|
|
|
|
void SaveScene(const std::string& file)
|
|
{
|
|
if (!file.empty()) {
|
|
SceneSerializer serializer(scene);
|
|
serializer.Serialize(file);
|
|
}
|
|
}
|
|
|
|
void DrawPlayBar()
|
|
{
|
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, { 0, 2 });
|
|
ImGui::PushStyleVar(ImGuiStyleVar_ItemInnerSpacing, { 0, 0 });
|
|
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, { 0, 0 });
|
|
ImGui::PushStyleColor(ImGuiCol_Button, { 0, 0, 0, 0 });
|
|
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, { 0.200f, 0.207f, 0.286f, 1.0f });
|
|
ImGui::PushStyleColor(ImGuiCol_ButtonActive, { 0, 0, 0, 0 });
|
|
|
|
ImGui::Begin("##play_state_bar", nullptr, ImGuiWindowFlags_NoDecoration
|
|
| ImGuiWindowFlags_NoScrollWithMouse
|
|
| ImGuiWindowFlags_NoScrollbar
|
|
| ImGuiWindowFlags_NoTitleBar);
|
|
|
|
float size = ImGui::GetContentRegionAvail().y;
|
|
|
|
auto icon = state == PlayState::Play ? icons["stop"] : icons["play"];
|
|
|
|
ImGui::SetCursorPosX((ImGui::GetContentRegionAvail().x * 0.5) - (size * 0.5) );
|
|
if (ImGui::ImageButton("##play_button",
|
|
(ImTextureID)icon->GetID(), { size, size })) {
|
|
switch (state) {
|
|
case PlayState::Play : {
|
|
OnSceneStop();
|
|
break;
|
|
}
|
|
case PlayState::Edit : {
|
|
OnScenePlay();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
ImGui::End();
|
|
|
|
ImGui::PopStyleColor(3);
|
|
ImGui::PopStyleVar(3);
|
|
}
|
|
|
|
void OnImGuiRender() override
|
|
{
|
|
OE_PROFILE_FUNCTION();
|
|
|
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowMinSize, ImVec2(450, 35));
|
|
{
|
|
if (ImGui::BeginMainMenuBar()) {
|
|
if (ImGui::BeginMenu("File")) {
|
|
if (ImGui::MenuItem("Save Scene As", "Ctrl+S")) {
|
|
std::string file = FileDialogs::SaveFile("useless");
|
|
OE_TRACE("saving to filename: {}", file);
|
|
SaveScene(file);
|
|
}
|
|
if (ImGui::MenuItem("Open Scene", "Ctrl+O")) {
|
|
std::string file = FileDialogs::OpenFile("useless");
|
|
OE_DEBUG("loading scene: {}", file);
|
|
OpenScene(file);
|
|
}
|
|
if (ImGui::MenuItem("New Scene", "Ctrl+N")) {
|
|
scene = CreateRef<Scene>();
|
|
scene->OnViewportResize((uint32_t)viewport_size.x, (uint32_t)viewport_size.y);
|
|
scene_hierarchy.Init(scene);
|
|
}
|
|
ImGui::Separator();
|
|
if (ImGui::MenuItem("Exit"))
|
|
Application::Get().Close();
|
|
ImGui::EndMenu();
|
|
}
|
|
ImGui::EndMainMenuBar();
|
|
}
|
|
}
|
|
|
|
ImGui::DockSpaceOverViewport();
|
|
|
|
DrawStats();
|
|
scene_hierarchy.OnImGuiRender();
|
|
browser.OnImGuiRender();
|
|
DrawViewport();
|
|
DrawPlayBar();
|
|
|
|
ImGui::ShowDemoWindow();
|
|
ImGui::PopStyleVar();
|
|
};
|
|
|
|
void OnScenePlay()
|
|
{
|
|
state = PlayState::Play;
|
|
scene->OnRuntimeStart();
|
|
}
|
|
void OnSceneStop()
|
|
{
|
|
state = PlayState::Edit;
|
|
scene->OnRuntimeStop();
|
|
}
|
|
|
|
private:
|
|
ContentBrowserPanel browser;
|
|
std::vector<Time::ProfilingResult> profiling_results;
|
|
|
|
glm::vec2 world_pos_cursor = { 0.0f, 0.0f };
|
|
|
|
glm::vec2 viewport_size = { 0.0f, 0.0f };
|
|
Ref<OpenEngine::FrameBuffer> framebuffer;
|
|
glm::vec2 viewport_bounds[2];
|
|
|
|
bool viewport_focused = false, viewport_hovered = false;
|
|
|
|
SceneHierarchy scene_hierarchy;
|
|
|
|
EditorCamera editor_camera;
|
|
|
|
int guizmo_operation = -1;
|
|
|
|
// TODO: Rename this to GameState
|
|
PlayState state = PlayState::Edit;
|
|
|
|
std::unordered_map<const char*, Ref<Texture2D>> icons;
|
|
Ref<Scene> scene;
|
|
Entity selected_entity;
|
|
|
|
std::vector<Entity> entities;
|
|
};
|
|
}
|
|
|
|
class EditorApp : public OpenEngine::Application
|
|
{
|
|
public:
|
|
EditorApp(OpenEngine::ApplicationCommandLineArgs args);
|
|
~EditorApp();
|
|
};
|
|
|
|
#endif // EDITOR_HPP
|