ImGui + Dockspace¶
imgui を dockspace branch に切り替えて dockspace を使う。
#include <banana/dockspace.h>
#include <gorilla/device_and_target.h>
#include <gorilla/drawable.h>
#include <gorilla/texture_and_target.h>
#include <gorilla/window.h>
//
#include <imgui.h>
#include <imgui_impl_dx11.h>
//
#include <chrono>
#include <iostream>
#include <list>
#include <string_view>
auto CLASS_NAME = "CLASS_NAME";
auto WINDOW_TITLE = "ImGuiDockspace";
auto WIDTH = 640;
auto HEIGHT = 480;
template <typename T> using ComPtr = Microsoft::WRL::ComPtr<T>;
class DockSpace {
std::chrono::system_clock::time_point last = {};
std::list<banana::Dock> _docks;
public:
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
banana::OrbitCamera view_camera;
gorilla::Drawable view_drawable;
gorilla::TextureAndTarget view_rt;
ImVec4 view_clear_color = ImVec4(0.6f, 0.35f, 0.60f, 1.00f);
DockSpace(const ComPtr<ID3D11Device> &device,
const ComPtr<ID3D11DeviceContext> &context) {
// Setup Dear ImGui context
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO &io = ImGui::GetIO();
(void)io;
// io.ConfigFlags |=
// ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
// io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable
// Gamepad Controls
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking
io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; // Enable Multi-Viewport
// / Platform Windows
// io.ConfigViewportsNoAutoMerge = true;
// io.ConfigViewportsNoTaskBarIcon = true;
// io.ConfigViewportsNoDefaultParent = true;
// io.ConfigDockingAlwaysTabBar = true;
// io.ConfigDockingTransparentPayload = true;
// io.ConfigFlags |= ImGuiConfigFlags_DpiEnableScaleFonts; // FIXME-DPI:
// Experimental. THIS CURRENTLY DOESN'T WORK AS EXPECTED. DON'T USE IN USER
// APP! io.ConfigFlags |= ImGuiConfigFlags_DpiEnableScaleViewports; //
// FIXME-DPI: Experimental.
// Setup Dear ImGui style
ImGui::StyleColorsDark();
// ImGui::StyleColorsClassic();
// When viewports are enabled we tweak WindowRounding/WindowBg so platform
// windows can look identical to regular ones.
ImGuiStyle &style = ImGui::GetStyle();
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) {
style.WindowRounding = 0.0f;
style.Colors[ImGuiCol_WindowBg].w = 1.0f;
}
// Setup Platform/Renderer backends
// ImGui_ImplWin32_Init(hwnd);
ImGui_ImplDX11_Init(device.Get(), context.Get());
//
// initialize docks
//
// 1. Show the big demo window (Most of the sample code is in
// ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear
// ImGui!).
auto demo = _docks.emplace_back(banana::Dock{"demo", &ImGui::ShowDemoWindow});
// 3. Show another simple window.
auto show_another = [](bool *p_open) {
ImGui::Begin("Another Window",
p_open); // Pass a pointer to our bool variable (the
// window will have a closing button that will
// clear the bool when clicked)
ImGui::Text("Hello from another window!");
if (ImGui::Button("Close Me"))
*p_open = false;
ImGui::End();
};
auto another = _docks.emplace_back(banana::Dock{"another", show_another});
// 2. Show a simple window that we create ourselves. We use a Begin/End pair
// to created a named window.
auto show_hello = [&demo, &another,
&clear_color = this->clear_color](bool *p_open) {
static float f = 0.0f;
static int counter = 0;
ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!"
// and append into it.
ImGui::Text("This is some useful text."); // Display some text (you can
// use a format strings too)
ImGui::Checkbox(
"Demo Window",
&demo.open); // Edit bools storing our window open/close state
ImGui::Checkbox("Another Window", &another.open);
ImGui::SliderFloat("float", &f, 0.0f,
1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
ImGui::ColorEdit3(
"clear color",
(float *)&clear_color); // Edit 3 floats representing a color
if (ImGui::Button("Button")) // Buttons return true when clicked (most
// widgets return true when edited/activated)
counter++;
ImGui::SameLine();
ImGui::Text("counter = %d", counter);
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)",
1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
ImGui::End();
};
_docks.push_back({"hello", show_hello});
}
~DockSpace() {
// Cleanup
ImGui_ImplDX11_Shutdown();
// ImGui_ImplWin32_Shutdown();
ImGui::DestroyContext();
}
void update(const ComPtr<ID3D11DeviceContext> &context,
const gorilla::ScreenState &state) {
//
// update custom backend
//
ImGuiIO &io = ImGui::GetIO();
if (last == std::chrono::system_clock::time_point{}) {
} else {
io.DeltaTime = std::chrono::duration_cast<std::chrono::milliseconds>(
state.time - last)
.count() *
0.001f;
}
if (io.DeltaTime == 0) {
io.DeltaTime = 0.016f;
}
last = state.time;
io.DisplaySize = {state.width, state.height};
io.MousePos = {state.mouse_x, state.mouse_y};
io.MouseDown[0] = state.mouse_button_flag & gorilla::MouseButtonLeftDown;
io.MouseDown[1] = state.mouse_button_flag & gorilla::MouseButtonRightDown;
io.MouseDown[2] = state.mouse_button_flag & gorilla::MouseButtonMiddleDown;
io.MouseWheel = state.wheel;
// Start the Dear ImGui frame
ImGui_ImplDX11_NewFrame();
// ImGui_ImplWin32_NewFrame();
ImGui::NewFrame();
dockspace(_docks);
// Rendering
ImGui::Render();
}
void render() { ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData()); }
};
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow) {
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
gorilla::Window window;
auto hwnd = window.create(hInstance, CLASS_NAME, WINDOW_TITLE, WIDTH, HEIGHT);
if (!hwnd) {
return 1;
}
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
gorilla::DeviceAndTarget renderer;
auto [device, context] = renderer.create(hwnd);
if (!device) {
return 2;
}
//
// main loop
//
DockSpace gui(device, context);
gorilla::ScreenState state;
for (UINT frame_count = 0; window.process_messages(&state); ++frame_count) {
gui.update(context, state);
// draw
renderer.begin_frame(state, &gui.clear_color.x);
gui.render();
renderer.end_frame();
}
return 0;
}