浏览代码

move sokol_gfx_imgui.h to util/, update docs

Andre Weissflog 6 年之前
父节点
当前提交
072b8d2158
共有 5 个文件被更改,包括 83 次插入564 次删除
  1. 18 0
      README.md
  2. 1 1
      fips.yml
  3. 0 538
      imgui/README.md
  4. 11 3
      util/README.md
  5. 53 22
      util/sokol_gfx_imgui.h

+ 18 - 0
README.md

@@ -3,6 +3,8 @@
 **Sokol (Сокол)**: Russian for Falcon, a smaller and more nimble
 bird of prey than the Eagle (Орёл, Oryol)
 
+[See what's new](#updates)
+
 Minimalistic header-only cross-platform libs in C:
 
 - **sokol\_gfx.h**: 3D-API wrapper (GL + Metal + D3D11)
@@ -407,6 +409,22 @@ Mainly some "missing features" for desktop apps:
 
 # Updates
 
+- **15-Mar-2019**: various Dear ImGui related changes:
+    - there's a new utility header sokol_imgui.h with a simple drop-in
+      renderer for Dear ImGui on top of sokol_gfx.h and sokol_app.h
+      (sokol_app.h is optional, and only used for input handling)
+    - the sokol_gfx_imgui.h debug inspection header no longer
+      depends on internal data structures and functions of sokol_gfx.h, as such
+      it is now a normal *utility header* and has been moved to the *utils*
+      directory
+    - the implementation macro for sokol_gfx_imgui.h has been changed
+      from SOKOL_IMPL to SOKOL_GFX_IMGUI_IMPL (so when you suddenly get
+      unresoled linker errors, that's the reason)
+    - all headers now have two preprocessor defines for the declaration
+      and implementation (for instance in sokol_gfx.h: SOKOL_GFX_INCLUDED
+      and SOKOL_GFX_IMPL_INCLUDED) these are checked in the utility-headers
+      to provide useful error message when dependent headers are missing
+
 - **05-Mar-2019**: sokol_gfx.h now has a 'trace hook' API, and I have started
 implementing optional debug-inspection-UI headers on top of Dear ImGui:
     - sokol_gfx.h has a new function *sg_install_trace_hooks()*, this allows

+ 1 - 1
fips.yml

@@ -1,2 +1,2 @@
 exports:
-  header-dirs: [ ".", "imgui", "util" ]
+  header-dirs: [ ".", "util" ]

+ 0 - 538
imgui/README.md

@@ -1,538 +0,0 @@
-# Sokol Debug Inspection UIs
-
-This directory contains optional 'extension headers' which implement debug
-inspection UIs for various Sokol headers implemented with [Dear
-ImGui](https://github.com/ocornut/imgui).
-
-## Integration Howto
-
-These are the steps to add the debug inspection UIs to your own project.
-
-### 1. Compile the implementation as C++ (or Objective-C++)
-
-Dear ImGui is a C++ library, and offers a C++ API. This means the implementation
-of the debug inspection headers is also written in C++, and
-must be compiled in C++ or Objective-C++ mode.
-
-### 2. Compile the Sokol headers with trace-hooks enabled
-
-The debug inspection headers may need to *hook into* the Sokol APIs via
-callback functions. These API callbacks are called **trace hooks** and must
-be enabled by defining ```SOKOL_TRACE_HOOKS``` before including the
-implementation.
-
-### 3. Include "imgui.h" before the implementation
-
-The debug inspection headers don't include ```imgui.h``` themselves,
-instead the ImGui header must be included before the implementation.
-
-### 3. Include the debug UI implementations after the Sokol implementations
-
-The debug inspection headers need access to private data and functions of
-their associated Sokol header. This means the implementation of the
-debug inspection headers must be included **after** the implementation
-of the their associated Sokol headers. I'd recomment putting all the
-Sokol headers of a project into a single implementation file, together
-with all *extension headers*. 
-
-```cpp
-// sokol-ui.cc
-//
-// Sokol header implementations and their debug inspection headers,
-// compiled as C++ code and with trace-hooks enabled. On macOS/iOS 
-// this would need to be an Objective-C++ file instead (.mm extension).
-//
-#define SOKOL_IMPL
-#define SOKOL_TRACE_HOOKS
-#include "sokol_app.h"
-#include "sokol_gfx.h"
-#include "sokol_time.h"
-#include "imgui.h"
-#include "sokol_app_imgui.h"
-#include "sokol_gfx_imgui.h"
-```
-
-### 4. Provide your own ImGui renderer
-
-You need to provide your own ImGui initialization and rendering
-code. If you are using sokol_gfx.h together with sokol_app.h, you
-can just copy the code from the sokol-samples:
-
-```cpp
-#pragma once
-/*
-    Implements a Dear ImGui renderer on top of sokol_gfx.h for 
-    the debug-visualization UIs.
-*/
-#include "sokol_app.h"
-#include "sokol_gfx.h"
-
-#if defined(__cplusplus)
-extern "C" {
-#endif
-void imgui_init(int sample_count);
-void imgui_newframe(void);
-void imgui_draw(void);
-void imgui_event(const sapp_event* event);
-#if defined(__cplusplus)
-} // extern "C"
-#endif
-
-//------------------------------------------------------------------------------
-#if defined(UI_IMPL)
-#include "imgui.h"
-
-typedef struct {
-    ImVec2 disp_size;
-} vs_params_t;
-
-static bool btn_down[SAPP_MAX_MOUSEBUTTONS];
-static bool btn_up[SAPP_MAX_MOUSEBUTTONS];
-static const int MaxVertices = (1<<17);
-static const int MaxIndices = MaxVertices * 3;
-static sg_pipeline imgui_pip;
-static sg_bindings imgui_bind;
-
-extern const char* vs_src_imgui;
-extern const char* fs_src_imgui;
-
-void imgui_init(int sample_count) {
-    ImGui::CreateContext();
-    ImGui::StyleColorsDark();
-    auto& style = ImGui::GetStyle();
-    style.WindowRounding = 0.0f;
-    style.WindowBorderSize = 1.0f;
-    style.Alpha = 1.0f;
-    auto& io = ImGui::GetIO();
-    io.Fonts->AddFontDefault();
-    io.IniFilename = nullptr;
-    io.KeyMap[ImGuiKey_Tab] = SAPP_KEYCODE_TAB;
-    io.KeyMap[ImGuiKey_LeftArrow] = SAPP_KEYCODE_LEFT;
-    io.KeyMap[ImGuiKey_RightArrow] = SAPP_KEYCODE_RIGHT;
-    io.KeyMap[ImGuiKey_UpArrow] = SAPP_KEYCODE_UP;
-    io.KeyMap[ImGuiKey_DownArrow] = SAPP_KEYCODE_DOWN;
-    io.KeyMap[ImGuiKey_PageUp] = SAPP_KEYCODE_PAGE_UP;
-    io.KeyMap[ImGuiKey_PageDown] = SAPP_KEYCODE_PAGE_DOWN;
-    io.KeyMap[ImGuiKey_Home] = SAPP_KEYCODE_HOME;
-    io.KeyMap[ImGuiKey_End] = SAPP_KEYCODE_END;
-    io.KeyMap[ImGuiKey_Delete] = SAPP_KEYCODE_DELETE;
-    io.KeyMap[ImGuiKey_Backspace] = SAPP_KEYCODE_BACKSPACE;
-    io.KeyMap[ImGuiKey_Space] = SAPP_KEYCODE_SPACE;
-    io.KeyMap[ImGuiKey_Enter] = SAPP_KEYCODE_ENTER;
-    io.KeyMap[ImGuiKey_Escape] = SAPP_KEYCODE_ESCAPE;
-    io.KeyMap[ImGuiKey_A] = SAPP_KEYCODE_A;
-    io.KeyMap[ImGuiKey_C] = SAPP_KEYCODE_C;
-    io.KeyMap[ImGuiKey_V] = SAPP_KEYCODE_V;
-    io.KeyMap[ImGuiKey_X] = SAPP_KEYCODE_X;
-    io.KeyMap[ImGuiKey_Y] = SAPP_KEYCODE_Y;
-    io.KeyMap[ImGuiKey_Z] = SAPP_KEYCODE_Z;
-
-    sg_push_debug_group("imgui init");
-
-    // dynamic vertex- and index-buffers for imgui-generated geometry
-    sg_buffer_desc vbuf_desc = { };
-    vbuf_desc.usage = SG_USAGE_STREAM;
-    vbuf_desc.size = MaxVertices * sizeof(ImDrawVert);
-    vbuf_desc.label = "imgui-vertices";
-    imgui_bind.vertex_buffers[0] = sg_make_buffer(&vbuf_desc);
-
-    sg_buffer_desc ibuf_desc = { };
-    ibuf_desc.type = SG_BUFFERTYPE_INDEXBUFFER;
-    ibuf_desc.usage = SG_USAGE_STREAM;
-    ibuf_desc.size = MaxIndices * sizeof(ImDrawIdx);
-    ibuf_desc.label = "imgui-indices";
-    imgui_bind.index_buffer = sg_make_buffer(&ibuf_desc);
-
-    // font texture for imgui's default font
-    unsigned char* font_pixels;
-    int font_width, font_height;
-    io.Fonts->GetTexDataAsRGBA32(&font_pixels, &font_width, &font_height);
-    sg_image_desc img_desc = { };
-    img_desc.width = font_width;
-    img_desc.height = font_height;
-    img_desc.pixel_format = SG_PIXELFORMAT_RGBA8;
-    img_desc.wrap_u = SG_WRAP_CLAMP_TO_EDGE;
-    img_desc.wrap_v = SG_WRAP_CLAMP_TO_EDGE;
-    img_desc.min_filter = SG_FILTER_LINEAR;
-    img_desc.mag_filter = SG_FILTER_LINEAR;
-    img_desc.content.subimage[0][0].ptr = font_pixels;
-    img_desc.content.subimage[0][0].size = font_width * font_height * 4;
-    img_desc.label = "imgui-font";
-    io.Fonts->TexID = (ImTextureID)(uintptr_t) sg_make_image(&img_desc).id;
-
-    // shader object for imgui rendering
-    sg_shader_desc shd_desc = { };
-    auto& ub = shd_desc.vs.uniform_blocks[0];
-    ub.size = sizeof(vs_params_t);
-    ub.uniforms[0].name = "disp_size";
-    ub.uniforms[0].type = SG_UNIFORMTYPE_FLOAT2;
-    shd_desc.fs.images[0].name = "tex";
-    shd_desc.fs.images[0].type = SG_IMAGETYPE_2D;
-    shd_desc.vs.source = vs_src_imgui;
-    shd_desc.fs.source = fs_src_imgui;
-    shd_desc.label = "imgui-shader";
-    sg_shader shd = sg_make_shader(&shd_desc);
-
-    // pipeline object for imgui rendering
-    sg_pipeline_desc pip_desc = { };
-    pip_desc.layout.buffers[0].stride = sizeof(ImDrawVert);
-    auto& attrs = pip_desc.layout.attrs;
-    attrs[0].name="position"; attrs[0].sem_name="POSITION"; attrs[0].offset=offsetof(ImDrawVert, pos); attrs[0].format=SG_VERTEXFORMAT_FLOAT2;
-    attrs[1].name="texcoord0"; attrs[1].sem_name="TEXCOORD"; attrs[1].offset=offsetof(ImDrawVert, uv); attrs[1].format=SG_VERTEXFORMAT_FLOAT2;
-    attrs[2].name="color0"; attrs[2].sem_name="COLOR"; attrs[2].offset=offsetof(ImDrawVert, col); attrs[2].format=SG_VERTEXFORMAT_UBYTE4N;
-    pip_desc.shader = shd;
-    pip_desc.index_type = SG_INDEXTYPE_UINT16;
-    pip_desc.blend.enabled = true;
-    pip_desc.blend.src_factor_rgb = SG_BLENDFACTOR_SRC_ALPHA;
-    pip_desc.blend.dst_factor_rgb = SG_BLENDFACTOR_ONE_MINUS_SRC_ALPHA;
-    pip_desc.blend.color_write_mask = SG_COLORMASK_RGB;
-    pip_desc.rasterizer.sample_count = sample_count;
-    pip_desc.label = "imgui-pipeline";
-    imgui_pip = sg_make_pipeline(&pip_desc);
-
-    sg_pop_debug_group();
-}
-
-void imgui_newframe(void) {
-    const int cur_width = sapp_width();
-    const int cur_height = sapp_height();
-    ImGuiIO& io = ImGui::GetIO();
-    io.DisplaySize = ImVec2(float(cur_width), float(cur_height));
-    io.DeltaTime = 1.0f / 60.0f;
-    for (int i = 0; i < SAPP_MAX_MOUSEBUTTONS; i++) {
-        if (btn_down[i]) {
-            btn_down[i] = false;
-            io.MouseDown[i] = true;
-        }
-        else if (btn_up[i]) {
-            btn_up[i] = false;
-            io.MouseDown[i] = false;
-        }
-    }
-    ImGui::NewFrame();
-}
-
-void imgui_draw(void) {
-    ImGui::Render();
-    ImDrawData* draw_data = ImGui::GetDrawData();
-    if (nullptr == draw_data) {
-        return;
-    }
-    if (draw_data->CmdListsCount == 0) {
-        return;
-    }
-
-    // render the command list
-    sg_push_debug_group("imgui");
-    sg_apply_pipeline(imgui_pip);
-    vs_params_t vs_params;
-    vs_params.disp_size.x = ImGui::GetIO().DisplaySize.x;
-    vs_params.disp_size.y = ImGui::GetIO().DisplaySize.y;
-    sg_apply_uniforms(SG_SHADERSTAGE_VS, 0, &vs_params, sizeof(vs_params));
-    for (int cl_index = 0; cl_index < draw_data->CmdListsCount; cl_index++) {
-        const ImDrawList* cl = draw_data->CmdLists[cl_index];
-
-        // append vertices and indices to buffers, record start offsets in draw state
-        const int vtx_size = cl->VtxBuffer.size() * sizeof(ImDrawVert);
-        const int idx_size = cl->IdxBuffer.size() * sizeof(ImDrawIdx);
-        const int vb_offset = sg_append_buffer(imgui_bind.vertex_buffers[0], &cl->VtxBuffer.front(), vtx_size);
-        const int ib_offset = sg_append_buffer(imgui_bind.index_buffer, &cl->IdxBuffer.front(), idx_size);
-        /* don't render anything if the buffer is in overflow state (this is also
-            checked internally in sokol_gfx, draw calls that attempt from
-            overflowed buffers will be silently dropped)
-        */
-        if (sg_query_buffer_overflow(imgui_bind.vertex_buffers[0]) ||
-            sg_query_buffer_overflow(imgui_bind.index_buffer))
-        {
-            break;
-        }
-
-        ImTextureID tex_id = ImGui::GetIO().Fonts->TexID;
-        imgui_bind.vertex_buffer_offsets[0] = vb_offset;
-        imgui_bind.index_buffer_offset = ib_offset;
-        imgui_bind.fs_images[0].id = (uint32_t)(uintptr_t)tex_id;
-
-        sg_apply_bindings(&imgui_bind);
-        int base_element = 0;
-        for (const ImDrawCmd& pcmd : cl->CmdBuffer) {
-            if (pcmd.UserCallback) {
-                pcmd.UserCallback(cl, &pcmd);
-            }
-            else {
-                if (tex_id != pcmd.TextureId) {
-                    tex_id = pcmd.TextureId;
-                    imgui_bind.fs_images[0].id = (uint32_t)(uintptr_t)tex_id;
-                    sg_apply_bindings(&imgui_bind);
-                }
-                const int scissor_x = (int) (pcmd.ClipRect.x);
-                const int scissor_y = (int) (pcmd.ClipRect.y);
-                const int scissor_w = (int) (pcmd.ClipRect.z - pcmd.ClipRect.x);
-                const int scissor_h = (int) (pcmd.ClipRect.w - pcmd.ClipRect.y);
-                sg_apply_scissor_rect(scissor_x, scissor_y, scissor_w, scissor_h, true);
-                sg_draw(base_element, pcmd.ElemCount, 1);
-            }
-            base_element += pcmd.ElemCount;
-        }
-    }
-    sg_pop_debug_group();
-}
-
-void imgui_event(const sapp_event* event) {
-    auto& io = ImGui::GetIO();
-    io.KeyAlt = (event->modifiers & SAPP_MODIFIER_ALT) != 0;
-    io.KeyCtrl = (event->modifiers & SAPP_MODIFIER_CTRL) != 0;
-    io.KeyShift = (event->modifiers & SAPP_MODIFIER_SHIFT) != 0;
-    io.KeySuper = (event->modifiers & SAPP_MODIFIER_SUPER) != 0;
-    switch (event->type) {
-        case SAPP_EVENTTYPE_MOUSE_DOWN:
-            io.MousePos.x = event->mouse_x;
-            io.MousePos.y = event->mouse_y;
-            btn_down[event->mouse_button] = true;
-            break;
-        case SAPP_EVENTTYPE_MOUSE_UP:
-            io.MousePos.x = event->mouse_x;
-            io.MousePos.y = event->mouse_y;
-            btn_up[event->mouse_button] = true;
-            break;
-        case SAPP_EVENTTYPE_MOUSE_MOVE:
-            io.MousePos.x = event->mouse_x;
-            io.MousePos.y = event->mouse_y;
-            break;
-        case SAPP_EVENTTYPE_MOUSE_ENTER:
-        case SAPP_EVENTTYPE_MOUSE_LEAVE:
-            for (int i = 0; i < 3; i++) {
-                btn_down[i] = false;
-                btn_up[i] = false;
-                io.MouseDown[i] = false;
-            }
-            break;
-        case SAPP_EVENTTYPE_MOUSE_SCROLL:
-            io.MouseWheelH = event->scroll_x;
-            io.MouseWheel = event->scroll_y;
-            break;
-        case SAPP_EVENTTYPE_TOUCHES_BEGAN:
-            btn_down[0] = true;
-            io.MousePos.x = event->touches[0].pos_x;
-            io.MousePos.y = event->touches[0].pos_y;
-            break;
-        case SAPP_EVENTTYPE_TOUCHES_MOVED:
-            io.MousePos.x = event->touches[0].pos_x;
-            io.MousePos.y = event->touches[0].pos_y;
-            break;
-        case SAPP_EVENTTYPE_TOUCHES_ENDED:
-            btn_up[0] = true;
-            io.MousePos.x = event->touches[0].pos_x;
-            io.MousePos.y = event->touches[0].pos_y;
-            break;
-        case SAPP_EVENTTYPE_TOUCHES_CANCELLED:
-            btn_up[0] = btn_down[0] = false;
-            break;
-        case SAPP_EVENTTYPE_KEY_DOWN:
-            io.KeysDown[event->key_code] = true;
-            break;
-        case SAPP_EVENTTYPE_KEY_UP:
-            io.KeysDown[event->key_code] = false;
-            break;
-        case SAPP_EVENTTYPE_CHAR:
-            io.AddInputCharacter((ImWchar)event->char_code);
-            break;
-        default:
-            break;
-    }
-}
-
-#if defined(SOKOL_GLCORE33)
-const char* vs_src_imgui =
-    "#version 330\n"
-    "uniform vec2 disp_size;\n"
-    "in vec2 position;\n"
-    "in vec2 texcoord0;\n"
-    "in vec4 color0;\n"
-    "out vec2 uv;\n"
-    "out vec4 color;\n"
-    "void main() {\n"
-    "    gl_Position = vec4(((position/disp_size)-0.5)*vec2(2.0,-2.0), 0.5, 1.0);\n"
-    "    uv = texcoord0;\n"
-    "    color = color0;\n"
-    "}\n";
-const char* fs_src_imgui =
-    "#version 330\n"
-    "uniform sampler2D tex;\n"
-    "in vec2 uv;\n"
-    "in vec4 color;\n"
-    "out vec4 frag_color;\n"
-    "void main() {\n"
-    "    frag_color = texture(tex, uv) * color;\n"
-    "}\n";
-#elif defined(SOKOL_GLES2) || defined(SOKOL_GLES3)
-const char* vs_src_imgui =
-    "uniform vec2 disp_size;\n"
-    "attribute vec2 position;\n"
-    "attribute vec2 texcoord0;\n"
-    "attribute vec4 color0;\n"
-    "varying vec2 uv;\n"
-    "varying vec4 color;\n"
-    "void main() {\n"
-    "    gl_Position = vec4(((position/disp_size)-0.5)*vec2(2.0,-2.0), 0.5, 1.0);\n"
-    "    uv = texcoord0;\n"
-    "    color = color0;\n"
-    "}\n";
-const char* fs_src_imgui =
-    "precision mediump float;\n"
-    "uniform sampler2D tex;\n"
-    "varying vec2 uv;\n"
-    "varying vec4 color;\n"
-    "void main() {\n"
-    "    gl_FragColor = texture2D(tex, uv) * color;\n"
-    "}\n";
-#elif defined(SOKOL_METAL)
-const char* vs_src_imgui =
-    "#include <metal_stdlib>\n"
-    "using namespace metal;\n"
-    "struct params_t {\n"
-    "  float2 disp_size;\n"
-    "};\n"
-    "struct vs_in {\n"
-    "  float2 pos [[attribute(0)]];\n"
-    "  float2 uv [[attribute(1)]];\n"
-    "  float4 color [[attribute(2)]];\n"
-    "};\n"
-    "struct vs_out {\n"
-    "  float4 pos [[position]];\n"
-    "  float2 uv;\n"
-    "  float4 color;\n"
-    "};\n"
-    "vertex vs_out _main(vs_in in [[stage_in]], constant params_t& params [[buffer(0)]]) {\n"
-    "  vs_out out;\n"
-    "  out.pos = float4(((in.pos / params.disp_size)-0.5)*float2(2.0,-2.0), 0.5, 1.0);\n"
-    "  out.uv = in.uv;\n"
-    "  out.color = in.color;\n"
-    "  return out;\n"
-    "}\n";
-const char* fs_src_imgui =
-    "#include <metal_stdlib>\n"
-    "using namespace metal;\n"
-    "struct fs_in {\n"
-    "  float2 uv;\n"
-    "  float4 color;\n"
-    "};\n"
-    "fragment float4 _main(fs_in in [[stage_in]], texture2d<float> tex [[texture(0)]], sampler smp [[sampler(0)]]) {\n"
-    "  return tex.sample(smp, in.uv) * in.color;\n"
-    "}\n";
-#elif defined(SOKOL_D3D11)
-const char* vs_src_imgui =
-    "cbuffer params {\n"
-    "  float2 disp_size;\n"
-    "};\n"
-    "struct vs_in {\n"
-    "  float2 pos: POSITION;\n"
-    "  float2 uv: TEXCOORD0;\n"
-    "  float4 color: COLOR0;\n"
-    "};\n"
-    "struct vs_out {\n"
-    "  float2 uv: TEXCOORD0;\n"
-    "  float4 color: COLOR0;\n"
-    "  float4 pos: SV_Position;\n"
-    "};\n"
-    "vs_out main(vs_in inp) {\n"
-    "  vs_out outp;\n"
-    "  outp.pos = float4(((inp.pos/disp_size)-0.5)*float2(2.0,-2.0), 0.5, 1.0);\n"
-    "  outp.uv = inp.uv;\n"
-    "  outp.color = inp.color;\n"
-    "  return outp;\n"
-    "}\n";
-const char* fs_src_imgui =
-    "Texture2D<float4> tex: register(t0);\n"
-    "sampler smp: register(s0);\n"
-    "float4 main(float2 uv: TEXCOORD0, float4 color: COLOR0): SV_Target0 {\n"
-    "  return tex.Sample(smp, uv) * color;\n"
-    "}\n";
-#else
-#error "No sokol-gfx backend selected"
-#endif
-
-#endif /* UI_IMPL */
-```
-
-### 5. Add UI init- and rendering-calls to your code
-
-All debug inspection headers follow the same API pattern (here shown
-with ```sokol_gfx_imgui.h``` as an example):
-
-- a struct to store all state
-- an init-function to initialize this struct to a good state
-- a one-in-all draw-function which is called per frame
-- ...and a discard function called at shutdown
-
-```cpp
-static sg_imgui_t sg_imgui;
-
-void init(void) {
-    ...
-    /* initialize the sokol-gfx debug inspection UI */
-    sg_imgui_init(&sg_imgui)
-    ...
-}
-
-void draw_frame(void) {
-    ...
-    /* draw the debug inspection UI via Dear ImGui calls */
-    sg_imgui_draw(&sg_imgui);
-    ...
-}
-
-void shutdown(void) {
-    ...
-    sg_imgui_discard(&sg_imgui);
-    ...
-}
-```
-
-When running this code, nothing will be rendered because all debug inspection
-windows are in closed state. Opening and closing the windows is done
-directly by toggling public bool members of the state struct.
-
-For instance in with sokol_gfx_imgui.h:
-
-```cpp
-/* open all sokol_gfx_imgui.h windows */
-sg_imgui.buffers.open = true
-sg_imgui.images.open = true;
-sg_imgui.shaders.open = true;
-sg_imgui.pipelines.open = true;
-sg_imgui.passes.open = true;
-sg_imgui.capture.open = true;
-```
-
-Exposing the open state as booleans has been done to make it easier to 
-toggle the window visibility with other ImGui functions. For instance
-you could build a menu like this:
-
-```cpp
-if (ImGui::BeginMainMenuBar()) {
-    if (ImGui::BeginMenu("sokol-gfx")) {
-        ImGui::MenuItem("Buffers", 0, &sg_imgui.buffers.open);
-        ImGui::MenuItem("Images", 0, &sg_imgui.images.open);
-        ImGui::MenuItem("Shaders", 0, &sg_imgui.shaders.open);
-        ImGui::MenuItem("Pipelines", 0, &sg_imgui.pipelines.open);
-        ImGui::MenuItem("Passes", 0, &sg_imgui.passes.open);
-        ImGui::MenuItem("Calls", 0, &sg_imgui.capture.open);
-        ImGui::EndMenu();
-    }
-    ImGui::EndMainMenuBar();
-}
-```
-
-The debug inspection headers also offer more granular drawing functions
-for more flexible integration into your own UI, for example the following
-```sokol_gfx_imgui.h``` functions only draw the window content, so you
-can integrate the UIs into your own windows:
-
-```cpp
-void sg_imgui_draw_buffers_content(sg_imgui_t* ctx);
-void sg_imgui_draw_images_content(sg_imgui_t* ctx);
-void sg_imgui_draw_shaders_content(sg_imgui_t* ctx);
-void sg_imgui_draw_pipelines_content(sg_imgui_t* ctx);
-void sg_imgui_draw_passes_content(sg_imgui_t* ctx);
-void sg_imgui_draw_capture_content(sg_imgui_t* ctx);
-```

+ 11 - 3
util/README.md

@@ -1,7 +1,15 @@
 # Sokol Utility Headers
 
 These are optional utility headers on top of the Sokol headers. Unlike the
-'core headers' they are not standalone, and usually do not contain
-platform specific code.
+'core headers' they are not standalone but depend on other Sokol headers
+and sometimes also external libraries.
 
-FIXME: overview of the headers, and general usage instructions.
+### What's in here:
+
+- **sokol_imgui.h**: implements a renderer for [Dear ImGui](https://github.com/ocornut/imgui) on top of sokol_gfx.h and sokol_app.h (the latter being optional if you do your own input-forwarding to ImGui)
+- **sokol_gfx_imgui.h**: a debug-inspection UI for sokol_gfx.h, this hooks into the sokol-gfx API and lets you inspect resource objects and captured API calls
+- **sokol_gl.h**: (WIP) an OpenGL 1.x style immediate-mode rendering API
+in top of sokol-gfx
+- **sokol_dbgtxt.h**: (planned) an as simple-as-possible debug-text renderer on top of sokol-gl
+
+See the embedded header-documentation for build- and usage-details.

+ 53 - 22
imgui/sokol_gfx_imgui.h → util/sokol_gfx_imgui.h

@@ -2,29 +2,44 @@
 /*
     sokol_gfx_imgui.h -- debug-inspection UI for sokol_gfx.h using Dear ImGui
 
-    This is an extension header for sokol_gfx.h, this means sokol_gfx_imgui.h
-    must be included *after* sokol_gfx.h both for the implementation
-    and declaration.
+    Do this:
+        #define SOKOL_GFX_IMGUI_IMPL
+    before you include this file in *one* C++ file to create the
+    implementation.
 
-    You also need to include imgui.h before including the implementation
-    of sokol_gfx_imgui.h.
+    NOTE that the implementation must be compiled as C++ or Objective-C++
+    because it calls into the ImGui C++ API. The sokol_gfx_imgui.h API
+    itself is plain C though.
 
-    The implementation must be compiled as C++ or Objective-C++, the
-    declaration can be included in plain C sources.
+    Include the following file(s) before including sokol_gfx_imgui.h:
 
-    The sokol_gfx_imgui.h header recognizes the same preprocessor defines
-    that have been set for the actual Sokol headers (for instance
-    SOKOL_IMPL, SOKOL_MALLOC, SOKOL_LOG, etc...).
+        sokol_gfx.h
 
-    STEP BY STEP:
-    =============
-    --- include the sokol_gfx_imgui.h header after the actual Sokol header
-        implementations and the imgui.h header (and make sure this code
-        is compiled as C++ or Objective-C++)
+    Additionally, include the following files(s) beforing including
+    the implementation of sokol_gfx_imgui.h:
+
+        imgui.h
+
+    The sokol_gfx.h implementation must be compiled with debug trace hooks
+    enabled by defining:
 
-    --- add a Dear ImGui renderer to your application, and the basic
-        per-frame code to render an ImGui UI.
+        SOKOL_TRACE_HOOKS
 
+    ...before including the sokol_gfx.h implementation.
+
+    Before including the sokol_gfx_imgui.h implementation, optionally
+    override the following macros:
+
+        SOKOL_ASSERT(c)     -- your own assert macro, default: assert(c)
+        SOKOL_UNREACHABLE   -- your own macro to annotate unreachable code,
+                               default: SOKOL_ASSERT(false)
+        SOKOL_MALLOC(s)     -- your own memory allocation function, default: malloc(s)
+        SOKOL_FREE(p)       -- your own memory free function, default: free(p)
+        SOKOL_API_DECL      - public function declaration prefix (default: extern)
+        SOKOL_API_IMPL      - public function implementation prefix (default: -)
+
+    STEP BY STEP:
+    =============
     --- create an sg_imgui_t struct (which must be preserved between frames)
         and initialize it with:
 
@@ -62,13 +77,15 @@
                 ImGui::EndMainMenuBar();
             }
 
-    --- finally before application shutdown, call:
+    --- before application shutdown, call:
 
             sg_imgui_discard(&sg_imgui);
 
         ...this is not strictly necessary because the application exits
         anyway, but not doing this may trigger memory leak detection tools.
 
+    --- finally, your application needs an ImGui renderer, you can either
+        provide your own, or drop in the sokol_imgui.h utility header
 
     ALTERNATIVE DRAWING FUNCTIONS:
     ==============================
@@ -98,8 +115,8 @@
     Finer-grained drawing functions may be moved to the public API
     in the future as needed.
 
-
-
+    LICENSE
+    =======
     zlib/libpng license
 
     Copyright (c) 2018 Andre Weissflog
@@ -130,6 +147,10 @@
 #error "Please include sokol_gfx.h before sokol_gfx_imgui.h"
 #endif
 
+#ifndef SOKOL_API_DECL
+#define SOKOL_API_DECL extern
+#endif
+
 #if defined(__cplusplus)
 extern "C" {
 #endif
@@ -541,7 +562,7 @@ SOKOL_API_DECL void sg_imgui_draw_capture_window(sg_imgui_t* ctx);
 #endif
 
 /*=== IMPLEMENTATION =========================================================*/
-#if defined SOKOL_IMPL
+#if defined SOKOL_GFX_IMGUI_IMPL
 #if !defined(IMGUI_VERSION)
 #error "Please include imgui.h before the sokol_gfx_imgui.h implementation"
 #endif
@@ -557,6 +578,16 @@ SOKOL_API_DECL void sg_imgui_draw_capture_window(sg_imgui_t* ctx);
     #define SOKOL_MALLOC(s) malloc(s)
     #define SOKOL_FREE(p) free(p)
 #endif
+#ifndef _SOKOL_PRIVATE
+    #if defined(__GNUC__)
+        #define _SOKOL_PRIVATE __attribute__((unused)) static
+    #else
+        #define _SOKOL_PRIVATE static
+    #endif
+#endif
+#ifndef SOKOL_API_IMPL
+#define SOKOL_API_IMPL
+#endif
 
 #include <string.h>
 #include <stdio.h>      /* snprintf */
@@ -3421,4 +3452,4 @@ SOKOL_API_IMPL void sg_imgui_draw_capture_content(sg_imgui_t* ctx) {
     _sg_imgui_draw_capture_panel(ctx);
 }
 
-#endif /* SOKOL_IMPL */
+#endif /* SOKOL_GFX_IMGUI_IMPL */