Merge branch 'master' into viewport

# Conflicts:
#	imgui.cpp
This commit is contained in:
omar
2018-07-08 13:08:16 +02:00
80 changed files with 2706 additions and 2541 deletions

206
imgui.cpp
View File

@ -120,34 +120,73 @@
- Refer to the bindings and demo applications in the examples/ folder for instruction on how to setup your code.
THIS IS HOW A SIMPLE APPLICATION MAY LOOK LIKE
EXHIBIT 1: USING THE EXAMPLE BINDINGS (imgui_impl_XXX.cpp files from the examples/ folder)
// Application init
// Create a context
// Application init: create a dear imgui context, setup some options, load fonts
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO();
// TODO: Set optional io.ConfigFlags values, e.g. 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard' to enable keyboard controls
// TODO: Fill optional settings of the io structure later.
// TODO: Load fonts if you don't want to use the default font.
// TODO: Load TTF/OTF fonts if you don't want to use the default font.
// Initialize helper Platform and Renderer bindings (here we are using imgui_impl_win32 and imgui_impl_dx11)
ImGui_ImplWin32_Init(hwnd);
ImGui_ImplDX11_Init(g_pd3dDevice, g_pd3dDeviceContext);
// Application main loop
while (true)
{
// Feed inputs to dear imgui, start new frame
ImGui_ImplDX11_NewFrame();
ImGui_ImplWin32_NewFrame();
ImGui::NewFrame();
// Any application code here
ImGui::Text("Hello, world!");
// Render dear imgui into screen
ImGui::Render();
ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());
g_pSwapChain->Present(1, 0);
}
// Shutdown
ImGui_ImplDX11_Shutdown();
ImGui_ImplWin32_Shutdown();
ImGui::DestroyContext();
THIS IS HOW A SIMPLE APPLICATION MAY LOOK LIKE
EXHIBIT 2: IMPLEMENTING CUSTOM BINDING / CUSTOM ENGINE
// Application init: create a dear imgui context, setup some options, load fonts
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO();
// TODO: Set optional io.ConfigFlags values, e.g. 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard' to enable keyboard controls
// TODO: Fill optional settings of the io structure later.
// TODO: Load TTF/OTF fonts if you don't want to use the default font.
// Build and load the texture atlas into a texture
unsigned char* pixels = NULL;
// (In the examples/ app this is usually done within the ImGui_ImplXXX_Init() function from one of the demo Renderer)
int width, height;
unsigned char* pixels = NULL;
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
// At this point you've got the texture data and you need to upload that your your graphic system:
// After we have created the texture, store its pointer/identifier (_in whichever format your engine uses_) in 'io.Fonts->TexID'.
// This will be passed back to your via the renderer. Basically ImTextureID == void*. Read FAQ below for details about ImTextureID.
MyTexture* texture = MyEngine::CreateTextureFromMemoryPixels(pixels, width, height, TEXTURE_TYPE_RGBA32)
// Store your texture pointer/identifier (in whatever formatyour engine uses) in 'io.Fonts->TexID'.
// This will be passed back to your via the renderer. Read FAQ for details about ImTextureID.
io.Fonts->TexID = (void*)texture;
// Application main loop
while (true)
{
// Setup low-level inputs (e.g. on Win32, GetKeyboardState(), or write to those fields from your Windows message loop handlers, etc.)
ImGuiIO& io = ImGui::GetIO();
io.DeltaTime = 1.0f/60.0f;
io.DisplaySize.x = 1920.0f;
io.DisplaySize.y = 1280.0f;
io.MousePos = my_mouse_pos;
io.MouseDown[0] = my_mouse_buttons[0];
// Setup low-level inputs, e.g. on Win32: calling GetKeyboardState(), or write to those fields from your Windows message handlers, etc.
// (In the examples/ app this is usually done within the ImGui_ImplXXX_NewFrame() function from one of the demo Platform bindings)
io.DeltaTime = 1.0f/60.0f; // set the time elapsed since the previous frame (in seconds)
io.DisplaySize.x = 1920.0f; // set the current display width
io.DisplaySize.y = 1280.0f; // set the current display height here
io.MousePos = my_mouse_pos; // set the mouse position
io.MouseDown[0] = my_mouse_buttons[0]; // set the mouse button states
io.MouseDown[1] = my_mouse_buttons[1];
// Call NewFrame(), after this point you can use ImGui::* functions anytime
@ -163,7 +202,8 @@
// (You want to try calling EndFrame/Render as late as you can, to be able to use imgui in your own game rendering code)
ImGui::EndFrame();
ImGui::Render();
MyImGuiRenderFunction(ImGui::GetDrawData());
ImDrawData* draw_data = ImGui::GetDrawData();
MyImGuiRenderFunction(draw_data);
SwapBuffers();
}
@ -276,7 +316,7 @@
- 2018/XX/XX (1.XX) - Moved IME support functions from io.ImeSetInputScreenPosFn, io.ImeWindowHandle to the PlatformIO api.
- 2018/XX/XX (1.XX) - removed io.DisplayVisibleMin, io.DisplayVisibleMax settings (it was used to clip within the DisplayMin..DisplayMax range, I don't know of anyone using it)
- 2018/07/06 (1.63) - removed per-window ImGuiWindowFlags_ResizeFromAnySide beta flag in favor of a global io.OptResizeWindowsFromEdges to enable the feature.
- 2018/06/06 (1.62) - renamed GetGlyphRangesChinese() to GetGlyphRangesChineseFull() to distinguish other variants and discourage using the full set.
- 2018/06/06 (1.62) - TreeNodeEx()/TreeNodeBehavior(): the ImGuiTreeNodeFlags_CollapsingHeader helper now include the ImGuiTreeNodeFlags_NoTreePushOnOpen flag. See Changelog for details.
- 2018/05/03 (1.61) - DragInt(): the default compile-time format string has been changed from "%.0f" to "%d", as we are not using integers internally any more.
@ -857,6 +897,8 @@ static bool DataTypeApplyOpFromText(const char* buf, const char* ini
namespace ImGui
{
static bool BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, bool border, ImGuiWindowFlags flags);
static void NavUpdate();
static void NavUpdateWindowing();
static void NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, const ImGuiID id);
@ -2274,7 +2316,7 @@ void ImGui::MarkItemValueChanged(ImGuiID id)
// ActiveId might have been released by the time we call this (as in the typical press/release button behavior) but still need need to fill the data.
(void)id; // Avoid unused variable warnings when asserts are compiled out.
ImGuiContext& g = *GImGui;
IM_ASSERT(g.ActiveId == id || g.ActiveId == 0);
IM_ASSERT(g.ActiveId == id || g.ActiveId == 0 || g.DragDropActive);
g.ActiveIdValueChanged = true;
}
@ -4113,11 +4155,15 @@ void ImGui::NewFrame()
for (int n = 0; n < ImGuiKey_COUNT; n++)
IM_ASSERT(g.IO.KeyMap[n] >= -1 && g.IO.KeyMap[n] < IM_ARRAYSIZE(g.IO.KeysDown) && "io.KeyMap[] contains an out of bound value (need to be 0..512, or -1 for unmapped key)");
// Perform simple check for required key mapping (we intentionally do NOT check all keys to not pressure user into setting up everything, but Space is required and was only recently added in 1.60 WIP)
// Perform simple check: required key mapping (we intentionally do NOT check all keys to not pressure user into setting up everything, but Space is required and was only recently added in 1.60 WIP)
if (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard)
IM_ASSERT(g.IO.KeyMap[ImGuiKey_Space] != -1 && "ImGuiKey_Space is not mapped, required for keyboard navigation.");
// Perform simple checks for multi-viewport and platform windows support
// Perform simple check: the beta io.OptResizeWindowsFromEdges option requires back-end to honor mouse cursor changes and set the ImGuiBackendFlags_HasMouseCursors flag accordingly.
if (g.IO.OptResizeWindowsFromEdges && !(g.IO.BackendFlags & ImGuiBackendFlags_HasMouseCursors))
g.IO.OptResizeWindowsFromEdges = false;
// Perform simple checks: multi-viewport and platform windows support
if (g.IO.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
{
if ((g.IO.BackendFlags & ImGuiBackendFlags_PlatformHasViewports) && (g.IO.BackendFlags & ImGuiBackendFlags_RendererHasViewports))
@ -6060,45 +6106,47 @@ bool ImGui::BeginPopupContextVoid(const char* str_id, int mouse_button)
return BeginPopupEx(id, ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoSavedSettings);
}
static bool BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, bool border, ImGuiWindowFlags extra_flags)
static bool ImGui::BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, bool border, ImGuiWindowFlags flags)
{
ImGuiContext& g = *GImGui;
ImGuiWindow* parent_window = ImGui::GetCurrentWindow();
ImGuiWindowFlags flags = ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_ChildWindow;
ImGuiWindow* parent_window = g.CurrentWindow;
flags |= ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_ChildWindow;
flags |= (parent_window->Flags & ImGuiWindowFlags_NoMove); // Inherit the NoMove flag
const ImVec2 content_avail = ImGui::GetContentRegionAvail();
// Size
const ImVec2 content_avail = GetContentRegionAvail();
ImVec2 size = ImFloor(size_arg);
const int auto_fit_axises = ((size.x == 0.0f) ? (1 << ImGuiAxis_X) : 0x00) | ((size.y == 0.0f) ? (1 << ImGuiAxis_Y) : 0x00);
if (size.x <= 0.0f)
size.x = ImMax(content_avail.x + size.x, 4.0f); // Arbitrary minimum child size (0.0f causing too much issues)
if (size.y <= 0.0f)
size.y = ImMax(content_avail.y + size.y, 4.0f);
SetNextWindowSize(size);
const float backup_border_size = g.Style.ChildBorderSize;
if (!border)
g.Style.ChildBorderSize = 0.0f;
flags |= extra_flags;
// Name
char title[256];
if (name)
ImFormatString(title, IM_ARRAYSIZE(title), "%s/%s", parent_window->Name, name);
else
ImFormatString(title, IM_ARRAYSIZE(title), "%s/%08X", parent_window->Name, id);
ImGui::SetNextWindowSize(size);
bool ret = ImGui::Begin(title, NULL, flags);
ImGuiWindow* child_window = ImGui::GetCurrentWindow();
child_window->ChildId = id;
child_window->AutoFitChildAxises = auto_fit_axises;
const float backup_border_size = g.Style.ChildBorderSize;
if (!border)
g.Style.ChildBorderSize = 0.0f;
bool ret = Begin(title, NULL, flags);
g.Style.ChildBorderSize = backup_border_size;
ImGuiWindow* child_window = g.CurrentWindow;
child_window->ChildId = id;
child_window->AutoFitChildAxises = auto_fit_axises;
// Process navigation-in immediately so NavInit can run on first frame
if (!(flags & ImGuiWindowFlags_NavFlattened) && (child_window->DC.NavLayerActiveMask != 0 || child_window->DC.NavHasScroll) && g.NavActivateId == id)
if (g.NavActivateId == id && !(flags & ImGuiWindowFlags_NavFlattened) && (child_window->DC.NavLayerActiveMask != 0 || child_window->DC.NavHasScroll))
{
ImGui::FocusWindow(child_window);
ImGui::NavInitWindow(child_window, false);
ImGui::SetActiveID(id+1, child_window); // Steal ActiveId with a dummy id so that key-press won't activate child item
FocusWindow(child_window);
NavInitWindow(child_window, false);
SetActiveID(id+1, child_window); // Steal ActiveId with a dummy id so that key-press won't activate child item
g.ActiveIdSource = ImGuiInputSource_Nav;
}
@ -6443,8 +6491,10 @@ static ImVec2 CalcSizeAutoFit(ImGuiWindow* window, const ImVec2& size_contents)
else
{
// Maximum window size is determined by the viewport size or monitor size
ImVec2 size_min(0.0f, 0.0f);
if (!(window->Flags & ImGuiWindowFlags_ChildMenu))
const bool is_popup = (window->Flags & ImGuiWindowFlags_Popup) != 0 && (window->Flags & ImGuiWindowFlags_AlwaysAutoResize) != 0;
const bool is_menu = (window->Flags & ImGuiWindowFlags_ChildMenu) != 0;
ImVec2 size_min(1.0f, 1.0f);
if (!is_popup && !is_menu)
size_min = style.WindowMinSize;
ImVec2 avail_size = window->Viewport->Size;
if (window->ViewportOwned)
@ -6703,7 +6753,7 @@ static void ImGui::UpdateManualResize(ImGuiWindow* window, const ImVec2& size_au
if ((flags & ImGuiWindowFlags_NoResize) || (flags & ImGuiWindowFlags_AlwaysAutoResize) || window->AutoFitFramesX > 0 || window->AutoFitFramesY > 0)
return;
const int resize_border_count = (flags & ImGuiWindowFlags_ResizeFromAnySide) ? 4 : 0;
const int resize_border_count = g.IO.OptResizeWindowsFromEdges ? 4 : 0;
const float grip_draw_size = (float)(int)ImMax(g.FontSize * 1.35f, window->WindowRounding + 1.0f + g.FontSize * 0.2f);
const float grip_hover_size = (float)(int)(grip_draw_size * 0.75f);
@ -7183,7 +7233,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
// Handle manual resize: Resize Grips, Borders, Gamepad
int border_held = -1;
ImU32 resize_grip_col[4] = { 0 };
const int resize_grip_count = (flags & ImGuiWindowFlags_ResizeFromAnySide) ? 2 : 1; // 4
const int resize_grip_count = g.IO.OptResizeWindowsFromEdges ? 2 : 1; // 4
const float grip_draw_size = (float)(int)ImMax(g.FontSize * 1.35f, window->WindowRounding + 1.0f + g.FontSize * 0.2f);
if (!window->Collapsed)
UpdateManualResize(window, size_auto_fit, &border_held, resize_grip_count, &resize_grip_col[0]);
@ -12288,23 +12338,51 @@ void ImGui::EndCombo()
EndPopup();
}
// Getter for the old Combo() API: const char*[]
static bool Items_ArrayGetter(void* data, int idx, const char** out_text)
{
const char* const* items = (const char* const*)data;
if (out_text)
*out_text = items[idx];
return true;
}
// Getter for the old Combo() API: "item1\0item2\0item3\0"
static bool Items_SingleStringGetter(void* data, int idx, const char** out_text)
{
// FIXME-OPT: we could pre-compute the indices to fasten this. But only 1 active combo means the waste is limited.
const char* items_separated_by_zeros = (const char*)data;
int items_count = 0;
const char* p = items_separated_by_zeros;
while (*p)
{
if (idx == items_count)
break;
p += strlen(p) + 1;
items_count++;
}
if (!*p)
return false;
if (out_text)
*out_text = p;
return true;
}
// Old API, prefer using BeginCombo() nowadays if you can.
bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(void*, int, const char**), void* data, int items_count, int popup_max_height_in_items)
{
ImGuiContext& g = *GImGui;
const char* preview_text = NULL;
// Call the getter to obtain the preview string which is a parameter to BeginCombo()
const char* preview_value = NULL;
if (*current_item >= 0 && *current_item < items_count)
items_getter(data, *current_item, &preview_text);
items_getter(data, *current_item, &preview_value);
// The old Combo() API exposed "popup_max_height_in_items". The new more general BeginCombo() API doesn't, so we emulate it here.
// The old Combo() API exposed "popup_max_height_in_items". The new more general BeginCombo() API doesn't have/need it, but we emulate it here.
if (popup_max_height_in_items != -1 && !g.NextWindowData.SizeConstraintCond)
{
float popup_max_height = CalcMaxPopupHeightFromItemCount(popup_max_height_in_items);
SetNextWindowSizeConstraints(ImVec2(0,0), ImVec2(FLT_MAX, popup_max_height));
}
SetNextWindowSizeConstraints(ImVec2(0,0), ImVec2(FLT_MAX, CalcMaxPopupHeightFromItemCount(popup_max_height_in_items)));
if (!BeginCombo(label, preview_text, 0))
if (!BeginCombo(label, preview_value, ImGuiComboFlags_None))
return false;
// Display items
@ -12331,34 +12409,6 @@ bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(voi
return value_changed;
}
static bool Items_ArrayGetter(void* data, int idx, const char** out_text)
{
const char* const* items = (const char* const*)data;
if (out_text)
*out_text = items[idx];
return true;
}
static bool Items_SingleStringGetter(void* data, int idx, const char** out_text)
{
// FIXME-OPT: we could pre-compute the indices to fasten this. But only 1 active combo means the waste is limited.
const char* items_separated_by_zeros = (const char*)data;
int items_count = 0;
const char* p = items_separated_by_zeros;
while (*p)
{
if (idx == items_count)
break;
p += strlen(p) + 1;
items_count++;
}
if (!*p)
return false;
if (out_text)
*out_text = p;
return true;
}
// Combo box helper allowing to pass an array of strings.
bool ImGui::Combo(const char* label, int* current_item, const char* const items[], int items_count, int height_in_items)
{
@ -12366,7 +12416,7 @@ bool ImGui::Combo(const char* label, int* current_item, const char* const items[
return value_changed;
}
// Combo box helper allowing to pass all items in a single string.
// Combo box helper allowing to pass all items in a single string literal holding multiple zero-terminated items "item1\0item2\0"
bool ImGui::Combo(const char* label, int* current_item, const char* items_separated_by_zeros, int height_in_items)
{
int items_count = 0;
@ -12381,7 +12431,7 @@ bool ImGui::Combo(const char* label, int* current_item, const char* items_separa
}
// Tip: pass an empty label (e.g. "##dummy") then you can use the space to draw other text or image.
// But you need to make sure the ID is unique, e.g. enclose calls in PushID/PopID.
// But you need to make sure the ID is unique, e.g. enclose calls in PushID/PopID or use ##unique_id.
bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags flags, const ImVec2& size_arg)
{
ImGuiWindow* window = GetCurrentWindow();