1
0
Fork 0
Univerxel/src/render/UI.cpp

218 lines
11 KiB
C++

#include "UI.hpp"
#include "imgui_impl_glfw.h"
#include "imgui_impl_opengl3.h"
#include "pass/Program.hpp"
#include "../contouring/Abstract.hpp"
void UI::setup(GLFWwindow* window) {
// Setup Dear ImGui context
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGui::StyleColorsDark();
// Setup Platform/Renderer bindings
ImGui_ImplGlfw_InitForOpenGL(window, true);
ImGui_ImplOpenGL3_Init("#version 130");
}
void UI::unload() {
ImGui_ImplGlfw_Shutdown();
ImGui_ImplOpenGL3_Shutdown();
ImGui::DestroyContext();
}
UI::Actions UI::draw(options &options, state &state, const reports &reports, GLuint aim) {
auto actions = Actions::None;
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
const ImGuiIO &io = ImGui::GetIO();
if(state.capture_mouse) {
ImGui::SetNextWindowPos(ImVec2(io.DisplaySize.x / 2, io.DisplaySize.y / 2), ImGuiCond_Always, ImVec2(.5f, .5f));
ImGui::Begin("Aim", NULL, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav | ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoInputs);
ImGui::Image((void *)(intptr_t)aim, ImVec2(32, 32));
ImGui::End();
}
if (options.show_debug_menu) {
ImGui::BeginMainMenuBar();
ImGui::Checkbox("Render", &options.show_debug_render);
ImGui::Checkbox("World", &options.show_debug_world);
ImGui::Checkbox("Contouring", &options.show_debug_contouring);
ImGui::Checkbox("Controls", &options.show_debug_controls);
if(ImGui::MenuItem("Close"))
options.show_debug_menu = false;
ImGui::EndMainMenuBar();
}
if (options.show_debug_render) {
ImGui::Begin("Debug: Render", &options.show_debug_render, ImGuiWindowFlags_AlwaysAutoResize);
ImGui::PlotHistogram("FPS", reports.main.fps.buffer.get(), reports.main.fps.size, 0, std::to_string(reports.main.fps.current()).c_str(), 0, options.target_fps >= MIN_FPS && options.target_fps <= MAX_FPS ? options.target_fps * 1.2 : FLT_MAX, ImVec2(0, 30));
ImGui::PlotHistogram("Update", reports.main.update.buffer.get(), reports.main.update.size, 0, std::to_string(reports.main.update.current()).c_str(), 0);
ImGui::PlotHistogram("Render", reports.main.render.buffer.get(), reports.main.render.size, 0, std::to_string(reports.main.render.current()).c_str(), 0);
ImGui::PlotHistogram("Swap", reports.main.swap.buffer.get(), reports.main.swap.size, 0, std::to_string(reports.main.swap.current()).c_str(), 0);
ImGui::PlotHistogram("Wait", reports.main.wait.buffer.get(), reports.main.wait.size, 0, std::to_string(reports.main.wait.current()).c_str(), 0);
ImGui::Text("Tris: %ld (%ld models)", reports.main.tris_count, reports.main.models_count);
ImGui::Separator();
ImGui::Checkbox("Overlay", &options.overlay_show);
if (ImGui::SliderInt("FPS", &options.target_fps, MIN_FPS-1, MAX_FPS+1, options.target_fps > MIN_FPS ? (options.target_fps < MAX_FPS ? "%d" : "UNLIMITED") : "VSYNC")){
actions = actions | Actions::FPS;
}
ImGui::Text("Sampling %d (requires restart)", options.samples);
if (ImGui::Checkbox("Fullscreen", &options.fullscreen)){
actions = actions | Actions::FullScreen;
}
if (ImGui::ColorEdit3("Fog color", (float *)&options.renderer.clear_color)) {
actions = actions | Actions::ClearColor;
}
{
bool changeRenderer = false;
changeRenderer |= ImGui::Checkbox("PBR", &options.renderer.main.pbr);
ImGui::SameLine();
changeRenderer |= ImGui::Checkbox("Triplanar", &options.renderer.main.triplanar);
changeRenderer |= ImGui::Checkbox("Fog", &options.renderer.main.fog);
ImGui::SameLine();
ImGui::Checkbox("Skybox", &options.renderer.skybox);
if (changeRenderer) {
actions = actions | Actions::RendererSharders;
}
}
if (ImGui::Checkbox("Wireframe", &options.renderer.wireframe))
glPolygonMode(GL_FRONT_AND_BACK, options.renderer.wireframe ? GL_LINE : GL_FILL);
ImGui::Text("Textures '%s'", options.renderer.textures.c_str()); // MAYBE: select
if (ImGui::SliderFloat("LOD", &options.renderer.mipMapLOD, -1, 1)) {
actions = actions | Actions::RendererTextures;
}
ImGui::End();
}
if (options.show_debug_world) {
ImGui::Begin("Debug: World", &options.show_debug_world, ImGuiWindowFlags_AlwaysAutoResize);
ImGui::PlotHistogram("Count", reports.world.chunk_count.buffer.get(), reports.world.chunk_count.size, 0, std::to_string(reports.world.chunk_count.current()).c_str(), 0);
ImGui::PlotHistogram("Loading", reports.world.chunk_load.buffer.get(), reports.world.chunk_load.size, 0, std::to_string(reports.world.chunk_load.current()).c_str(), 0);
ImGui::PlotHistogram("Saving", reports.world.chunk_unload.buffer.get(), reports.world.chunk_unload.size, 0, std::to_string(reports.world.chunk_unload.current()).c_str(), 0);
ImGui::Separator();
if (ImGui::SliderInt("Load distance", &options.world.loadDistance, 1, options.world.keepDistance) |
ImGui::SliderInt("Keep distance", &options.world.keepDistance, options.world.loadDistance + 1, 21)) {
actions = actions | Actions::World;
const auto far = std::clamp(options.camera.far, (options.world.loadDistance - 1.5f) * CHUNK_LENGTH * options.voxel_size, (options.world.keepDistance + .5f) * CHUNK_LENGTH * options.voxel_size);
if(far != options.camera.far) {
options.camera.far = far;
actions = actions | Actions::Camera;
}
}
ImGui::SliderFloat("Voxel size", &options.voxel_size, .1, 2);
ImGui::End();
}
if (options.show_debug_contouring) {
ImGui::Begin("Debug: Contouring", &options.show_debug_contouring, ImGuiWindowFlags_AlwaysAutoResize);
const auto prev_idx = options.contouring_idx;
if(ImGui::Combo("Contouring", &options.contouring_idx, contouring::cnames.c_str())) {
actions = actions | Actions::ChangeContouring;
contouring::save(prev_idx, state.contouring, options.contouring_data);
}
ImGui::Checkbox("Culling", &options.culling);
state.contouring->onGui();
ImGui::End();
}
if (options.show_debug_controls) {
ImGui::Begin("Debug: Controls", &options.show_debug_controls, ImGuiWindowFlags_AlwaysAutoResize);
ImGui::Text("Position: (%.3f, %.3f, %.3f)", state.position.x, state.position.y, state.position.z);
if (state.look_at.has_value()) {
ImGui::Text("Look at: (%lld, %lld, %lld) (%d, %.1d)", state.look_at.value().first.x, state.look_at.value().first.y, state.look_at.value().first.z, state.look_at.value().second.Material, state.look_at.value().second.Density / UCHAR_MAX);
ImGui::Text("(%.3f, %.3f, %.3f)", state.look_at.value().first.x * options.voxel_size, state.look_at.value().first.y * options.voxel_size, state.look_at.value().first.z * options.voxel_size);
} else {
ImGui::Text("Look at: none");
}
ImGui::Separator();
{
bool changePerspective = false;
changePerspective |= ImGui::SliderAngle("FoV", &options.camera.fov, 30, 110);
changePerspective |= ImGui::SliderFloat("Near", &options.camera.near, 0.01, 10);
changePerspective |= ImGui::SliderFloat("Far", &options.camera.far, (options.world.loadDistance - 1.5) * CHUNK_LENGTH * options.voxel_size, (options.world.keepDistance + .5) * CHUNK_LENGTH * options.voxel_size);
changePerspective |= ImGui::SliderFloat("Move speed", &options.camera.speed, 0.1, 50);
changePerspective |= ImGui::SliderInt("Sensibility", &options.camera.sensibility, 1, 100, "%d%%");
if(changePerspective) {
actions = actions | Actions::Camera;
}
}
ImGui::End();
}
/*if (show_console) {
ImGui::SetNextWindowPos(ImVec2(UI_MARGIN, 500), ImGuiCond_FirstUseEver);
ImGui::SetNextWindowSize(ImVec2(200, 100), ImGuiCond_FirstUseEver);
ImGui::Begin("Console", &show_console, ImGuiWindowFlags_MenuBar);
ImGui::BeginMenuBar();
ImGui::MenuItem("Auto-scrool", NULL, &console_scrool);
ImGui::EndMenuBar();
// TODO: text
ImGui::Separator();
// Command-line
bool reclaim_focus = false;
// TODO: completion callback
if (ImGui::InputText("Input", console_buffer, IM_ARRAYSIZE(console_buffer), ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_CallbackHistory)) {
char *s = console_buffer;
//Strtrim(s);
//if (s[0])
// ExecCommand(s);
strcpy(s, "");
reclaim_focus = true;
}
// Auto-focus on window apparition
ImGui::SetItemDefaultFocus();
if (reclaim_focus)
ImGui::SetKeyboardFocusHere(-1); // Auto focus previous widget
ImGui::End();
}*/
if (options.overlay_show) {
if (options.overlay_corner != -1) {
ImVec2 window_pos = ImVec2((options.overlay_corner & 1) ? io.DisplaySize.x - UI_MARGIN : UI_MARGIN, (options.overlay_corner & 2) ? io.DisplaySize.y - UI_MARGIN : UI_MARGIN);
ImVec2 window_pos_pivot = ImVec2((options.overlay_corner & 1) ? 1.0f : 0.0f, (options.overlay_corner & 2) ? 1.0f : 0.0f);
ImGui::SetNextWindowPos(window_pos, ImGuiCond_Always, window_pos_pivot);
}
ImGui::SetNextWindowBgAlpha(0.35f); // Transparent background
ImGui::Begin("Overlay", &options.overlay_show, (options.overlay_corner != -1 ? ImGuiWindowFlags_NoMove : 0) | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav);
ImGui::Text("%.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate);
ImGui::Text("%ld tris(%ld models)", reports.main.tris_count, reports.main.models_count);
if (ImGui::BeginPopupContextWindow()) {
if (ImGui::MenuItem("Custom", NULL, options.overlay_corner == -1))
options.overlay_corner = -1;
if (ImGui::MenuItem("Top-left", NULL, options.overlay_corner == 0))
options.overlay_corner = 0;
if (ImGui::MenuItem("Top-right", NULL, options.overlay_corner == 1))
options.overlay_corner = 1;
if (ImGui::MenuItem("Bottom-left", NULL, options.overlay_corner == 2))
options.overlay_corner = 2;
if (ImGui::MenuItem("Bottom-right", NULL, options.overlay_corner == 3))
options.overlay_corner = 3;
if (options.overlay_show && ImGui::MenuItem("Close"))
options.overlay_show = false;
ImGui::EndPopup();
}
ImGui::End();
}
ImGui::Render();
return actions;
}
void UI::render() {
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
}
bool UI::isFocus() {
return ImGui::IsAnyItemActive();
}