WIP DearImGui conversion

This commit is contained in:
Graham Pentheny
2025-07-10 11:11:54 -04:00
parent 9af5723d32
commit 6b906538dc
15 changed files with 862 additions and 302 deletions

View File

@@ -0,0 +1,346 @@
// dear imgui: Renderer Backend for OpenGL2 (legacy OpenGL, fixed pipeline)
// This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..)
// Implemented features:
// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture as texture identifier. Read the FAQ about ImTextureID/ImTextureRef!
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
// Missing features or Issues:
// [ ] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
// Learn about Dear ImGui:
// - FAQ https://dearimgui.com/faq
// - Getting Started https://dearimgui.com/getting-started
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
// - Introduction, links and more at the top of imgui.cpp
// **DO NOT USE THIS CODE IF YOUR CODE/ENGINE IS USING MODERN OPENGL (SHADERS, VBO, VAO, etc.)**
// **Prefer using the code in imgui_impl_opengl3.cpp**
// This code is mostly provided as a reference to learn how ImGui integration works, because it is shorter to read.
// If your code is using GL3+ context or any semi modern OpenGL calls, using this is likely to make everything more
// complicated, will require your code to reset every single OpenGL attributes to their initial state, and might
// confuse your GPU driver.
// The GL2 code is unable to reset attributes or even call e.g. "glUseProgram(0)" because they don't exist in that API.
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2025-06-11: OpenGL: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas. Removed ImGui_ImplOpenGL2_CreateFontsTexture() and ImGui_ImplOpenGL2_DestroyFontsTexture().
// 2024-10-07: OpenGL: Changed default texture sampler to Clamp instead of Repeat/Wrap.
// 2024-06-28: OpenGL: ImGui_ImplOpenGL2_NewFrame() recreates font texture if it has been destroyed by ImGui_ImplOpenGL2_DestroyFontsTexture(). (#7748)
// 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11.
// 2021-12-08: OpenGL: Fixed mishandling of the ImDrawCmd::IdxOffset field! This is an old bug but it never had an effect until some internal rendering changes in 1.86.
// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
// 2021-05-19: OpenGL: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
// 2021-01-03: OpenGL: Backup, setup and restore GL_SHADE_MODEL state, disable GL_STENCIL_TEST and disable GL_NORMAL_ARRAY client state to increase compatibility with legacy OpenGL applications.
// 2020-01-23: OpenGL: Backup, setup and restore GL_TEXTURE_ENV to increase compatibility with legacy OpenGL applications.
// 2019-04-30: OpenGL: Added support for special ImDrawCallback_ResetRenderState callback to reset render state.
// 2019-02-11: OpenGL: Projecting clipping rectangles correctly using draw_data->FramebufferScale to allow multi-viewports for retina display.
// 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window.
// 2018-08-03: OpenGL: Disabling/restoring GL_LIGHTING and GL_COLOR_MATERIAL to increase compatibility with legacy OpenGL applications.
// 2018-06-08: Misc: Extracted imgui_impl_opengl2.cpp/.h away from the old combined GLFW/SDL+OpenGL2 examples.
// 2018-06-08: OpenGL: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle.
// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplOpenGL2_RenderDrawData() in the .h file so you can call it yourself.
// 2017-09-01: OpenGL: Save and restore current polygon mode.
// 2016-09-10: OpenGL: Uploading font texture as RGBA32 to increase compatibility with users shaders (not ideal).
// 2016-09-05: OpenGL: Fixed save and restore of current scissor rectangle.
#include "imgui.h"
#ifndef IMGUI_DISABLE
#include "imgui_impl_opengl2.h"
#include <stdint.h> // intptr_t
// Clang/GCC warnings with -Weverything
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-macros" // warning: macro is not used
#pragma clang diagnostic ignored "-Wnonportable-system-include-path"
#endif
// Include OpenGL header (without an OpenGL loader) requires a bit of fiddling
#if defined(_WIN32) && !defined(APIENTRY)
#define APIENTRY __stdcall // It is customary to use APIENTRY for OpenGL function pointer declarations on all platforms. Additionally, the Windows OpenGL header needs APIENTRY.
#endif
#if defined(_WIN32) && !defined(WINGDIAPI)
#define WINGDIAPI __declspec(dllimport) // Some Windows OpenGL headers need this
#endif
#if defined(__APPLE__)
#define GL_SILENCE_DEPRECATION
#include <OpenGL/gl.h>
#else
#include <GL/gl.h>
#endif
// [Debugging]
//#define IMGUI_IMPL_OPENGL_DEBUG
#ifdef IMGUI_IMPL_OPENGL_DEBUG
#include <stdio.h>
#define GL_CALL(_CALL) do { _CALL; GLenum gl_err = glGetError(); if (gl_err != 0) fprintf(stderr, "GL error 0x%x returned from '%s'.\n", gl_err, #_CALL); } while (0) // Call with error check
#else
#define GL_CALL(_CALL) _CALL // Call without error check
#endif
// OpenGL data
struct ImGui_ImplOpenGL2_Data
{
ImGui_ImplOpenGL2_Data() { memset((void*)this, 0, sizeof(*this)); }
};
// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts
// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.
static ImGui_ImplOpenGL2_Data* ImGui_ImplOpenGL2_GetBackendData()
{
return ImGui::GetCurrentContext() ? (ImGui_ImplOpenGL2_Data*)ImGui::GetIO().BackendRendererUserData : nullptr;
}
// Functions
bool ImGui_ImplOpenGL2_Init()
{
ImGuiIO& io = ImGui::GetIO();
IMGUI_CHECKVERSION();
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
// Setup backend capabilities flags
ImGui_ImplOpenGL2_Data* bd = IM_NEW(ImGui_ImplOpenGL2_Data)();
io.BackendRendererUserData = (void*)bd;
io.BackendRendererName = "imgui_impl_opengl2";
io.BackendFlags |= ImGuiBackendFlags_RendererHasTextures; // We can honor ImGuiPlatformIO::Textures[] requests during render.
return true;
}
void ImGui_ImplOpenGL2_Shutdown()
{
ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_GetBackendData();
IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?");
ImGuiIO& io = ImGui::GetIO();
ImGui_ImplOpenGL2_DestroyDeviceObjects();
io.BackendRendererName = nullptr;
io.BackendRendererUserData = nullptr;
io.BackendFlags &= ~(ImGuiBackendFlags_RendererHasTextures);
IM_DELETE(bd);
}
void ImGui_ImplOpenGL2_NewFrame()
{
ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_GetBackendData();
IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplOpenGL2_Init()?");
IM_UNUSED(bd);
}
static void ImGui_ImplOpenGL2_SetupRenderState(ImDrawData* draw_data, int fb_width, int fb_height)
{
// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers, polygon fill.
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
//glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); // In order to composite our output buffer we need to preserve alpha
glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
glDisable(GL_STENCIL_TEST);
glDisable(GL_LIGHTING);
glDisable(GL_COLOR_MATERIAL);
glEnable(GL_SCISSOR_TEST);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glEnable(GL_TEXTURE_2D);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glShadeModel(GL_SMOOTH);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
// If you are using this code with non-legacy OpenGL header/contexts (which you should not, prefer using imgui_impl_opengl3.cpp!!),
// you may need to backup/reset/restore other state, e.g. for current shader using the commented lines below.
// (DO NOT MODIFY THIS FILE! Add the code in your calling function)
// GLint last_program;
// glGetIntegerv(GL_CURRENT_PROGRAM, &last_program);
// glUseProgram(0);
// ImGui_ImplOpenGL2_RenderDrawData(...);
// glUseProgram(last_program)
// There are potentially many more states you could need to clear/setup that we can't access from default headers.
// e.g. glBindBuffer(GL_ARRAY_BUFFER, 0), glDisable(GL_TEXTURE_CUBE_MAP).
// Setup viewport, orthographic projection matrix
// Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps.
GL_CALL(glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height));
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(draw_data->DisplayPos.x, draw_data->DisplayPos.x + draw_data->DisplaySize.x, draw_data->DisplayPos.y + draw_data->DisplaySize.y, draw_data->DisplayPos.y, -1.0f, +1.0f);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
}
// OpenGL2 Render function.
// Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly.
// This is in order to be able to run within an OpenGL engine that doesn't do so.
void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data)
{
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x);
int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y);
if (fb_width == 0 || fb_height == 0)
return;
// Catch up with texture updates. Most of the times, the list will have 1 element with an OK status, aka nothing to do.
// (This almost always points to ImGui::GetPlatformIO().Textures[] but is part of ImDrawData to allow overriding or disabling texture updates).
if (draw_data->Textures != nullptr)
for (ImTextureData* tex : *draw_data->Textures)
if (tex->Status != ImTextureStatus_OK)
ImGui_ImplOpenGL2_UpdateTexture(tex);
// Backup GL state
GLint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
GLint last_polygon_mode[2]; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode);
GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport);
GLint last_scissor_box[4]; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box);
GLint last_shade_model; glGetIntegerv(GL_SHADE_MODEL, &last_shade_model);
GLint last_tex_env_mode; glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &last_tex_env_mode);
glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT);
// Setup desired GL state
ImGui_ImplOpenGL2_SetupRenderState(draw_data, fb_width, fb_height);
// Will project scissor/clipping rectangles into framebuffer space
ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports
ImVec2 clip_scale = draw_data->FramebufferScale; // (1,1) unless using retina display which are often (2,2)
// Render command lists
for (int n = 0; n < draw_data->CmdListsCount; n++)
{
const ImDrawList* draw_list = draw_data->CmdLists[n];
const ImDrawVert* vtx_buffer = draw_list->VtxBuffer.Data;
const ImDrawIdx* idx_buffer = draw_list->IdxBuffer.Data;
glVertexPointer(2, GL_FLOAT, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + offsetof(ImDrawVert, pos)));
glTexCoordPointer(2, GL_FLOAT, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + offsetof(ImDrawVert, uv)));
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + offsetof(ImDrawVert, col)));
for (int cmd_i = 0; cmd_i < draw_list->CmdBuffer.Size; cmd_i++)
{
const ImDrawCmd* pcmd = &draw_list->CmdBuffer[cmd_i];
if (pcmd->UserCallback)
{
// User callback, registered via ImDrawList::AddCallback()
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
ImGui_ImplOpenGL2_SetupRenderState(draw_data, fb_width, fb_height);
else
pcmd->UserCallback(draw_list, pcmd);
}
else
{
// Project scissor/clipping rectangles into framebuffer space
ImVec2 clip_min((pcmd->ClipRect.x - clip_off.x) * clip_scale.x, (pcmd->ClipRect.y - clip_off.y) * clip_scale.y);
ImVec2 clip_max((pcmd->ClipRect.z - clip_off.x) * clip_scale.x, (pcmd->ClipRect.w - clip_off.y) * clip_scale.y);
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
continue;
// Apply scissor/clipping rectangle (Y is inverted in OpenGL)
glScissor((int)clip_min.x, (int)((float)fb_height - clip_max.y), (int)(clip_max.x - clip_min.x), (int)(clip_max.y - clip_min.y));
// Bind texture, Draw
glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->GetTexID());
glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer + pcmd->IdxOffset);
}
}
}
// Restore modified GL state
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glBindTexture(GL_TEXTURE_2D, (GLuint)last_texture);
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glPopAttrib();
glPolygonMode(GL_FRONT, (GLenum)last_polygon_mode[0]); glPolygonMode(GL_BACK, (GLenum)last_polygon_mode[1]);
glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]);
glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]);
glShadeModel(last_shade_model);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, last_tex_env_mode);
}
void ImGui_ImplOpenGL2_UpdateTexture(ImTextureData* tex)
{
if (tex->Status == ImTextureStatus_WantCreate)
{
// Create and upload new texture to graphics system
//IMGUI_DEBUG_LOG("UpdateTexture #%03d: WantCreate %dx%d\n", tex->UniqueID, tex->Width, tex->Height);
IM_ASSERT(tex->TexID == 0 && tex->BackendUserData == nullptr);
IM_ASSERT(tex->Format == ImTextureFormat_RGBA32);
const void* pixels = tex->GetPixels();
GLuint gl_texture_id = 0;
// Upload texture to graphics system
// (Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling)
GLint last_texture;
GL_CALL(glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture));
GL_CALL(glGenTextures(1, &gl_texture_id));
GL_CALL(glBindTexture(GL_TEXTURE_2D, gl_texture_id));
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP));
GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP));
GL_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH, 0));
GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex->Width, tex->Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels));
// Store identifiers
tex->SetTexID((ImTextureID)(intptr_t)gl_texture_id);
tex->SetStatus(ImTextureStatus_OK);
// Restore state
GL_CALL(glBindTexture(GL_TEXTURE_2D, last_texture));
}
else if (tex->Status == ImTextureStatus_WantUpdates)
{
// Update selected blocks. We only ever write to textures regions which have never been used before!
// This backend choose to use tex->Updates[] but you can use tex->UpdateRect to upload a single region.
GLint last_texture;
GL_CALL(glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture));
GLuint gl_tex_id = (GLuint)(intptr_t)tex->TexID;
GL_CALL(glBindTexture(GL_TEXTURE_2D, gl_tex_id));
GL_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH, tex->Width));
for (ImTextureRect& r : tex->Updates)
GL_CALL(glTexSubImage2D(GL_TEXTURE_2D, 0, r.x, r.y, r.w, r.h, GL_RGBA, GL_UNSIGNED_BYTE, tex->GetPixelsAt(r.x, r.y)));
GL_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH, 0));
GL_CALL(glBindTexture(GL_TEXTURE_2D, last_texture)); // Restore state
tex->SetStatus(ImTextureStatus_OK);
}
else if (tex->Status == ImTextureStatus_WantDestroy)
{
GLuint gl_tex_id = (GLuint)(intptr_t)tex->TexID;
glDeleteTextures(1, &gl_tex_id);
// Clear identifiers and mark as destroyed (in order to allow e.g. calling InvalidateDeviceObjects while running)
tex->SetTexID(ImTextureID_Invalid);
tex->SetStatus(ImTextureStatus_Destroyed);
}
}
bool ImGui_ImplOpenGL2_CreateDeviceObjects()
{
return true;
}
void ImGui_ImplOpenGL2_DestroyDeviceObjects()
{
for (ImTextureData* tex : ImGui::GetPlatformIO().Textures)
if (tex->RefCount == 1)
{
tex->SetStatus(ImTextureStatus_WantDestroy);
ImGui_ImplOpenGL2_UpdateTexture(tex);
}
}
//-----------------------------------------------------------------------------
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
#endif // #ifndef IMGUI_DISABLE

View File

@@ -0,0 +1,43 @@
// dear imgui: Renderer Backend for OpenGL2 (legacy OpenGL, fixed pipeline)
// This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..)
// Implemented features:
// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture as texture identifier. Read the FAQ about ImTextureID/ImTextureRef!
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
// Missing features or Issues:
// [ ] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
// Learn about Dear ImGui:
// - FAQ https://dearimgui.com/faq
// - Getting Started https://dearimgui.com/getting-started
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
// - Introduction, links and more at the top of imgui.cpp
// **DO NOT USE THIS CODE IF YOUR CODE/ENGINE IS USING MODERN OPENGL (SHADERS, VBO, VAO, etc.)**
// **Prefer using the code in imgui_impl_opengl3.cpp**
// This code is mostly provided as a reference to learn how ImGui integration works, because it is shorter to read.
// If your code is using GL3+ context or any semi modern OpenGL calls, using this is likely to make everything more
// complicated, will require your code to reset every single OpenGL attributes to their initial state, and might
// confuse your GPU driver.
// The GL2 code is unable to reset attributes or even call e.g. "glUseProgram(0)" because they don't exist in that API.
#pragma once
#include "imgui.h" // IMGUI_IMPL_API
#ifndef IMGUI_DISABLE
// Follow "Getting Started" link and check examples/ folder to learn about using backends!
IMGUI_IMPL_API bool ImGui_ImplOpenGL2_Init();
IMGUI_IMPL_API void ImGui_ImplOpenGL2_Shutdown();
IMGUI_IMPL_API void ImGui_ImplOpenGL2_NewFrame();
IMGUI_IMPL_API void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data);
// Called by Init/NewFrame/Shutdown
IMGUI_IMPL_API bool ImGui_ImplOpenGL2_CreateDeviceObjects();
IMGUI_IMPL_API void ImGui_ImplOpenGL2_DestroyDeviceObjects();
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = NULL to handle this manually.
IMGUI_IMPL_API void ImGui_ImplOpenGL2_UpdateTexture(ImTextureData* tex);
#endif // #ifndef IMGUI_DISABLE

View File

@@ -116,6 +116,7 @@ bool pointInPoly(int nvert, const float* verts, const float* p)
void ConvexVolumeTool::handleMenu()
{
#if 0
imguiSlider("Shape Height", &boxHeight, 0.1f, 20.0f, 0.1f);
imguiSlider("Shape Descent", &boxDescent, 0.1f, 20.0f, 0.1f);
imguiSlider("Poly Offset", &polyOffset, 0.0f, 10.0f, 0.1f);
@@ -157,6 +158,7 @@ void ConvexVolumeTool::handleMenu()
numPoints = 0;
numHull = 0;
}
#endif
}
void ConvexVolumeTool::handleClick(const float* /*s*/, const float* p, bool shift)
@@ -294,6 +296,7 @@ void ConvexVolumeTool::handleRender()
void ConvexVolumeTool::handleRenderOverlay(double* /*proj*/, double* /*model*/, int* view)
{
#if 0
// Tool help
const int h = view[3];
if (!numPoints)
@@ -320,4 +323,5 @@ void ConvexVolumeTool::handleRenderOverlay(double* /*proj*/, double* /*model*/,
"The shape will be convex hull of all added points.",
imguiRGBA(255, 255, 255, 192));
}
#endif
}

View File

@@ -506,7 +506,9 @@ void CrowdToolState::handleRenderOverlay(double* proj, double* model, int* view)
if (m_targetRef &&
gluProject((GLdouble)m_targetPos[0], (GLdouble)m_targetPos[1], (GLdouble)m_targetPos[2], model, proj, view, &x, &y, &z))
{
#if 0
imguiDrawText((int)x, (int)(y + 25), IMGUI_ALIGN_CENTER, "TARGET", imguiRGBA(0, 0, 0, 220));
#endif
}
char label[32];
@@ -540,7 +542,9 @@ void CrowdToolState::handleRenderOverlay(double* proj, double* model, int* view)
{
const float heuristic = node->total; // - node->cost;
snprintf(label, 32, "%.2f", heuristic);
#if 0
imguiDrawText((int)x, (int)y + 15, IMGUI_ALIGN_CENTER, label, imguiRGBA(0, 0, 0, 220));
#endif
}
}
}
@@ -562,7 +566,9 @@ void CrowdToolState::handleRenderOverlay(double* proj, double* model, int* view)
if (gluProject((GLdouble)pos[0], (GLdouble)pos[1] + h, (GLdouble)pos[2], model, proj, view, &x, &y, &z))
{
snprintf(label, 32, "%d", i);
#if 0
imguiDrawText((int)x, (int)y + 15, IMGUI_ALIGN_CENTER, label, imguiRGBA(0, 0, 0, 220));
#endif
}
}
}
@@ -596,7 +602,9 @@ void CrowdToolState::handleRenderOverlay(double* proj, double* model, int* view)
&z))
{
snprintf(label, 32, "%.3f", ag->neis[j].dist);
#if 0
imguiDrawText((int)x, (int)y + 15, IMGUI_ALIGN_CENTER, label, imguiRGBA(255, 255, 255, 220));
#endif
}
}
}
@@ -842,6 +850,7 @@ void CrowdTool::reset() {}
void CrowdTool::handleMenu()
{
#if 0
if (!m_state) { return; }
CrowdToolParams* params = m_state->getToolParams();
@@ -923,6 +932,7 @@ void CrowdTool::handleMenu()
if (imguiCheck("Show Detail All", params->m_showDetailAll)) { params->m_showDetailAll = !params->m_showDetailAll; }
imguiUnindent();
}
#endif
}
void CrowdTool::handleClick(const float* s, const float* p, bool shift)
@@ -1001,6 +1011,7 @@ void CrowdTool::handleRender() {}
void CrowdTool::handleRenderOverlay(double* proj, double* model, int* view)
{
#if 0
rcIgnoreUnused(model);
rcIgnoreUnused(proj);
@@ -1037,4 +1048,5 @@ void CrowdTool::handleRenderOverlay(double* proj, double* model, int* view)
imguiDrawText(280, ty, IMGUI_ALIGN_LEFT, "- RUNNING -", imguiRGBA(255, 32, 16, 255));
}
else { imguiDrawText(280, ty, IMGUI_ALIGN_LEFT, "- PAUSED -", imguiRGBA(255, 255, 255, 128)); }
#endif
}

View File

@@ -225,6 +225,7 @@ void NavMeshPruneTool::handleMenu()
return;
}
#if 0
if (imguiButton("Clear Selection"))
{
flags->clearAllFlags();
@@ -236,6 +237,7 @@ void NavMeshPruneTool::handleMenu()
delete flags;
flags = nullptr;
}
#endif
}
void NavMeshPruneTool::handleClick(const float* s, const float* p, bool shift)
@@ -323,5 +325,7 @@ void NavMeshPruneTool::handleRender()
void NavMeshPruneTool::handleRenderOverlay(double* /*proj*/, double* /*model*/, int* view)
{
#if 0
imguiDrawText(280, view[3] - 40, IMGUI_ALIGN_LEFT, "LMB: Click fill area.", imguiRGBA(255, 255, 255, 192));
#endif
}

View File

@@ -214,6 +214,7 @@ void NavMeshTesterTool::init(Sample* sample)
void NavMeshTesterTool::handleMenu()
{
#if 0
if (imguiCheck("Pathfind Follow", m_toolMode == TOOLMODE_PATHFIND_FOLLOW))
{
m_toolMode = TOOLMODE_PATHFIND_FOLLOW;
@@ -419,6 +420,7 @@ void NavMeshTesterTool::handleMenu()
imguiUnindent();
imguiSeparator();
#endif
}
void NavMeshTesterTool::handleClick(const float* /*s*/, const float* p, bool shift)
@@ -1482,6 +1484,7 @@ void NavMeshTesterTool::handleRender()
void NavMeshTesterTool::handleRenderOverlay(double* proj, double* model, int* view)
{
#if 0
GLdouble x, y, z;
// Draw start and end point labels
@@ -1502,6 +1505,7 @@ void NavMeshTesterTool::handleRenderOverlay(double* proj, double* model, int* vi
IMGUI_ALIGN_LEFT,
"LMB+SHIFT: Set start location LMB: Set end location",
imguiRGBA(255, 255, 255, 192));
#endif
}
void NavMeshTesterTool::drawAgent(const float* pos, float r, float h, float c, const unsigned int col)

View File

@@ -54,6 +54,7 @@ void OffMeshConnectionTool::reset()
void OffMeshConnectionTool::handleMenu()
{
#if 0
if (imguiCheck("One Way", !bidir))
{
bidir = false;
@@ -62,6 +63,7 @@ void OffMeshConnectionTool::handleMenu()
{
bidir = true;
}
#endif
}
void OffMeshConnectionTool::handleClick(const float* /*rayStartPos*/, const float* rayHitPos, bool shift)
@@ -145,6 +147,7 @@ void OffMeshConnectionTool::handleRender()
void OffMeshConnectionTool::handleRenderOverlay(double* proj, double* model, int* view)
{
#if 0
GLdouble x, y, z;
// Draw start and end point labels
@@ -173,4 +176,5 @@ void OffMeshConnectionTool::handleRenderOverlay(double* proj, double* model, int
"LMB: Set connection end point and finish.",
imguiRGBA(255, 255, 255, 192));
}
#endif
}

View File

@@ -201,6 +201,7 @@ void Sample::resetCommonSettings()
void Sample::handleCommonSettings()
{
#if 0
imguiLabel("Rasterization");
imguiSlider("Cell Size", &cellSize, 0.1f, 1.0f, 0.01f);
imguiSlider("Cell Height", &cellHeight, 0.1f, 1.0f, 0.01f);
@@ -270,6 +271,7 @@ void Sample::handleCommonSettings()
imguiSlider("Max Sample Error", &detailSampleMaxError, 0.0f, 16.0f, 1.0f);
imguiSeparator();
#endif
}
void Sample::handleClick(const float* rayStartPos, const float* rayHitPos, bool shift)

View File

@@ -67,6 +67,7 @@ void Sample_SoloMesh::handleSettings()
{
handleCommonSettings();
#if 0
imguiSeparator();
imguiIndent();
@@ -92,10 +93,12 @@ void Sample_SoloMesh::handleSettings()
imguiLabel(message);
imguiSeparator();
#endif
}
void Sample_SoloMesh::handleTools()
{
#if 0
const SampleToolType type = !tool ? SampleToolType::NONE : tool->type();
if (imguiCheck("Test Navmesh", type == SampleToolType::NAVMESH_TESTER)) { setTool(new NavMeshTesterTool); }
@@ -114,18 +117,22 @@ void Sample_SoloMesh::handleTools()
}
imguiUnindent();
#endif
}
void Sample_SoloMesh::UI_DrawModeOption(const char* name, const DrawMode drawMode, const bool enabled)
{
#if 0
if (imguiCheck(name, currentDrawMode == drawMode, enabled))
{
currentDrawMode = drawMode;
}
#endif
}
void Sample_SoloMesh::handleDebugMode()
{
#if 0
imguiLabel("Draw");
UI_DrawModeOption("Input Mesh", DrawMode::MESH, true);
UI_DrawModeOption("Navmesh", DrawMode::NAVMESH, navMesh != nullptr);
@@ -144,6 +151,7 @@ void Sample_SoloMesh::handleDebugMode()
UI_DrawModeOption("Contours", DrawMode::CONTOURS, contourSet != nullptr);
UI_DrawModeOption("Poly Mesh", DrawMode::POLYMESH, polyMesh != nullptr);
UI_DrawModeOption("Poly Mesh Detail", DrawMode::POLYMESH_DETAIL, detailMesh != nullptr);
#endif
}
void Sample_SoloMesh::handleRender()
@@ -164,10 +172,10 @@ void Sample_SoloMesh::handleRender()
duDebugDrawTriMeshSlope(
&debugDraw,
inputGeometry->verts.data(),
static_cast<int>(inputGeometry->verts.size()) / 3,
inputGeometry->getVertCount(),
inputGeometry->tris.data(),
inputGeometry->normals.data(),
static_cast<int>(inputGeometry->tris.size()) / 3,
inputGeometry->getTriCount(),
agentMaxSlope,
texScale);
inputGeometry->drawOffMeshConnections(&debugDraw);

View File

@@ -584,12 +584,14 @@ void drawDetailOverlay(const dtTileCache* tileCache, const int tileX, const int
GLdouble x, y, z;
if (gluProject(static_cast<GLdouble>(pos[0]), static_cast<GLdouble>(pos[1]), static_cast<GLdouble>(pos[2]), model, proj, view, &x, &y, &z))
{
#if 0
snprintf(text, 128, "(%d,%d)/%d", tile->header->tx, tile->header->ty, tile->header->tlayer);
imguiDrawText(static_cast<int>(x), static_cast<int>(y) - 25, IMGUI_ALIGN_CENTER, text, imguiRGBA(0, 0, 0, 220));
snprintf(text, 128, "Compressed: %.1f kB", tile->dataSize / 1024.0f);
imguiDrawText(static_cast<int>(x), static_cast<int>(y) - 45, IMGUI_ALIGN_CENTER, text, imguiRGBA(0, 0, 0, 128));
snprintf(text, 128, "Raw:%.1fkB", rawSize / 1024.0f);
imguiDrawText(static_cast<int>(x), static_cast<int>(y) - 65, IMGUI_ALIGN_CENTER, text, imguiRGBA(0, 0, 0, 128));
#endif
}
}
}
@@ -670,6 +672,7 @@ public:
void handleMenu() override
{
#if 0
imguiLabel("Highlight Tile Cache");
imguiValue("Click LMB to highlight a tile.");
imguiSeparator();
@@ -689,6 +692,7 @@ public:
{
m_drawType = DRAWDETAIL_MESH;
}
#endif
}
void handleClick(const float* /*s*/, const float* p, bool /*shift*/) override
@@ -758,6 +762,7 @@ public:
void handleMenu() override
{
#if 0
imguiLabel("Create Temp Obstacles");
if (imguiButton("Remove All"))
@@ -767,6 +772,7 @@ public:
imguiValue("Click LMB to create an obstacle.");
imguiValue("Shift+LMB to remove an obstacle.");
#endif
}
void handleClick(const float* s, const float* p, bool shift) override
@@ -811,7 +817,7 @@ Sample_TempObstacles::~Sample_TempObstacles()
void Sample_TempObstacles::handleSettings()
{
Sample::handleCommonSettings();
#if 0
if (imguiCheck("Keep Itermediate Results", m_keepInterResults))
{
m_keepInterResults = !m_keepInterResults;
@@ -894,10 +900,12 @@ void Sample_TempObstacles::handleSettings()
imguiUnindent();
imguiSeparator();
#endif
}
void Sample_TempObstacles::handleTools()
{
#if 0
const SampleToolType type = !tool ? SampleToolType::NONE : tool->type();
if (imguiCheck("Test Navmesh", type == SampleToolType::NAVMESH_TESTER))
@@ -935,6 +943,7 @@ void Sample_TempObstacles::handleTools()
}
imguiUnindent();
#endif
}
void Sample_TempObstacles::handleDebugMode()
@@ -972,6 +981,7 @@ void Sample_TempObstacles::handleDebugMode()
return;
}
#if 0
imguiLabel("Draw");
if (imguiCheck("Input Mesh", m_drawMode == DRAWMODE_MESH, valid[DRAWMODE_MESH]))
{
@@ -1012,6 +1022,7 @@ void Sample_TempObstacles::handleDebugMode()
imguiValue("rebuild some tiles to see");
imguiValue("more debug mode options.");
}
#endif
}
void Sample_TempObstacles::handleRender()

View File

@@ -94,6 +94,7 @@ public:
void handleMenu() override
{
#if 0
imguiLabel("Create Tiles");
if (imguiButton("Create All"))
{
@@ -109,6 +110,7 @@ public:
m_sample->removeAllTiles();
}
}
#endif
}
void handleClick(const float* /*s*/, const float* p, bool shift) override
@@ -157,6 +159,7 @@ public:
void handleRenderOverlay(double* proj, double* model, int* view) override
{
#if 0
GLdouble x, y, z;
if (m_hitPosSet && gluProject(m_hitPos[0], m_hitPos[1], m_hitPos[2], model, proj, view, &x, &y, &z))
{
@@ -175,6 +178,7 @@ public:
IMGUI_ALIGN_LEFT,
"LMB: Rebuild hit tile. Shift+LMB: Clear hit tile.",
imguiRGBA(255, 255, 255, 192));
#endif
}
};
@@ -210,6 +214,7 @@ void Sample_TileMesh::cleanup()
void Sample_TileMesh::handleSettings()
{
Sample::handleCommonSettings();
#if 0
if (imguiCheck("Build All Tiles", buildAll))
{
@@ -278,10 +283,12 @@ void Sample_TileMesh::handleSettings()
imguiSeparator();
imguiSeparator();
#endif
}
void Sample_TileMesh::handleTools()
{
#if 0
const SampleToolType type = !tool ? SampleToolType::NONE : tool->type();
if (imguiCheck("Test Navmesh", type == SampleToolType::NAVMESH_TESTER))
@@ -319,18 +326,22 @@ void Sample_TileMesh::handleTools()
}
imguiUnindent();
#endif
}
void Sample_TileMesh::UI_DrawModeOption(const char* name, DrawMode drawMode, bool enabled)
{
#if 0
if (imguiCheck(name, this->drawMode == drawMode, enabled))
{
this->drawMode = drawMode;
}
#endif
}
void Sample_TileMesh::handleDebugMode()
{
#if 0
imguiLabel("Draw");
UI_DrawModeOption("Input Mesh", DrawMode::MESH, true);
UI_DrawModeOption("Navmesh", DrawMode::NAVMESH, navMesh != nullptr);
@@ -350,6 +361,7 @@ void Sample_TileMesh::handleDebugMode()
UI_DrawModeOption("Contours", DrawMode::CONTOURS, contourSet != nullptr);
UI_DrawModeOption("Poly Mesh", DrawMode::POLYMESH, polyMesh != nullptr);
UI_DrawModeOption("Poly Mesh Detail", DrawMode::POLYMESH_DETAIL, detailPolyMesh != nullptr);
#endif
}
void Sample_TileMesh::handleRender()
@@ -528,6 +540,7 @@ void Sample_TileMesh::handleRender()
void Sample_TileMesh::handleRenderOverlay(double* proj, double* model, int* view)
{
#if 0
GLdouble x, y, z;
// Draw start and end point labels
@@ -553,6 +566,7 @@ void Sample_TileMesh::handleRenderOverlay(double* proj, double* model, int* view
tool->handleRenderOverlay(proj, model, view);
}
renderOverlayToolStates(proj, model, view);
#endif
}
void Sample_TileMesh::handleMeshChanged(InputGeom* geom)

View File

@@ -424,6 +424,7 @@ void TestCase::handleRender()
bool TestCase::handleRenderOverlay(double* proj, double* model, int* view)
{
#if 0
GLdouble x, y, z;
char text[64];
char subtext[64];
@@ -464,6 +465,7 @@ bool TestCase::handleRenderOverlay(double* proj, double* model, int* view)
}
imguiDrawText((int)x, (int)(y - 25), IMGUI_ALIGN_CENTER, text, col);
}
n++;
}
@@ -500,4 +502,7 @@ bool TestCase::handleRenderOverlay(double* proj, double* model, int* view)
imguiEndScrollArea();
return mouseOverMenu;
#else
return false;
#endif
}

View File

@@ -59,6 +59,7 @@ void GraphParams::setValueRange(float minValue, float maxValue, int numDivisions
void drawGraphBackground(const GraphParams* params)
{
#if 0
// BG
imguiDrawRoundedRect(
static_cast<float>(params->x),
@@ -94,10 +95,12 @@ void drawGraphBackground(const GraphParams* params)
1.0f,
imguiRGBA(0, 0, 0, 64));
}
#endif
}
void drawGraph(const GraphParams* params, const ValueHistory* graph, int index, const char* label, const unsigned int color)
{
#if 0
const float sx = static_cast<float>(params->width - params->padding * 2) / static_cast<float>(graph->getSampleCount());
const float sy = static_cast<float>(params->height - params->padding * 2) / (params->rangeMax - params->rangeMin);
const float ox = static_cast<float>(params->x) + static_cast<float>(params->padding);
@@ -129,4 +132,5 @@ void drawGraph(const GraphParams* params, const ValueHistory* graph, int index,
snprintf(text, 64, "%.2f %s", graph->getAverage(), params->units.c_str());
imguiDrawText(ix + size + 5, iy + 3, IMGUI_ALIGN_LEFT, label, imguiRGBA(255, 255, 255, 192));
imguiDrawText(ix + size + 150, iy + 3, IMGUI_ALIGN_RIGHT, text, imguiRGBA(255, 255, 255, 128));
#endif
}

View File

@@ -17,8 +17,8 @@
//
#include "SDL.h"
#include "SDL_opengl.h"
#include "SDL_keycode.h"
#include "SDL_opengl.h"
#include <cstdio>
#include <functional>
@@ -37,8 +37,10 @@
#include "Sample_TempObstacles.h"
#include "Sample_TileMesh.h"
#include "TestCase.h"
#include "imgui.h"
#include "imguiRenderGL.h"
#include <imgui.h>
#include <imgui_impl_opengl2.h>
#include <imgui_impl_sdl2.h>
#ifdef WIN32
# define snprintf _snprintf
@@ -67,7 +69,7 @@ struct AppData
int width;
int height;
SDL_Window* window;
SDL_Renderer* renderer;
SDL_GLContext glContext;
// Recast data, samples, and test cases
BuildContext buildContext;
@@ -110,21 +112,17 @@ struct AppData
float rayEnd[3];
// UI
string sampleName = "Choose Sample...";
int sampleIndex = -1;
string meshName = "Choose Mesh...";
// UI state
bool showMenu = true;
bool showLog = false;
bool showTools = true;
bool showLevels = false;
bool showSample = false;
bool showTestCases = false;
// Window scroll positions.
int propScroll = 0;
int logScroll = 0;
int toolsScroll = 0;
// Files
vector<string> files;
@@ -134,6 +132,30 @@ struct AppData
// Markers
float markerPosition[3] = {0, 0, 0};
bool markerPositionSet = false;
void resetCamera()
{
const float* bmin = 0;
const float* bmax = 0;
if (inputGeometry)
{
bmin = inputGeometry->getNavMeshBoundsMin();
bmax = inputGeometry->getNavMeshBoundsMax();
}
// Reset camera and fog to match the mesh bounds.
if (bmin && bmax)
{
camr = sqrtf(rcSqr(bmax[0] - bmin[0]) + rcSqr(bmax[1] - bmin[1]) + rcSqr(bmax[2] - bmin[2])) / 2;
cameraPos[0] = (bmax[0] + bmin[0]) / 2 + camr;
cameraPos[1] = (bmax[1] + bmin[1]) / 2 + camr;
cameraPos[2] = (bmax[2] + bmin[2]) / 2 + camr;
camr *= 3;
}
cameraEulers[0] = 45;
cameraEulers[1] = -45;
glFogf(GL_FOG_START, camr * 0.1f);
glFogf(GL_FOG_END, camr * 1.25f);
}
};
int main(int /*argc*/, char** /*argv*/)
@@ -169,27 +191,163 @@ int main(int /*argc*/, char** /*argv*/)
app.width = rcMin(displayMode.w, static_cast<int>(static_cast<float>(displayMode.h) * (16.0f / 9.0f))) - 80;
app.height = displayMode.h - 80;
int errorCode = SDL_CreateWindowAndRenderer(
// Create the SDL window with OpenGL support
app.window = SDL_CreateWindow(
"My App",
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
app.width,
app.height,
SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE,
&app.window,
&app.renderer);
SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
if (errorCode != 0 || !app.window || !app.renderer)
// Create the OpenGL context
app.glContext = SDL_GL_CreateContext(app.window);
SDL_GL_MakeCurrent(app.window, app.glContext);
if (!app.window || !app.glContext)
{
printf("Could not initialise SDL opengl\nError: %s\n", SDL_GetError());
printf("Could not initialize SDL opengl\nError: %s\n", SDL_GetError());
return -1;
}
SDL_SetWindowPosition(app.window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
if (!imguiRenderGLInit("DroidSans.ttf"))
{
printf("Could not init GUI renderer.\n");
SDL_Quit();
return -1;
}
// Setup Dear ImGui context
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO();
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
io.Fonts->AddFontFromFileTTF("DroidSans.ttf", 16.0f); // Size in pixels
ImGui::PushFont(io.Fonts->Fonts[0]);
ImGui::StyleColorsDark();
// Set style
float main_scale = ImGui_ImplSDL2_GetContentScaleForDisplay(0);
ImGuiStyle& style = ImGui::GetStyle();
style.ScaleAllSizes(main_scale);
style.FontScaleDpi = main_scale;
style.WindowRounding = 8.0f;
style.FrameRounding = 4.0f;
style.WindowPadding = ImVec2(10, 10);
style.FramePadding = ImVec2(8, 4);
style.Colors[ImGuiCol_WindowBg] = ImVec4(0.0f, 0.0f, 0.0f, 0.75f);
style.Colors[ImGuiCol_Header] = ImVec4(1.0f, 1.0f, 1.0f, 0.5f);
style.Colors[ImGuiCol_ScrollbarBg] = ImVec4(0.0f, 0.0f, 0.0f, 0.75f);
style.Colors[ImGuiCol_ScrollbarGrab] = ImVec4(1.0f, 1.0f, 1.0f, 0.25f);
style.Colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(1.0f, 0.75f, 0, 0.75f);
style.Colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(1.0f, 0.75f, 0, 0.37f);
style.Colors[ImGuiCol_Button] = ImVec4(0.5f, 0.5f, 0.5f, 96.0f / 255.0f);
style.Colors[ImGuiCol_ButtonActive] = ImVec4(0.5f, 0.5f, 0.5f, 196.0f / 255.0f);
//style.Colors[ImGuiCol_ButtonHovered] = ImVec4(1.0f, 196.0f / 255.0f, 0, 96.0f / 255.0f);
/*
/// 0 = FLAT APPEARENCE
/// 1 = MORE "3D" LOOK
int is3D = 1;
style.Colors[ImGuiCol_Text] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
style.Colors[ImGuiCol_TextDisabled] = ImVec4(0.40f, 0.40f, 0.40f, 1.00f);
style.Colors[ImGuiCol_TextSelectedBg] = ImVec4(0.73f, 0.73f, 0.73f, 0.35f);
style.Colors[ImGuiCol_ChildBg] = ImVec4(0.0f, 0.0f, 0.0f, 0.75f);
style.Colors[ImGuiCol_WindowBg] = ImVec4(0.0f, 0.0f, 0.0f, 0.75f);
style.Colors[ImGuiCol_PopupBg] = ImVec4(0.0f, 0.0f, 0.0f, 0.75f);
style.Colors[ImGuiCol_Border] = ImVec4(0.12f, 0.12f, 0.12f, 0.71f);
style.Colors[ImGuiCol_BorderShadow] = ImVec4(1.00f, 1.00f, 1.00f, 0.06f);
style.Colors[ImGuiCol_FrameBg] = ImVec4(0.42f, 0.42f, 0.42f, 0.54f);
style.Colors[ImGuiCol_FrameBgHovered] = ImVec4(0.42f, 0.42f, 0.42f, 0.40f);
style.Colors[ImGuiCol_FrameBgActive] = ImVec4(0.56f, 0.56f, 0.56f, 0.67f);
style.Colors[ImGuiCol_TitleBg] = ImVec4(0.19f, 0.19f, 0.19f, 1.00f);
style.Colors[ImGuiCol_TitleBgActive] = ImVec4(0.22f, 0.22f, 0.22f, 1.00f);
style.Colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.17f, 0.17f, 0.17f, 0.90f);
style.Colors[ImGuiCol_MenuBarBg] = ImVec4(0.335f, 0.335f, 0.335f, 1.000f);
style.Colors[ImGuiCol_ScrollbarBg] = ImVec4(0.24f, 0.24f, 0.24f, 0.53f);
style.Colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.41f, 0.41f, 0.41f, 1.00f);
style.Colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.52f, 0.52f, 0.52f, 1.00f);
style.Colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.76f, 0.76f, 0.76f, 1.00f);
style.Colors[ImGuiCol_CheckMark] = ImVec4(0.65f, 0.65f, 0.65f, 1.00f);
style.Colors[ImGuiCol_SliderGrab] = ImVec4(0.52f, 0.52f, 0.52f, 1.00f);
style.Colors[ImGuiCol_SliderGrabActive] = ImVec4(0.64f, 0.64f, 0.64f, 1.00f);
style.Colors[ImGuiCol_Button] = ImVec4(0.54f, 0.54f, 0.54f, 0.35f);
style.Colors[ImGuiCol_ButtonHovered] = ImVec4(0.52f, 0.52f, 0.52f, 0.59f);
style.Colors[ImGuiCol_ButtonActive] = ImVec4(0.76f, 0.76f, 0.76f, 1.00f);
style.Colors[ImGuiCol_Header] = ImVec4(0.38f, 0.38f, 0.38f, 1.00f);
style.Colors[ImGuiCol_HeaderHovered] = ImVec4(0.47f, 0.47f, 0.47f, 1.00f);
style.Colors[ImGuiCol_HeaderActive] = ImVec4(0.76f, 0.76f, 0.76f, 0.77f);
style.Colors[ImGuiCol_Separator] = ImVec4(0.000f, 0.000f, 0.000f, 0.137f);
style.Colors[ImGuiCol_SeparatorHovered] = ImVec4(0.700f, 0.671f, 0.600f, 0.290f);
style.Colors[ImGuiCol_SeparatorActive] = ImVec4(0.702f, 0.671f, 0.600f, 0.674f);
style.Colors[ImGuiCol_ResizeGrip] = ImVec4(0.26f, 0.59f, 0.98f, 0.25f);
style.Colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.67f);
style.Colors[ImGuiCol_ResizeGripActive] = ImVec4(0.26f, 0.59f, 0.98f, 0.95f);
style.Colors[ImGuiCol_PlotLines] = ImVec4(0.61f, 0.61f, 0.61f, 1.00f);
style.Colors[ImGuiCol_PlotLinesHovered] = ImVec4(1.00f, 0.43f, 0.35f, 1.00f);
style.Colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
style.Colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f);
style.Colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.35f);
style.Colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f);
style.Colors[ImGuiCol_NavHighlight] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
style.Colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f);
style.Colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.20f);
style.PopupRounding = 3;
style.WindowPadding = ImVec2(4, 4);
style.FramePadding = ImVec2(6, 4);
style.ItemSpacing = ImVec2(6, 2);
style.ScrollbarSize = 18;
style.WindowBorderSize = 1;
style.ChildBorderSize = 1;
style.PopupBorderSize = 1;
style.FrameBorderSize = is3D;
style.WindowRounding = 3;
style.ChildRounding = 3;
style.FrameRounding = 3;
style.ScrollbarRounding = 2;
style.GrabRounding = 3;
#ifdef IMGUI_HAS_DOCK
style.TabBorderSize = is3D;
style.TabRounding = 3;
colors[ImGuiCol_DockingEmptyBg] = ImVec4(0.38f, 0.38f, 0.38f, 1.00f);
colors[ImGuiCol_Tab] = ImVec4(0.25f, 0.25f, 0.25f, 1.00f);
colors[ImGuiCol_TabHovered] = ImVec4(0.40f, 0.40f, 0.40f, 1.00f);
colors[ImGuiCol_TabActive] = ImVec4(0.33f, 0.33f, 0.33f, 1.00f);
colors[ImGuiCol_TabUnfocused] = ImVec4(0.25f, 0.25f, 0.25f, 1.00f);
colors[ImGuiCol_TabUnfocusedActive] = ImVec4(0.33f, 0.33f, 0.33f, 1.00f);
colors[ImGuiCol_DockingPreview] = ImVec4(0.85f, 0.85f, 0.85f, 0.28f);
if (ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
{
style.WindowRounding = 0.0f;
style.Colors[ImGuiCol_WindowBg].w = 1.0f;
}
#endif
*/
// Setup Platform/Renderer backends
ImGui_ImplSDL2_InitForOpenGL(app.window, app.glContext);
ImGui_ImplOpenGL2_Init();
ImGuiWindowFlags staticWindowFlags = ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoCollapse;
app.prevFrameTime = SDL_GetTicks();
@@ -204,19 +362,47 @@ int main(int /*argc*/, char** /*argv*/)
glEnable(GL_CULL_FACE);
glDepthFunc(GL_LEQUAL);
//----------------------------------------------------------------------------
scanDirectory(app.meshesFolder, ".obj", app.files);
app.meshName = app.files[0];
app.inputGeometry = new InputGeom;
app.inputGeometry->load(&app.buildContext, app.meshesFolder + "/" + app.meshName);
app.sampleIndex = 0;
app.sample = g_samples[0].create();
app.sample->setContext(&app.buildContext);
app.sample->handleMeshChanged(app.inputGeometry);
// Reset camera and fog to match the mesh bounds.
const float* bmin = app.inputGeometry->getNavMeshBoundsMin();
const float* bmax = app.inputGeometry->getNavMeshBoundsMax();
app.camr = sqrtf(rcSqr(bmax[0] - bmin[0]) + rcSqr(bmax[1] - bmin[1]) + rcSqr(bmax[2] - bmin[2])) / 2;
app.cameraPos[0] = (bmax[0] + bmin[0]) / 2 + app.camr;
app.cameraPos[1] = (bmax[1] + bmin[1]) / 2 + app.camr;
app.cameraPos[2] = (bmax[2] + bmin[2]) / 2 + app.camr;
app.camr *= 3;
app.cameraEulers[0] = 45;
app.cameraEulers[1] = -45;
glFogf(GL_FOG_START, app.camr * 0.1f);
glFogf(GL_FOG_END, app.camr * 1.25f);
//----------------------------------------------------------------------------
bool done = false;
while (!done)
{
// Handle input events.
int mouseScroll = 0;
bool processHitTest = false;
bool processHitTestShift = false;
// Per frame input
app.mouseOverMenu = ImGui::IsWindowHovered(ImGuiHoveredFlags_AnyWindow);
SDL_Event event;
while (SDL_PollEvent(&event))
{
ImGui_ImplSDL2_ProcessEvent(&event);
switch (event.type)
{
case SDL_KEYDOWN:
@@ -227,8 +413,6 @@ int main(int /*argc*/, char** /*argv*/)
done = true;
break;
case SDLK_t:
app.showLevels = false;
app.showSample = false;
app.showTestCases = true;
app.files.clear();
scanDirectory(app.testCasesFolder, ".txt", app.files);
@@ -262,11 +446,7 @@ int main(int /*argc*/, char** /*argv*/)
break;
case SDL_MOUSEWHEEL:
if (app.mouseOverMenu)
{
mouseScroll += event.wheel.y;
}
else
if (!app.mouseOverMenu)
{
app.scrollZoom += static_cast<float>(event.wheel.y);
}
@@ -355,16 +535,6 @@ int main(int /*argc*/, char** /*argv*/)
}
}
unsigned char mouseButtonMask = 0;
if (SDL_GetMouseState(0, 0) & SDL_BUTTON_LMASK)
{
mouseButtonMask |= IMGUI_MBUT_LEFT;
}
if (SDL_GetMouseState(0, 0) & SDL_BUTTON_RMASK)
{
mouseButtonMask |= IMGUI_MBUT_RIGHT;
}
Uint32 time = SDL_GetTicks();
float dt = static_cast<float>(time - app.prevFrameTime) / 1000.0f;
app.prevFrameTime = time;
@@ -476,12 +646,30 @@ int main(int /*argc*/, char** /*argv*/)
// Handle keyboard movement.
const Uint8* keystate = SDL_GetKeyboardState(NULL);
app.moveFront = rcClamp(app.moveFront + dt * 4 * ((keystate[SDL_SCANCODE_W] || keystate[SDL_SCANCODE_UP]) ? 1.0f : -1.0f), 0.0f, 1.0f);
app.moveLeft = rcClamp(app.moveLeft + dt * 4 * ((keystate[SDL_SCANCODE_A] || keystate[SDL_SCANCODE_LEFT]) ? 1.0f : -1.0f), 0.0f, 1.0f);
app.moveBack = rcClamp(app.moveBack + dt * 4 * ((keystate[SDL_SCANCODE_S] || keystate[SDL_SCANCODE_DOWN]) ? 1.0f : -1.0f), 0.0f, 1.0f);
app.moveRight = rcClamp(app.moveRight + dt * 4 * ((keystate[SDL_SCANCODE_D] || keystate[SDL_SCANCODE_RIGHT]) ? 1.0f : -1.0f), 0.0f, 1.0f);
app.moveUp = rcClamp(app.moveUp + dt * 4 * ((keystate[SDL_SCANCODE_Q] || keystate[SDL_SCANCODE_PAGEUP]) ? 1.0f : -1.0f), 0.0f, 1.0f);
app.moveDown = rcClamp(app.moveDown + dt * 4 * ((keystate[SDL_SCANCODE_E] || keystate[SDL_SCANCODE_PAGEDOWN]) ? 1.0f : -1.0f), 0.0f, 1.0f);
app.moveFront = rcClamp(
app.moveFront + dt * 4 * ((keystate[SDL_SCANCODE_W] || keystate[SDL_SCANCODE_UP]) ? 1.0f : -1.0f),
0.0f,
1.0f);
app.moveLeft = rcClamp(
app.moveLeft + dt * 4 * ((keystate[SDL_SCANCODE_A] || keystate[SDL_SCANCODE_LEFT]) ? 1.0f : -1.0f),
0.0f,
1.0f);
app.moveBack = rcClamp(
app.moveBack + dt * 4 * ((keystate[SDL_SCANCODE_S] || keystate[SDL_SCANCODE_DOWN]) ? 1.0f : -1.0f),
0.0f,
1.0f);
app.moveRight = rcClamp(
app.moveRight + dt * 4 * ((keystate[SDL_SCANCODE_D] || keystate[SDL_SCANCODE_RIGHT]) ? 1.0f : -1.0f),
0.0f,
1.0f);
app.moveUp = rcClamp(
app.moveUp + dt * 4 * ((keystate[SDL_SCANCODE_Q] || keystate[SDL_SCANCODE_PAGEUP]) ? 1.0f : -1.0f),
0.0f,
1.0f);
app.moveDown = rcClamp(
app.moveDown + dt * 4 * ((keystate[SDL_SCANCODE_E] || keystate[SDL_SCANCODE_PAGEDOWN]) ? 1.0f : -1.0f),
0.0f,
1.0f);
float keybSpeed = 22.0f;
if (SDL_GetModState() & KMOD_SHIFT)
@@ -526,7 +714,10 @@ int main(int /*argc*/, char** /*argv*/)
app.mouseOverMenu = false;
imguiBeginFrame(app.mousePos[0], app.mousePos[1], mouseButtonMask, mouseScroll);
ImGui_ImplOpenGL2_NewFrame();
ImGui_ImplSDL2_NewFrame();
ImGui::NewFrame();
ImGui::ShowDemoWindow();
if (app.sample)
{
@@ -543,256 +734,150 @@ int main(int /*argc*/, char** /*argv*/)
// Help text.
if (app.showMenu)
{
const char msg[] = "W/S/A/D: Move RMB: Rotate";
imguiDrawText(280, app.height - 20, IMGUI_ALIGN_LEFT, msg, imguiRGBA(255, 255, 255, 128));
ImDrawList* draw_list = ImGui::GetForegroundDrawList();
draw_list->AddText({280.0f, 20.0f}, IM_COL32(255, 255, 255, 128), "W/A/S/D: Move RMB: Rotate");
}
bool newMeshSelected = false;
bool newSampleSelected = false;
if (app.showMenu)
{
if (imguiBeginScrollArea("Properties", app.width - 250 - 10, 10, 250, app.height - 20, &app.propScroll))
ImGui::SetNextWindowPos(ImVec2(app.width - 250 - 10, 10), ImGuiCond_Always); // Position in screen space
ImGui::SetNextWindowSize(ImVec2(250, app.height - 20), ImGuiCond_Always); // Size of the window
ImGui::Begin("Properties", nullptr, staticWindowFlags);
ImGui::Checkbox("Show Log", &app.showLog);
ImGui::Checkbox("Show Tools", &app.showTools);
ImGui::SeparatorText("Input Mesh");
// Level selection dialog.
if (ImGui::BeginCombo("##levelCombo", app.meshName.c_str(), 0))
{
app.mouseOverMenu = true;
app.files.clear();
scanDirectory(app.meshesFolder, ".obj", app.files);
scanDirectory(app.meshesFolder, ".gset", app.files);
for (const auto& file : app.files)
{
const bool is_selected = (app.meshName == file);
if (ImGui::Selectable(file.c_str(), is_selected) && !is_selected)
{
app.meshName = file;
newMeshSelected = true;
}
// Set the initial focus when opening the combo (scrolling + keyboard navigation focus)
if (is_selected)
{
ImGui::SetItemDefaultFocus();
}
}
ImGui::EndCombo();
}
if (imguiCheck("Show Log", app.showLog))
{
app.showLog = !app.showLog;
}
if (imguiCheck("Show Tools", app.showTools))
{
app.showTools = !app.showTools;
}
imguiSeparator();
imguiLabel("Sample");
if (imguiButton(app.sampleName.c_str()))
{
if (app.showSample)
{
app.showSample = false;
}
else
{
app.showSample = true;
app.showLevels = false;
app.showTestCases = false;
}
}
imguiSeparator();
imguiLabel("Input Mesh");
if (imguiButton(app.meshName.c_str()))
{
if (app.showLevels)
{
app.showLevels = false;
}
else
{
app.showSample = false;
app.showTestCases = false;
app.showLevels = true;
app.files.clear();
scanDirectory(app.meshesFolder, ".obj", app.files);
scanDirectory(app.meshesFolder, ".gset", app.files);
}
}
if (app.inputGeometry)
{
char text[64];
snprintf(
text,
64,
ImGui::Text(
"Verts: %.1fk Tris: %.1fk",
static_cast<float>(app.inputGeometry->getVertCount()) / 1000.0f,
static_cast<float>(app.inputGeometry->getTriCount()) / 1000.0f);
imguiValue(text);
static_cast<float>(app.inputGeometry->getVertCount()) / 1000.0f,
static_cast<float>(app.inputGeometry->getTriCount()) / 1000.0f);
}
imguiSeparator();
if (app.inputGeometry && app.sample)
ImGui::SeparatorText("Sample");
if (ImGui::BeginCombo("##sampleCombo", app.sampleIndex >= 0 ? g_samples[app.sampleIndex].name.c_str() : "Choose Sample...", 0))
{
imguiSeparatorLine();
app.sample->handleSettings();
if (imguiButton("Build"))
for (int n = 0; n < IM_ARRAYSIZE(g_samples); n++)
{
app.buildContext.resetLog();
if (!app.sample->handleBuild())
const bool is_selected = (app.sampleIndex == n);
if (ImGui::Selectable(g_samples[n].name.c_str(), is_selected))
{
app.showLog = true;
app.logScroll = 0;
newSampleSelected = !is_selected;
app.sampleIndex = n;
}
app.buildContext.dumpLog("Build log %s:", app.meshName.c_str());
// Clear test.
delete app.testCase;
app.testCase = 0;
// Set the initial focus when opening the combo (scrolling + keyboard navigation focus)
if (is_selected)
{
ImGui::SetItemDefaultFocus();
}
}
imguiSeparator();
ImGui::EndCombo();
}
if (app.sample)
{
imguiSeparatorLine();
if (app.inputGeometry)
{
app.sample->handleSettings();
if (ImGui::Button("Build"))
{
app.buildContext.resetLog();
if (!app.sample->handleBuild())
{
app.showLog = true;
app.logScroll = 0;
}
app.buildContext.dumpLog("Build log %s:", app.meshName.c_str());
// Clear test.
delete app.testCase;
app.testCase = 0;
}
}
ImGui::SeparatorText("Debug Settings");
app.sample->handleDebugMode();
}
imguiEndScrollArea();
ImGui::End();
}
// Sample selection dialog.
if (app.showSample)
if (newSampleSelected)
{
static int levelScroll = 0;
if (imguiBeginScrollArea(
"Choose sample",
app.width - 10 - 250 - 10 - 200,
app.height - 10 - 250,
200,
250,
&levelScroll))
delete app.sample;
app.sample = g_samples[app.sampleIndex].create();
app.sample->setContext(&app.buildContext);
if (app.inputGeometry)
{
app.mouseOverMenu = true;
app.sample->handleMeshChanged(app.inputGeometry);
app.resetCamera();
}
Sample* newSample = 0;
for (int i = 0; i < g_nsamples; ++i)
{
if (imguiItem(g_samples[i].name.c_str()))
{
newSample = g_samples[i].create();
if (newSample)
{
app.sampleName = g_samples[i].name;
}
}
}
if (newSample)
{
delete app.sample;
app.sample = newSample;
app.sample->setContext(&app.buildContext);
if (app.inputGeometry)
{
app.sample->handleMeshChanged(app.inputGeometry);
}
app.showSample = false;
}
if (app.inputGeometry || app.sample)
{
const float* bmin = 0;
const float* bmax = 0;
if (app.inputGeometry)
{
bmin = app.inputGeometry->getNavMeshBoundsMin();
bmax = app.inputGeometry->getNavMeshBoundsMax();
}
// Reset camera and fog to match the mesh bounds.
if (bmin && bmax)
{
app.camr = sqrtf(rcSqr(bmax[0] - bmin[0]) + rcSqr(bmax[1] - bmin[1]) + rcSqr(bmax[2] - bmin[2])) / 2;
app.cameraPos[0] = (bmax[0] + bmin[0]) / 2 + app.camr;
app.cameraPos[1] = (bmax[1] + bmin[1]) / 2 + app.camr;
app.cameraPos[2] = (bmax[2] + bmin[2]) / 2 + app.camr;
app.camr *= 3;
}
app.cameraEulers[0] = 45;
app.cameraEulers[1] = -45;
glFogf(GL_FOG_START, app.camr * 0.1f);
glFogf(GL_FOG_END, app.camr * 1.25f);
}
imguiEndScrollArea();
}
// Level selection dialog.
if (app.showLevels)
if (newMeshSelected)
{
static int levelScroll = 0;
if (imguiBeginScrollArea(
"Choose Level",
app.width - 10 - 250 - 10 - 200,
app.height - 10 - 450,
200,
450,
&levelScroll))
string path = app.meshesFolder + "/" + app.meshName;
delete app.inputGeometry;
app.inputGeometry = new InputGeom;
if (!app.inputGeometry->load(&app.buildContext, path))
{
app.mouseOverMenu = true;
}
vector<string>::const_iterator fileIter = app.files.begin();
vector<string>::const_iterator filesEnd = app.files.end();
vector<string>::const_iterator levelToLoad = filesEnd;
for (; fileIter != filesEnd; ++fileIter)
{
if (imguiItem(fileIter->c_str()))
{
levelToLoad = fileIter;
}
}
if (levelToLoad != filesEnd)
{
app.meshName = *levelToLoad;
app.showLevels = false;
string path = app.meshesFolder + "/" + app.meshName;
delete app.inputGeometry;
app.inputGeometry = new InputGeom;
if (!app.inputGeometry->load(&app.buildContext, path))
{
delete app.inputGeometry;
app.inputGeometry = nullptr;
app.inputGeometry = nullptr;
// Destroy the sample if it already had geometry loaded, as we've just deleted it!
if (app.sample && app.sample->getInputGeom())
{
delete app.sample;
app.sample = nullptr;
}
app.showLog = true;
app.logScroll = 0;
app.buildContext.dumpLog("geom load log %s:", app.meshName.c_str());
}
if (app.sample && app.inputGeometry)
// Destroy the sample if it already had geometry loaded, as we've just deleted it!
if (app.sample && app.sample->getInputGeom())
{
app.sample->handleMeshChanged(app.inputGeometry);
delete app.sample;
app.sample = nullptr;
}
if (app.inputGeometry || app.sample)
{
const float* bmin = 0;
const float* bmax = 0;
if (app.inputGeometry)
{
bmin = app.inputGeometry->getNavMeshBoundsMin();
bmax = app.inputGeometry->getNavMeshBoundsMax();
}
// Reset camera and fog to match the mesh bounds.
if (bmin && bmax)
{
app.camr = sqrtf(rcSqr(bmax[0] - bmin[0]) + rcSqr(bmax[1] - bmin[1]) + rcSqr(bmax[2] - bmin[2])) / 2;
app.cameraPos[0] = (bmax[0] + bmin[0]) / 2 + app.camr;
app.cameraPos[1] = (bmax[1] + bmin[1]) / 2 + app.camr;
app.cameraPos[2] = (bmax[2] + bmin[2]) / 2 + app.camr;
app.camr *= 3;
}
app.cameraEulers[0] = 45;
app.cameraEulers[1] = -45;
glFogf(GL_FOG_START, app.camr * 0.1f);
glFogf(GL_FOG_END, app.camr * 1.25f);
}
app.showLog = true;
app.logScroll = 0;
app.buildContext.dumpLog("geom load log %s:", app.meshName.c_str());
}
app.resetCamera();
if (app.sample)
{
app.sample->handleMeshChanged(app.inputGeometry);
}
imguiEndScrollArea();
}
#if 0
// Test cases
if (app.showTestCases)
{
@@ -841,7 +926,7 @@ int main(int /*argc*/, char** /*argv*/)
newSample = g_samples[i].create();
if (newSample)
{
app.sampleName = g_samples[i].name;
app.sampleIndex = i;
}
}
}
@@ -924,35 +1009,37 @@ int main(int /*argc*/, char** /*argv*/)
imguiEndScrollArea();
}
#endif
// Log
static bool auto_scroll = true;
if (app.showLog && app.showMenu)
{
if (imguiBeginScrollArea("Log", 250 + 20, 10, app.width - 300 - 250, 200, &app.logScroll))
{
app.mouseOverMenu = true;
}
ImGui::SetNextWindowPos(ImVec2(250 + 20, app.height - 200 - 10), ImGuiCond_Always); // Position in screen space
ImGui::SetNextWindowSize(ImVec2(app.width - 250 - 250 - 20 - 20, 200), ImGuiCond_Always); // Size of the window
ImGui::Begin("Log", nullptr, staticWindowFlags);
for (int i = 0; i < app.buildContext.getLogCount(); ++i)
{
imguiLabel(app.buildContext.getLogText(i));
ImGui::TextUnformatted(app.buildContext.getLogText(i));
}
imguiEndScrollArea();
ImGui::End();
}
// Left column tools menu
if (!app.showTestCases && app.showTools && app.showMenu)
{
if (imguiBeginScrollArea("Tools", 10, 10, 250, app.height - 20, &app.toolsScroll))
{
app.mouseOverMenu = true;
}
ImGui::SetNextWindowPos(ImVec2(10, 10), ImGuiCond_Always); // Position in screen space
ImGui::SetNextWindowSize(ImVec2(250, app.height - 20), ImGuiCond_Always); // Size of the window
ImGui::Begin("Tools", nullptr, staticWindowFlags);
if (app.sample)
{
app.sample->handleTools();
}
imguiEndScrollArea();
ImGui::End();
}
// Marker
@@ -974,16 +1061,20 @@ int main(int /*argc*/, char** /*argv*/)
glLineWidth(1.0f);
}
imguiEndFrame();
imguiRenderGLDraw();
glEnable(GL_DEPTH_TEST);
ImGui::Render();
ImGui_ImplOpenGL2_RenderDrawData(ImGui::GetDrawData());
SDL_GL_SwapWindow(app.window);
}
imguiRenderGLDestroy();
ImGui_ImplOpenGL2_Shutdown();
ImGui_ImplSDL2_Shutdown();
ImGui::DestroyContext();
SDL_Quit();
SDL_GL_DeleteContext(app.glContext);
SDL_DestroyWindow(app.window);
SDL_Quit();
delete app.sample;
delete app.inputGeometry;

View File

@@ -7,15 +7,15 @@ local action = _ACTION or ""
local todir = "Build/" .. action
workspace "recastnavigation"
configurations {
configurations {
"Debug",
"Release"
}
location (todir)
-- Use fast math operations. This is not required, but it speeds up some calculations
-- at the expense of accuracy. Because there are some functions like dtMathIsfinite
-- Use fast math operations. This is not required, but it speeds up some calculations
-- at the expense of accuracy. Because there are some functions like dtMathIsfinite
-- that use floating point functions that become undefined behavior when compiled with
-- fast-math, we need to conditionally short-circuit these functions.
floatingpoint "Fast"
@@ -30,7 +30,7 @@ workspace "recastnavigation"
filter "configurations:Debug"
defines { "DEBUG" }
targetdir ( todir .. "/lib/Debug" )
-- release configs
filter "configurations:Release"
defines { "RC_DISABLE_ASSERTS" }
@@ -59,7 +59,7 @@ project "DebugUtils"
language "C++"
cppdialect "C++98"
kind "StaticLib"
includedirs {
includedirs {
"../DebugUtils/Include",
"../Detour/Include",
"../DetourTileCache/Include",
@@ -74,12 +74,12 @@ project "Detour"
language "C++"
cppdialect "C++98"
kind "StaticLib"
includedirs {
"../Detour/Include"
includedirs {
"../Detour/Include"
}
files {
"../Detour/Include/*.h",
"../Detour/Source/*.cpp"
files {
"../Detour/Include/*.h",
"../Detour/Source/*.cpp"
}
-- linux library cflags and libs
filter {"system:linux", "toolset:gcc"}
@@ -120,19 +120,19 @@ project "Recast"
language "C++"
cppdialect "C++98"
kind "StaticLib"
includedirs {
"../Recast/Include"
includedirs {
"../Recast/Include"
}
files {
files {
"../Recast/Include/*.h",
"../Recast/Source/*.cpp"
"../Recast/Source/*.cpp"
}
project "RecastDemo"
language "C++"
cppdialect "C++20" -- we don't care about this being compatible in the same way we do with the library code.
kind "WindowedApp"
includedirs {
includedirs {
"../RecastDemo/Include",
"../RecastDemo/Contrib",
"../RecastDemo/Contrib/fastlz",
@@ -142,11 +142,18 @@ project "RecastDemo"
"../DetourTileCache/Include",
"../Recast/Include"
}
externalincludedirs {
"../RecastDemo/Contrib/imgui",
"../RecastDemo/Contrib/imgui/backends",
}
files {
"../RecastDemo/Include/*.h",
"../RecastDemo/Source/*.cpp",
"../RecastDemo/Contrib/fastlz/*.h",
"../RecastDemo/Contrib/fastlz/*.c"
"../RecastDemo/Contrib/fastlz/*.c",
"../RecastDemo/Contrib/imgui/*.cpp",
"../RecastDemo/Contrib/imgui/backends/imgui_impl_sdl2.cpp",
"../RecastDemo/Contrib/imgui/backends/imgui_impl_opengl2.cpp",
}
-- project dependencies
@@ -163,16 +170,16 @@ project "RecastDemo"
-- linux library cflags and libs
filter "system:linux"
buildoptions {
buildoptions {
"`pkg-config --cflags sdl2`",
"`pkg-config --cflags gl`",
"`pkg-config --cflags glu`",
"-Wno-ignored-qualifiers",
}
linkoptions {
linkoptions {
"`pkg-config --libs sdl2`",
"`pkg-config --libs gl`",
"`pkg-config --libs glu`"
"`pkg-config --libs glu`"
}
filter { "system:linux", "toolset:gcc", "files:*.c" }
@@ -185,7 +192,7 @@ project "RecastDemo"
includedirs { "../RecastDemo/Contrib/SDL/include" }
libdirs { "../RecastDemo/Contrib/SDL/lib/%{cfg.architecture:gsub('x86_64', 'x64')}" }
debugdir "../RecastDemo/Bin/"
links {
links {
"glu32",
"opengl32",
"SDL2",
@@ -200,8 +207,9 @@ project "RecastDemo"
filter "system:macosx"
kind "ConsoleApp" -- xcode4 failes to run the project if using WindowedApp
includedirs { "Bin/SDL2.framework/Headers" }
links {
"OpenGL.framework",
externalincludedirs { "Bin/SDL2.framework/Headers" }
links {
"OpenGL.framework",
"SDL2.framework",
"Cocoa.framework",
}
@@ -215,7 +223,7 @@ project "Tests"
exceptionhandling "On"
rtti "On"
includedirs {
includedirs {
"../DebugUtils/Include",
"../Detour/Include",
"../DetourCrowd/Include",
@@ -226,7 +234,7 @@ project "Tests"
"../Tests",
"../Tests/Contrib"
}
files {
files {
"../Tests/*.h",
"../Tests/*.hpp",
"../Tests/*.cpp",
@@ -239,7 +247,7 @@ project "Tests"
}
-- project dependencies
links {
links {
"DebugUtils",
"DetourCrowd",
"Detour",
@@ -266,7 +274,7 @@ project "Tests"
"`pkg-config --cflags glu`",
"-Wno-parentheses" -- Disable parentheses warning for the Tests target, as Catch's macros generate this everywhere.
}
linkoptions {
linkoptions {
"`pkg-config --libs sdl2`",
"`pkg-config --libs gl`",
"`pkg-config --libs glu`",
@@ -278,7 +286,7 @@ project "Tests"
includedirs { "../RecastDemo/Contrib/SDL/include" }
libdirs { "../RecastDemo/Contrib/SDL/lib/%{cfg.architecture:gsub('x86_64', 'x64')}" }
debugdir "../RecastDemo/Bin/"
links {
links {
"glu32",
"opengl32",
"SDL2",