Merge branch 'master' of https://github.com/ocornut/imgui
|
@ -2,6 +2,8 @@ ImGui
|
|||
=====
|
||||
[![Build Status](https://travis-ci.org/ocornut/imgui.svg?branch=master)](https://travis-ci.org/ocornut/imgui)
|
||||
|
||||
[![Patreon](https://cloud.githubusercontent.com/assets/8225057/5990484/70413560-a9ab-11e4-8942-1a63607c0b00.png)](http://www.patreon.com/imgui)
|
||||
|
||||
ImGui is a bloat-free graphical user interface library for C++. It outputs vertex buffers that you can render in your 3D-pipeline enabled application. It is portable, renderer agnostic and carries minimal amount of dependencies. It is based on an "immediate" graphical user interface paradigm which allows you to build user interfaces with ease.
|
||||
|
||||
ImGui is designed to enable fast iteration and allow programmers to create "content creation" or "debug" tools (as opposed to UI for the average end-user). It favors simplicity and productivity toward this goal, and thus lacks certain features normally found in more high-level libraries.
|
||||
|
@ -32,6 +34,7 @@ Gallery
|
|||
![screenshot 2](/web/test_window_02.png?raw=true)
|
||||
![screenshot 3](/web/test_window_03.png?raw=true)
|
||||
![screenshot 4](/web/test_window_04.png?raw=true)
|
||||
![screenshot 4](/web/examples_02.png?raw=true)
|
||||
|
||||
ImGui can load TTF fonts. UTF-8 is supported for text display and input. Here using M+ font to display Japanese:
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
|
|
|
@ -517,11 +517,11 @@ void UpdateImGui()
|
|||
int WINAPI wWinMain(HINSTANCE hInst, HINSTANCE, LPWSTR, int)
|
||||
{
|
||||
// Register the window class
|
||||
WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, WndProc, 0L, 0L, GetModuleHandle(NULL), NULL, LoadCursor(NULL, IDC_ARROW), NULL, NULL, "ImGui Example", NULL };
|
||||
WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, WndProc, 0L, 0L, GetModuleHandle(NULL), NULL, LoadCursor(NULL, IDC_ARROW), NULL, NULL, L"ImGui Example", NULL };
|
||||
RegisterClassEx(&wc);
|
||||
|
||||
// Create the application's window
|
||||
hWnd = CreateWindow("ImGui Example", "ImGui DirectX11 Example", WS_OVERLAPPEDWINDOW, 100, 100, 1280, 800, NULL, NULL, wc.hInstance, NULL);
|
||||
hWnd = CreateWindow(L"ImGui Example", L"ImGui DirectX11 Example", WS_OVERLAPPEDWINDOW, 100, 100, 1280, 800, NULL, NULL, wc.hInstance, NULL);
|
||||
|
||||
if (!QueryPerformanceFrequency((LARGE_INTEGER *)&ticks_per_second))
|
||||
return 1;
|
||||
|
@ -532,7 +532,7 @@ int WINAPI wWinMain(HINSTANCE hInst, HINSTANCE, LPWSTR, int)
|
|||
if (InitDeviceD3D(hWnd) < 0)
|
||||
{
|
||||
CleanupDevice();
|
||||
UnregisterClass("ImGui Example", wc.hInstance);
|
||||
UnregisterClass(L"ImGui Example", wc.hInstance);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -603,7 +603,7 @@ int WINAPI wWinMain(HINSTANCE hInst, HINSTANCE, LPWSTR, int)
|
|||
}
|
||||
|
||||
ImGui::Shutdown();
|
||||
UnregisterClass("ImGui Example", wc.hInstance);
|
||||
UnregisterClass(L"ImGui Example", wc.hInstance);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
80
imgui.cpp
|
@ -1102,6 +1102,11 @@ static ImGuiWindow* GetCurrentWindow()
|
|||
return GImGui->CurrentWindow;
|
||||
}
|
||||
|
||||
static void SetActiveId(ImGuiID id)
|
||||
{
|
||||
GImGui.ActiveId = id;
|
||||
}
|
||||
|
||||
static void RegisterAliveId(const ImGuiID& id)
|
||||
{
|
||||
if (GImGui->ActiveId == id)
|
||||
|
@ -1682,7 +1687,7 @@ void ImGui::NewFrame()
|
|||
// Clear reference to active widget if the widget isn't alive anymore
|
||||
g.HoveredId = 0;
|
||||
if (!g.ActiveIdIsAlive && g.ActiveIdPreviousFrame == g.ActiveId && g.ActiveId != 0)
|
||||
g.ActiveId = 0;
|
||||
SetActiveId(0);
|
||||
g.ActiveIdPreviousFrame = g.ActiveId;
|
||||
g.ActiveIdIsAlive = false;
|
||||
|
||||
|
@ -1868,7 +1873,7 @@ void ImGui::Render()
|
|||
|
||||
// Select window for move/focus when we're done with all our widgets (we only consider non-childs windows here)
|
||||
if (g.ActiveId == 0 && g.HoveredId == 0 && g.HoveredRootWindow != NULL && g.IO.MouseClicked[0])
|
||||
g.ActiveId = g.HoveredRootWindow->GetID("#MOVE");
|
||||
SetActiveId(g.HoveredRootWindow->GetID("#MOVE"));
|
||||
|
||||
// Sort the window list so that all child windows are after their parent
|
||||
// We cannot do that on FocusWindow() because childs may not exist yet
|
||||
|
@ -2554,7 +2559,7 @@ bool ImGui::Begin(const char* name, bool* p_opened, ImVec2 size, float fill_alph
|
|||
}
|
||||
else
|
||||
{
|
||||
g.ActiveId = 0;
|
||||
SetActiveId(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3567,7 +3572,7 @@ static bool ButtonBehaviour(const ImGuiAabb& bb, const ImGuiID& id, bool* out_ho
|
|||
{
|
||||
if (g.IO.MouseClicked[0])
|
||||
{
|
||||
g.ActiveId = id;
|
||||
SetActiveId(id);
|
||||
FocusWindow(window);
|
||||
}
|
||||
else if (repeat && g.ActiveId && ImGui::IsMouseClicked(0, true))
|
||||
|
@ -3588,7 +3593,7 @@ static bool ButtonBehaviour(const ImGuiAabb& bb, const ImGuiID& id, bool* out_ho
|
|||
{
|
||||
if (hovered)
|
||||
pressed = true;
|
||||
g.ActiveId = 0;
|
||||
SetActiveId(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4244,7 +4249,7 @@ bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, c
|
|||
bool start_text_input = false;
|
||||
if (tab_focus_requested || (hovered && g.IO.MouseClicked[0]))
|
||||
{
|
||||
g.ActiveId = id;
|
||||
SetActiveId(id);
|
||||
FocusWindow(window);
|
||||
|
||||
const bool is_ctrl_down = g.IO.KeyCtrl;
|
||||
|
@ -4262,7 +4267,7 @@ bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, c
|
|||
char text_buf[64];
|
||||
ImFormatString(text_buf, IM_ARRAYSIZE(text_buf), "%.*f", decimal_precision, *v);
|
||||
|
||||
g.ActiveId = g.SliderAsInputTextId;
|
||||
SetActiveId(g.SliderAsInputTextId);
|
||||
g.HoveredId = 0;
|
||||
window->FocusItemUnregister(); // Our replacement slider will override the focus ID (registered previously to allow for a TAB focus to happen)
|
||||
value_changed = ImGui::InputText(label, text_buf, IM_ARRAYSIZE(text_buf), ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_AutoSelectAll);
|
||||
|
@ -4271,15 +4276,18 @@ bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, c
|
|||
// First frame
|
||||
IM_ASSERT(g.ActiveId == id); // InputText ID should match the Slider ID (else we'd need to store them both which is also possible)
|
||||
g.SliderAsInputTextId = g.ActiveId;
|
||||
g.ActiveId = id;
|
||||
SetActiveId(id);
|
||||
g.HoveredId = id;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (g.ActiveId == g.SliderAsInputTextId)
|
||||
g.ActiveId = id;
|
||||
SetActiveId(id);
|
||||
else
|
||||
g.ActiveId = g.SliderAsInputTextId = 0;
|
||||
{
|
||||
SetActiveId(0);
|
||||
g.SliderAsInputTextId = 0;
|
||||
}
|
||||
}
|
||||
if (value_changed)
|
||||
{
|
||||
|
@ -4343,7 +4351,7 @@ bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, c
|
|||
}
|
||||
else
|
||||
{
|
||||
g.ActiveId = 0;
|
||||
SetActiveId(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5084,7 +5092,7 @@ bool ImGui::InputText(const char* label, char* buf, size_t buf_size, ImGuiInputT
|
|||
if (tab_focus_requested || is_ctrl_down)
|
||||
select_all = true;
|
||||
}
|
||||
g.ActiveId = id;
|
||||
SetActiveId(id);
|
||||
FocusWindow(window);
|
||||
}
|
||||
else if (io.MouseClicked[0])
|
||||
|
@ -5092,7 +5100,7 @@ bool ImGui::InputText(const char* label, char* buf, size_t buf_size, ImGuiInputT
|
|||
// Release focus when we click outside
|
||||
if (g.ActiveId == id)
|
||||
{
|
||||
g.ActiveId = 0;
|
||||
SetActiveId(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5130,6 +5138,25 @@ bool ImGui::InputText(const char* label, char* buf, size_t buf_size, ImGuiInputT
|
|||
if (edit_state.SelectedAllMouseLock && !io.MouseDown[0])
|
||||
edit_state.SelectedAllMouseLock = false;
|
||||
|
||||
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++)
|
||||
{
|
||||
const ImWchar c = g.IO.InputCharacters[n];
|
||||
if (c)
|
||||
{
|
||||
// Insert character if they pass filtering
|
||||
if (InputTextFilterCharacter(c, flags))
|
||||
continue;
|
||||
edit_state.OnKeyPressed(c);
|
||||
}
|
||||
}
|
||||
|
||||
// Consume characters
|
||||
memset(g.IO.InputCharacters, 0, sizeof(g.IO.InputCharacters));
|
||||
}
|
||||
|
||||
const int k_mask = (is_shift_down ? STB_TEXTEDIT_K_SHIFT : 0);
|
||||
if (IsKeyPressedMap(ImGuiKey_LeftArrow)) { edit_state.OnKeyPressed(is_ctrl_down ? STB_TEXTEDIT_K_WORDLEFT | k_mask : STB_TEXTEDIT_K_LEFT | k_mask); }
|
||||
else if (IsKeyPressedMap(ImGuiKey_RightArrow)) { edit_state.OnKeyPressed(is_ctrl_down ? STB_TEXTEDIT_K_WORDRIGHT | k_mask : STB_TEXTEDIT_K_RIGHT | k_mask); }
|
||||
|
@ -5137,8 +5164,8 @@ bool ImGui::InputText(const char* label, char* buf, size_t buf_size, ImGuiInputT
|
|||
else if (IsKeyPressedMap(ImGuiKey_End)) { edit_state.OnKeyPressed(is_ctrl_down ? STB_TEXTEDIT_K_TEXTEND | k_mask : STB_TEXTEDIT_K_LINEEND | k_mask); }
|
||||
else if (IsKeyPressedMap(ImGuiKey_Delete)) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_DELETE | k_mask); }
|
||||
else if (IsKeyPressedMap(ImGuiKey_Backspace)) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_BACKSPACE | k_mask); }
|
||||
else if (IsKeyPressedMap(ImGuiKey_Enter)) { g.ActiveId = 0; enter_pressed = true; }
|
||||
else if (IsKeyPressedMap(ImGuiKey_Escape)) { g.ActiveId = 0; cancel_edit = true; }
|
||||
else if (IsKeyPressedMap(ImGuiKey_Enter)) { SetActiveId(0); enter_pressed = true; }
|
||||
else if (IsKeyPressedMap(ImGuiKey_Escape)) { SetActiveId(0); cancel_edit = true; }
|
||||
else if (is_ctrl_down && IsKeyPressedMap(ImGuiKey_Z)) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_UNDO); }
|
||||
else if (is_ctrl_down && IsKeyPressedMap(ImGuiKey_Y)) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_REDO); }
|
||||
else if (is_ctrl_down && IsKeyPressedMap(ImGuiKey_A)) { edit_state.SelectAll(); }
|
||||
|
@ -5191,24 +5218,6 @@ bool ImGui::InputText(const char* label, char* buf, size_t buf_size, ImGuiInputT
|
|||
}
|
||||
}
|
||||
}
|
||||
else if (g.IO.InputCharacters[0])
|
||||
{
|
||||
// Text input
|
||||
for (int n = 0; n < IM_ARRAYSIZE(g.IO.InputCharacters) && g.IO.InputCharacters[n]; n++)
|
||||
{
|
||||
const ImWchar c = g.IO.InputCharacters[n];
|
||||
if (c)
|
||||
{
|
||||
// Insert character if they pass filtering
|
||||
if (InputTextFilterCharacter(c, flags))
|
||||
continue;
|
||||
edit_state.OnKeyPressed(c);
|
||||
}
|
||||
}
|
||||
|
||||
// Consume characters
|
||||
memset(g.IO.InputCharacters, 0, sizeof(g.IO.InputCharacters));
|
||||
}
|
||||
|
||||
edit_state.CursorAnim += g.IO.DeltaTime;
|
||||
edit_state.UpdateScrollOffset();
|
||||
|
@ -5527,7 +5536,7 @@ bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(voi
|
|||
}
|
||||
if (item_pressed)
|
||||
{
|
||||
g.ActiveId = 0;
|
||||
SetActiveId(0);
|
||||
g.ActiveComboID = 0;
|
||||
value_changed = true;
|
||||
*current_item = item_idx;
|
||||
|
@ -7827,7 +7836,8 @@ void ImGui::ShowTestWindow(bool* opened)
|
|||
// Most compiler appears to support UTF-8 in source code (with Visual Studio you need to save your file as 'UTF-8 without signature')
|
||||
// However for the sake for maximum portability here we are *not* including raw UTF-8 character in this source file, instead we encode the string with hexadecimal constants.
|
||||
// In your own application be reasonable and use UTF-8 in source or retrieve the data from file system!
|
||||
ImGui::TextWrapped("CJK text will only appears if the font was loaded with the appropriate CJK character ranges. Call io.Font->LoadFromFileTTF() manually to specify extra character ranges. Note that characters values are preserved even if the font cannot be displayed, so you can safely copy & paste garbled characters into another application.");
|
||||
// Note that characters values are preserved even if the font cannot be displayed, so you can safely copy & paste garbled characters into another application.
|
||||
ImGui::TextWrapped("CJK text will only appears if the font was loaded with the appropriate CJK character ranges. Call io.Font->LoadFromFileTTF() manually to load extra character ranges.");
|
||||
ImGui::Text("Hiragana: \xe3\x81\x8b\xe3\x81\x8d\xe3\x81\x8f\xe3\x81\x91\xe3\x81\x93 (kakikukeko)");
|
||||
ImGui::Text("Kanjis: \xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e (nihongo)");
|
||||
static char buf[32] = "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e";
|
||||
|
|
Before Width: | Height: | Size: 7.8 KiB After Width: | Height: | Size: 9.4 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 9.5 KiB |
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 5.5 KiB |
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 5.5 KiB |
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 5.6 KiB |
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 5.9 KiB |
Before Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 7.2 KiB |
Before Width: | Height: | Size: 5.4 KiB After Width: | Height: | Size: 16 KiB |