mirror of
https://github.com/scratchfoundation/bgfx.git
synced 2024-11-25 00:58:30 -05:00
Updated imgui.
This commit is contained in:
parent
2c3bd9ce95
commit
06624bb7c2
7 changed files with 566 additions and 280 deletions
44
3rdparty/ocornut-imgui/imgui.cpp
vendored
44
3rdparty/ocornut-imgui/imgui.cpp
vendored
|
@ -128,8 +128,10 @@
|
|||
// swap video buffer, etc.
|
||||
}
|
||||
|
||||
- after calling ImGui::NewFrame() you can read back 'io.WantCaptureMouse' and 'io.WantCaptureKeyboard' to tell if ImGui
|
||||
wants to use your inputs. if it does you can discard/hide the inputs from the rest of your application.
|
||||
- after calling ImGui::NewFrame() you can read back flags from the IO structure to tell how ImGui intends to use your inputs.
|
||||
When 'io.WantCaptureMouse' or 'io.WantCaptureKeyboard' flags are set you may want to discard/hide the inputs from the rest of your application.
|
||||
When 'io.WantInputsCharacters' is set to may want to notify your OS to popup an onscreen keyboard, if available.
|
||||
|
||||
|
||||
API BREAKING CHANGES
|
||||
====================
|
||||
|
@ -1901,6 +1903,7 @@ void ImGui::NewFrame()
|
|||
bool mouse_owned_by_application = mouse_earliest_button_down != -1 && !g.IO.MouseDownOwned[mouse_earliest_button_down];
|
||||
g.IO.WantCaptureMouse = (!mouse_owned_by_application && g.HoveredWindow != NULL) || (!mouse_owned_by_application && mouse_any_down) || (g.ActiveId != 0) || (!g.OpenedPopupStack.empty()) || (g.CaptureMouseNextFrame);
|
||||
g.IO.WantCaptureKeyboard = (g.ActiveId != 0) || (g.CaptureKeyboardNextFrame);
|
||||
g.IO.WantInputCharacters = (g.ActiveId != 0 && g.InputTextState.Id == g.ActiveId);
|
||||
g.MouseCursor = ImGuiMouseCursor_Arrow;
|
||||
g.CaptureMouseNextFrame = g.CaptureKeyboardNextFrame = false;
|
||||
|
||||
|
@ -2256,10 +2259,14 @@ void ImGui::Render()
|
|||
if (!(g.FocusedWindow && !g.FocusedWindow->WasActive && g.FocusedWindow->Active)) // Unless we just made a popup appear
|
||||
{
|
||||
if (g.HoveredRootWindow != NULL)
|
||||
{
|
||||
FocusWindow(g.HoveredWindow);
|
||||
if (!(g.HoveredWindow->Flags & ImGuiWindowFlags_NoMove))
|
||||
{
|
||||
g.MovedWindow = g.HoveredWindow;
|
||||
SetActiveID(g.HoveredRootWindow->MoveID, g.HoveredRootWindow);
|
||||
}
|
||||
}
|
||||
else if (g.FocusedWindow != NULL && GetFrontMostModalRootWindow() == NULL)
|
||||
{
|
||||
// Clicking on void disable focus
|
||||
|
@ -2826,6 +2833,7 @@ ImVec2 ImGui::GetMousePos()
|
|||
return GImGui->IO.MousePos;
|
||||
}
|
||||
|
||||
// NB: prefer to call right after BeginPopup(). At the time Selectable/MenuItem is activated, the popup is already closed!
|
||||
ImVec2 ImGui::GetMousePosOnOpeningCurrentPopup()
|
||||
{
|
||||
ImGuiState& g = *GImGui;
|
||||
|
@ -3173,7 +3181,7 @@ bool ImGui::BeginPopupContextVoid(const char* str_id, int mouse_button)
|
|||
bool ImGui::BeginChild(const char* str_id, const ImVec2& size_arg, bool border, ImGuiWindowFlags extra_flags)
|
||||
{
|
||||
ImGuiWindow* window = GetCurrentWindow();
|
||||
ImGuiWindowFlags flags = ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_ChildWindow;
|
||||
ImGuiWindowFlags flags = ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_ChildWindow;
|
||||
|
||||
const ImVec2 content_avail = ImGui::GetContentRegionAvail();
|
||||
ImVec2 size = size_arg;
|
||||
|
@ -3248,7 +3256,7 @@ bool ImGui::BeginChildFrame(ImGuiID id, const ImVec2& size)
|
|||
const ImGuiStyle& style = g.Style;
|
||||
ImGui::PushStyleColor(ImGuiCol_ChildWindowBg, style.Colors[ImGuiCol_FrameBg]);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ChildWindowRounding, style.FrameRounding);
|
||||
return ImGui::BeginChild(id, size);
|
||||
return ImGui::BeginChild(id, size, false, ImGuiWindowFlags_NoMove);
|
||||
}
|
||||
|
||||
void ImGui::EndChildFrame()
|
||||
|
@ -3898,9 +3906,11 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_
|
|||
// We set this up after processing the resize grip so that our clip rectangle doesn't lag by a frame
|
||||
// Note that if our window is collapsed we will end up with a null clipping rectangle which is the correct behavior.
|
||||
const ImRect title_bar_rect = window->TitleBarRect();
|
||||
ImVec4 clip_rect(title_bar_rect.Min.x+0.5f+window->WindowPadding.x*0.5f, title_bar_rect.Max.y+window->MenuBarHeight()+0.5f, window->Rect().Max.x+0.5f-window->WindowPadding.x*0.5f, window->Rect().Max.y-1.5f);
|
||||
ImRect clip_rect(title_bar_rect.Min.x+0.5f+window->WindowPadding.x*0.5f, title_bar_rect.Max.y+window->MenuBarHeight()+0.5f, window->Pos.x+window->Size.x+0.5f-window->WindowPadding.x*0.5f, window->Pos.y+window->Size.y+0.5f);
|
||||
if ((flags & ImGuiWindowFlags_ChildWindow) && (flags & ImGuiWindowFlags_ShowBorders))
|
||||
clip_rect.Min += ImVec2(1.0f,1.0f);
|
||||
if (window->ScrollbarY)
|
||||
clip_rect.z -= style.ScrollbarWidth;
|
||||
clip_rect.Max.x -= style.ScrollbarWidth;
|
||||
PushClipRect(clip_rect);
|
||||
|
||||
// Clear 'accessed' flag last thing
|
||||
|
@ -4343,6 +4353,12 @@ float ImGui::GetWindowWidth()
|
|||
return window->Size.x;
|
||||
}
|
||||
|
||||
float ImGui::GetWindowHeight()
|
||||
{
|
||||
ImGuiWindow* window = GImGui->CurrentWindow;
|
||||
return window->Size.y;
|
||||
}
|
||||
|
||||
ImVec2 ImGui::GetWindowPos()
|
||||
{
|
||||
ImGuiState& g = *GImGui;
|
||||
|
@ -7022,8 +7038,9 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
|
|||
if (g.IO.InputCharacters[0])
|
||||
{
|
||||
// Process text input (before we check for Return because using some IME will effectively send a Return?)
|
||||
for (int n = 0; n < IM_ARRAYSIZE(g.IO.InputCharacters) && g.IO.InputCharacters[n]; n++)
|
||||
if (!is_ctrl_down && !is_alt_down)
|
||||
{
|
||||
for (int n = 0; n < IM_ARRAYSIZE(g.IO.InputCharacters) && g.IO.InputCharacters[n]; n++)
|
||||
if (unsigned int c = (unsigned int)g.IO.InputCharacters[n])
|
||||
{
|
||||
// Insert character if they pass filtering
|
||||
|
@ -8555,7 +8572,7 @@ void ImGui::Columns(int columns_count, const char* id, bool border)
|
|||
ItemSize(ImVec2(0,0)); // Advance to column 0
|
||||
ImGui::PopItemWidth();
|
||||
PopClipRect();
|
||||
window->DrawList->ChannelsMerge(window->DC.ColumnsCount);
|
||||
window->DrawList->ChannelsMerge();
|
||||
|
||||
window->DC.ColumnsCellMaxY = ImMax(window->DC.ColumnsCellMaxY, window->DC.CursorPos.y);
|
||||
window->DC.CursorPos.y = window->DC.ColumnsCellMaxY;
|
||||
|
@ -8844,7 +8861,7 @@ void ImGui::ShowMetricsWindow(bool* opened)
|
|||
ImGui::Text("%d vertices, %d indices (%d triangles)", ImGui::GetIO().MetricsRenderVertices, ImGui::GetIO().MetricsRenderIndices, ImGui::GetIO().MetricsRenderIndices / 3);
|
||||
ImGui::Text("%d allocations", ImGui::GetIO().MetricsAllocs);
|
||||
static bool show_clip_rects = true;
|
||||
ImGui::Checkbox("Show clipping rectangles when hovering ImDrawList", &show_clip_rects);
|
||||
ImGui::Checkbox("Show clipping rectangles when hovering a ImDrawCmd", &show_clip_rects);
|
||||
ImGui::Separator();
|
||||
|
||||
struct Funcs
|
||||
|
@ -8923,6 +8940,15 @@ void ImGui::ShowMetricsWindow(bool* opened)
|
|||
}
|
||||
ImGui::TreePop();
|
||||
}
|
||||
if (ImGui::TreeNode("Basic state"))
|
||||
{
|
||||
ImGui::Text("FocusedWindow: '%s'", g.FocusedWindow ? g.FocusedWindow->Name : "NULL");
|
||||
ImGui::Text("HoveredWindow: '%s'", g.HoveredWindow ? g.HoveredWindow->Name : "NULL");
|
||||
ImGui::Text("HoveredRootWindow: '%s'", g.HoveredRootWindow ? g.HoveredRootWindow->Name : "NULL");
|
||||
ImGui::Text("HoveredID: 0x%08X/0x%08X", g.HoveredId, g.HoveredIdPreviousFrame); // Data is "in-flight" so depending on when the Metrics window is called we may see current frame information or not
|
||||
ImGui::Text("ActiveID: 0x%08X/0x%08X", g.ActiveId, g.ActiveIdPreviousFrame);
|
||||
ImGui::TreePop();
|
||||
}
|
||||
g.DisableHideTextAfterDoubleHash--;
|
||||
}
|
||||
ImGui::End();
|
||||
|
|
24
3rdparty/ocornut-imgui/imgui.h
vendored
24
3rdparty/ocornut-imgui/imgui.h
vendored
|
@ -131,6 +131,7 @@ namespace ImGui
|
|||
IMGUI_API ImVec2 GetWindowPos(); // get current window position in screen space (useful if you want to do your own drawing via the DrawList api)
|
||||
IMGUI_API ImVec2 GetWindowSize(); // get current window size
|
||||
IMGUI_API float GetWindowWidth();
|
||||
IMGUI_API float GetWindowHeight();
|
||||
IMGUI_API bool IsWindowCollapsed();
|
||||
|
||||
IMGUI_API void SetNextWindowPos(const ImVec2& pos, ImGuiSetCond cond = 0); // set next window position. call before Begin()
|
||||
|
@ -177,7 +178,7 @@ namespace ImGui
|
|||
IMGUI_API void PopButtonRepeat();
|
||||
|
||||
// Cursor / Layout
|
||||
IMGUI_API void BeginGroup(); // once closing a group it is seen as a single item (so you can use IsItemHovered() on a group, SameLine() between groups, etc.
|
||||
IMGUI_API void BeginGroup(); // lock horizontal starting position. once closing a group it is seen as a single item (so you can use IsItemHovered() on a group, SameLine() between groups, etc.
|
||||
IMGUI_API void EndGroup();
|
||||
IMGUI_API void Separator(); // horizontal line
|
||||
IMGUI_API void SameLine(float local_pos_x = 0.0f, float spacing_w = -1.0f); // call between widgets or groups to layout them horizontally
|
||||
|
@ -399,7 +400,7 @@ namespace ImGui
|
|||
IMGUI_API bool IsMouseDragging(int button = 0, float lock_threshold = -1.0f); // is mouse dragging. if lock_threshold < -1.0f uses io.MouseDraggingThreshold
|
||||
IMGUI_API ImVec2 GetMousePos(); // shortcut to ImGui::GetIO().MousePos provided by user, to be consistent with other calls
|
||||
IMGUI_API ImVec2 GetMousePosOnOpeningCurrentPopup(); // retrieve backup of mouse positioning at the time of opening popup we have BeginPopup() into
|
||||
IMGUI_API ImVec2 GetMouseDragDelta(int button = 0, float lock_threshold = -1.0f); // dragging amount since clicking, also see: GetItemActiveDragDelta(). if lock_threshold < -1.0f uses io.MouseDraggingThreshold
|
||||
IMGUI_API ImVec2 GetMouseDragDelta(int button = 0, float lock_threshold = -1.0f); // dragging amount since clicking. if lock_threshold < -1.0f uses io.MouseDraggingThreshold
|
||||
IMGUI_API void ResetMouseDragDelta(int button = 0); //
|
||||
IMGUI_API ImGuiMouseCursor GetMouseCursor(); // get desired cursor type, reset in ImGui::NewFrame(), this updated during the frame. valid before Render(). If you use software rendering by setting io.MouseDrawCursor ImGui will render those for you
|
||||
IMGUI_API void SetMouseCursor(ImGuiMouseCursor type); // set desired cursor type
|
||||
|
@ -724,6 +725,7 @@ struct ImGuiIO
|
|||
|
||||
bool WantCaptureMouse; // Mouse is hovering a window or widget is active (= ImGui will use your mouse input)
|
||||
bool WantCaptureKeyboard; // Widget is active (= ImGui will use your keyboard input)
|
||||
bool WantInputCharacters; // Some text input widget is active, which will read input characters from the InputCharacters array.
|
||||
float Framerate; // Framerate estimation, in frame per second. Rolling average estimation based on IO.DeltaTime over 120 frames
|
||||
int MetricsAllocs; // Number of active memory allocations
|
||||
int MetricsRenderVertices; // Vertices output during last call to Render()
|
||||
|
@ -1014,6 +1016,8 @@ struct ImDrawCmd
|
|||
ImTextureID TextureId; // User-provided texture ID. Set by user in ImfontAtlas::SetTexID() for fonts or passed to Image*() functions. Ignore if never using images or multiple fonts atlas.
|
||||
ImDrawCallback UserCallback; // If != NULL, call the function instead of rendering the vertices. clip_rect and texture_id will be set normally.
|
||||
void* UserCallbackData; // The draw callback code can access this.
|
||||
|
||||
ImDrawCmd() { ElemCount = 0; ClipRect.x = ClipRect.y = -8192.0f; ClipRect.z = ClipRect.w = +8192.0f; TextureId = NULL; UserCallback = NULL; UserCallbackData = NULL; }
|
||||
};
|
||||
|
||||
// Vertex index (override with, e.g. '#define ImDrawIdx unsigned int' in ImConfig)
|
||||
|
@ -1037,6 +1041,7 @@ IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT;
|
|||
#endif
|
||||
|
||||
// Draw channels are used by the Columns API to "split" the render list into different channels while building, so items of each column can be batched together.
|
||||
// You can also use them to simulate drawing layers and submit primitives in a different order than how they will be rendered.
|
||||
struct ImDrawChannel
|
||||
{
|
||||
ImVector<ImDrawCmd> CmdBuffer;
|
||||
|
@ -1065,8 +1070,9 @@ struct ImDrawList
|
|||
ImVector<ImVec4> _ClipRectStack; // [Internal]
|
||||
ImVector<ImTextureID> _TextureIdStack; // [Internal]
|
||||
ImVector<ImVec2> _Path; // [Internal] current path building
|
||||
int _ChannelCurrent; // [Internal] current channel number (0)
|
||||
ImVector<ImDrawChannel> _Channels; // [Internal] draw channels for columns API
|
||||
int _ChannelsCurrent; // [Internal] current channel number (0)
|
||||
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() { ClearFreeMemory(); }
|
||||
|
@ -1101,12 +1107,16 @@ 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(); }
|
||||
|
||||
// Channels
|
||||
// - Use to simulate layers. By switching channels to can render out-of-order (e.g. submit foreground primitives before background primitives)
|
||||
// - Use to minimize draw calls (e.g. if going back-and-forth between multiple non-overlapping clipping rectangles, prefer to append into separate channels then merge at the end)
|
||||
IMGUI_API void ChannelsSplit(int channels_count);
|
||||
IMGUI_API void ChannelsMerge();
|
||||
IMGUI_API void ChannelsSetCurrent(int channel_index);
|
||||
|
||||
// Advanced
|
||||
IMGUI_API void AddCallback(ImDrawCallback callback, void* callback_data); // Your rendering function must check for 'UserCallback' in ImDrawCmd and call the function instead of rendering triangles.
|
||||
IMGUI_API void AddDrawCmd(); // This is useful if you need to forcefully create a new draw call (to allow for dependent rendering / blending). Otherwise primitives are merged into the same draw-call as much as possible
|
||||
IMGUI_API void ChannelsSplit(int channel_count);
|
||||
IMGUI_API void ChannelsMerge(int channel_count);
|
||||
IMGUI_API void ChannelsSetCurrent(int idx);
|
||||
|
||||
// Internal helpers
|
||||
// NB: all primitives needs to be reserved via PrimReserve() beforehand!
|
||||
|
|
1
3rdparty/ocornut-imgui/imgui_demo.cpp
vendored
1
3rdparty/ocornut-imgui/imgui_demo.cpp
vendored
|
@ -1343,6 +1343,7 @@ void ImGui::ShowTestWindow(bool* opened)
|
|||
|
||||
ImGui::Text("WantCaptureMouse: %s", io.WantCaptureMouse ? "true" : "false");
|
||||
ImGui::Text("WantCaptureKeyboard: %s", io.WantCaptureKeyboard ? "true" : "false");
|
||||
ImGui::Text("WantInputCharacters: %s", io.WantInputCharacters ? "true" : "false");
|
||||
|
||||
ImGui::Button("Hover me\nto enforce\ninputs capture");
|
||||
if (ImGui::IsItemHovered())
|
||||
|
|
54
3rdparty/ocornut-imgui/imgui_draw.cpp
vendored
54
3rdparty/ocornut-imgui/imgui_draw.cpp
vendored
|
@ -85,7 +85,7 @@ using namespace IMGUI_STB_NAMESPACE;
|
|||
// ImDrawList
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static ImVec4 GNullClipRect(-9999.0f,-9999.0f, +9999.0f, +9999.0f);
|
||||
static ImVec4 GNullClipRect(-8192.0f, -8192.0f, +8192.0f, +8192.0f); // Large values that are easy to encode in a few bits+shift
|
||||
|
||||
void ImDrawList::Clear()
|
||||
{
|
||||
|
@ -98,7 +98,8 @@ void ImDrawList::Clear()
|
|||
_ClipRectStack.resize(0);
|
||||
_TextureIdStack.resize(0);
|
||||
_Path.resize(0);
|
||||
_ChannelCurrent = 0;
|
||||
_ChannelsCurrent = 0;
|
||||
_ChannelsCount = 1;
|
||||
// NB: Do not clear channels so our allocations are re-used after the first frame.
|
||||
}
|
||||
|
||||
|
@ -113,7 +114,8 @@ void ImDrawList::ClearFreeMemory()
|
|||
_ClipRectStack.clear();
|
||||
_TextureIdStack.clear();
|
||||
_Path.clear();
|
||||
_ChannelCurrent = 0;
|
||||
_ChannelsCurrent = 0;
|
||||
_ChannelsCount = 1;
|
||||
for (int i = 0; i < _Channels.Size; i++)
|
||||
{
|
||||
if (i == 0) memset(&_Channels[0], 0, sizeof(_Channels[0])); // channel 0 is a copy of CmdBuffer/IdxBuffer, don't destruct again
|
||||
|
@ -126,11 +128,8 @@ void ImDrawList::ClearFreeMemory()
|
|||
void ImDrawList::AddDrawCmd()
|
||||
{
|
||||
ImDrawCmd draw_cmd;
|
||||
draw_cmd.ElemCount = 0;
|
||||
draw_cmd.ClipRect = _ClipRectStack.Size ? _ClipRectStack.back() : GNullClipRect;
|
||||
draw_cmd.TextureId = _TextureIdStack.Size ? _TextureIdStack.back() : NULL;
|
||||
draw_cmd.UserCallback = NULL;
|
||||
draw_cmd.UserCallbackData = NULL;
|
||||
|
||||
IM_ASSERT(draw_cmd.ClipRect.x <= draw_cmd.ClipRect.z && draw_cmd.ClipRect.y <= draw_cmd.ClipRect.w);
|
||||
CmdBuffer.push_back(draw_cmd);
|
||||
|
@ -151,24 +150,34 @@ void ImDrawList::AddCallback(ImDrawCallback callback, void* callback_data)
|
|||
AddDrawCmd();
|
||||
}
|
||||
|
||||
void ImDrawList::ChannelsSplit(int channel_count)
|
||||
void ImDrawList::ChannelsSplit(int channels_count)
|
||||
{
|
||||
IM_ASSERT(_ChannelCurrent == 0);
|
||||
IM_ASSERT(_ChannelsCurrent == 0 && _ChannelsCount == 1);
|
||||
int old_channels_count = _Channels.Size;
|
||||
if (old_channels_count < channel_count)
|
||||
_Channels.resize(channel_count);
|
||||
for (int i = 0; i < channel_count; i++)
|
||||
if (old_channels_count < channels_count)
|
||||
_Channels.resize(channels_count);
|
||||
_ChannelsCount = channels_count;
|
||||
for (int i = 0; i < channels_count; i++)
|
||||
{
|
||||
if (i >= old_channels_count)
|
||||
new(&_Channels[i]) ImDrawChannel();
|
||||
else
|
||||
else if (i > 0)
|
||||
_Channels[i].CmdBuffer.resize(0), _Channels[i].IdxBuffer.resize(0);
|
||||
if (_Channels[i].CmdBuffer.Size == 0)
|
||||
{
|
||||
ImDrawCmd draw_cmd;
|
||||
draw_cmd.ClipRect = _ClipRectStack.back();
|
||||
draw_cmd.TextureId = _TextureIdStack.back();
|
||||
_Channels[i].CmdBuffer.push_back(draw_cmd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ImDrawList::ChannelsMerge(int channel_count)
|
||||
void ImDrawList::ChannelsMerge()
|
||||
{
|
||||
// Note that we never use or rely on channels.Size because it is merely a buffer that we never shrink back to 0 to keep all sub-buffers ready for use.
|
||||
// This is why this function takes 'channel_count' as a parameter of how many channels to merge (the user knows)
|
||||
if (channel_count < 2)
|
||||
if (_ChannelsCount <= 1)
|
||||
return;
|
||||
|
||||
ChannelsSetCurrent(0);
|
||||
|
@ -176,7 +185,7 @@ void ImDrawList::ChannelsMerge(int channel_count)
|
|||
CmdBuffer.pop_back();
|
||||
|
||||
int new_cmd_buffer_count = 0, new_idx_buffer_count = 0;
|
||||
for (int i = 1; i < channel_count; i++)
|
||||
for (int i = 1; i < _ChannelsCount; i++)
|
||||
{
|
||||
ImDrawChannel& ch = _Channels[i];
|
||||
if (ch.CmdBuffer.Size && ch.CmdBuffer.back().ElemCount == 0)
|
||||
|
@ -189,23 +198,24 @@ void ImDrawList::ChannelsMerge(int channel_count)
|
|||
|
||||
ImDrawCmd* cmd_write = CmdBuffer.Data + CmdBuffer.Size - new_cmd_buffer_count;
|
||||
_IdxWritePtr = IdxBuffer.Data + IdxBuffer.Size - new_idx_buffer_count;
|
||||
for (int i = 1; i < channel_count; i++)
|
||||
for (int i = 1; i < _ChannelsCount; i++)
|
||||
{
|
||||
ImDrawChannel& ch = _Channels[i];
|
||||
if (int sz = ch.CmdBuffer.Size) { memcpy(cmd_write, ch.CmdBuffer.Data, sz * sizeof(ImDrawCmd)); cmd_write += sz; }
|
||||
if (int sz = ch.IdxBuffer.Size) { memcpy(_IdxWritePtr, ch.IdxBuffer.Data, sz * sizeof(ImDrawIdx)); _IdxWritePtr += sz; }
|
||||
}
|
||||
AddDrawCmd();
|
||||
_ChannelsCount = 1;
|
||||
}
|
||||
|
||||
void ImDrawList::ChannelsSetCurrent(int idx)
|
||||
{
|
||||
if (_ChannelCurrent == idx) return;
|
||||
memcpy(&_Channels.Data[_ChannelCurrent].CmdBuffer, &CmdBuffer, sizeof(CmdBuffer));
|
||||
memcpy(&_Channels.Data[_ChannelCurrent].IdxBuffer, &IdxBuffer, sizeof(IdxBuffer));
|
||||
_ChannelCurrent = idx;
|
||||
memcpy(&CmdBuffer, &_Channels.Data[_ChannelCurrent].CmdBuffer, sizeof(CmdBuffer));
|
||||
memcpy(&IdxBuffer, &_Channels.Data[_ChannelCurrent].IdxBuffer, sizeof(IdxBuffer));
|
||||
if (_ChannelsCurrent == idx) return;
|
||||
memcpy(&_Channels.Data[_ChannelsCurrent].CmdBuffer, &CmdBuffer, sizeof(CmdBuffer)); // copy 12 bytes, four times
|
||||
memcpy(&_Channels.Data[_ChannelsCurrent].IdxBuffer, &IdxBuffer, sizeof(IdxBuffer));
|
||||
_ChannelsCurrent = idx;
|
||||
memcpy(&CmdBuffer, &_Channels.Data[_ChannelsCurrent].CmdBuffer, sizeof(CmdBuffer));
|
||||
memcpy(&IdxBuffer, &_Channels.Data[_ChannelsCurrent].IdxBuffer, sizeof(IdxBuffer));
|
||||
_IdxWritePtr = IdxBuffer.Data + IdxBuffer.Size;
|
||||
}
|
||||
|
||||
|
|
231
3rdparty/ocornut-imgui/imgui_node_graph_test.cpp
vendored
Normal file
231
3rdparty/ocornut-imgui/imgui_node_graph_test.cpp
vendored
Normal file
|
@ -0,0 +1,231 @@
|
|||
// Creating a node graph editor for ImGui
|
||||
// Quick demo, not production code!
|
||||
// See https://github.com/ocornut/imgui/issues/306
|
||||
// v0.01
|
||||
// Animated gif: https://cloud.githubusercontent.com/assets/8225057/9472357/c0263c04-4b4c-11e5-9fdf-2cd4f33f6582.gif
|
||||
|
||||
#include <math.h>
|
||||
#include "imgui.h"
|
||||
|
||||
// NB: You can use math functions/operators on ImVec2 if you #define IMGUI_DEFINE_MATH_OPERATORS and #include "imgui_internal.h"
|
||||
// Here we only declare simple +/- operators so others don't leak into the demo code.
|
||||
static inline ImVec2 operator+(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x+rhs.x, lhs.y+rhs.y); }
|
||||
static inline ImVec2 operator-(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x-rhs.x, lhs.y-rhs.y); }
|
||||
|
||||
// Really dumb data structure provided for the example.
|
||||
// Note that we storing links are INDICES (not ID) to make example code shorter, obviously a bad idea for any general purpose code.
|
||||
void ShowExampleAppCustomNodeGraph(bool* opened)
|
||||
{
|
||||
ImGui::SetNextWindowSize(ImVec2(700,600), ImGuiSetCond_FirstUseEver);
|
||||
if (!ImGui::Begin("Example: Custom Node Graph", opened))
|
||||
{
|
||||
ImGui::End();
|
||||
return;
|
||||
}
|
||||
|
||||
struct Node
|
||||
{
|
||||
int ID;
|
||||
char Name[32];
|
||||
ImVec2 Pos, Size;
|
||||
float Value;
|
||||
int InputsCount, OutputsCount;
|
||||
|
||||
Node(int id, const char* name, const ImVec2& pos, float value, int inputs_count, int outputs_count) { ID = id; strncpy(Name, name, 31); Name[31] = 0; Pos = pos; Value = value; InputsCount = inputs_count; OutputsCount = outputs_count; }
|
||||
|
||||
ImVec2 GetInputSlotPos(int slot_no) const { return ImVec2(Pos.x, Pos.y + Size.y * ((float)slot_no+1) / ((float)InputsCount+1)); }
|
||||
ImVec2 GetOutputSlotPos(int slot_no) const { return ImVec2(Pos.x + Size.x, Pos.y + Size.y * ((float)slot_no+1) / ((float)OutputsCount+1)); }
|
||||
};
|
||||
struct NodeLink
|
||||
{
|
||||
int InputIdx, InputSlot, OutputIdx, OutputSlot;
|
||||
|
||||
NodeLink(int input_idx, int input_slot, int output_idx, int output_slot) { InputIdx = input_idx; InputSlot = input_slot; OutputIdx = output_idx; OutputSlot = output_slot; }
|
||||
};
|
||||
|
||||
static ImVector<Node> nodes;
|
||||
static ImVector<NodeLink> links;
|
||||
static bool inited = false;
|
||||
static ImVec2 scrolling = ImVec2(0.0f, 0.0f);
|
||||
static int node_selected = -1;
|
||||
if (!inited)
|
||||
{
|
||||
nodes.push_back(Node(0, "MainTex", ImVec2(40,50), 0.5f, 1, 1));
|
||||
nodes.push_back(Node(1, "BumpMap", ImVec2(40,150), 0.42f, 1, 1));
|
||||
nodes.push_back(Node(2, "Combine", ImVec2(270,80), 1.0f, 2, 2));
|
||||
links.push_back(NodeLink(0, 0, 2, 0));
|
||||
links.push_back(NodeLink(1, 0, 2, 1));
|
||||
inited = true;
|
||||
}
|
||||
|
||||
// Draw a list of nodes on the left side
|
||||
bool open_context_menu = false;
|
||||
int node_hovered_in_list = -1;
|
||||
int node_hovered_in_scene = -1;
|
||||
ImGui::BeginChild("node_list", ImVec2(100,0));
|
||||
ImGui::Text("Nodes");
|
||||
ImGui::Separator();
|
||||
for (int node_idx = 0; node_idx < nodes.Size; node_idx++)
|
||||
{
|
||||
Node* node = &nodes[node_idx];
|
||||
ImGui::PushID(node->ID);
|
||||
if (ImGui::Selectable(node->Name, node->ID == node_selected))
|
||||
node_selected = node->ID;
|
||||
if (ImGui::IsItemHovered())
|
||||
{
|
||||
node_hovered_in_list = node->ID;
|
||||
open_context_menu |= ImGui::IsMouseClicked(1);
|
||||
}
|
||||
ImGui::PopID();
|
||||
}
|
||||
ImGui::EndChild();
|
||||
|
||||
ImGui::SameLine();
|
||||
ImGui::BeginGroup();
|
||||
|
||||
const float NODE_SLOT_RADIUS = 4.0f;
|
||||
const ImVec2 NODE_WINDOW_PADDING(8.0f, 8.0f);
|
||||
|
||||
// Create our child canvas
|
||||
ImGui::Text("Hold middle mouse button to scroll (%.2f,%.2f)", scrolling.x, scrolling.y);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(1,1));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0,0));
|
||||
ImGui::PushStyleColor(ImGuiCol_ChildWindowBg, ImColor(40,40,40,200));
|
||||
ImGui::BeginChild("scrolling_region", ImVec2(0,0), true, ImGuiWindowFlags_NoScrollbar|ImGuiWindowFlags_NoMove);
|
||||
ImGui::PushItemWidth(120.0f);
|
||||
|
||||
ImDrawList* draw_list = ImGui::GetWindowDrawList();
|
||||
draw_list->ChannelsSplit(2);
|
||||
ImVec2 offset = ImGui::GetCursorScreenPos() - scrolling;
|
||||
|
||||
// Display links
|
||||
draw_list->ChannelsSetCurrent(0); // Background
|
||||
for (int link_idx = 0; link_idx < links.Size; link_idx++)
|
||||
{
|
||||
NodeLink* link = &links[link_idx];
|
||||
Node* node_inp = &nodes[link->InputIdx];
|
||||
Node* node_out = &nodes[link->OutputIdx];
|
||||
|
||||
#if 1
|
||||
// Hermite spline
|
||||
// TODO: move to ImDrawList path API
|
||||
ImVec2 p1 = offset+node_inp->GetOutputSlotPos(link->InputSlot);
|
||||
ImVec2 t1 = ImVec2(+80.0f, 0.0f);
|
||||
ImVec2 p2 = offset+node_out->GetInputSlotPos(link->OutputSlot);
|
||||
ImVec2 t2 = ImVec2(+80.0f, 0.0f);
|
||||
const int STEPS = 12;
|
||||
for (int step = 0; step <= STEPS; step++)
|
||||
{
|
||||
float t = (float)step / (float)STEPS;
|
||||
float h1 = +2*t*t*t - 3*t*t + 1.0f;
|
||||
float h2 = -2*t*t*t + 3*t*t;
|
||||
float h3 = t*t*t - 2*t*t + t;
|
||||
float h4 = t*t*t - t*t;
|
||||
draw_list->PathLineTo(ImVec2(h1*p1.x + h2*p2.x + h3*t1.x + h4*t2.x, h1*p1.y + h2*p2.y + h3*t1.y + h4*t2.y));
|
||||
}
|
||||
draw_list->PathStroke(ImColor(200,200,100), false, 3.0f);
|
||||
#else
|
||||
draw_list->AddLine(offset+node_inp->GetOutputSlotPos(link->InputSlot), offset+node_out->GetInputSlotPos(link->OutputSlot), ImColor(200,200,100), 3.0f);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Display nodes
|
||||
for (int node_idx = 0; node_idx < nodes.Size; node_idx++)
|
||||
{
|
||||
Node* node = &nodes[node_idx];
|
||||
ImGui::PushID(node->ID);
|
||||
ImVec2 node_rect_min = offset + node->Pos;
|
||||
|
||||
// Display node contents first
|
||||
draw_list->ChannelsSetCurrent(1); // Foreground
|
||||
bool old_any_active = ImGui::IsAnyItemActive();
|
||||
ImGui::SetCursorScreenPos(node_rect_min + NODE_WINDOW_PADDING);
|
||||
ImGui::BeginGroup(); // Lock horizontal position
|
||||
ImGui::Text("%s", node->Name);
|
||||
ImGui::SliderFloat("##value", &node->Value, 0.0f, 1.0f, "Alpha %.2f");
|
||||
float dummy_color[3] = { node->Pos.x / ImGui::GetWindowWidth(), node->Pos.y / ImGui::GetWindowHeight(), fmodf((float)node->ID * 0.5f, 1.0f) };
|
||||
ImGui::ColorEdit3("##color", &dummy_color[0]);
|
||||
ImGui::EndGroup();
|
||||
|
||||
// Save the size of what we have emitted and weither any of the widgets are being used
|
||||
bool node_widgets_active = (!old_any_active && ImGui::IsAnyItemActive());
|
||||
node->Size = ImGui::GetItemRectSize() + NODE_WINDOW_PADDING + NODE_WINDOW_PADDING;
|
||||
ImVec2 node_rect_max = node_rect_min + node->Size;
|
||||
|
||||
// Display node box
|
||||
draw_list->ChannelsSetCurrent(0); // Background
|
||||
ImGui::SetCursorScreenPos(node_rect_min);
|
||||
ImGui::InvisibleButton("node", node->Size);
|
||||
if (ImGui::IsItemHovered())
|
||||
{
|
||||
node_hovered_in_scene = node->ID;
|
||||
open_context_menu |= ImGui::IsMouseClicked(1);
|
||||
}
|
||||
bool node_moving_active = ImGui::IsItemActive();
|
||||
if (node_widgets_active || node_moving_active)
|
||||
node_selected = node->ID;
|
||||
if (node_moving_active && ImGui::IsMouseDragging(0))
|
||||
node->Pos = node->Pos + ImGui::GetIO().MouseDelta;
|
||||
|
||||
ImU32 node_bg_color = (node_hovered_in_list == node->ID || node_hovered_in_scene == node->ID || (node_hovered_in_list == -1 && node_selected == node->ID)) ? ImColor(75,75,75) : ImColor(60,60,60);
|
||||
draw_list->AddRectFilled(node_rect_min, node_rect_max, node_bg_color, 4.0f);
|
||||
draw_list->AddRect(node_rect_min, node_rect_max, ImColor(100,100,100), 4.0f);
|
||||
for (int slot_idx = 0; slot_idx < node->InputsCount; slot_idx++)
|
||||
draw_list->AddCircleFilled(offset + node->GetInputSlotPos(slot_idx), NODE_SLOT_RADIUS, ImColor(150,150,150,150));
|
||||
for (int slot_idx = 0; slot_idx < node->OutputsCount; slot_idx++)
|
||||
draw_list->AddCircleFilled(offset + node->GetOutputSlotPos(slot_idx), NODE_SLOT_RADIUS, ImColor(150,150,150,150));
|
||||
|
||||
ImGui::PopID();
|
||||
}
|
||||
draw_list->ChannelsMerge();
|
||||
|
||||
// Open context menu
|
||||
if (!ImGui::IsAnyItemHovered() && ImGui::IsMouseHoveringWindow() && ImGui::IsMouseClicked(1))
|
||||
{
|
||||
node_selected = node_hovered_in_list = node_hovered_in_scene = -1;
|
||||
open_context_menu = true;
|
||||
}
|
||||
if (open_context_menu)
|
||||
{
|
||||
ImGui::OpenPopup("context_menu");
|
||||
if (node_hovered_in_list != -1)
|
||||
node_selected = node_hovered_in_list;
|
||||
if (node_hovered_in_scene != -1)
|
||||
node_selected = node_hovered_in_scene;
|
||||
}
|
||||
|
||||
// Draw context menu
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(8,8));
|
||||
if (ImGui::BeginPopup("context_menu"))
|
||||
{
|
||||
Node* node = node_selected != -1 ? &nodes[node_selected] : NULL;
|
||||
ImVec2 scene_pos = ImGui::GetMousePosOnOpeningCurrentPopup() - offset;
|
||||
if (node)
|
||||
{
|
||||
ImGui::Text("Node '%s'", node->Name);
|
||||
ImGui::Separator();
|
||||
if (ImGui::MenuItem("Rename..", NULL, false, false)) {}
|
||||
if (ImGui::MenuItem("Delete", NULL, false, false)) {}
|
||||
if (ImGui::MenuItem("Copy", NULL, false, false)) {}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ImGui::MenuItem("Add")) { nodes.push_back(Node(nodes.Size, "New node", scene_pos, 0.5f, 2, 2)); }
|
||||
if (ImGui::MenuItem("Paste", NULL, false, false)) {}
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
ImGui::PopStyleVar();
|
||||
|
||||
// Scrolling
|
||||
if (ImGui::IsWindowHovered() && !ImGui::IsAnyItemActive() && ImGui::IsMouseDragging(2, 0.0f))
|
||||
scrolling = scrolling - ImGui::GetIO().MouseDelta;
|
||||
|
||||
ImGui::PopItemWidth();
|
||||
ImGui::EndChild();
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::PopStyleVar(2);
|
||||
ImGui::EndGroup();
|
||||
|
||||
ImGui::End();
|
||||
}
|
|
@ -251,8 +251,16 @@ struct OcornutImguiContext
|
|||
|
||||
ImGui::NewFrame();
|
||||
|
||||
//ImGui::ShowTestWindow(); //Debug only.
|
||||
//
|
||||
#if 0
|
||||
ImGui::ShowTestWindow(); //Debug only.
|
||||
#endif // 0
|
||||
|
||||
#if 0
|
||||
extern void ShowExampleAppCustomNodeGraph(bool* opened);
|
||||
bool opened = true;
|
||||
ShowExampleAppCustomNodeGraph(&opened);
|
||||
#endif // 0
|
||||
|
||||
#if defined(SCI_NAMESPACE) && 0
|
||||
bool opened = true;
|
||||
ImGuiScintilla("Scintilla Editor", &opened, ImVec2(640.0f, 480.0f) );
|
||||
|
|
Loading…
Reference in a new issue