浏览代码

Merge branch 'master' of https://github.com/benoitjacquier/bgfx into readtexture_mip

benoitjacquier 9 年之前
父节点
当前提交
9a0e685861
共有 42 个文件被更改,包括 1697 次插入2687 次删除
  1. 83 82
      3rdparty/ocornut-imgui/imgui.cpp
  2. 19 19
      3rdparty/ocornut-imgui/imgui.h
  3. 12 10
      3rdparty/ocornut-imgui/imgui_demo.cpp
  4. 20 18
      3rdparty/ocornut-imgui/imgui_draw.cpp
  5. 10 1
      3rdparty/ocornut-imgui/imgui_internal.h
  6. 1 0
      3rdparty/ocornut-imgui/imgui_user.h
  7. 1 0
      3rdparty/ocornut-imgui/imgui_user.inl
  8. 0 1688
      3rdparty/ocornut-imgui/imgui_wm.cpp
  9. 0 310
      3rdparty/ocornut-imgui/imgui_wm.h
  10. 21 0
      3rdparty/ocornut-imgui/widgets/dock.h
  11. 1084 0
      3rdparty/ocornut-imgui/widgets/dock.inl
  12. 44 40
      3rdparty/stb/stb_textedit.h
  13. 32 0
      examples/08-update/cs_update.sc
  14. 62 19
      examples/08-update/update.cpp
  15. 1 0
      examples/15-shadowmaps-simple/shadowmaps_simple.cpp
  16. 2 5
      examples/common/entry/entry_windows.cpp
  17. 0 1
      examples/common/imgui/imgui.h
  18. 2 353
      examples/common/imgui/ocornut_imgui.cpp
  19. 4 0
      examples/common/nanovg/nanovg.cpp
  20. 0 2
      examples/runtime/.gitignore
  21. 二进制
      examples/runtime/shaders/dx11/cs_update.bin
  22. 二进制
      examples/runtime/shaders/glsl/cs_update.bin
  23. 1 0
      examples/runtime/shaders/pssl/.gitignore
  24. 1 0
      examples/runtime/shaders/spirv/.gitignore
  25. 23 21
      include/bgfx/bgfx.h
  26. 1 0
      include/bgfx/bgfxplatform.h
  27. 1 0
      include/bgfx/c99/bgfxplatform.h
  28. 5 3
      scripts/shader.mk
  29. 15 7
      scripts/shaderc.lua
  30. 24 19
      src/bgfx.cpp
  31. 8 1
      src/bgfx_compute.sh
  32. 32 18
      src/bgfx_p.h
  33. 1 1
      src/bgfx_shader.sh
  34. 4 0
      src/config.h
  35. 5 1
      src/glimports.h
  36. 0 1
      src/hmd.h
  37. 32 8
      src/hmd_ovr.cpp
  38. 2 2
      src/image.cpp
  39. 68 32
      src/renderer_gl.cpp
  40. 20 0
      src/renderer_gl.h
  41. 54 23
      tools/shaderc/shaderc.cpp
  42. 2 2
      tools/shaderc/shaderc_hlsl.cpp

+ 83 - 82
3rdparty/ocornut-imgui/imgui.cpp

@@ -150,6 +150,7 @@
  Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code.
  Also read releases logs https://github.com/ocornut/imgui/releases for more details.
 
+ - 2016/10/15 (1.50) - avoid 'void* user_data' parameter to io.SetClipboardTextFn/io.GetClipboardTextFn pointers. We pass io.ClipboardUserData to it.
  - 2016/09/25 (1.50) - style.WindowTitleAlign is now a ImVec2 (ImGuiAlign enum was removed). set to (0.5f,0.5f) for horizontal+vertical centering, (0.0f,0.0f) for upper-left, etc.
  - 2016/07/30 (1.50) - SameLine(x) with x>0.0f is now relative to left of column/group if any, and not always to left of window. This was sort of always the intent and hopefully breakage should be minimal.
  - 2016/05/12 (1.49) - title bar (using ImGuiCol_TitleBg/ImGuiCol_TitleBgActive colors) isn't rendered over a window background (ImGuiCol_WindowBg color) anymore. 
@@ -294,7 +295,7 @@
     Also make sure your orthographic projection matrix and io.DisplaySize matches your actual framebuffer dimension.
 
  Q: I integrated ImGui in my engine and some elements are clipping or disappearing when I move windows around..
- A: Most likely you are mishandling the clipping rectangles in your render function. Rectangles provided by ImGui are defined as (x1,y1,x2,y2) and NOT as (x1,y1,width,height).
+ A: Most likely you are mishandling the clipping rectangles in your render function. Rectangles provided by ImGui are defined as (x1=left,y1=top,x2=right,y2=bottom) and NOT as (x1,y1,width,height).
 
  Q: Can I have multiple widgets with the same label? Can I have widget without a label? (Yes)
  A: Yes. A primer on the use of labels/IDs in ImGui..
@@ -708,8 +709,8 @@ static bool             DataTypeApplyOpFromText(const char* buf, const char* ini
 // Platform dependent default implementations
 //-----------------------------------------------------------------------------
 
-static const char*      GetClipboardTextFn_DefaultImpl();
-static void             SetClipboardTextFn_DefaultImpl(const char* text);
+static const char*      GetClipboardTextFn_DefaultImpl(void* user_data);
+static void             SetClipboardTextFn_DefaultImpl(void* user_data, const char* text);
 static void             ImeSetInputScreenPosFn_DefaultImpl(int x, int y);
 
 //-----------------------------------------------------------------------------
@@ -834,6 +835,7 @@ ImGuiIO::ImGuiIO()
     MemFreeFn = free;
     GetClipboardTextFn = GetClipboardTextFn_DefaultImpl;   // Platform dependent default implementations
     SetClipboardTextFn = SetClipboardTextFn_DefaultImpl;
+    ClipboardUserData = NULL;
     ImeSetInputScreenPosFn = ImeSetInputScreenPosFn_DefaultImpl;
 
     // Set OS X style defaults based on __APPLE__ compile time flag
@@ -2015,13 +2017,13 @@ void ImGui::MemFree(void* ptr)
 
 const char* ImGui::GetClipboardText()
 {
-    return GImGui->IO.GetClipboardTextFn ? GImGui->IO.GetClipboardTextFn() : "";
+    return GImGui->IO.GetClipboardTextFn ? GImGui->IO.GetClipboardTextFn(GImGui->IO.ClipboardUserData) : "";
 }
 
 void ImGui::SetClipboardText(const char* text)
 {
     if (GImGui->IO.SetClipboardTextFn)
-        GImGui->IO.SetClipboardTextFn(text);
+        GImGui->IO.SetClipboardTextFn(GImGui->IO.ClipboardUserData, text);
 }
 
 const char* ImGui::GetVersion()
@@ -2934,7 +2936,7 @@ void ImGui::RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border,
 }
 
 // Render a triangle to denote expanded/collapsed state
-void ImGui::RenderCollapseTriangle(ImVec2 p_min, bool is_open, float scale, bool shadow)
+void ImGui::RenderCollapseTriangle(ImVec2 p_min, bool is_open, float scale)
 {
     ImGuiContext& g = *GImGui;
     ImGuiWindow* window = GetCurrentWindow();
@@ -2958,8 +2960,6 @@ void ImGui::RenderCollapseTriangle(ImVec2 p_min, bool is_open, float scale, bool
         c = center + ImVec2(-0.500f,-0.866f)*r;
     }
 
-    if (shadow && (window->Flags & ImGuiWindowFlags_ShowBorders) != 0)
-        window->DrawList->AddTriangleFilled(a+ImVec2(2,2), b+ImVec2(2,2), c+ImVec2(2,2), GetColorU32(ImGuiCol_BorderShadow));
     window->DrawList->AddTriangleFilled(a, b, c, GetColorU32(ImGuiCol_Text));
 }
 
@@ -3495,11 +3495,11 @@ static bool BeginPopupEx(const char* str_id, ImGuiWindowFlags extra_flags)
     ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
     ImGuiWindowFlags flags = extra_flags|ImGuiWindowFlags_Popup|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_AlwaysAutoResize;
 
-    char name[32];
+    char name[20];
     if (flags & ImGuiWindowFlags_ChildMenu)
-        ImFormatString(name, 20, "##menu_%d", g.CurrentPopupStack.Size);    // Recycle windows based on depth
+        ImFormatString(name, IM_ARRAYSIZE(name), "##menu_%d", g.CurrentPopupStack.Size);    // Recycle windows based on depth
     else
-        ImFormatString(name, 20, "##popup_%08x", id); // Not recycling, so we can close/open during the same frame
+        ImFormatString(name, IM_ARRAYSIZE(name), "##popup_%08x", id); // Not recycling, so we can close/open during the same frame
 
     bool is_open = ImGui::Begin(name, NULL, flags);
     if (!(window->Flags & ImGuiWindowFlags_ShowBorders))
@@ -4199,8 +4199,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us
             window->ScrollbarSizes = ImVec2(window->ScrollbarY ? style.ScrollbarSize : 0.0f, window->ScrollbarX ? style.ScrollbarSize : 0.0f);
             window->BorderSize = (flags & ImGuiWindowFlags_ShowBorders) ? 1.0f : 0.0f;
 
-            // Window background
-            // Default alpha
+            // Window background, Default Alpha
             ImGuiCol bg_color_idx = ImGuiCol_WindowBg;
             if ((flags & ImGuiWindowFlags_ComboBox) != 0)
                 bg_color_idx = ImGuiCol_ComboBg;
@@ -4213,19 +4212,19 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us
                 bg_color.w = bg_alpha;
             bg_color.w *= style.Alpha;
             if (bg_color.w > 0.0f)
-                window->DrawList->AddRectFilled(window->Pos+ImVec2(0,window->TitleBarHeight()), window->Pos+window->Size, ColorConvertFloat4ToU32(bg_color), window_rounding, (flags & ImGuiWindowFlags_NoTitleBar) ? 15 : 4|8);
+                window->DrawList->AddRectFilled(window->Pos+ImVec2(0,window->TitleBarHeight()), window->Pos+window->Size, ColorConvertFloat4ToU32(bg_color), window_rounding, (flags & ImGuiWindowFlags_NoTitleBar) ? ImGuiCorner_All : ImGuiCorner_BottomLeft|ImGuiCorner_BottomRight);
 
             // Title bar
             if (!(flags & ImGuiWindowFlags_NoTitleBar))
-                window->DrawList->AddRectFilled(title_bar_rect.GetTL(), title_bar_rect.GetBR(), GetColorU32((g.FocusedWindow && window->RootNonPopupWindow == g.FocusedWindow->RootNonPopupWindow) ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBg), window_rounding, 1|2);
+                window->DrawList->AddRectFilled(title_bar_rect.GetTL(), title_bar_rect.GetBR(), GetColorU32((g.FocusedWindow && window->RootNonPopupWindow == g.FocusedWindow->RootNonPopupWindow) ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBg), window_rounding, ImGuiCorner_TopLeft|ImGuiCorner_TopRight);
 
             // Menu bar
             if (flags & ImGuiWindowFlags_MenuBar)
             {
                 ImRect menu_bar_rect = window->MenuBarRect();
-                window->DrawList->AddRectFilled(menu_bar_rect.GetTL(), menu_bar_rect.GetBR(), GetColorU32(ImGuiCol_MenuBarBg), (flags & ImGuiWindowFlags_NoTitleBar) ? window_rounding : 0.0f, 1|2);
                 if (flags & ImGuiWindowFlags_ShowBorders)
-                    window->DrawList->AddLine(menu_bar_rect.GetBL()-ImVec2(0,0), menu_bar_rect.GetBR()-ImVec2(0,0), GetColorU32(ImGuiCol_Border));
+                    window->DrawList->AddLine(menu_bar_rect.GetBL(), menu_bar_rect.GetBR(), GetColorU32(ImGuiCol_Border));
+                window->DrawList->AddRectFilled(menu_bar_rect.GetTL(), menu_bar_rect.GetBR(), GetColorU32(ImGuiCol_MenuBarBg), (flags & ImGuiWindowFlags_NoTitleBar) ? window_rounding : 0.0f, ImGuiCorner_TopLeft|ImGuiCorner_TopRight);
             }
 
             // Scrollbars
@@ -4317,7 +4316,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us
 
             const ImVec2 text_size = CalcTextSize(name, NULL, true);
             if (!(flags & ImGuiWindowFlags_NoCollapse))
-                RenderCollapseTriangle(window->Pos + style.FramePadding, !window->Collapsed, 1.0f, true);
+                RenderCollapseTriangle(window->Pos + style.FramePadding, !window->Collapsed, 1.0f);
 
             ImVec2 text_min = window->Pos;
             ImVec2 text_max = window->Pos + ImVec2(window->Size.x, style.FramePadding.y*2 + text_size.y);
@@ -4433,9 +4432,9 @@ static void Scrollbar(ImGuiWindow* window, bool horizontal)
     float window_rounding = (window->Flags & ImGuiWindowFlags_ChildWindow) ? style.ChildWindowRounding : style.WindowRounding;
     int window_rounding_corners;
     if (horizontal)
-        window_rounding_corners = 8 | (other_scrollbar ? 0 : 4);
+        window_rounding_corners = ImGuiCorner_BottomLeft | (other_scrollbar ? 0 : ImGuiCorner_BottomRight);
     else
-        window_rounding_corners = (((window->Flags & ImGuiWindowFlags_NoTitleBar) && !(window->Flags & ImGuiWindowFlags_MenuBar)) ? 2 : 0) | (other_scrollbar ? 0 : 4);
+        window_rounding_corners = (((window->Flags & ImGuiWindowFlags_NoTitleBar) && !(window->Flags & ImGuiWindowFlags_MenuBar)) ? ImGuiCorner_TopRight : 0) | (other_scrollbar ? 0 : ImGuiCorner_BottomRight);
     window->DrawList->AddRectFilled(bb.Min, bb.Max, ImGui::GetColorU32(ImGuiCol_ScrollbarBg), window_rounding, window_rounding_corners);
     bb.Reduce(ImVec2(ImClamp((float)(int)((bb.Max.x - bb.Min.x - 2.0f) * 0.5f), 0.0f, 3.0f), ImClamp((float)(int)((bb.Max.y - bb.Min.y - 2.0f) * 0.5f), 0.0f, 3.0f)));
 
@@ -5805,8 +5804,7 @@ void ImGui::LogFinish()
     }
     if (g.LogClipboard->size() > 1)
     {
-        if (g.IO.SetClipboardTextFn)
-            g.IO.SetClipboardTextFn(g.LogClipboard->begin());
+        SetClipboardText(g.LogClipboard->begin());
         g.LogClipboard->clear();
     }
 }
@@ -5956,7 +5954,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
     {
         // Framed type
         RenderFrame(bb.Min, bb.Max, col, true, style.FrameRounding);
-        RenderCollapseTriangle(bb.Min + padding + ImVec2(0.0f, text_base_offset_y), is_open, 1.0f, true);
+        RenderCollapseTriangle(bb.Min + padding + ImVec2(0.0f, text_base_offset_y), is_open, 1.0f);
         if (g.LogEnabled)
         {
             // NB: '##' is normally used to hide text (as a library-wide feature), so we need to specify the text range to make sure the ## aren't stripped out here.
@@ -5980,7 +5978,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
         if (flags & ImGuiTreeNodeFlags_Bullet)
             RenderBullet(bb.Min + ImVec2(text_offset_x * 0.5f, g.FontSize*0.50f + text_base_offset_y));
         else if (!(flags & ImGuiTreeNodeFlags_Leaf))
-            RenderCollapseTriangle(bb.Min + ImVec2(padding.x, g.FontSize*0.15f + text_base_offset_y), is_open, 0.70f, false);
+            RenderCollapseTriangle(bb.Min + ImVec2(padding.x, g.FontSize*0.15f + text_base_offset_y), is_open, 0.70f);
         if (g.LogEnabled)
             LogRenderedText(text_pos, ">");
         RenderText(text_pos, label, label_end, false);
@@ -7086,59 +7084,62 @@ void ImGui::PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_ge
 
     RenderFrame(frame_bb.Min, frame_bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding);
 
-    int res_w = ImMin((int)graph_size.x, values_count) + ((plot_type == ImGuiPlotType_Lines) ? -1 : 0);
-    int item_count = values_count + ((plot_type == ImGuiPlotType_Lines) ? -1 : 0);
-
-    // Tooltip on hover
-    int v_hovered = -1;
-    if (IsHovered(inner_bb, 0))
+    if (values_count > 0)
     {
-        const float t = ImClamp((g.IO.MousePos.x - inner_bb.Min.x) / (inner_bb.Max.x - inner_bb.Min.x), 0.0f, 0.9999f);
-        const int v_idx = (int)(t * item_count);
-        IM_ASSERT(v_idx >= 0 && v_idx < values_count);
-
-        const float v0 = values_getter(data, (v_idx + values_offset) % values_count);
-        const float v1 = values_getter(data, (v_idx + 1 + values_offset) % values_count);
-        if (plot_type == ImGuiPlotType_Lines)
-            SetTooltip("%d: %8.4g\n%d: %8.4g", v_idx, v0, v_idx+1, v1);
-        else if (plot_type == ImGuiPlotType_Histogram)
-            SetTooltip("%d: %8.4g", v_idx, v0);
-        v_hovered = v_idx;
-    }
+        int res_w = ImMin((int)graph_size.x, values_count) + ((plot_type == ImGuiPlotType_Lines) ? -1 : 0);
+        int item_count = values_count + ((plot_type == ImGuiPlotType_Lines) ? -1 : 0);
 
-    const float t_step = 1.0f / (float)res_w;
+        // Tooltip on hover
+        int v_hovered = -1;
+        if (IsHovered(inner_bb, 0))
+        {
+            const float t = ImClamp((g.IO.MousePos.x - inner_bb.Min.x) / (inner_bb.Max.x - inner_bb.Min.x), 0.0f, 0.9999f);
+            const int v_idx = (int)(t * item_count);
+            IM_ASSERT(v_idx >= 0 && v_idx < values_count);
+
+            const float v0 = values_getter(data, (v_idx + values_offset) % values_count);
+            const float v1 = values_getter(data, (v_idx + 1 + values_offset) % values_count);
+            if (plot_type == ImGuiPlotType_Lines)
+                SetTooltip("%d: %8.4g\n%d: %8.4g", v_idx, v0, v_idx+1, v1);
+            else if (plot_type == ImGuiPlotType_Histogram)
+                SetTooltip("%d: %8.4g", v_idx, v0);
+            v_hovered = v_idx;
+        }
 
-    float v0 = values_getter(data, (0 + values_offset) % values_count);
-    float t0 = 0.0f;
-    ImVec2 tp0 = ImVec2( t0, 1.0f - ImSaturate((v0 - scale_min) / (scale_max - scale_min)) );    // Point in the normalized space of our target rectangle
+        const float t_step = 1.0f / (float)res_w;
 
-    const ImU32 col_base = GetColorU32((plot_type == ImGuiPlotType_Lines) ? ImGuiCol_PlotLines : ImGuiCol_PlotHistogram);
-    const ImU32 col_hovered = GetColorU32((plot_type == ImGuiPlotType_Lines) ? ImGuiCol_PlotLinesHovered : ImGuiCol_PlotHistogramHovered);
+        float v0 = values_getter(data, (0 + values_offset) % values_count);
+        float t0 = 0.0f;
+        ImVec2 tp0 = ImVec2( t0, 1.0f - ImSaturate((v0 - scale_min) / (scale_max - scale_min)) );    // Point in the normalized space of our target rectangle
 
-    for (int n = 0; n < res_w; n++)
-    {
-        const float t1 = t0 + t_step;
-        const int v1_idx = (int)(t0 * item_count + 0.5f);
-        IM_ASSERT(v1_idx >= 0 && v1_idx < values_count);
-        const float v1 = values_getter(data, (v1_idx + values_offset + 1) % values_count);
-        const ImVec2 tp1 = ImVec2( t1, 1.0f - ImSaturate((v1 - scale_min) / (scale_max - scale_min)) );
+        const ImU32 col_base = GetColorU32((plot_type == ImGuiPlotType_Lines) ? ImGuiCol_PlotLines : ImGuiCol_PlotHistogram);
+        const ImU32 col_hovered = GetColorU32((plot_type == ImGuiPlotType_Lines) ? ImGuiCol_PlotLinesHovered : ImGuiCol_PlotHistogramHovered);
 
-        // NB: Draw calls are merged together by the DrawList system. Still, we should render our batch are lower level to save a bit of CPU.
-        ImVec2 pos0 = ImLerp(inner_bb.Min, inner_bb.Max, tp0);
-        ImVec2 pos1 = ImLerp(inner_bb.Min, inner_bb.Max, (plot_type == ImGuiPlotType_Lines) ? tp1 : ImVec2(tp1.x, 1.0f));
-        if (plot_type == ImGuiPlotType_Lines)
-        {
-            window->DrawList->AddLine(pos0, pos1, v_hovered == v1_idx ? col_hovered : col_base);
-        }
-        else if (plot_type == ImGuiPlotType_Histogram)
+        for (int n = 0; n < res_w; n++)
         {
-            if (pos1.x >= pos0.x + 2.0f)
-                pos1.x -= 1.0f;
-            window->DrawList->AddRectFilled(pos0, pos1, v_hovered == v1_idx ? col_hovered : col_base);
-        }
+            const float t1 = t0 + t_step;
+            const int v1_idx = (int)(t0 * item_count + 0.5f);
+            IM_ASSERT(v1_idx >= 0 && v1_idx < values_count);
+            const float v1 = values_getter(data, (v1_idx + values_offset + 1) % values_count);
+            const ImVec2 tp1 = ImVec2( t1, 1.0f - ImSaturate((v1 - scale_min) / (scale_max - scale_min)) );
+
+            // NB: Draw calls are merged together by the DrawList system. Still, we should render our batch are lower level to save a bit of CPU.
+            ImVec2 pos0 = ImLerp(inner_bb.Min, inner_bb.Max, tp0);
+            ImVec2 pos1 = ImLerp(inner_bb.Min, inner_bb.Max, (plot_type == ImGuiPlotType_Lines) ? tp1 : ImVec2(tp1.x, 1.0f));
+            if (plot_type == ImGuiPlotType_Lines)
+            {
+                window->DrawList->AddLine(pos0, pos1, v_hovered == v1_idx ? col_hovered : col_base);
+            }
+            else if (plot_type == ImGuiPlotType_Histogram)
+            {
+                if (pos1.x >= pos0.x + 2.0f)
+                    pos1.x -= 1.0f;
+                window->DrawList->AddRectFilled(pos0, pos1, v_hovered == v1_idx ? col_hovered : col_base);
+            }
 
-        t0 = t1;
-        tp0 = tp1;
+            t0 = t1;
+            tp0 = tp1;
+        }
     }
 
     // Text overlay
@@ -7434,12 +7435,12 @@ static void    STB_TEXTEDIT_LAYOUTROW(StbTexteditRow* r, STB_TEXTEDIT_STRING* ob
 
 static bool is_separator(unsigned int c)                                        { return ImCharIsSpace(c) || c==',' || c==';' || c=='(' || c==')' || c=='{' || c=='}' || c=='[' || c==']' || c=='|'; }
 static int  is_word_boundary_from_right(STB_TEXTEDIT_STRING* obj, int idx)      { return idx > 0 ? (is_separator( obj->Text[idx-1] ) && !is_separator( obj->Text[idx] ) ) : 1; }
-static int  STB_TEXTEDIT_MOVEWORDLEFT_IMPL(STB_TEXTEDIT_STRING* obj, int idx)   { while (idx >= 0 && !is_word_boundary_from_right(obj, idx)) idx--; return idx < 0 ? 0 : idx; }
+static int  STB_TEXTEDIT_MOVEWORDLEFT_IMPL(STB_TEXTEDIT_STRING* obj, int idx)   { idx--; while (idx >= 0 && !is_word_boundary_from_right(obj, idx)) idx--; return idx < 0 ? 0 : idx; }
 #ifdef __APPLE__    // FIXME: Move setting to IO structure
 static int  is_word_boundary_from_left(STB_TEXTEDIT_STRING* obj, int idx)       { return idx > 0 ? (!is_separator( obj->Text[idx-1] ) && is_separator( obj->Text[idx] ) ) : 1; }
-static int  STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(STB_TEXTEDIT_STRING* obj, int idx)  { int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_left(obj, idx)) idx++; return idx > len ? len : idx; }
+static int  STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(STB_TEXTEDIT_STRING* obj, int idx)  { idx++; int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_left(obj, idx)) idx++; return idx > len ? len : idx; }
 #else
-static int  STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(STB_TEXTEDIT_STRING* obj, int idx)  { int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_right(obj, idx)) idx++; return idx > len ? len : idx; }
+static int  STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(STB_TEXTEDIT_STRING* obj, int idx)  { idx++; int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_right(obj, idx)) idx++; return idx > len ? len : idx; }
 #endif
 #define STB_TEXTEDIT_MOVEWORDLEFT   STB_TEXTEDIT_MOVEWORDLEFT_IMPL    // They need to be #define for stb_textedit.h
 #define STB_TEXTEDIT_MOVEWORDRIGHT  STB_TEXTEDIT_MOVEWORDRIGHT_IMPL
@@ -7865,7 +7866,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
                 const int ie = edit_state.HasSelection() ? ImMax(edit_state.StbState.select_start, edit_state.StbState.select_end) : edit_state.CurLenW;
                 edit_state.TempTextBuffer.resize((ie-ib) * 4 + 1);
                 ImTextStrToUtf8(edit_state.TempTextBuffer.Data, edit_state.TempTextBuffer.Size, edit_state.Text.Data+ib, edit_state.Text.Data+ie);
-                io.SetClipboardTextFn(edit_state.TempTextBuffer.Data);
+                SetClipboardText(edit_state.TempTextBuffer.Data);
             }
 
             if (cut)
@@ -7877,7 +7878,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
         else if (is_shortcut_key_only && IsKeyPressedMap(ImGuiKey_V) && is_editable)
         {
             // Paste
-            if (const char* clipboard = io.GetClipboardTextFn ? io.GetClipboardTextFn() : NULL)
+            if (const char* clipboard = GetClipboardText())
             {
                 // Filter pasted buffer
                 const int clipboard_len = (int)strlen(clipboard);
@@ -8253,7 +8254,7 @@ bool ImGui::InputFloat(const char* label, float* v, float step, float step_fast,
     if (decimal_precision < 0)
         strcpy(display_format, "%f");      // Ideally we'd have a minimum decimal precision of 1 to visually denote that this is a float, while hiding non-significant digits? %f doesn't have a minimum of 1
     else
-        ImFormatString(display_format, 16, "%%.%df", decimal_precision);
+        ImFormatString(display_format, IM_ARRAYSIZE(display_format), "%%.%df", decimal_precision);
     return InputScalarEx(label, ImGuiDataType_Float, (void*)v, (void*)(step>0.0f ? &step : NULL), (void*)(step_fast>0.0f ? &step_fast : NULL), display_format, extra_flags);
 }
 
@@ -9098,8 +9099,8 @@ void ImGui::Separator()
     if (!window->DC.GroupStack.empty())
         x1 += window->DC.IndentX;
 
-    const ImRect bb(ImVec2(x1, window->DC.CursorPos.y), ImVec2(x2, window->DC.CursorPos.y));
-    ItemSize(ImVec2(0.0f, 0.0f)); // NB: we don't provide our width so that it doesn't get feed back into AutoFit   // FIXME: Height should be 1.0f not 0.0f ?
+    const ImRect bb(ImVec2(x1, window->DC.CursorPos.y), ImVec2(x2, window->DC.CursorPos.y+1.0f));
+    ItemSize(ImVec2(0.0f, 0.0f)); // NB: we don't provide our width so that it doesn't get feed back into AutoFit, we don't provide height to not alter layout.
     if (!ItemAdd(bb, NULL))
     {
         if (window->DC.ColumnsCount > 1)
@@ -9107,7 +9108,7 @@ void ImGui::Separator()
         return;
     }
 
-    window->DrawList->AddLine(bb.Min, bb.Max, GetColorU32(ImGuiCol_Border));
+    window->DrawList->AddLine(bb.Min, ImVec2(bb.Max.x,bb.Min.y), GetColorU32(ImGuiCol_Border));
 
     ImGuiContext& g = *GImGui;
     if (g.LogEnabled)
@@ -9571,7 +9572,7 @@ void ImGui::ValueColor(const char* prefix, ImU32 v)
 #pragma comment(lib, "user32")
 #endif
 
-static const char* GetClipboardTextFn_DefaultImpl()
+static const char* GetClipboardTextFn_DefaultImpl(void*)
 {
     static ImVector<char> buf_local;
     buf_local.clear();
@@ -9591,7 +9592,7 @@ static const char* GetClipboardTextFn_DefaultImpl()
     return buf_local.Data;
 }
 
-static void SetClipboardTextFn_DefaultImpl(const char* text)
+static void SetClipboardTextFn_DefaultImpl(void*, const char* text)
 {
     if (!OpenClipboard(NULL))
         return;
@@ -9610,13 +9611,13 @@ static void SetClipboardTextFn_DefaultImpl(const char* text)
 #else
 
 // Local ImGui-only clipboard implementation, if user hasn't defined better clipboard handlers
-static const char* GetClipboardTextFn_DefaultImpl()
+static const char* GetClipboardTextFn_DefaultImpl(void*)
 {
     return GImGui->PrivateClipboard;
 }
 
 // Local ImGui-only clipboard implementation, if user hasn't defined better clipboard handlers
-static void SetClipboardTextFn_DefaultImpl(const char* text)
+static void SetClipboardTextFn_DefaultImpl(void*, const char* text)
 {
     ImGuiContext& g = *GImGui;
     if (g.PrivateClipboard)

+ 19 - 19
3rdparty/ocornut-imgui/imgui.h

@@ -665,6 +665,7 @@ enum ImGuiColorEditMode_
 // Enumeration for GetMouseCursor()
 enum ImGuiMouseCursor_
 {
+    ImGuiMouseCursor_None = -1,
     ImGuiMouseCursor_Arrow = 0,
     ImGuiMouseCursor_TextInput,         // When hovering over InputText, etc.
     ImGuiMouseCursor_Move,              // Unused
@@ -758,8 +759,9 @@ struct ImGuiIO
 
     // Optional: access OS clipboard
     // (default to use native Win32 clipboard on Windows, otherwise uses a private clipboard. Override to access OS clipboard on other architectures)
-    const char* (*GetClipboardTextFn)();
-    void        (*SetClipboardTextFn)(const char* text);
+    const char* (*GetClipboardTextFn)(void* user_data);
+    void        (*SetClipboardTextFn)(void* user_data, const char* text);
+    void*       ClipboardUserData;
 
     // Optional: override memory allocations. MemFreeFn() may be called with a NULL pointer.
     // (default to posix malloc/free)
@@ -805,7 +807,7 @@ struct ImGuiIO
     int         MetricsActiveWindows;       // Number of visible windows (exclude child windows)
 
     //------------------------------------------------------------------
-    // [Internal] ImGui will maintain those fields for you
+    // [Private] ImGui will maintain those fields. Forward compatibility not guaranteed!
     //------------------------------------------------------------------
 
     ImVec2      MousePosPrev;               // Previous mouse position
@@ -952,10 +954,9 @@ struct ImGuiTextBuffer
 };
 
 // Helper: Simple Key->value storage
-// - Store collapse state for a tree (Int 0/1)
-// - Store color edit options (Int using values in ImGuiColorEditMode enum).
-// - Custom user storage for temporary values.
 // Typically you don't have to worry about this since a storage is held within each Window.
+// We use it to e.g. store collapse state for a tree (Int 0/1), store color edit options.
+// You can use it as custom user storage for temporary values.
 // Declare your own storage if:
 // - You want to manipulate the open/close state of a particular sub-tree in your interface (tree node uses Int 0/1 to store their state).
 // - You want to store custom debug data easily without adding or editing structures in your code.
@@ -987,9 +988,8 @@ struct ImGuiStorage
 
     // - Get***Ref() functions finds pair, insert on demand if missing, return pointer. Useful if you intend to do Get+Set.
     // - References are only valid until a new value is added to the storage. Calling a Set***() function or a Get***Ref() function invalidates the pointer.
-    // - A typical use case where this is convenient:
+    // - A typical use case where this is convenient for quick hacking (e.g. add storage during a live Edit&Continue session if you can't modify existing struct)
     //      float* pvar = ImGui::GetFloatRef(key); ImGui::SliderFloat("var", pvar, 0, 100.0f); some_var += *pvar;
-    // - You can also use this to quickly create temporary editable values during a session of using Edit&Continue, without restarting your application.
     IMGUI_API int*      GetIntRef(ImGuiID key, int default_val = 0);
     IMGUI_API bool*     GetBoolRef(ImGuiID key, bool default_val = false);
     IMGUI_API float*    GetFloatRef(ImGuiID key, float default_val = 0.0f);
@@ -1043,11 +1043,13 @@ struct ImGuiSizeConstraintCallbackData
 #define IM_COL32_G_SHIFT    8
 #define IM_COL32_B_SHIFT    0
 #define IM_COL32_A_SHIFT    24
+#define IM_COL32_A_MASK     0xFF000000
 #else
 #define IM_COL32_R_SHIFT    0
 #define IM_COL32_G_SHIFT    8
 #define IM_COL32_B_SHIFT    16
 #define IM_COL32_A_SHIFT    24
+#define IM_COL32_A_MASK     0xFF000000
 #endif
 #define IM_COL32(R,G,B,A)    (((ImU32)(A)<<IM_COL32_A_SHIFT) | ((ImU32)(B)<<IM_COL32_B_SHIFT) | ((ImU32)(G)<<IM_COL32_G_SHIFT) | ((ImU32)(R)<<IM_COL32_R_SHIFT))
 #define IM_COL32_WHITE       IM_COL32(255,255,255,255)  // Opaque white
@@ -1056,8 +1058,8 @@ struct ImGuiSizeConstraintCallbackData
 
 // ImColor() helper to implicity converts colors to either ImU32 (packed 4x1 byte) or ImVec4 (4x1 float)
 // Prefer using IM_COL32() macros if you want a guaranteed compile-time ImU32 for usage with ImDrawList API.
-// Avoid storing ImColor! Store either u32 of ImVec4. This is not a full-featured color class.
-// None of the ImGui API are using ImColor directly but you can use it as a convenience to pass colors in either ImU32 or ImVec4 formats.
+// **Avoid storing ImColor! Store either u32 of ImVec4. This is not a full-featured color class.
+// **None of the ImGui API are using ImColor directly but you can use it as a convenience to pass colors in either ImU32 or ImVec4 formats.
 struct ImColor
 {
     ImVec4              Value;
@@ -1171,7 +1173,7 @@ struct ImDrawList
     ImVector<ImDrawVert>    VtxBuffer;          // Vertex buffer.
 
     // [Internal, used while building lists]
-    const char*             _OwnerName;         // Pointer to owner window's name (if any) for debugging
+    const char*             _OwnerName;         // Pointer to owner window's name for debugging
     unsigned int            _VtxCurrentIdx;     // [Internal] == VtxBuffer.Size
     ImDrawVert*             _VtxWritePtr;       // [Internal] point within VtxBuffer.Data after each add command (to avoid using the ImVector<> operators too much)
     ImDrawIdx*              _IdxWritePtr;       // [Internal] point within IdxBuffer.Data after each add command (to avoid using the ImVector<> operators too much)
@@ -1182,7 +1184,7 @@ struct ImDrawList
     int                     _ChannelsCount;     // [Internal] number of active channels (1+)
     ImVector<ImDrawChannel> _Channels;          // [Internal] draw channels for columns API (not resized down so _ChannelsCount may be smaller than _Channels.Size)
 
-    ImDrawList() { _OwnerName = NULL; Clear(); }
+    ImDrawList()  { _OwnerName = NULL; Clear(); }
     ~ImDrawList() { ClearFreeMemory(); }
     IMGUI_API void  PushClipRect(ImVec2 clip_rect_min, ImVec2 clip_rect_max, bool intersect_with_current_clip_rect = false);  // Render-level scissoring. This is passed down to your render function but not used for CPU-side coarse clipping. Prefer using higher-level ImGui::PushClipRect() to affect logic (hit-testing and widget culling)
     IMGUI_API void  PushClipRectFullScreen();
@@ -1192,8 +1194,8 @@ struct ImDrawList
 
     // Primitives
     IMGUI_API void  AddLine(const ImVec2& a, const ImVec2& b, ImU32 col, float thickness = 1.0f);
-    IMGUI_API void  AddRect(const ImVec2& a, const ImVec2& b, ImU32 col, float rounding = 0.0f, int rounding_corners = 0x0F, float thickness = 1.0f);   // a: upper-left, b: lower-right
-    IMGUI_API void  AddRectFilled(const ImVec2& a, const ImVec2& b, ImU32 col, float rounding = 0.0f, int rounding_corners = 0x0F);                     // a: upper-left, b: lower-right
+    IMGUI_API void  AddRect(const ImVec2& a, const ImVec2& b, ImU32 col, float rounding = 0.0f, int rounding_corners_flags = ~0, float thickness = 1.0f);   // a: upper-left, b: lower-right, rounding_corners_flags: 4-bits corresponding to which corner to round
+    IMGUI_API void  AddRectFilled(const ImVec2& a, const ImVec2& b, ImU32 col, float rounding = 0.0f, int rounding_corners_flags = ~0);                     // a: upper-left, b: lower-right
     IMGUI_API void  AddRectFilledMultiColor(const ImVec2& a, const ImVec2& b, ImU32 col_upr_left, ImU32 col_upr_right, ImU32 col_bot_right, ImU32 col_bot_left);
     IMGUI_API void  AddQuad(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, ImU32 col, float thickness = 1.0f);
     IMGUI_API void  AddQuadFilled(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, ImU32 col);
@@ -1215,9 +1217,9 @@ struct ImDrawList
     inline    void  PathFill(ImU32 col)                                         { AddConvexPolyFilled(_Path.Data, _Path.Size, col, true); PathClear(); }
     inline    void  PathStroke(ImU32 col, bool closed, float thickness = 1.0f)  { AddPolyline(_Path.Data, _Path.Size, col, closed, thickness, true); PathClear(); }
     IMGUI_API void  PathArcTo(const ImVec2& centre, float radius, float a_min, float a_max, int num_segments = 10);
-    IMGUI_API void  PathArcToFast(const ImVec2& centre, float radius, int a_min_of_12, int a_max_of_12);                 // Use precomputed angles for a 12 steps circle
+    IMGUI_API void  PathArcToFast(const ImVec2& centre, float radius, int a_min_of_12, int a_max_of_12);                                // Use precomputed angles for a 12 steps circle
     IMGUI_API void  PathBezierCurveTo(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, int num_segments = 0);
-    IMGUI_API void  PathRect(const ImVec2& rect_min, const ImVec2& rect_max, float rounding = 0.0f, int rounding_corners = 0x0F);
+    IMGUI_API void  PathRect(const ImVec2& rect_min, const ImVec2& rect_max, float rounding = 0.0f, int rounding_corners_flags = ~0);   // rounding_corners_flags: 4-bits corresponding to which corner to round
 
     // Channels
     // - Use to simulate layers. By switching channels to can render out-of-order (e.g. submit foreground primitives before background primitives)
@@ -1395,9 +1397,7 @@ struct ImFont
 #pragma clang diagnostic pop
 #endif
 
-//---- Include imgui_user.h at the end of imgui.h
-//---- So you can include code that extends ImGui using any of the types declared above.
-//---- (also convenient for user to only explicitly include vanilla imgui.h)
+// Include imgui_user.h at the end of imgui.h (convenient for user to only explicitly include vanilla imgui.h)
 #ifdef IMGUI_INCLUDE_IMGUI_USER_H
 #include "imgui_user.h"
 #endif

+ 12 - 10
3rdparty/ocornut-imgui/imgui_demo.cpp

@@ -30,7 +30,9 @@
 #pragma clang diagnostic ignored "-Wint-to-void-pointer-cast"   // warning : cast to 'void *' from smaller integer type 'int'
 #pragma clang diagnostic ignored "-Wformat-security"            // warning : warning: format string is not a string literal
 #pragma clang diagnostic ignored "-Wexit-time-destructors"      // warning : declaration requires an exit-time destructor       // exit-time destruction order is undefined. if MemFree() leads to users code that has been disabled before exit it might cause problems. ImGui coding style welcomes static/globals.
-#pragma clang diagnostic ignored "-Wreserved-id-macro"          // warning : macro name is a reserved identifier                // 
+#if __has_warning("-Wreserved-id-macro")
+#pragma clang diagnostic ignored "-Wreserved-id-macro"          // warning : macro name is a reserved identifier                //
+#endif
 #elif defined(__GNUC__)
 #pragma GCC diagnostic ignored "-Wint-to-pointer-cast"          // warning: cast to pointer from integer of different size
 #pragma GCC diagnostic ignored "-Wformat-security"              // warning : format string is not a string literal (potentially insecure)
@@ -1421,9 +1423,9 @@ void ImGui::ShowTestWindow(bool* p_open)
             ImGui::InputFloat("blue", &bar, 0.05f, 0, 3);
             ImGui::NextColumn();
 
-            if (ImGui::CollapsingHeader("Category A")) ImGui::Text("Blah blah blah"); ImGui::NextColumn();
-            if (ImGui::CollapsingHeader("Category B")) ImGui::Text("Blah blah blah"); ImGui::NextColumn();
-            if (ImGui::CollapsingHeader("Category C")) ImGui::Text("Blah blah blah"); ImGui::NextColumn();
+            if (ImGui::CollapsingHeader("Category A")) { ImGui::Text("Blah blah blah"); } ImGui::NextColumn();
+            if (ImGui::CollapsingHeader("Category B")) { ImGui::Text("Blah blah blah"); } ImGui::NextColumn();
+            if (ImGui::CollapsingHeader("Category C")) { ImGui::Text("Blah blah blah"); } ImGui::NextColumn();
             ImGui::Columns(1);
             ImGui::Separator();
             ImGui::TreePop();
@@ -1540,7 +1542,7 @@ void ImGui::ShowTestWindow(bool* p_open)
 
         if (ImGui::TreeNode("Dragging"))
         {
-            ImGui::TextWrapped("You can use ImGui::GetItemActiveDragDelta() to query for the dragged amount on any widget.");
+            ImGui::TextWrapped("You can use ImGui::GetMouseDragDelta(0) to query for the dragged amount on any widget.");
             ImGui::Button("Drag Me");
             if (ImGui::IsItemActive())
             {
@@ -1924,8 +1926,8 @@ static void ShowExampleAppConstrainedResize(bool* p_open)
             "Custom: Fixed Steps (100)",
         };
         ImGui::Combo("Constraint", &type, desc, IM_ARRAYSIZE(desc)); 
-        if (ImGui::Button("200x200")) ImGui::SetWindowSize(ImVec2(200,200)); ImGui::SameLine();
-        if (ImGui::Button("500x500")) ImGui::SetWindowSize(ImVec2(500,500)); ImGui::SameLine();
+        if (ImGui::Button("200x200")) { ImGui::SetWindowSize(ImVec2(200,200)); } ImGui::SameLine();
+        if (ImGui::Button("500x500")) { ImGui::SetWindowSize(ImVec2(500,500)); } ImGui::SameLine();
         if (ImGui::Button("800x200")) ImGui::SetWindowSize(ImVec2(800,200));
         for (int i = 0; i < 10; i++) 
             ImGui::Text("Hello, sailor! Making this line long enough for the example.");
@@ -2139,8 +2141,8 @@ struct ExampleAppConsole
         // TODO: display items starting from the bottom
 
         if (ImGui::SmallButton("Add Dummy Text")) { AddLog("%d some text", Items.Size); AddLog("some more text"); AddLog("display very important message here!"); } ImGui::SameLine();
-        if (ImGui::SmallButton("Add Dummy Error")) AddLog("[error] something went wrong"); ImGui::SameLine();
-        if (ImGui::SmallButton("Clear")) ClearLog(); ImGui::SameLine();
+        if (ImGui::SmallButton("Add Dummy Error")) { AddLog("[error] something went wrong"); } ImGui::SameLine();
+        if (ImGui::SmallButton("Clear")) { ClearLog(); } ImGui::SameLine();
         if (ImGui::SmallButton("Scroll to bottom")) ScrollToBottom = true;
         //static float t = 0.0f; if (ImGui::GetTime() - t > 0.02f) { t = ImGui::GetTime(); AddLog("Spam %f", t); }
 
@@ -2194,7 +2196,7 @@ struct ExampleAppConsole
         if (ImGui::InputText("Input", InputBuf, IM_ARRAYSIZE(InputBuf), ImGuiInputTextFlags_EnterReturnsTrue|ImGuiInputTextFlags_CallbackCompletion|ImGuiInputTextFlags_CallbackHistory, &TextEditCallbackStub, (void*)this))
         {
             char* input_end = InputBuf+strlen(InputBuf);
-            while (input_end > InputBuf && input_end[-1] == ' ') input_end--; *input_end = 0;
+            while (input_end > InputBuf && input_end[-1] == ' ') { input_end--; } *input_end = 0;
             if (InputBuf[0])
                 ExecCommand(InputBuf);
             strcpy(InputBuf, "");

+ 20 - 18
3rdparty/ocornut-imgui/imgui_draw.cpp

@@ -39,7 +39,9 @@
 #pragma clang diagnostic ignored "-Wfloat-equal"            // warning : comparing floating point with == or != is unsafe   // storing and comparing against same constants ok.
 #pragma clang diagnostic ignored "-Wglobal-constructors"    // warning : declaration requires a global destructor           // similar to above, not sure what the exact difference it.
 #pragma clang diagnostic ignored "-Wsign-conversion"        // warning : implicit conversion changes signedness             //
+#if __has_warning("-Wreserved-id-macro")
 #pragma clang diagnostic ignored "-Wreserved-id-macro"      // warning : macro name is a reserved identifier                //
+#endif
 #elif defined(__GNUC__)
 #pragma GCC diagnostic ignored "-Wunused-function"          // warning: 'xxxx' defined but not used
 #pragma GCC diagnostic ignored "-Wdouble-promotion"         // warning: implicit conversion from 'float' to 'double' when passing argument to function
@@ -799,7 +801,7 @@ void ImDrawList::PathRect(const ImVec2& a, const ImVec2& b, float rounding, int
 
 void ImDrawList::AddLine(const ImVec2& a, const ImVec2& b, ImU32 col, float thickness)
 {
-    if ((col >> 24) == 0)
+    if ((col & IM_COL32_A_MASK) == 0)
         return;
     PathLineTo(a + ImVec2(0.5f,0.5f));
     PathLineTo(b + ImVec2(0.5f,0.5f));
@@ -807,21 +809,21 @@ void ImDrawList::AddLine(const ImVec2& a, const ImVec2& b, ImU32 col, float thic
 }
 
 // a: upper-left, b: lower-right. we don't render 1 px sized rectangles properly.
-void ImDrawList::AddRect(const ImVec2& a, const ImVec2& b, ImU32 col, float rounding, int rounding_corners, float thickness)
+void ImDrawList::AddRect(const ImVec2& a, const ImVec2& b, ImU32 col, float rounding, int rounding_corners_flags, float thickness)
 {
-    if ((col >> 24) == 0)
+    if ((col & IM_COL32_A_MASK) == 0)
         return;
-    PathRect(a + ImVec2(0.5f,0.5f), b - ImVec2(0.5f,0.5f), rounding, rounding_corners);
+    PathRect(a + ImVec2(0.5f,0.5f), b - ImVec2(0.5f,0.5f), rounding, rounding_corners_flags);
     PathStroke(col, true, thickness);
 }
 
-void ImDrawList::AddRectFilled(const ImVec2& a, const ImVec2& b, ImU32 col, float rounding, int rounding_corners)
+void ImDrawList::AddRectFilled(const ImVec2& a, const ImVec2& b, ImU32 col, float rounding, int rounding_corners_flags)
 {
-    if ((col >> 24) == 0)
+    if ((col & IM_COL32_A_MASK) == 0)
         return;
     if (rounding > 0.0f)
     {
-        PathRect(a, b, rounding, rounding_corners);
+        PathRect(a, b, rounding, rounding_corners_flags);
         PathFill(col);
     }
     else
@@ -833,7 +835,7 @@ void ImDrawList::AddRectFilled(const ImVec2& a, const ImVec2& b, ImU32 col, floa
 
 void ImDrawList::AddRectFilledMultiColor(const ImVec2& a, const ImVec2& c, ImU32 col_upr_left, ImU32 col_upr_right, ImU32 col_bot_right, ImU32 col_bot_left)
 {
-    if (((col_upr_left | col_upr_right | col_bot_right | col_bot_left) >> 24) == 0)
+    if (((col_upr_left | col_upr_right | col_bot_right | col_bot_left) & IM_COL32_A_MASK) == 0)
         return;
 
     const ImVec2 uv = GImGui->FontTexUvWhitePixel;
@@ -848,7 +850,7 @@ void ImDrawList::AddRectFilledMultiColor(const ImVec2& a, const ImVec2& c, ImU32
 
 void ImDrawList::AddQuad(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, ImU32 col, float thickness)
 {
-    if ((col >> 24) == 0)
+    if ((col & IM_COL32_A_MASK) == 0)
         return;
 
     PathLineTo(a);
@@ -860,7 +862,7 @@ void ImDrawList::AddQuad(const ImVec2& a, const ImVec2& b, const ImVec2& c, cons
 
 void ImDrawList::AddQuadFilled(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, ImU32 col)
 {
-    if ((col >> 24) == 0)
+    if ((col & IM_COL32_A_MASK) == 0)
         return;
 
     PathLineTo(a);
@@ -872,7 +874,7 @@ void ImDrawList::AddQuadFilled(const ImVec2& a, const ImVec2& b, const ImVec2& c
 
 void ImDrawList::AddTriangle(const ImVec2& a, const ImVec2& b, const ImVec2& c, ImU32 col, float thickness)
 {
-    if ((col >> 24) == 0)
+    if ((col & IM_COL32_A_MASK) == 0)
         return;
 
     PathLineTo(a);
@@ -883,7 +885,7 @@ void ImDrawList::AddTriangle(const ImVec2& a, const ImVec2& b, const ImVec2& c,
 
 void ImDrawList::AddTriangleFilled(const ImVec2& a, const ImVec2& b, const ImVec2& c, ImU32 col)
 {
-    if ((col >> 24) == 0)
+    if ((col & IM_COL32_A_MASK) == 0)
         return;
 
     PathLineTo(a);
@@ -894,7 +896,7 @@ void ImDrawList::AddTriangleFilled(const ImVec2& a, const ImVec2& b, const ImVec
 
 void ImDrawList::AddCircle(const ImVec2& centre, float radius, ImU32 col, int num_segments, float thickness)
 {
-    if ((col >> 24) == 0)
+    if ((col & IM_COL32_A_MASK) == 0)
         return;
 
     const float a_max = IM_PI*2.0f * ((float)num_segments - 1.0f) / (float)num_segments;
@@ -904,7 +906,7 @@ void ImDrawList::AddCircle(const ImVec2& centre, float radius, ImU32 col, int nu
 
 void ImDrawList::AddCircleFilled(const ImVec2& centre, float radius, ImU32 col, int num_segments)
 {
-    if ((col >> 24) == 0)
+    if ((col & IM_COL32_A_MASK) == 0)
         return;
 
     const float a_max = IM_PI*2.0f * ((float)num_segments - 1.0f) / (float)num_segments;
@@ -914,7 +916,7 @@ void ImDrawList::AddCircleFilled(const ImVec2& centre, float radius, ImU32 col,
 
 void ImDrawList::AddBezierCurve(const ImVec2& pos0, const ImVec2& cp0, const ImVec2& cp1, const ImVec2& pos1, ImU32 col, float thickness, int num_segments)
 {
-    if ((col >> 24) == 0)
+    if ((col & IM_COL32_A_MASK) == 0)
         return;
 
     PathLineTo(pos0);
@@ -924,7 +926,7 @@ void ImDrawList::AddBezierCurve(const ImVec2& pos0, const ImVec2& cp0, const ImV
 
 void ImDrawList::AddText(const ImFont* font, float font_size, const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end, float wrap_width, const ImVec4* cpu_fine_clip_rect)
 {
-    if ((col >> 24) == 0)
+    if ((col & IM_COL32_A_MASK) == 0)
         return;
 
     if (text_end == NULL)
@@ -959,7 +961,7 @@ void ImDrawList::AddText(const ImVec2& pos, ImU32 col, const char* text_begin, c
 
 void ImDrawList::AddImage(ImTextureID user_texture_id, const ImVec2& a, const ImVec2& b, const ImVec2& uv0, const ImVec2& uv1, ImU32 col)
 {
-    if ((col >> 24) == 0)
+    if ((col & IM_COL32_A_MASK) == 0)
         return;
 
     // FIXME-OPT: This is wasting draw calls.
@@ -1169,7 +1171,7 @@ static void         Decode85(const unsigned char* src, unsigned char* dst)
     while (*src)
     {
         unsigned int tmp = Decode85Byte(src[0]) + 85*(Decode85Byte(src[1]) + 85*(Decode85Byte(src[2]) + 85*(Decode85Byte(src[3]) + 85*Decode85Byte(src[4]))));
-        dst[0] = ((tmp >> 0) & 0xFF); dst[1] = ((tmp >> 8) & 0xFF); dst[2] = ((tmp >> 16) & 0xFF); dst[3] = ((tmp >> 24) & 0xFF);   // We can't assume little-endianess.
+        dst[0] = ((tmp >> 0) & 0xFF); dst[1] = ((tmp >> 8) & 0xFF); dst[2] = ((tmp >> 16) & 0xFF); dst[3] = ((tmp >> 24) & 0xFF);   // We can't assume little-endianness.
         src += 5;
         dst += 4;
     }

+ 10 - 1
3rdparty/ocornut-imgui/imgui_internal.h

@@ -197,6 +197,15 @@ enum ImGuiDataType
     ImGuiDataType_Float2,
 };
 
+enum ImGuiCorner
+{
+    ImGuiCorner_TopLeft     = 1 << 0, // 1
+    ImGuiCorner_TopRight    = 1 << 1, // 2
+    ImGuiCorner_BottomRight = 1 << 2, // 4
+    ImGuiCorner_BottomLeft  = 1 << 3, // 8
+    ImGuiCorner_All         = 0x0F
+};
+
 // 2D axis aligned bounding-box
 // NB: we can't rely on ImVec2 math operators being available here
 struct IMGUI_API ImRect
@@ -717,7 +726,7 @@ namespace ImGui
     IMGUI_API void          RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end, float wrap_width);
     IMGUI_API void          RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& align = ImVec2(0,0), const ImRect* clip_rect = NULL);
     IMGUI_API void          RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border = true, float rounding = 0.0f);
-    IMGUI_API void          RenderCollapseTriangle(ImVec2 pos, bool is_open, float scale = 1.0f, bool shadow = false);
+    IMGUI_API void          RenderCollapseTriangle(ImVec2 pos, bool is_open, float scale = 1.0f);
     IMGUI_API void          RenderBullet(ImVec2 pos);
     IMGUI_API void          RenderCheckMark(ImVec2 pos, ImU32 col);
     IMGUI_API const char*   FindRenderedTextEnd(const char* text, const char* text_end = NULL); // Find the optional ## from which we stop displaying text.

+ 1 - 0
3rdparty/ocornut-imgui/imgui_user.h

@@ -45,3 +45,4 @@ namespace ImGui
 #include "widgets/file_list.h"
 #include "widgets/memory_editor.h"
 #include "widgets/gizmo.h"
+#include "widgets/dock.h"

+ 1 - 0
3rdparty/ocornut-imgui/imgui_user.inl

@@ -75,3 +75,4 @@ namespace ImGui
 #include "widgets/file_list.inl"
 #include "widgets/memory_editor.inl"
 #include "widgets/gizmo.inl"
+#include "widgets/dock.inl"

+ 0 - 1688
3rdparty/ocornut-imgui/imgui_wm.cpp

@@ -1,1688 +0,0 @@
-/*
- * Copyright 2011-2016 Branimir Karadzic. All rights reserved.
- * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
- */
-
-/*
- * Based on ImWindow code from:
- * https://github.com/thennequin/ImWindow
- *
- * MIT license:
- * https://github.com/thennequin/ImWindow/blob/master/LICENSE
- */
-
-#include "imgui_wm.h"
-#include "imgui_internal.h"
-#include <algorithm>
-
-#define IMGUI_NEW(type)              new (ImGui::MemAlloc(sizeof(type) ) ) type
-#define IMGUI_DELETE(type, obj)      static_cast<type*>(obj)->~type(), ImGui::MemFree(obj)
-#define IMGUI_DELETE_NULL(type, obj) for (;;) { if (NULL != obj) { IMGUI_DELETE(type, obj); obj = NULL; } break; }
-
-namespace ImGuiWM
-{
-    enum EPlatformWindowAction
-    {
-        E_PLATFORM_WINDOW_ACTION_DESTOY       =  1,
-        E_PLATFORM_WINDOW_ACTION_SHOW         =  2,
-        E_PLATFORM_WINDOW_ACTION_HIDE         =  4,
-        E_PLATFORM_WINDOW_ACTION_SET_POSITION =  8,
-        E_PLATFORM_WINDOW_ACTION_SET_SIZE     = 16,
-    };
-
-    static const ImVec2 IM_VEC2_0  = ImVec2(0, 0);
-    static const ImVec2 IM_VEC2_N1 = ImVec2(-1, -1);
-
-    int Id::s_iNextId = 0;
-
-    Id::Id()
-    {
-        m_iId = s_iNextId++;
-        ImFormatString(m_pId, 11, "0x%8X", m_iId);
-    }
-
-    ImU32 Id::GetId() const
-    {
-        return m_iId;
-    }
-
-    const char* Id::GetStr() const
-    {
-        return m_pId;
-    }
-
-    Window::Window()
-    {
-        m_pTitle = NULL;
-        WindowManager::GetInstance()->AddWindow(this);
-    }
-
-    Window::~Window()
-    {
-        WindowManager::GetInstance()->RemoveWindow(this);
-        ImGui::MemFree(m_pTitle);
-    }
-
-    void Window::Destroy()
-    {
-        WindowManager::GetInstance()->DestroyWindow(this);
-    }
-
-    void Window::SetTitle(const char* pTitle)
-    {
-        ImGui::MemFree(m_pTitle);
-        m_pTitle = ImStrdup(pTitle);
-    }
-
-    const char* Window::GetTitle() const
-    {
-        return m_pTitle;
-    }
-
-    const ImVec2& Window::GetLastPosition() const
-    {
-        return m_oLastPosition;
-    }
-
-    const ImVec2& Window::GetLastSize() const
-    {
-        return m_oLastSize;
-    }
-
-    Container::Container(Container* pParent)
-    {
-        IM_ASSERT(NULL != pParent);
-        m_pSplits[0] = NULL;
-        m_pSplits[1] = NULL;
-        m_bVerticalSplit = false;
-        m_iActiveWindow = 0;
-        m_fSplitRatio = 0.5f;
-        m_bIsDrag = false;
-        m_pParent = pParent;
-        m_pParentWindow = (NULL != pParent) ? pParent->m_pParentWindow : NULL;
-    }
-
-    Container::Container(PlatformWindow* pParent)
-    {
-        IM_ASSERT(NULL != pParent);
-        m_pSplits[0] = NULL;
-        m_pSplits[1] = NULL;
-        m_bVerticalSplit = false;
-        m_iActiveWindow = 0;
-        m_fSplitRatio = 0.5f;
-        m_bIsDrag = false;
-        m_pParent = NULL;
-        m_pParentWindow = pParent;
-    }
-
-    Container::~Container()
-    {
-        while (m_lWindows.begin() != m_lWindows.end())
-        {
-            Window* window = *m_lWindows.begin();
-            WindowManager::GetInstance()->RemoveWindow(window);
-            IMGUI_DELETE(Window, window);
-            m_lWindows.erase(m_lWindows.begin());
-        }
-
-        IMGUI_DELETE_NULL(Container, m_pSplits[0]);
-        IMGUI_DELETE_NULL(Container, m_pSplits[1]);
-    }
-
-    void Container::CreateSplits()
-    {
-        m_pSplits[0] = IMGUI_NEW(Container)(this);
-        m_pSplits[1] = IMGUI_NEW(Container)(this);
-    }
-
-    void Container::Dock(Window* pWindow, EDockOrientation eOrientation)
-    {
-        IM_ASSERT(NULL != pWindow);
-
-        if (NULL != pWindow)
-        {
-            IM_ASSERT(eOrientation != E_DOCK_ORIENTATION_CENTER || !IsSplit());
-
-            if (!IsSplit())
-            {
-                if (m_lWindows.size() == 0)
-                {
-                    eOrientation = E_DOCK_ORIENTATION_CENTER;
-                }
-
-                switch (eOrientation)
-                {
-                case E_DOCK_ORIENTATION_CENTER:
-                {
-                    m_lWindows.push_back(pWindow);
-                    m_iActiveWindow = int(m_lWindows.size() - 1);
-                }
-                break;
-                case E_DOCK_ORIENTATION_TOP:
-                {
-                    m_bVerticalSplit = true;
-                    CreateSplits();
-                    m_pSplits[0]->Dock(pWindow);
-                    m_pSplits[1]->m_lWindows.insert(m_pSplits[1]->m_lWindows.begin(), m_lWindows.begin(), m_lWindows.end());
-                    m_lWindows.clear();
-                    m_iActiveWindow = 0;
-                }
-                break;
-                case E_DOCK_ORIENTATION_LEFT:
-                {
-                    m_bVerticalSplit = false;
-                    CreateSplits();
-                    m_pSplits[0]->Dock(pWindow);
-                    m_pSplits[1]->m_lWindows.insert(m_pSplits[1]->m_lWindows.begin(), m_lWindows.begin(), m_lWindows.end());
-                    m_lWindows.clear();
-                    m_iActiveWindow = 0;
-                }
-                break;
-                case E_DOCK_ORIENTATION_RIGHT:
-                {
-                    m_bVerticalSplit = false;
-                    CreateSplits();
-                    m_pSplits[0]->m_lWindows.insert(m_pSplits[0]->m_lWindows.begin(), m_lWindows.begin(), m_lWindows.end());
-                    m_pSplits[1]->Dock(pWindow);
-                    m_lWindows.clear();
-                    m_iActiveWindow = 0;
-                }
-                break;
-                case E_DOCK_ORIENTATION_BOTTOM:
-                {
-                    m_bVerticalSplit = true;
-                    CreateSplits();
-                    m_pSplits[0]->m_lWindows.insert(m_pSplits[0]->m_lWindows.begin(), m_lWindows.begin(), m_lWindows.end());
-                    m_pSplits[1]->Dock(pWindow);
-                    m_lWindows.clear();
-                    m_iActiveWindow = 0;
-                }
-                break;
-                }
-            }
-            else
-            {
-                switch (eOrientation)
-                {
-                case E_DOCK_ORIENTATION_CENTER:
-                    IM_ASSERT(false);
-                    break;
-                case E_DOCK_ORIENTATION_TOP:
-                {
-                    Container* pSplit0 = m_pSplits[0];
-                    Container* pSplit1 = m_pSplits[1];
-                    CreateSplits();
-                    m_pSplits[0]->m_lWindows.push_back(pWindow);
-                    m_pSplits[1]->m_bVerticalSplit = m_bVerticalSplit;
-                    m_pSplits[1]->m_fSplitRatio = m_fSplitRatio;
-                    m_pSplits[1]->m_pSplits[0] = pSplit0;
-                    m_pSplits[1]->m_pSplits[1] = pSplit1;
-                    m_pSplits[1]->m_pSplits[0]->m_pParent = m_pSplits[1];
-                    m_pSplits[1]->m_pSplits[1]->m_pParent = m_pSplits[1];
-                    m_fSplitRatio = WindowManager::GetInstance()->GetConfig().m_fDragMarginSizeRatio;
-                    m_bVerticalSplit = true;
-                }
-                break;
-                case E_DOCK_ORIENTATION_LEFT:
-                {
-                    Container* pSplit0 = m_pSplits[0];
-                    Container* pSplit1 = m_pSplits[1];
-                    CreateSplits();
-                    m_pSplits[0]->m_lWindows.push_back(pWindow);
-                    m_pSplits[1]->m_bVerticalSplit = m_bVerticalSplit;
-                    m_pSplits[1]->m_fSplitRatio = m_fSplitRatio;
-                    m_pSplits[1]->m_pSplits[0] = pSplit0;
-                    m_pSplits[1]->m_pSplits[1] = pSplit1;
-                    m_pSplits[1]->m_pSplits[0]->m_pParent = m_pSplits[1];
-                    m_pSplits[1]->m_pSplits[1]->m_pParent = m_pSplits[1];
-                    m_fSplitRatio = WindowManager::GetInstance()->GetConfig().m_fDragMarginSizeRatio;
-                    m_bVerticalSplit = false;
-                }
-                break;
-                case E_DOCK_ORIENTATION_RIGHT:
-                {
-                    Container* pSplit0 = m_pSplits[0];
-                    Container* pSplit1 = m_pSplits[1];
-                    CreateSplits();
-                    m_pSplits[1]->m_lWindows.push_back(pWindow);
-                    m_pSplits[0]->m_bVerticalSplit = m_bVerticalSplit;
-                    m_pSplits[0]->m_fSplitRatio = m_fSplitRatio;
-                    m_pSplits[0]->m_pSplits[0] = pSplit0;
-                    m_pSplits[0]->m_pSplits[1] = pSplit1;
-                    m_pSplits[0]->m_pSplits[0]->m_pParent = m_pSplits[0];
-                    m_pSplits[0]->m_pSplits[1]->m_pParent = m_pSplits[0];
-                    m_fSplitRatio = 1.f - WindowManager::GetInstance()->GetConfig().m_fDragMarginSizeRatio;
-                    m_bVerticalSplit = false;
-                }
-                break;
-                case E_DOCK_ORIENTATION_BOTTOM:
-                {
-                    Container* pSplit0 = m_pSplits[0];
-                    Container* pSplit1 = m_pSplits[1];
-                    CreateSplits();
-                    m_pSplits[1]->m_lWindows.push_back(pWindow);
-                    m_pSplits[0]->m_bVerticalSplit = m_bVerticalSplit;
-                    m_pSplits[0]->m_fSplitRatio = m_fSplitRatio;
-                    m_pSplits[0]->m_pSplits[0] = pSplit0;
-                    m_pSplits[0]->m_pSplits[1] = pSplit1;
-                    m_pSplits[0]->m_pSplits[0]->m_pParent = m_pSplits[0];
-                    m_pSplits[0]->m_pSplits[1]->m_pParent = m_pSplits[0];
-                    m_fSplitRatio = 1.f - WindowManager::GetInstance()->GetConfig().m_fDragMarginSizeRatio;
-                    m_bVerticalSplit = true;
-                }
-                break;
-                }
-            }
-        }
-    }
-
-    bool Container::UnDock(Window* pWindow)
-    {
-        if (std::find(m_lWindows.begin(), m_lWindows.end(), pWindow) != m_lWindows.end())
-        {
-            m_lWindows.remove(pWindow);
-            if (m_iActiveWindow >= int(m_lWindows.size()))
-            {
-                m_iActiveWindow = int(m_lWindows.size() - 1);
-            }
-            return true;
-        }
-
-        if (NULL != m_pSplits[0] && NULL != m_pSplits[1])
-        {
-            if (m_pSplits[0]->UnDock(pWindow))
-            {
-                if (m_pSplits[0]->IsEmpty())
-                {
-                    if (m_pSplits[1]->IsSplit())
-                    {
-                        Container* pSplit = m_pSplits[1];
-                        m_bVerticalSplit = pSplit->m_bVerticalSplit;
-                        IMGUI_DELETE_NULL(Container, m_pSplits[0]);
-                        m_pSplits[0] = pSplit->m_pSplits[0];
-                        m_pSplits[1] = pSplit->m_pSplits[1];
-                        pSplit->m_pSplits[0] = NULL;
-                        pSplit->m_pSplits[1] = NULL;
-                        m_pSplits[0]->m_pParent = this;
-                        m_pSplits[1]->m_pParent = this;
-                        IMGUI_DELETE_NULL(Container, pSplit);
-                    }
-                    else
-                    {
-                        m_lWindows.insert(m_lWindows.end(), m_pSplits[1]->m_lWindows.begin(), m_pSplits[1]->m_lWindows.end());
-                        m_pSplits[1]->m_lWindows.clear();
-                        m_pSplits[1]->m_iActiveWindow = 0;
-                        IMGUI_DELETE_NULL(Container, m_pSplits[0]);
-                        IMGUI_DELETE_NULL(Container, m_pSplits[1]);
-                    }
-                }
-                return true;
-            }
-
-            if (m_pSplits[1]->UnDock(pWindow))
-            {
-                if (m_pSplits[1]->IsEmpty())
-                {
-                    if (m_pSplits[0]->IsSplit())
-                    {
-                        Container* pSplit = m_pSplits[0];
-                        m_bVerticalSplit = pSplit->m_bVerticalSplit;
-                        IMGUI_DELETE_NULL(Container, m_pSplits[1]);
-                        m_pSplits[0] = pSplit->m_pSplits[0];
-                        m_pSplits[1] = pSplit->m_pSplits[1];
-                        pSplit->m_pSplits[0] = NULL;
-                        pSplit->m_pSplits[1] = NULL;
-                        m_pSplits[0]->m_pParent = this;
-                        m_pSplits[1]->m_pParent = this;
-                        IMGUI_DELETE_NULL(Container, pSplit);
-                    }
-                    else
-                    {
-                        m_lWindows.insert(m_lWindows.end(), m_pSplits[0]->m_lWindows.begin(), m_pSplits[0]->m_lWindows.end());
-                        m_pSplits[0]->m_lWindows.clear();
-                        m_pSplits[0]->m_iActiveWindow = 0;
-                        IMGUI_DELETE_NULL(Container, m_pSplits[0]);
-                        IMGUI_DELETE_NULL(Container, m_pSplits[1]);
-                    }
-                }
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-    bool Container::IsEmpty()
-    {
-        //IM_ASSERT(IsSplit() != HasWindowTabbed());
-        return !(IsSplit() || HasWindowTabbed());
-    }
-
-    bool Container::IsSplit()
-    {
-        IM_ASSERT((NULL == m_pSplits[0]) == (NULL == m_pSplits[1]));
-        return (NULL != m_pSplits[0] && NULL != m_pSplits[1]);
-    }
-
-    bool Container::HasWindowTabbed()
-    {
-        return m_lWindows.size() > 0;
-    }
-
-    Container* Container::HasWindow(const Window* pWindow)
-    {
-        if (std::find(m_lWindows.begin(), m_lWindows.end(), pWindow) != m_lWindows.end())
-        {
-            return this;
-        }
-        else
-        {
-            if (NULL != m_pSplits[0])
-            {
-                Container* pContainer = m_pSplits[0]->HasWindow(pWindow);
-                if (NULL != pContainer)
-                {
-                    return pContainer;
-                }
-            }
-            if (NULL != m_pSplits[1])
-            {
-                Container* pContainer = m_pSplits[1]->HasWindow(pWindow);
-                if (NULL != pContainer)
-                {
-                    return pContainer;
-                }
-            }
-        }
-        return NULL;
-    }
-
-    PlatformWindow* Container::GetPlatformWindowParent() const
-    {
-        return m_pParentWindow;
-    }
-
-    void Container::Paint()
-    {
-        WindowManager* pWindowManager = WindowManager::GetInstance();
-        ImGuiWindow* pWindow = ImGui::GetCurrentWindow();
-        const ImGuiStyle& oStyle = ImGui::GetStyle();
-        ImDrawList* pDrawList = ImGui::GetWindowDrawList();
-
-        const ImVec2 oPos  = ImGui::GetWindowPos();
-        const ImVec2 oSize = ImGui::GetWindowSize();
-        const ImVec2 oMin = ImVec2(oPos.x + 1, oPos.y + 1);
-        const ImVec2 oMax = ImVec2(oPos.x + oSize.x - 2, oPos.y + oSize.y - 2);
-
-        m_oLastPosition = oPos;
-        m_oLastSize = oSize;
-
-        const int iSeparatorHalfSize = 2;
-        const int iSeparatorSize = iSeparatorHalfSize * 2;
-
-        if (IsSplit())
-        {
-            if (m_bVerticalSplit)
-            {
-                float iFirstHeight = oSize.y * m_fSplitRatio - iSeparatorHalfSize - pWindow->WindowPadding.x;
-
-                ImGui::BeginChild("Split1", ImVec2(0, iFirstHeight), false, ImGuiWindowFlags_NoScrollbar);
-                m_pSplits[0]->Paint();
-                ImGui::EndChild();
-
-                ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, 0.0f));
-                ImRect oSeparatorRect(0, iFirstHeight, oSize.x, iFirstHeight + iSeparatorSize);
-                ImGui::Button("", oSeparatorRect.GetSize());
-                if (ImGui::IsItemHovered() || m_bIsDrag)
-                {
-                    ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeNS);
-                }
-                ImGui::PopStyleVar(1);
-
-                if (ImGui::IsItemActive())
-                {
-                    if (!m_bIsDrag)
-                    {
-                        m_bIsDrag = true;
-                    }
-                    m_fSplitRatio += ImGui::GetIO().MouseDelta.y / oSize.y;
-                    m_fSplitRatio = ImClamp(m_fSplitRatio, 0.05f, 0.95f);
-
-                }
-                else
-                {
-                    m_bIsDrag = false;
-                }
-
-                ImGui::BeginChild("Split2", ImVec2(0, 0), false, ImGuiWindowFlags_NoScrollbar);
-                m_pSplits[1]->Paint(/*iX, iY + iFirstHeight, iWidth, iSecondHeight*/);
-                ImGui::EndChild();
-            }
-            else
-            {
-                float iFirstWidth = oSize.x * m_fSplitRatio - iSeparatorHalfSize - pWindow->WindowPadding.y;
-                ImGui::BeginChild("Split1", ImVec2(iFirstWidth, 0), false, ImGuiWindowFlags_NoScrollbar);
-                m_pSplits[0]->Paint();
-                ImGui::EndChild();
-
-                ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, 0.0f));
-                ImGui::SameLine();
-
-                ImRect oSeparatorRect(iFirstWidth, 0, iFirstWidth + iSeparatorSize, oSize.y);
-                ImGui::Button("", oSeparatorRect.GetSize());
-
-                if (ImGui::IsItemHovered() || m_bIsDrag)
-                {
-                    ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeEW);
-                }
-                ImGui::PopStyleVar(1);
-
-                if (ImGui::IsItemActive())
-                {
-                    if (!m_bIsDrag)
-                    {
-                        m_bIsDrag = true;
-                    }
-
-                    m_fSplitRatio += ImGui::GetIO().MouseDelta.x / oSize.x;
-                    m_fSplitRatio = ImClamp(m_fSplitRatio, 0.05f, 0.95f);
-                }
-                else
-                {
-                    m_bIsDrag = false;
-                }
-
-                ImGui::SameLine();
-
-                ImGui::BeginChild("Split2", ImVec2(0, 0), false, ImGuiWindowFlags_NoScrollbar);
-                m_pSplits[1]->Paint();
-                ImGui::EndChild();
-            }
-        }
-        else if (HasWindowTabbed())
-        {
-            ImGui::InvisibleButton("TabListButton", ImVec2(16, 16));
-            ImGui::SameLine();
-
-            if (ImGui::BeginPopupContextItem("TabListMenu", 0))
-            {
-                int iIndex = 0;
-                for (WindowList::const_iterator itWindow = m_lWindows.begin(); itWindow != m_lWindows.end(); ++itWindow, ++iIndex)
-                {
-                    if (ImGui::Selectable((*itWindow)->GetTitle()))
-                    {
-                        m_iActiveWindow = iIndex;
-                    }
-                }
-                ImGui::EndPopup();
-            }
-
-            ImColor oLinesColor = ImColor(160, 160, 160, 255);
-            if (ImGui::IsItemHovered())
-            {
-                oLinesColor = ImColor(255, 255, 255, 255);
-            }
-            ImVec2 oButtonMin = ImGui::GetItemRectMin();
-            ImVec2 oButtonMax = ImGui::GetItemRectMax();
-            ImVec2 oButtonSize = ImVec2(oButtonMax.x - oButtonMin.x, oButtonMax.y - oButtonMin.y);
-            pDrawList->AddLine(
-                ImVec2(oButtonMin.x + 1, oButtonMin.y + oButtonSize.y / 2),
-                ImVec2(oButtonMax.x - 1, oButtonMin.y + oButtonSize.y / 2),
-                oLinesColor);
-
-            pDrawList->AddLine(
-                ImVec2(oButtonMin.x + 1, oButtonMin.y + oButtonSize.y / 2 - 4),
-                ImVec2(oButtonMax.x - 1, oButtonMin.y + oButtonSize.y / 2 - 4),
-                oLinesColor);
-
-            pDrawList->AddLine(
-                ImVec2(oButtonMin.x + 1, oButtonMin.y + oButtonSize.y / 2 + 4),
-                ImVec2(oButtonMax.x - 1, oButtonMin.y + oButtonSize.y / 2 + 4),
-                oLinesColor);
-
-            pDrawList->ChannelsSplit(2);
-
-            //Tabs
-            int iIndex = 0;
-            int iNewActive = m_iActiveWindow;
-            int iSize = int(m_lWindows.size());
-            for (WindowList::iterator it = m_lWindows.begin(); it != m_lWindows.end(); ++it)
-            {
-                const ImVec2 oTextSize = ImGui::CalcTextSize((*it)->GetTitle());
-                ImVec2 oRectSize(oTextSize.x + 15, 25);
-
-                ImGui::PushID(iIndex);
-
-                bool bSelected = iIndex == m_iActiveWindow;
-                if (ImGui::InvisibleButton((*it)->GetId(), oRectSize))
-                {
-                    iNewActive = iIndex;
-                }
-                if (iIndex < (iSize - 1))
-                {
-                    ImGui::SameLine();
-                }
-
-                if (ImGui::IsItemActive())
-                {
-                    if (ImGui::IsMouseDragging())
-                    {
-                        pWindowManager->StartDragWindow(*it);
-                    }
-                }
-
-                ImColor oNormalTab(50, 50, 50, 255); // normal
-                ImColor oSelectedTab(37, 37, 37, 255); // selected
-                ImColor oBorderColor(72, 72, 72, 255); // border
-
-                ImVec2 oRectMin = ImGui::GetItemRectMin();
-                ImVec2 oRectMax = ImGui::GetItemRectMax();
-
-                const float fOverlap = 10.f;
-                const float fSlopWidth = 30.f;
-                const float sSlopP1Ratio = 0.6f;
-                const float fSlopP2Ratio = 0.4f;
-                const float fSlopHRatio = 0.f;
-                const float fShadowDropSize = 15.f;
-                const float fShadowSlopRatio = 0.6f;
-                const float fShadowAlpha = 0.75f;
-
-                pDrawList->PathClear();
-                if (bSelected)
-                {
-                    pDrawList->ChannelsSetCurrent(1);
-                }
-                else
-                {
-                    pDrawList->ChannelsSetCurrent(0);
-                }
-
-                //Drop shadows
-                const ImVec2 uv = GImGui->FontTexUvWhitePixel;
-                pDrawList->PrimReserve(3, 3);
-                pDrawList->PrimWriteIdx((ImDrawIdx)(pDrawList->_VtxCurrentIdx)); pDrawList->PrimWriteIdx((ImDrawIdx)(pDrawList->_VtxCurrentIdx + 1)); pDrawList->PrimWriteIdx((ImDrawIdx)(pDrawList->_VtxCurrentIdx + 2));
-                pDrawList->PrimWriteVtx(ImVec2(oRectMin.x - fOverlap - fShadowDropSize, oRectMax.y), uv, ImColor(0.f, 0.f, 0.f, 0.f));
-                pDrawList->PrimWriteVtx(ImVec2(oRectMin.x - fOverlap + fSlopWidth * fShadowSlopRatio, oRectMin.y), uv, ImColor(0.f, 0.f, 0.f, 0.f));
-                pDrawList->PrimWriteVtx(ImVec2(oRectMin.x - fOverlap + fSlopWidth * fShadowSlopRatio, oRectMax.y), uv, ImColor(0.f, 0.f, 0.f, fShadowAlpha));
-                if (bSelected)
-                {
-                    pDrawList->PrimReserve(3, 3);
-                    pDrawList->PrimWriteIdx((ImDrawIdx)(pDrawList->_VtxCurrentIdx)); pDrawList->PrimWriteIdx((ImDrawIdx)(pDrawList->_VtxCurrentIdx + 1)); pDrawList->PrimWriteIdx((ImDrawIdx)(pDrawList->_VtxCurrentIdx + 2));
-                    pDrawList->PrimWriteVtx(ImVec2(oRectMax.x + fOverlap + fShadowDropSize, oRectMax.y), uv, ImColor(0.f, 0.f, 0.f, 0.f));
-                    pDrawList->PrimWriteVtx(ImVec2(oRectMax.x + fOverlap - fSlopWidth * fShadowSlopRatio, oRectMin.y), uv, ImColor(0.f, 0.f, 0.f, 0.f));
-                    pDrawList->PrimWriteVtx(ImVec2(oRectMax.x + fOverlap - fSlopWidth * fShadowSlopRatio, oRectMax.y), uv, ImColor(0.f, 0.f, 0.f, fShadowAlpha));
-                }
-
-                // Draw tab and border
-                if (bSelected)
-                {
-                    pDrawList->PathLineTo(ImVec2(oMin.x, oRectMax.y));
-                }
-                pDrawList->PathLineTo(ImVec2(oRectMin.x - fOverlap, oRectMax.y));
-                pDrawList->PathBezierCurveTo(
-                        ImVec2(oRectMin.x + fSlopWidth * sSlopP1Ratio - fOverlap, oRectMin.y + (oRectMax.y - oRectMin.y) * fSlopHRatio),
-                        ImVec2(oRectMin.x + fSlopWidth * fSlopP2Ratio - fOverlap, oRectMin.y),
-                        ImVec2(oRectMin.x + fSlopWidth - fOverlap, oRectMin.y)
-                        );
-                pDrawList->PathLineTo(ImVec2(oRectMax.x - fSlopWidth + fOverlap, oRectMin.y));
-                pDrawList->PathBezierCurveTo(
-                        ImVec2(oRectMax.x - fSlopWidth * fSlopP2Ratio + fOverlap, oRectMin.y),
-                        ImVec2(oRectMax.x - fSlopWidth * sSlopP1Ratio + fOverlap, oRectMin.y + (oRectMax.y - oRectMin.y) * fSlopHRatio),
-                        ImVec2(oRectMax.x + fOverlap, oRectMax.y)
-                        );
-
-                if (bSelected)
-                {
-                    pDrawList->AddConvexPolyFilled(pDrawList->_Path.Data + 1, pDrawList->_Path.Size - 1, bSelected ? oSelectedTab : oNormalTab, true);
-                    if (oMax.x > (oRectMax.x + fOverlap))
-                    {
-                        pDrawList->PathLineTo(ImVec2(oMax.x, oRectMax.y));
-                    }
-                    pDrawList->AddPolyline(pDrawList->_Path.Data, pDrawList->_Path.Size, oBorderColor, false, 1.5f, true);
-                }
-                else
-                {
-                    pDrawList->AddConvexPolyFilled(pDrawList->_Path.Data, pDrawList->_Path.Size, bSelected ? oSelectedTab : oNormalTab, true);
-                }
-
-                pDrawList->PathClear();
-
-                ImGui::RenderTextClipped(
-                      oRectMin
-                    , ImVec2(oRectMax.x, oRectMax.y)
-                    , (*it)->GetTitle()
-                    , NULL
-                    , &oTextSize
-                    , ImVec2(0.5f, 0.5f)
-                );
-
-                if (ImGui::BeginPopupContextItem("TabMenu"))
-                {
-                    if (ImGui::Selectable("Close"))
-                    {
-                        (*it)->Destroy();
-                    }
-                    if (ImGui::BeginMenu("Dock to"))
-                    {
-                        int iIndex1 = 0;
-
-                        if (pWindowManager->GetMainPlatformWindow()->GetContainer()->IsEmpty())
-                        {
-                            ImGui::PushID(0);
-                            if (ImGui::Selectable("Main")) pWindowManager->Dock((*it));
-                            ImGui::PopID();
-                            ++iIndex1;
-                        }
-                        const WindowList& lWindows = pWindowManager->GetWindowList();
-                        for (WindowList::const_iterator itWindow = lWindows.begin(); itWindow != lWindows.end(); ++itWindow)
-                        {
-                            if ((*it) != (*itWindow))
-                            {
-                                ImGui::PushID(iIndex1);
-                                if (ImGui::BeginMenu((*itWindow)->GetTitle()))
-                                {
-                                    bool bHovered = false;
-                                    PlatformWindow* pPlatformWindow = pWindowManager->GetWindowParent((*itWindow));
-
-                                    ImVec2 oLastWinPos = (*itWindow)->GetLastPosition();
-                                    ImVec2 oLastWinSize = (*itWindow)->GetLastSize();
-
-                                    ImGui::PushID(0);
-                                    if (ImGui::Selectable("Tab")) pWindowManager->DockWith((*it), (*itWindow), E_DOCK_ORIENTATION_CENTER);
-                                    if (ImGui::IsItemHovered() && NULL != pPlatformWindow)
-                                    {
-                                        bHovered = true;
-                                        pWindowManager->DrawWindowArea(pPlatformWindow, oLastWinPos, oLastWinSize, ImColor(0.f, 0.5f, 1.f, 0.5f));
-                                    }
-                                    ImGui::PopID();
-
-                                    ImGui::PushID(1);
-                                    if (ImGui::Selectable("Top")) pWindowManager->DockWith((*it), (*itWindow), E_DOCK_ORIENTATION_TOP);
-                                    if (ImGui::IsItemHovered() && NULL != pPlatformWindow)
-                                    {
-                                        bHovered = true;
-                                        pWindowManager->DrawWindowArea(pPlatformWindow, oLastWinPos, ImVec2(oLastWinSize.x, oLastWinSize.y / 2.f), ImColor(0.f, 0.5f, 1.f, 0.5f));
-                                    }
-                                    ImGui::PopID();
-
-                                    ImGui::PushID(2);
-                                    if (ImGui::Selectable("Left")) pWindowManager->DockWith((*it), (*itWindow), E_DOCK_ORIENTATION_LEFT);
-                                    if (ImGui::IsItemHovered() && NULL != pPlatformWindow)
-                                    {
-                                        bHovered = true;
-                                        pWindowManager->DrawWindowArea(pPlatformWindow, oLastWinPos, ImVec2(oLastWinSize.x / 2.f, oLastWinSize.y), ImColor(0.f, 0.5f, 1.f, 0.5f));
-                                    }
-                                    ImGui::PopID();
-
-                                    ImGui::PushID(3);
-                                    if (ImGui::Selectable("Right")) pWindowManager->DockWith((*it), (*itWindow), E_DOCK_ORIENTATION_RIGHT);
-                                    if (ImGui::IsItemHovered() && NULL != pPlatformWindow)
-                                    {
-                                        bHovered = true;
-                                        pWindowManager->DrawWindowArea(pPlatformWindow, ImVec2(oLastWinPos.x + oLastWinSize.x / 2.f, oLastWinPos.y), ImVec2(oLastWinSize.x / 2.f, oLastWinSize.y), ImColor(0.f, 0.5f, 1.f, 0.5f));
-                                    }
-                                    ImGui::PopID();
-
-                                    ImGui::PushID(4);
-                                    if (ImGui::Selectable("Bottom")) pWindowManager->DockWith((*it), (*itWindow), E_DOCK_ORIENTATION_BOTTOM);
-                                    if (ImGui::IsItemHovered() && NULL != pPlatformWindow)
-                                    {
-                                        bHovered = true;
-                                        pWindowManager->DrawWindowArea(pPlatformWindow, ImVec2(oLastWinPos.x, oLastWinPos.y + oLastWinSize.y / 2.f), ImVec2(oLastWinSize.x, oLastWinSize.y / 2.f), ImColor(0.f, 0.5f, 1.f, 0.5f));
-                                    }
-                                    ImGui::PopID();
-
-                                    if (!bHovered)
-                                    {
-                                        if (NULL != pPlatformWindow)
-                                        {
-                                            pWindowManager->DrawWindowArea(pPlatformWindow, oLastWinPos, oLastWinSize, ImColor(0.f, 0.5f, 1.f, 0.5f));
-                                        }
-                                    }
-
-                                    ImGui::EndMenu();
-                                }
-                                ImGui::PopID();
-                            }
-                            ++iIndex1;
-                        }
-
-                        ImGui::EndMenu();
-                    }
-                    if (ImGui::Selectable("Float"))
-                    {
-                        pWindowManager->Float((*it));
-                    }
-
-                    ImGui::EndPopup();
-                }
-
-                ImGui::PopID();
-
-                ++iIndex;
-            }
-            m_iActiveWindow = iNewActive;
-            pDrawList->ChannelsMerge();
-
-            WindowList::iterator itActiveWindow = m_lWindows.begin();
-            std::advance(itActiveWindow, m_iActiveWindow);
-
-            //Draw active
-            IM_ASSERT(itActiveWindow != m_lWindows.end());
-            if (itActiveWindow != m_lWindows.end())
-            {
-                ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, oStyle.WindowPadding);
-                //ImGui::PushStyleColor(ImGuiCol_ChildWindowBg, ImColor(59, 59, 59, 255));
-                ImGui::BeginChild((*itActiveWindow)->GetId(), ImVec2(0, 0), false, ImGuiWindowFlags_HorizontalScrollbar);
-
-                ImVec2 oWinPos = ImGui::GetWindowPos();
-                ImVec2 oWinSize = ImGui::GetWindowSize();
-
-                for (WindowList::iterator it = m_lWindows.begin(); it != m_lWindows.end(); ++it)
-                {
-                    (*it)->m_oLastPosition = oWinPos;
-                    (*it)->m_oLastSize = oWinSize;
-                }
-                (*itActiveWindow)->OnGui();
-
-                ImGui::EndChild();
-                //ImGui::PopStyleColor(1);
-                ImGui::PopStyleVar(1);
-            }
-        }
-        else
-        {
-            // This case can happened only where it's main container
-            IM_ASSERT(m_pParent == NULL);
-        }
-    }
-
-    Container* Container::GetBestDocking(const ImVec2 oCursorPos, EDockOrientation& oOutOrientation, ImVec2& oOutAreaPos, ImVec2& oOutAreaSize)
-    {
-        if (m_pParent == NULL ||
-            (oCursorPos.x >= m_oLastPosition.x && oCursorPos.x <= (m_oLastPosition.x + m_oLastSize.x) &&
-            oCursorPos.y >= m_oLastPosition.y && oCursorPos.y <= (m_oLastPosition.y + m_oLastSize.y)))
-        {
-            if (IsSplit())
-            {
-                Container* pBestContainer = NULL;
-                pBestContainer = m_pSplits[0]->GetBestDocking(oCursorPos, oOutOrientation, oOutAreaPos, oOutAreaSize);
-                if (NULL != pBestContainer)
-                {
-                    return pBestContainer;
-                }
-                pBestContainer = m_pSplits[1]->GetBestDocking(oCursorPos, oOutOrientation, oOutAreaPos, oOutAreaSize);
-                if (NULL != pBestContainer)
-                {
-                    return pBestContainer;
-                }
-            }
-            else
-            {
-                const float c_fBoxHalfSize = 20.f;
-                const float c_fBoxSize = c_fBoxHalfSize * 2.f;
-                const float c_fMinSize = c_fBoxSize * 4.f;
-                const float c_fSplitRatio = 0.5f;
-                //const float c_fSplitRatio = oConfig.m_fDragMarginSizeRatio;
-                const ImColor oBoxColor(200, 200, 255, 255);
-                const ImColor oBoxHightlightColor(100, 100, 255, 255);
-
-                if (m_oLastSize.x < c_fMinSize && m_oLastSize.y < c_fMinSize)
-                {
-                    oOutOrientation = E_DOCK_ORIENTATION_CENTER;
-                    oOutAreaPos = m_oLastPosition;
-                    oOutAreaSize = m_oLastSize;
-                    return this;
-                }
-                else
-                {
-                    ImVec2 oCenter = ImVec2(m_oLastPosition.x + m_oLastSize.x / 2.f, m_oLastPosition.y + m_oLastSize.y / 2.f);
-
-                    bool bIsInCenter = false;
-                    bool bIsInTop = false;
-                    bool bIsInLeft = false;
-                    bool bIsInRight = false;
-                    bool bIsInBottom = false;
-
-                    //Center
-                    ImRect oRectCenter(ImVec2(oCenter.x - c_fBoxHalfSize, oCenter.y - c_fBoxHalfSize), ImVec2(oCenter.x + c_fBoxHalfSize, oCenter.y + c_fBoxHalfSize));
-                    bIsInCenter = oRectCenter.Contains(oCursorPos);
-                    WindowManager::GetInstance()->DrawWindowArea(m_pParentWindow, oRectCenter.Min, oRectCenter.GetSize(), bIsInCenter ? oBoxHightlightColor : oBoxColor);
-
-                    if (m_oLastSize.y >= c_fMinSize)
-                    {
-                        //Top
-                        ImRect oRectTop(ImVec2(oCenter.x - c_fBoxHalfSize, oCenter.y - c_fBoxHalfSize * 4.f), ImVec2(oCenter.x + c_fBoxHalfSize, oCenter.y - c_fBoxHalfSize * 2.f));
-                        bIsInTop = oRectTop.Contains(oCursorPos);
-                        WindowManager::GetInstance()->DrawWindowArea(m_pParentWindow, oRectTop.Min, oRectTop.GetSize(), bIsInTop ? oBoxHightlightColor : oBoxColor);
-
-                        //Bottom
-                        ImRect oRectBottom(ImVec2(oCenter.x - c_fBoxHalfSize, oCenter.y + c_fBoxHalfSize * 2.f), ImVec2(oCenter.x + c_fBoxHalfSize, oCenter.y + c_fBoxHalfSize * 4.f));
-                        bIsInBottom = oRectBottom.Contains(oCursorPos);
-                        WindowManager::GetInstance()->DrawWindowArea(m_pParentWindow, oRectBottom.Min, oRectBottom.GetSize(), bIsInBottom ? oBoxHightlightColor : oBoxColor);
-                    }
-
-                    if (m_oLastSize.x >= c_fMinSize)
-                    {
-                        //Left
-                        ImRect oRectLeft(ImVec2(oCenter.x - c_fBoxHalfSize * 4.f, oCenter.y - c_fBoxHalfSize), ImVec2(oCenter.x - c_fBoxHalfSize * 2.f, oCenter.y + c_fBoxHalfSize));
-                        bIsInLeft = oRectLeft.Contains(oCursorPos);
-                        WindowManager::GetInstance()->DrawWindowArea(m_pParentWindow, oRectLeft.Min, oRectLeft.GetSize(), bIsInLeft ? oBoxHightlightColor : oBoxColor);
-
-                        //Right
-                        ImRect oRectRight(ImVec2(oCenter.x + c_fBoxHalfSize * 2.f, oCenter.y - c_fBoxHalfSize), ImVec2(oCenter.x + c_fBoxHalfSize * 4.f, oCenter.y + c_fBoxHalfSize));
-                        bIsInRight = oRectRight.Contains(oCursorPos);
-                        WindowManager::GetInstance()->DrawWindowArea(m_pParentWindow, oRectRight.Min, oRectRight.GetSize(), bIsInRight ? oBoxHightlightColor : oBoxColor);
-                    }
-
-                    if (bIsInCenter)
-                    {
-                        oOutOrientation = E_DOCK_ORIENTATION_CENTER;
-                        oOutAreaPos = m_oLastPosition;
-                        oOutAreaSize = m_oLastSize;
-                        return this;
-                    }
-                    else if (bIsInTop)
-                    {
-                        oOutOrientation = E_DOCK_ORIENTATION_TOP;
-                        oOutAreaPos = m_oLastPosition;
-                        oOutAreaSize = ImVec2(m_oLastSize.x, m_oLastSize.y * c_fSplitRatio);
-                        return this;
-                    }
-                    else if (bIsInLeft)
-                    {
-                        oOutOrientation = E_DOCK_ORIENTATION_LEFT;
-                        oOutAreaPos = m_oLastPosition;
-                        oOutAreaSize = ImVec2(m_oLastSize.x * c_fSplitRatio, m_oLastSize.y);
-                        return this;
-                    }
-                    else if (bIsInRight)
-                    {
-                        oOutOrientation = E_DOCK_ORIENTATION_RIGHT;
-                        oOutAreaPos = ImVec2(m_oLastPosition.x + m_oLastSize.x * (1.f - c_fSplitRatio), m_oLastPosition.y);
-                        oOutAreaSize = ImVec2(m_oLastSize.x * c_fSplitRatio, m_oLastSize.y);
-                        return this;
-                    }
-                    else if (bIsInBottom)
-                    {
-                        oOutOrientation = E_DOCK_ORIENTATION_BOTTOM;
-                        oOutAreaPos = ImVec2(m_oLastPosition.x, m_oLastPosition.y + m_oLastSize.y * (1.f - c_fSplitRatio));
-                        oOutAreaSize = ImVec2(m_oLastSize.x, m_oLastSize.y * c_fSplitRatio);
-                        return this;
-                    }
-                }
-            }
-        }
-
-        return NULL;
-    }
-
-    PlatformWindow::PlatformWindow(bool bMain, bool bIsDragWindow)
-    {
-        m_bMain = bMain;
-        m_bIsDragWindow = bIsDragWindow;
-        m_pContainer = IMGUI_NEW(Container)(this);
-        m_pPreviousState = NULL;
-
-        ImGui::GetIO().IniFilename = NULL;
-
-        m_pState = ImGui::CreateContext();
-    }
-
-    PlatformWindow::~PlatformWindow()
-    {
-        IMGUI_DELETE_NULL(Container, m_pContainer);
-
-        SetState();
-        if (!IsMain())
-        {
-            ImGui::GetIO().Fonts = NULL;
-        }
-
-        RestoreState();
-        ImGui::DestroyContext(m_pState);
-        m_pState = NULL;
-    }
-
-    void PlatformWindow::OnClose()
-    {
-        WindowManager::GetInstance()->OnClosePlatformWindow(this);
-    }
-
-    static bool s_bStatePush = false;
-
-    bool PlatformWindow::IsStateSet()
-    {
-        return s_bStatePush;
-    }
-
-    void PlatformWindow::SetState()
-    {
-        IM_ASSERT(s_bStatePush == false);
-        s_bStatePush = true;
-        m_pPreviousState = ImGui::GetCurrentContext();
-        ImGui::SetCurrentContext(m_pState);
-        memcpy(&m_pState->Style, &m_pPreviousState->Style, sizeof(ImGuiStyle) );
-    }
-
-    void PlatformWindow::RestoreState()
-    {
-        IM_ASSERT(s_bStatePush == true);
-        s_bStatePush = false;
-        memcpy(&m_pPreviousState->Style, &m_pState->Style, sizeof(ImGuiStyle) );
-        ImGui::SetCurrentContext(m_pPreviousState);
-    }
-
-    void PlatformWindow::OnLoseFocus()
-    {
-        ImGuiContext& g = *m_pState;
-        g.SetNextWindowPosCond = g.SetNextWindowSizeCond = g.SetNextWindowContentSizeCond = g.SetNextWindowCollapsedCond = g.SetNextWindowFocus = 0;
-    }
-
-    void PlatformWindow::Paint()
-    {
-        PaintBegin();
-        WindowManager::GetInstance()->Paint(this);
-        PaintEnd();
-    }
-
-    bool PlatformWindow::IsMain()
-    {
-        return m_bMain;
-    }
-
-    void PlatformWindow::Dock(Window* pWindow)
-    {
-        m_pContainer->Dock(pWindow);
-    }
-
-    bool PlatformWindow::UnDock(Window* pWindow)
-    {
-        return m_pContainer->UnDock(pWindow);
-    }
-
-    Container* PlatformWindow::GetContainer()
-    {
-        return m_pContainer;
-    }
-
-    Container* PlatformWindow::HasWindow(Window* pWindow)
-    {
-        return m_pContainer->HasWindow(pWindow);
-    }
-
-    void PlatformWindow::PaintContainer()
-    {
-        m_pContainer->Paint();
-    }
-
-    WindowManager::DrawWindowAreaAction::DrawWindowAreaAction(PlatformWindow* pWindow, const ImVec2& oRectPos, const ImVec2& oRectSize, const ImColor& oColor)
-        : m_oColor(oColor)
-    {
-        m_pWindow = pWindow;
-        m_oRectPos = oRectPos;
-        m_oRectSize = oRectSize;
-    }
-
-    WindowManager* WindowManager::s_pInstance = 0;
-
-    //////////////////////////////////////////////////////////////////////////
-
-    WindowManager::Config::Config()
-        : m_fDragMarginRatio(0.1f)
-        , m_fDragMarginSizeRatio(0.25f)
-        , m_oHightlightAreaColor(0.f, 0.5f, 1.f, 0.5f)
-    {
-    }
-
-    //////////////////////////////////////////////////////////////////////////
-
-    WindowManager::WindowManager()
-    {
-        s_pInstance = this;
-        m_pMainPlatformWindow = NULL;
-        m_pDragPlatformWindow = NULL;
-        m_pCurrentPlatformWindow = NULL;
-        m_pDraggedWindow = NULL;
-        m_oDragPreviewOffset = ImVec2(-20, -10);
-    }
-
-    WindowManager::~WindowManager()
-    {
-        IMGUI_DELETE_NULL(PlatformWindow, m_pMainPlatformWindow);
-        IMGUI_DELETE_NULL(PlatformWindow, m_pDragPlatformWindow);
-        s_pInstance = 0;
-        ImGui::Shutdown();
-    }
-
-    bool WindowManager::Init()
-    {
-        m_pMainPlatformWindow = CreatePlatformWindow(true, NULL, false);
-        if (NULL != m_pMainPlatformWindow)
-        {
-            m_pMainPlatformWindow->Show();
-
-            m_pDragPlatformWindow = CreatePlatformWindow(false, m_pMainPlatformWindow, true);
-            return true;
-        }
-        return false;
-    }
-
-    bool WindowManager::Run()
-    {
-        if (m_pMainPlatformWindow != NULL)
-        {
-            ImGuiIO& io = ImGui::GetIO();
-            m_pMainPlatformWindow->SetSize(io.DisplaySize);
-        }
-        InternalRun();
-        return m_pMainPlatformWindow != NULL;
-    }
-
-    void WindowManager::Exit()
-    {
-        //TODO : Manual exit
-    }
-
-    PlatformWindow* WindowManager::GetMainPlatformWindow()
-    {
-        return m_pMainPlatformWindow;
-    }
-
-    WindowManager::Config& WindowManager::GetConfig()
-    {
-        return m_oConfig;
-    }
-
-    void WindowManager::SetMainTitle(const char* pTitle)
-    {
-        if (NULL != m_pMainPlatformWindow)
-        {
-            m_pMainPlatformWindow->SetTitle(pTitle);
-        }
-    }
-
-    void WindowManager::Dock(Window* pWindow, EDockOrientation eOrientation, PlatformWindow* pToPlatformWindow)
-    {
-        DockAction* pAction = IMGUI_NEW(DockAction);
-        pAction->m_bFloat = false;
-        pAction->m_pWindow = pWindow;
-        pAction->m_pWith = NULL;
-        pAction->m_eOrientation = eOrientation;
-        pAction->m_pToPlatformWindow = (pToPlatformWindow != NULL) ? pToPlatformWindow : m_pMainPlatformWindow;
-        pAction->m_pToContainer = NULL;
-        m_lDockActions.push_back(pAction);
-    }
-
-    void WindowManager::DockTo(Window* pWindow, EDockOrientation eOrientation, Container* pContainer)
-    {
-        IM_ASSERT(NULL != pContainer);
-        if (NULL != pContainer)
-        {
-            DockAction* pAction = IMGUI_NEW(DockAction);
-            pAction->m_bFloat = false;
-            pAction->m_pWindow = pWindow;
-            pAction->m_pWith = NULL;
-            pAction->m_eOrientation = eOrientation;
-            pAction->m_pToPlatformWindow = NULL;
-            pAction->m_pToContainer = pContainer;
-            m_lDockActions.push_back(pAction);
-        }
-    }
-
-    void WindowManager::DockWith(Window* pWindow, Window* pWithWindow, EDockOrientation eOrientation)
-    {
-        DockAction* pAction = IMGUI_NEW(DockAction);
-        pAction->m_bFloat = false;
-        pAction->m_pWindow = pWindow;
-        pAction->m_pWith = pWithWindow;
-        pAction->m_eOrientation = eOrientation;
-        m_lDockActions.push_back(pAction);
-    }
-
-    void WindowManager::Float(Window* pWindow, const ImVec2& oPosition, const ImVec2& oSize)
-    {
-        DockAction* pAction = IMGUI_NEW(DockAction);
-        pAction->m_bFloat = true;
-        pAction->m_pWindow = pWindow;
-        pAction->m_oPosition = oPosition;
-        pAction->m_oSize = oSize;
-        m_lDockActions.push_back(pAction);
-    }
-
-    const WindowList& WindowManager::GetWindowList() const
-    {
-        return m_lWindows;
-    }
-
-    PlatformWindow* WindowManager::GetCurrentPlatformWindow()
-    {
-        return m_pCurrentPlatformWindow;
-    }
-
-    PlatformWindow* WindowManager::GetWindowParent(Window* pWindow)
-    {
-        Container* pContainer = m_pMainPlatformWindow->HasWindow(pWindow);
-        if (NULL != pContainer)
-        {
-            return m_pMainPlatformWindow;
-        }
-
-        for (PlatformWindowList::iterator it = m_lPlatformWindows.begin(); it != m_lPlatformWindows.end(); ++it)
-        {
-            pContainer = (*it)->HasWindow(pWindow);
-            if (NULL != pContainer)
-            {
-                return *it;
-            }
-        }
-        IM_ASSERT(false);
-        return NULL;
-    }
-
-    void WindowManager::Log(const char* pFormat, ...)
-    {
-        char pBuffer[32768];
-        va_list argptr;
-        va_start(argptr, pFormat);
-        ImFormatStringV(pBuffer, sizeof(char) * 32767, pFormat, argptr);
-        va_end(argptr);
-        LogFormatted(pBuffer);
-    }
-
-    void WindowManager::PreUpdate()
-    {
-        if (NULL != m_pMainPlatformWindow)
-        {
-            m_pMainPlatformWindow->PreUpdate();
-        }
-
-        for (PlatformWindowList::iterator it = m_lPlatformWindows.begin(); it != m_lPlatformWindows.end(); ++it)
-        {
-            (*it)->PreUpdate();
-        }
-    }
-
-    void WindowManager::Update()
-    {
-        UpdatePlatformwWindowActions();
-        UpdateDockActions();
-        UpdateOrphans();
-
-        while (m_lToDestroyWindows.begin() != m_lToDestroyWindows.end())
-        {
-            Window* pWindow = *m_lToDestroyWindows.begin();
-
-            m_lToDestroyWindows.remove(pWindow);
-            m_lOrphanWindows.remove(pWindow);
-            m_lWindows.remove(pWindow);
-
-            InternalUnDock(pWindow);
-
-            IMGUI_DELETE(Window, pWindow);
-        }
-
-        while (m_lToDestroyPlatformWindows.begin() != m_lToDestroyPlatformWindows.end())
-        {
-            PlatformWindow* pPlatformWindow = *m_lToDestroyPlatformWindows.begin();
-            m_lToDestroyPlatformWindows.remove(pPlatformWindow);
-            m_lPlatformWindows.remove(pPlatformWindow);
-            IMGUI_DELETE(PlatformWindow, pPlatformWindow);
-        }
-
-        UpdateDragWindow();
-
-        m_pCurrentPlatformWindow = m_pMainPlatformWindow;
-        if (NULL != m_pMainPlatformWindow)
-        {
-            m_pMainPlatformWindow->Paint();
-        }
-
-        for (PlatformWindowList::iterator it = m_lPlatformWindows.begin(); it != m_lPlatformWindows.end(); ++it)
-        {
-            m_pCurrentPlatformWindow = (*it);
-            (*it)->Paint();
-        }
-
-        m_pCurrentPlatformWindow = NULL;
-    }
-
-    void WindowManager::UpdatePlatformwWindowActions()
-    {
-        while (m_lPlatformWindowActions.begin() != m_lPlatformWindowActions.end())
-        {
-            PlatformWindowAction* pAction = *m_lPlatformWindowActions.begin();
-
-            IM_ASSERT((pAction->m_iFlags & E_PLATFORM_WINDOW_ACTION_SHOW & E_PLATFORM_WINDOW_ACTION_HIDE) == 0); // Can't show and hide		
-
-            if (pAction->m_iFlags & E_PLATFORM_WINDOW_ACTION_DESTOY)
-            {
-                //pAction->m_pPlatformWindow->Show();
-                //todo destroy
-                bool bFound = false;
-                if (m_pMainPlatformWindow == pAction->m_pPlatformWindow)
-                {
-                    while (m_lPlatformWindows.begin() != m_lPlatformWindows.end())
-                    {
-                        IMGUI_DELETE(PlatformWindow, *m_lPlatformWindows.begin());
-                        m_lPlatformWindows.erase(m_lPlatformWindows.begin());
-                    }
-                    IMGUI_DELETE(PlatformWindow, m_pMainPlatformWindow);
-                    m_pMainPlatformWindow = NULL;
-                    bFound = true;
-                }
-                else
-                {
-                    for (PlatformWindowList::iterator it = m_lPlatformWindows.begin(); it != m_lPlatformWindows.end(); ++it)
-                    {
-                        if (*it == pAction->m_pPlatformWindow)
-                        {
-                            IMGUI_DELETE(PlatformWindow, *it);
-                            m_lPlatformWindows.erase(it);
-                            bFound = true;
-                            break;
-                        }
-                    }
-                }
-
-                if (!bFound)
-                {
-                    IM_ASSERT(false, "ImwPlatformWindow not found, maybe already closed");
-                }
-            }
-
-            if (pAction->m_iFlags & E_PLATFORM_WINDOW_ACTION_SHOW)
-            {
-                pAction->m_pPlatformWindow->Show();
-            }
-
-            if (pAction->m_iFlags & E_PLATFORM_WINDOW_ACTION_HIDE)
-            {
-                pAction->m_pPlatformWindow->Hide();
-            }
-
-            if (pAction->m_iFlags & E_PLATFORM_WINDOW_ACTION_SET_POSITION)
-            {
-                pAction->m_pPlatformWindow->SetPosition(pAction->m_oPosition);
-            }
-
-            if (pAction->m_iFlags & E_PLATFORM_WINDOW_ACTION_SET_SIZE)
-            {
-                pAction->m_pPlatformWindow->SetSize(pAction->m_oSize);
-            }
-
-            IMGUI_DELETE(PlatformWindowAction, *m_lPlatformWindowActions.begin());
-            m_lPlatformWindowActions.erase(m_lPlatformWindowActions.begin());
-        }
-    }
-
-    void WindowManager::UpdateDockActions()
-    {
-        while (m_lDockActions.begin() != m_lDockActions.end())
-        {
-            DockAction* pAction = *m_lDockActions.begin();
-
-            InternalUnDock(pAction->m_pWindow);
-
-            if (pAction->m_bFloat)
-            {
-                if (!InternalFloat(pAction->m_pWindow, pAction->m_oPosition, pAction->m_oSize) )
-                {
-                    InternalDock(pAction->m_pWindow, E_DOCK_ORIENTATION_LEFT, m_pMainPlatformWindow);
-                }
-            }
-            else
-            {
-                if (NULL != pAction->m_pWith)
-                {
-                    InternalDockWith(pAction->m_pWindow, pAction->m_pWith, pAction->m_eOrientation);
-                }
-                else if (NULL != pAction->m_pToContainer)
-                {
-                    InternalDockTo(pAction->m_pWindow, pAction->m_eOrientation, pAction->m_pToContainer);
-                }
-                else
-                {
-                    InternalDock(pAction->m_pWindow, pAction->m_eOrientation, pAction->m_pToPlatformWindow);
-                }
-            }
-
-            m_lOrphanWindows.remove(pAction->m_pWindow);
-
-            IMGUI_DELETE(DockAction, pAction);
-            m_lDockActions.erase(m_lDockActions.begin());
-        }
-    }
-
-    void WindowManager::UpdateOrphans()
-    {
-        while (m_lOrphanWindows.begin() != m_lOrphanWindows.end())
-        {
-            if (m_pMainPlatformWindow->m_pContainer->IsEmpty())
-            {
-                InternalDock(*m_lOrphanWindows.begin(), E_DOCK_ORIENTATION_CENTER, m_pMainPlatformWindow);
-            }
-            else
-            {
-                ImVec2 oSize = ImVec2(300, 300);
-                ImVec2 oPos = m_pMainPlatformWindow->GetPosition();
-                ImVec2 oMainSize = m_pMainPlatformWindow->GetSize();
-                oPos.x += (oMainSize.x - oSize.x) / 2;
-                oPos.y += (oMainSize.y - oSize.y) / 2;
-                InternalFloat(*m_lOrphanWindows.begin(), oPos, oSize);
-            }
-            m_lOrphanWindows.erase(m_lOrphanWindows.begin());
-        }
-    }
-
-    void WindowManager::Paint(PlatformWindow* pWindow)
-    {
-        if (!pWindow->GetContainer()->IsEmpty() )
-        {
-            float fY = 0.f;
-
-            ImGui::SetNextWindowPos(ImVec2(0, fY), ImGuiSetCond_Always);
-            ImGui::SetNextWindowSize(ImVec2(pWindow->GetSize().x, pWindow->GetSize().y - fY), ImGuiSetCond_Always);
-            int iFlags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse;
-
-            if (NULL != m_pDraggedWindow)
-            {
-                iFlags += ImGuiWindowFlags_NoInputs;
-            }
-
-            ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(5.0f, 5.0f));
-            char name[64];
-            ImFormatString(name, sizeof(name), "Window %p", pWindow);
-            ImGui::Begin(name, NULL, iFlags);
-            pWindow->PaintContainer();
-            ImGui::End();
-            ImGui::PopStyleVar(1);
-
-            ImGui::Begin("##Overlay", NULL, ImVec2(0, 0), 0.f, ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_AlwaysAutoResize);
-            ImDrawList* pDrawList = ImGui::GetWindowDrawList();
-            for (ImwList<DrawWindowAreaAction>::iterator it = m_lDrawWindowAreas.begin(); it != m_lDrawWindowAreas.end();)
-            {
-                const DrawWindowAreaAction& oAction = *it;
-
-                if (pWindow == oAction.m_pWindow)
-                {
-                    ImVec2 oPosA = oAction.m_oRectPos;
-                    ImVec2 oPosB = oAction.m_oRectSize;
-                    oPosB.x += oPosA.x;
-                    oPosB.y += oPosA.y;
-
-                    pDrawList->PushClipRectFullScreen();
-                    pDrawList->AddRectFilled(oPosA, oPosB, oAction.m_oColor);
-                    pDrawList->PopClipRect();
-                    ImwList<DrawWindowAreaAction>::iterator toRemove = it;
-                    ++it;
-                    m_lDrawWindowAreas.erase(toRemove);
-                }
-                else
-                {
-                    ++it;
-                }
-            }
-
-            ImGui::End();
-        }
-    }
-
-    static ImVec2 GetCursorPos()
-    {
-        ImGuiIO& io = ImGui::GetIO();
-        return io.MousePos;
-    }
-
-    void WindowManager::StartDragWindow(Window* pWindow)
-    {
-        if (NULL == m_pDraggedWindow)
-        {
-            m_pDraggedWindow = pWindow;
-
-            PlatformWindowAction* pAction = IMGUI_NEW(PlatformWindowAction);
-            pAction->m_pPlatformWindow = m_pDragPlatformWindow;
-            pAction->m_iFlags = E_PLATFORM_WINDOW_ACTION_SHOW | E_PLATFORM_WINDOW_ACTION_SET_POSITION | E_PLATFORM_WINDOW_ACTION_SET_SIZE;
-            ImVec2 oCursorPos = GetCursorPos();
-            pAction->m_oPosition = ImVec2(oCursorPos.x + m_oDragPreviewOffset.x, oCursorPos.y + m_oDragPreviewOffset.y);
-            pAction->m_oSize = ImVec2(pWindow->GetLastSize().x, pWindow->GetLastSize().y);
-            m_lPlatformWindowActions.push_back(pAction);
-
-            Dock(pWindow, E_DOCK_ORIENTATION_CENTER, m_pDragPlatformWindow);
-            m_pDragPlatformWindow->m_pState->IO.MouseDown[0] = true;
-        }
-    }
-
-    void WindowManager::StopDragWindow()
-    {
-        PlatformWindowAction* pAction = IMGUI_NEW(PlatformWindowAction);
-        pAction->m_pPlatformWindow = m_pDragPlatformWindow;
-        pAction->m_iFlags = E_PLATFORM_WINDOW_ACTION_HIDE;
-        m_pDragPlatformWindow->Hide();
-        m_lPlatformWindowActions.push_back(pAction);
-        m_pDraggedWindow = NULL;
-    }
-
-    void WindowManager::UpdateDragWindow()
-    {
-        if (NULL != m_pDraggedWindow)
-        {
-            m_pCurrentPlatformWindow = m_pDragPlatformWindow;
-            m_pDragPlatformWindow->Paint();
-            m_pCurrentPlatformWindow = NULL;
-
-            ImVec2 oCursorPos = GetCursorPos();
-            m_pDragPlatformWindow->SetPosition(ImVec2(oCursorPos.x + m_oDragPreviewOffset.x, oCursorPos.y + m_oDragPreviewOffset.y));
-
-            //Search best dock area
-            EDockOrientation eBestDockOrientation;
-            ImVec2 oHightlightPos;
-            ImVec2 oHightlightSize;
-            Container* pBestContainer = GetBestDocking(m_pMainPlatformWindow, oCursorPos, eBestDockOrientation, oHightlightPos, oHightlightSize);
-            if (NULL == pBestContainer)
-            {
-                for (PlatformWindowList::iterator it = m_lPlatformWindows.begin(); it != m_lPlatformWindows.end() && NULL == pBestContainer; ++it)
-                {
-                    pBestContainer = GetBestDocking(*it, oCursorPos, eBestDockOrientation, oHightlightPos, oHightlightSize);
-                }
-            }
-            if (pBestContainer)
-            {
-                DrawWindowArea(pBestContainer->GetPlatformWindowParent(), oHightlightPos, oHightlightSize, m_oConfig.m_oHightlightAreaColor);
-            }
-
-            ImGuiIO& io = ImGui::GetIO();
-            if (!io.MouseDown[0])
-            {
-                if (NULL != pBestContainer)
-                {
-                    DockTo(m_pDraggedWindow, eBestDockOrientation, pBestContainer);
-                }
-                else
-                {
-                    Float(m_pDraggedWindow, m_pDragPlatformWindow->GetPosition(), m_pDragPlatformWindow->GetSize());
-                }
-
-                StopDragWindow();
-            }
-        }
-    }
-
-    Container* WindowManager::GetBestDocking(PlatformWindow* pPlatformWindow, const ImVec2 oCursorPos, EDockOrientation& oOutOrientation, ImVec2& oOutAreaPos, ImVec2& oOutAreaSize)
-    {
-        ImVec2 oPos = pPlatformWindow->GetPosition();
-        ImVec2 oSize = pPlatformWindow->GetSize();
-        if (oCursorPos.x >= oPos.x && oCursorPos.x <= (oPos.x + oSize.x) &&
-            oCursorPos.y >= oPos.y && oCursorPos.y <= (oPos.y + oSize.y))
-        {
-            ImVec2 oRectPos(oCursorPos.x - oPos.x, oCursorPos.y - oPos.y);
-
-            Container* pBestContainer = pPlatformWindow->GetContainer()->GetBestDocking(oRectPos, oOutOrientation, oOutAreaPos, oOutAreaSize);
-            if (NULL != pBestContainer)
-            {
-                return pBestContainer;
-            }
-
-            //Left
-            if (oRectPos.x <= oSize.x * m_oConfig.m_fDragMarginRatio)
-            {
-                oOutOrientation = E_DOCK_ORIENTATION_LEFT;
-                oOutAreaPos = IM_VEC2_0;
-                oOutAreaSize = ImVec2(oSize.x * m_oConfig.m_fDragMarginSizeRatio, oSize.y);
-            }
-            //Right
-            else if (oRectPos.x >=  oSize.x * (1.f - m_oConfig.m_fDragMarginRatio))
-            {
-                oOutOrientation = E_DOCK_ORIENTATION_RIGHT;
-                oOutAreaPos = ImVec2(oSize.x * (1.f - m_oConfig.m_fDragMarginSizeRatio), 0.f);
-                oOutAreaSize = ImVec2(oSize.x * m_oConfig.m_fDragMarginSizeRatio, oSize.y);
-            }
-            //Top
-            else if (oRectPos.y <= oSize.y * m_oConfig.m_fDragMarginRatio)
-            {
-                oOutOrientation = E_DOCK_ORIENTATION_TOP;
-                oOutAreaPos = IM_VEC2_0;
-                oOutAreaSize = ImVec2(oSize.x, oSize.y * m_oConfig.m_fDragMarginSizeRatio);
-            }
-            //Bottom
-            else if (oRectPos.y >=  oSize.y * (1.f - m_oConfig.m_fDragMarginRatio))
-            {
-                oOutOrientation = E_DOCK_ORIENTATION_BOTTOM;
-                oOutAreaPos = ImVec2(0.f, oSize.y * (1.f - m_oConfig.m_fDragMarginSizeRatio));
-                oOutAreaSize = ImVec2(oSize.x, oSize.y * m_oConfig.m_fDragMarginSizeRatio);
-            }
-            else
-            {
-                oOutOrientation = E_DOCK_ORIENTATION_CENTER;
-                oOutAreaPos = IM_VEC2_0;
-                oOutAreaSize = ImVec2(oSize.x, oSize.y);
-                //IM_ASSERT(false); //Best dock orientation not found
-                return NULL;
-            }
-            return pPlatformWindow->GetContainer();
-        }
-        return NULL;
-    }
-
-    void WindowManager::AddWindow(Window* pWindow)
-    {
-        m_lWindows.push_back(pWindow);
-
-        m_lOrphanWindows.push_back(pWindow);
-    }
-
-    void WindowManager::RemoveWindow(Window* pWindow)
-    {
-        m_lWindows.remove(pWindow);
-        m_lOrphanWindows.remove(pWindow);
-    }
-
-    void WindowManager::DestroyWindow(Window* pWindow)
-    {
-        if (NULL != pWindow && std::find(m_lToDestroyWindows.begin(), m_lToDestroyWindows.end(), pWindow) == m_lToDestroyWindows.end())
-        {
-            m_lToDestroyWindows.push_back(pWindow);
-        }
-    }
-
-    void WindowManager::InternalDock(Window* pWindow, EDockOrientation eOrientation, PlatformWindow* pToPlatformWindow)
-    {
-        pToPlatformWindow->m_pContainer->Dock(pWindow, eOrientation);
-    }
-
-    void WindowManager::InternalDockTo(Window* pWindow, EDockOrientation eOrientation, Container* pToContainer)
-    {
-        pToContainer->Dock(pWindow, eOrientation);
-    }
-
-    void WindowManager::InternalDockWith(Window* pWindow, Window* pWithWindow, EDockOrientation eOrientation)
-    {
-        Container* pContainer = m_pMainPlatformWindow->HasWindow(pWithWindow);
-        if (NULL != pContainer)
-        {
-            pContainer->Dock(pWindow, eOrientation);
-        }
-
-        for (PlatformWindowList::iterator it = m_lPlatformWindows.begin(); it != m_lPlatformWindows.end(); ++it)
-        {
-            pContainer = (*it)->HasWindow(pWithWindow);
-            if (NULL != pContainer)
-            {
-                pContainer->Dock(pWindow, eOrientation);
-                break;
-            }
-        }
-    }
-
-    bool WindowManager::InternalFloat(Window* pWindow, ImVec2 oPosition, ImVec2 oSize)
-    {
-        PlatformWindow* pPlatformWindow = CreatePlatformWindow(false, m_pMainPlatformWindow, false);
-        if (NULL == pPlatformWindow)
-        {
-            return false;
-        }
-
-        m_lPlatformWindows.push_back(pPlatformWindow);
-
-        if (oSize.x == IM_VEC2_N1.x && oSize.y == IM_VEC2_N1.y)
-        {
-            oSize = pWindow->GetLastSize();
-        }
-
-        if (oPosition.x == IM_VEC2_N1.x && oPosition.y == IM_VEC2_N1.y)
-        {
-            oPosition = GetCursorPos();
-            oPosition.x -= 20;
-            oPosition.x -= 10;
-        }
-        pPlatformWindow->Dock(pWindow);
-        pPlatformWindow->SetSize(oSize);
-        pPlatformWindow->SetPosition(oPosition);
-        pPlatformWindow->Show();
-
-        return true;
-    }
-
-    void WindowManager::InternalUnDock(Window* pWindow)
-    {
-        if (m_pMainPlatformWindow->UnDock(pWindow))
-        {
-            return;
-        }
-
-        for (PlatformWindowList::iterator it = m_lPlatformWindows.begin(); it != m_lPlatformWindows.end(); ++it)
-        {
-            if ((*it)->UnDock(pWindow))
-            {
-                //Destroy empty platform window if not main window
-                if (!(*it)->IsMain() && (*it)->GetContainer()->IsEmpty())
-                {
-                    m_lToDestroyPlatformWindows.push_back(*it);
-                }
-                return;
-            }
-        }
-
-        m_pDragPlatformWindow->UnDock(pWindow);
-    }
-
-    void WindowManager::OnClosePlatformWindow(PlatformWindow* pWindow)
-    {
-        PlatformWindowAction* pAction = IMGUI_NEW(PlatformWindowAction);
-        pAction->m_iFlags = E_PLATFORM_WINDOW_ACTION_DESTOY;
-        pAction->m_pPlatformWindow = pWindow;
-        m_lPlatformWindowActions.push_back(pAction);
-    }
-
-    void WindowManager::DrawWindowArea(PlatformWindow* pWindow, const ImVec2& oPos, const ImVec2& oSize, const ImColor& oColor)
-    {
-        m_lDrawWindowAreas.push_back(DrawWindowAreaAction(pWindow, oPos, oSize, oColor));
-    }
-
-    // Static
-    WindowManager* WindowManager::GetInstance()
-    {
-        return s_pInstance;
-    }
-
-} // namespace ImWindow

+ 0 - 310
3rdparty/ocornut-imgui/imgui_wm.h

@@ -1,310 +0,0 @@
-/*
- * Copyright 2011-2016 Branimir Karadzic. All rights reserved.
- * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
- */
-
-/*
- * Based on ImWindow code from:
- * https://github.com/thennequin/ImWindow
- *
- * MIT license:
- * https://github.com/thennequin/ImWindow/blob/master/LICENSE
- */
-
-#ifndef IMGUI_WM_H_HEADER_GUARD
-#define IMGUI_WM_H_HEADER_GUARD
-
-#include "imgui.h"
-
-typedef unsigned int ImU32;
-
-#ifndef ImwList
-# include <list>
-# define ImwList std::list
-#endif // ImList
-
-#ifndef ImwMap
-# include <unordered_map>
-# define ImwMap std::unordered_map
-#endif // ImMap
-
-namespace ImGuiWM
-{
-    enum EDockOrientation
-    {
-        E_DOCK_ORIENTATION_CENTER,
-        E_DOCK_ORIENTATION_TOP,
-        E_DOCK_ORIENTATION_LEFT,
-        E_DOCK_ORIENTATION_RIGHT,
-        E_DOCK_ORIENTATION_BOTTOM,
-    };
-
-    class Id
-    {
-    public:
-        Id();
-        ImU32 GetId() const;
-        const char* GetStr() const;
-
-    private:
-        ImU32 m_iId;
-        char  m_pId[11];
-        static int s_iNextId;
-    };
-
-    class Window
-    {
-        friend class WindowManager;
-        friend class Container;
-
-    public:
-        virtual void OnGui() = 0;
-        virtual void OnMenu() {};
-
-        const char* GetId() const { return m_oId.GetStr(); }
-
-        void Destroy();
-
-        void SetTitle(const char* pTitle);
-        const char* GetTitle() const;
-
-        const ImVec2& GetLastPosition() const;
-        const ImVec2& GetLastSize() const;
-
-    protected:
-        Window();
-        virtual ~Window();
-
-        char* m_pTitle;
-        Id m_oId;
-
-        ImVec2 m_oLastPosition;
-        ImVec2 m_oLastSize;
-    };
-
-    typedef ImwList<Window*> WindowList;
-
-    class PlatformWindow;
-
-    class Container
-    {
-        friend class PlatformWindow;
-
-    public:
-        void Dock(Window* pWindow,EDockOrientation eOrientation = E_DOCK_ORIENTATION_CENTER);
-        bool UnDock(Window* pWindow);
-
-        bool IsEmpty();
-        bool IsSplit();
-        bool HasWindowTabbed();
-        Container* HasWindow(const Window* pWindow);
-        PlatformWindow* GetPlatformWindowParent() const;
-        Container* GetBestDocking(const ImVec2 oCursorPosInContainer,EDockOrientation& oOutOrientation,ImVec2& oOutAreaPos,ImVec2& oOutAreaSize);
-
-    protected:
-        Container(Container* pParent);
-        Container(PlatformWindow* pParent);
-        ~Container();
-
-        void CreateSplits();
-        void Paint();
-
-        Container* m_pParent;
-        PlatformWindow* m_pParentWindow;
-        WindowList m_lWindows;
-        Container* m_pSplits[2];
-
-        float m_fSplitRatio;
-        bool m_bVerticalSplit;
-        int m_iActiveWindow;
-
-        bool m_bIsDrag;
-
-        ImVec2 m_oLastPosition;
-        ImVec2 m_oLastSize;
-    };
-
-    class PlatformWindow
-    {
-        friend class WindowManager;
-
-    public:
-        PlatformWindow(bool bMainWindow,bool bIsDragWindow);
-        virtual ~PlatformWindow();
-
-        virtual bool Init(PlatformWindow* pParent) = 0;
-
-        virtual const ImVec2& GetPosition() const = 0;
-        virtual const ImVec2& GetSize() const = 0;
-
-        virtual void Show() = 0;
-        virtual void Hide() = 0;
-        virtual void SetSize(const ImVec2& size) = 0;
-        virtual void SetPosition(const ImVec2& pos) = 0;
-        virtual void SetTitle(const char* pTitle) = 0;
-
-        bool IsMain();
-
-        void Dock(Window* pWindow);
-        bool UnDock(Window* pWindow);
-
-        Container* GetContainer();
-        Container* HasWindow(Window* pWindow);
-        bool IsStateSet();
-
-    protected:
-        void SetState();
-        void RestoreState();
-        void OnLoseFocus();
-        virtual void PreUpdate() = 0;
-        virtual void PaintBegin() = 0;
-        virtual void Paint();
-        virtual void PaintEnd() = 0;
-        virtual void Destroy() = 0;
-        virtual void StartDrag() = 0;
-        virtual void StopDrag() = 0;
-        virtual bool IsDraging() = 0;
-
-        void PaintContainer();
-        void OnClose();
-
-        Id m_oId;
-        bool m_bMain;
-        bool m_bIsDragWindow;
-        Container* m_pContainer;
-        ImGuiContext* m_pState;
-        ImGuiContext* m_pPreviousState;
-    };
-
-    typedef ImwList<PlatformWindow*> PlatformWindowList;
-
-    class WindowManager
-    {
-        friend class Window;
-        friend class PlatformWindow;
-        friend class Container;
-
-        struct PlatformWindowAction
-        {
-            PlatformWindow* m_pPlatformWindow;
-            unsigned int m_iFlags;
-            ImVec2 m_oPosition;
-            ImVec2 m_oSize;
-        };
-
-        struct DockAction
-        {
-            Window* m_pWindow;
-
-            // Is Dock or Float
-            bool m_bFloat;
-
-            //For Docking
-            Window* m_pWith;
-            EDockOrientation m_eOrientation;
-            PlatformWindow* m_pToPlatformWindow;
-            Container* m_pToContainer;
-
-            //For Floating
-            ImVec2 m_oPosition;
-            ImVec2 m_oSize;
-        };
-
-        struct DrawWindowAreaAction
-        {
-            DrawWindowAreaAction(PlatformWindow* pWindow,const ImVec2& oRectPos,const ImVec2& oRectSize,const ImColor& oColor);
-            PlatformWindow* m_pWindow;
-            ImVec2 m_oRectPos;
-            ImVec2 m_oRectSize;
-            ImColor m_oColor;
-        };
-
-    public:
-        struct Config
-        {
-            Config();
-            float m_fDragMarginRatio;
-            float m_fDragMarginSizeRatio;
-            ImColor m_oHightlightAreaColor;
-        };
-
-        WindowManager();
-        virtual ~WindowManager();
-
-        bool Init();
-        bool Run();
-        void Exit();
-
-        PlatformWindow* GetMainPlatformWindow();
-        Config& GetConfig();
-
-        void SetMainTitle(const char* pTitle);
-
-        void Dock(Window* pWindow, EDockOrientation eOrientation = E_DOCK_ORIENTATION_CENTER, PlatformWindow* pToPlatformWindow = NULL);
-        void DockTo(Window* pWindow, EDockOrientation eOrientation = E_DOCK_ORIENTATION_CENTER, Container* pContainer = NULL);
-        void DockWith(Window* pWindow, Window* pWithWindow,EDockOrientation eOrientation = E_DOCK_ORIENTATION_CENTER);
-        void Float(Window* pWindow, const ImVec2& oPosition = ImVec2(-1,-1), const ImVec2& oSize = ImVec2(-1,-1));
-
-        const WindowList& GetWindowList() const;
-        PlatformWindow* GetCurrentPlatformWindow();
-        PlatformWindow* GetWindowParent(Window* pWindow);
-
-        void Log(const char* pFormat, ...);
-        virtual void LogFormatted(const char* pStr) = 0;;
-
-        static WindowManager* GetInstance();
-
-    protected:
-        virtual PlatformWindow* CreatePlatformWindow(bool bMain,PlatformWindow* pParent,bool bDragWindow) = 0;
-        virtual void InternalRun() = 0;
-
-        void AddWindow(Window* pWindow);
-        void RemoveWindow(Window* pWindow);
-        void DestroyWindow(Window* pWindow);
-
-        void InternalDock(Window* pWindow,EDockOrientation eOrientation,PlatformWindow* pToPlatformWindow);
-        void InternalDockTo(Window* pWindow,EDockOrientation eOrientation,Container* pToContainer);
-        void InternalDockWith(Window* pWindow,Window* pWithWindow,EDockOrientation eOrientation);
-        bool InternalFloat(Window* pWindow,ImVec2 oPosition,ImVec2 oSize);
-        void InternalUnDock(Window* pWindow);
-        void InternalDrag(Window* pWindow);
-
-        void OnClosePlatformWindow(PlatformWindow* pWindow);
-
-        void DrawWindowArea(PlatformWindow* pWindow,const ImVec2& oPos,const ImVec2& oSize,const ImColor& oColor);
-
-        void PreUpdate();
-        void Update();
-        void UpdatePlatformwWindowActions();
-        void UpdateDockActions();
-        void UpdateOrphans();
-
-        void Paint(PlatformWindow* pWindow);
-
-        void StartDragWindow(Window* pWindow);
-        void StopDragWindow();
-        void UpdateDragWindow();
-        Container* GetBestDocking(PlatformWindow* pPlatformWindow,const ImVec2 oCursorPos,EDockOrientation& oOutOrientation,ImVec2& oOutAreaPos,ImVec2& oOutAreaSize);
-
-        Config m_oConfig;
-        PlatformWindow* m_pMainPlatformWindow;
-        PlatformWindowList m_lPlatformWindows;
-        PlatformWindow* m_pDragPlatformWindow;
-        WindowList m_lWindows;
-        WindowList m_lOrphanWindows;
-        WindowList m_lToDestroyWindows;
-        PlatformWindowList m_lToDestroyPlatformWindows;
-        ImwList<PlatformWindowAction*> m_lPlatformWindowActions;
-        ImwList<DockAction*> m_lDockActions;
-        ImwList<DrawWindowAreaAction> m_lDrawWindowAreas;
-
-        PlatformWindow* m_pCurrentPlatformWindow;
-        Window* m_pDraggedWindow;
-
-        ImVec2 m_oDragPreviewOffset;
-
-        static WindowManager* s_pInstance;
-    };
-}
-
-#endif // IMGUI_WM_H_HEADER_GUARD

+ 21 - 0
3rdparty/ocornut-imgui/widgets/dock.h

@@ -0,0 +1,21 @@
+namespace ImGui
+{
+	///
+	IMGUI_API void InitDockContext();
+
+	///
+	IMGUI_API void ShutdownDockContext();
+
+	///
+	IMGUI_API void RootDock(const ImVec2& pos, const ImVec2& size);
+
+	///
+	IMGUI_API bool BeginDock(const char* label, bool* opened = NULL, ImGuiWindowFlags extra_flags = 0);
+
+	///
+	IMGUI_API void EndDock();
+
+	///
+	IMGUI_API void SetDockActive();
+
+} // namespace ImGui

+ 1084 - 0
3rdparty/ocornut-imgui/widgets/dock.inl

@@ -0,0 +1,1084 @@
+// https://github.com/vassvik/imgui_docking_minimal/
+//
+// This is free and unencumbered software released into the public domain.
+//
+// Anyone is free to copy, modify, publish, use, compile, sell, or
+// distribute this software, either in source code form or as a compiled
+// binary, for any purpose, commercial or non-commercial, and by any
+// means.
+//
+// In jurisdictions that recognize copyright laws, the author or authors
+// of this software dedicate any and all copyright interest in the
+// software to the public domain. We make this dedication for the benefit
+// of the public at large and to the detriment of our heirs and
+// successors. We intend this dedication to be an overt act of
+// relinquishment in perpetuity of all present and future rights to this
+// software under copyright law.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+// For more information, please refer to <http://unlicense.org>
+
+#include <new> // placement new
+
+namespace ImGui
+{
+	struct DockContext
+	{
+		enum Slot_
+		{
+			Slot_Left,
+			Slot_Right,
+			Slot_Top,
+			Slot_Bottom,
+			Slot_Tab,
+
+			Slot_Float,
+			Slot_None
+		};
+
+		enum EndAction_
+		{
+			EndAction_None,
+			EndAction_Panel,
+			EndAction_End,
+			EndAction_EndChild
+		};
+
+		enum Status_
+		{
+			Status_Docked,
+			Status_Float,
+			Status_Dragged
+		};
+
+		struct Dock
+		{
+			Dock()
+				: id(0)
+				, label(NULL)
+				, next_tab(NULL)
+				, prev_tab(NULL)
+				, parent(NULL)
+				, pos(0, 0)
+				, size(-1, -1)
+				, active(true)
+				, status(Status_Float)
+				, opened(false)
+			{
+				location[0] = 0;
+				children[0] = children[1] = NULL;
+			}
+
+			~Dock()
+			{
+				MemFree(label);
+			}
+
+			ImVec2 getMinSize() const
+			{
+				if (!children[0]) return ImVec2(16, 16 + GetTextLineHeightWithSpacing());
+
+				ImVec2 s0 = children[0]->getMinSize();
+				ImVec2 s1 = children[1]->getMinSize();
+				return isHorizontal() ? ImVec2(s0.x + s1.x, ImMax(s0.y, s1.y))
+					: ImVec2(ImMax(s0.x, s1.x), s0.y + s1.y);
+			}
+
+			bool isHorizontal() const
+			{
+				return children[0]->pos.x < children[1]->pos.x;
+			}
+
+			void setParent(Dock* dock)
+			{
+				parent = dock;
+				for (Dock* tmp = prev_tab; tmp; tmp = tmp->prev_tab) tmp->parent = dock;
+				for (Dock* tmp = next_tab; tmp; tmp = tmp->next_tab) tmp->parent = dock;
+			}
+
+			Dock& getSibling()
+			{
+				IM_ASSERT(parent);
+				if (parent->children[0] == &getFirstTab()) return *parent->children[1];
+				return *parent->children[0];
+			}
+
+			Dock& getFirstTab()
+			{
+				Dock* tmp = this;
+				while (tmp->prev_tab) tmp = tmp->prev_tab;
+				return *tmp;
+			}
+
+			void setActive()
+			{
+				active = true;
+				for (Dock* tmp = prev_tab; tmp; tmp = tmp->prev_tab) tmp->active = false;
+				for (Dock* tmp = next_tab; tmp; tmp = tmp->next_tab) tmp->active = false;
+			}
+
+			bool isContainer() const
+			{
+				return children[0] != NULL;
+			}
+
+			void setChildrenPosSize(const ImVec2& _pos, const ImVec2& _size)
+			{
+				ImVec2 s = children[0]->size;
+				if (isHorizontal())
+				{
+					s.y = _size.y;
+					s.x = (float)int(
+							_size.x * children[0]->size.x / (children[0]->size.x + children[1]->size.x));
+					if (s.x < children[0]->getMinSize().x)
+					{
+						s.x = children[0]->getMinSize().x;
+					}
+					else if (_size.x - s.x < children[1]->getMinSize().x)
+					{
+						s.x = _size.x - children[1]->getMinSize().x;
+					}
+					children[0]->setPosSize(_pos, s);
+
+					s.x = _size.x - children[0]->size.x;
+					ImVec2 p = _pos;
+					p.x += children[0]->size.x;
+					children[1]->setPosSize(p, s);
+				}
+				else
+				{
+					s.x = _size.x;
+					s.y = (float)int(
+							_size.y * children[0]->size.y / (children[0]->size.y + children[1]->size.y));
+					if (s.y < children[0]->getMinSize().y)
+					{
+						s.y = children[0]->getMinSize().y;
+					}
+					else if (_size.y - s.y < children[1]->getMinSize().y)
+					{
+						s.y = _size.y - children[1]->getMinSize().y;
+					}
+					children[0]->setPosSize(_pos, s);
+
+					s.y = _size.y - children[0]->size.y;
+					ImVec2 p = _pos;
+					p.y += children[0]->size.y;
+					children[1]->setPosSize(p, s);
+				}
+			}
+
+			void setPosSize(const ImVec2& _pos, const ImVec2& _size)
+			{
+				size = _size;
+				pos = _pos;
+				for (Dock* tmp = prev_tab; tmp; tmp = tmp->prev_tab)
+				{
+					tmp->size = _size;
+					tmp->pos = _pos;
+				}
+				for (Dock* tmp = next_tab; tmp; tmp = tmp->next_tab)
+				{
+					tmp->size = _size;
+					tmp->pos = _pos;
+				}
+
+				if (!isContainer()) return;
+				setChildrenPosSize(_pos, _size);
+			}
+
+			ImU32   id;
+			char*   label;
+			Dock*   next_tab;
+			Dock*   prev_tab;
+			Dock*   parent;
+			ImVec2  pos;
+			ImVec2  size;
+			bool    active;
+			Status_ status;
+			bool    opened;
+
+			Dock* children[2];
+			char  location[16];
+			int   last_frame;
+			int   invalid_frames;
+			bool  first;
+		};
+
+		typedef ImVector<Dock*> DockVector;
+		DockVector m_docks;
+		ImVec2 m_drag_offset;
+		Dock* m_current;
+		int m_last_frame;
+		EndAction_ m_end_action;
+
+		DockContext()
+			: m_current(NULL)
+			, m_last_frame(0)
+		{
+		}
+
+		~DockContext()
+		{
+		}
+
+		Dock& getDock(const char* label, bool opened)
+		{
+			ImU32 id = ImHash(label, 0);
+			for (int i = 0; i < m_docks.size(); ++i)
+			{
+				if (m_docks[i]->id == id) return *m_docks[i];
+			}
+
+			Dock* new_dock = (Dock*)MemAlloc(sizeof(Dock));
+			IM_PLACEMENT_NEW(new_dock) Dock();
+			m_docks.push_back(new_dock);
+			new_dock->label = ImStrdup(label);
+			IM_ASSERT(new_dock->label);
+			new_dock->id = id;
+			new_dock->setActive();
+			new_dock->status = Status_Float;
+			new_dock->pos = ImVec2(0, 0);
+			new_dock->size = GetIO().DisplaySize;
+			new_dock->opened = opened;
+			new_dock->first = true;
+			new_dock->last_frame = 0;
+			new_dock->invalid_frames = 0;
+			new_dock->location[0] = 0;
+			return *new_dock;
+		}
+
+		void putInBackground()
+		{
+			ImGuiWindow* win = GetCurrentWindow();
+			ImGuiContext& g = *GImGui;
+			if (g.Windows[0] == win) return;
+
+			for (int i = 0; i < g.Windows.Size; i++)
+			{
+				if (g.Windows[i] == win)
+				{
+					for (int j = i - 1; j >= 0; --j)
+					{
+						g.Windows[j + 1] = g.Windows[j];
+					}
+					g.Windows[0] = win;
+					break;
+				}
+			}
+		}
+
+		void splits()
+		{
+			if (GetFrameCount() == m_last_frame)
+			{
+				return;
+			}
+
+			m_last_frame = GetFrameCount();
+
+			putInBackground();
+
+			ImU32 color = GetColorU32(ImGuiCol_Button);
+			ImU32 color_hovered = GetColorU32(ImGuiCol_ButtonHovered);
+			ImDrawList* draw_list = GetWindowDrawList();
+			ImGuiIO& io = GetIO();
+			for (int i = 0; i < m_docks.size(); ++i)
+			{
+				Dock& dock = *m_docks[i];
+				if (!dock.isContainer())
+				{
+					continue;
+				}
+
+				PushID(i);
+				if (!IsMouseDown(0))
+				{
+					dock.status = Status_Docked;
+				}
+
+				ImVec2 dsize(0, 0);
+				SetCursorScreenPos(dock.children[1]->pos);
+				ImVec2 min_size0 = dock.children[0]->getMinSize();
+				ImVec2 min_size1 = dock.children[1]->getMinSize();
+				if (dock.isHorizontal())
+				{
+					InvisibleButton("split", ImVec2(3, dock.size.y));
+					if (dock.status == Status_Dragged) dsize.x = io.MouseDelta.x;
+					dsize.x = -ImMin(-dsize.x, dock.children[0]->size.x - min_size0.x);
+					dsize.x = ImMin(dsize.x, dock.children[1]->size.x - min_size1.x);
+				}
+				else
+				{
+					InvisibleButton("split", ImVec2(dock.size.x, 3));
+					if (dock.status == Status_Dragged) dsize.y = io.MouseDelta.y;
+					dsize.y = -ImMin(-dsize.y, dock.children[0]->size.y - min_size0.y);
+					dsize.y = ImMin(dsize.y, dock.children[1]->size.y - min_size1.y);
+				}
+				ImVec2 new_size0 = dock.children[0]->size + dsize;
+				ImVec2 new_size1 = dock.children[1]->size - dsize;
+				ImVec2 new_pos1 = dock.children[1]->pos + dsize;
+				dock.children[0]->setPosSize(dock.children[0]->pos, new_size0);
+				dock.children[1]->setPosSize(new_pos1, new_size1);
+
+				if (IsItemHovered() && IsMouseClicked(0))
+				{
+					dock.status = Status_Dragged;
+				}
+
+				draw_list->AddRectFilled(
+						GetItemRectMin(), GetItemRectMax(), IsItemHovered() ? color_hovered : color);
+				PopID();
+			}
+		}
+
+		void checkNonexistent()
+		{
+			int frame_limit = ImMax(0, ImGui::GetFrameCount() - 2);
+			for (DockVector::iterator it = m_docks.begin(), itEnd = m_docks.end(); it != itEnd; ++it)
+			{
+				Dock* dock = *it;
+				if (dock->isContainer()) continue;
+				if (dock->status == Status_Float) continue;
+				if (dock->last_frame < frame_limit)
+				{
+					++dock->invalid_frames;
+					if (dock->invalid_frames > 2)
+					{
+						doUndock(*dock);
+						dock->status = Status_Float;
+					}
+					return;
+				}
+				dock->invalid_frames = 0;
+			}
+		}
+
+		void beginPanel()
+		{
+			ImGuiWindowFlags flags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize |
+				ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse |
+				ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoScrollbar |
+				ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_ShowBorders | 
+				ImGuiWindowFlags_NoBringToFrontOnFocus;
+			Dock* root = getRootDock();
+			if (root)
+			{
+				SetNextWindowPos(root->pos);
+				SetNextWindowSize(root->size);
+			}
+			else
+			{
+				SetNextWindowPos(ImVec2(0, 0));
+				SetNextWindowSize(GetIO().DisplaySize);
+			}
+			ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0);
+			Begin("###DockPanel", NULL, flags);
+			splits();
+
+			checkNonexistent();
+		}
+
+		void endPanel()
+		{
+			End();
+			ImGui::PopStyleVar();
+		}
+
+		// Doesn't use input??
+		Dock* getDockAt(const ImVec2& /*pos*/) const
+		{
+			for (int i = 0; i < m_docks.size(); ++i)
+			{
+				Dock& dock = *m_docks[i];
+				if (dock.isContainer()) continue;
+				if (dock.status != Status_Docked) continue;
+				if (IsMouseHoveringRect(dock.pos, dock.pos + dock.size, false))
+				{
+					return &dock;
+				}
+			}
+
+			return NULL;
+		}
+
+		static ImRect getDockedRect(const ImRect& rect, Slot_ dock_slot)
+		{
+			ImVec2 half_size = rect.GetSize() * 0.5f;
+			switch (dock_slot)
+			{
+				default: return rect;
+				case Slot_Top: return ImRect(rect.Min, rect.Min + ImVec2(rect.Max.x, half_size.y));
+				case Slot_Right: return ImRect(rect.Min + ImVec2(half_size.x, 0), rect.Max);
+				case Slot_Bottom: return ImRect(rect.Min + ImVec2(0, half_size.y), rect.Max);
+				case Slot_Left: return ImRect(rect.Min, rect.Min + ImVec2(half_size.x, rect.Max.y));
+			}
+		}
+
+		static ImRect getSlotRect(ImRect parent_rect, Slot_ dock_slot)
+		{
+			ImVec2 size = parent_rect.Max - parent_rect.Min;
+			ImVec2 center = parent_rect.Min + size * 0.5f;
+			switch (dock_slot)
+			{
+				default: return ImRect(center - ImVec2(20, 20), center + ImVec2(20, 20));
+				case Slot_Top: return ImRect(center + ImVec2(-20, -50), center + ImVec2(20, -30));
+				case Slot_Right: return ImRect(center + ImVec2(30, -20), center + ImVec2(50, 20));
+				case Slot_Bottom: return ImRect(center + ImVec2(-20, +30), center + ImVec2(20, 50));
+				case Slot_Left: return ImRect(center + ImVec2(-50, -20), center + ImVec2(-30, 20));
+			}
+		}
+
+		static ImRect getSlotRectOnBorder(ImRect parent_rect, Slot_ dock_slot)
+		{
+			ImVec2 size = parent_rect.Max - parent_rect.Min;
+			ImVec2 center = parent_rect.Min + size * 0.5f;
+			switch (dock_slot)
+			{
+				case Slot_Top:
+					return ImRect(ImVec2(center.x - 20, parent_rect.Min.y + 10),
+							ImVec2(center.x + 20, parent_rect.Min.y + 30));
+				case Slot_Left:
+					return ImRect(ImVec2(parent_rect.Min.x + 10, center.y - 20),
+							ImVec2(parent_rect.Min.x + 30, center.y + 20));
+				case Slot_Bottom:
+					return ImRect(ImVec2(center.x - 20, parent_rect.Max.y - 30),
+							ImVec2(center.x + 20, parent_rect.Max.y - 10));
+				case Slot_Right:
+					return ImRect(ImVec2(parent_rect.Max.x - 30, center.y - 20),
+							ImVec2(parent_rect.Max.x - 10, center.y + 20));
+				default: IM_ASSERT(false);
+			}
+			IM_ASSERT(false);
+			return ImRect();
+		}
+
+		Dock* getRootDock()
+		{
+			for (int i = 0; i < m_docks.size(); ++i)
+			{
+				if (!m_docks[i]->parent &&
+						(m_docks[i]->status == Status_Docked || m_docks[i]->children[0]))
+				{
+					return m_docks[i];
+				}
+			}
+			return NULL;
+		}
+
+		bool dockSlots(Dock& dock, Dock* dest_dock, const ImRect& rect, bool on_border)
+		{
+			ImDrawList* canvas = GetWindowDrawList();
+			ImU32 color = GetColorU32(ImGuiCol_Button);
+			ImU32 color_hovered = GetColorU32(ImGuiCol_ButtonHovered);
+			ImVec2 mouse_pos = GetIO().MousePos;
+			for (int i = 0; i < (on_border ? 4 : 5); ++i)
+			{
+				ImRect r =
+					on_border ? getSlotRectOnBorder(rect, (Slot_)i) : getSlotRect(rect, (Slot_)i);
+				bool hovered = r.Contains(mouse_pos);
+
+				canvas->AddRectFilled(r.Min, r.Max, hovered ? color_hovered : color);
+				if (!hovered) continue;
+
+				if (!IsMouseDown(0))
+				{
+					doDock(dock, dest_dock ? dest_dock : getRootDock(), (Slot_)i);
+					return true;
+				}
+				ImRect docked_rect = getDockedRect(rect, (Slot_)i);
+				canvas->AddRectFilled(docked_rect.Min, docked_rect.Max, GetColorU32(ImGuiCol_Button));
+			}
+			return false;
+		}
+
+		void handleDrag(Dock& dock)
+		{
+			Dock* dest_dock = getDockAt(GetIO().MousePos);
+
+			Begin("##Overlay",
+					NULL,
+					ImVec2(0, 0),
+					0.f,
+					ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoMove |
+					ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings |
+					ImGuiWindowFlags_AlwaysAutoResize);
+			ImDrawList* canvas = GetWindowDrawList();
+
+			canvas->PushClipRectFullScreen();
+
+			ImU32 docked_color = GetColorU32(ImGuiCol_FrameBg);
+			docked_color = (docked_color & 0x00ffFFFF) | 0x80000000;
+			dock.pos = GetIO().MousePos - m_drag_offset;
+			if (dest_dock)
+			{
+				if (dockSlots(dock,
+							dest_dock,
+							ImRect(dest_dock->pos, dest_dock->pos + dest_dock->size),
+							false))
+				{
+					canvas->PopClipRect();
+					End();
+					return;
+				}
+			}
+			if (dockSlots(dock, NULL, ImRect(ImVec2(0, 0), GetIO().DisplaySize), true))
+			{
+				canvas->PopClipRect();
+				End();
+				return;
+			}
+			canvas->AddRectFilled(dock.pos, dock.pos + dock.size, docked_color);
+			canvas->PopClipRect();
+
+			if (!IsMouseDown(0))
+			{
+				dock.status = Status_Float;
+				dock.location[0] = 0;
+				dock.setActive();
+			}
+
+			End();
+		}
+
+		void fillLocation(Dock& dock)
+		{
+			if (dock.status == Status_Float) return;
+			char* c = dock.location;
+			Dock* tmp = &dock;
+			while (tmp->parent)
+			{
+				*c = getLocationCode(tmp);
+				tmp = tmp->parent;
+				++c;
+			}
+			*c = 0;
+		}
+
+		void doUndock(Dock& dock)
+		{
+			if (dock.prev_tab)
+				dock.prev_tab->setActive();
+			else if (dock.next_tab)
+				dock.next_tab->setActive();
+			else
+				dock.active = false;
+			Dock* container = dock.parent;
+
+			if (container)
+			{
+				Dock& sibling = dock.getSibling();
+				if (container->children[0] == &dock)
+				{
+					container->children[0] = dock.next_tab;
+				}
+				else if (container->children[1] == &dock)
+				{
+					container->children[1] = dock.next_tab;
+				}
+
+				bool remove_container = !container->children[0] || !container->children[1];
+				if (remove_container)
+				{
+					if (container->parent)
+					{
+						Dock*& child = container->parent->children[0] == container
+							? container->parent->children[0]
+							: container->parent->children[1];
+						child = &sibling;
+						child->setPosSize(container->pos, container->size);
+						child->setParent(container->parent);
+					}
+					else
+					{
+						if (container->children[0])
+						{
+							container->children[0]->setParent(NULL);
+							container->children[0]->setPosSize(container->pos, container->size);
+						}
+						if (container->children[1])
+						{
+							container->children[1]->setParent(NULL);
+							container->children[1]->setPosSize(container->pos, container->size);
+						}
+					}
+					for (int i = 0; i < m_docks.size(); ++i)
+					{
+						if (m_docks[i] == container)
+						{
+							m_docks.erase(m_docks.begin() + i);
+							break;
+						}
+					}
+					container->~Dock();
+					MemFree(container);
+				}
+			}
+			if (dock.prev_tab) dock.prev_tab->next_tab = dock.next_tab;
+			if (dock.next_tab) dock.next_tab->prev_tab = dock.prev_tab;
+			dock.parent = NULL;
+			dock.prev_tab = dock.next_tab = NULL;
+		}
+
+		void drawTabbarListButton(Dock& dock)
+		{
+			if (!dock.next_tab) return;
+
+			ImDrawList* draw_list = GetWindowDrawList();
+			if (InvisibleButton("list", ImVec2(16, 16)))
+			{
+				OpenPopup("tab_list_popup");
+			}
+			if (BeginPopup("tab_list_popup"))
+			{
+				Dock* tmp = &dock;
+				while (tmp)
+				{
+					bool dummy = false;
+					if (Selectable(tmp->label, &dummy))
+					{
+						tmp->setActive();
+					}
+					tmp = tmp->next_tab;
+				}
+				EndPopup();
+			}
+
+			bool hovered = IsItemHovered();
+			ImVec2 min = GetItemRectMin();
+			ImVec2 max = GetItemRectMax();
+			ImVec2 center = (min + max) * 0.5f;
+			ImU32 text_color = GetColorU32(ImGuiCol_Text);
+			ImU32 color_active = GetColorU32(ImGuiCol_FrameBgActive);
+			draw_list->AddRectFilled(ImVec2(center.x - 4, min.y + 3),
+					ImVec2(center.x + 4, min.y + 5),
+					hovered ? color_active : text_color);
+			draw_list->AddTriangleFilled(ImVec2(center.x - 4, min.y + 7),
+					ImVec2(center.x + 4, min.y + 7),
+					ImVec2(center.x, min.y + 12),
+					hovered ? color_active : text_color);
+		}
+
+		bool tabbar(Dock& dock, bool close_button)
+		{
+			float tabbar_height = 2 * GetTextLineHeightWithSpacing();
+			ImVec2 size0(dock.size.x, tabbar_height);
+			bool tab_closed = false;
+
+			SetCursorScreenPos(dock.pos);
+			char tmp[20];
+			ImFormatString(tmp, IM_ARRAYSIZE(tmp), "tabs%d", (int)dock.id);
+			if (BeginChild(tmp, size0, true))
+			{
+				Dock* dock_tab = &dock;
+
+				ImDrawList* draw_list = GetWindowDrawList();
+				ImU32 color = GetColorU32(ImGuiCol_FrameBg);
+				ImU32 color_active = GetColorU32(ImGuiCol_FrameBgActive);
+				ImU32 color_hovered = GetColorU32(ImGuiCol_FrameBgHovered);
+				ImU32 text_color = GetColorU32(ImGuiCol_Text);
+				ImU32 text_color_disabled = GetColorU32(ImGuiCol_TextDisabled);
+				float line_height = GetTextLineHeightWithSpacing();
+				float tab_base;
+
+				drawTabbarListButton(dock);
+
+				while (dock_tab)
+				{
+					SameLine(0, 15);
+
+					const char* text_end = FindRenderedTextEnd(dock_tab->label);
+					ImVec2 size1(CalcTextSize(dock_tab->label, text_end).x, line_height);
+					if (InvisibleButton(dock_tab->label, size1))
+					{
+						dock_tab->setActive();
+					}
+
+					if (IsItemActive() && IsMouseDragging())
+					{
+						m_drag_offset = GetMousePos() - dock_tab->pos;
+						doUndock(*dock_tab);
+						dock_tab->status = Status_Dragged;
+					}
+
+					bool hovered = IsItemHovered();
+					ImVec2 pos = GetItemRectMin();
+					size1.x += 20 + GetStyle().ItemSpacing.x;
+
+					tab_base = pos.y;
+
+					draw_list->AddRectFilled(pos+ImVec2(-8.0f, 0.0),
+							pos+size1,
+							hovered ? color_hovered : (dock_tab->active ? color_active : color));
+					draw_list->AddText(pos, text_color, dock_tab->label, text_end);
+
+					if (dock_tab->active && close_button)
+					{
+						SameLine();
+						tab_closed = InvisibleButton("close", ImVec2(16, 16));
+
+						ImVec2 center = ((GetItemRectMin() + GetItemRectMax()) * 0.5f);
+						draw_list->AddLine( center + ImVec2(-3.5f, -3.5f), center + ImVec2(3.5f, 3.5f), text_color);
+						draw_list->AddLine( center + ImVec2(3.5f, -3.5f), center + ImVec2(-3.5f, 3.5f), text_color);
+					} else {
+						if(!dock_tab->active && close_button) {
+							SameLine();
+							InvisibleButton("close", ImVec2(16, 16));
+
+							ImVec2 center = ((GetItemRectMin() + GetItemRectMax()) * 0.5f);
+							draw_list->AddLine( center + ImVec2(-3.5f, -3.5f), center + ImVec2(3.5f, 3.5f), text_color_disabled);
+							draw_list->AddLine( center + ImVec2(3.5f, -3.5f), center + ImVec2(-3.5f, 3.5f), text_color_disabled);
+						}
+					}
+
+					dock_tab = dock_tab->next_tab;
+				}
+				ImVec2 cp(dock.pos.x, tab_base + line_height);
+				draw_list->AddLine(cp, cp + ImVec2(dock.size.x, 0), color);
+			}
+			EndChild();
+			return tab_closed;
+		}
+
+		static void setDockPosSize(Dock& dest, Dock& dock, Slot_ dock_slot, Dock& container)
+		{
+			IM_ASSERT(!dock.prev_tab && !dock.next_tab && !dock.children[0] && !dock.children[1]);
+
+			dest.pos = container.pos;
+			dest.size = container.size;
+			dock.pos = container.pos;
+			dock.size = container.size;
+
+			switch (dock_slot)
+			{
+				case Slot_Bottom:
+					dest.size.y *= 0.5f;
+					dock.size.y *= 0.5f;
+					dock.pos.y += dest.size.y;
+					break;
+				case Slot_Right:
+					dest.size.x *= 0.5f;
+					dock.size.x *= 0.5f;
+					dock.pos.x += dest.size.x;
+					break;
+				case Slot_Left:
+					dest.size.x *= 0.5f;
+					dock.size.x *= 0.5f;
+					dest.pos.x += dock.size.x;
+					break;
+				case Slot_Top:
+					dest.size.y *= 0.5f;
+					dock.size.y *= 0.5f;
+					dest.pos.y += dock.size.y;
+					break;
+				default: IM_ASSERT(false); break;
+			}
+			dest.setPosSize(dest.pos, dest.size);
+
+			if (container.children[1]->pos.x < container.children[0]->pos.x ||
+					container.children[1]->pos.y < container.children[0]->pos.y)
+			{
+				Dock* tmp = container.children[0];
+				container.children[0] = container.children[1];
+				container.children[1] = tmp;
+			}
+		}
+
+		void doDock(Dock& dock, Dock* dest, Slot_ dock_slot)
+		{
+			IM_ASSERT(!dock.parent);
+			if (!dest)
+			{
+				dock.status = Status_Docked;
+				dock.setPosSize(ImVec2(0, 0), GetIO().DisplaySize);
+			}
+			else if (dock_slot == Slot_Tab)
+			{
+				Dock* tmp = dest;
+				while (tmp->next_tab)
+				{
+					tmp = tmp->next_tab;
+				}
+
+				tmp->next_tab = &dock;
+				dock.prev_tab = tmp;
+				dock.size = tmp->size;
+				dock.pos = tmp->pos;
+				dock.parent = dest->parent;
+				dock.status = Status_Docked;
+			}
+			else if (dock_slot == Slot_None)
+			{
+				dock.status = Status_Float;
+			}
+			else
+			{
+				Dock* container = (Dock*)MemAlloc(sizeof(Dock));
+				IM_PLACEMENT_NEW(container) Dock();
+				m_docks.push_back(container);
+				container->children[0] = &dest->getFirstTab();
+				container->children[1] = &dock;
+				container->next_tab = NULL;
+				container->prev_tab = NULL;
+				container->parent = dest->parent;
+				container->size = dest->size;
+				container->pos = dest->pos;
+				container->status = Status_Docked;
+				container->label = ImStrdup("");
+
+				if (!dest->parent)
+				{
+				}
+				else if (&dest->getFirstTab() == dest->parent->children[0])
+				{
+					dest->parent->children[0] = container;
+				}
+				else
+				{
+					dest->parent->children[1] = container;
+				}
+
+				dest->setParent(container);
+				dock.parent = container;
+				dock.status = Status_Docked;
+
+				setDockPosSize(*dest, dock, dock_slot, *container);
+			}
+			dock.setActive();
+		}
+
+		void rootDock(const ImVec2& pos, const ImVec2& size)
+		{
+			Dock* root = getRootDock();
+			if (!root) return;
+
+			ImVec2 min_size = root->getMinSize();
+			ImVec2 requested_size = size;
+			root->setPosSize(pos, ImMax(min_size, requested_size));
+		}
+
+		void setDockActive()
+		{
+			IM_ASSERT(m_current);
+			if (m_current) m_current->setActive();
+		}
+
+		static Slot_ getSlotFromLocationCode(char code)
+		{
+			switch (code)
+			{
+				case '1': return Slot_Left;
+				case '2': return Slot_Top;
+				case '3': return Slot_Bottom;
+				default: return Slot_Right;
+			}
+		}
+
+		static char getLocationCode(Dock* dock)
+		{
+			if (!dock) return '0';
+
+			if (dock->parent->isHorizontal())
+			{
+				if (dock->pos.x < dock->parent->children[0]->pos.x) return '1';
+				if (dock->pos.x < dock->parent->children[1]->pos.x) return '1';
+				return '0';
+			}
+			else
+			{
+				if (dock->pos.y < dock->parent->children[0]->pos.y) return '2';
+				if (dock->pos.y < dock->parent->children[1]->pos.y) return '2';
+				return '3';
+			}
+		}
+
+		void tryDockToStoredLocation(Dock& dock)
+		{
+			if (dock.status == Status_Docked) return;
+			if (dock.location[0] == 0) return;
+
+			Dock* tmp = getRootDock();
+			if (!tmp) return;
+
+			Dock* prev = NULL;
+			char* c = dock.location + strlen(dock.location) - 1;
+			while (c >= dock.location && tmp)
+			{
+				prev = tmp;
+				tmp = *c == getLocationCode(tmp->children[0]) ? tmp->children[0] : tmp->children[1];
+				if(tmp) --c;
+			}
+			if (tmp && tmp->children[0]) tmp = tmp->parent;
+			doDock(dock, tmp ? tmp : prev, tmp && !tmp->children[0] ? Slot_Tab : getSlotFromLocationCode(*c));
+		}
+
+		bool begin(const char* label, bool* opened, ImGuiWindowFlags extra_flags)
+		{
+			Dock& dock = getDock(label, !opened || *opened);
+			if (!dock.opened && (!opened || *opened)) tryDockToStoredLocation(dock);
+			dock.last_frame = ImGui::GetFrameCount();
+			if (strcmp(dock.label, label) != 0)
+			{
+				MemFree(dock.label);
+				dock.label = ImStrdup(label);
+			}
+
+			m_end_action = EndAction_None;
+
+			if (dock.first && opened) *opened = dock.opened;
+			dock.first = false;
+			if (opened && !*opened)
+			{
+				if (dock.status != Status_Float)
+				{
+					fillLocation(dock);
+					doUndock(dock);
+					dock.status = Status_Float;
+				}
+				dock.opened = false;
+				return false;
+			}
+			dock.opened = true;
+
+			m_end_action = EndAction_Panel;
+			beginPanel();
+
+			m_current = &dock;
+			if (dock.status == Status_Dragged) handleDrag(dock);
+
+			bool is_float = dock.status == Status_Float;
+
+			if (is_float)
+			{
+				SetNextWindowPos(dock.pos);
+				SetNextWindowSize(dock.size);
+				bool ret = Begin(label,
+						opened,
+						dock.size,
+						-1.0f,
+						ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_ShowBorders | extra_flags);
+				m_end_action = EndAction_End;
+				dock.pos = GetWindowPos();
+				dock.size = GetWindowSize();
+
+				ImGuiContext& g = *GImGui;
+
+				if (g.ActiveId == GetCurrentWindow()->MoveId && g.IO.MouseDown[0])
+				{
+					m_drag_offset = GetMousePos() - dock.pos;
+					doUndock(dock);
+					dock.status = Status_Dragged;
+				}
+				return ret;
+			}
+
+			if (!dock.active && dock.status != Status_Dragged) return false;
+
+			m_end_action = EndAction_EndChild;
+
+			PushStyleColor(ImGuiCol_Border, ImVec4(0, 0, 0, 0));
+			PushStyleColor(ImGuiCol_BorderShadow, ImVec4(0, 0, 0, 0));
+			float tabbar_height = GetTextLineHeightWithSpacing();
+			if (tabbar(dock.getFirstTab(), opened != NULL))
+			{
+				fillLocation(dock);
+				*opened = false;
+			}
+			ImVec2 pos = dock.pos;
+			ImVec2 size = dock.size;
+			pos.y += tabbar_height + GetStyle().WindowPadding.y;
+			size.y -= tabbar_height + GetStyle().WindowPadding.y;
+
+			SetCursorScreenPos(pos);
+			ImGuiWindowFlags flags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize |
+				ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse |
+				ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoBringToFrontOnFocus |
+				extra_flags;
+			char tmp[256];
+			strcpy(tmp, label);
+			strcat(tmp, "_docked"); // to avoid https://github.com/ocornut/imgui/issues/713
+			bool ret = BeginChild(tmp, size, true, flags);
+			PopStyleColor();
+			PopStyleColor();
+			return ret;
+		}
+
+		void end()
+		{
+			if (m_end_action == EndAction_End)
+			{
+				End();
+			}
+			else if (m_end_action == EndAction_EndChild)
+			{
+				PushStyleColor(ImGuiCol_Border, ImVec4(0, 0, 0, 0));
+				PushStyleColor(ImGuiCol_BorderShadow, ImVec4(0, 0, 0, 0));
+				EndChild();
+				PopStyleColor();
+				PopStyleColor();
+			}
+			m_current = NULL;
+			if (m_end_action > EndAction_None) endPanel();
+		}
+
+		int getDockIndex(Dock* dock)
+		{
+			if (!dock) return -1;
+
+			for (int i = 0; i < m_docks.size(); ++i)
+			{
+				if (dock == m_docks[i]) return i;
+			}
+
+			IM_ASSERT(false);
+			return -1;
+		}
+
+		Dock* getDockByIndex(int idx)
+		{
+			return idx < 0 ? NULL : m_docks[(int)idx];
+		}
+	};
+
+	static DockContext* s_dock = NULL;
+
+	IMGUI_API void InitDockContext()
+	{
+		void* ptr = ImGui::MemAlloc(sizeof(DockContext) );
+		s_dock = new(ptr) DockContext;
+	}
+
+	IMGUI_API void ShutdownDockContext()
+	{
+		s_dock->~DockContext();
+		ImGui::MemFree(s_dock);
+		s_dock = NULL;
+	}
+
+	IMGUI_API void RootDock(const ImVec2& pos, const ImVec2& size)
+	{
+		s_dock->rootDock(pos, size);
+	}
+
+	IMGUI_API bool BeginDock(const char* label, bool* opened, ImGuiWindowFlags extra_flags)
+	{
+		return s_dock->begin(label, opened, extra_flags);
+	}
+
+	IMGUI_API void EndDock()
+	{
+		s_dock->end();
+	}
+
+	IMGUI_API void SetDockActive()
+	{
+		s_dock->setDockActive();
+	}
+
+} // namespace ImGui

+ 44 - 40
3rdparty/stb/stb_textedit.h

@@ -1,9 +1,10 @@
-// [ImGui] this is a slightly modified version of stb_truetype.h 1.8
+// [ImGui] this is a slightly modified version of stb_truetype.h 1.9. Those changes would need to be pushed into nothings/sb
+// [ImGui] - fixed linestart handler when over last character of multi-line buffer + simplified existing code (#588, #815)
+// [ImGui] - fixed a state corruption/crash bug in stb_text_redo and stb_textedit_discard_redo (#715)
 // [ImGui] - fixed a crash bug in stb_textedit_discard_redo (#681)
 // [ImGui] - fixed some minor warnings
-// [ImGui] - added STB_TEXTEDIT_MOVEWORDLEFT/STB_TEXTEDIT_MOVEWORDRIGHT custom handler (#473)
 
-// stb_textedit.h - v1.8  - public domain - Sean Barrett
+// stb_textedit.h - v1.9  - public domain - Sean Barrett
 // Development of this library was sponsored by RAD Game Tools
 //
 // This C header file implements the guts of a multi-line text-editing
@@ -36,6 +37,7 @@
 //
 // VERSION HISTORY
 //
+//   1.9  (2016-08-27) customizable move-by-word
 //   1.8  (2016-04-02) better keyboard handling when mouse button is down
 //   1.7  (2015-09-13) change y range handling in case baseline is non-0
 //   1.6  (2015-04-15) allow STB_TEXTEDIT_memmove
@@ -424,10 +426,9 @@ static int stb_text_locate_coord(STB_TEXTEDIT_STRING *str, float x, float y)
    // check if it's before the end of the line
    if (x < r.x1) {
       // search characters in row for one that straddles 'x'
-      k = i;
       prev_x = r.x0;
-      for (i=0; i < r.num_chars; ++i) {
-         float w = STB_TEXTEDIT_GETWIDTH(str, k, i);
+      for (k=0; k < r.num_chars; ++k) {
+         float w = STB_TEXTEDIT_GETWIDTH(str, i, k);
          if (x < prev_x+w) {
             if (x < prev_x+w/2)
                return k+i;
@@ -617,15 +618,16 @@ static void stb_textedit_move_to_last(STB_TEXTEDIT_STRING *str, STB_TexteditStat
 }
 
 #ifdef STB_TEXTEDIT_IS_SPACE
-static int is_word_boundary( STB_TEXTEDIT_STRING *_str, int _idx )
+static int is_word_boundary( STB_TEXTEDIT_STRING *str, int idx )
 {
-   return _idx > 0 ? (STB_TEXTEDIT_IS_SPACE( STB_TEXTEDIT_GETCHAR(_str,_idx-1) ) && !STB_TEXTEDIT_IS_SPACE( STB_TEXTEDIT_GETCHAR(_str, _idx) ) ) : 1;
+   return idx > 0 ? (STB_TEXTEDIT_IS_SPACE( STB_TEXTEDIT_GETCHAR(str,idx-1) ) && !STB_TEXTEDIT_IS_SPACE( STB_TEXTEDIT_GETCHAR(str, idx) ) ) : 1;
 }
 
 #ifndef STB_TEXTEDIT_MOVEWORDLEFT
-static int stb_textedit_move_to_word_previous( STB_TEXTEDIT_STRING *_str, int c )
+static int stb_textedit_move_to_word_previous( STB_TEXTEDIT_STRING *str, int c )
 {
-   while( c >= 0 && !is_word_boundary( _str, c ) )
+   --c; // always move at least one character
+   while( c >= 0 && !is_word_boundary( str, c ) )
       --c;
 
    if( c < 0 )
@@ -637,10 +639,11 @@ static int stb_textedit_move_to_word_previous( STB_TEXTEDIT_STRING *_str, int c
 #endif
 
 #ifndef STB_TEXTEDIT_MOVEWORDRIGHT
-static int stb_textedit_move_to_word_next( STB_TEXTEDIT_STRING *_str, int c )
+static int stb_textedit_move_to_word_next( STB_TEXTEDIT_STRING *str, int c )
 {
-   const int len = STB_TEXTEDIT_STRINGLEN(_str);
-   while( c < len && !is_word_boundary( _str, c ) )
+   const int len = STB_TEXTEDIT_STRINGLEN(str);
+   ++c; // always move at least one character
+   while( c < len && !is_word_boundary( str, c ) )
       ++c;
 
    if( c > len )
@@ -777,7 +780,7 @@ retry:
          if (STB_TEXT_HAS_SELECTION(state))
             stb_textedit_move_to_first(state);
          else {
-            state->cursor = STB_TEXTEDIT_MOVEWORDLEFT(str, state->cursor-1);
+            state->cursor = STB_TEXTEDIT_MOVEWORDLEFT(str, state->cursor);
             stb_textedit_clamp( str, state );
          }
          break;
@@ -786,7 +789,7 @@ retry:
          if( !STB_TEXT_HAS_SELECTION( state ) )
             stb_textedit_prep_selection_at_cursor(state);
 
-         state->cursor = STB_TEXTEDIT_MOVEWORDLEFT(str, state->cursor-1);
+         state->cursor = STB_TEXTEDIT_MOVEWORDLEFT(str, state->cursor);
          state->select_end = state->cursor;
 
          stb_textedit_clamp( str, state );
@@ -798,7 +801,7 @@ retry:
          if (STB_TEXT_HAS_SELECTION(state)) 
             stb_textedit_move_to_last(str, state);
          else {
-            state->cursor = STB_TEXTEDIT_MOVEWORDRIGHT(str, state->cursor+1);
+            state->cursor = STB_TEXTEDIT_MOVEWORDRIGHT(str, state->cursor);
             stb_textedit_clamp( str, state );
          }
          break;
@@ -807,7 +810,7 @@ retry:
          if( !STB_TEXT_HAS_SELECTION( state ) )
             stb_textedit_prep_selection_at_cursor(state);
 
-         state->cursor = STB_TEXTEDIT_MOVEWORDRIGHT(str, state->cursor+1);
+         state->cursor = STB_TEXTEDIT_MOVEWORDRIGHT(str, state->cursor);
          state->select_end = state->cursor;
 
          stb_textedit_clamp( str, state );
@@ -990,58 +993,58 @@ retry:
 #ifdef STB_TEXTEDIT_K_LINESTART2
       case STB_TEXTEDIT_K_LINESTART2:
 #endif
-      case STB_TEXTEDIT_K_LINESTART: {
-         StbFindState find;
+      case STB_TEXTEDIT_K_LINESTART:
          stb_textedit_clamp(str, state);
          stb_textedit_move_to_first(state);
-         stb_textedit_find_charpos(&find, str, state->cursor, state->single_line);
-         state->cursor = find.first_char;
+         if (state->single_line)
+            state->cursor = 0;
+         else while (state->cursor > 0 && STB_TEXTEDIT_GETCHAR(str, state->cursor-1) != STB_TEXTEDIT_NEWLINE)
+            --state->cursor;
          state->has_preferred_x = 0;
          break;
-      }
 
 #ifdef STB_TEXTEDIT_K_LINEEND2
       case STB_TEXTEDIT_K_LINEEND2:
 #endif
       case STB_TEXTEDIT_K_LINEEND: {
-         StbFindState find;
+         int n = STB_TEXTEDIT_STRINGLEN(str);
          stb_textedit_clamp(str, state);
          stb_textedit_move_to_first(state);
-         stb_textedit_find_charpos(&find, str, state->cursor, state->single_line);
-
+         if (state->single_line)
+             state->cursor = n;
+         else while (state->cursor < n && STB_TEXTEDIT_GETCHAR(str, state->cursor) != STB_TEXTEDIT_NEWLINE)
+             ++state->cursor;
          state->has_preferred_x = 0;
-         state->cursor = find.first_char + find.length;
-         if (find.length > 0 && STB_TEXTEDIT_GETCHAR(str, state->cursor-1) == STB_TEXTEDIT_NEWLINE)
-            --state->cursor;
          break;
       }
 
 #ifdef STB_TEXTEDIT_K_LINESTART2
       case STB_TEXTEDIT_K_LINESTART2 | STB_TEXTEDIT_K_SHIFT:
 #endif
-      case STB_TEXTEDIT_K_LINESTART | STB_TEXTEDIT_K_SHIFT: {
-         StbFindState find;
+      case STB_TEXTEDIT_K_LINESTART | STB_TEXTEDIT_K_SHIFT:
          stb_textedit_clamp(str, state);
          stb_textedit_prep_selection_at_cursor(state);
-         stb_textedit_find_charpos(&find, str, state->cursor, state->single_line);
-         state->cursor = state->select_end = find.first_char;
+         if (state->single_line)
+            state->cursor = 0;
+         else while (state->cursor > 0 && STB_TEXTEDIT_GETCHAR(str, state->cursor-1) != STB_TEXTEDIT_NEWLINE)
+            --state->cursor;
+         state->select_end = state->cursor;
          state->has_preferred_x = 0;
          break;
-      }
 
 #ifdef STB_TEXTEDIT_K_LINEEND2
       case STB_TEXTEDIT_K_LINEEND2 | STB_TEXTEDIT_K_SHIFT:
 #endif
       case STB_TEXTEDIT_K_LINEEND | STB_TEXTEDIT_K_SHIFT: {
-         StbFindState find;
+         int n = STB_TEXTEDIT_STRINGLEN(str);
          stb_textedit_clamp(str, state);
          stb_textedit_prep_selection_at_cursor(state);
-         stb_textedit_find_charpos(&find, str, state->cursor, state->single_line);
-         state->has_preferred_x = 0;
-         state->cursor = find.first_char + find.length;
-         if (find.length > 0 && STB_TEXTEDIT_GETCHAR(str, state->cursor-1) == STB_TEXTEDIT_NEWLINE)
-            --state->cursor;
+         if (state->single_line)
+             state->cursor = n;
+         else while (state->cursor < n && STB_TEXTEDIT_GETCHAR(str, state->cursor) != STB_TEXTEDIT_NEWLINE)
+            ++state->cursor;
          state->select_end = state->cursor;
+         state->has_preferred_x = 0;
          break;
       }
 
@@ -1101,8 +1104,8 @@ static void stb_textedit_discard_redo(StbUndoState *state)
             if (state->undo_rec[i].char_storage >= 0)
                state->undo_rec[i].char_storage = state->undo_rec[i].char_storage + (short) n; // vsnet05
       }
+      STB_TEXTEDIT_memmove(state->undo_rec + state->redo_point, state->undo_rec + state->redo_point-1, (size_t) ((size_t)(STB_TEXTEDIT_UNDOSTATECOUNT - state->redo_point)*sizeof(state->undo_rec[0])));
       ++state->redo_point;
-      STB_TEXTEDIT_memmove(state->undo_rec + state->redo_point-1, state->undo_rec + state->redo_point, (size_t) ((size_t)(STB_TEXTEDIT_UNDOSTATECOUNT - state->redo_point)*sizeof(state->undo_rec[0])));
    }
 }
 
@@ -1260,6 +1263,7 @@ static void stb_text_redo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
    if (r.insert_length) {
       // easy case: need to insert n characters
       STB_TEXTEDIT_INSERTCHARS(str, r.where, &s->undo_char[r.char_storage], r.insert_length);
+      s->redo_char_point += r.insert_length;
    }
 
    state->cursor = r.where + r.insert_length;

+ 32 - 0
examples/08-update/cs_update.sc

@@ -0,0 +1,32 @@
+/*
+ * Copyright 2014 Stanlo Slasinski. All rights reserved.
+ * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
+ */
+
+#include "bgfx_compute.sh"
+
+IMAGE2D_ARRAY_WR(s_texColor,rgba32f,0);
+uniform vec4 u_time;
+
+NUM_THREADS(16, 16, 1)
+void main()
+{
+	vec3 colors[] = {
+		vec3(1,0,0),
+		vec3(1,1,0),
+		vec3(1,0,1),
+		vec3(0,1,0),
+		vec3(0,1,1),
+		vec3(0,0,1),
+	};
+
+	for (int face=0;face<6;face++)
+	{
+		vec3 color = colors[face]*0.75 + sin( u_time.x*4.0 )*0.25;
+		ivec3 dest = ivec3( gl_GlobalInvocationID.xy, face );
+		imageStore( s_texColor, dest, vec4(color,1) );
+	}
+}
+
+
+

+ 62 - 19
examples/08-update/update.cpp

@@ -162,7 +162,8 @@ public:
 		const bgfx::Caps* caps = bgfx::getCaps();
 		m_texture3DSupported = !!(caps->supported & BGFX_CAPS_TEXTURE_3D);
 		m_blitSupported      = !!(caps->supported & BGFX_CAPS_TEXTURE_BLIT);
-		m_numm_textures3d      = 0;
+		m_computeSupported   = !!(caps->supported & BGFX_CAPS_COMPUTE);
+		m_numm_textures3d    = 0;
 
 		if (m_texture3DSupported)
 		{
@@ -215,6 +216,12 @@ public:
 			m_program3d = loadProgram("vs_update", "fs_update_3d");
 		}
 
+		m_programCompute.idx = bgfx::invalidHandle;
+		if (m_computeSupported)
+		{
+			m_programCompute = bgfx::createProgram( loadShader( "cs_update" ), true );
+		}
+
 		// Create texture sampler uniforms.
 		s_texCube  = bgfx::createUniform("s_texCube",  bgfx::UniformType::Int1);
 		s_texColor = bgfx::createUniform("s_texColor", bgfx::UniformType::Int1);
@@ -222,6 +229,11 @@ public:
 		// Create time uniform.
 		u_time = bgfx::createUniform("u_time", bgfx::UniformType::Vec4);
 
+		for(uint32_t ii = 0; ii<BX_COUNTOF( m_textureCube ); ++ii)
+		{
+			m_textureCube[ii].idx = bgfx::invalidHandle;
+		}
+
 		m_textureCube[0] = bgfx::createTextureCube(
 				  textureside
 				, false
@@ -241,6 +253,17 @@ public:
 					);
 		}
 
+		if (m_computeSupported) 
+		{
+			m_textureCube[2] = bgfx::createTextureCube(
+				textureside
+				, false
+				, 1
+				, bgfx::TextureFormat::RGBA8
+				, BGFX_TEXTURE_COMPUTE_WRITE
+				);
+		}
+
 		m_texture2d = bgfx::createTexture2D(
 				  texture2dSize
 				, texture2dSize
@@ -284,11 +307,15 @@ public:
 		}
 
 		bgfx::destroyTexture(m_texture2d);
-		bgfx::destroyTexture(m_textureCube[0]);
-		if (m_blitSupported)
+
+		for (uint32_t ii = 0; ii<BX_COUNTOF(m_textureCube); ++ii)
 		{
-			bgfx::destroyTexture(m_textureCube[1]);
+			if (bgfx::isValid(m_textureCube[ii]))
+			{
+				bgfx::destroyTexture(m_textureCube[ii]);
+			}
 		}
+
 		bgfx::destroyIndexBuffer(m_ibh);
 		bgfx::destroyVertexBuffer(m_vbh);
 		if (bgfx::isValid(m_program3d) )
@@ -296,6 +323,10 @@ public:
 			bgfx::destroyProgram(m_program3d);
 		}
 		bgfx::destroyProgram(m_programCmp);
+		if (bgfx::isValid(m_programCompute) )
+		{
+			bgfx::destroyProgram(m_programCompute);
+		}
 		bgfx::destroyProgram(m_program);
 		bgfx::destroyUniform(u_time);
 		bgfx::destroyUniform(s_texColor);
@@ -426,26 +457,36 @@ public:
 			// Set view and projection matrix for view 0.
 			bgfx::setViewTransform(0, view, proj);
 
-			for (uint32_t ii = 0; ii < 1 + uint32_t(m_blitSupported); ++ii)
+			// Update texturecube using compute shader
+			if (m_computeSupported )
 			{
-				float mtx[16];
-				bx::mtxSRT(mtx, 1.0f, 1.0f, 1.0f, time, time*0.37f, 0.0f, -1.5f*m_blitSupported + ii*3.0f, 0.0f, 0.0f);
+				bgfx::setImage( 0, s_texCube, m_textureCube[2], 0, bgfx::Access::Write );
+				bgfx::dispatch( 0, m_programCompute, textureside/16, textureside/16 );
+			}
 
-				// Set model matrix for rendering.
-				bgfx::setTransform(mtx);
+			for (uint32_t ii = 0; ii < BX_COUNTOF(m_textureCube); ++ii)
+			{
+				if (bgfx::isValid(m_textureCube[ii])) 
+				{
+					float mtx[16];
+					bx::mtxSRT( mtx, 0.7f, 0.7f, 0.7f, time, time*0.37f, 0.0f, -2.0f +ii*2.0f, 0.0f, 0.0f );
 
-				// Set vertex and index buffer.
-				bgfx::setVertexBuffer(m_vbh);
-				bgfx::setIndexBuffer(m_ibh);
+					// Set model matrix for rendering.
+					bgfx::setTransform( mtx );
 
-				// Bind texture.
-				bgfx::setTexture(0, s_texCube, m_textureCube[ii]);
+					// Set vertex and index buffer.
+					bgfx::setVertexBuffer( m_vbh );
+					bgfx::setIndexBuffer( m_ibh );
 
-				// Set render states.
-				bgfx::setState(BGFX_STATE_DEFAULT);
+					// Bind texture.
+					bgfx::setTexture( 0, s_texCube, m_textureCube[ii] );
+
+					// Set render states.
+					bgfx::setState( BGFX_STATE_DEFAULT );
 
-				// Submit primitive for rendering to view 0.
-				bgfx::submit(0, m_program);
+					// Submit primitive for rendering to view 0.
+					bgfx::submit( 0, m_program );
+				}
 			}
 
 			// Set view and projection matrix for view 1.
@@ -557,6 +598,7 @@ public:
 	uint32_t m_numm_textures3d;
 	bool m_texture3DSupported;
 	bool m_blitSupported;
+	bool m_computeSupported;
 
 	std::list<PackCube> m_quads;
 	RectPackCubeT<256> m_cube;
@@ -573,11 +615,12 @@ public:
 	bgfx::TextureHandle m_textures[9];
 	bgfx::TextureHandle m_textures3d[3];
 	bgfx::TextureHandle m_texture2d;
-	bgfx::TextureHandle m_textureCube[2];
+	bgfx::TextureHandle m_textureCube[3];
 	bgfx::IndexBufferHandle m_ibh;
 	bgfx::VertexBufferHandle m_vbh;
 	bgfx::ProgramHandle m_program3d;
 	bgfx::ProgramHandle m_programCmp;
+	bgfx::ProgramHandle m_programCompute;
 	bgfx::ProgramHandle m_program;
 	bgfx::UniformHandle u_time;
 	bgfx::UniformHandle s_texColor;

+ 1 - 0
examples/15-shadowmaps-simple/shadowmaps_simple.cpp

@@ -385,6 +385,7 @@ int _main_(int _argc, char** _argv)
 	bgfx::destroyUniform(u_shadowMap);
 	bgfx::destroyUniform(u_lightPos);
 	bgfx::destroyUniform(u_lightMtx);
+	bgfx::destroyUniform(u_depthScaleOffset);
 
 	// Shutdown bgfx.
 	bgfx::shutdown();

+ 2 - 5
examples/common/entry/entry_windows.cpp

@@ -34,11 +34,8 @@ namespace entry
 	inline void winSetHwnd(::HWND _window)
 	{
 		bgfx::PlatformData pd;
-		pd.ndt          = NULL;
-		pd.nwh          = _window;
-		pd.context      = NULL;
-		pd.backBuffer   = NULL;
-		pd.backBufferDS = NULL;
+		memset(&pd, 0, sizeof(pd) );
+		pd.nwh = _window;
 		bgfx::setPlatformData(pd);
 	}
 

+ 0 - 1
examples/common/imgui/imgui.h

@@ -28,7 +28,6 @@
 
 #include <bgfx/bgfx.h>
 #include <ocornut-imgui/imgui.h>
-#include <ocornut-imgui/imgui_wm.h>
 #include <iconfontheaders/icons_kenney.h>
 #include <iconfontheaders/icons_font_awesome.h>
 

+ 2 - 353
examples/common/imgui/ocornut_imgui.cpp

@@ -8,7 +8,6 @@
 #include <bx/fpumath.h>
 #include <bx/timer.h>
 #include <ocornut-imgui/imgui.h>
-#include <ocornut-imgui/imgui_wm.h>
 #include "imgui.h"
 #include "ocornut_imgui.h"
 
@@ -50,181 +49,6 @@ static FontRangeMerge s_fontRangeMerge[] =
 	{ s_iconsFontAwesomeTtf, sizeof(s_iconsFontAwesomeTtf), { ICON_MIN_FA, ICON_MAX_FA, 0 } },
 };
 
-class PlatformWindow : public ImGuiWM::PlatformWindow
-{
-	typedef ImGuiWM::PlatformWindow Super;
-
-public:
-	PlatformWindow(bool _mainWindow, bool _isDragWindow)
-		: ImGuiWM::PlatformWindow(_mainWindow, _isDragWindow)
-		, m_pos(0.0f, 0.0f)
-		, m_size(0.0f, 0.0f)
-		, m_drag(false)
-	{
-#if USE_ENTRY
-		if (!_mainWindow
-		&&  !_isDragWindow)
-		{
-			m_window = entry::createWindow(0, 0, 640, 380);
-			extern void pwToWindow(entry::WindowHandle _handle, class PlatformWindow* _pw);
-			pwToWindow(m_window, this);
-		}
-		else
-		{
-			m_window.idx = 0;
-		}
-#endif // USE_ENTRY
-	}
-
-	virtual ~PlatformWindow()
-	{
-#if USE_ENTRY
-		if (0 != m_window.idx)
-		{
-			entry::destroyWindow(m_window);
-		}
-#endif // USE_ENTRY
-	}
-
-	virtual bool Init(ImGuiWM::PlatformWindow* /*_parent*/) BX_OVERRIDE
-	{
-		return true;
-	}
-
-	virtual const ImVec2& GetPosition() const BX_OVERRIDE
-	{
-		return m_pos;
-	}
-
-	virtual const ImVec2& GetSize() const BX_OVERRIDE
-	{
-		return m_size;
-	}
-
-	virtual void Show() BX_OVERRIDE
-	{
-	}
-
-	virtual void Hide() BX_OVERRIDE
-	{
-	}
-
-	virtual void SetSize(const ImVec2& _size) BX_OVERRIDE
-	{
-#if USE_ENTRY
-		if (0 != m_window.idx
-		&&  m_size.x != _size.x
-		&&  m_size.y != _size.y)
-		{
-			entry::setWindowSize(m_window, int32_t(_size.x), int32_t(_size.y) );
-		}
-#endif // USE_ENTRY
-
-		m_size = _size;
-	}
-
-	virtual void SetPosition(const ImVec2& _pos) BX_OVERRIDE
-	{
-#if USE_ENTRY
-		if (0 != m_window.idx
-		&&  m_pos.x != _pos.x
-		&&  m_pos.y != _pos.y)
-		{
-			entry::setWindowPos(m_window, int32_t(_pos.x), int32_t(_pos.y) );
-		}
-#endif // USE_ENTRY
-
-		m_pos = _pos;
-	}
-
-	virtual void SetTitle(const char* _title) BX_OVERRIDE
-	{
-#if USE_ENTRY
-		entry::setWindowTitle(m_window, _title);
-#else
-		BX_UNUSED(_title);
-#endif // USE_ENTRY
-	}
-
-	virtual void PreUpdate() BX_OVERRIDE
-	{
-	}
-
-	virtual void PaintBegin() BX_OVERRIDE;
-	virtual void Paint() BX_OVERRIDE;
-	virtual void PaintEnd() BX_OVERRIDE;
-
-	virtual void Destroy() BX_OVERRIDE
-	{
-	}
-
-	virtual void StartDrag() BX_OVERRIDE
-	{
-		m_drag = true;
-	}
-
-	virtual void StopDrag() BX_OVERRIDE
-	{
-		m_drag = false;
-	}
-
-	virtual bool IsDraging() BX_OVERRIDE
-	{
-		return m_drag;
-	}
-
-private:
-	ImVec2 m_pos;
-	ImVec2 m_size;
-	bool m_drag;
-
-#if USE_ENTRY
-	entry::WindowHandle m_window;
-#endif // USE_ENTRY
-};
-
-class WindowManager : public ImGuiWM::WindowManager
-{
-	typedef ImGuiWM::WindowManager Super;
-
-public:
-	WindowManager()
-	{
-	}
-
-	virtual ~WindowManager()
-	{
-	}
-
-protected:
-	virtual ImGuiWM::PlatformWindow* CreatePlatformWindow(bool _main, ImGuiWM::PlatformWindow* _parent, bool _isDragWindow) BX_OVERRIDE
-	{
-#if USE_ENTRY
-#else
-		if (!_main
-		&&  !_isDragWindow)
-		{
-			return NULL;
-		}
-#endif // USE_ENTRY
-
-		PlatformWindow* window = new (ImGui::MemAlloc(sizeof(PlatformWindow) ) ) PlatformWindow(_main, _isDragWindow);
-		window->Init(_parent);
-		return static_cast<ImGuiWM::PlatformWindow*>(window);
-	}
-
-	virtual void LogFormatted(const char* _str) BX_OVERRIDE
-	{
-		BX_TRACE("%s", _str); BX_UNUSED(_str);
-	}
-
-	virtual void InternalRun() BX_OVERRIDE
-	{
-		PreUpdate();
-		Update();
-	}
-};
-
 struct OcornutImguiContext
 {
 	static void* memAlloc(size_t _size);
@@ -483,60 +307,12 @@ struct OcornutImguiContext
 			, bgfx::copy(data, width*height*4)
 			);
 
-		m_wm = BX_NEW(m_allocator, WindowManager);
-		m_wm->Init();
-
-#if 0
-		{
-			class Window : public ImGuiWM::Window
-			{
-			public:
-				Window(const char* _title)
-					: ImGuiWM::Window()
-				{
-					SetTitle(_title);
-				}
-
-				virtual void OnGui() BX_OVERRIDE
-				{
-				}
-			};
-
-			class WindowX : public ImGuiWM::Window
-			{
-			public:
-				WindowX(const char* _title)
-					: ImGuiWM::Window()
-				{
-					SetTitle(_title);
-				}
-
-				virtual void OnGui() BX_OVERRIDE
-				{
-#if defined(SCI_NAMESPACE) && 0
-					bool opened = true;
-					ImGuiScintilla("Scintilla Editor", &opened, ImVec2(640.0f, 480.0f) );
-#endif // 0
-				}
-			};
-
-			Window*  w0 = new Window("test");
-			WindowX* w1 = new WindowX("Scintilla");
-			Window*  w2 = new Window("xyzw");
-			Window*  w3 = new Window("0123");
-
- 			m_wm->Dock(w0);
- 			m_wm->DockWith(w1, w0, ImGuiWM::E_DOCK_ORIENTATION_RIGHT);
- 			m_wm->DockWith(w2, w1, ImGuiWM::E_DOCK_ORIENTATION_BOTTOM);
- 			m_wm->DockWith(w3, w0, ImGuiWM::E_DOCK_ORIENTATION_BOTTOM);
-		}
-#endif // 0
+		ImGui::InitDockContext();
 	}
 
 	void destroy()
 	{
-		m_wm->Exit();
-		BX_DELETE(m_allocator, m_wm);
+		ImGui::ShutdownDockContext();
 		ImGui::Shutdown();
 
 		bgfx::destroyUniform(s_tex);
@@ -656,36 +432,10 @@ struct OcornutImguiContext
 		ImGui::NewFrame();
 		ImGuizmo::BeginFrame();
 		ImGui::PushStyleVar(ImGuiStyleVar_ViewId, (float)_viewId);
-
-#if 0
-		ImGui::ShowTestWindow(); //Debug only.
-#endif // 0
-
-#if 0
-		{
-			static ImGui::MemoryEditor me;
-			bool open = true;
-			if (ImGui::Begin("HexII", &open))
-			{
-				me.Draw(s_iconsKenneyTtf, sizeof(s_iconsKenneyTtf) );
-
-				ImGui::End();
-			}
-		}
-#endif // 0
-
-#if 0
-		{
-			extern void ShowExampleAppCustomNodeGraph(bool* opened);
-			bool opened = true;
-			ShowExampleAppCustomNodeGraph(&opened);
-		}
-#endif // 0
 	}
 
 	void endFrame()
 	{
-		m_wm->Run();
 		ImGui::PopStyleVar(1);
 		ImGui::Render();
 	}
@@ -696,114 +446,13 @@ struct OcornutImguiContext
 	bgfx::TextureHandle m_texture;
 	bgfx::UniformHandle s_tex;
 	ImFont* m_font[ImGui::Font::Count];
-	WindowManager* m_wm;
 	int64_t m_last;
 	int32_t m_lastScroll;
 	uint8_t m_viewId;
-
-#if USE_ENTRY
-	struct Window
-	{
-		Window()
-		{
-			m_fbh.idx = bgfx::invalidHandle;
-		}
-
-		entry::WindowState m_state;
-		PlatformWindow* m_pw;
-		bgfx::FrameBufferHandle m_fbh;
-		uint8_t m_viewId;
-	};
-
-	Window m_window[16];
-#endif // USE_ENTRY
 };
 
 static OcornutImguiContext s_ctx;
 
-void PlatformWindow::PaintBegin()
-{
-#if USE_ENTRY
-	if (!m_bIsDragWindow)
-	{
-		OcornutImguiContext::Window& win = s_ctx.m_window[m_window.idx];
-		entry::WindowState& state = win.m_state;
-		ImGuiIO& io = ImGui::GetIO();
-		io.MousePos = ImVec2((float)state.m_mouse.m_mx, (float)state.m_mouse.m_my);
-		io.MouseDown[0] = !!state.m_mouse.m_buttons[entry::MouseButton::Left];
-		io.MouseDown[1] = !!state.m_mouse.m_buttons[entry::MouseButton::Right];
-		io.MouseDown[2] = !!state.m_mouse.m_buttons[entry::MouseButton::Middle];
-		io.MouseWheel   = float(state.m_mouse.m_mz);
-
-		ImGui::PushStyleVar(ImGuiStyleVar_ViewId, (float)win.m_viewId);
-	}
-#endif // USE_ENTRY
-}
-
-void PlatformWindow::Paint()
-{
-	if (!m_bIsDragWindow)
-	{
-		Super::Paint();
-	}
-}
-
-void PlatformWindow::PaintEnd()
-{
-#if USE_ENTRY
-	if (!m_bIsDragWindow)
-	{
-		ImGui::PopStyleVar(1);
-
-		entry::WindowState& state = s_ctx.m_window[0].m_state;
-		ImGuiIO& io = ImGui::GetIO();
-		io.MousePos = ImVec2((float)state.m_mouse.m_mx, (float)state.m_mouse.m_my);
-		io.MouseDown[0] = !!state.m_mouse.m_buttons[entry::MouseButton::Left];
-		io.MouseDown[1] = !!state.m_mouse.m_buttons[entry::MouseButton::Right];
-		io.MouseDown[2] = !!state.m_mouse.m_buttons[entry::MouseButton::Middle];
-		io.MouseWheel   = float(state.m_mouse.m_mz);
-	}
-#endif // USE_ENTRY
-}
-
-#if USE_ENTRY
-
-void pwToWindow(entry::WindowHandle _handle, PlatformWindow* _pw)
-{
-	s_ctx.m_window[_handle.idx].m_pw = _pw;
-}
-
-void imguiUpdateWindow(const entry::WindowState& _state)
-{
-	OcornutImguiContext::Window& window = s_ctx.m_window[_state.m_handle.idx];
-
-	if (window.m_state.m_nwh    != _state.m_nwh
-	|| (window.m_state.m_width  != _state.m_width
-	||  window.m_state.m_height != _state.m_height) )
-	{
-		// When window changes size or native window handle changed
-		// frame buffer must be recreated.
-		if (bgfx::isValid(window.m_fbh) )
-		{
-			bgfx::destroyFrameBuffer(window.m_fbh);
-			window.m_fbh.idx = bgfx::invalidHandle;
-		}
-
-		if (NULL != _state.m_nwh)
-		{
-			window.m_fbh = bgfx::createFrameBuffer(_state.m_nwh, _state.m_width, _state.m_height);
-			window.m_viewId = 200 + _state.m_handle.idx;
-		}
-		else
-		{
-			window.m_viewId = s_ctx.m_viewId;
-		}
-	}
-
-	memcpy(&window.m_state, &_state, sizeof(entry::WindowState) );
-}
-#endif // USE_ENTRY
-
 void* OcornutImguiContext::memAlloc(size_t _size)
 {
 	return BX_ALLOC(s_ctx.m_allocator, _size);

+ 4 - 0
examples/common/nanovg/nanovg.cpp

@@ -67,6 +67,10 @@ BX_PRAGMA_DIAGNOSTIC_PUSH();
 BX_PRAGMA_DIAGNOSTIC_IGNORED_CLANG_GCC("-Wmissing-field-initializers");
 BX_PRAGMA_DIAGNOSTIC_IGNORED_CLANG_GCC("-Wshadow");
 BX_PRAGMA_DIAGNOSTIC_IGNORED_CLANG_GCC("-Wint-to-pointer-cast")
+#if BX_COMPILER_GCC >= 60000
+BX_PRAGMA_DIAGNOSTIC_IGNORED_GCC("-Wmisleading-indentation");
+BX_PRAGMA_DIAGNOSTIC_IGNORED_GCC("-Wshift-negative-value");
+#endif // BX_COMPILER_GCC >= 60000_
 #define STBI_MALLOC(_size)        lodepng_malloc(_size)
 #define STBI_REALLOC(_ptr, _size) lodepng_realloc(_ptr, _size)
 #define STBI_FREE(_ptr)           lodepng_free(_ptr)

+ 0 - 2
examples/runtime/.gitignore

@@ -2,5 +2,3 @@
 *.so
 *.pdb
 imgui*
-shaders/pssl/*
-shaders/spirv/*

二进制
examples/runtime/shaders/dx11/cs_update.bin


二进制
examples/runtime/shaders/glsl/cs_update.bin


+ 1 - 0
examples/runtime/shaders/pssl/.gitignore

@@ -0,0 +1 @@
+*

+ 1 - 0
examples/runtime/shaders/spirv/.gitignore

@@ -0,0 +1 @@
+*

+ 23 - 21
include/bgfx/bgfx.h

@@ -520,7 +520,7 @@ namespace bgfx
 		///
 		uint64_t supported;
 
-		uint16_t vendorId;         //!< Selected GPU vendor id.
+		uint16_t vendorId;         //!< Selected GPU vendor PCI id.
 		uint16_t deviceId;         //!< Selected GPU device id.
 		bool     homogeneousDepth; //!< True when NDC depth is in [-1, 1] range.
 		bool     originBottomLeft; //!< True when NDC origin is at bottom left.
@@ -532,8 +532,8 @@ namespace bgfx
 		///
 		struct GPU
 		{
-			uint16_t vendorId;
-			uint16_t deviceId;
+			uint16_t vendorId; //!< Vendor PCI id. See `BGFX_PCI_ID_*`.
+			uint16_t deviceId; //!< Device id.
 		};
 
 		GPU gpu[4]; //!< Enumerated GPUs.
@@ -541,23 +541,23 @@ namespace bgfx
 		struct Limits
 		{
 			uint32_t maxDrawCalls;            //!< Maximum draw calls.
-			uint32_t maxBlits;                //!<
+			uint32_t maxBlits;                //!< Maximum number of blit calls.
 			uint32_t maxTextureSize;          //!< Maximum texture size.
 			uint32_t maxViews;                //!< Maximum views.
-			uint32_t maxFrameBuffers;         //!<
+			uint32_t maxFrameBuffers;         //!< Maximum number of frame buffer handles.
 			uint32_t maxFBAttachments;        //!< Maximum frame buffer attachments.
-			uint32_t maxPrograms;             //!<
-			uint32_t maxShaders;              //!<
-			uint32_t maxTextures;             //!<
-			uint32_t maxTextureSamplers;      //!<
-			uint32_t maxVertexDecls;          //!<
-			uint32_t maxVertexStreams;        //!<
-			uint32_t maxIndexBuffers;         //!<
-			uint32_t maxVertexBuffers;        //!<
-			uint32_t maxDynamicIndexBuffers;  //!<
-			uint32_t maxDynamicVertexBuffers; //!<
-			uint32_t maxUniforms;             //!<
-			uint32_t maxOcclusionQueries;     //!<
+			uint32_t maxPrograms;             //!< Maximum number of program handles.
+			uint32_t maxShaders;              //!< Maximum number of shader handles.
+			uint32_t maxTextures;             //!< Maximum number of texture handles.
+			uint32_t maxTextureSamplers;      //!< Maximum number of texture samplers.
+			uint32_t maxVertexDecls;          //!< Maximum number of vertex format declarations.
+			uint32_t maxVertexStreams;        //!< Maximum number of vertex streams.
+			uint32_t maxIndexBuffers;         //!< Maximum number of index buffer handles.
+			uint32_t maxVertexBuffers;        //!< Maximum number of vertex buffer handles.
+			uint32_t maxDynamicIndexBuffers;  //!< Maximum number of dynamic index buffer handles.
+			uint32_t maxDynamicVertexBuffers; //!< Maximum number of dynamic vertex buffer handles.
+			uint32_t maxUniforms;             //!< Maximum number of uniform handles.
+			uint32_t maxOcclusionQueries;     //!< Maximum number of occlusion query handles.
 		};
 
 		Limits limits;
@@ -725,7 +725,7 @@ namespace bgfx
 
 		/// End VertexDecl.
 		///
-		/// @attention C99 equivalent is `bgfx_vertex_decl_begin`.
+		/// @attention C99 equivalent is `bgfx_vertex_decl_end`.
 		///
 		void end();
 
@@ -986,7 +986,7 @@ namespace bgfx
 	/// @param[in] _callback Provide application specific callback interface.
 	///   See: `bgfx::CallbackI`
 	///
-	/// @param[in] _reallocator Custom allocator. When custom allocator is not
+	/// @param[in] _allocator Custom allocator. When custom allocator is not
 	///   specified, library uses default CRT allocator. The library assumes
 	///   custom allocator is thread safe.
 	///
@@ -999,7 +999,7 @@ namespace bgfx
 		, uint16_t _vendorId = BGFX_PCI_ID_NONE
 		, uint16_t _deviceId = 0
 		, CallbackI* _callback = NULL
-		, bx::AllocatorI* _reallocator = NULL
+		, bx::AllocatorI* _allocator = NULL
 		);
 
 	/// Shutdown bgfx library.
@@ -1077,6 +1077,8 @@ namespace bgfx
 
 	/// Returns performance counters.
 	///
+	/// @attention C99 equivalent is `bgfx_get_stats`.
+	///
 	const Stats* getStats();
 
 	/// Allocate buffer to pass to bgfx calls. Data will be freed inside bgfx.
@@ -2563,7 +2565,7 @@ namespace bgfx
 	///   call submit.
 	/// @returns Number of draw calls.
 	///
-	/// @attention C99 equivalent is `bgfx_submit_occlusion_query.
+	/// @attention C99 equivalent is `bgfx_submit_occlusion_query`.
 	///
 	uint32_t submit(
 		  uint8_t _id

+ 1 - 0
include/bgfx/bgfxplatform.h

@@ -51,6 +51,7 @@ namespace bgfx
 		void* context;      //!< GL context, or D3D device.
 		void* backBuffer;   //!< GL backbuffer, or D3D render target view.
 		void* backBufferDS; //!< Backbuffer depth/stencil.
+		void* session;      //!< ovrSession, for Oculus SDK
 	};
 
 	/// Set platform data.

+ 1 - 0
include/bgfx/c99/bgfxplatform.h

@@ -39,6 +39,7 @@ typedef struct bgfx_platform_data
     void* context;
     void* backBuffer;
     void* backBufferDS;
+    void* session;
 
 } bgfx_platform_data_t;
 

+ 5 - 3
scripts/shader.mk

@@ -25,6 +25,8 @@ all:
 	@echo "  TARGET=7 (spriv)"
 else
 
+ADDITIONAL_INCLUDES?=
+
 ifeq ($(TARGET), 0)
 VS_FLAGS=--platform windows -p vs_3_0 -O 3
 FS_FLAGS=--platform windows -p ps_3_0 -O 3
@@ -80,9 +82,9 @@ endif
 endif
 
 THISDIR := $(dir $(lastword $(MAKEFILE_LIST)))
-VS_FLAGS+=-i $(THISDIR)../src/
-FS_FLAGS+=-i $(THISDIR)../src/
-CS_FLAGS+=-i $(THISDIR)../src/
+VS_FLAGS+=-i $(THISDIR)../src/ $(ADDITIONAL_INCLUDES)
+FS_FLAGS+=-i $(THISDIR)../src/ $(ADDITIONAL_INCLUDES)
+CS_FLAGS+=-i $(THISDIR)../src/ $(ADDITIONAL_INCLUDES)
 
 BUILD_OUTPUT_DIR=$(addprefix ./, $(RUNTIME_DIR)/$(SHADER_PATH))
 BUILD_INTERMEDIATE_DIR=$(addprefix $(BUILD_DIR)/, $(SHADER_PATH))

+ 15 - 7
scripts/shaderc.lua

@@ -114,16 +114,24 @@ project "shaderc"
 		path.join(GLSL_OPTIMIZER, "src/glsl/builtin_stubs.cpp"),
 	}
 
-	overridefiles(BGFX_DIR, path.join(BGFX_DIR, "../bgfx-ext"), {
-			path.join(BGFX_DIR, "tools/shaderc/shaderc_pssl.cpp"),
-	})
-
 	if filesexist(BGFX_DIR, path.join(BGFX_DIR, "../bgfx-ext"), {
 		path.join(BGFX_DIR, "scripts/shaderc.lua"), }) then
 
-		removefiles {
-			path.join(BGFX_DIR, "tools/shaderc/shaderc_spirv.cpp"),
-		}
+		if filesexist(BGFX_DIR, path.join(BGFX_DIR, "../bgfx-ext"), {
+			path.join(BGFX_DIR, "tools/shaderc/shaderc_pssl.cpp"), }) then
+
+			removefiles {
+				path.join(BGFX_DIR, "tools/shaderc/shaderc_pssl.cpp"),
+			}
+		end
+
+		if filesexist(BGFX_DIR, path.join(BGFX_DIR, "../bgfx-ext"), {
+			path.join(BGFX_DIR, "tools/shaderc/shaderc_spirv.cpp"), }) then
+
+			removefiles {
+				path.join(BGFX_DIR, "tools/shaderc/shaderc_spirv.cpp"),
+			}
+		end
 
 		dofile(path.join(BGFX_DIR, "../bgfx-ext/scripts/shaderc.lua") )
 	end

+ 24 - 19
src/bgfx.cpp

@@ -542,10 +542,10 @@ namespace bgfx
 			.add(Attrib::TexCoord0, 2, AttribType::Float)
 			.end();
 
-		uint16_t width = 2048;
+		uint16_t width  = 2048;
 		uint16_t height = 24;
-		uint8_t bpp = 1;
-		uint32_t pitch = width*bpp;
+		uint8_t  bpp    = 1;
+		uint32_t pitch  = width*bpp;
 
 		const Memory* mem;
 
@@ -980,7 +980,7 @@ namespace bgfx
 			if (s_ctx->renderFrame() )
 			{
 				Context* ctx = s_ctx;
-				ctx->gameSemWait();
+				ctx->apiSemWait();
 				s_ctx = NULL;
 				ctx->renderSemPost();
 				return RenderFrame::Exiting;
@@ -1568,22 +1568,23 @@ namespace bgfx
 			m_renderCtx->flip(m_render->m_hmd);
 		}
 
-		gameSemWait();
-
-		rendererExecCommands(m_render->m_cmdPre);
-		if (m_rendererInitialized)
+		if (apiSemWait(BGFX_CONFIG_API_SEMAPHORE_TIMEOUT) )
 		{
-			BGFX_PROFILER_SCOPE(bgfx, render_submit, 0xff2040ff);
-			m_renderCtx->submit(m_render, m_clearQuad, m_textVideoMemBlitter);
-		}
-		rendererExecCommands(m_render->m_cmdPost);
+			rendererExecCommands(m_render->m_cmdPre);
+			if (m_rendererInitialized)
+			{
+				BGFX_PROFILER_SCOPE(bgfx, render_submit, 0xff2040ff);
+				m_renderCtx->submit(m_render, m_clearQuad, m_textVideoMemBlitter);
+			}
+			rendererExecCommands(m_render->m_cmdPost);
 
-		renderSemPost();
+			renderSemPost();
 
-		if (m_rendererInitialized
-		&&  m_flipAfterRender)
-		{
-			m_renderCtx->flip(m_render->m_hmd);
+			if (m_rendererInitialized
+			&&  m_flipAfterRender)
+			{
+				m_renderCtx->flip(m_render->m_hmd);
+			}
 		}
 
 		return m_exit;
@@ -1729,7 +1730,7 @@ namespace bgfx
 #if BX_PLATFORM_OSX || BX_PLATFORM_IOS
 		{ mtl::rendererCreate,   mtl::rendererDestroy,   BGFX_RENDERER_METAL_NAME,      !!BGFX_CONFIG_RENDERER_METAL      }, // Metal
 #else
-		{ noop::rendererCreate,  noop::rendererDestroy,  BGFX_RENDERER_NOOP_NAME,       !!BGFX_CONFIG_RENDERER_NOOP       }, // Noop
+		{ noop::rendererCreate,  noop::rendererDestroy,  BGFX_RENDERER_NOOP_NAME,       false                             }, // Noop
 #endif // BX_PLATFORM_OSX || BX_PLATFORM_IOS
 		{ gl::rendererCreate,    gl::rendererDestroy,    BGFX_RENDERER_OPENGL_NAME,     !!BGFX_CONFIG_RENDERER_OPENGLES   }, // OpenGLES
 		{ gl::rendererCreate,    gl::rendererDestroy,    BGFX_RENDERER_OPENGL_NAME,     !!BGFX_CONFIG_RENDERER_OPENGL     }, // OpenGL
@@ -1836,6 +1837,10 @@ namespace bgfx
 				{
 					score += RendererType::OpenGLES == renderer ? 20 : 0;
 				}
+				else if (BX_ENABLED(BX_PLATFORM_PS4) )
+				{
+					score += RendererType::Gnm      == renderer ? 20 : 0;
+				}
 				else if (BX_ENABLED(0
 					 ||  BX_PLATFORM_XBOXONE
 					 ||  BX_PLATFORM_WINRT
@@ -3161,7 +3166,7 @@ error:
 	{
 		BGFX_CHECK_MAIN_THREAD();
 		BX_CHECK(NULL != _mem, "_mem can't be NULL");
-		if (_width == 0
+		if (_width  == 0
 		||  _height == 0)
 		{
 			release(_mem);

+ 8 - 1
src/bgfx_compute.sh

@@ -19,6 +19,7 @@
 #define rg16f   float2
 #define rgba16f float4
 #define rgba8   float4
+#define rgba32f float4
 
 #define IMAGE2D_RO( _name, _format, _reg) Texture2D<_format>   _name : register(t[_reg])
 #define UIMAGE2D_RO(_name, _format, _reg) Texture2D<_format>   _name : register(t[_reg])
@@ -153,12 +154,18 @@ uint atomicCompSwap(uint _mem, uint _compare, uint _data)
 #define readwrite
 #define IMAGE2D_RO( _name, _format, _reg) __IMAGE_XX(_name, _format, _reg, image2D,  readonly)
 #define UIMAGE2D_RO(_name, _format, _reg) __IMAGE_XX(_name, _format, _reg, uimage2D, readonly)
-
 #define IMAGE2D_WR( _name, _format, _reg) __IMAGE_XX(_name, _format, _reg, image2D,  writeonly)
 #define UIMAGE2D_WR(_name, _format, _reg) __IMAGE_XX(_name, _format, _reg, uimage2D, writeonly)
 #define IMAGE2D_RW( _name, _reg) __IMAGE_XX(_name, r32f,  _reg, image2D,  readwrite)
 #define UIMAGE2D_RW(_name, _reg) __IMAGE_XX(_name, r32ui, _reg, uimage2D, readwrite)
 
+#define IMAGE2D_ARRAY_RO( _name, _format, _reg) __IMAGE_XX(_name, _format, _reg, image2DArray,  readonly)
+#define UIMAGE2D_ARRAY_RO(_name, _format, _reg) __IMAGE_XX(_name, _format, _reg, uimage2DArray, readonly)
+#define IMAGE2D_ARRAY_WR( _name, _format, _reg) __IMAGE_XX(_name, _format, _reg, image2DArray,  writeonly)
+#define UIMAGE2D_ARRAY_WR(_name, _format, _reg) __IMAGE_XX(_name, _format, _reg, uimage2DArray, writeonly)
+#define IMAGE2D_ARRAY_RW( _name, _reg) __IMAGE_XX(_name, r32f,  _reg, image2DArray,  readwrite)
+#define UIMAGE2D_ARRAY_RW(_name, _reg) __IMAGE_XX(_name, r32ui, _reg, uimage2DArray, readwrite)
+
 #define IMAGE3D_RO( _name, _format, _reg) __IMAGE_XX(_name, _format, _reg, image3D,  readonly)
 #define UIMAGE3D_RO(_name, _format, _reg) __IMAGE_XX(_name, _format, _reg, uimage3D, readonly)
 #define IMAGE3D_WR( _name, _format, _reg) __IMAGE_XX(_name, _format, _reg, image3D,  writeonly)

+ 32 - 18
src/bgfx_p.h

@@ -402,13 +402,13 @@ namespace bgfx
 
 		void resize(bool _small = false, uint32_t _width = BGFX_DEFAULT_WIDTH, uint32_t _height = BGFX_DEFAULT_HEIGHT)
 		{
-			uint32_t width = bx::uint32_max(1, _width/8);
-			uint32_t height = bx::uint32_max(1, _height/(_small ? 8 : 16) );
+			uint32_t width  = bx::uint32_imax(1, _width/8);
+			uint32_t height = bx::uint32_imax(1, _height/(_small ? 8 : 16) );
 
 			if (NULL == m_mem
-			||  m_width != width
+			||  m_width  != width
 			||  m_height != height
-			||  m_small != _small)
+			||  m_small  != _small)
 			{
 				m_small  = _small;
 				m_width  = (uint16_t)width;
@@ -2187,9 +2187,14 @@ namespace bgfx
 
 		BGFX_API_FUNC(void reset(uint32_t _width, uint32_t _height, uint32_t _flags) )
 		{
-			BX_WARN(0 != _width && 0 != _height, "Frame buffer resolution width or height cannot be 0 (width %d, height %d).", _width, _height);
-			m_resolution.m_width  = bx::uint32_max(1, _width);
-			m_resolution.m_height = bx::uint32_max(1, _height);
+			BX_WARN(1 <= int32_t(_width)
+				&&  1 <= int32_t(_height)
+				, "Frame buffer resolution width or height cannot be 0 (width %d, height %d)."
+				, _width
+				, _height
+				);
+			m_resolution.m_width  = bx::uint32_imax(1, _width);
+			m_resolution.m_height = bx::uint32_imax(1, _height);
 			m_resolution.m_flags  = 0
 				| _flags
 				| (g_platformDataChangedSinceReset ? BGFX_RESET_INTERNAL_FORCE : 0)
@@ -3001,7 +3006,7 @@ namespace bgfx
 			if (!isValid(_vsh)
 			||  !isValid(_fsh) )
 			{
-				BX_WARN(false, "Vertex/fragment shader is invalid (vsh %d, fsh %d).", _vsh.idx, _fsh.idx);
+				BX_TRACE("Vertex/fragment shader is invalid (vsh %d, fsh %d).", _vsh.idx, _fsh.idx);
 				ProgramHandle invalid = BGFX_INVALID_HANDLE;
 				return invalid;
 			}
@@ -3019,7 +3024,7 @@ namespace bgfx
 			const ShaderRef& fsr = m_shaderRef[_fsh.idx];
 			if (vsr.m_hash != fsr.m_hash)
 			{
-				BX_WARN(vsr.m_hash == fsr.m_hash, "Vertex shader output doesn't match fragment shader input.");
+				BX_TRACE("Vertex shader output doesn't match fragment shader input.");
 				ProgramHandle invalid = BGFX_INVALID_HANDLE;
 				return invalid;
 			}
@@ -3977,21 +3982,28 @@ namespace bgfx
 		{
 			if (!m_singleThreaded)
 			{
-				m_gameSem.post();
+				m_apiSem.post();
 			}
 		}
 
-		void gameSemWait()
+		bool apiSemWait(int32_t _msecs = -1)
 		{
-			if (!m_singleThreaded)
+			if (m_singleThreaded)
+			{
+				return true;
+			}
+
+			BGFX_PROFILER_SCOPE(bgfx, main_thread_wait, 0xff2040ff);
+			int64_t start = bx::getHPCounter();
+			bool ok = m_apiSem.wait(_msecs);
+			if (ok)
 			{
-				BGFX_PROFILER_SCOPE(bgfx, main_thread_wait, 0xff2040ff);
-				int64_t start = bx::getHPCounter();
-				bool ok = m_gameSem.wait();
-				BX_CHECK(ok, "Semaphore wait failed."); BX_UNUSED(ok);
 				m_render->m_waitSubmit = bx::getHPCounter()-start;
 				m_submit->m_perfStats.waitSubmit = m_submit->m_waitSubmit;
+				return true;
 			}
+
+			return false;
 		}
 
 		void renderSemPost()
@@ -4016,15 +4028,17 @@ namespace bgfx
 		}
 
 		bx::Semaphore m_renderSem;
-		bx::Semaphore m_gameSem;
+		bx::Semaphore m_apiSem;
 		bx::Thread m_thread;
 #else
 		void gameSemPost()
 		{
 		}
 
-		void gameSemWait()
+		bool apiSemWait(int32_t _msecs = -1)
 		{
+			BX_UNUSED(_msecs);
+			return true;
 		}
 
 		void renderSemPost()

+ 1 - 1
src/bgfx_shader.sh

@@ -285,7 +285,7 @@ vec4 bgfxTexelFetch(BgfxSampler3D _sampler, ivec3 _coord, int _lod)
 
 #		define SAMPLER3D(_name, _reg) \
 			uniform SamplerState _name ## Sampler : REGISTER(s, _reg); \
-			uniform Texture3D _name ## Texture : REGISTER(t[_reg]); \
+			uniform Texture3D _name ## Texture : REGISTER(t, _reg); \
 			static BgfxSampler3D _name = { _name ## Sampler, _name ## Texture }
 #		define ISAMPLER3D(_name, _reg) \
 			uniform Texture3D<ivec4> _name ## Texture : REGISTER(t, _reg); \

+ 4 - 0
src/config.h

@@ -343,4 +343,8 @@
 #	define BGFX_CONFIG_RENDERDOC_CAPTURE_KEYS { eRENDERDOC_Key_F11 }
 #endif // BGFX_CONFIG_RENDERDOC_CAPTURE_KEYS
 
+#ifndef BGFX_CONFIG_API_SEMAPHORE_TIMEOUT
+#	define BGFX_CONFIG_API_SEMAPHORE_TIMEOUT (-1)
+#endif // BGFX_CONFIG_API_SEMAPHORE_TIMEOUT
+
 #endif // BGFX_CONFIG_H_HEADER_GUARD

+ 5 - 1
src/glimports.h

@@ -162,6 +162,7 @@ typedef void           (GL_APIENTRYP PFNGLOBJECTLABELPROC) (GLenum identifier, G
 typedef void           (GL_APIENTRYP PFNGLOBJECTPTRLABELPROC) (const void *ptr, GLsizei length, const GLchar *label);
 typedef void           (GL_APIENTRYP PFNGLPIXELSTOREIPROC) (GLenum pname, GLint param);
 typedef void           (GL_APIENTRYP PFNGLPOINTSIZEPROC) (GLfloat size);
+typedef void           (GL_APIENTRYP PFNGLPOLYGONMODEPROC) (GLenum face, GLenum mode);
 typedef void           (GL_APIENTRYP PFNGLPOPDEBUGGROUPPROC) (void);
 typedef void           (GL_APIENTRYP PFNGLPROGRAMBINARYPROC) (GLuint program, GLenum binaryFormat, const void *binary, GLsizei length);
 typedef void           (GL_APIENTRYP PFNGLPROGRAMPARAMETERIPROC) (GLuint program, GLenum pname, GLint value);
@@ -404,7 +405,8 @@ GL_IMPORT______(false, PFNGLVIEWPORTPROC,                          glViewport);
 
 #	if BGFX_CONFIG_RENDERER_OPENGL
 GL_IMPORT______(false, PFNGLCLEARDEPTHPROC,                        glClearDepth);
-GL_IMPORT______(false, PFNGLPOINTSIZEPROC,                         glPointSize);
+GL_IMPORT______(true,  PFNGLPOINTSIZEPROC,                         glPointSize);
+GL_IMPORT______(true,  PFNGLPOLYGONMODEPROC,                       glPolygonMode);
 
 GL_IMPORT_ARB__(true,  PFNGLDEBUGMESSAGECONTROLPROC,               glDebugMessageControl);
 GL_IMPORT_ARB__(true,  PFNGLDEBUGMESSAGEINSERTPROC,                glDebugMessageInsert);
@@ -467,6 +469,8 @@ GL_IMPORT______(true,  PFNGLFRAMETERMINATORGREMEDYPROC,            glFrameTermin
 GL_IMPORT______(true,  PFNGLGETTRANSLATEDSHADERSOURCEANGLEPROC,    glGetTranslatedShaderSourceANGLE);
 
 #if !BGFX_CONFIG_RENDERER_OPENGL
+GL_IMPORT______(true,  PFNGLPOINTSIZEPROC,                         glPointSize);
+GL_IMPORT______(true,  PFNGLPOLYGONMODEPROC,                       glPolygonMode);
 GL_IMPORT_ANGLE(true,  PFNGLBLITFRAMEBUFFERPROC,                   glBlitFramebuffer);
 GL_IMPORT_ANGLE(true,  PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC,    glRenderbufferStorageMultisample);
 

+ 0 - 1
src/hmd.h

@@ -26,7 +26,6 @@ namespace bgfx
 
 	struct VRDesc
 	{
-		uint64_t m_adapterLuid;
 		uint32_t m_deviceType;
 		float m_refreshRate;
 		VRSize m_deviceSize;

+ 32 - 8
src/hmd_ovr.cpp

@@ -30,11 +30,21 @@ namespace bgfx
 
 	VRImplOVR::~VRImplOVR()
 	{
+		if (NULL != g_platformData.session)
+		{
+			return;
+		}
+
 		BX_CHECK(NULL == m_session, "OVR not shutdown properly.");
 	}
 
 	bool VRImplOVR::init()
 	{
+		if (NULL != g_platformData.session)
+		{
+			return true;
+		}
+
 		ovrResult initialized = ovr_Initialize(NULL);
 		if (!OVR_SUCCESS(initialized))
 		{
@@ -47,21 +57,30 @@ namespace bgfx
 
 	void VRImplOVR::shutdown()
 	{
+		if (NULL != g_platformData.session)
+		{
+			return;
+		}
+
 		ovr_Shutdown();
 	}
 
 	void VRImplOVR::connect(VRDesc* _desc)
 	{
-		ovrGraphicsLuid luid;
-		ovrResult result = ovr_Create(&m_session, &luid);
-		if (!OVR_SUCCESS(result))
+		if (NULL == g_platformData.session)
 		{
-			BX_TRACE("Failed to create OVR device.");
-			return;
+			ovrGraphicsLuid luid;
+			ovrResult result = ovr_Create(&m_session, &luid);
+			if (!OVR_SUCCESS(result))
+			{
+				BX_TRACE("Failed to create OVR device.");
+				return;
+			}
+		}
+		else
+		{
+			m_session = (ovrSession)g_platformData.session;
 		}
-
-		BX_STATIC_ASSERT(sizeof(_desc->m_adapterLuid) >= sizeof(luid));
-		memcpy(&_desc->m_adapterLuid, &luid, sizeof(luid));
 
 		ovrHmdDesc hmdDesc = ovr_GetHmdDesc(m_session);
 		_desc->m_deviceType = hmdDesc.Type;
@@ -118,6 +137,11 @@ namespace bgfx
 
 	void VRImplOVR::disconnect()
 	{
+		if (NULL != g_platformData.session)
+		{
+			return;
+		}
+
 		if (NULL != m_session)
 		{
 			ovr_Destroy(m_session);

+ 2 - 2
src/image.cpp

@@ -258,9 +258,9 @@ namespace bgfx
 		_depth  = bx::uint16_max(1, _depth);
 
 		uint32_t max = bx::uint32_max(_width, bx::uint32_max(_height, _depth) );
-		uint8_t numMips = uint8_t(bx::flog2(float(max) ) );
+		uint32_t numMips = bx::uint32_max(1, uint8_t(bx::flog2(float(max) ) ) );
 
-		return numMips;
+		return uint8_t(numMips);
 	}
 
 	uint32_t imageGetSize(TextureFormat::Enum _format, uint16_t _width, uint16_t _height, uint16_t _depth, uint16_t _numLayers, bool _cubeMap, uint8_t _numMips)

+ 68 - 32
src/renderer_gl.cpp

@@ -1015,6 +1015,10 @@ namespace bgfx { namespace gl
 		}
 	}
 
+	static void GL_APIENTRY stubPolygonMode(GLenum /*_face*/, GLenum /*_mode*/)
+	{
+	}
+
 	typedef void (*PostSwapBuffersFn)(uint32_t _width, uint32_t _height);
 
 	static const char* getGLString(GLenum _name)
@@ -1928,6 +1932,11 @@ namespace bgfx { namespace gl
 				: 0
 				;
 
+			if (NULL == glPolygonMode)
+			{
+				glPolygonMode = stubPolygonMode;
+			}
+
 			if (s_extension[Extension::ARB_copy_image].m_supported
 			||  s_extension[Extension::EXT_copy_image].m_supported
 			||  s_extension[Extension:: NV_copy_image].m_supported
@@ -3755,6 +3764,7 @@ namespace bgfx { namespace gl
 			GLSL_TYPE(GL_UNSIGNED_INT_IMAGE_1D);
 
 			GLSL_TYPE(GL_IMAGE_2D);
+			GLSL_TYPE(GL_IMAGE_2D_ARRAY);
 			GLSL_TYPE(GL_INT_IMAGE_2D);
 			GLSL_TYPE(GL_UNSIGNED_INT_IMAGE_2D);
 
@@ -3852,6 +3862,7 @@ namespace bgfx { namespace gl
 		case GL_UNSIGNED_INT_IMAGE_1D:
 
 		case GL_IMAGE_2D:
+		case GL_IMAGE_2D_ARRAY:
 		case GL_INT_IMAGE_2D:
 		case GL_UNSIGNED_INT_IMAGE_2D:
 
@@ -4351,6 +4362,11 @@ namespace bgfx { namespace gl
 		, const GLvoid* _data
 	)
 	{
+		if (NULL == _data)
+		{
+			return;
+		}
+
 		if (_target == GL_TEXTURE_3D
 		||  _target == GL_TEXTURE_2D_ARRAY
 		||  _target == GL_TEXTURE_CUBE_MAP_ARRAY)
@@ -4421,7 +4437,19 @@ namespace bgfx { namespace gl
 		else if (_target == GL_TEXTURE_2D_ARRAY
 			 ||  _target == GL_TEXTURE_CUBE_MAP_ARRAY)
 		{
-			texSubImage(_target, _level, 0, 0, _depth, _width, _height, 1, _format, _type, _data);
+			texSubImage(
+				  _target
+				, _level
+				, 0
+				, 0
+				, _depth
+				, _width
+				, _height
+				, 1
+				, _format
+				, _type
+				, _data
+				);
 		}
 		else if (_target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY)
 		{
@@ -5964,7 +5992,8 @@ namespace bgfx { namespace gl
 		uint32_t dsFlags = _flags & (BGFX_CLEAR_DISCARD_DEPTH|BGFX_CLEAR_DISCARD_STENCIL);
 		if (BGFX_CLEAR_NONE != dsFlags)
 		{
-			if ( (BGFX_CLEAR_DISCARD_DEPTH|BGFX_CLEAR_DISCARD_STENCIL) == dsFlags)
+			if (!BX_ENABLED(BGFX_CONFIG_RENDERER_OPENGLES)
+			&&  (BGFX_CLEAR_DISCARD_DEPTH|BGFX_CLEAR_DISCARD_STENCIL) == dsFlags)
 			{
 				buffers[idx++] = GL_DEPTH_STENCIL_ATTACHMENT;
 			}
@@ -6122,11 +6151,17 @@ namespace bgfx { namespace gl
 
 		uint8_t primIndex;
 		{
-			const uint64_t pt = _render->m_debug&BGFX_DEBUG_WIREFRAME ? BGFX_STATE_PT_LINES : 0;
+			const uint64_t pt = 0;
 			primIndex = uint8_t(pt>>BGFX_STATE_PT_SHIFT);
 		}
 		PrimInfo prim = s_primInfo[primIndex];
 
+		GL_CHECK(glPolygonMode(GL_FRONT_AND_BACK
+			, _render->m_debug&BGFX_DEBUG_WIREFRAME
+			? GL_LINE
+			: GL_FILL
+			) );
+
 		uint32_t baseVertex = 0;
 		GLuint currentVao = 0;
 		bool wasCompute = false;
@@ -6357,7 +6392,7 @@ namespace bgfx { namespace gl
 										GL_CHECK(glBindImageTexture(ii
 											, texture.m_id
 											, bind.m_un.m_compute.m_mip
-											, GL_FALSE
+											, texture.isCubeMap()?GL_TRUE:GL_FALSE
 											, 0
 											, s_access[bind.m_un.m_compute.m_access]
 											, s_imageFormat[bind.m_un.m_compute.m_format])
@@ -6626,38 +6661,39 @@ namespace bgfx { namespace gl
 						viewState.m_alphaRef = ref/255.0f;
 					}
 
-#if BGFX_CONFIG_RENDERER_OPENGL
-					if ( (BGFX_STATE_PT_POINTS|BGFX_STATE_POINT_SIZE_MASK) & changedFlags)
+					if (BX_ENABLED(BGFX_CONFIG_RENDERER_OPENGL) )
 					{
-						float pointSize = (float)(bx::uint32_max(1, (newFlags&BGFX_STATE_POINT_SIZE_MASK)>>BGFX_STATE_POINT_SIZE_SHIFT) );
-						GL_CHECK(glPointSize(pointSize) );
-					}
+						if ( (BGFX_STATE_PT_POINTS|BGFX_STATE_POINT_SIZE_MASK) & changedFlags)
+						{
+							float pointSize = (float)(bx::uint32_max(1, (newFlags&BGFX_STATE_POINT_SIZE_MASK)>>BGFX_STATE_POINT_SIZE_SHIFT) );
+							GL_CHECK(glPointSize(pointSize) );
+						}
 
-					if (BGFX_STATE_MSAA & changedFlags)
-					{
-						GL_CHECK(BGFX_STATE_MSAA & newFlags
-							? glEnable(GL_MULTISAMPLE)
-							: glDisable(GL_MULTISAMPLE)
-							);
-					}
+						if (BGFX_STATE_MSAA & changedFlags)
+						{
+							GL_CHECK(BGFX_STATE_MSAA & newFlags
+								? glEnable(GL_MULTISAMPLE)
+								: glDisable(GL_MULTISAMPLE)
+								);
+						}
 
-					if (BGFX_STATE_LINEAA & changedFlags)
-					{
-						GL_CHECK(BGFX_STATE_LINEAA & newFlags
-							? glEnable(GL_LINE_SMOOTH)
-							: glDisable(GL_LINE_SMOOTH)
-							);
-					}
+						if (BGFX_STATE_LINEAA & changedFlags)
+						{
+							GL_CHECK(BGFX_STATE_LINEAA & newFlags
+								? glEnable(GL_LINE_SMOOTH)
+								: glDisable(GL_LINE_SMOOTH)
+								);
+						}
 
-					if (m_conservativeRasterSupport
-					&&  BGFX_STATE_CONSERVATIVE_RASTER & changedFlags)
-					{
-						GL_CHECK(BGFX_STATE_CONSERVATIVE_RASTER & newFlags
-							? glEnable(GL_CONSERVATIVE_RASTERIZATION_NV)
-							: glDisable(GL_CONSERVATIVE_RASTERIZATION_NV)
-							);
+						if (m_conservativeRasterSupport
+						&&  BGFX_STATE_CONSERVATIVE_RASTER & changedFlags)
+						{
+							GL_CHECK(BGFX_STATE_CONSERVATIVE_RASTER & newFlags
+								? glEnable(GL_CONSERVATIVE_RASTERIZATION_NV)
+								: glDisable(GL_CONSERVATIVE_RASTERIZATION_NV)
+								);
+						}
 					}
-#endif // BGFX_CONFIG_RENDERER_OPENGL
 
 					if ( (BGFX_STATE_ALPHA_WRITE|BGFX_STATE_RGB_WRITE) & changedFlags)
 					{
@@ -6787,7 +6823,7 @@ namespace bgfx { namespace gl
 						blendFactor = draw.m_rgba;
 					}
 
-					const uint64_t pt = _render->m_debug&BGFX_DEBUG_WIREFRAME ? BGFX_STATE_PT_LINES : newFlags&BGFX_STATE_PT_MASK;
+					const uint64_t pt = newFlags&BGFX_STATE_PT_MASK;
 					primIndex = uint8_t(pt>>BGFX_STATE_PT_SHIFT);
 					prim = s_primInfo[primIndex];
 				}

+ 20 - 0
src/renderer_gl.h

@@ -720,6 +720,10 @@ typedef uint64_t GLuint64;
 #	define GL_IMAGE_2D 0x904D
 #endif // GL_IMAGE_2D
 
+#ifndef GL_IMAGE_2D_ARRAY
+#	define GL_IMAGE_2D_ARRAY 0x9053
+#endif // GL_IMAGE_2D_ARRAY
+
 #ifndef GL_IMAGE_3D
 #	define GL_IMAGE_3D 0x904E
 #endif // GL_IMAGE_3D
@@ -915,6 +919,22 @@ typedef uint64_t GLuint64;
 #	define GL_DEBUG_SEVERITY_NOTIFICATION 0x826b
 #endif // GL_DEBUG_SEVERITY_NOTIFICATION
 
+#ifndef GL_LINE
+#	define GL_LINE 0x1B01
+#endif // GL_LINE
+
+#ifndef GL_FILL
+#	define GL_FILL 0x1B02
+#endif // GL_FILL
+
+#ifndef GL_MULTISAMPLE
+#	define GL_MULTISAMPLE 0x809D
+#endif // GL_MULTISAMPLE
+
+#ifndef GL_LINE_SMOOTH
+#	define GL_LINE_SMOOTH 0x0B20
+#endif // GL_LINE_SMOOTH
+
 #if BX_PLATFORM_NACL
 #	include "glcontext_ppapi.h"
 #elif BX_PLATFORM_WINDOWS

+ 54 - 23
tools/shaderc/shaderc.cpp

@@ -422,7 +422,7 @@ namespace bgfx
 
 	struct Preprocessor
 	{
-		Preprocessor(const char* _filePath, bool _essl, const char* _includeDir = NULL)
+		Preprocessor(const char* _filePath, bool _essl)
 			: m_tagptr(m_tags)
 			, m_scratchPos(0)
 			, m_fgetsPos(0)
@@ -459,11 +459,6 @@ namespace bgfx
 			m_tagptr->data = scratch(_filePath);
 			m_tagptr++;
 
-			if (NULL != _includeDir)
-			{
-				addInclude(_includeDir);
-			}
-
 			if (!_essl)
 			{
 				m_default = "#define lowp\n#define mediump\n#define highp\n";
@@ -784,8 +779,7 @@ namespace bgfx
 		const char* platform = cmdLine.findOption('\0', "platform");
 		if (NULL == platform)
 		{
-			help("Must specify platform.");
-			return EXIT_FAILURE;
+			platform = "";
 		}
 
 		bool raw = cmdLine.hasArg('\0', "raw");
@@ -796,6 +790,7 @@ namespace bgfx
 		uint32_t d3d   = 11;
 		uint32_t metal = 0;
 		uint32_t pssl  = 0;
+		uint32_t spirv = 0;
 		const char* profile = cmdLine.findOption('p', "profile");
 		if (NULL != profile)
 		{
@@ -824,6 +819,10 @@ namespace bgfx
 			{
 				pssl = 1;
 			}
+			else if (0 == strcmp(profile, "spirv") )
+			{
+				spirv = 1;
+			}
 			else
 			{
 				glsl = atoi(profile);
@@ -865,7 +864,13 @@ namespace bgfx
 		bool preprocessOnly = cmdLine.hasArg("preprocess");
 		const char* includeDir = cmdLine.findOption('i');
 
-		Preprocessor preprocessor(filePath, 0 != essl, includeDir);
+		Preprocessor preprocessor(filePath, 0 != essl);
+
+		for (int ii = 1; NULL != includeDir; ++ii)
+		{
+			preprocessor.addInclude(includeDir);
+			includeDir = cmdLine.findOption(ii, 'i');
+		}
 
 		std::string dir;
 		{
@@ -902,17 +907,25 @@ namespace bgfx
 		preprocessor.setDefaultDefine("BX_PLATFORM_PS4");
 		preprocessor.setDefaultDefine("BX_PLATFORM_WINDOWS");
 		preprocessor.setDefaultDefine("BX_PLATFORM_XBOX360");
+		preprocessor.setDefaultDefine("BX_PLATFORM_XBOXONE");
+
 //		preprocessor.setDefaultDefine("BGFX_SHADER_LANGUAGE_ESSL");
 		preprocessor.setDefaultDefine("BGFX_SHADER_LANGUAGE_GLSL");
 		preprocessor.setDefaultDefine("BGFX_SHADER_LANGUAGE_HLSL");
 		preprocessor.setDefaultDefine("BGFX_SHADER_LANGUAGE_METAL");
 		preprocessor.setDefaultDefine("BGFX_SHADER_LANGUAGE_PSSL");
+
 		preprocessor.setDefaultDefine("BGFX_SHADER_TYPE_COMPUTE");
 		preprocessor.setDefaultDefine("BGFX_SHADER_TYPE_FRAGMENT");
 		preprocessor.setDefaultDefine("BGFX_SHADER_TYPE_VERTEX");
 
 		char glslDefine[128];
-		bx::snprintf(glslDefine, BX_COUNTOF(glslDefine), "BGFX_SHADER_LANGUAGE_GLSL=%d", essl ? 1 : glsl);
+		bx::snprintf(glslDefine, BX_COUNTOF(glslDefine)
+				, "BGFX_SHADER_LANGUAGE_GLSL=%d"
+				, essl  ? 1
+				: spirv ? 130
+				: glsl
+				);
 
 		if (0 == bx::stricmp(platform, "android") )
 		{
@@ -965,11 +978,6 @@ namespace bgfx
 			preprocessor.setDefine("BGFX_SHADER_LANGUAGE_PSSL=1");
 			preprocessor.setDefine("lit=lit_reserved");
 		}
-		else
-		{
-			fprintf(stderr, "Unknown platform %s?!", platform);
-			return EXIT_FAILURE;
-		}
 
 		preprocessor.setDefine("M_PI=3.1415926535897932384626433832795");
 
@@ -1242,7 +1250,8 @@ namespace bgfx
 				{
 					if (0 != glsl
 					||  0 != essl
-					||  0 != metal)
+					||  0 != metal
+					||  0 != spirv)
 					{
 					}
 					else
@@ -1384,6 +1393,10 @@ namespace bgfx
 								compiled = compileGLSLShader(cmdLine, essl, code, writer);
 	#endif // 0
 							}
+							else if (0 != spirv)
+							{
+								compiled = compileSPIRVShader(cmdLine, 0, preprocessor.m_preprocessed, writer);
+							}
 							else if (0 != pssl)
 							{
 								compiled = compilePSSLShader(cmdLine, 0, preprocessor.m_preprocessed, writer);
@@ -1425,7 +1438,8 @@ namespace bgfx
 				{
 					if (0 != glsl
 					||  0 != essl
-					||  0 != metal)
+					||  0 != metal
+					||  0 != spirv)
 					{
 						if (0 == essl)
 						{
@@ -1807,7 +1821,8 @@ namespace bgfx
 
 							if (0 != glsl
 							||  0 != essl
-							||  0 != metal)
+							||  0 != metal
+							||  0 != spirv )
 							{
 								std::string code;
 
@@ -1829,6 +1844,10 @@ namespace bgfx
 									{
 										bx::stringPrintf(code, "#version 120\n");
 									}
+									else if (0 != spirv)
+									{
+										bx::stringPrintf(code, "#version 130\n");
+									}
 									else
 									{
 										bx::stringPrintf(code, "#version %s\n", need130 ? "130" : profile);
@@ -1957,11 +1976,23 @@ namespace bgfx
 								}
 
 								code += preprocessor.m_preprocessed;
-								compiled = compileGLSLShader(cmdLine
-									, metal ? BX_MAKEFOURCC('M', 'T', 'L', 0) : essl
-									, code
-									, writer
-									);
+
+								if (0 != spirv)
+								{
+									compiled = compileSPIRVShader(cmdLine
+										, 0
+										, code
+										, writer
+										);
+								}
+								else
+								{
+									compiled = compileGLSLShader(cmdLine
+										, metal ? BX_MAKEFOURCC('M', 'T', 'L', 0) : essl
+										, code
+										, writer
+										);
+								}
 							}
 							else if (0 != pssl)
 							{

+ 2 - 2
tools/shaderc/shaderc_hlsl.cpp

@@ -659,7 +659,7 @@ namespace bgfx { namespace hlsl
 			UniformNameList unusedUniforms;
 			if (!getReflectionDataD3D11(code, profile[0] == 'v', uniforms, numAttrs, attrs, size, unusedUniforms) )
 			{
-				fprintf(stderr, "Unable to get D3D11 reflection data.\n");
+				fprintf(stderr, "Error: Unable to get D3D11 reflection data.\n");
 				goto error;
 			}
 
@@ -699,7 +699,7 @@ namespace bgfx { namespace hlsl
 				}
 
 				// recompile with the unused uniforms converted to statics
-				return compileHLSLShader(_cmdLine, _version, output.c_str(), _writer);
+				return compile(_cmdLine, _version, output.c_str(), _writer, false);
 			}
 		}