This commit is contained in:
Jim Tilander 2015-01-31 20:31:41 -08:00
commit e9ff2f3d24
14 changed files with 53 additions and 40 deletions

View File

@ -2,6 +2,8 @@ ImGui
===== =====
[![Build Status](https://travis-ci.org/ocornut/imgui.svg?branch=master)](https://travis-ci.org/ocornut/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 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. 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 2](/web/test_window_02.png?raw=true)
![screenshot 3](/web/test_window_03.png?raw=true) ![screenshot 3](/web/test_window_03.png?raw=true)
![screenshot 4](/web/test_window_04.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: ImGui can load TTF fonts. UTF-8 is supported for text display and input. Here using M+ font to display Japanese:

View File

@ -18,7 +18,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType> <ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries> <UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet> <CharacterSet>Unicode</CharacterSet>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType> <ConfigurationType>Application</ConfigurationType>

View File

@ -517,11 +517,11 @@ void UpdateImGui()
int WINAPI wWinMain(HINSTANCE hInst, HINSTANCE, LPWSTR, int) int WINAPI wWinMain(HINSTANCE hInst, HINSTANCE, LPWSTR, int)
{ {
// Register the window class // 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); RegisterClassEx(&wc);
// Create the application's window // 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)) if (!QueryPerformanceFrequency((LARGE_INTEGER *)&ticks_per_second))
return 1; return 1;
@ -532,7 +532,7 @@ int WINAPI wWinMain(HINSTANCE hInst, HINSTANCE, LPWSTR, int)
if (InitDeviceD3D(hWnd) < 0) if (InitDeviceD3D(hWnd) < 0)
{ {
CleanupDevice(); CleanupDevice();
UnregisterClass("ImGui Example", wc.hInstance); UnregisterClass(L"ImGui Example", wc.hInstance);
return 1; return 1;
} }
@ -603,7 +603,7 @@ int WINAPI wWinMain(HINSTANCE hInst, HINSTANCE, LPWSTR, int)
} }
ImGui::Shutdown(); ImGui::Shutdown();
UnregisterClass("ImGui Example", wc.hInstance); UnregisterClass(L"ImGui Example", wc.hInstance);
return 0; return 0;
} }

View File

@ -1102,6 +1102,11 @@ static ImGuiWindow* GetCurrentWindow()
return GImGui->CurrentWindow; return GImGui->CurrentWindow;
} }
static void SetActiveId(ImGuiID id)
{
GImGui.ActiveId = id;
}
static void RegisterAliveId(const ImGuiID& id) static void RegisterAliveId(const ImGuiID& id)
{ {
if (GImGui->ActiveId == id) if (GImGui->ActiveId == id)
@ -1682,7 +1687,7 @@ void ImGui::NewFrame()
// Clear reference to active widget if the widget isn't alive anymore // Clear reference to active widget if the widget isn't alive anymore
g.HoveredId = 0; g.HoveredId = 0;
if (!g.ActiveIdIsAlive && g.ActiveIdPreviousFrame == g.ActiveId && g.ActiveId != 0) if (!g.ActiveIdIsAlive && g.ActiveIdPreviousFrame == g.ActiveId && g.ActiveId != 0)
g.ActiveId = 0; SetActiveId(0);
g.ActiveIdPreviousFrame = g.ActiveId; g.ActiveIdPreviousFrame = g.ActiveId;
g.ActiveIdIsAlive = false; 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) // 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]) 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 // 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 // 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 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]) if (g.IO.MouseClicked[0])
{ {
g.ActiveId = id; SetActiveId(id);
FocusWindow(window); FocusWindow(window);
} }
else if (repeat && g.ActiveId && ImGui::IsMouseClicked(0, true)) 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) if (hovered)
pressed = true; 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; bool start_text_input = false;
if (tab_focus_requested || (hovered && g.IO.MouseClicked[0])) if (tab_focus_requested || (hovered && g.IO.MouseClicked[0]))
{ {
g.ActiveId = id; SetActiveId(id);
FocusWindow(window); FocusWindow(window);
const bool is_ctrl_down = g.IO.KeyCtrl; 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]; char text_buf[64];
ImFormatString(text_buf, IM_ARRAYSIZE(text_buf), "%.*f", decimal_precision, *v); ImFormatString(text_buf, IM_ARRAYSIZE(text_buf), "%.*f", decimal_precision, *v);
g.ActiveId = g.SliderAsInputTextId; SetActiveId(g.SliderAsInputTextId);
g.HoveredId = 0; g.HoveredId = 0;
window->FocusItemUnregister(); // Our replacement slider will override the focus ID (registered previously to allow for a TAB focus to happen) 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); 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 // 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) 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.SliderAsInputTextId = g.ActiveId;
g.ActiveId = id; SetActiveId(id);
g.HoveredId = id; g.HoveredId = id;
} }
else else
{ {
if (g.ActiveId == g.SliderAsInputTextId) if (g.ActiveId == g.SliderAsInputTextId)
g.ActiveId = id; SetActiveId(id);
else else
g.ActiveId = g.SliderAsInputTextId = 0; {
SetActiveId(0);
g.SliderAsInputTextId = 0;
}
} }
if (value_changed) if (value_changed)
{ {
@ -4343,7 +4351,7 @@ bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, c
} }
else 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) if (tab_focus_requested || is_ctrl_down)
select_all = true; select_all = true;
} }
g.ActiveId = id; SetActiveId(id);
FocusWindow(window); FocusWindow(window);
} }
else if (io.MouseClicked[0]) 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 // Release focus when we click outside
if (g.ActiveId == id) 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]) if (edit_state.SelectedAllMouseLock && !io.MouseDown[0])
edit_state.SelectedAllMouseLock = false; 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); 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); } 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); } 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_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_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_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_Enter)) { SetActiveId(0); enter_pressed = true; }
else if (IsKeyPressedMap(ImGuiKey_Escape)) { g.ActiveId = 0; cancel_edit = 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_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_Y)) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_REDO); }
else if (is_ctrl_down && IsKeyPressedMap(ImGuiKey_A)) { edit_state.SelectAll(); } 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.CursorAnim += g.IO.DeltaTime;
edit_state.UpdateScrollOffset(); edit_state.UpdateScrollOffset();
@ -5527,7 +5536,7 @@ bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(voi
} }
if (item_pressed) if (item_pressed)
{ {
g.ActiveId = 0; SetActiveId(0);
g.ActiveComboID = 0; g.ActiveComboID = 0;
value_changed = true; value_changed = true;
*current_item = item_idx; *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') // 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. // 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! // 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("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)"); 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"; static char buf[32] = "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e";

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.8 KiB

After

Width:  |  Height:  |  Size: 9.4 KiB

BIN
web/examples_01.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
web/examples_02.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 16 KiB