简单添加entt实体组件系统库

This commit is contained in:
2025-05-29 21:21:15 +08:00
parent 1da0252d6a
commit 31c77dcb5e
43 changed files with 95682 additions and 250 deletions

1
.gitignore vendored
View File

@ -1,5 +1,6 @@
# Directories
.vs/
.vscode/
bin/
bin-int/
.idea/

View File

@ -8,20 +8,28 @@ add_subdirectory(vendor/glm)
file(GLOB_RECURSE SOURCES "src/*.cpp")
include_directories(vendor/stb)
file(GLOB STB vendor/stb/stb_image.h)
# stb_image
set(STB_INCLUDE_DIR vendor/stb)
include_directories(${SRB_INCLUDE_DIR}/include)
file(GLOB_RECURSE STB ${STB_INCLUDE_DIR}/include/*)
# entt
set(ENTT_INCLUDE_DIR vendor/entt)
include_directories(${ENTT_INCLUDE_DIR}/include)
file(GLOB_RECURSE ENTT ${ENTT_INCLUDE_DIR}/include/*)
include_directories(vendor/imgui)
include_directories(vendor/imgui/backends)
file(GLOB IMGUI vendor/imgui/**.cpp
vendor/imgui/backends/imgui_impl_opengl3.cpp
vendor/imgui/backends/imgui_impl_sdl3.cpp)
# imgui
set(IMGUI_INCLUDE_DIR vendor/imgui)
include_directories(${IMGUI_INCLUDE_DIR} ${IMGUI_INCLUDE_DIR}/backends)
file(GLOB IMGUI ${IMGUI_INCLUDE_DIR}/*.cpp
${IMGUI_INCLUDE_DIR}/backends/imgui_impl_opengl3.cpp
${IMGUI_INCLUDE_DIR}/backends/imgui_impl_sdl3.cpp)
add_library(Hazel SHARED
${SOURCES}
${IMGUI}
${STB}
${ENTT}
)
@ -35,8 +43,9 @@ set(SDL3_SHARED ON CACHE BOOL "Build SDL as shared library" FORCE)
target_include_directories(${PROJECT_NAME}
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/src # 暴露头文件给其他项目
vendor/imgui
vendor/imgui/backends
${STB_INCLUDE_DIR}
${IMGUI_INCLUDE_DIR}
${ENTT_INCLUDE_DIR}
)

View File

@ -7,23 +7,26 @@
#include "Hazel/Core/Application.h"
#include "Hazel/Core/Core.h"
#include "Hazel/Core/Log.h"
#include "Hazel/Debug/Instrumentor.h"
#include "Hazel/Core/Window.h"
#include "Hazel/Debug/Instrumentor.h"
#include "Hazel/ImGui/ImGuiLayer.h"
#include "Hazel/Scene/Components.h"
#include "Hazel/Scene/Scene.h"
#include "Hazel/Scene/ScriptableEntity.h"
#include "Hazel/Scene/Entity.h"
// ------------------------ Renderer ----------------------------
#include "Hazel/Renderer/Buffer.h"
#include "Hazel/Renderer/FrameBuffer.h"
#include "Hazel/Renderer/OrthographicCameraController.h"
#include "Hazel/Renderer/Renderer.h"
#include "Hazel/Renderer/Renderer2D.h"
#include "Hazel/Renderer/RendererCommand.h"
#include "Hazel/Renderer/Buffer.h"
#include "Hazel/Renderer/Shader.h"
#include "Hazel/Renderer/Texture.h"
#include "Hazel/Renderer/SubTexture2D.h"
#include "Hazel/Renderer/Texture.h"
#include "Hazel/Renderer/VertexArray.h"
#include "Hazel/Renderer/OrthographicCameraController.h"

View File

@ -14,7 +14,7 @@ namespace Hazel {
Application* Application::s_Instance = nullptr;
Application::Application()
Application::Application(const std::string& name, int width, int height)
{
HZ_PROFILE_FUNCTION();
@ -24,7 +24,7 @@ namespace Hazel {
}
s_Instance = this;
m_Window = std::unique_ptr<Window>(Window::Create());
m_Window = Window::Create(WindowProps(name, width, height));
m_Window->SetEventCallback(std::bind(&Application::OnEvent, this, std::placeholders::_1));
m_Window->SetWindowResizeEventCallback(std::bind(&Application::OnWindowResize, this, std::placeholders::_1));
@ -107,7 +107,7 @@ namespace Hazel {
HZ_PROFILE_FUNCTION();
m_Minimized = false;
HZ_CORE_INFO("Resized window:({0}, {1})", m_Window->GetWidth(), m_Window->GetHeight());
Renderer::OnWindowResize(m_Window->GetWidth(), m_Window->GetHeight());
// Renderer::OnWindowResize(m_Window->GetWidth(), m_Window->GetHeight());
}
void Application::PushLayer(Layer* layer)
{
@ -122,4 +122,9 @@ namespace Hazel {
m_layerStack.PushOverlay(layer);
layer->OnAttach();
}
void Application::Close()
{
m_Running = false;
}
}

View File

@ -13,7 +13,7 @@ namespace Hazel {
class HAZEL_API Application
{
public:
Application();
Application(const std::string& name = "Hazel App", int width = 1280, int height = 720);
virtual ~Application();
void Run();
@ -22,11 +22,16 @@ namespace Hazel {
void OnWindowResize(SDL_Event& e);
void PushLayer(Layer* layer);
void PushOverlay(Layer* layer);
inline Window& GetWindow() { return *m_Window; }
void Close();
ImGuiLayer* GetImGuiLayer() const { return m_imguiLayer; }
inline Window& GetWindow() const { return *m_Window; }
inline static Application& Get() { return *s_Instance; }
private:
std::unique_ptr<Hazel::Window> m_Window;
Scope<Window> m_Window;
ImGuiLayer* m_imguiLayer;
bool m_Running = true;

View File

@ -17,6 +17,13 @@ namespace Hazel
template<typename T>
using Scope = std::unique_ptr<T>;
template<typename T, typename ... Args>
constexpr Scope<T> CreateScope(Args&&... args)
{
return std::make_unique<T>(std::forward<Args>(args)...);
}
template<typename T>
using Ref = std::shared_ptr<T>;

View File

@ -27,6 +27,7 @@ namespace Hazel {
}
#define HZ_CORE_TRACE(...) ::Hazel::Log::getCoreLogger()->trace(__VA_ARGS__)
#define HZ_CORE_DEBUG(...) ::Hazel::Log::getCoreLogger()->debug(__VA_ARGS__)
#define HZ_CORE_INFO(...) ::Hazel::Log::getCoreLogger()->info(__VA_ARGS__)

View File

@ -15,12 +15,12 @@ namespace Hazel
struct WindowProps
{
std::string title;
unsigned int width;
unsigned int height;
uint32_t width;
uint32_t height;
WindowProps(const std::string& title = "Hazel",
unsigned int width = 1280,
unsigned int height = 720) : title(title), width(width), height(height) {}
WindowProps(const std::string& title = "Hazel App",
uint32_t width = 1280,
uint32_t height = 720) : title(title), width(width), height(height) {}
};
@ -34,8 +34,8 @@ namespace Hazel
virtual void OnUpdate() = 0;
virtual unsigned int GetWidth() const = 0;
virtual unsigned int GetHeight() const = 0;
virtual uint32_t GetWidth() const = 0;
virtual uint32_t GetHeight() const = 0;
// Window attributes
virtual void SetEventCallback(const EventCallbackFn& callback) = 0;
@ -43,7 +43,7 @@ namespace Hazel
virtual void SetVSync(bool enabled) = 0;
virtual bool IsVSync() const = 0;
static Window* Create(const WindowProps& props = WindowProps());
static Scope<Window> Create(const WindowProps& props = WindowProps());
virtual Uint32 GetMainWindowID() const = 0;
virtual void* GetNativeWindow() const = 0;

View File

@ -61,7 +61,10 @@ namespace Hazel
void ImGuiLayer::OnEvent(SDL_Event& e)
{
ImGui_ImplSDL3_ProcessEvent(&e);
// if (m_BlockEvent)
// {
ImGui_ImplSDL3_ProcessEvent(&e);
// }
}
void ImGuiLayer::OnImGuiRender()
@ -81,7 +84,7 @@ namespace Hazel
{
HZ_PROFILE_FUNCTION();
ImGuiIO& io = ImGui::GetIO();
Application& app = Application::Get();
const Application& app = Application::Get();
io.DisplaySize = ImVec2(static_cast<float>(app.GetWindow().GetWidth()), static_cast<float>(app.GetWindow().GetHeight()));
ImGui::Render();
@ -90,7 +93,7 @@ namespace Hazel
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
{
SDL_Window* backup_current_window = SDL_GL_GetCurrentWindow();
SDL_GLContext backup_current_context = SDL_GL_GetCurrentContext();
const SDL_GLContext backup_current_context = SDL_GL_GetCurrentContext();
ImGui::UpdatePlatformWindows();
ImGui::RenderPlatformWindowsDefault();
SDL_GL_MakeCurrent(backup_current_window, backup_current_context);

View File

@ -22,7 +22,10 @@ namespace Hazel {
void Begin();
void End();
void BlockEvents(const bool block) {m_BlockEvent = block;}
private:
bool m_BlockEvent = true;
float m_Time = 0.0f;
};

View File

@ -0,0 +1,5 @@
//
// Created by sfd on 25-5-28.
//
#include "Camera.h"

View File

@ -0,0 +1,24 @@
//
// Created by sfd on 25-5-28.
//
#ifndef CAMERA_H
#define CAMERA_H
#include "glm/glm.hpp"
#include "Hazel/Core/Core.h"
namespace Hazel {
class HAZEL_API Camera{
public:
Camera() = default;
Camera(const glm::mat4& projection) : m_Projection(projection) {}
virtual ~Camera() = default;
const glm::mat4& GetProjection() const { return m_Projection; }
protected:
glm::mat4 m_Projection = glm::mat4(1.0f);
};
}
#endif //CAMERA_H

View File

@ -0,0 +1,29 @@
//
// Created by sfd on 25-5-25.
//
#include "FrameBuffer.h"
#include <Platform/OpenGL/OpenGLFrameBuffer.h>
#include "Renderer.h"
namespace Hazel
{
Ref<FrameBuffer> FrameBuffer::Create(const FrameBufferSpecification& spec)
{
switch (Renderer::GetAPI())
{
case RendererAPI::API::NONE:
HZ_CORE_ERROR("NONE is not Support!");
return nullptr;
case RendererAPI::API::OPENGL:
return CreateRef<OpenGLFrameBuffer>(spec);
default:
break;
}
HZ_CORE_ERROR("Unknown RendererAPI!");
return nullptr;
}
}

View File

@ -0,0 +1,41 @@
//
// Created by sfd on 25-5-25.
//
#ifndef FRAMEBUFFER_H
#define FRAMEBUFFER_H
#include <Hazel/Core/Core.h>
#include "glm/vec2.hpp"
namespace Hazel
{
struct FrameBufferSpecification
{
uint32_t Width, Height;
uint32_t Samples;
bool SwapChainTarget = false;
};
class HAZEL_API FrameBuffer
{
public:
virtual ~FrameBuffer() = default;
// virtual FrameBufferSpecification& GetSpecification() = 0;
virtual const FrameBufferSpecification& GetSpecification() const = 0;
virtual uint32_t GetColorAttachmentID() const = 0;
virtual void Bind() = 0;
virtual void UnBind() = 0;
virtual void Resize(uint32_t width, uint32_t height) = 0;
static Ref<FrameBuffer> Create(const FrameBufferSpecification& spec);
};
}
#endif //FRAMEBUFFER_H

View File

@ -12,6 +12,7 @@ namespace Hazel
class HAZEL_API GraphicsContext
{
public:
virtual ~GraphicsContext() = default;
virtual void Init() = 0;
virtual void SwapBuffers() = 0;

View File

@ -10,41 +10,41 @@
namespace Hazel
{
OrthographicCameraController::OrthographicCameraController(float aspectRatio, bool isRotation) : m_AspectRatio(aspectRatio), m_isRotation(isRotation),m_Bounds(-m_AspectRatio * m_ZoomLevel, m_AspectRatio * m_ZoomLevel, -m_ZoomLevel, m_ZoomLevel), m_Camera(m_Bounds.left, m_Bounds.right, m_Bounds.bottom, m_Bounds.top)
OrthographicCameraController::OrthographicCameraController(float aspectRatio, bool isRotation)
: m_AspectRatio(aspectRatio), m_isRotation(isRotation),
m_Bounds(-m_AspectRatio * m_ZoomLevel, m_AspectRatio * m_ZoomLevel, -m_ZoomLevel, m_ZoomLevel),
m_Camera(m_Bounds.left, m_Bounds.right, m_Bounds.bottom, m_Bounds.top)
{
}
void OrthographicCameraController::OnResize(const float width, const float height)
{
m_AspectRatio = width / height;
CalculateView();
}
void OrthographicCameraController::OnUpdate(TimeStep ts)
{
HZ_PROFILE_FUNCTION();
const bool* state = SDL_GetKeyboardState(NULL);
static const bool* state = SDL_GetKeyboardState(NULL);
float time = ts;
if (state[SDL_SCANCODE_A])
{
m_CameraPosition.x -= m_CameraTranslationSpeed * time;
}
else if (state[SDL_SCANCODE_D])
{
m_CameraPosition.x += m_CameraTranslationSpeed * time;
}
if (state[SDL_SCANCODE_W])
{
m_CameraPosition.y += m_CameraTranslationSpeed * time;
}
else if (state[SDL_SCANCODE_S])
{
m_CameraPosition.y -= m_CameraTranslationSpeed * time;
}
if (m_isRotation)
{
if (state[SDL_SCANCODE_Q])
{
m_CameraRotation += m_CameraRotationSpeed * time;
}
else if (state[SDL_SCANCODE_E])
{
m_CameraRotation -= m_CameraRotationSpeed * time;
}
m_Camera.SetRotation(m_CameraRotation);
}
@ -57,35 +57,38 @@ namespace Hazel
void OrthographicCameraController::OnEvent(SDL_Event& e)
{
HZ_PROFILE_FUNCTION();
OnMouseScrolled(e);
OnWindowResized(e);
HZ_PROFILE_FUNCTION();
OnMouseScrolled(e);
OnWindowResized(e);
}
void OrthographicCameraController::CalculateView()
{
m_Bounds = {-m_AspectRatio * m_ZoomLevel, m_AspectRatio * m_ZoomLevel, -m_ZoomLevel, m_ZoomLevel};
m_Camera.SetProjection(m_Bounds.left, m_Bounds.right, m_Bounds.bottom, m_Bounds.top);
}
bool OrthographicCameraController::OnMouseScrolled(SDL_Event& e)
{
HZ_PROFILE_FUNCTION();
if (e.type == SDL_EVENT_MOUSE_WHEEL)
{
m_ZoomLevel += e.wheel.y * 0.25f;
m_ZoomLevel = std::max(m_ZoomLevel, 0.25f);
m_Bounds = { -m_AspectRatio * m_ZoomLevel,m_AspectRatio * m_ZoomLevel, -m_ZoomLevel, m_ZoomLevel };
m_Camera.SetProjection(m_Bounds.left, m_Bounds.right, m_Bounds.bottom, m_Bounds.top);
return false;
}
return true;
HZ_PROFILE_FUNCTION();
if (e.type == SDL_EVENT_MOUSE_WHEEL)
{
m_ZoomLevel -= e.wheel.y * 0.25f;
m_ZoomLevel = std::max(m_ZoomLevel, 0.25f);
CalculateView();
return false;
}
return true;
}
bool OrthographicCameraController::OnWindowResized(SDL_Event& e)
{
HZ_PROFILE_FUNCTION();
if (e.type == SDL_EVENT_WINDOW_RESIZED && (e.window.windowID == Application::Get().GetWindow().GetMainWindowID()))
{
m_AspectRatio = static_cast<float>(e.window.data1) / static_cast<float>(e.window.data2);
m_Bounds = { -m_AspectRatio * m_ZoomLevel,m_AspectRatio * m_ZoomLevel, -m_ZoomLevel, m_ZoomLevel };
m_Camera.SetProjection(m_Bounds.left, m_Bounds.right, m_Bounds.bottom, m_Bounds.top);
return false;
}
return true;
HZ_PROFILE_FUNCTION();
if (e.type == SDL_EVENT_WINDOW_RESIZED)
{
OnResize(static_cast<float>(e.window.data1), static_cast<float>(e.window.data2));
return false;
}
return true;
}
}

View File

@ -19,8 +19,8 @@ namespace Hazel
struct OrthographicCameraBounds
{
float left, right, bottom, top;
float GetWidth() { return right - left; }
float GetHeight() { return top - bottom; }
float GetWidth() const { return right - left; }
float GetHeight() const { return top - bottom; }
};
class HAZEL_API OrthographicCameraController
@ -29,11 +29,14 @@ namespace Hazel
OrthographicCameraController(float aspectRatio, bool isRotation = false);
void SetProjection(float left, float right, float bottom, float top);
void OnResize(const float width, const float height);
void OnUpdate(TimeStep ts);
void OnEvent(SDL_Event& e);
void SetZoomLevel(float level) {m_ZoomLevel = level;}
void CalculateView();
void SetZoomLevel(const float level) {m_ZoomLevel = level; CalculateView();}
float GetZoomLevel() const {return m_ZoomLevel;}
OrthographicCamera& GetCamera() {return m_Camera;}

View File

@ -127,6 +127,22 @@ namespace Hazel
s_Data.QuadVertexPosition[3] = {-0.5f, 0.5f, 0.0f, 1.0f};
}
void Renderer2D::BeginScene(const Camera& camera, const glm::mat4& tranform)
{
HZ_PROFILE_FUNCTION();
const glm::mat4 viewProjection = camera.GetProjection() * glm::inverse(tranform);
s_Data.TextureShader->Bind();
s_Data.TextureShader->SetMat4("u_ViewProjection", viewProjection);
s_Data.QuadIndexCount = 0;
s_Data.QuadVertexBufferPtr = s_Data.QuadVertexBufferBase;
s_Data.TextureSlotIndex = 1;
}
void Renderer2D::BeginScene(const OrthographicCamera& camera)
{
HZ_PROFILE_FUNCTION();
@ -182,7 +198,6 @@ namespace Hazel
s_Data.QuadVertexBufferPtr = s_Data.QuadVertexBufferBase;
s_Data.TextureSlotIndex = 1;
}
@ -198,26 +213,9 @@ namespace Hazel
{
FlushAndReset();
}
constexpr float texIndex = 0.0f;
constexpr float tilingFactor = 1.0f;
glm::vec2 texCoords[] = {{0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 1.0f}};
const glm::mat4 transform = glm::translate(glm::mat4(1.0f), position) * glm::scale(glm::mat4(1.0f), { size.x, size.y, 1.0f });
for (unsigned int i = 0; i < 4; i++)
{
s_Data.QuadVertexBufferPtr->Position = transform * s_Data.QuadVertexPosition[i];
s_Data.QuadVertexBufferPtr->Color = color;
s_Data.QuadVertexBufferPtr->TexCoord = texCoords[i];
s_Data.QuadVertexBufferPtr->TexIndex = texIndex;
s_Data.QuadVertexBufferPtr->TilingFactor = tilingFactor;
s_Data.QuadVertexBufferPtr++;
}
s_Data.QuadIndexCount += 6;
s_Data.Stats.QuadCount ++;
DrawQuad(transform, color);
}
void Renderer2D::DrawQuad(const glm::vec2& position, const glm::vec2& size, const Ref<Texture2D>& texture, const float tilingFactor, const glm::vec4& tintColor)
@ -233,41 +231,9 @@ namespace Hazel
FlushAndReset();
}
glm::vec2 texCoords[] = {{0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 1.0f}};
float textureIndex = 0.0f;
for (uint32_t i = 1; i < s_Data.TextureSlotIndex; i++)
{
if (*s_Data.TextureSlots[i].get() == *texture.get())
{
textureIndex = (float)i;
break;
}
}
if (textureIndex == 0.0f)
{
textureIndex = (float)s_Data.TextureSlotIndex;
s_Data.TextureSlots[s_Data.TextureSlotIndex] = texture;
s_Data.TextureSlotIndex++;
}
const glm::mat4 transform = glm::translate(glm::mat4(1.0f), position) * glm::scale(glm::mat4(1.0f), { size.x, size.y, 1.0f });
for (unsigned int i = 0; i < 4; i++)
{
s_Data.QuadVertexBufferPtr->Position = transform * s_Data.QuadVertexPosition[i];
s_Data.QuadVertexBufferPtr->Color = tintColor;
s_Data.QuadVertexBufferPtr->TexCoord = texCoords[i];
s_Data.QuadVertexBufferPtr->TexIndex = textureIndex;
s_Data.QuadVertexBufferPtr->TilingFactor = tilingFactor;
s_Data.QuadVertexBufferPtr++;
}
s_Data.QuadIndexCount += 6;
s_Data.Stats.QuadCount ++;
DrawQuad(transform, texture, tilingFactor, tintColor);
}
void Renderer2D::DrawQuad(const glm::vec2& position, const glm::vec2& size, const Ref<SubTexture2D>& subTexture, const float tilingFactor, const glm::vec4& tintColor)
@ -321,6 +287,77 @@ namespace Hazel
s_Data.Stats.QuadCount ++;
}
void Renderer2D::DrawQuad(const glm::mat4& transform, const glm::vec4& Color)
{
HZ_PROFILE_FUNCTION();
if (s_Data.QuadIndexCount >= s_Data.MaxIndices)
{
FlushAndReset();
}
glm::vec2 texCoords[] = {{0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 1.0f}};
const float textureIndex = 0.0f;
const float tilingFactor = 1.0f;
for (unsigned int i = 0; i < 4; i++)
{
s_Data.QuadVertexBufferPtr->Position = transform * s_Data.QuadVertexPosition[i];
s_Data.QuadVertexBufferPtr->Color = Color;
s_Data.QuadVertexBufferPtr->TexCoord = texCoords[i];
s_Data.QuadVertexBufferPtr->TexIndex = textureIndex;
s_Data.QuadVertexBufferPtr->TilingFactor = tilingFactor;
s_Data.QuadVertexBufferPtr++;
}
s_Data.QuadIndexCount += 6;
s_Data.Stats.QuadCount ++;
}
void Renderer2D::DrawQuad(const glm::mat4& transform, const Ref<Texture2D>& texture, float tilingFactor,
const glm::vec4& tintColor)
{
HZ_PROFILE_FUNCTION();
if (s_Data.QuadIndexCount >= s_Data.MaxIndices)
{
FlushAndReset();
}
glm::vec2 texCoords[] = {{0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 1.0f}};
float textureIndex = 0.0f;
for (uint32_t i = 1; i < s_Data.TextureSlotIndex; i++)
{
if (*s_Data.TextureSlots[i].get() == *texture.get())
{
textureIndex = (float)i;
break;
}
}
if (textureIndex == 0.0f)
{
textureIndex = (float)s_Data.TextureSlotIndex;
s_Data.TextureSlots[s_Data.TextureSlotIndex] = texture;
s_Data.TextureSlotIndex++;
}
for (unsigned int i = 0; i < 4; i++)
{
s_Data.QuadVertexBufferPtr->Position = transform * s_Data.QuadVertexPosition[i];
s_Data.QuadVertexBufferPtr->Color = tintColor;
s_Data.QuadVertexBufferPtr->TexCoord = texCoords[i];
s_Data.QuadVertexBufferPtr->TexIndex = textureIndex;
s_Data.QuadVertexBufferPtr->TilingFactor = tilingFactor;
s_Data.QuadVertexBufferPtr++;
}
s_Data.QuadIndexCount += 6;
s_Data.Stats.QuadCount ++;
}
void Renderer2D::DrawRotateQuad(const glm::vec2& position, const glm::vec2& size, const float rotation,
const glm::vec4& color)

View File

@ -5,6 +5,7 @@
#ifndef RENDERER2D_H
#define RENDERER2D_H
#include "Camera.h"
#include "OrthographicCamera.h"
#include "SubTexture2D.h"
#include "Texture.h"
@ -15,9 +16,19 @@ namespace Hazel
{
class HAZEL_API Renderer2D{
public:
struct RenderCamera
{
glm::mat4 projection;
glm::mat4 view;
};
static void Init();
static void BeginScene(const OrthographicCamera& camera);
static void BeginScene(const Camera& camera, const glm::mat4& tranform);
static void BeginScene(const OrthographicCamera& camera); // TODO: remove this
static void EndScene();
static void Flush();
@ -28,6 +39,9 @@ namespace Hazel
static void DrawQuad(const glm::vec2& position, const glm::vec2& size, const Ref<SubTexture2D>& subTexture, float tilingFactor = 1.0f, const glm::vec4& tintColor = glm::vec4(1.0f));
static void DrawQuad(const glm::vec3& position, const glm::vec2& size, const Ref<SubTexture2D>& subTexture, float tilingFactor = 1.0f, const glm::vec4& tintColor = glm::vec4(1.0f));
static void DrawQuad(const glm::mat4& transform, const glm::vec4& Color);
static void DrawQuad(const glm::mat4& transform, const Ref<Texture2D>& texture, float tilingFactor = 1.0f, const glm::vec4& tintColor = glm::vec4(1.0f));
static void DrawRotateQuad(const glm::vec2& position, const glm::vec2& size, float rotation, const glm::vec4& color);
static void DrawRotateQuad(const glm::vec3& position, const glm::vec2& size, float rotation, const glm::vec4& color);
static void DrawRotateQuad(const glm::vec2& position, const glm::vec2& size, float rotation, const Ref<Texture2D>& texture, float tilingFactor = 1.0f, const glm::vec4& tintColor = glm::vec4(1.0f));

View File

@ -23,12 +23,13 @@ namespace Hazel
};
public:
virtual ~RendererAPI() = default;
virtual void Init() = 0;
virtual void SetClearColor(const glm::vec4& color) = 0;
virtual void SetViewPort(uint32_t x, uint32_t y, uint32_t width, uint32_t height) = 0;
virtual void Clear() = 0;
virtual void DrawIndexed(const std::shared_ptr<Hazel::VertexArray>& vertexArray, uint32_t indexCount = 0) = 0;
virtual void DrawIndexed(const std::shared_ptr<VertexArray>& vertexArray, uint32_t indexCount = 0) = 0;
inline static API GetAPI() {return s_API; }

View File

@ -0,0 +1,61 @@
//
// Created by sfd on 25-5-28.
//
#include "ScenceCamera.h"
#include <glm/ext/matrix_clip_space.hpp>
namespace Hazel
{
ScenceCamera::ScenceCamera()
{
RecalculateProjection();
}
void ScenceCamera::SetOrthographic(const float size, const float nearClip, const float farClip)
{
m_ProjectionType = ProjectionType::Orthographic;
m_OrthographicSize = size;
m_OrthographicNear = nearClip;
m_OrthographicFar = farClip;
RecalculateProjection();
}
void ScenceCamera::SetPerspective(const float verticalFOV, const float nearClip, const float farClip)
{
m_ProjectionType = ProjectionType::Perspective;
m_PerspectiveFOV = verticalFOV;
m_PerspectiveNear = nearClip;
m_PerspectiveFar = farClip;
RecalculateProjection();
}
void ScenceCamera::SetViewPortSize(uint32_t width, uint32_t height)
{
m_AspectRatio = (float)width / (float)height;
RecalculateProjection();
}
void ScenceCamera::RecalculateProjection()
{
if (m_ProjectionType == ProjectionType::Perspective)
{
m_Projection = glm::perspective(m_PerspectiveFOV, m_AspectRatio, m_PerspectiveNear, m_PerspectiveFar);
}
else
{
const float orthoLeft = -m_OrthographicSize * m_AspectRatio * 0.5f;
const float orthoRight = m_OrthographicSize * m_AspectRatio * 0.5f;
const float orthoBottom = -m_OrthographicSize * 0.5f;
const float orthoTop = m_OrthographicSize * 0.5f;
m_Projection = glm::ortho(orthoLeft, orthoRight, orthoBottom, orthoTop, m_OrthographicNear,
m_OrthographicFar);
}
}
}

View File

@ -0,0 +1,64 @@
//
// Created by sfd on 25-5-28.
//
#ifndef SCENCECAMERA_H
#define SCENCECAMERA_H
#include "Camera.h"
namespace Hazel
{
class HAZEL_API ScenceCamera : public Camera
{
public:
enum class ProjectionType {Perspective = 0, Orthographic = 1};
public:
ScenceCamera();
virtual ~ScenceCamera() = default;
void SetOrthographic(const float size, const float nearClip, const float farClip);
void SetPerspective(const float verticalFOV, const float nearClip, const float farClip);
void SetViewPortSize(uint32_t width, uint32_t height);
// Perspective getters
float GetPerspectiveVerticalFOV() const { return m_PerspectiveFOV;};
float GetPerspectiveNearCLip() const { return m_PerspectiveNear; }
float GetPerspectiveFarCLip() const { return m_PerspectiveFar; }
// Perspective setters
void SetPerspectiveVerticalFOV(const float fov) { m_PerspectiveFOV = fov; RecalculateProjection(); }
void SetPerspectiveNearClip(const float nearClip) {m_PerspectiveNear = nearClip; RecalculateProjection();}
void SetPerspectiveFarClip(const float farClip) {m_PerspectiveFar = farClip; RecalculateProjection();}
// Orthographic getters
float GetOrthographicSize() const { return m_OrthographicSize; }
float GetOrthographicNearCLip() const { return m_OrthographicNear; }
float GetOrthographicFarCLip() const { return m_OrthographicFar; }
// Orthographic setters
void SetOrthographicSize(const float size) { m_OrthographicSize = size; RecalculateProjection(); }
void SetOrthographicNearClip(const float nearClip) {m_OrthographicNear = nearClip; RecalculateProjection();}
void SetOrthographicFarClip(const float farClip) {m_OrthographicFar = farClip; RecalculateProjection();}
ProjectionType GetProjectionType() const { return m_ProjectionType; }
void SetProjectionType(const ProjectionType type) { m_ProjectionType = type; RecalculateProjection(); }
private:
void RecalculateProjection();
private:
ProjectionType m_ProjectionType = ProjectionType::Orthographic;
float m_OrthographicSize = 10.0f;
float m_OrthographicNear = -1.0f, m_OrthographicFar = 1.0f;
float m_PerspectiveFOV = glm::radians(45.f);
float m_PerspectiveNear = 0.01f, m_PerspectiveFar = 1000.0f;
float m_AspectRatio = 1.0f;
};
}
#endif //SCENCECAMERA_H

View File

@ -22,7 +22,7 @@ namespace Hazel
HZ_CORE_ERROR("NONE is not Support!");
return nullptr;
case RendererAPI::API::OPENGL:
return std::make_shared<OpenGLVertexArray>();
return CreateRef<OpenGLVertexArray>();
default:
break;
}

View File

@ -0,0 +1,77 @@
//
// Created by sfd on 25-5-26.
//
#ifndef COMPONENTS_H
#define COMPONENTS_H
#include <Hazel/Renderer/Camera.h>
#include <Hazel/Renderer/ScenceCamera.h>
#include "ScriptableEntity.h"
#include "glm/glm.hpp"
namespace Hazel
{
struct TransformComponent
{
glm::mat4 Transform{1.0f};
TransformComponent() = default;
TransformComponent(const TransformComponent&) = default;
TransformComponent(const glm::mat4& transform) : Transform(transform)
{
}
operator glm::mat4&() { return Transform; }
operator const glm::mat4&() const { return Transform; }
};
struct SpriteRendererComponent
{
glm::vec4 Color{1.0f, 1.0f, 1.0f, 1.0f};
SpriteRendererComponent() = default;
SpriteRendererComponent(const SpriteRendererComponent&) = default;
SpriteRendererComponent(const glm::vec4& color) : Color(color)
{
}
};
struct TagComponent
{
std::string Tag;
TagComponent(const TagComponent&) = default;
TagComponent(const std::string& tag) : Tag(tag) {}
};
struct CameraComponent
{
ScenceCamera Camera;
bool Primary = true; //TODO: 考虑多相机如何同步, 考虑移至Scence中
bool FixedAspectRatio = false;
CameraComponent() = default;
CameraComponent(const CameraComponent&) = default;
};
struct NativeScriptComponent
{
ScriptableEntity* Instance = nullptr;
ScriptableEntity* (*InstantiateScript)();
void (*DestroyScript)(NativeScriptComponent*);
template<typename T>
void Bind()
{
InstantiateScript = []() { return static_cast<ScriptableEntity*>(new T()); };
DestroyScript = [](NativeScriptComponent* nsc) { delete nsc->Instance; nsc->Instance = nullptr; };
}
};
}
#endif //COMPONENTS_H

View File

@ -0,0 +1,13 @@
//
// Created by sfd on 25-5-28.
//
#include "Entity.h"
namespace Hazel
{
Entity::Entity(entt::entity handle, Scene* scene)
: m_EntityHandle(handle), m_Scene(scene)
{
}
}

View File

@ -0,0 +1,82 @@
//
// Created by sfd on 25-5-28.
//
#ifndef ENTITY_H
#define ENTITY_H
#include <Hazel/Core/Log.h>
#include "Scene.h"
namespace Hazel
{
class HAZEL_API Entity
{
public:
Entity() = default;
Entity(entt::entity handle, Scene* scene);
Entity(const Entity& other) = default;
template<typename T, typename... Args>
T& AddComponent(Args&&... args)
{
if (HasComponent<T>())
{
HZ_CORE_WARN("Entity already has this Component!");
return GetComponent<T>();
}
return m_Scene->m_Registry.emplace<T>(m_EntityHandle, std::forward<Args>(args)...);
}
template<typename T>
T& GetComponent()
{
if (!HasComponent<T>())
{
HZ_CORE_ERROR("Entity has no component!");
assert(-1);
}
return m_Scene->m_Registry.get<T>(m_EntityHandle);
}
template<typename T>
void RemoveComponent() const
{
if (!HasComponent<T>())
{
HZ_CORE_WARN("Entity has no component!");
return;
}
m_Scene->m_Registry.remove<T>(m_EntityHandle);
}
template<typename T>
bool HasComponent() const
{
if (auto entity = m_Scene->m_Registry.try_get<T>(m_EntityHandle))
{
return true;
}
return false;
}
explicit operator bool() const { return m_EntityHandle != entt::null; }
operator uint32_t() const { return static_cast<uint32_t>(m_EntityHandle); }
bool operator==(const Entity& other) const { return m_EntityHandle == other.m_EntityHandle && m_Scene == other.m_Scene; }
bool operator!=(const Entity& other) const { return !(*this==other); }
private:
entt::entity m_EntityHandle{ entt::null };
Scene* m_Scene = nullptr;
};
}
#endif //ENTITY_H

View File

@ -0,0 +1,105 @@
//
// Created by sfd on 25-5-26.
//
#include "Scene.h"
#include <Hazel/Renderer/Renderer2D.h>
#include "Components.h"
#include "Entity.h"
namespace Hazel
{
Scene::Scene()
{
}
Scene::~Scene()
{
}
Entity Scene::CreateEntity(const std::string& name)
{
Entity entity = {m_Registry.create(), this};
entity.AddComponent<TransformComponent>();
entity.AddComponent<TagComponent>(name.empty() ? "Entity" : name);
return entity;
}
void Scene::OnUpdate(TimeStep& ts)
{
// Update scripts
{
m_Registry.view<NativeScriptComponent>().each([=](auto entity, auto& nsc)
{
// TODO: move to Scene::OnScenePlay
if (!nsc.Instance)
{
nsc.Instance = nsc.InstantiateScript();
nsc.Instance->m_Entity = Entity{entity, this};
nsc.Instance->OnCreate();
}
nsc.Instance->OnUpdate(ts);
});
}
// Renderer 2D
Camera* mainCamera = nullptr;
glm::mat4* cameraTranform = nullptr;
{
for (auto view = m_Registry.view<TransformComponent, CameraComponent>(); const auto entity : view)
{
auto&& [transform, camera] = view.get<TransformComponent, CameraComponent>(entity);
if (camera.Primary)
{
mainCamera = &camera.Camera;
cameraTranform = &transform.Transform;
break;
}
}
}
if (mainCamera != nullptr)
{
Renderer2D::BeginScene(mainCamera->GetProjection(), *cameraTranform);
auto group = m_Registry.group<TransformComponent>(entt::get<SpriteRendererComponent>);
for (auto entity : group)
{
auto [transform, sprite] = group.get<TransformComponent, SpriteRendererComponent>(entity);
Renderer2D::DrawQuad(transform, sprite.Color);
}
Renderer2D::EndScene();
}
}
void Scene::OnViewportResize(uint32_t width, uint32_t height)
{
m_ViewportWidth = width;
m_ViewportHeight = height;
//Reisze our non-fixedAspectRatio Cameras
auto view = m_Registry.view<CameraComponent>();
for (auto entity : view)
{
auto& cameraComponent = view.get<CameraComponent>(entity);
if (!cameraComponent.FixedAspectRatio)
{
cameraComponent.Camera.SetViewPortSize(width, height);
}
}
}
}

View File

@ -0,0 +1,41 @@
//
// Created by sfd on 25-5-26.
//
#ifndef SCENE_H
#define SCENE_H
#include <Hazel/Core/TimeStep.h>
#include "entt.hpp"
#include "Hazel/Core/Core.h"
namespace Hazel
{
class Entity;
class HAZEL_API Scene {
public:
Scene();
~Scene();
Entity CreateEntity(const std::string& name = "");
void OnUpdate(TimeStep& ts);
void OnViewportResize(uint32_t width, uint32_t height);
private:
entt::registry m_Registry;
uint32_t m_ViewportWidth = 0, m_ViewportHeight = 0;
friend class Entity;
friend class SceneHierachyPanel;
};
}
#endif //SCENE_H

View File

@ -0,0 +1,5 @@
//
// Created by sfd on 25-5-28.
//
#include "ScriptableEntity.h"

View File

@ -0,0 +1,37 @@
//
// Created by sfd on 25-5-28.
//
#ifndef SCRIPTABLEENTITY_H
#define SCRIPTABLEENTITY_H
#include "Entity.h"
#include "Hazel/Core/Core.h"
namespace Hazel
{
class HAZEL_API ScriptableEntity{
public:
virtual ~ScriptableEntity() {}
template<typename T>
T& GetComponent()
{
return m_Entity.GetComponent<T>();
}
protected:
virtual void OnCreate(){}
virtual void OnDestroy(){}
virtual void OnUpdate(TimeStep ts) {}
private:
Entity m_Entity;
friend class Scene;
};
}
#endif //SCRIPTABLEENTITY_H

View File

@ -0,0 +1,109 @@
//
// Created by sfd on 25-5-25.
//
#include "OpenGLFrameBuffer.h"
#include <glad/glad.h>
#include <Hazel/Core/Log.h>
namespace Hazel
{
static constexpr uint32_t s_MaxFrameBufferSize = 8192;
OpenGLFrameBuffer::OpenGLFrameBuffer(const FrameBufferSpecification& spec)
: m_Specification(spec)
{
Invalidata();
}
OpenGLFrameBuffer::~OpenGLFrameBuffer()
{
glDeleteFramebuffers(1, &m_RendererID);
glDeleteTextures(1, &m_ColorAttachment);
glDeleteTextures(1, &m_DepthAttachment);
}
void OpenGLFrameBuffer::Bind()
{
glBindFramebuffer(GL_FRAMEBUFFER, m_RendererID);
}
void OpenGLFrameBuffer::UnBind()
{
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
void OpenGLFrameBuffer::Resize(const uint32_t width, const uint32_t height)
{
if (width == 0 || height == 0)
{
HZ_CORE_WARN("attempting to resize framebuffer to {0}x{1}", width, height);
}
m_Specification.Width = width > s_MaxFrameBufferSize ? s_MaxFrameBufferSize : width;
m_Specification.Height = height > s_MaxFrameBufferSize ? s_MaxFrameBufferSize : height;
Invalidata();
}
void OpenGLFrameBuffer::Invalidata()
{
if (m_RendererID)
{
glDeleteFramebuffers(1, &m_RendererID);
glDeleteTextures(1, &m_ColorAttachment);
glDeleteTextures(1, &m_DepthAttachment);
glViewport(0, 0, m_Specification.Width, m_Specification.Height);
}
glCreateFramebuffers(1, &m_RendererID);
glBindFramebuffer(GL_FRAMEBUFFER, m_RendererID);
glCreateTextures(GL_TEXTURE_2D, 1, &m_ColorAttachment);
glBindTexture(GL_TEXTURE_2D, m_ColorAttachment);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, m_Specification.Width, m_Specification.Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_ColorAttachment, 0);
glCreateTextures(GL_TEXTURE_2D, 1, &m_DepthAttachment);
glBindTexture(GL_TEXTURE_2D, m_DepthAttachment);
glTexStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH24_STENCIL8, m_Specification.Width, m_Specification.Height);
// glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, m_Specification.Width, m_Specification.Height, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, nullptr);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, m_DepthAttachment, 0);
{
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
switch(status) {
case GL_FRAMEBUFFER_COMPLETE:
break;
case GL_FRAMEBUFFER_UNDEFINED: /* 默认帧缓冲不存在 */
HZ_CORE_ERROR("默认缓冲不存在!"); break;
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: /* 附件不完整 */
HZ_CORE_ERROR("附件不完整!"); break;
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: /* 缺少颜色附件 */
HZ_CORE_ERROR("附件不完整!"); break;
case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: /* 颜色附件索引无效 */
HZ_CORE_ERROR("颜色附件索引无效!"); break;
case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: /* 读取缓冲区设置错误 */
HZ_CORE_ERROR("读取缓冲区设置错误!"); break;
case GL_FRAMEBUFFER_UNSUPPORTED: /* 格式组合不支持 */
HZ_CORE_ERROR("格式组合不支持!"); break;
case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: /* 多重采样不一致 */
HZ_CORE_ERROR("多重采样不一致!"); break;
case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS: /* 图层目标不完整 */
HZ_CORE_ERROR("图层目标不完整!"); break;
default: /* 未知错误 */
HZ_CORE_ERROR("未知错误!"); break;
}
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
}

View File

@ -0,0 +1,34 @@
//
// Created by sfd on 25-5-25.
//
#ifndef OPENGLFRAMEBUFFER_H
#define OPENGLFRAMEBUFFER_H
#include <Hazel/Renderer/FrameBuffer.h>
namespace Hazel
{
class OpenGLFrameBuffer : public FrameBuffer
{
public:
OpenGLFrameBuffer(const FrameBufferSpecification& spec);
virtual ~OpenGLFrameBuffer();
void Bind() override;
void UnBind() override;
virtual const FrameBufferSpecification& GetSpecification() const override { return m_Specification; }
virtual uint32_t GetColorAttachmentID() const override { return m_ColorAttachment; }
virtual void Resize(uint32_t width, uint32_t height) override;
void Invalidata();
private:
uint32_t m_RendererID = 0;
uint32_t m_ColorAttachment = 0, m_DepthAttachment = 0;
FrameBufferSpecification m_Specification;
};
}
#endif //OPENGLFRAMEBUFFER_H

View File

@ -21,8 +21,8 @@ namespace Hazel
Init(props);
}
Window* Window::Create(const WindowProps& props) {
return new WindowsWindow(props);
Scope<Window> Window::Create(const WindowProps& props) {
return CreateScope<WindowsWindow>(props);
}

21
Hazel/vendor/entt/LICENSE vendored Normal file
View File

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2017-2025 Michele Caini, author of EnTT
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copy of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copy or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

93963
Hazel/vendor/entt/entt.hpp vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -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)

View 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);
}
}
}

View 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

View 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();
}
}
}
}

View 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

View File

@ -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);
}

View File

@ -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;

View File

@ -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();
}