add render command queue

This commit is contained in:
2025-11-22 09:13:48 +08:00
parent 69bdaaec2e
commit 36f886b189
19 changed files with 616 additions and 43 deletions

View File

@ -32,10 +32,16 @@ set(LINK_LIBRARIES
if(WIN32)
list(APPEND LINK_LIBRARIES opengl32)
elseif(UNIX AND NOT APPLE)
list(APPEND LINK_LIBRARIES GL)
find_package(X11 REQUIRED)
list(APPEND LINK_LIBRARIES GL ${X11_LIBRARIES})
endif()
set(TARGET_INCLUDE_DIR
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>
${IMGUI_DIR}
)
# static library
set(STATIC_LIBRARY ${PROJECT_NAME}-static)
@ -47,8 +53,7 @@ target_compile_definitions(${STATIC_LIBRARY} PRIVATE
)
target_include_directories(${STATIC_LIBRARY} PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>
${TARGET_INCLUDE_DIR}
)
target_link_libraries(${STATIC_LIBRARY} PRIVATE
${LINK_LIBRARIES}
@ -73,7 +78,7 @@ target_compile_definitions(${SHARED_LIBRARY} PRIVATE
)
target_include_directories(${SHARED_LIBRARY} PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>
${TARGET_INCLUDE_DIR}
)
target_link_libraries(${SHARED_LIBRARY} PRIVATE
${LINK_LIBRARIES}

View File

@ -12,6 +12,7 @@
#include "Prism/Core/Events/Event.h"
#include "Prism/Core/Events/KeyEvent.h"
#include "Prism/Core/Events/MouseEvent.h"
#include "Prism/Renderer/Renderer.h"
#endif //PRISM_H

View File

@ -6,6 +6,7 @@
#include "Application.h"
#include "glad/glad.h"
#include "Prism/Renderer/Renderer.h"
namespace Prism
@ -25,6 +26,9 @@ namespace Prism
m_Window = std::unique_ptr<Window>(Window::Create());
m_Window->SetEventCallback(BIND_EVENT_FN(OnEvent));
m_ImGuiLayer = new ImGuiLayer("ImGui Layer");
PushOverlay(m_ImGuiLayer);
}
Application::~Application()
@ -37,12 +41,14 @@ namespace Prism
while (m_Running)
{
glClearColor(0.2, 0.2, 0.2, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
for (Layer* layer : m_LayerStack)
layer->OnUpdate();
Application* app = this;
PM_RENDER_1(app, { app->RenderImGui(); });
Renderer::Get().WaitAndRender();
m_Window->OnUpdate();
}
@ -62,6 +68,14 @@ namespace Prism
}
}
void Application::RenderImGui()
{
m_ImGuiLayer->Begin();
for (Layer* layer : m_LayerStack)
layer->OnImGuiRender();
m_ImGuiLayer->End();
}
void Application::PushLayer(Layer* layer)
{
m_LayerStack.PushLayer(layer);

View File

@ -8,6 +8,7 @@
#include "LayerStack.h"
#include "Window.h"
#include "Events/ApplicationEvent.h"
#include "ImGui/ImGuiLayer.h"
namespace Prism
{
@ -25,6 +26,8 @@ namespace Prism
virtual void OnEvent(Event& e);
void RenderImGui();
inline Window& GetWindow() { return *m_Window; }
inline static Application& Get() { return *s_Instance; }
@ -40,6 +43,7 @@ namespace Prism
bool m_Running = true;
LayerStack m_LayerStack;
ImGuiLayer* m_ImGuiLayer;
static Application* s_Instance;
};

View File

@ -11,8 +11,17 @@
#else
#define PRISM_API __declspec(dllimport)
#endif
// ImGui
#ifdef BUILD_PRISM_DLL
#define IMGUI_API __declspec(dllexport)
#else
#define IMGUI_API __declspec(dllimport)
#endif
#else
#define PRISM_API
#define IMGUI_API
#endif
#define BIT(x) (1 << x)
@ -32,5 +41,10 @@
#define PM_CORE_ASSERT(x, ...)
#endif
namespace Prism
{
using byte = unsigned char;
}
#endif //CORE_H

View File

@ -4,7 +4,6 @@
#include "ImGuiLayer.h"
#include "imgui.h"
#include "imgui_impl_opengl3.h"
#include "imgui_impl_glfw.h"
#include "GLFW/glfw3.h"
@ -28,6 +27,32 @@ namespace Prism
{
}
void ImGuiLayer::Begin()
{
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
}
void ImGuiLayer::End()
{
ImGuiIO& io = ImGui::GetIO();
Application& app = Application::Get();
io.DisplaySize = ImVec2(app.GetWindow().GetWidth(), app.GetWindow().GetHeight());
// Rendering
ImGui::Render();
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
{
GLFWwindow* backup_current_context = glfwGetCurrentContext();
ImGui::UpdatePlatformWindows();
ImGui::RenderPlatformWindowsDefault();
glfwMakeContextCurrent(backup_current_context);
}
}
void ImGuiLayer::OnAttach()
{
// Setup Dear ImGui context
@ -54,7 +79,7 @@ namespace Prism
}
Application& app = Application::Get();
GLFWwindow* window = (GLFWwindow*)app.GetWindow().GetNativeWindow();
const auto window = static_cast<GLFWwindow*>(app.GetWindow().GetNativeWindow());
// Setup Platform/Renderer bindings
ImGui_ImplGlfw_InitForOpenGL(window, true);
@ -69,31 +94,8 @@ namespace Prism
ImGui::DestroyContext();
}
void ImGuiLayer::OnUpdate()
void ImGuiLayer::OnImGuiRender()
{
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
static bool show_demo_window = true;
if (show_demo_window)
ImGui::ShowDemoWindow(&show_demo_window);
ImGuiIO& io = ImGui::GetIO();
Application& app = Application::Get();
io.DisplaySize = ImVec2(app.GetWindow().GetWidth(), app.GetWindow().GetHeight());
// Rendering
ImGui::Render();
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
{
GLFWwindow* backup_current_context = glfwGetCurrentContext();
ImGui::UpdatePlatformWindows();
ImGui::RenderPlatformWindowsDefault();
glfwMakeContextCurrent(backup_current_context);
}
}
}

View File

@ -5,10 +5,9 @@
#ifndef IMGUILAYER_H
#define IMGUILAYER_H
#include "imgui.h"
#include "Prism/Core/Layer.h"
#include "Prism/Core/Events/ApplicationEvent.h"
#include "Prism/Core/Events/KeyEvent.h"
#include "Prism/Core/Events/MouseEvent.h"
namespace Prism
{
@ -17,12 +16,14 @@ namespace Prism
public:
ImGuiLayer();
explicit ImGuiLayer(const std::string& name);
virtual ~ImGuiLayer() override;
void Begin();
void End();
virtual void OnAttach() override;
virtual void OnDetach() override;
virtual void OnUpdate() override;
virtual void OnImGuiRender() override;
private:
float m_Time = 0.0f;

View File

@ -19,6 +19,7 @@ namespace Prism
virtual void OnAttach() {}
virtual void OnDetach() {}
virtual void OnUpdate() {}
virtual void OnImGuiRender() {}
virtual void OnEvent(Event& e) {}
inline const std::string& GetName() const { return m_DebugName; }

View File

@ -10,7 +10,6 @@ namespace Prism
{
LayerStack::LayerStack()
{
m_LayerIterator = m_Layers.begin();
}
LayerStack::~LayerStack()
@ -21,7 +20,8 @@ namespace Prism
void LayerStack::PushLayer(Layer* layer)
{
m_LayerIterator = m_Layers.emplace(m_LayerIterator, layer);
m_Layers.emplace(m_Layers.begin() + m_LayerInsertIndex, layer);
m_LayerInsertIndex++;
}
void LayerStack::PushOverlay(Layer* layer)
@ -35,7 +35,7 @@ namespace Prism
if (it != m_Layers.end())
{
m_Layers.erase(it);
m_LayerIterator--;
m_LayerInsertIndex--;
}
}

View File

@ -25,7 +25,7 @@ namespace Prism
std::vector<Layer*>::iterator end() { return m_Layers.end(); }
private:
std::vector<Layer*> m_Layers;
std::vector<Layer*>::iterator m_LayerIterator;
unsigned int m_LayerInsertIndex = 0;
};
}

View File

@ -0,0 +1,24 @@
//
// Created by sfd on 25-11-21.
//
#include "Prism/Renderer/RendererAPI.h"
#include "glad/glad.h"
namespace Prism
{
void RendererAPI::Clear(const float r, const float g, const float b, const float a)
{
glClearColor(r, g, b, a);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
void RendererAPI::SetClearColor(const float r, const float g, const float b, const float a)
{
glClearColor(r, g, b, a);
}
}

View File

@ -0,0 +1,61 @@
//
// Created by sfd on 25-11-21.
//
#include "RenderCommandQueue.h"
#include "Prism/Core/Core.h"
#include "Prism/Core/Log.h"
#define PM_RENDER_TRACE(...) PM_CORE_TRACE(__VA_ARGS__)
namespace Prism
{
RenderCommandQueue::RenderCommandQueue()
{
m_CommandBuffer = new unsigned char[10 * 1024 * 1024]; // 10mb buffer
m_CommandBufferPtr = m_CommandBuffer;
memset(m_CommandBuffer, 0, 10 * 1024 * 1024);
}
RenderCommandQueue::~RenderCommandQueue()
{
delete[] m_CommandBuffer;
}
void* RenderCommandQueue::Allocate(RenderCommandFn func, unsigned int size)
{
*(RenderCommandFn*)m_CommandBufferPtr = func;
m_CommandBufferPtr += sizeof(RenderCommandFn);
*(int*)m_CommandBufferPtr = size;
m_CommandBufferPtr += sizeof(unsigned int);
void* memory = m_CommandBufferPtr;
m_CommandBufferPtr += size;
m_CommandCount ++;
return memory;
}
void RenderCommandQueue::Execute()
{
PM_RENDER_TRACE("RenderCommandQueue::Execute -- {0} commands, {1} bytes", m_CommandCount, (m_CommandBufferPtr - m_CommandBuffer));
byte* buffer = m_CommandBuffer;
for (unsigned i = 0 ; i < m_CommandCount ; i++)
{
RenderCommandFn function = *(RenderCommandFn*)(buffer);
buffer += sizeof(RenderCommandFn);
unsigned int size = *(unsigned int*)buffer;
buffer += sizeof(unsigned int);
function(buffer);
buffer += size;
}
m_CommandBufferPtr = m_CommandBuffer;
m_CommandCount = 0;
}
}

View File

@ -0,0 +1,30 @@
//
// Created by sfd on 25-11-21.
//
#ifndef RENDERCOMMANDQUEUE_H
#define RENDERCOMMANDQUEUE_H
#include <functional>
namespace Prism
{
class PRISM_API RenderCommandQueue
{
public:
typedef void(*RenderCommandFn)(void*);
RenderCommandQueue();
~RenderCommandQueue();
void* Allocate(RenderCommandFn func, unsigned int size);
void Execute();
private:
unsigned char* m_CommandBuffer = nullptr;
unsigned char* m_CommandBufferPtr = nullptr;
unsigned int m_CommandCount = 0;
};
}
#endif //RENDERCOMMANDQUEUE_H

View File

@ -0,0 +1,43 @@
//
// Created by sfd on 25-11-21.
//
#include "Renderer.h"
#include "RendererAPI.h"
namespace Prism
{
Renderer* Renderer::s_Instance = new Renderer();
void Renderer::Clear()
{
}
void Renderer::Clear(float r, float g, float b, float a)
{
PM_RENDER_4(r, g, b, a, {
RendererAPI::Clear(r, g, b, a);
});
}
void Renderer::SetClearColor(float r, float g, float b, float a)
{
}
void Renderer::ClearMagenta()
{
Clear(1, 0, 1);
}
void Renderer::Init()
{
s_Instance = new Renderer();
}
void Renderer::WaitAndRender()
{
s_Instance->m_CommandQueue.Execute();
}
}

View File

@ -0,0 +1,155 @@
//
// Created by sfd on 25-11-21.
//
#ifndef RENDERER_H
#define RENDERER_H
#include "RenderCommandQueue.h"
#include "Prism/Core/Application.h"
namespace Prism
{
class PRISM_API Renderer
{
public:
typedef void(*RenderCommandFn)(void*);
static void Clear();
static void Clear(float r, float g, float b, float a = 1.0f);
static void SetClearColor(float r, float g, float b, float a);
// test
static void ClearMagenta();
void Init();
static void* Submit(const RenderCommandFn func, const unsigned int size)
{
return s_Instance->m_CommandQueue.Allocate(func, size);
}
void WaitAndRender();
inline static Renderer& Get() { return *s_Instance; }
private:
static Renderer* s_Instance;
// static inline Renderer* s_Instance = nullptr;
RenderCommandQueue m_CommandQueue;
};
#define PM_RENDER_PASTE2(a, b) a ## b
#define PM_RENDER_PASTE(a, b) PM_RENDER_PASTE2(a, b)
#define PM_RENDER_UNIQUE(x) PM_RENDER_PASTE(x, __LINE__)
#define PM_RENDER(code) \
struct PM_RENDER_UNIQUE(PMRenderCommand) \
{\
static void Execute(void*)\
{\
code\
}\
};\
{\
auto mem = RenderCommandQueue::Submit(sizeof(PM_RENDER_UNIQUE(PMRenderCommand)), PM_RENDER_UNIQUE(PMRenderCommand)::Execute);\
new (mem) PM_RENDER_UNIQUE(PMRenderCommand)();\
}\
#define PM_RENDER_1(arg0, code) \
do{\
struct PM_RENDER_UNIQUE(PMRenderCommand) \
{\
PM_RENDER_UNIQUE(PMRenderCommand)(typename ::std::remove_const<typename ::std::remove_reference<decltype(arg0)>::type>::type arg0) \
: m_arg0(arg0) {}\
\
static void Execute(void* self)\
{\
auto& arg0 = ((PM_RENDER_UNIQUE(PMRenderCommand)*)self)->m_arg0;\
code\
}\
\
typename ::std::remove_const<typename ::std::remove_reference<decltype(arg0)>::type>::type m_arg0;\
};\
{\
auto mem = ::Prism::Renderer::Submit(PM_RENDER_UNIQUE(PMRenderCommand)::Execute, sizeof(PM_RENDER_UNIQUE(PMRenderCommand)));\
new (mem) PM_RENDER_UNIQUE(PMRenderCommand)(arg0);\
} } while(0)
#define PM_RENDER_2(arg0, arg1, code) \
struct PM_RENDER_UNIQUE(PMRenderCommand) \
{\
PM_RENDER_UNIQUE(PMRenderCommand)(typename ::std::remove_const<typename ::std::remove_reference<decltype(arg0)>::type>::type arg0,\
typename ::std::remove_const<typename ::std::remove_reference<decltype(arg1)>::type>::type arg1) \
: m_arg0(arg0), m_arg1(arg1) {}\
\
static void Execute(void* self)\
{\
auto& arg0 = ((PM_RENDER_UNIQUE(PMRenderCommand)*)self)->m_arg0;\
auto& arg1 = ((PM_RENDER_UNIQUE(PMRenderCommand)*)self)->m_arg1;\
code\
}\
\
typename ::std::remove_const<typename ::std::remove_reference<decltype(arg0)>::type>::type m_arg0;\
typename ::std::remove_const<typename ::std::remove_reference<decltype(arg1)>::type>::type m_arg1;\
};\
{\
auto mem = ::Prism::Renderer::Submit(PM_RENDER_UNIQUE(PMRenderCommand)::Execute, sizeof(PM_RENDER_UNIQUE(PMRenderCommand)));\
new (mem) PM_RENDER_UNIQUE(PMRenderCommand)(arg0, arg1);\
}\
#define PM_RENDER_3(arg0, arg1, arg2, code) \
struct PM_RENDER_UNIQUE(PMRenderCommand) \
{\
PM_RENDER_UNIQUE(PMRenderCommand)(typename ::std::remove_const<typename ::std::remove_reference<decltype(arg0)>::type>::type arg0,\
typename ::std::remove_const<typename ::std::remove_reference<decltype(arg1)>::type>::type arg1,\
typename ::std::remove_const<typename ::std::remove_reference<decltype(arg2)>::type>::type arg2) \
: m_arg0(arg0), m_arg1(arg1), m_arg2(arg2) {}\
\
static void Execute(void* self)\
{\
auto& arg0 = ((PM_RENDER_UNIQUE(PMRenderCommand)*)self)->m_arg0;\
auto& arg1 = ((PM_RENDER_UNIQUE(PMRenderCommand)*)self)->m_arg1;\
auto& arg2 = ((PM_RENDER_UNIQUE(PMRenderCommand)*)self)->m_arg2;\
code\
}\
\
typename ::std::remove_const<typename ::std::remove_reference<decltype(arg0)>::type>::type m_arg0;\
typename ::std::remove_const<typename ::std::remove_reference<decltype(arg1)>::type>::type m_arg1;\
typename ::std::remove_const<typename ::std::remove_reference<decltype(arg2)>::type>::type m_arg2;\
};\
{\
auto mem = ::Prism::Renderer::Submit(PM_RENDER_UNIQUE(PMRenderCommand)::Execute, sizeof(PM_RENDER_UNIQUE(PMRenderCommand)));\
new (mem) PM_RENDER_UNIQUE(PMRenderCommand)(arg0, arg1, arg2);\
}\
#define PM_RENDER_4(arg0, arg1, arg2, arg3, code) \
struct PM_RENDER_UNIQUE(PMRenderCommand) \
{\
PM_RENDER_UNIQUE(PMRenderCommand)(typename ::std::remove_const<typename ::std::remove_reference<decltype(arg0)>::type>::type arg0,\
typename ::std::remove_const<typename ::std::remove_reference<decltype(arg1)>::type>::type arg1,\
typename ::std::remove_const<typename ::std::remove_reference<decltype(arg2)>::type>::type arg2,\
typename ::std::remove_const<typename ::std::remove_reference<decltype(arg3)>::type>::type arg3)\
: m_arg0(arg0), m_arg1(arg1), m_arg2(arg2), m_arg3(arg3) {}\
\
static void Execute(void* self)\
{\
auto& arg0 = ((PM_RENDER_UNIQUE(PMRenderCommand)*)self)->m_arg0;\
auto& arg1 = ((PM_RENDER_UNIQUE(PMRenderCommand)*)self)->m_arg1;\
auto& arg2 = ((PM_RENDER_UNIQUE(PMRenderCommand)*)self)->m_arg2;\
auto& arg3 = ((PM_RENDER_UNIQUE(PMRenderCommand)*)self)->m_arg3;\
code\
}\
\
typename ::std::remove_const<typename ::std::remove_reference<decltype(arg0)>::type>::type m_arg0;\
typename ::std::remove_const<typename ::std::remove_reference<decltype(arg1)>::type>::type m_arg1;\
typename ::std::remove_const<typename ::std::remove_reference<decltype(arg2)>::type>::type m_arg2;\
typename ::std::remove_const<typename ::std::remove_reference<decltype(arg3)>::type>::type m_arg3;\
};\
{\
auto mem = ::Prism::Renderer::Submit(PM_RENDER_UNIQUE(PMRenderCommand)::Execute, sizeof(PM_RENDER_UNIQUE(PMRenderCommand)));\
new (mem) PM_RENDER_UNIQUE(PMRenderCommand)(arg0, arg1, arg2, arg3);\
}
}
#endif //RENDERER_H

View File

@ -0,0 +1,18 @@
//
// Created by sfd on 25-11-21.
//
#ifndef RENDERERAPI_H
#define RENDERERAPI_H
namespace Prism
{
class PRISM_API RendererAPI
{
public:
static void Clear(float r, float g, float b, float a);
static void SetClearColor(float r, float g, float b, float a);
};
}
#endif //RENDERERAPI_H

View File

@ -0,0 +1,172 @@
//
// Created by sfd on 25-11-21.
//
#include "DemoLayer.h"
#include "Prism/Renderer/Renderer.h"
static void ImGuiShowHelpMarker(const char* desc)
{
ImGui::TextDisabled("(?)");
if (ImGui::IsItemHovered())
{
ImGui::BeginTooltip();
ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
ImGui::TextUnformatted(desc);
ImGui::PopTextWrapPos();
ImGui::EndTooltip();
}
}
DemoLayer::DemoLayer()
{
}
DemoLayer::~DemoLayer()
{
}
void DemoLayer::OnAttach()
{
}
void DemoLayer::OnDetach()
{
}
void DemoLayer::OnUpdate()
{
Prism::Renderer::Clear(m_ClearColor[0], m_ClearColor[1], m_ClearColor[2], m_ClearColor[3]);
}
void DemoLayer::OnImGuiRender()
{
static bool show_demo_window = true;
if (show_demo_window)
ImGui::ShowDemoWindow(&show_demo_window);
ImGui::Begin("GameLayer");
ImGui::ColorEdit4("Clear Color", m_ClearColor);
ImGui::End();
#if ENABLE_DOCKSPACE
static bool p_open = 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", &p_open, window_flags);
if (!opt_padding)
ImGui::PopStyleVar();
if (opt_fullscreen)
ImGui::PopStyleVar(2);
// Submit the DockSpace
// REMINDER: THIS IS A DEMO FOR ADVANCED USAGE OF DockSpace()!
// MOST REGULAR APPLICATIONS WILL SIMPLY WANT TO CALL DockSpaceOverViewport(). READ COMMENTS ABOVE.
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);
}
// Show demo options and help
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("Flag: NoDockingOverCentralNode", "", (dockspace_flags & ImGuiDockNodeFlags_NoDockingOverCentralNode) != 0)) { dockspace_flags ^= ImGuiDockNodeFlags_NoDockingOverCentralNode; }
if (ImGui::MenuItem("Flag: NoDockingSplit", "", (dockspace_flags & ImGuiDockNodeFlags_NoDockingSplit) != 0)) { dockspace_flags ^= ImGuiDockNodeFlags_NoDockingSplit; }
if (ImGui::MenuItem("Flag: NoUndocking", "", (dockspace_flags & ImGuiDockNodeFlags_NoUndocking) != 0)) { dockspace_flags ^= ImGuiDockNodeFlags_NoUndocking; }
if (ImGui::MenuItem("Flag: NoResize", "", (dockspace_flags & ImGuiDockNodeFlags_NoResize) != 0)) { dockspace_flags ^= ImGuiDockNodeFlags_NoResize; }
if (ImGui::MenuItem("Flag: AutoHideTabBar", "", (dockspace_flags & ImGuiDockNodeFlags_AutoHideTabBar) != 0)) { dockspace_flags ^= ImGuiDockNodeFlags_AutoHideTabBar; }
if (ImGui::MenuItem("Flag: PassthruCentralNode", "", (dockspace_flags & ImGuiDockNodeFlags_PassthruCentralNode) != 0, opt_fullscreen)) { dockspace_flags ^= ImGuiDockNodeFlags_PassthruCentralNode; }
ImGui::Separator();
if (ImGui::MenuItem("Close", NULL, false, p_open != false))
p_open = false;
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Help"))
{
ImGui::TextUnformatted(
"This demo has nothing to do with enabling docking!" "\n"
"This demo only demonstrate the use of ImGui::DockSpace() which allows you to manually\ncreate a docking node _within_ another window." "\n"
"Most application can simply call ImGui::DockSpaceOverViewport() and be done with it.");
ImGui::Separator();
ImGui::TextUnformatted("When docking is enabled, you can ALWAYS dock MOST window into another! Try it now!" "\n"
"- Drag from window title bar or their tab to dock/undock." "\n"
"- Drag from window menu button (upper-left button) to undock an entire node (all windows)." "\n"
"- Hold SHIFT to disable docking (if io.ConfigDockingWithShift == false, default)" "\n"
"- Hold SHIFT to enable docking (if io.ConfigDockingWithShift == true)");
ImGui::Separator();
ImGui::TextUnformatted("More details:"); ImGui::Bullet(); ImGui::SameLine(); ImGui::TextLinkOpenURL("Docking Wiki page", "https://github.com/ocornut/imgui/wiki/Docking");
ImGui::BulletText("Read comments in ShowExampleAppDockSpace()");
ImGui::EndMenu();
}
ImGuiShowHelpMarker(
"You can _always_ dock _any_ window into another by holding the SHIFT key while moving a window. Try it now!" "\n"
"This demo app has nothing to do with it!" "\n\n"
"This demo app only demonstrate the use of ImGui::DockSpace() which allows you to manually create a docking node _within_ another window. This is useful so you can decorate your main application window (e.g. with a menu bar)." "\n\n"
"ImGui::DockSpace() comes with one hard constraint: it needs to be submitted _before_ any window which may be docked into it. Therefore, if you use a dock spot as the central point of your application, you'll probably want it to be part of the very first window you are submitting to imgui every frame." "\n\n"
"(NB: because of this constraint, the implicit \"Debug\" window can not be docked into an explicit DockSpace() node, because that window is submitted as part of the NewFrame() call. An easy workaround is that you can create your own implicit \"Debug##2\" window after calling DockSpace() and leave it in the window stack for anyone to use.)"
);
ImGui::EndMenuBar();
}
ImGui::End();
#endif
}
void DemoLayer::OnEvent(Prism::Event& e)
{
Layer::OnEvent(e);
}

View File

@ -0,0 +1,28 @@
//
// Created by sfd on 25-11-21.
//
#ifndef DEMOLAYER_H
#define DEMOLAYER_H
#include "Prism/Core/Layer.h"
class DemoLayer : public Prism::Layer
{
public:
DemoLayer();
virtual ~DemoLayer();
virtual void OnAttach() override;
virtual void OnDetach() override;
virtual void OnUpdate() override;
virtual void OnImGuiRender() override;
virtual void OnEvent(Prism::Event& e) override;
private:
float m_ClearColor[4] = { 0.2f, 0.2f, 0.2f, 1.0f };
};
#endif //DEMOLAYER_H

View File

@ -3,6 +3,7 @@
//
#include "Layer/DemoLayer.h"
#include "Prism/Core/Application.h"
#include "Prism/Core/EntryPoint.h"
#include "Prism/Core/ImGui/ImGuiLayer.h"
@ -16,8 +17,7 @@ public:
virtual void OnInit() override
{
PushLayer(new Prism::ImGuiLayer());
PushLayer(new Prism::ImGuiLayer("Second Layer"));
PushLayer(new DemoLayer());
}
};