简单添加entt实体组件系统库
This commit is contained in:
@ -1,34 +1,24 @@
|
||||
set(PROJECT_NAME "Sandbox")
|
||||
set(PROJECT_NAME "HazelApp")
|
||||
|
||||
# SandBox
|
||||
project(${PROJECT_NAME})
|
||||
file(GLOB_RECURSE SOURCES
|
||||
src/SandboxApp.cpp
|
||||
src/SandBox2D/*.cpp)
|
||||
src/Sandbox2D/**.cpp)
|
||||
|
||||
add_executable(${PROJECT_NAME} ${SOURCES})
|
||||
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE Hazel)
|
||||
|
||||
|
||||
# demo App
|
||||
set(DEMO_PROJECT "${PROJECT_NAME}-Demo")
|
||||
file(GLOB_RECURSE DEMO_SOURCES
|
||||
|
||||
# Hazel-Editor
|
||||
set(PROJECT_NAME "${PROJECT_NAME}-Editor")
|
||||
project(${PROJECT_NAME})
|
||||
file(GLOB_RECURSE SOURCES
|
||||
src/SandboxApp.cpp
|
||||
src/DemoBox/*.cpp)
|
||||
src/Editor/**.cpp)
|
||||
|
||||
add_executable(${DEMO_PROJECT} ${DEMO_SOURCES})
|
||||
add_executable(${PROJECT_NAME} ${SOURCES})
|
||||
|
||||
target_link_libraries(${DEMO_PROJECT} PRIVATE Hazel)
|
||||
|
||||
|
||||
# Example
|
||||
|
||||
set(EXAMPLE_PROJECT "${PROJECT_NAME}-Example")
|
||||
file(GLOB_RECURSE EXAMPLE_SOURCES
|
||||
src/SandboxApp.cpp
|
||||
src/Example/*.cpp)
|
||||
|
||||
add_executable(${EXAMPLE_PROJECT} ${EXAMPLE_SOURCES})
|
||||
|
||||
target_link_libraries(${EXAMPLE_PROJECT} PRIVATE Hazel)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE Hazel)
|
||||
|
||||
258
Sandbox/src/Editor/EditorLayer.cpp
Normal file
258
Sandbox/src/Editor/EditorLayer.cpp
Normal file
@ -0,0 +1,258 @@
|
||||
//
|
||||
// Created by sfd on 25-5-25.
|
||||
//
|
||||
|
||||
#include "EditorLayer.h"
|
||||
|
||||
#include <imgui.h>
|
||||
#include <iostream>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
#include "glm/ext/matrix_clip_space.hpp"
|
||||
|
||||
namespace Hazel
|
||||
{
|
||||
EditorLayer::EditorLayer()
|
||||
: Layer("HazelEditor"), m_CameraController((float)Application::Get().GetWindow().GetWidth() / (float)Application::Get().GetWindow().GetHeight())
|
||||
{
|
||||
}
|
||||
|
||||
void EditorLayer::OnAttach()
|
||||
{
|
||||
|
||||
FrameBufferSpecification spec;
|
||||
spec.Width = Application::Get().GetWindow().GetWidth();
|
||||
spec.Height = Application::Get().GetWindow().GetHeight();
|
||||
m_FrameBuffer = FrameBuffer::Create(spec);
|
||||
|
||||
m_ViewPortSize = { spec.Width, spec.Height };
|
||||
|
||||
m_LogoTexture = Texture2D::Create("assets/textures/iceLogo.png");
|
||||
m_CheckerBoardTexture = Texture2D::Create("assets/textures/Checkerboard.png");
|
||||
|
||||
m_ActiveScene = CreateRef<Scene>();
|
||||
|
||||
// Entity
|
||||
m_SquareEntity = m_ActiveScene->CreateEntity("Square A");
|
||||
m_SquareEntity.AddComponent<SpriteRendererComponent>(glm::vec4{0.2f, 0.3f, 0.8f, 1.0f});
|
||||
|
||||
auto redSquare = m_ActiveScene->CreateEntity("Square B");
|
||||
redSquare.AddComponent<SpriteRendererComponent>(glm::vec4{1.0f, 0.0f, 0.0f, 1.0f});
|
||||
|
||||
|
||||
|
||||
|
||||
m_CameraEntity = m_ActiveScene->CreateEntity("Camera A");
|
||||
m_CameraEntity.AddComponent<CameraComponent>();
|
||||
m_PrimaryCamera = true;
|
||||
|
||||
|
||||
m_SecondCamera = m_ActiveScene->CreateEntity("Camera B");
|
||||
m_SecondCamera.AddComponent<CameraComponent>();
|
||||
m_SecondCamera.GetComponent<CameraComponent>().Primary = false;
|
||||
|
||||
|
||||
class CameraController : public ScriptableEntity
|
||||
{
|
||||
public:
|
||||
void OnUpdate(const TimeStep ts)
|
||||
{
|
||||
auto& transform = GetComponent<TransformComponent>().Transform;
|
||||
static const auto state = SDL_GetKeyboardState(nullptr);
|
||||
if (state[SDL_SCANCODE_A])
|
||||
transform[3][0] -= ts * speed;
|
||||
if (state[SDL_SCANCODE_D])
|
||||
transform[3][0] += ts * speed;
|
||||
if (state[SDL_SCANCODE_W])
|
||||
transform[3][1] += ts * speed;
|
||||
if (state[SDL_SCANCODE_S])
|
||||
transform[3][1] -= ts * speed;
|
||||
}
|
||||
private:
|
||||
float speed = 2.0f;
|
||||
};
|
||||
|
||||
m_CameraEntity.AddComponent<NativeScriptComponent>().Bind<CameraController>();
|
||||
m_SecondCamera.AddComponent<NativeScriptComponent>().Bind<CameraController>();
|
||||
|
||||
|
||||
m_SceneHierachyPanel.SetContext(m_ActiveScene);
|
||||
}
|
||||
|
||||
void EditorLayer::OnDetech()
|
||||
{
|
||||
}
|
||||
|
||||
void EditorLayer::OnUpdate(TimeStep& ts)
|
||||
{
|
||||
// reset Renderer Draw Stats
|
||||
Renderer2D::ResetStats();
|
||||
|
||||
if (const auto& spec = m_FrameBuffer->GetSpecification();
|
||||
spec.Width != m_ViewPortSize.x || spec.Height != m_ViewPortSize.y)
|
||||
{
|
||||
m_FrameBuffer->Resize((uint32_t)m_ViewPortSize.x, (uint32_t)m_ViewPortSize.y);
|
||||
m_CameraController.OnResize(m_ViewPortSize.x, m_ViewPortSize.y);
|
||||
|
||||
m_ActiveScene->OnViewportResize(m_ViewPortSize.x, m_ViewPortSize.y);
|
||||
|
||||
}
|
||||
|
||||
// update camera
|
||||
if (m_ViewportFocused && m_ViewportHovered)
|
||||
{
|
||||
m_CameraController.OnUpdate(ts);
|
||||
}
|
||||
|
||||
// update Renderer
|
||||
m_FrameBuffer->Bind();
|
||||
RendererCommand::SetClearColor(m_BackgroundColor);
|
||||
RendererCommand::Clear();
|
||||
|
||||
|
||||
// Renderer2D::BeginScene(m_cameraController.GetCamera());
|
||||
|
||||
// update Scene
|
||||
m_ActiveScene->OnUpdate(ts);
|
||||
|
||||
// Renderer2D::DrawQuad({0, 0.5f}, {1.0f, 1.0f}, {0.2f, 0.3f, 0.8f, 1.0f});
|
||||
// Renderer2D::DrawQuad({0, -0.5f}, {1.0f, 1.0f}, {0.8f, 0.2f, 0.2f, 1.0f});
|
||||
// Renderer2D::DrawQuad({-1, 0}, {1, 1}, m_LogoTexture);
|
||||
// Renderer2D::DrawQuad({1, 0}, {1, 1}, m_CheckerBoardTexture);
|
||||
|
||||
// Renderer2D::EndScene();
|
||||
m_FrameBuffer->UnBind();
|
||||
}
|
||||
|
||||
void EditorLayer::OnImGuiRender()
|
||||
{
|
||||
static bool showDockspace = true;
|
||||
if (showDockspace)
|
||||
{
|
||||
static bool dockspaceOpen = true;
|
||||
static bool opt_fullscreen = true;
|
||||
static bool opt_padding = false;
|
||||
static ImGuiDockNodeFlags dockspace_flags = ImGuiDockNodeFlags_None;
|
||||
|
||||
// We are using the ImGuiWindowFlags_NoDocking flag to make the parent window not dockable into,
|
||||
// because it would be confusing to have two docking targets within each others.
|
||||
ImGuiWindowFlags window_flags = ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoDocking;
|
||||
if (opt_fullscreen)
|
||||
{
|
||||
const ImGuiViewport* viewport = ImGui::GetMainViewport();
|
||||
ImGui::SetNextWindowPos(viewport->WorkPos);
|
||||
ImGui::SetNextWindowSize(viewport->WorkSize);
|
||||
ImGui::SetNextWindowViewport(viewport->ID);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
|
||||
window_flags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize |
|
||||
ImGuiWindowFlags_NoMove;
|
||||
window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus;
|
||||
}
|
||||
else
|
||||
{
|
||||
dockspace_flags &= ~ImGuiDockNodeFlags_PassthruCentralNode;
|
||||
}
|
||||
|
||||
// When using ImGuiDockNodeFlags_PassthruCentralNode, DockSpace() will render our background
|
||||
// and handle the pass-thru hole, so we ask Begin() to not render a background.
|
||||
if (dockspace_flags & ImGuiDockNodeFlags_PassthruCentralNode)
|
||||
window_flags |= ImGuiWindowFlags_NoBackground;
|
||||
|
||||
// Important: note that we proceed even if Begin() returns false (aka window is collapsed).
|
||||
// This is because we want to keep our DockSpace() active. If a DockSpace() is inactive,
|
||||
// all active windows docked into it will lose their parent and become undocked.
|
||||
// We cannot preserve the docking relationship between an active window and an inactive docking, otherwise
|
||||
// any change of dockspace/settings would lead to windows being stuck in limbo and never being visible.
|
||||
if (!opt_padding)
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
|
||||
ImGui::Begin("DockSpace Demo", &dockspaceOpen, window_flags);
|
||||
if (!opt_padding)
|
||||
ImGui::PopStyleVar();
|
||||
|
||||
if (opt_fullscreen)
|
||||
ImGui::PopStyleVar(2);
|
||||
|
||||
// Submit the DockSpace
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
if (io.ConfigFlags & ImGuiConfigFlags_DockingEnable)
|
||||
{
|
||||
ImGuiID dockspace_id = ImGui::GetID("MyDockSpace");
|
||||
ImGui::DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), dockspace_flags);
|
||||
}
|
||||
|
||||
if (ImGui::BeginMenuBar())
|
||||
{
|
||||
if (ImGui::BeginMenu("Options"))
|
||||
{
|
||||
// Disabling fullscreen would allow the window to be moved to the front of other windows,
|
||||
// which we can't undo at the moment without finer window depth/z control.
|
||||
// ImGui::MenuItem("Fullscreen", NULL, &opt_fullscreen);
|
||||
// ImGui::MenuItem("Padding", NULL, &opt_padding);
|
||||
// ImGui::Separator();
|
||||
|
||||
if (ImGui::MenuItem("Exit")) { Hazel::Application::Get().Close(); }
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
ImGui::EndMenuBar();
|
||||
}
|
||||
|
||||
m_SceneHierachyPanel.OnImGuiRender();
|
||||
{
|
||||
ImGui::Begin("Render Status");
|
||||
|
||||
auto stats = Renderer2D::GetStats();
|
||||
ImGui::Text("Renderer BatchInfo: ");
|
||||
ImGui::Text("Draw Calls: %d", stats.DrawCalls);
|
||||
ImGui::Text("Quads: %d", stats.QuadCount);
|
||||
ImGui::Text("Vertices: %d", stats.GetTotalVertexCount());
|
||||
ImGui::Text("Indices: %d", stats.GetTotalIndexCount());
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
if (ImGui::Checkbox("Camera A", &m_PrimaryCamera))
|
||||
{
|
||||
m_CameraEntity.GetComponent<CameraComponent>().Primary = m_PrimaryCamera;
|
||||
m_SecondCamera.GetComponent<CameraComponent>().Primary = !m_PrimaryCamera;
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
ImGui::Text("viewPortSize: (%.2f, %.2f)", m_ViewPortSize.x, m_ViewPortSize.y);
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
{
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, {0.0f, 0.0f});
|
||||
ImGui::Begin("Viewport");
|
||||
m_ViewportFocused = ImGui::IsWindowFocused();
|
||||
m_ViewportHovered = ImGui::IsWindowHovered();
|
||||
|
||||
|
||||
ImVec2 viewPortPanelSize = ImGui::GetContentRegionAvail();
|
||||
if (m_ViewPortSize != *reinterpret_cast<glm::vec2*>(&viewPortPanelSize))
|
||||
{
|
||||
m_ViewPortSize = {viewPortPanelSize.x, viewPortPanelSize.y};
|
||||
}
|
||||
// ImGui::Text("Viewport: (%.2f, %.2f)", viewPortPanelSize.x, viewPortPanelSize.y);
|
||||
ImGui::Image(m_FrameBuffer->GetColorAttachmentID(), {m_ViewPortSize.x, m_ViewPortSize.y}, {0, 1},
|
||||
{1, 0});
|
||||
|
||||
ImGui::End();
|
||||
ImGui::PopStyleVar();
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
}
|
||||
|
||||
void EditorLayer::OnEvent(SDL_Event& e)
|
||||
{
|
||||
if (m_ViewportFocused && m_ViewportHovered)
|
||||
{
|
||||
m_CameraController.OnEvent(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
53
Sandbox/src/Editor/EditorLayer.h
Normal file
53
Sandbox/src/Editor/EditorLayer.h
Normal file
@ -0,0 +1,53 @@
|
||||
//
|
||||
// Created by sfd on 25-5-25.
|
||||
//
|
||||
|
||||
#ifndef EDITORLAYER_H
|
||||
#define EDITORLAYER_H
|
||||
#include <Hazel.h>
|
||||
|
||||
#include "Panels/SceneHierachyPanel.h"
|
||||
|
||||
namespace Hazel
|
||||
{
|
||||
class EditorLayer : public Layer
|
||||
{
|
||||
public:
|
||||
EditorLayer();
|
||||
virtual ~EditorLayer() = default;
|
||||
|
||||
virtual void OnAttach() override;
|
||||
virtual void OnDetech() override;
|
||||
|
||||
virtual void OnUpdate(TimeStep& ts) override;
|
||||
virtual void OnImGuiRender() override;
|
||||
virtual void OnEvent(SDL_Event& e) override;
|
||||
|
||||
private:
|
||||
OrthographicCameraController m_CameraController;
|
||||
|
||||
Ref<Texture2D> m_LogoTexture;
|
||||
Ref<Texture2D> m_CheckerBoardTexture;
|
||||
|
||||
Ref<Scene> m_ActiveScene;
|
||||
Entity m_SquareEntity;
|
||||
Entity m_CameraEntity;
|
||||
Entity m_SecondCamera;
|
||||
|
||||
bool m_PrimaryCamera = false;
|
||||
|
||||
glm::vec4 m_BackgroundColor = { 0.2f, 0.2f, 0.2f, 1.0f };
|
||||
glm::vec4 m_SquareColor = { 0.2f, 0.2f, 0.2f, 1.0f };
|
||||
|
||||
bool m_ViewportFocused = false, m_ViewportHovered = false;
|
||||
glm::vec2 m_ViewPortSize = {0, 0};
|
||||
|
||||
Ref<FrameBuffer> m_FrameBuffer;
|
||||
|
||||
SceneHierachyPanel m_SceneHierachyPanel;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif //EDITORLAYER_H
|
||||
168
Sandbox/src/Editor/Panels/SceneHierachyPanel.cpp
Normal file
168
Sandbox/src/Editor/Panels/SceneHierachyPanel.cpp
Normal file
@ -0,0 +1,168 @@
|
||||
//
|
||||
// Created by sfd on 25-5-29.
|
||||
//
|
||||
|
||||
#include "SceneHierachyPanel.h"
|
||||
|
||||
#include <imgui.h>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
#include <Hazel/Scene/Components.h>
|
||||
|
||||
namespace Hazel
|
||||
{
|
||||
SceneHierachyPanel::SceneHierachyPanel(const Ref<Scene>& context)
|
||||
{
|
||||
SetContext(context);
|
||||
}
|
||||
|
||||
void SceneHierachyPanel::SetContext(const Ref<Scene>& context)
|
||||
{
|
||||
m_Context = context;
|
||||
}
|
||||
|
||||
void SceneHierachyPanel::OnImGuiRender()
|
||||
{
|
||||
ImGui::Begin("Scene Hierachy");
|
||||
|
||||
for (const auto entityID : m_Context->m_Registry.view<entt::entity>())
|
||||
{
|
||||
DrawEntityNode({entityID, m_Context.get()});
|
||||
}
|
||||
|
||||
if (ImGui::IsMouseDown(0) && ImGui::IsWindowHovered())
|
||||
{
|
||||
m_SelectionContext = { };
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
|
||||
ImGui::Begin("Properties");
|
||||
if (m_SelectionContext)
|
||||
{
|
||||
DrawComponents(m_SelectionContext);
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
|
||||
void SceneHierachyPanel::DrawEntityNode(Entity entity)
|
||||
{
|
||||
auto& tag = entity.GetComponent<TagComponent>().Tag;
|
||||
|
||||
ImGuiTreeNodeFlags flags = ((m_SelectionContext == entity) ? ImGuiTreeNodeFlags_Selected : 0) | ImGuiTreeNodeFlags_OpenOnArrow;
|
||||
const bool isopened = ImGui::TreeNodeEx((void*)(uint64_t)(uint32_t)entity, flags, tag.c_str());
|
||||
if (ImGui::IsItemClicked())
|
||||
{
|
||||
m_SelectionContext = entity;
|
||||
}
|
||||
|
||||
if (isopened)
|
||||
{
|
||||
ImGui::TreePop();
|
||||
}
|
||||
}
|
||||
|
||||
void SceneHierachyPanel::DrawComponents(Entity entity)
|
||||
{
|
||||
|
||||
if (entity.HasComponent<TagComponent>())
|
||||
{
|
||||
auto& tag = entity.GetComponent<TagComponent>().Tag;
|
||||
|
||||
char buffer[256] = {};
|
||||
strcpy_s(buffer,sizeof(buffer), tag.c_str());
|
||||
if (ImGui::InputText("Tag", buffer, sizeof(buffer)))
|
||||
{
|
||||
tag = std::string(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
if (entity.HasComponent<TransformComponent>())
|
||||
{
|
||||
if (ImGui::TreeNodeEx((void*)(uint64_t)typeid(TransformComponent).hash_code(), ImGuiTreeNodeFlags_DefaultOpen, "Transform"))
|
||||
{
|
||||
auto& transform = entity.GetComponent<TransformComponent>().Transform;
|
||||
ImGui::DragFloat3("Position", glm::value_ptr(transform[3]), 0.01f);
|
||||
ImGui::TreePop();
|
||||
}
|
||||
}
|
||||
|
||||
if (entity.HasComponent<CameraComponent>())
|
||||
{
|
||||
if (ImGui::TreeNodeEx((void*)(uint64_t)typeid(CameraComponent).hash_code(), ImGuiTreeNodeFlags_DefaultOpen, "Transform"))
|
||||
{
|
||||
auto& cameraComponent = entity.GetComponent<CameraComponent>();
|
||||
auto& camera = cameraComponent.Camera;
|
||||
|
||||
ImGui::Checkbox("isPrimary", &cameraComponent.Primary);
|
||||
|
||||
static const char* projectionTypeStrings[] = { "Perspective", "Orthographic" };
|
||||
|
||||
const char* currentProjectionTypeString = projectionTypeStrings[(int)camera.GetProjectionType()];
|
||||
if (ImGui::BeginCombo("Projection", currentProjectionTypeString))
|
||||
{
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
const bool isSelected = currentProjectionTypeString == projectionTypeStrings[i];
|
||||
if (ImGui::Selectable(projectionTypeStrings[i], isSelected))
|
||||
{
|
||||
currentProjectionTypeString = projectionTypeStrings[i];
|
||||
camera.SetProjectionType(static_cast<ScenceCamera::ProjectionType>(i));
|
||||
}
|
||||
|
||||
if (isSelected)
|
||||
{
|
||||
ImGui::SetItemDefaultFocus();
|
||||
}
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
|
||||
if (camera.GetProjectionType() == ScenceCamera::ProjectionType::Perspective)
|
||||
{
|
||||
float fov = glm::degrees(camera.GetPerspectiveVerticalFOV());
|
||||
if (ImGui::DragFloat("FOV", &fov, 0.1f))
|
||||
camera.SetPerspectiveVerticalFOV(glm::radians(fov));
|
||||
|
||||
float near = camera.GetPerspectiveNearCLip();
|
||||
if (ImGui::DragFloat("Near", &near))
|
||||
camera.SetPerspectiveNearClip(near);
|
||||
|
||||
float far = camera.GetPerspectiveFarCLip();
|
||||
if (ImGui::DragFloat("Far", &far))
|
||||
camera.SetPerspectiveFarClip(far);
|
||||
}
|
||||
if (camera.GetProjectionType() == ScenceCamera::ProjectionType::Orthographic)
|
||||
{
|
||||
float size = camera.GetOrthographicSize();
|
||||
if (ImGui::DragFloat("Size", &size))
|
||||
camera.SetOrthographicSize(size);
|
||||
|
||||
float near = camera.GetOrthographicNearCLip();
|
||||
if (ImGui::DragFloat("Near", &near))
|
||||
camera.SetOrthographicNearClip(near);
|
||||
|
||||
float far = camera.GetOrthographicFarCLip();
|
||||
if (ImGui::DragFloat("Far", &far))
|
||||
camera.SetOrthographicFarClip(far);
|
||||
|
||||
ImGui::Checkbox("Fixed Aspect Ratio", &cameraComponent.FixedAspectRatio);
|
||||
}
|
||||
|
||||
|
||||
ImGui::TreePop();
|
||||
}
|
||||
}
|
||||
|
||||
if (entity.HasComponent<SpriteRendererComponent>())
|
||||
{
|
||||
if (ImGui::TreeNodeEx((void*)(uint64_t)typeid(SpriteRendererComponent).hash_code(), ImGuiTreeNodeFlags_DefaultOpen, "Sprite Renderer"))
|
||||
{
|
||||
auto& spriteRendererComponent = entity.GetComponent<SpriteRendererComponent>();
|
||||
ImGui::ColorEdit4("Color", glm::value_ptr(spriteRendererComponent.Color));
|
||||
|
||||
ImGui::TreePop();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
35
Sandbox/src/Editor/Panels/SceneHierachyPanel.h
Normal file
35
Sandbox/src/Editor/Panels/SceneHierachyPanel.h
Normal file
@ -0,0 +1,35 @@
|
||||
//
|
||||
// Created by sfd on 25-5-29.
|
||||
//
|
||||
|
||||
#ifndef SCENEHIERACHYPANEL_H
|
||||
#define SCENEHIERACHYPANEL_H
|
||||
#include <Hazel/Core/Core.h>
|
||||
#include <Hazel/Scene/Entity.h>
|
||||
#include <Hazel/Scene/Scene.h>
|
||||
|
||||
namespace Hazel
|
||||
{
|
||||
class SceneHierachyPanel
|
||||
{
|
||||
public:
|
||||
SceneHierachyPanel() = default;
|
||||
SceneHierachyPanel(const Ref<Scene>& context);
|
||||
|
||||
void SetContext(const Ref<Scene>& context);
|
||||
void OnImGuiRender();
|
||||
|
||||
void DrawComponents(Entity entity);
|
||||
|
||||
private:
|
||||
void DrawEntityNode(Entity entity);
|
||||
|
||||
private:
|
||||
|
||||
Ref<Scene> m_Context;
|
||||
Entity m_SelectionContext;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif //SCENEHIERACHYPANEL_H
|
||||
@ -8,8 +8,26 @@
|
||||
|
||||
#include "glm/gtc/type_ptr.hpp"
|
||||
|
||||
static constexpr uint32_t s_MapWidth = 24;
|
||||
static const char* s_MapTiles =
|
||||
"WWWWWWWDDDDDDDDWWWAWWWWW"
|
||||
"WWWWWWWDWWWWWWWWWWWWWWWW"
|
||||
"WWWWWWWWWDDDDDDDDDDWWWWW"
|
||||
"WWWWWWWDDDDDDDWWWWWWWWWW"
|
||||
"WWWWWDDDDDDDDDDWWWWWWWWW"
|
||||
"WWWWDDDDDDDDDDWDDDDDWWWW"
|
||||
"WWDDDDDDWWWWWWWWDDDDDWWW"
|
||||
"WDDDDDDWWWWWWWWWDDDDWWWW"
|
||||
"WDDDDDDDDDDWWWWDDDDWWWWW"
|
||||
"WWWWDDDDDDDDDDDDDDWWWWWW"
|
||||
"WWWWWWWWWWWWWWWWWWWWWWWW"
|
||||
"WWWWWWWWWWWWWWWWWWWWWWWW";
|
||||
|
||||
SandBox2D::SandBox2D()
|
||||
: Layer("SandBox2D"), m_CameraController((float)Hazel::Application::Get().GetWindow().GetWidth() / (float)Hazel::Application::Get().GetWindow().GetHeight())
|
||||
: Layer("SandBox2D"),
|
||||
m_CameraController(
|
||||
(float)Hazel::Application::Get().GetWindow().GetWidth() / (float)Hazel::Application::Get().GetWindow().
|
||||
GetHeight())
|
||||
{
|
||||
}
|
||||
|
||||
@ -17,17 +35,28 @@ void SandBox2D::OnAttach()
|
||||
{
|
||||
HZ_PROFILE_FUNCTION();
|
||||
m_LogoTexture = Hazel::Texture2D::Create("assets/textures/iceLogo.png");
|
||||
m_Texture = Hazel::Texture2D::Create("assets/textures/spritesheet-tiles-double.png");
|
||||
m_SubTexture = Hazel::SubTexture2D::CreateFromCoords(m_Texture, {8, 5}, {128, 128}, {1, 2});
|
||||
m_Texture = Hazel::Texture2D::Create("assets/textures/spritesheet-tiles-double.png");
|
||||
|
||||
m_Particle.ColorBegin = {0 / 255.f, 212 /255.f, 123 / 255.f,1.0f};
|
||||
m_Particle.ColorEnd = {254 / 255.f, 109 /255.f, 41 / 255.f,1.0f};
|
||||
m_Particle.SizeBegin = 0.3f, m_Particle.SizeVariation = 0.3f, m_Particle.SizeEnd = 0.0f;
|
||||
m_Particle.LifeTime = 1.0f;
|
||||
m_Particle.Velocity = {0.0f, 0.0f};
|
||||
m_MapWidth = s_MapWidth;
|
||||
m_MapHeight = strlen(s_MapTiles) / s_MapWidth;
|
||||
|
||||
m_defaultTexture = Hazel::SubTexture2D::CreateFromCoords(m_Texture, {13, 3}, {128, 128});
|
||||
|
||||
m_TextureMap['D'] = Hazel::SubTexture2D::CreateFromCoords(m_Texture, {1, 2}, {128, 128});
|
||||
m_TextureMap['W'] = Hazel::SubTexture2D::CreateFromCoords(m_Texture, {0, 11}, {128, 128});
|
||||
// m_SubTexture = Hazel::SubTexture2D::CreateFromCoords(m_Texture, {8, 5}, {128, 128}, {1, 2});
|
||||
Hazel::FrameBufferSpecification specification;
|
||||
specification.Width = 1280;
|
||||
specification.Height = 720;
|
||||
m_FrameBuffer = Hazel::FrameBuffer::Create(specification);
|
||||
|
||||
m_Particle.ColorBegin = {0 / 255.f, 212 / 255.f, 123 / 255.f, 1.0f};
|
||||
m_Particle.ColorEnd = {254 / 255.f, 109 / 255.f, 41 / 255.f, 1.0f};
|
||||
m_Particle.SizeBegin = 0.3f, m_Particle.SizeVariation = 0.3f, m_Particle.SizeEnd = 0.0f;
|
||||
m_Particle.LifeTime = 1.0f;
|
||||
m_Particle.Velocity = {0.0f, 0.0f};
|
||||
m_Particle.VelocityVariation = {2.0f, 2.0f};
|
||||
m_Particle.Position = {0.0f, 0.0f};
|
||||
|
||||
m_Particle.Position = {0.0f, 0.0f};
|
||||
}
|
||||
|
||||
void SandBox2D::OnDetech()
|
||||
@ -46,47 +75,51 @@ void SandBox2D::OnUpdate(Hazel::TimeStep& ts)
|
||||
|
||||
{
|
||||
HZ_PROFILE_SCOPE("Renderer Prep");
|
||||
// Hazel::RendererCommand::SetClearColor({0.2f, 0.2f, 0.2f, 1.0f});
|
||||
|
||||
m_FrameBuffer->Bind();
|
||||
Hazel::RendererCommand::SetClearColor(m_BackgroundColor);
|
||||
Hazel::RendererCommand::Clear();
|
||||
}
|
||||
|
||||
{
|
||||
HZ_PROFILE_SCOPE("Renderer Draw");
|
||||
Hazel::Renderer2D::BeginScene(m_CameraController.GetCamera());
|
||||
|
||||
for (unsigned int y = 0; y < m_MapHeight; y++)
|
||||
{
|
||||
for (unsigned int x = 0; x < m_MapWidth; x++)
|
||||
{
|
||||
const char tileType = s_MapTiles[y * m_MapWidth + x];
|
||||
Hazel::Ref<Hazel::SubTexture2D> texture;
|
||||
if (m_TextureMap.find(tileType) != m_TextureMap.end())
|
||||
{
|
||||
texture = m_TextureMap[tileType];
|
||||
}else
|
||||
{
|
||||
texture = m_defaultTexture;
|
||||
}
|
||||
|
||||
// Hazel::Renderer2D::DrawQuad({0, 0}, {1.0f,1.0f}, {1.0f, 1.0f, 1.0f, 1.0f});
|
||||
Hazel::Renderer2D::DrawRotateQuad({-0.5f, 0}, {1.0f,1.0f}, glm::radians(0.f), m_LogoTexture);
|
||||
// Hazel::Renderer2D::DrawQuad({0.5f, 0}, {1.0f,1.0f}, m_Texture);
|
||||
Hazel::Renderer2D::DrawQuad({0.5f, 0}, {1.0f,2.0f}, m_SubTexture);
|
||||
|
||||
// Hazel::Renderer2D::DrawRotateQuad({-1.0f, 0.0f}, {0.5f, 0.5f}, 75.f, {1.0f, 0.0f, 1.0f, 1.0f});
|
||||
// Hazel::Renderer2D::DrawRotateQuad({0.0f, 0.0f}, {1.0f, 1.0f}, rotation, m_LogoTexture, 10.f);
|
||||
|
||||
for (float y = -5.0f; y < 5.0f; y += 0.5f)
|
||||
{
|
||||
for (float x = -5.0f; x < 5.0f; x += 0.5f)
|
||||
{
|
||||
auto color = glm::vec4((x + 5.0f ) /10.0f, 0.4f, (y + 5.0f) / 10.0f, 1.0f);
|
||||
Hazel::Renderer2D::DrawQuad({x, y, -0.1f}, {0.45f, 0.45f}, m_LogoTexture, 1, color);
|
||||
}
|
||||
}
|
||||
Hazel::Renderer2D::DrawQuad({x - m_MapWidth / 2.0f, m_MapHeight / 2.0f - y, -0.1f}, {1.0f, 1.0f}, texture);
|
||||
}
|
||||
}
|
||||
|
||||
Hazel::Renderer2D::EndScene();
|
||||
if ((mouseState & SDL_BUTTON_LMASK) && m_CurrentWindowID == Hazel::Application::Get().GetWindow().GetMainWindowID())
|
||||
|
||||
if ((mouseState & SDL_BUTTON_LMASK) && m_CurrentWindowID == Hazel::Application::Get().GetWindow().
|
||||
GetMainWindowID())
|
||||
{
|
||||
auto width = Hazel::Application::Get().GetWindow().GetWidth();
|
||||
auto width = Hazel::Application::Get().GetWindow().GetWidth();
|
||||
auto height = Hazel::Application::Get().GetWindow().GetHeight();
|
||||
|
||||
float x, y;
|
||||
SDL_GetMouseState(&x, &y);
|
||||
auto bounds = m_CameraController.GetBounds();
|
||||
auto bounds = m_CameraController.GetBounds();
|
||||
auto cameraPos = m_CameraController.GetCamera().GetPosition();
|
||||
|
||||
x = (x / width) * bounds.GetWidth() - bounds.GetWidth() * 0.5f;
|
||||
y = bounds.GetHeight() * 0.5f - (y / height) * bounds.GetHeight();
|
||||
x = (x / width) * bounds.GetWidth() - bounds.GetWidth() * 0.5f;
|
||||
y = bounds.GetHeight() * 0.5f - (y / height) * bounds.GetHeight();
|
||||
m_Particle.Position = {x + cameraPos.x, y + cameraPos.y};
|
||||
for (int i = 0; i < 5; i ++)
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
m_ParticleSystem.Emit(m_Particle);
|
||||
}
|
||||
@ -95,57 +128,145 @@ void SandBox2D::OnUpdate(Hazel::TimeStep& ts)
|
||||
m_ParticleSystem.OnUpdate(ts);
|
||||
m_ParticleSystem.OnRender(m_CameraController.GetCamera());
|
||||
}
|
||||
m_FrameBuffer->UnBind();
|
||||
|
||||
}
|
||||
|
||||
void SandBox2D::OnImGuiRender()
|
||||
{
|
||||
// const auto cameraRotation = m_CameraController.GetCamera().GetRotation();
|
||||
const auto cameraPosition = m_CameraController.GetCamera().GetPosition();
|
||||
const auto windowWidth = Hazel::Application::Get().GetWindow().GetWidth();
|
||||
const auto windowHeight = Hazel::Application::Get().GetWindow().GetHeight();
|
||||
|
||||
auto stats = Hazel::Renderer2D::GetStats();
|
||||
|
||||
ImGui::Begin("Hazel Layer");
|
||||
|
||||
ImGui::Text("Renderer BatchInfo: ");
|
||||
ImGui::Text("Draw Calls: %d", stats.DrawCalls);
|
||||
ImGui::Text("Quads: %d", stats.QuadCount);
|
||||
ImGui::Text("Vertices: %d", stats.GetTotalVertexCount());
|
||||
ImGui::Text("Indices: %d", stats.GetTotalIndexCount());
|
||||
|
||||
ImGui::Text("WindowSize: (%u, %u)", windowWidth, windowHeight);
|
||||
|
||||
ImGui::Text("Camera");
|
||||
// ImGui::Text("Camera Rotation: %f", cameraRotation);
|
||||
ImGui::Text("Camera Position: ( %.2f, %.2f, %.2f)", cameraPosition.x, cameraPosition.y, cameraPosition.z);
|
||||
|
||||
ImGui::NewLine();
|
||||
ImGui::Text("frame: %.3f", ImGui::GetIO().Framerate);
|
||||
ImGui::ColorEdit4("Square Color", glm::value_ptr(m_BackgroundColor));
|
||||
|
||||
|
||||
ImGui::NewLine();
|
||||
ImGui::ColorEdit4("begin Color", glm::value_ptr(m_Particle.ColorBegin));
|
||||
ImGui::ColorEdit4("End Color", glm::value_ptr(m_Particle.ColorEnd));
|
||||
|
||||
ImGui::NewLine();
|
||||
for (auto& profileResult : m_ProfileResults)
|
||||
{
|
||||
ImGui::Text("%s: %.3fms", profileResult.Name, profileResult.Time);
|
||||
}
|
||||
m_ProfileResults.clear();
|
||||
|
||||
ImGui::NewLine();
|
||||
static bool isSync = Hazel::Application::Get().GetWindow().IsVSync();
|
||||
bool laststate = isSync;
|
||||
ImGui::Checkbox("isVSync", &isSync);
|
||||
if (isSync != laststate)
|
||||
{
|
||||
Hazel::Application::Get().GetWindow().SetVSync(isSync);
|
||||
}
|
||||
|
||||
ImGui::Begin("Settings");
|
||||
ImGui::Image(m_FrameBuffer->GetColorAttachmentID(), {1280.f, 720.f});
|
||||
ImGui::End();
|
||||
|
||||
static bool showDockspace = false;
|
||||
if (showDockspace)
|
||||
{
|
||||
// const auto cameraRotation = m_CameraController.GetCamera().GetRotation();
|
||||
const auto cameraPosition = m_CameraController.GetCamera().GetPosition();
|
||||
const auto windowWidth = Hazel::Application::Get().GetWindow().GetWidth();
|
||||
const auto windowHeight = Hazel::Application::Get().GetWindow().GetHeight();
|
||||
|
||||
auto stats = Hazel::Renderer2D::GetStats();
|
||||
|
||||
|
||||
static bool dockspaceOpen = true;
|
||||
static bool opt_fullscreen = true;
|
||||
static bool opt_padding = false;
|
||||
static ImGuiDockNodeFlags dockspace_flags = ImGuiDockNodeFlags_None;
|
||||
|
||||
// We are using the ImGuiWindowFlags_NoDocking flag to make the parent window not dockable into,
|
||||
// because it would be confusing to have two docking targets within each others.
|
||||
ImGuiWindowFlags window_flags = ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoDocking;
|
||||
if (opt_fullscreen)
|
||||
{
|
||||
const ImGuiViewport* viewport = ImGui::GetMainViewport();
|
||||
ImGui::SetNextWindowPos(viewport->WorkPos);
|
||||
ImGui::SetNextWindowSize(viewport->WorkSize);
|
||||
ImGui::SetNextWindowViewport(viewport->ID);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
|
||||
window_flags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize |
|
||||
ImGuiWindowFlags_NoMove;
|
||||
window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus;
|
||||
}
|
||||
else
|
||||
{
|
||||
dockspace_flags &= ~ImGuiDockNodeFlags_PassthruCentralNode;
|
||||
}
|
||||
|
||||
// When using ImGuiDockNodeFlags_PassthruCentralNode, DockSpace() will render our background
|
||||
// and handle the pass-thru hole, so we ask Begin() to not render a background.
|
||||
if (dockspace_flags & ImGuiDockNodeFlags_PassthruCentralNode)
|
||||
window_flags |= ImGuiWindowFlags_NoBackground;
|
||||
|
||||
// Important: note that we proceed even if Begin() returns false (aka window is collapsed).
|
||||
// This is because we want to keep our DockSpace() active. If a DockSpace() is inactive,
|
||||
// all active windows docked into it will lose their parent and become undocked.
|
||||
// We cannot preserve the docking relationship between an active window and an inactive docking, otherwise
|
||||
// any change of dockspace/settings would lead to windows being stuck in limbo and never being visible.
|
||||
if (!opt_padding)
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
|
||||
ImGui::Begin("DockSpace Demo", &dockspaceOpen, window_flags);
|
||||
if (!opt_padding)
|
||||
ImGui::PopStyleVar();
|
||||
|
||||
if (opt_fullscreen)
|
||||
ImGui::PopStyleVar(2);
|
||||
|
||||
// Submit the DockSpace
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
if (io.ConfigFlags & ImGuiConfigFlags_DockingEnable)
|
||||
{
|
||||
ImGuiID dockspace_id = ImGui::GetID("MyDockSpace");
|
||||
ImGui::DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), dockspace_flags);
|
||||
}
|
||||
|
||||
if (ImGui::BeginMenuBar())
|
||||
{
|
||||
if (ImGui::BeginMenu("Options"))
|
||||
{
|
||||
// Disabling fullscreen would allow the window to be moved to the front of other windows,
|
||||
// which we can't undo at the moment without finer window depth/z control.
|
||||
// ImGui::MenuItem("Fullscreen", NULL, &opt_fullscreen);
|
||||
// ImGui::MenuItem("Padding", NULL, &opt_padding);
|
||||
// ImGui::Separator();
|
||||
|
||||
if (ImGui::MenuItem("Exit")) { Hazel::Application::Get().Close(); }
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
ImGui::EndMenuBar();
|
||||
}
|
||||
|
||||
{
|
||||
ImGui::Begin("Hazel Layer");
|
||||
|
||||
ImGui::Text("Renderer BatchInfo: ");
|
||||
ImGui::Text("Draw Calls: %d", stats.DrawCalls);
|
||||
ImGui::Text("Quads: %d", stats.QuadCount);
|
||||
ImGui::Text("Vertices: %d", stats.GetTotalVertexCount());
|
||||
ImGui::Text("Indices: %d", stats.GetTotalIndexCount());
|
||||
|
||||
ImGui::Text("WindowSize: (%u, %u)", windowWidth, windowHeight);
|
||||
|
||||
ImGui::Text("Camera");
|
||||
// ImGui::Text("Camera Rotation: %f", cameraRotation);
|
||||
ImGui::Text("Camera Position: ( %.2f, %.2f, %.2f)", cameraPosition.x, cameraPosition.y, cameraPosition.z);
|
||||
|
||||
ImGui::NewLine();
|
||||
ImGui::Text("frame: %.3f", ImGui::GetIO().Framerate);
|
||||
ImGui::ColorEdit4("Square Color", glm::value_ptr(m_BackgroundColor));
|
||||
|
||||
|
||||
ImGui::NewLine();
|
||||
ImGui::ColorEdit4("begin Color", glm::value_ptr(m_Particle.ColorBegin));
|
||||
ImGui::ColorEdit4("End Color", glm::value_ptr(m_Particle.ColorEnd));
|
||||
|
||||
ImGui::NewLine();
|
||||
for (auto& profileResult : m_ProfileResults)
|
||||
{
|
||||
ImGui::Text("%s: %.3fms", profileResult.Name, profileResult.Time);
|
||||
}
|
||||
m_ProfileResults.clear();
|
||||
|
||||
ImGui::NewLine();
|
||||
static bool isSync = Hazel::Application::Get().GetWindow().IsVSync();
|
||||
bool laststate = isSync;
|
||||
ImGui::Checkbox("isVSync", &isSync);
|
||||
if (isSync != laststate)
|
||||
{
|
||||
Hazel::Application::Get().GetWindow().SetVSync(isSync);
|
||||
}
|
||||
uint32_t textureID = m_FrameBuffer->GetColorAttachmentID();
|
||||
ImGui::Image(textureID, ImVec2(1280.f, 720.f));
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
}
|
||||
|
||||
void SandBox2D::OnEvent(SDL_Event& e)
|
||||
@ -153,5 +274,5 @@ void SandBox2D::OnEvent(SDL_Event& e)
|
||||
if (m_CurrentWindowID != e.window.windowID)
|
||||
m_CurrentWindowID = e.window.windowID;
|
||||
|
||||
m_CameraController.OnEvent(e);
|
||||
m_CameraController.OnEvent(e);
|
||||
}
|
||||
|
||||
@ -24,7 +24,8 @@ private:
|
||||
Hazel::Ref<Hazel::Shader> m_FlatColorShader;
|
||||
Hazel::Ref<Hazel::Texture2D> m_Texture;
|
||||
Hazel::Ref<Hazel::Texture2D> m_LogoTexture;
|
||||
Hazel::Ref<Hazel::SubTexture2D> m_SubTexture;
|
||||
Hazel::Ref<Hazel::SubTexture2D> m_defaultTexture;
|
||||
Hazel::Ref<Hazel::FrameBuffer> m_FrameBuffer;
|
||||
|
||||
glm::vec4 m_BackgroundColor = {0.2f, 0.2f, 0.2f, 1.0f};
|
||||
|
||||
@ -35,6 +36,8 @@ private:
|
||||
};
|
||||
|
||||
std::vector<ProfileResult> m_ProfileResults;
|
||||
std::unordered_map<char, Hazel::Ref<Hazel::SubTexture2D>> m_TextureMap;
|
||||
uint32_t m_MapWidth, m_MapHeight;
|
||||
|
||||
ParticleSystem m_ParticleSystem;
|
||||
ParticleProp m_Particle;
|
||||
|
||||
@ -1,31 +1,28 @@
|
||||
#include <Hazel.h>
|
||||
#include "Hazel/Core/EntryPoint.h"
|
||||
|
||||
#include "SandBox2D/SandBox2D.h"
|
||||
// #include "DemoBox/GameLayer.h"
|
||||
// #include "Example/ExampleLayer.h"
|
||||
#include "Editor/EditorLayer.h"
|
||||
|
||||
|
||||
|
||||
class Sandbox : public Hazel::Application
|
||||
namespace Hazel
|
||||
{
|
||||
public:
|
||||
Sandbox()
|
||||
class HazelEditor : public Application
|
||||
{
|
||||
// PushLayer(new ExampleLayer());
|
||||
PushLayer(new SandBox2D());
|
||||
// PushLayer(new GameLayer());
|
||||
public:
|
||||
HazelEditor()
|
||||
: Application("Hazel Editor", 1280, 720)
|
||||
{
|
||||
PushLayer(new EditorLayer());
|
||||
}
|
||||
|
||||
~HazelEditor() = default;
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
|
||||
Application* CreateApplication()
|
||||
{
|
||||
return new HazelEditor();
|
||||
}
|
||||
|
||||
~Sandbox();
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
|
||||
Sandbox::~Sandbox() = default;
|
||||
|
||||
Hazel::Application* Hazel::CreateApplication()
|
||||
{
|
||||
return new Sandbox();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user