添加D3D12 ImGui编辑器UI框架
This commit is contained in:
62
ui/CMakeLists.txt
Normal file
62
ui/CMakeLists.txt
Normal file
@@ -0,0 +1,62 @@
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
project(XCVolumeRendererUI2 VERSION 1.0 LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
add_definitions(-DUNICODE -D_UNICODE)
|
||||
add_definitions(-DIMGUI_ENABLE_DOCKING)
|
||||
|
||||
include(FetchContent)
|
||||
|
||||
FetchContent_Declare(
|
||||
imgui
|
||||
GIT_REPOSITORY https://github.com/ocornut/imgui.git
|
||||
GIT_TAG docking
|
||||
GIT_SHALLOW TRUE
|
||||
)
|
||||
|
||||
FetchContent_MakeAvailable(imgui)
|
||||
|
||||
set(IMGUI_SOURCES
|
||||
${imgui_SOURCE_DIR}/imgui.cpp
|
||||
${imgui_SOURCE_DIR}/imgui_demo.cpp
|
||||
${imgui_SOURCE_DIR}/imgui_draw.cpp
|
||||
${imgui_SOURCE_DIR}/imgui_tables.cpp
|
||||
${imgui_SOURCE_DIR}/imgui_widgets.cpp
|
||||
${imgui_SOURCE_DIR}/backends/imgui_impl_win32.cpp
|
||||
${imgui_SOURCE_DIR}/backends/imgui_impl_dx12.cpp
|
||||
)
|
||||
|
||||
add_executable(${PROJECT_NAME} WIN32
|
||||
src/main.cpp
|
||||
src/Application.cpp
|
||||
src/Theme.cpp
|
||||
src/panels/Panel.cpp
|
||||
src/panels/MenuBar.cpp
|
||||
src/panels/HierarchyPanel.cpp
|
||||
src/panels/SceneViewPanel.cpp
|
||||
src/panels/InspectorPanel.cpp
|
||||
src/panels/ConsolePanel.cpp
|
||||
src/panels/ProjectPanel.cpp
|
||||
${IMGUI_SOURCES}
|
||||
)
|
||||
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
${imgui_SOURCE_DIR}
|
||||
${imgui_SOURCE_DIR}/backends
|
||||
)
|
||||
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE UNICODE _UNICODE)
|
||||
target_compile_options(${PROJECT_NAME} PRIVATE /utf-8 /MT)
|
||||
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE
|
||||
d3d12.lib
|
||||
dxgi.lib
|
||||
d3dcompiler.lib
|
||||
)
|
||||
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES
|
||||
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/bin"
|
||||
)
|
||||
304
ui/src/Application.cpp
Normal file
304
ui/src/Application.cpp
Normal file
@@ -0,0 +1,304 @@
|
||||
#include "Application.h"
|
||||
#include <imgui_impl_win32.h>
|
||||
#include <imgui_impl_dx12.h>
|
||||
#include <imgui_internal.h>
|
||||
#include <stdio.h>
|
||||
|
||||
extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
namespace UI {
|
||||
|
||||
Application& Application::Get() {
|
||||
static Application instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
bool Application::Initialize(HWND hwnd) {
|
||||
m_hwnd = hwnd;
|
||||
|
||||
if (!CreateDevice()) {
|
||||
MessageBoxW(hwnd, L"Failed to create D3D12 device", L"Error", MB_OK | MB_ICONERROR);
|
||||
return false;
|
||||
}
|
||||
if (!CreateRenderTarget()) {
|
||||
MessageBoxW(hwnd, L"Failed to create render target", L"Error", MB_OK | MB_ICONERROR);
|
||||
return false;
|
||||
}
|
||||
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGui::CreateContext();
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
|
||||
|
||||
unsigned char* pixels;
|
||||
int width, height;
|
||||
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
|
||||
|
||||
ApplyUnityDarkTheme();
|
||||
|
||||
ImGui_ImplWin32_Init(hwnd);
|
||||
ImGui_ImplDX12_Init(m_device, 3, DXGI_FORMAT_R8G8B8A8_UNORM, m_srvHeap,
|
||||
m_srvHeap->GetCPUDescriptorHandleForHeapStart(),
|
||||
m_srvHeap->GetGPUDescriptorHandleForHeapStart());
|
||||
|
||||
m_menuBar = std::make_unique<MenuBar>();
|
||||
m_hierarchyPanel = std::make_unique<HierarchyPanel>();
|
||||
m_sceneViewPanel = std::make_unique<SceneViewPanel>();
|
||||
m_inspectorPanel = std::make_unique<InspectorPanel>();
|
||||
m_consolePanel = std::make_unique<ConsolePanel>();
|
||||
m_projectPanel = std::make_unique<ProjectPanel>();
|
||||
|
||||
m_inspectorPanel->SetHierarchyPanel(m_hierarchyPanel.get());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Application::Shutdown() {
|
||||
ImGui_ImplDX12_Shutdown();
|
||||
ImGui_ImplWin32_Shutdown();
|
||||
ImGui::DestroyContext();
|
||||
|
||||
CleanupRenderTarget();
|
||||
|
||||
if (m_fence) m_fence->Release();
|
||||
if (m_commandList) m_commandList->Release();
|
||||
if (m_commandAllocator) m_commandAllocator->Release();
|
||||
if (m_commandQueue) m_commandQueue->Release();
|
||||
if (m_rtvHeap) m_rtvHeap->Release();
|
||||
if (m_srvHeap) m_srvHeap->Release();
|
||||
if (m_swapChain) m_swapChain->Release();
|
||||
if (m_device) m_device->Release();
|
||||
}
|
||||
|
||||
void Application::Render() {
|
||||
ImGui_ImplDX12_NewFrame();
|
||||
ImGui_ImplWin32_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
|
||||
SetupDockspace();
|
||||
RenderUI();
|
||||
|
||||
ImGui::Render();
|
||||
|
||||
m_frameIndex = m_swapChain->GetCurrentBackBufferIndex();
|
||||
m_commandAllocator->Reset();
|
||||
m_commandList->Reset(m_commandAllocator, nullptr);
|
||||
|
||||
D3D12_RESOURCE_BARRIER barrier = {};
|
||||
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
||||
barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
|
||||
barrier.Transition.pResource = m_renderTargets[m_frameIndex];
|
||||
barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT;
|
||||
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET;
|
||||
barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
|
||||
m_commandList->ResourceBarrier(1, &barrier);
|
||||
|
||||
float clearColor[4] = { 0.12f, 0.12f, 0.12f, 1.0f };
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = m_rtvHeap->GetCPUDescriptorHandleForHeapStart();
|
||||
rtvHandle.ptr += m_frameIndex * m_rtvDescriptorSize;
|
||||
m_commandList->ClearRenderTargetView(rtvHandle, clearColor, 0, nullptr);
|
||||
m_commandList->OMSetRenderTargets(1, &rtvHandle, FALSE, nullptr);
|
||||
|
||||
ID3D12DescriptorHeap* heaps[] = { m_srvHeap };
|
||||
m_commandList->SetDescriptorHeaps(1, heaps);
|
||||
|
||||
ImGui_ImplDX12_RenderDrawData(ImGui::GetDrawData(), m_commandList);
|
||||
|
||||
barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET;
|
||||
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT;
|
||||
m_commandList->ResourceBarrier(1, &barrier);
|
||||
|
||||
m_commandList->Close();
|
||||
ID3D12CommandList* cmdLists[] = { m_commandList };
|
||||
m_commandQueue->ExecuteCommandLists(1, cmdLists);
|
||||
|
||||
m_swapChain->Present(1, 0);
|
||||
|
||||
m_fenceValue++;
|
||||
m_commandQueue->Signal(m_fence, m_fenceValue);
|
||||
if (m_fence->GetCompletedValue() < m_fenceValue) {
|
||||
m_fence->SetEventOnCompletion(m_fenceValue, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void Application::OnResize(int width, int height) {
|
||||
if (width <= 0 || height <= 0) return;
|
||||
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
|
||||
CleanupRenderTarget();
|
||||
|
||||
if (m_swapChain) {
|
||||
DXGI_SWAP_CHAIN_DESC desc;
|
||||
m_swapChain->GetDesc(&desc);
|
||||
m_swapChain->ResizeBuffers(3, width, height, desc.BufferDesc.Format, desc.Flags);
|
||||
}
|
||||
|
||||
CreateRenderTarget();
|
||||
}
|
||||
|
||||
bool Application::CreateDevice() {
|
||||
HRESULT hr = D3D12CreateDevice(nullptr, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_device));
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
D3D12_COMMAND_QUEUE_DESC queueDesc = {};
|
||||
queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
|
||||
queueDesc.Priority = 0;
|
||||
queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
|
||||
queueDesc.NodeMask = 0;
|
||||
hr = m_device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&m_commandQueue));
|
||||
if (FAILED(hr)) return false;
|
||||
|
||||
hr = m_device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&m_commandAllocator));
|
||||
if (FAILED(hr)) return false;
|
||||
|
||||
hr = m_device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, m_commandAllocator, nullptr, IID_PPV_ARGS(&m_commandList));
|
||||
if (FAILED(hr)) return false;
|
||||
m_commandList->Close();
|
||||
|
||||
hr = m_device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&m_fence));
|
||||
if (FAILED(hr)) return false;
|
||||
|
||||
IDXGIFactory4* factory = nullptr;
|
||||
hr = CreateDXGIFactory1(IID_PPV_ARGS(&factory));
|
||||
if (FAILED(hr)) return false;
|
||||
|
||||
DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {};
|
||||
swapChainDesc.BufferCount = 3;
|
||||
swapChainDesc.Width = m_width;
|
||||
swapChainDesc.Height = m_height;
|
||||
swapChainDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
|
||||
swapChainDesc.SampleDesc.Count = 1;
|
||||
|
||||
IDXGISwapChain1* swapChain1 = nullptr;
|
||||
hr = factory->CreateSwapChainForHwnd(m_commandQueue, m_hwnd, &swapChainDesc, nullptr, nullptr, &swapChain1);
|
||||
factory->Release();
|
||||
if (FAILED(hr)) return false;
|
||||
|
||||
hr = swapChain1->QueryInterface(IID_PPV_ARGS(&m_swapChain));
|
||||
swapChain1->Release();
|
||||
if (FAILED(hr)) return false;
|
||||
|
||||
D3D12_DESCRIPTOR_HEAP_DESC rtvDesc = {};
|
||||
rtvDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
|
||||
rtvDesc.NumDescriptors = 3;
|
||||
rtvDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
|
||||
hr = m_device->CreateDescriptorHeap(&rtvDesc, IID_PPV_ARGS(&m_rtvHeap));
|
||||
if (FAILED(hr)) return false;
|
||||
m_rtvDescriptorSize = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
|
||||
|
||||
D3D12_DESCRIPTOR_HEAP_DESC srvDesc = {};
|
||||
srvDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
|
||||
srvDesc.NumDescriptors = 1;
|
||||
srvDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
|
||||
hr = m_device->CreateDescriptorHeap(&srvDesc, IID_PPV_ARGS(&m_srvHeap));
|
||||
if (FAILED(hr)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Application::CreateRenderTarget() {
|
||||
if (!m_swapChain || !m_device || !m_rtvHeap) return false;
|
||||
|
||||
for (UINT i = 0; i < 3; i++) {
|
||||
HRESULT hr = m_swapChain->GetBuffer(i, IID_PPV_ARGS(&m_renderTargets[i]));
|
||||
if (FAILED(hr)) return false;
|
||||
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = m_rtvHeap->GetCPUDescriptorHandleForHeapStart();
|
||||
rtvHandle.ptr += i * m_rtvDescriptorSize;
|
||||
m_device->CreateRenderTargetView(m_renderTargets[i], nullptr, rtvHandle);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Application::CleanupRenderTarget() {
|
||||
for (UINT i = 0; i < 3; i++) {
|
||||
if (m_renderTargets[i]) {
|
||||
m_renderTargets[i]->Release();
|
||||
m_renderTargets[i] = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Application::SetupDockspace() {
|
||||
static ImGuiDockNodeFlags dockspaceFlags = ImGuiDockNodeFlags_None;
|
||||
|
||||
ImGuiWindowFlags windowFlags = ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoDocking;
|
||||
|
||||
ImGuiViewport* viewport = ImGui::GetMainViewport();
|
||||
ImGui::SetNextWindowPos(viewport->Pos);
|
||||
ImGui::SetNextWindowSize(viewport->Size);
|
||||
ImGui::SetNextWindowViewport(viewport->ID);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
|
||||
windowFlags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove;
|
||||
windowFlags |= ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus;
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
|
||||
ImGui::Begin("MainDockspace", nullptr, windowFlags);
|
||||
ImGui::PopStyleVar();
|
||||
ImGui::PopStyleVar(2);
|
||||
|
||||
ImGuiID dockspaceId = ImGui::GetID("MyDockspace");
|
||||
ImGui::DockSpace(dockspaceId, ImVec2(0.0f, 0.0f), dockspaceFlags);
|
||||
|
||||
static bool firstTime = true;
|
||||
if (firstTime) {
|
||||
firstTime = false;
|
||||
ImGui::DockBuilderRemoveNode(dockspaceId);
|
||||
ImGui::DockBuilderAddNode(dockspaceId, dockspaceFlags | ImGuiDockNodeFlags_DockSpace);
|
||||
ImGui::DockBuilderSetNodeSize(dockspaceId, viewport->Size);
|
||||
|
||||
ImGuiID dockMain = dockspaceId;
|
||||
ImGuiID dockBottom = ImGui::DockBuilderSplitNode(dockMain, ImGuiDir_Down, 0.25f, nullptr, &dockMain);
|
||||
ImGuiID dockLeft = ImGui::DockBuilderSplitNode(dockMain, ImGuiDir_Left, 0.15f, nullptr, &dockMain);
|
||||
ImGuiID dockRight = ImGui::DockBuilderSplitNode(dockMain, ImGuiDir_Right, 0.25f, nullptr, &dockMain);
|
||||
|
||||
ImGui::DockBuilderDockWindow("Hierarchy", dockLeft);
|
||||
ImGui::DockBuilderDockWindow("Scene", dockMain);
|
||||
ImGui::DockBuilderDockWindow("Inspector", dockRight);
|
||||
ImGui::DockBuilderDockWindow("Console", dockBottom);
|
||||
ImGui::DockBuilderDockWindow("Project", dockBottom);
|
||||
|
||||
ImGui::DockBuilderFinish(dockspaceId);
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
void Application::RenderUI() {
|
||||
m_menuBar->Render();
|
||||
|
||||
m_hierarchyPanel->Render();
|
||||
m_sceneViewPanel->Render();
|
||||
m_inspectorPanel->Render();
|
||||
|
||||
ImGui::Begin("BottomPanel", nullptr, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse);
|
||||
|
||||
if (ImGui::Button("Console", ImVec2(80, 0))) {
|
||||
m_currentBottomPanel = BottomPanel::Console;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Project", ImVec2(80, 0))) {
|
||||
m_currentBottomPanel = BottomPanel::Project;
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
ImGui::BeginChild("BottomContent");
|
||||
|
||||
if (m_currentBottomPanel == BottomPanel::Console) {
|
||||
m_consolePanel->Render();
|
||||
} else {
|
||||
m_projectPanel->Render();
|
||||
}
|
||||
|
||||
ImGui::EndChild();
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
}
|
||||
67
ui/src/Application.h
Normal file
67
ui/src/Application.h
Normal file
@@ -0,0 +1,67 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <imgui.h>
|
||||
#include <d3d12.h>
|
||||
#include <dxgi1_6.h>
|
||||
|
||||
#include "Theme.h"
|
||||
#include "panels/Panel.h"
|
||||
#include "panels/MenuBar.h"
|
||||
#include "panels/HierarchyPanel.h"
|
||||
#include "panels/SceneViewPanel.h"
|
||||
#include "panels/InspectorPanel.h"
|
||||
#include "panels/ConsolePanel.h"
|
||||
#include "panels/ProjectPanel.h"
|
||||
|
||||
namespace UI {
|
||||
|
||||
enum class BottomPanel { Console, Project };
|
||||
|
||||
class Application {
|
||||
public:
|
||||
static Application& Get();
|
||||
|
||||
bool Initialize(HWND hwnd);
|
||||
void Shutdown();
|
||||
void Render();
|
||||
void OnResize(int width, int height);
|
||||
|
||||
private:
|
||||
Application() = default;
|
||||
~Application() = default;
|
||||
|
||||
bool CreateDevice();
|
||||
bool CreateRenderTarget();
|
||||
void CleanupRenderTarget();
|
||||
void SetupDockspace();
|
||||
void RenderUI();
|
||||
|
||||
HWND m_hwnd = nullptr;
|
||||
int m_width = 1280;
|
||||
int m_height = 720;
|
||||
|
||||
ID3D12Device* m_device = nullptr;
|
||||
ID3D12CommandQueue* m_commandQueue = nullptr;
|
||||
ID3D12CommandAllocator* m_commandAllocator = nullptr;
|
||||
ID3D12GraphicsCommandList* m_commandList = nullptr;
|
||||
IDXGISwapChain3* m_swapChain = nullptr;
|
||||
ID3D12DescriptorHeap* m_rtvHeap = nullptr;
|
||||
ID3D12DescriptorHeap* m_srvHeap = nullptr;
|
||||
ID3D12Resource* m_renderTargets[3] = {};
|
||||
ID3D12Fence* m_fence = nullptr;
|
||||
UINT64 m_fenceValue = 0;
|
||||
UINT m_rtvDescriptorSize = 0;
|
||||
UINT m_frameIndex = 0;
|
||||
|
||||
std::unique_ptr<MenuBar> m_menuBar;
|
||||
std::unique_ptr<HierarchyPanel> m_hierarchyPanel;
|
||||
std::unique_ptr<SceneViewPanel> m_sceneViewPanel;
|
||||
std::unique_ptr<InspectorPanel> m_inspectorPanel;
|
||||
std::unique_ptr<ConsolePanel> m_consolePanel;
|
||||
std::unique_ptr<ProjectPanel> m_projectPanel;
|
||||
|
||||
BottomPanel m_currentBottomPanel = BottomPanel::Console;
|
||||
};
|
||||
|
||||
}
|
||||
82
ui/src/Theme.cpp
Normal file
82
ui/src/Theme.cpp
Normal file
@@ -0,0 +1,82 @@
|
||||
#include "Theme.h"
|
||||
#include <imgui.h>
|
||||
|
||||
namespace UI {
|
||||
|
||||
void ApplyUnityDarkTheme() {
|
||||
ImGuiStyle& style = ImGui::GetStyle();
|
||||
ImVec4* colors = style.Colors;
|
||||
|
||||
colors[ImGuiCol_Text] = ImVec4(0.90f, 0.90f, 0.90f, 1.00f);
|
||||
colors[ImGuiCol_TextDisabled] = ImVec4(0.50f, 0.50f, 0.50f, 1.00f);
|
||||
colors[ImGuiCol_WindowBg] = ImVec4(0.12f, 0.12f, 0.12f, 1.00f);
|
||||
colors[ImGuiCol_ChildBg] = ImVec4(0.15f, 0.15f, 0.15f, 1.00f);
|
||||
colors[ImGuiCol_PopupBg] = ImVec4(0.18f, 0.18f, 0.18f, 0.94f);
|
||||
colors[ImGuiCol_Border] = ImVec4(0.08f, 0.08f, 0.08f, 1.00f);
|
||||
colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
|
||||
colors[ImGuiCol_FrameBg] = ImVec4(0.20f, 0.20f, 0.20f, 1.00f);
|
||||
colors[ImGuiCol_FrameBgHovered] = ImVec4(0.28f, 0.28f, 0.28f, 1.00f);
|
||||
colors[ImGuiCol_FrameBgActive] = ImVec4(0.35f, 0.35f, 0.35f, 1.00f);
|
||||
colors[ImGuiCol_TitleBg] = ImVec4(0.10f, 0.10f, 0.10f, 1.00f);
|
||||
colors[ImGuiCol_TitleBgActive] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
|
||||
colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.10f, 0.10f, 0.10f, 0.75f);
|
||||
colors[ImGuiCol_MenuBarBg] = ImVec4(0.14f, 0.14f, 0.14f, 1.00f);
|
||||
colors[ImGuiCol_ScrollbarBg] = ImVec4(0.10f, 0.10f, 0.10f, 0.53f);
|
||||
colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.30f, 0.30f, 0.30f, 1.00f);
|
||||
colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.40f, 0.40f, 0.40f, 1.00f);
|
||||
colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.50f, 0.50f, 0.50f, 1.00f);
|
||||
colors[ImGuiCol_CheckMark] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
|
||||
colors[ImGuiCol_SliderGrab] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
|
||||
colors[ImGuiCol_SliderGrabActive] = ImVec4(0.36f, 0.69f, 1.00f, 1.00f);
|
||||
colors[ImGuiCol_Button] = ImVec4(0.26f, 0.59f, 0.98f, 0.40f);
|
||||
colors[ImGuiCol_ButtonHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.60f);
|
||||
colors[ImGuiCol_ButtonActive] = ImVec4(0.26f, 0.59f, 0.98f, 0.80f);
|
||||
colors[ImGuiCol_Header] = ImVec4(0.20f, 0.20f, 0.20f, 1.00f);
|
||||
colors[ImGuiCol_HeaderHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.40f);
|
||||
colors[ImGuiCol_HeaderActive] = ImVec4(0.26f, 0.59f, 0.98f, 0.60f);
|
||||
colors[ImGuiCol_Separator] = ImVec4(0.08f, 0.08f, 0.08f, 1.00f);
|
||||
colors[ImGuiCol_SeparatorHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.78f);
|
||||
colors[ImGuiCol_SeparatorActive] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
|
||||
colors[ImGuiCol_ResizeGrip] = ImVec4(0.26f, 0.59f, 0.98f, 0.20f);
|
||||
colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.78f);
|
||||
colors[ImGuiCol_ResizeGripActive] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
|
||||
colors[ImGuiCol_Tab] = ImVec4(0.18f, 0.18f, 0.18f, 0.86f);
|
||||
colors[ImGuiCol_TabHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.80f);
|
||||
colors[ImGuiCol_TabActive] = ImVec4(0.20f, 0.20f, 0.20f, 1.00f);
|
||||
colors[ImGuiCol_TabUnfocused] = ImVec4(0.15f, 0.15f, 0.15f, 0.97f);
|
||||
colors[ImGuiCol_TabUnfocusedActive] = ImVec4(0.18f, 0.18f, 0.18f, 1.00f);
|
||||
colors[ImGuiCol_DockingPreview] = ImVec4(0.26f, 0.59f, 0.98f, 0.70f);
|
||||
colors[ImGuiCol_DockingEmptyBg] = ImVec4(0.12f, 0.12f, 0.12f, 1.00f);
|
||||
colors[ImGuiCol_PlotLines] = ImVec4(0.61f, 0.61f, 0.61f, 1.00f);
|
||||
colors[ImGuiCol_PlotLinesHovered] = ImVec4(1.00f, 0.43f, 0.35f, 1.00f);
|
||||
colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
|
||||
colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f);
|
||||
colors[ImGuiCol_TableHeaderBg] = ImVec4(0.19f, 0.19f, 0.20f, 1.00f);
|
||||
colors[ImGuiCol_TableBorderStrong] = ImVec4(0.31f, 0.31f, 0.35f, 1.00f);
|
||||
colors[ImGuiCol_TableBorderLight] = ImVec4(0.23f, 0.23f, 0.25f, 1.00f);
|
||||
colors[ImGuiCol_TableRowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
|
||||
colors[ImGuiCol_TableRowBgAlt] = ImVec4(1.00f, 1.00f, 1.00f, 0.06f);
|
||||
colors[ImGuiCol_TextSelectedBg] = ImVec4(0.26f, 0.59f, 0.98f, 0.35f);
|
||||
colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f);
|
||||
colors[ImGuiCol_NavHighlight] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
|
||||
colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f);
|
||||
colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.20f);
|
||||
colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.35f);
|
||||
|
||||
style.WindowRounding = 4.0f;
|
||||
style.ChildRounding = 4.0f;
|
||||
style.FrameRounding = 4.0f;
|
||||
style.GrabRounding = 4.0f;
|
||||
style.PopupRounding = 4.0f;
|
||||
style.ScrollbarRounding = 4.0f;
|
||||
style.TabRounding = 4.0f;
|
||||
style.WindowBorderSize = 1.0f;
|
||||
style.ChildBorderSize = 1.0f;
|
||||
style.FrameBorderSize = 0.0f;
|
||||
style.WindowPadding = ImVec2(8.0f, 8.0f);
|
||||
style.FramePadding = ImVec2(6.0f, 4.0f);
|
||||
style.ItemSpacing = ImVec2(8.0f, 4.0f);
|
||||
style.ItemInnerSpacing = ImVec2(6.0f, 4.0f);
|
||||
}
|
||||
|
||||
}
|
||||
7
ui/src/Theme.h
Normal file
7
ui/src/Theme.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
namespace UI {
|
||||
|
||||
void ApplyUnityDarkTheme();
|
||||
|
||||
}
|
||||
96
ui/src/main.cpp
Normal file
96
ui/src/main.cpp
Normal file
@@ -0,0 +1,96 @@
|
||||
#include "Application.h"
|
||||
#include <imgui.h>
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
|
||||
LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, LPWSTR, int nCmdShow) {
|
||||
AllocConsole();
|
||||
freopen("CONOUT$", "w", stdout);
|
||||
printf("Starting UI application...\n");
|
||||
|
||||
WNDCLASSEXW wc = {};
|
||||
wc.cbSize = sizeof(wc);
|
||||
wc.style = CS_CLASSDC;
|
||||
wc.lpfnWndProc = WndProc;
|
||||
wc.hInstance = GetModuleHandle(nullptr);
|
||||
wc.lpszClassName = L"XCVolumeRendererUI2";
|
||||
|
||||
if (!RegisterClassExW(&wc)) {
|
||||
printf("Failed to register window class, error: %lu\n", GetLastError());
|
||||
return 1;
|
||||
}
|
||||
printf("Window class registered.\n");
|
||||
|
||||
HWND hwnd = CreateWindowExW(
|
||||
0, wc.lpszClassName, L"XCVolumeRenderer - Unity Style Editor",
|
||||
WS_OVERLAPPEDWINDOW, 100, 100, 1280, 720,
|
||||
nullptr, nullptr, wc.hInstance, nullptr
|
||||
);
|
||||
|
||||
if (!hwnd) {
|
||||
printf("Failed to create window, error: %lu\n", GetLastError());
|
||||
return 1;
|
||||
}
|
||||
printf("Window created.\n");
|
||||
|
||||
ShowWindow(hwnd, nCmdShow);
|
||||
UpdateWindow(hwnd);
|
||||
printf("Window shown.\n");
|
||||
|
||||
printf("Initializing application...\n");
|
||||
if (!UI::Application::Get().Initialize(hwnd)) {
|
||||
printf("Failed to initialize application!\n");
|
||||
UnregisterClassW(wc.lpszClassName, wc.hInstance);
|
||||
system("pause");
|
||||
return 1;
|
||||
}
|
||||
printf("Application initialized successfully.\n");
|
||||
|
||||
MSG msg = {};
|
||||
int frameCount = 0;
|
||||
while (msg.message != WM_QUIT) {
|
||||
if (PeekMessageW(&msg, nullptr, 0U, 0U, PM_REMOVE)) {
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessageW(&msg);
|
||||
} else {
|
||||
UI::Application::Get().Render();
|
||||
frameCount++;
|
||||
if (frameCount % 100 == 0) {
|
||||
printf("Frame %d\n", frameCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
printf("Shutting down...\n");
|
||||
UI::Application::Get().Shutdown();
|
||||
UnregisterClassW(wc.lpszClassName, wc.hInstance);
|
||||
|
||||
printf("Press any key to exit...\n");
|
||||
system("pause");
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
|
||||
if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam))
|
||||
return true;
|
||||
|
||||
switch (msg) {
|
||||
case WM_SIZE:
|
||||
if (wParam != SIZE_MINIMIZED) {
|
||||
UI::Application::Get().OnResize((int)LOWORD(lParam), (int)HIWORD(lParam));
|
||||
}
|
||||
return 0;
|
||||
case WM_SYSCOMMAND:
|
||||
if ((wParam & 0xfff0) == SC_KEYMENU)
|
||||
return 0;
|
||||
break;
|
||||
case WM_DESTROY:
|
||||
PostQuitMessage(0);
|
||||
return 0;
|
||||
}
|
||||
return DefWindowProcW(hWnd, msg, wParam, lParam);
|
||||
}
|
||||
77
ui/src/panels/ConsolePanel.cpp
Normal file
77
ui/src/panels/ConsolePanel.cpp
Normal file
@@ -0,0 +1,77 @@
|
||||
#include "ConsolePanel.h"
|
||||
#include <imgui.h>
|
||||
|
||||
namespace UI {
|
||||
|
||||
ConsolePanel::ConsolePanel() : Panel("Console") {
|
||||
m_logs.push_back({LogEntry::Level::Info, "Engine initialized successfully"});
|
||||
m_logs.push_back({LogEntry::Level::Info, "Loading default scene..."});
|
||||
m_logs.push_back({LogEntry::Level::Warning, "Missing material on object 'Cube'"});
|
||||
m_logs.push_back({LogEntry::Level::Error, "Failed to load texture: 'Assets/Textures/missing.png'"});
|
||||
m_logs.push_back({LogEntry::Level::Info, "Scene loaded successfully"});
|
||||
}
|
||||
|
||||
void ConsolePanel::Render() {
|
||||
ImGui::Begin(m_name.c_str(), &m_isOpen, ImGuiWindowFlags_None);
|
||||
|
||||
if (ImGui::Button("Clear")) {
|
||||
Clear();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Info")) {
|
||||
AddLog(LogEntry::Level::Info, "Test info message");
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Warn")) {
|
||||
AddLog(LogEntry::Level::Warning, "Test warning message");
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Error")) {
|
||||
AddLog(LogEntry::Level::Error, "Test error message");
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
ImGui::BeginChild("LogScroll", ImVec2(0, 0), false, ImGuiWindowFlags_HorizontalScrollbar);
|
||||
|
||||
for (const auto& log : m_logs) {
|
||||
ImVec4 color;
|
||||
const char* prefix;
|
||||
|
||||
switch (log.level) {
|
||||
case LogEntry::Level::Info:
|
||||
color = ImVec4(0.7f, 0.7f, 0.7f, 1.0f);
|
||||
prefix = "[Info] ";
|
||||
break;
|
||||
case LogEntry::Level::Warning:
|
||||
color = ImVec4(1.0f, 0.8f, 0.0f, 1.0f);
|
||||
prefix = "[Warn] ";
|
||||
break;
|
||||
case LogEntry::Level::Error:
|
||||
color = ImVec4(1.0f, 0.3f, 0.3f, 1.0f);
|
||||
prefix = "[Error]";
|
||||
break;
|
||||
}
|
||||
|
||||
ImGui::TextColored(color, "%s%s", prefix, log.message.c_str());
|
||||
}
|
||||
|
||||
if (m_scrollToBottom) {
|
||||
ImGui::SetScrollHereY(1.0f);
|
||||
m_scrollToBottom = false;
|
||||
}
|
||||
|
||||
ImGui::EndChild();
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
void ConsolePanel::AddLog(LogEntry::Level level, const std::string& message) {
|
||||
m_logs.push_back({level, message});
|
||||
m_scrollToBottom = true;
|
||||
}
|
||||
|
||||
void ConsolePanel::Clear() {
|
||||
m_logs.clear();
|
||||
}
|
||||
|
||||
}
|
||||
28
ui/src/panels/ConsolePanel.h
Normal file
28
ui/src/panels/ConsolePanel.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#include "Panel.h"
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
namespace UI {
|
||||
|
||||
struct LogEntry {
|
||||
enum class Level { Info, Warning, Error };
|
||||
Level level;
|
||||
std::string message;
|
||||
};
|
||||
|
||||
class ConsolePanel : public Panel {
|
||||
public:
|
||||
ConsolePanel();
|
||||
void Render() override;
|
||||
void AddLog(LogEntry::Level level, const std::string& message);
|
||||
|
||||
private:
|
||||
void Clear();
|
||||
|
||||
std::vector<LogEntry> m_logs;
|
||||
bool m_scrollToBottom = false;
|
||||
};
|
||||
|
||||
}
|
||||
75
ui/src/panels/HierarchyPanel.cpp
Normal file
75
ui/src/panels/HierarchyPanel.cpp
Normal file
@@ -0,0 +1,75 @@
|
||||
#include "HierarchyPanel.h"
|
||||
#include <imgui.h>
|
||||
|
||||
namespace UI {
|
||||
|
||||
HierarchyPanel::HierarchyPanel() : Panel("Hierarchy") {
|
||||
InitDemoData();
|
||||
}
|
||||
|
||||
void HierarchyPanel::InitDemoData() {
|
||||
GameObject mainCamera;
|
||||
mainCamera.name = "Main Camera";
|
||||
|
||||
GameObject directionalLight;
|
||||
directionalLight.name = "Directional Light";
|
||||
|
||||
GameObject cube;
|
||||
cube.name = "Cube";
|
||||
|
||||
GameObject sphere;
|
||||
sphere.name = "Sphere";
|
||||
|
||||
GameObject player;
|
||||
player.name = "Player";
|
||||
GameObject weapon;
|
||||
weapon.name = "Weapon";
|
||||
player.children.push_back(weapon);
|
||||
|
||||
m_rootObjects.push_back(mainCamera);
|
||||
m_rootObjects.push_back(directionalLight);
|
||||
m_rootObjects.push_back(cube);
|
||||
m_rootObjects.push_back(sphere);
|
||||
m_rootObjects.push_back(player);
|
||||
}
|
||||
|
||||
void HierarchyPanel::Render() {
|
||||
ImGui::Begin(m_name.c_str(), &m_isOpen, ImGuiWindowFlags_None);
|
||||
|
||||
for (auto& obj : m_rootObjects) {
|
||||
RenderGameObject(obj);
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
void HierarchyPanel::RenderGameObject(GameObject& obj) {
|
||||
ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_SpanAvailWidth;
|
||||
|
||||
if (obj.children.empty()) {
|
||||
flags |= ImGuiTreeNodeFlags_Leaf;
|
||||
}
|
||||
|
||||
if (obj.selected) {
|
||||
flags |= ImGuiTreeNodeFlags_Selected;
|
||||
}
|
||||
|
||||
bool isOpen = ImGui::TreeNodeEx(obj.name.c_str(), flags);
|
||||
|
||||
if (ImGui::IsItemClicked() && !ImGui::IsItemToggledOpen()) {
|
||||
if (m_selectedObject) {
|
||||
m_selectedObject->selected = false;
|
||||
}
|
||||
obj.selected = true;
|
||||
m_selectedObject = &obj;
|
||||
}
|
||||
|
||||
if (isOpen) {
|
||||
for (auto& child : obj.children) {
|
||||
RenderGameObject(child);
|
||||
}
|
||||
ImGui::TreePop();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
30
ui/src/panels/HierarchyPanel.h
Normal file
30
ui/src/panels/HierarchyPanel.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#include "Panel.h"
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
namespace UI {
|
||||
|
||||
struct GameObject {
|
||||
std::string name;
|
||||
std::vector<GameObject> children;
|
||||
bool isOpen = false;
|
||||
bool selected = false;
|
||||
};
|
||||
|
||||
class HierarchyPanel : public Panel {
|
||||
public:
|
||||
HierarchyPanel();
|
||||
void Render() override;
|
||||
GameObject* GetSelectedObject() { return m_selectedObject; }
|
||||
|
||||
private:
|
||||
void RenderGameObject(GameObject& obj);
|
||||
void InitDemoData();
|
||||
|
||||
std::vector<GameObject> m_rootObjects;
|
||||
GameObject* m_selectedObject = nullptr;
|
||||
};
|
||||
|
||||
}
|
||||
74
ui/src/panels/InspectorPanel.cpp
Normal file
74
ui/src/panels/InspectorPanel.cpp
Normal file
@@ -0,0 +1,74 @@
|
||||
#include "InspectorPanel.h"
|
||||
#include <imgui.h>
|
||||
|
||||
namespace UI {
|
||||
|
||||
InspectorPanel::InspectorPanel() : Panel("Inspector") {}
|
||||
|
||||
void InspectorPanel::Render() {
|
||||
ImGui::Begin(m_name.c_str(), &m_isOpen, ImGuiWindowFlags_None);
|
||||
|
||||
GameObject* selected = nullptr;
|
||||
if (m_hierarchyPanel) {
|
||||
selected = m_hierarchyPanel->GetSelectedObject();
|
||||
}
|
||||
|
||||
if (selected) {
|
||||
ImGui::Text("%s", selected->name.c_str());
|
||||
ImGui::Separator();
|
||||
|
||||
RenderTransformSection();
|
||||
ImGui::Separator();
|
||||
RenderMeshRendererSection();
|
||||
} else {
|
||||
ImGui::Text("No object selected");
|
||||
ImGui::TextColored(ImVec4(0.5f, 0.5f, 0.5f, 1.0f), "Select an object in Hierarchy");
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
void InspectorPanel::RenderTransformSection() {
|
||||
if (ImGui::CollapsingHeader("Transform", ImGuiTreeNodeFlags_DefaultOpen)) {
|
||||
ImGui::Indent(10.0f);
|
||||
|
||||
ImGui::Text("Position");
|
||||
ImGui::SameLine(80);
|
||||
ImGui::SetNextItemWidth(180);
|
||||
ImGui::DragFloat3("##Position", m_position, 0.1f);
|
||||
|
||||
ImGui::Text("Rotation");
|
||||
ImGui::SameLine(80);
|
||||
ImGui::SetNextItemWidth(180);
|
||||
ImGui::DragFloat3("##Rotation", m_rotation, 1.0f);
|
||||
|
||||
ImGui::Text("Scale");
|
||||
ImGui::SameLine(80);
|
||||
ImGui::SetNextItemWidth(180);
|
||||
ImGui::DragFloat3("##Scale", m_scale, 0.1f);
|
||||
|
||||
ImGui::Unindent(10.0f);
|
||||
}
|
||||
}
|
||||
|
||||
void InspectorPanel::RenderMeshRendererSection() {
|
||||
if (ImGui::CollapsingHeader("Mesh Renderer", ImGuiTreeNodeFlags_DefaultOpen)) {
|
||||
ImGui::Indent(10.0f);
|
||||
|
||||
ImGui::Text("Material");
|
||||
ImGui::SameLine(80);
|
||||
ImGui::SetNextItemWidth(180);
|
||||
static char materialName[64] = "Default-Material";
|
||||
ImGui::InputText("##Material", materialName, sizeof(materialName));
|
||||
|
||||
ImGui::Text("Mesh");
|
||||
ImGui::SameLine(80);
|
||||
ImGui::SetNextItemWidth(180);
|
||||
static char meshName[64] = "Cube Mesh";
|
||||
ImGui::InputText("##Mesh", meshName, sizeof(meshName));
|
||||
|
||||
ImGui::Unindent(10.0f);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
25
ui/src/panels/InspectorPanel.h
Normal file
25
ui/src/panels/InspectorPanel.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include "Panel.h"
|
||||
#include "HierarchyPanel.h"
|
||||
|
||||
namespace UI {
|
||||
|
||||
class InspectorPanel : public Panel {
|
||||
public:
|
||||
InspectorPanel();
|
||||
void Render() override;
|
||||
void SetHierarchyPanel(HierarchyPanel* panel) { m_hierarchyPanel = panel; }
|
||||
|
||||
private:
|
||||
void RenderTransformSection();
|
||||
void RenderMeshRendererSection();
|
||||
|
||||
HierarchyPanel* m_hierarchyPanel = nullptr;
|
||||
|
||||
float m_position[3] = {0.0f, 1.0f, -10.0f};
|
||||
float m_rotation[3] = {0.0f, 0.0f, 0.0f};
|
||||
float m_scale[3] = {1.0f, 1.0f, 1.0f};
|
||||
};
|
||||
|
||||
}
|
||||
55
ui/src/panels/MenuBar.cpp
Normal file
55
ui/src/panels/MenuBar.cpp
Normal file
@@ -0,0 +1,55 @@
|
||||
#include "MenuBar.h"
|
||||
#include <imgui.h>
|
||||
|
||||
namespace UI {
|
||||
|
||||
MenuBar::MenuBar() : Panel("MenuBar") {}
|
||||
|
||||
void MenuBar::Render() {
|
||||
if (ImGui::BeginMainMenuBar()) {
|
||||
ShowFileMenu();
|
||||
ShowEditMenu();
|
||||
ShowViewMenu();
|
||||
ShowHelpMenu();
|
||||
ImGui::EndMainMenuBar();
|
||||
}
|
||||
}
|
||||
|
||||
void MenuBar::ShowFileMenu() {
|
||||
if (ImGui::BeginMenu("File")) {
|
||||
if (ImGui::MenuItem("New Scene", "Ctrl+N")) {}
|
||||
if (ImGui::MenuItem("Open Scene", "Ctrl+O")) {}
|
||||
if (ImGui::MenuItem("Save Scene", "Ctrl+S")) {}
|
||||
ImGui::Separator();
|
||||
if (ImGui::MenuItem("Exit", "Alt+F4")) {}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
}
|
||||
|
||||
void MenuBar::ShowEditMenu() {
|
||||
if (ImGui::BeginMenu("Edit")) {
|
||||
if (ImGui::MenuItem("Undo", "Ctrl+Z")) {}
|
||||
if (ImGui::MenuItem("Redo", "Ctrl+Y")) {}
|
||||
ImGui::Separator();
|
||||
if (ImGui::MenuItem("Cut", "Ctrl+X")) {}
|
||||
if (ImGui::MenuItem("Copy", "Ctrl+C")) {}
|
||||
if (ImGui::MenuItem("Paste", "Ctrl+V")) {}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
}
|
||||
|
||||
void MenuBar::ShowViewMenu() {
|
||||
if (ImGui::BeginMenu("View")) {
|
||||
if (ImGui::MenuItem("Reset Layout")) {}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
}
|
||||
|
||||
void MenuBar::ShowHelpMenu() {
|
||||
if (ImGui::BeginMenu("Help")) {
|
||||
if (ImGui::MenuItem("About")) {}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
19
ui/src/panels/MenuBar.h
Normal file
19
ui/src/panels/MenuBar.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include "Panel.h"
|
||||
|
||||
namespace UI {
|
||||
|
||||
class MenuBar : public Panel {
|
||||
public:
|
||||
MenuBar();
|
||||
void Render() override;
|
||||
|
||||
private:
|
||||
void ShowFileMenu();
|
||||
void ShowEditMenu();
|
||||
void ShowViewMenu();
|
||||
void ShowHelpMenu();
|
||||
};
|
||||
|
||||
}
|
||||
4
ui/src/panels/Panel.cpp
Normal file
4
ui/src/panels/Panel.cpp
Normal file
@@ -0,0 +1,4 @@
|
||||
#include "Panel.h"
|
||||
|
||||
namespace UI {
|
||||
}
|
||||
25
ui/src/panels/Panel.h
Normal file
25
ui/src/panels/Panel.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <imgui.h>
|
||||
|
||||
namespace UI {
|
||||
|
||||
class Panel {
|
||||
public:
|
||||
Panel(const std::string& name) : m_name(name), m_isOpen(true) {}
|
||||
virtual ~Panel() = default;
|
||||
|
||||
virtual void Render() = 0;
|
||||
|
||||
const std::string& GetName() const { return m_name; }
|
||||
bool IsOpen() const { return m_isOpen; }
|
||||
void SetOpen(bool open) { m_isOpen = open; }
|
||||
void Toggle() { m_isOpen = !m_isOpen; }
|
||||
|
||||
protected:
|
||||
std::string m_name;
|
||||
bool m_isOpen;
|
||||
};
|
||||
|
||||
}
|
||||
88
ui/src/panels/ProjectPanel.cpp
Normal file
88
ui/src/panels/ProjectPanel.cpp
Normal file
@@ -0,0 +1,88 @@
|
||||
#include "ProjectPanel.h"
|
||||
#include <imgui.h>
|
||||
#include <imgui_internal.h>
|
||||
|
||||
namespace UI {
|
||||
|
||||
ProjectPanel::ProjectPanel() : Panel("Project") {
|
||||
m_folders = {"Assets", "Scenes", "Scripts", "Materials", "Prefabs"};
|
||||
|
||||
m_items = {
|
||||
{"Cube", "Prefab", false},
|
||||
{"Sphere", "Prefab", false},
|
||||
{"Player", "Prefab", false},
|
||||
{"MainScript", "Script", false},
|
||||
{"DefaultMat", "Material", false},
|
||||
{"Scene1", "Scene", false},
|
||||
{"Textures", "Folder", true},
|
||||
{"Models", "Folder", true},
|
||||
};
|
||||
}
|
||||
|
||||
void ProjectPanel::Render() {
|
||||
ImGui::Begin(m_name.c_str(), &m_isOpen, ImGuiWindowFlags_None);
|
||||
|
||||
ImGui::Text("Assets/");
|
||||
ImGui::SameLine();
|
||||
ImGui::TextColored(ImVec4(0.5f, 0.5f, 0.5f, 1.0f), "> Project");
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
ImGui::BeginChild("AssetList", ImVec2(0, 0), false);
|
||||
|
||||
float buttonWidth = 80.0f;
|
||||
float buttonHeight = 90.0f;
|
||||
float padding = 10.0f;
|
||||
float panelWidth = ImGui::GetContentRegionAvail().x;
|
||||
int columns = (int)(panelWidth / (buttonWidth + padding));
|
||||
if (columns < 1) columns = 1;
|
||||
|
||||
for (int i = 0; i < m_items.size(); i++) {
|
||||
if (i > 0 && i % columns != 0) {
|
||||
ImGui::SameLine();
|
||||
}
|
||||
RenderAssetItem(m_items[i], i);
|
||||
}
|
||||
|
||||
ImGui::EndChild();
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
void ProjectPanel::RenderAssetItem(const AssetItem& item, int index) {
|
||||
ImGui::PushID(index);
|
||||
|
||||
bool isSelected = (m_selectedIndex == index);
|
||||
if (isSelected) {
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.26f, 0.59f, 0.98f, 0.40f));
|
||||
}
|
||||
|
||||
ImVec2 buttonSize(80.0f, 90.0f);
|
||||
if (ImGui::Button("##Asset", buttonSize)) {
|
||||
m_selectedIndex = index;
|
||||
}
|
||||
|
||||
if (isSelected) {
|
||||
ImGui::PopStyleColor();
|
||||
}
|
||||
|
||||
ImVec2 min = ImGui::GetItemRectMin();
|
||||
ImVec2 max = ImGui::GetItemRectMax();
|
||||
ImDrawList* drawList = ImGui::GetWindowDrawList();
|
||||
|
||||
ImU32 iconColor = item.isFolder ? IM_COL32(200, 180, 100, 255) : IM_COL32(100, 150, 200, 255);
|
||||
|
||||
float iconSize = 40.0f;
|
||||
ImVec2 iconMin(min.x + (80.0f - iconSize) * 0.5f, min.y + 10.0f);
|
||||
ImVec2 iconMax(iconMin.x + iconSize, iconMin.y + iconSize);
|
||||
drawList->AddRectFilled(iconMin, iconMax, iconColor, 4.0f);
|
||||
|
||||
ImVec2 textPos(min.x + 5.0f, min.y + 60.0f);
|
||||
ImVec4 textColor = isSelected ? ImVec4(1.0f, 1.0f, 1.0f, 1.0f) : ImVec4(0.8f, 0.8f, 0.8f, 1.0f);
|
||||
ImVec2 textSize = ImGui::CalcTextSize(item.name.c_str());
|
||||
float textOffset = (80.0f - textSize.x) * 0.5f;
|
||||
drawList->AddText(ImVec2(min.x + textOffset, textPos.y), ImGui::GetColorU32(textColor), item.name.c_str());
|
||||
|
||||
ImGui::PopID();
|
||||
}
|
||||
|
||||
}
|
||||
28
ui/src/panels/ProjectPanel.h
Normal file
28
ui/src/panels/ProjectPanel.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#include "Panel.h"
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
namespace UI {
|
||||
|
||||
struct AssetItem {
|
||||
std::string name;
|
||||
std::string type;
|
||||
bool isFolder;
|
||||
};
|
||||
|
||||
class ProjectPanel : public Panel {
|
||||
public:
|
||||
ProjectPanel();
|
||||
void Render() override;
|
||||
|
||||
private:
|
||||
void RenderAssetItem(const AssetItem& item, int index);
|
||||
|
||||
std::vector<std::string> m_folders;
|
||||
std::vector<AssetItem> m_items;
|
||||
int m_selectedIndex = -1;
|
||||
};
|
||||
|
||||
}
|
||||
78
ui/src/panels/SceneViewPanel.cpp
Normal file
78
ui/src/panels/SceneViewPanel.cpp
Normal file
@@ -0,0 +1,78 @@
|
||||
#include "SceneViewPanel.h"
|
||||
#include <imgui.h>
|
||||
#include <imgui_internal.h>
|
||||
|
||||
namespace UI {
|
||||
|
||||
SceneViewPanel::SceneViewPanel() : Panel("Scene") {}
|
||||
|
||||
void SceneViewPanel::Render() {
|
||||
ImGui::Begin(m_name.c_str(), &m_isOpen, ImGuiWindowFlags_None);
|
||||
|
||||
if (ImGui::BeginTabBar("SceneGameTabs")) {
|
||||
if (ImGui::BeginTabItem("Scene")) {
|
||||
m_isSceneView = true;
|
||||
ImVec2 canvasSize = ImGui::GetContentRegionAvail();
|
||||
ImDrawList* drawList = ImGui::GetWindowDrawList();
|
||||
ImVec2 canvasPos = ImGui::GetCursorScreenPos();
|
||||
|
||||
ImU32 bgColor = IM_COL32(30, 30, 30, 255);
|
||||
drawList->AddRectFilled(canvasPos, ImVec2(canvasPos.x + canvasSize.x, canvasPos.y + canvasSize.y), bgColor);
|
||||
|
||||
RenderGrid();
|
||||
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
if (ImGui::BeginTabItem("Game")) {
|
||||
m_isSceneView = false;
|
||||
ImVec2 canvasSize = ImGui::GetContentRegionAvail();
|
||||
ImDrawList* drawList = ImGui::GetWindowDrawList();
|
||||
ImVec2 canvasPos = ImGui::GetCursorScreenPos();
|
||||
|
||||
ImU32 bgColor = IM_COL32(20, 20, 25, 255);
|
||||
drawList->AddRectFilled(canvasPos, ImVec2(canvasPos.x + canvasSize.x, canvasPos.y + canvasSize.y), bgColor);
|
||||
|
||||
const char* text = "Game View (Press Play)";
|
||||
ImVec2 textSize = ImGui::CalcTextSize(text);
|
||||
ImVec2 textPos(canvasPos.x + (canvasSize.x - textSize.x) * 0.5f, canvasPos.y + (canvasSize.y - textSize.y) * 0.5f);
|
||||
drawList->AddText(textPos, IM_COL32(128, 128, 128, 255), text);
|
||||
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
ImGui::EndTabBar();
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
void SceneViewPanel::RenderGrid() {
|
||||
ImDrawList* drawList = ImGui::GetWindowDrawList();
|
||||
ImVec2 canvasPos = ImGui::GetCursorScreenPos();
|
||||
ImVec2 canvasSize = ImGui::GetContentRegionAvail();
|
||||
|
||||
float gridSize = 50.0f;
|
||||
ImU32 gridColor = IM_COL32(50, 50, 50, 255);
|
||||
|
||||
for (float x = fmodf(0, gridSize); x < canvasSize.x; x += gridSize) {
|
||||
drawList->AddLine(
|
||||
ImVec2(canvasPos.x + x, canvasPos.y),
|
||||
ImVec2(canvasPos.x + x, canvasPos.y + canvasSize.y),
|
||||
gridColor
|
||||
);
|
||||
}
|
||||
|
||||
for (float y = fmodf(0, gridSize); y < canvasSize.y; y += gridSize) {
|
||||
drawList->AddLine(
|
||||
ImVec2(canvasPos.x, canvasPos.y + y),
|
||||
ImVec2(canvasPos.x + canvasSize.x, canvasPos.y + y),
|
||||
gridColor
|
||||
);
|
||||
}
|
||||
|
||||
const char* label = "Scene View";
|
||||
ImVec2 labelSize = ImGui::CalcTextSize(label);
|
||||
ImVec2 labelPos(canvasPos.x + 10, canvasPos.y + 10);
|
||||
drawList->AddText(labelPos, IM_COL32(100, 100, 100, 255), label);
|
||||
}
|
||||
|
||||
}
|
||||
17
ui/src/panels/SceneViewPanel.h
Normal file
17
ui/src/panels/SceneViewPanel.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include "Panel.h"
|
||||
|
||||
namespace UI {
|
||||
|
||||
class SceneViewPanel : public Panel {
|
||||
public:
|
||||
SceneViewPanel();
|
||||
void Render() override;
|
||||
|
||||
private:
|
||||
bool m_isSceneView = true;
|
||||
void RenderGrid();
|
||||
};
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user