From dac9266f6ff7b212ad2654ac91668ed6a35b1096 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 9 Mar 2015 18:26:48 +0000 Subject: [PATCH 01/44] Fixed warnings --- imgui.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 6cb7be3e1..760471361 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5548,7 +5548,7 @@ static bool InputTextFilterCharacter(unsigned int* p_char, ImGuiInputTextFlags f if (flags & ImGuiInputTextFlags_CharsUppercase) if (c >= 'a' && c <= 'z') - *p_char = (c += 'A'-'a'); + *p_char = (c += (unsigned int)('A'-'a')); if (flags & ImGuiInputTextFlags_CharsNoBlank) if (ImCharIsSpace(c)) @@ -5560,7 +5560,7 @@ static bool InputTextFilterCharacter(unsigned int* p_char, ImGuiInputTextFlags f ImGuiTextEditCallbackData callback_data; memset(&callback_data, 0, sizeof(ImGuiTextEditCallbackData)); callback_data.EventFlag = ImGuiInputTextFlags_CallbackCharFilter; - callback_data.EventChar = c; + callback_data.EventChar = (ImWchar)c; callback_data.Flags = flags; callback_data.UserData = user_data; if (callback(&callback_data) != 0) @@ -9300,6 +9300,8 @@ static void ShowExampleAppFixedOverlay(bool* opened) static void ShowExampleAppManipulatingWindowTitle(bool* opened) { + (void)opened; + // By default, Windows are uniquely identified by their title. // You can use the "##" and "###" markers to manipulate the display/ID. Read FAQ at the top of this file! From 4b1a18c2c9370a7093ca9752c38cf75ede5a85b4 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 9 Mar 2015 18:36:03 +0000 Subject: [PATCH 02/44] Fixed more warnings from @bkaradzic --- imgui.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 760471361..4368cc7b8 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1835,7 +1835,7 @@ void ImGui::NewFrame() // Are we using inputs? Tell user so they can capture/discard the inputs away from the rest of their application. // When clicking outside of a window we assume the click is owned by the application and won't request capture. int mouse_earliest_button_down = -1; - for (size_t i = 0; i < IM_ARRAYSIZE(g.IO.MouseDown); i++) + for (int i = 0; i < IM_ARRAYSIZE(g.IO.MouseDown); i++) { if (g.IO.MouseClicked[i]) g.IO.MouseDownOwned[i] = (g.HoveredWindow != NULL); @@ -5636,9 +5636,9 @@ bool ImGui::InputText(const char* label, char* buf, size_t buf_size, ImGuiInputT { // Recycle existing cursor/selection/undo stack but clamp position // Note a single mouse click will override the cursor/position immediately by calling stb_textedit_click handler. - edit_state.StbState.cursor = ImMin(edit_state.StbState.cursor, edit_state.CurLenW); - edit_state.StbState.select_start = ImMin(edit_state.StbState.select_start, edit_state.CurLenW); - edit_state.StbState.select_end = ImMin(edit_state.StbState.select_end, edit_state.CurLenW); + edit_state.StbState.cursor = ImMin(edit_state.StbState.cursor, (int)edit_state.CurLenW); + edit_state.StbState.select_start = ImMin(edit_state.StbState.select_start, (int)edit_state.CurLenW); + edit_state.StbState.select_end = ImMin(edit_state.StbState.select_end, (int)edit_state.CurLenW); } if (focus_requested_by_tab || (user_clicked && is_ctrl_down)) select_all = true; @@ -5735,7 +5735,7 @@ bool ImGui::InputText(const char* label, char* buf, size_t buf_size, ImGuiInputT if (g.IO.SetClipboardTextFn) { const int ib = edit_state.HasSelection() ? ImMin(edit_state.StbState.select_start, edit_state.StbState.select_end) : 0; - const int ie = edit_state.HasSelection() ? ImMax(edit_state.StbState.select_start, edit_state.StbState.select_end) : edit_state.CurLenW; + const int ie = edit_state.HasSelection() ? ImMax(edit_state.StbState.select_start, edit_state.StbState.select_end) : (int)edit_state.CurLenW; ImTextStrToUtf8(text_tmp_utf8, IM_ARRAYSIZE(text_tmp_utf8), edit_state.Text+ib, edit_state.Text+ie); g.IO.SetClipboardTextFn(text_tmp_utf8); } From 5d1c38150931b4f191d4b23dd908c80873e9860e Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 11 Mar 2015 16:44:54 +0000 Subject: [PATCH 03/44] Update version number, added IMGUI_VERSION, ImGui::GetVersion() (#127) --- imgui.cpp | 7 ++++++- imgui.h | 5 ++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 4368cc7b8..266e898c2 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1,4 +1,4 @@ -// ImGui library v1.35 +// ImGui library v1.36 wip // See ImGui::ShowTestWindow() for sample code. // Read 'Programmer guide' below for notes on how to setup ImGui in your codebase. // Get latest version at https://github.com/ocornut/imgui @@ -1713,6 +1713,11 @@ static void MarkSettingsDirty() g.SettingsDirtyTimer = g.IO.IniSavingRate; } +const char* ImGui::GetVersion() +{ + return IMGUI_VERSION; +} + // Internal state access - if you want to share ImGui state between modules (e.g. DLL) or allocate it yourself // Note that we still point to some static data and members (such as GFontAtlas), so the state instance you end up using will point to the static data within its module void* ImGui::GetInternalState() diff --git a/imgui.h b/imgui.h index f4f36f183..6efe36730 100644 --- a/imgui.h +++ b/imgui.h @@ -1,4 +1,4 @@ -// ImGui library v1.35 +// ImGui library v1.36 wip // See .cpp file for documentation. // See ImGui::ShowTestWindow() for sample code. // Read 'Programmer guide' in .cpp for notes on how to setup ImGui in your codebase. @@ -13,6 +13,8 @@ #include // NULL, malloc #include // memset, memmove +#define IMGUI_VERSION "1.36 wip" + // Define assertion handler. #ifndef IM_ASSERT #include @@ -369,6 +371,7 @@ namespace ImGui IMGUI_API void ColorConvertHSVtoRGB(float h, float s, float v, float& out_r, float& out_g, float& out_b); // Internal state access - if you want to share ImGui state between modules (e.g. DLL) or allocate it yourself + IMGUI_API const char* GetVersion(); IMGUI_API void* GetInternalState(); IMGUI_API size_t GetInternalStateSize(); IMGUI_API void SetInternalState(void* state, bool construct = false); From 58dc3f97c54a104d52cd11bfceb69fcb52ce448e Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 11 Mar 2015 16:45:58 +0000 Subject: [PATCH 04/44] WIP marker in uppercase.. (#127) --- imgui.cpp | 2 +- imgui.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 266e898c2..3f509448d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1,4 +1,4 @@ -// ImGui library v1.36 wip +// ImGui library v1.36 WIP // See ImGui::ShowTestWindow() for sample code. // Read 'Programmer guide' below for notes on how to setup ImGui in your codebase. // Get latest version at https://github.com/ocornut/imgui diff --git a/imgui.h b/imgui.h index 6efe36730..8b9b7de07 100644 --- a/imgui.h +++ b/imgui.h @@ -1,4 +1,4 @@ -// ImGui library v1.36 wip +// ImGui library v1.36 WIP // See .cpp file for documentation. // See ImGui::ShowTestWindow() for sample code. // Read 'Programmer guide' in .cpp for notes on how to setup ImGui in your codebase. @@ -13,7 +13,7 @@ #include // NULL, malloc #include // memset, memmove -#define IMGUI_VERSION "1.36 wip" +#define IMGUI_VERSION "1.36 WIP" // Define assertion handler. #ifndef IM_ASSERT From 09115264249ba04baa539e2b0823c4ffdd997e90 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 13 Mar 2015 09:49:38 +0000 Subject: [PATCH 05/44] Added io.KeyAlt + support in examples apps Currently unused but supported by sample so that more people will have it set up when menus needs them --- examples/directx11_example/imgui_impl_dx11.cpp | 1 + examples/directx11_example/main.cpp | 4 ++++ examples/directx9_example/imgui_impl_dx9.cpp | 1 + examples/directx9_example/main.cpp | 4 ++++ examples/opengl3_example/imgui_impl_glfw_gl3.cpp | 1 + examples/opengl_example/imgui_impl_glfw.cpp | 1 + imgui.cpp | 4 +++- imgui.h | 1 + 8 files changed, 16 insertions(+), 1 deletion(-) diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index 727b5eeb8..f6ee6b5de 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -455,6 +455,7 @@ void ImGui_ImplDX11_NewFrame() // Read keyboard modifiers inputs io.KeyCtrl = (GetKeyState(VK_CONTROL) & 0x8000) != 0; io.KeyShift = (GetKeyState(VK_SHIFT) & 0x8000) != 0; + io.KeyAlt = (GetKeyState(VK_MENU) & 0x8000) != 0; // io.KeysDown : filled by WM_KEYDOWN/WM_KEYUP events // io.MousePos : filled by WM_MOUSEMOVE events // io.MouseDown : filled by WM_*BUTTON* events diff --git a/examples/directx11_example/main.cpp b/examples/directx11_example/main.cpp index 0620245b4..571fe1da2 100644 --- a/examples/directx11_example/main.cpp +++ b/examples/directx11_example/main.cpp @@ -117,6 +117,10 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) ImGui_ImplDX11_CreateDeviceObjects(); } return 0; + case WM_SYSCOMMAND: + if ((wParam & 0xfff0) == SC_KEYMENU) // Disable ALT application menu + return 0; + break; case WM_DESTROY: PostQuitMessage(0); return 0; diff --git a/examples/directx9_example/imgui_impl_dx9.cpp b/examples/directx9_example/imgui_impl_dx9.cpp index e47ddea97..b64b70eba 100644 --- a/examples/directx9_example/imgui_impl_dx9.cpp +++ b/examples/directx9_example/imgui_impl_dx9.cpp @@ -276,6 +276,7 @@ void ImGui_ImplDX9_NewFrame() // Read keyboard modifiers inputs io.KeyCtrl = (GetKeyState(VK_CONTROL) & 0x8000) != 0; io.KeyShift = (GetKeyState(VK_SHIFT) & 0x8000) != 0; + io.KeyAlt = (GetKeyState(VK_MENU) & 0x8000) != 0; // io.KeysDown : filled by WM_KEYDOWN/WM_KEYUP events // io.MousePos : filled by WM_MOUSEMOVE events // io.MouseDown : filled by WM_*BUTTON* events diff --git a/examples/directx9_example/main.cpp b/examples/directx9_example/main.cpp index 75892ffbf..5e0e58d64 100644 --- a/examples/directx9_example/main.cpp +++ b/examples/directx9_example/main.cpp @@ -30,6 +30,10 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) ImGui_ImplDX9_CreateDeviceObjects(); } return 0; + case WM_SYSCOMMAND: + if ((wParam & 0xfff0) == SC_KEYMENU) // Disable ALT application menu + return 0; + break; case WM_DESTROY: PostQuitMessage(0); return 0; diff --git a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp index adc2d6736..fa669d9c8 100644 --- a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp +++ b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp @@ -143,6 +143,7 @@ void ImGui_ImplGlfwGL3_KeyCallback(GLFWwindow* window, int key, int scancode, in io.KeysDown[key] = false; io.KeyCtrl = (mods & GLFW_MOD_CONTROL) != 0; io.KeyShift = (mods & GLFW_MOD_SHIFT) != 0; + io.KeyAlt = (mods & GLFW_MOD_ALT) != 0; } void ImGui_ImplGlfwGL3_CharCallback(GLFWwindow* window, unsigned int c) diff --git a/examples/opengl_example/imgui_impl_glfw.cpp b/examples/opengl_example/imgui_impl_glfw.cpp index 2be01de03..a6b9cb40a 100644 --- a/examples/opengl_example/imgui_impl_glfw.cpp +++ b/examples/opengl_example/imgui_impl_glfw.cpp @@ -123,6 +123,7 @@ void ImGui_ImplGlFw_KeyCallback(GLFWwindow* window, int key, int scancode, int a io.KeysDown[key] = false; io.KeyCtrl = (mods & GLFW_MOD_CONTROL) != 0; io.KeyShift = (mods & GLFW_MOD_SHIFT) != 0; + io.KeyAlt = (mods & GLFW_MOD_ALT) != 0; } void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c) diff --git a/imgui.cpp b/imgui.cpp index 3f509448d..2b45781c4 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -314,6 +314,7 @@ - input: support track pad style scrolling & slider edit. - tooltip: move to fit within screen (e.g. when mouse cursor is right of the screen). - portability: big-endian test/support (github issue #81) + - misc: let user copy any window content to clipboard easily (CTRL+C on windows? while moving it? context menu?) - misc: mark printf compiler attributes on relevant functions - misc: provide a way to compile out the entire implementation while providing a dummy API (e.g. #define IMGUI_DUMMY_IMPL) - misc: double-clicking on title bar to minimize isn't consistent, perhaps move to single-click on left-most collapse icon? @@ -4014,7 +4015,7 @@ static bool ButtonBehaviour(const ImGuiAabb& bb, const ImGuiID& id, bool* out_ho if (hovered) { g.HoveredId = id; - if (allow_key_modifiers || (!g.IO.KeyCtrl && !g.IO.KeyShift)) + if (allow_key_modifiers || (!g.IO.KeyCtrl && !g.IO.KeyShift && !g.IO.KeyAlt)) { if (g.IO.MouseClicked[0]) { @@ -8582,6 +8583,7 @@ void ImGui::ShowTestWindow(bool* opened) ImGui::Text("ImGui says hello."); //ImGui::Text("MousePos (%g, %g)", ImGui::GetIO().MousePos.x, ImGui::GetIO().MousePos.y); //ImGui::Text("MouseWheel %d", ImGui::GetIO().MouseWheel); + ImGui::Text("KeyMods %s%s%s", ImGui::GetIO().KeyCtrl ? "CTRL" : "", ImGui::GetIO().KeyShift ? "SHIFT" : "", ImGui::GetIO().KeyAlt? "ALT" : ""); //ImGui::Text("WantCaptureMouse: %d", ImGui::GetIO().WantCaptureMouse); //ImGui::Text("WantCaptureKeyboard: %d", ImGui::GetIO().WantCaptureKeyboard); diff --git a/imgui.h b/imgui.h index 8b9b7de07..fb24d89fa 100644 --- a/imgui.h +++ b/imgui.h @@ -601,6 +601,7 @@ struct ImGuiIO bool MouseDrawCursor; // Request ImGui to draw a mouse cursor for you (if you are on a platform without a mouse cursor). bool KeyCtrl; // Keyboard modifier pressed: Control bool KeyShift; // Keyboard modifier pressed: Shift + bool KeyAlt; // Keyboard modifier pressed: Alt bool KeysDown[512]; // Keyboard keys that are pressed (in whatever storage order you naturally have access to keyboard data) ImWchar InputCharacters[16+1]; // List of characters input (translated by user from keypress+keyboard state). Fill using AddInputCharacter() helper. From e2734d23ef9c02c0bdd7783955c00785e64344ad Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 13 Mar 2015 11:16:11 +0000 Subject: [PATCH 06/44] Child window don't take focus when they first appear (focus left to parent) --- imgui.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 2b45781c4..53d2d9afd 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2807,8 +2807,9 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size, float bg window->Visible = true; // New windows appears in front - if (window->LastFrameDrawn < current_frame - 1) - FocusWindow(window); + if (!(flags & ImGuiWindowFlags_ChildWindow)) + if (window->LastFrameDrawn < current_frame - 1) + FocusWindow(window); window->LastFrameDrawn = current_frame; window->ClipRectStack.resize(0); @@ -8583,7 +8584,7 @@ void ImGui::ShowTestWindow(bool* opened) ImGui::Text("ImGui says hello."); //ImGui::Text("MousePos (%g, %g)", ImGui::GetIO().MousePos.x, ImGui::GetIO().MousePos.y); //ImGui::Text("MouseWheel %d", ImGui::GetIO().MouseWheel); - ImGui::Text("KeyMods %s%s%s", ImGui::GetIO().KeyCtrl ? "CTRL" : "", ImGui::GetIO().KeyShift ? "SHIFT" : "", ImGui::GetIO().KeyAlt? "ALT" : ""); + //ImGui::Text("KeyMods %s%s%s", ImGui::GetIO().KeyCtrl ? "CTRL" : "", ImGui::GetIO().KeyShift ? "SHIFT" : "", ImGui::GetIO().KeyAlt? "ALT" : ""); //ImGui::Text("WantCaptureMouse: %d", ImGui::GetIO().WantCaptureMouse); //ImGui::Text("WantCaptureKeyboard: %d", ImGui::GetIO().WantCaptureKeyboard); From 1c1a55f6b1f8228b5ae2ea4af2d66eb6e629e931 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 13 Mar 2015 12:25:43 +0000 Subject: [PATCH 07/44] Added IsRootWindowFocused(), IsRootWindowOrAnyChildFocused(). Renamed GetWindowIsFocused() to IsWindowFocused() --- imgui.cpp | 29 ++++++++++++++++++++++------- imgui.h | 5 ++++- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 53d2d9afd..9e1028761 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -129,8 +129,9 @@ Occasionally introducing changes that are breaking the API. The breakage are generally minor and easy to fix. 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. + - 2015/03/13 (1.36) - renamed GetWindowIsFocused() to IsWindowFocused(). Kept inline redirection function. - 2015/03/08 (1.35) - renamed style.ScrollBarWidth to style.ScrollbarWidth - - 2015/02/27 (1.34) - renamed OpenNextNode(bool) to SetNextTreeNodeOpened(bool, ImGuiSetCond), kept inline redirection function. + - 2015/02/27 (1.34) - renamed OpenNextNode(bool) to SetNextTreeNodeOpened(bool, ImGuiSetCond). Kept inline redirection function. - 2015/02/27 (1.34) - renamed ImGuiSetCondition_*** to ImGuiSetCond_***, and _FirstUseThisSession becomes _Once. - 2015/02/11 (1.32) - changed text input callback ImGuiTextEditCallback return type from void-->int. reserved for future use, return 0 for now. - 2015/02/10 (1.32) - renamed GetItemWidth() to CalcItemWidth() to clarify its evolving behavior @@ -1138,12 +1139,12 @@ struct ImGuiWindow bool SkipItems; // == Visible && !Collapsed int AutoFitFrames; bool AutoFitOnlyGrows; - int SetWindowPosAllowFlags; // bit ImGuiSetCond_*** specify if SetWindowPos() call is allowed with this particular flag. - int SetWindowSizeAllowFlags; // bit ImGuiSetCond_*** specify if SetWindowSize() call is allowed with this particular flag. - int SetWindowCollapsedAllowFlags; // bit ImGuiSetCond_*** specify if SetWindowCollapsed() call is allowed with this particular flag. + int SetWindowPosAllowFlags; // bit ImGuiSetCond_*** specify if SetWindowPos() call will succeed with this particular flag. + int SetWindowSizeAllowFlags; // bit ImGuiSetCond_*** specify if SetWindowSize() call will succeed with this particular flag. + int SetWindowCollapsedAllowFlags; // bit ImGuiSetCond_*** specify if SetWindowCollapsed() call will succeed with this particular flag. - ImGuiDrawContext DC; - ImVector IDStack; + ImGuiDrawContext DC; // Temporary per-window data, reset at the beginning of the frame + ImVector IDStack; // ID stack. ID are hashes seeded with the value at the top of the stack ImVector ClipRectStack; // Scissoring / clipping rectangle. x1, y1, x2, y2. ImGuiAabb ClippedAabb; // = ClipRectStack.front() after setup in Begin() int LastFrameDrawn; @@ -3481,13 +3482,27 @@ const char* ImGui::GetStyleColName(ImGuiCol idx) return "Unknown"; } -bool ImGui::GetWindowIsFocused() +bool ImGui::IsWindowFocused() { ImGuiState& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); return g.FocusedWindow == window; } +bool ImGui::IsRootWindowFocused() +{ + ImGuiState& g = *GImGui; + ImGuiWindow* root_window = GetCurrentWindow()->RootWindow; + return g.FocusedWindow == root_window; +} + +bool ImGui::IsRootWindowOrAnyChildFocused() +{ + ImGuiState& g = *GImGui; + ImGuiWindow* root_window = GetCurrentWindow()->RootWindow; + return g.FocusedWindow->RootWindow == root_window; +} + float ImGui::GetWindowWidth() { ImGuiWindow* window = GetCurrentWindow(); diff --git a/imgui.h b/imgui.h index fb24d89fa..869fde9b9 100644 --- a/imgui.h +++ b/imgui.h @@ -166,7 +166,6 @@ namespace ImGui IMGUI_API bool BeginChild(const char* str_id, const ImVec2& size = ImVec2(0,0), bool border = false, ImGuiWindowFlags extra_flags = 0); // size==0.0f: use remaining window size, size<0.0f: use remaining window size minus abs(size). on each axis. IMGUI_API bool BeginChild(ImGuiID id, const ImVec2& size = ImVec2(0,0), bool border = false, ImGuiWindowFlags extra_flags = 0); // " IMGUI_API void EndChild(); - IMGUI_API bool GetWindowIsFocused(); IMGUI_API ImVec2 GetContentRegionMax(); // window or current column boundaries, in windows coordinates IMGUI_API ImVec2 GetWindowContentRegionMin(); // window boundaries, in windows coordinates IMGUI_API ImVec2 GetWindowContentRegionMax(); @@ -346,6 +345,9 @@ namespace ImGui IMGUI_API bool IsItemHovered(); // was the last item hovered by mouse? IMGUI_API bool IsItemActive(); // was the last item active? (e.g. button being held, text field being edited- items that don't interact will always return false) IMGUI_API bool IsAnyItemActive(); // + IMGUI_API bool IsWindowFocused(); // is current window focused (differentiate child windows from each others) + IMGUI_API bool IsRootWindowFocused(); // is current root window focused + IMGUI_API bool IsRootWindowOrAnyChildFocused(); // is current root window or any of its child (including current window) focused IMGUI_API ImVec2 GetItemBoxMin(); // get bounding box of last item IMGUI_API ImVec2 GetItemBoxMax(); // get bounding box of last item IMGUI_API bool IsClipped(const ImVec2& item_size); // to perform coarse clipping on user's side (as an optimization) @@ -379,6 +381,7 @@ namespace ImGui // Obsolete (will be removed) IMGUI_API void GetDefaultFontData(const void** fnt_data, unsigned int* fnt_size, const void** png_data, unsigned int* png_size); static inline void OpenNextNode(bool open) { ImGui::SetNextTreeNodeOpened(open, 0); } + static inline bool GetWindowIsFocused() { return ImGui::IsWindowFocused(); } } // namespace ImGui From 153454a0fb656a74f5790912986de71bcfe01b11 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 13 Mar 2015 12:28:23 +0000 Subject: [PATCH 08/44] Example console keeps focus on input box at all times --- imgui.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 9e1028761..35b50820d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9478,7 +9478,7 @@ struct ExampleAppConsole ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0,0)); static ImGuiTextFilter filter; filter.Draw("Filter (\"incl,-excl\") (\"error\")", 180); - if (ImGui::IsItemHovered()) ImGui::SetKeyboardFocusHere(-1); // Auto focus on hover + //if (ImGui::IsItemHovered()) ImGui::SetKeyboardFocusHere(-1); // Auto focus on hover ImGui::PopStyleVar(); ImGui::Separator(); @@ -9516,7 +9516,9 @@ struct ExampleAppConsole strcpy(InputBuf, ""); } - if (ImGui::IsItemHovered()) ImGui::SetKeyboardFocusHere(-1); // Auto focus on hover + // Demonstrate keeping auto focus on the input box + if (ImGui::IsItemHovered() || (ImGui::IsRootWindowOrAnyChildFocused() && !ImGui::IsAnyItemActive() && !ImGui::IsMouseClicked(0))) + ImGui::SetKeyboardFocusHere(-1); // Auto focus ImGui::End(); } From 55093ea8fe0143b65ed1e1c22337c5c11016f58a Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 13 Mar 2015 12:44:04 +0000 Subject: [PATCH 09/44] Separator() logs itself as text --- imgui.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/imgui.cpp b/imgui.cpp index 35b50820d..3b0a6f862 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6487,6 +6487,10 @@ void ImGui::Separator() window->DrawList->AddLine(bb.Min, bb.Max, window->Color(ImGuiCol_Border)); + ImGuiState& g = *GImGui; + if (g.LogEnabled) + ImGui::LogText(STR_NEWLINE "--------------------------------"); + if (window->DC.ColumnsCount > 1) { PushColumnClipRect(); From ceb4da20388254124394fd76e3e6987628fae76e Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 13 Mar 2015 13:04:10 +0000 Subject: [PATCH 10/44] Comments --- imgui.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 3b0a6f862..c97b499da 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3105,6 +3105,15 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size, float bg // Save clipped aabb so we can access it in constant-time in FindHoveredWindow() window->ClippedAabb = window->Aabb(); window->ClippedAabb.Clip(window->ClipRectStack.front()); + + // Pressing CTRL+C while holding on a window copy its content to the clipboard + // This works but 1. doesn't handle multiple Begin/End pairs, 2. recursing into another Begin/End pair - so we need to work that out and add better logging scope. + // Maybe we can support CTRL+C on every element? + /* + if (g.ActiveId == move_id) + if (g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_C)) + ImGui::LogToClipboard(); + */ } // Inner clipping rectangle @@ -6530,7 +6539,7 @@ static void ItemSize(ImVec2 size, ImVec2* adjust_vertical_offset) window->DC.CurrentLineHeight = 0.0f; } -static void ItemSize(const ImGuiAabb& bb, ImVec2* adjust_start_offset) +static inline void ItemSize(const ImGuiAabb& bb, ImVec2* adjust_start_offset) { ItemSize(bb.GetSize(), adjust_start_offset); } From 4d78c5c9aba58447eec046a77dd0551b4d1922a7 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 13 Mar 2015 13:15:01 +0000 Subject: [PATCH 11/44] Comments and reduced ImGuiTextEditState.InitialText[] to 3 KB (assuming average use case of UTF-8 uses 3 bytes charracters) --- imgui.cpp | 2 +- imgui.h | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index c97b499da..5f7bd5fa8 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -958,7 +958,7 @@ struct ImGuiTextEditState { ImGuiID Id; // widget id owning the text state ImWchar Text[1024]; // edit buffer, we need to persist but can't guarantee the persistence of the user-provided buffer. so we copy into own buffer. - char InitialText[1024*4+1]; // backup of end-user buffer at the time of focus (in UTF-8, unaltered) + char InitialText[1024*3+1]; // backup of end-user buffer at the time of focus (in UTF-8, unaltered) size_t CurLenA, CurLenW; // we need to maintain our buffer length in both UTF-8 and wchar format. size_t BufSizeA; // end-user buffer size, <= 1024 (or increase above) float Width; // widget width diff --git a/imgui.h b/imgui.h index 869fde9b9..0ad58bf1a 100644 --- a/imgui.h +++ b/imgui.h @@ -693,7 +693,6 @@ struct ImGuiTextBuffer ImVector Buf; ImGuiTextBuffer() { Buf.push_back(0); } - ~ImGuiTextBuffer() { } const char* begin() const { return &Buf.front(); } const char* end() const { return &Buf.back(); } // Buf is zero-terminated, so end() will point on the zero-terminator size_t size() const { return Buf.size()-1; } @@ -902,7 +901,7 @@ struct ImFontAtlas IMGUI_API void SetTexID(void* id) { TexID = id; } // Helpers to retrieve list of common Unicode ranges (2 value per range, values are inclusive, zero-terminated list) - // (Those functions could be static, aren't so simple use case doesn't have to refer to the ImFontAtlas:: type ever if in their code) + // (Those functions could be static but aren't so most users don't have to refer to the ImFontAtlas:: name ever if in their code; just using io.Fonts->) IMGUI_API const ImWchar* GetGlyphRangesDefault(); // Basic Latin, Extended Latin IMGUI_API const ImWchar* GetGlyphRangesJapanese(); // Default + Hiragana, Katakana, Half-Width, Selection of 1946 Ideographs IMGUI_API const ImWchar* GetGlyphRangesChinese(); // Japanese + full set of about 21000 CJK Unified Ideographs From aaca73de156a92ad28620c9aea96eff23844cbc0 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 13 Mar 2015 13:23:03 +0000 Subject: [PATCH 12/44] Refactor SliderFloat() internals into a helper SliderFloatAsInputText() + some comments --- imgui.cpp | 61 ++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 38 insertions(+), 23 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 5f7bd5fa8..4c18cefbd 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4680,8 +4680,45 @@ static void ApplyNumericalTextInput(const char* buf, float *v) *v = op_v; } +static bool SliderFloatAsInputText(const char* label, float* v, const ImGuiID& id, int decimal_precision) +{ + ImGuiState& g = *GImGui; + ImGuiWindow* window = GetCurrentWindow(); + + char text_buf[64]; + ImFormatString(text_buf, IM_ARRAYSIZE(text_buf), "%.*f", decimal_precision, *v); + + SetActiveId(g.SliderAsInputTextId); + g.HoveredId = 0; + + // Our replacement widget will override the focus ID (registered previously to allow for a TAB focus to happen) + window->FocusItemUnregister(); + + bool value_changed = ImGui::InputText(label, text_buf, IM_ARRAYSIZE(text_buf), ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_AutoSelectAll); + if (g.SliderAsInputTextId == 0) + { + // First frame + IM_ASSERT(g.ActiveId == id); // InputText ID expected to match the Slider ID (else we'd need to store them both, which is also possible) + g.SliderAsInputTextId = g.ActiveId; + g.HoveredId = id; + } + else if (g.ActiveId != g.SliderAsInputTextId) + { + // Release + g.SliderAsInputTextId = 0; + } + if (value_changed) + { + ApplyNumericalTextInput(text_buf, v); + } + return value_changed; +} + // Use power!=1.0 for logarithmic sliders. // Adjust display_format to decorate the value with a prefix or a suffix. +// "%.3f" 1.234 +// "%5.2f secs" 01.23 secs +// "Gold: %.0f" Gold: 1 bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, const char* display_format, float power) { ImGuiState& g = *GImGui; @@ -4777,29 +4814,7 @@ bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, c bool value_changed = false; if (start_text_input || (g.ActiveId == id && id == g.SliderAsInputTextId)) { - char text_buf[64]; - ImFormatString(text_buf, IM_ARRAYSIZE(text_buf), "%.*f", decimal_precision, *v); - - 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); - if (g.SliderAsInputTextId == 0) - { - // First frame - IM_ASSERT(g.ActiveId == id); // InputText ID expected to match the Slider ID (else we'd need to store them both, which is also possible) - g.SliderAsInputTextId = g.ActiveId; - g.HoveredId = id; - } - else if (g.ActiveId != g.SliderAsInputTextId) - { - // Release - g.SliderAsInputTextId = 0; - } - if (value_changed) - { - ApplyNumericalTextInput(text_buf, v); - } + value_changed = SliderFloatAsInputText(label, v, id, decimal_precision); return value_changed; } From 110d96034b5d04b28c37faa498c43db5f7014085 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 13 Mar 2015 13:28:30 +0000 Subject: [PATCH 13/44] SliderFloat() fast-path when power=1.0f (no powf() calls) also makes code easier to read --- imgui.cpp | 63 ++++++++++++++++++++++++++++++++----------------------- 1 file changed, 37 insertions(+), 26 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 4c18cefbd..e29e31854 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4763,6 +4763,7 @@ bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, c const bool tab_focus_requested = window->FocusItemRegister(g.ActiveId == id); const bool is_unbound = v_min == -FLT_MAX || v_min == FLT_MAX || v_max == -FLT_MAX || v_max == FLT_MAX; + const bool is_logarithmic = abs(power - 1.0f) > 0.0001f; const float grab_size_in_units = 1.0f; // In 'v' units. Probably needs to be parametrized, based on a 'v_step' value? decimal precision? float grab_size_in_pixels; @@ -4830,28 +4831,33 @@ bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, c { const float normalized_pos = ImClamp((g.IO.MousePos.x - slider_effective_x1) / slider_effective_w, 0.0f, 1.0f); - // Linear slider - //float new_value = ImLerp(v_min, v_max, normalized_pos); - - // Account for logarithmic scale on both sides of the zero float new_value; - if (normalized_pos < linear_zero_pos) + if (is_logarithmic) { - // Negative: rescale to the negative range before powering - float a = 1.0f - (normalized_pos / linear_zero_pos); - a = powf(a, power); - new_value = ImLerp(ImMin(v_max,0.f), v_min, a); + // Account for logarithmic scale on both sides of the zero + if (normalized_pos < linear_zero_pos) + { + // Negative: rescale to the negative range before powering + float a = 1.0f - (normalized_pos / linear_zero_pos); + a = powf(a, power); + new_value = ImLerp(ImMin(v_max,0.f), v_min, a); + } + else + { + // Positive: rescale to the positive range before powering + float a; + if (fabsf(linear_zero_pos - 1.0f) > 1.e-6) + a = (normalized_pos - linear_zero_pos) / (1.0f - linear_zero_pos); + else + a = normalized_pos; + a = powf(a, power); + new_value = ImLerp(ImMax(v_min,0.0f), v_max, a); + } } else { - // Positive: rescale to the positive range before powering - float a; - if (fabsf(linear_zero_pos - 1.0f) > 1.e-6) - a = (normalized_pos - linear_zero_pos) / (1.0f - linear_zero_pos); - else - a = normalized_pos; - a = powf(a, power); - new_value = ImLerp(ImMax(v_min,0.0f), v_max, a); + // Linear slider + new_value = ImLerp(v_min, v_max, normalized_pos); } // Round past decimal precision @@ -4879,21 +4885,26 @@ bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, c if (!is_unbound) { - // Linear slider - // const float grab_t = (ImClamp(*v, v_min, v_max) - v_min) / (v_max - v_min); - // Calculate slider grab positioning float grab_t; - float v_clamped = ImClamp(*v, v_min, v_max); - if (v_clamped < 0.0f) + if (is_logarithmic) { - const float f = 1.0f - (v_clamped - v_min) / (ImMin(0.0f,v_max) - v_min); - grab_t = (1.0f - powf(f, 1.0f/power)) * linear_zero_pos; + float v_clamped = ImClamp(*v, v_min, v_max); + if (v_clamped < 0.0f) + { + const float f = 1.0f - (v_clamped - v_min) / (ImMin(0.0f,v_max) - v_min); + grab_t = (1.0f - powf(f, 1.0f/power)) * linear_zero_pos; + } + else + { + const float f = (v_clamped - ImMax(0.0f,v_min)) / (v_max - ImMax(0.0f,v_min)); + grab_t = linear_zero_pos + powf(f, 1.0f/power) * (1.0f - linear_zero_pos); + } } else { - const float f = (v_clamped - ImMax(0.0f,v_min)) / (v_max - ImMax(0.0f,v_min)); - grab_t = linear_zero_pos + powf(f, 1.0f/power) * (1.0f - linear_zero_pos); + // Linear slider + grab_t = (ImClamp(*v, v_min, v_max) - v_min) / (v_max - v_min); } // Draw From eff466d77d6318c99f51a2e25ed2f34bf5bf44f8 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 13 Mar 2015 13:38:58 +0000 Subject: [PATCH 14/44] Fixed parsing of decimal precision back from format string when using %% --- imgui.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index e29e31854..f2f3b89d4 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4735,9 +4735,10 @@ bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, c // Parse display precision back from the display format string int decimal_precision = 3; - if (const char* p = strchr(display_format, '%')) + for (const char* p = display_format; p = strchr(p, '%'); ) { p++; + if (p[0] == '%') { p ++; continue; } // Ignore "%%" while (*p >= '0' && *p <= '9') p++; if (*p == '.') @@ -4746,6 +4747,7 @@ bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, c if (decimal_precision < 0 || decimal_precision > 10) decimal_precision = 3; } + break; } const ImVec2 label_size = CalcTextSize(label, NULL, true); From 72855becabb989146b319fab2e385f8972bdcad6 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 14 Mar 2015 09:36:15 +0000 Subject: [PATCH 15/44] Slider code syntax tweaks --- imgui.cpp | 85 +++++++++++++++++++++++++++---------------------------- 1 file changed, 41 insertions(+), 44 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index f2f3b89d4..36c3f0f51 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4827,56 +4827,53 @@ bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, c // Process clicking on the slider if (g.ActiveId == id) { - if (g.IO.MouseDown[0]) + if (!is_unbound && g.IO.MouseDown[0]) { - if (!is_unbound) - { - const float normalized_pos = ImClamp((g.IO.MousePos.x - slider_effective_x1) / slider_effective_w, 0.0f, 1.0f); + const float normalized_pos = ImClamp((g.IO.MousePos.x - slider_effective_x1) / slider_effective_w, 0.0f, 1.0f); - float new_value; - if (is_logarithmic) + float new_value; + if (is_logarithmic) + { + // Account for logarithmic scale on both sides of the zero + if (normalized_pos < linear_zero_pos) { - // Account for logarithmic scale on both sides of the zero - if (normalized_pos < linear_zero_pos) - { - // Negative: rescale to the negative range before powering - float a = 1.0f - (normalized_pos / linear_zero_pos); - a = powf(a, power); - new_value = ImLerp(ImMin(v_max,0.f), v_min, a); - } + // Negative: rescale to the negative range before powering + float a = 1.0f - (normalized_pos / linear_zero_pos); + a = powf(a, power); + new_value = ImLerp(ImMin(v_max,0.f), v_min, a); + } + else + { + // Positive: rescale to the positive range before powering + float a; + if (fabsf(linear_zero_pos - 1.0f) > 1.e-6) + a = (normalized_pos - linear_zero_pos) / (1.0f - linear_zero_pos); else - { - // Positive: rescale to the positive range before powering - float a; - if (fabsf(linear_zero_pos - 1.0f) > 1.e-6) - a = (normalized_pos - linear_zero_pos) / (1.0f - linear_zero_pos); - else - a = normalized_pos; - a = powf(a, power); - new_value = ImLerp(ImMax(v_min,0.0f), v_max, a); - } - } - else - { - // Linear slider - new_value = ImLerp(v_min, v_max, normalized_pos); + a = normalized_pos; + a = powf(a, power); + new_value = ImLerp(ImMax(v_min,0.0f), v_max, a); } + } + else + { + // Linear slider + new_value = ImLerp(v_min, v_max, normalized_pos); + } - // Round past decimal precision - // 0->1, 1->0.1, 2->0.01, etc. - // So when our value is 1.99999 with a precision of 0.001 we'll end up rounding to 2.0 - const float min_step = 1.0f / powf(10.0f, (float)decimal_precision); - const float remainder = fmodf(new_value, min_step); - if (remainder <= min_step*0.5f) - new_value -= remainder; - else - new_value += (min_step - remainder); + // Round past decimal precision + // 0->1, 1->0.1, 2->0.01, etc. + // So when our value is 1.99999 with a precision of 0.001 we'll end up rounding to 2.0 + const float min_step = 1.0f / powf(10.0f, (float)decimal_precision); + const float remainder = fmodf(new_value, min_step); + if (remainder <= min_step*0.5f) + new_value -= remainder; + else + new_value += (min_step - remainder); - if (*v != new_value) - { - *v = new_value; - value_changed = true; - } + if (*v != new_value) + { + *v = new_value; + value_changed = true; } } else @@ -4915,7 +4912,7 @@ bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, c window->DrawList->AddRectFilled(grab_bb.Min, grab_bb.Max, window->Color(g.ActiveId == id ? ImGuiCol_SliderGrabActive : ImGuiCol_SliderGrab)); } - // Draw value using user-provided display format so user can add prefix/suffix/decorations to the value. + // Display value using user-provided display format so user can add prefix/suffix/decorations to the value. char value_buf[64]; char* value_buf_end = value_buf + ImFormatString(value_buf, IM_ARRAYSIZE(value_buf), display_format, *v); const ImVec2 value_text_size = CalcTextSize(value_buf, value_buf_end, true); From 834085c90c46ea4663233f667aadae25599b8135 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 14 Mar 2015 10:00:11 +0000 Subject: [PATCH 16/44] Examples: Updated to GLFW 3.1 --- .../opengl3_example/opengl3_example.vcxproj | 4 +- .../opengl_example/glfw/include/GLFW/glfw3.h | 1932 +++++++++++++---- .../glfw/include/GLFW/glfw3native.h | 212 +- .../opengl_example/glfw/lib-msvc100/glfw3.lib | Bin 121560 -> 0 bytes .../opengl_example/glfw/lib-msvc110/glfw3.lib | Bin 121720 -> 0 bytes .../glfw/lib-vc2010-32/glfw3.lib | Bin 0 -> 129546 bytes .../opengl_example/opengl_example.vcxproj | 4 +- 7 files changed, 1701 insertions(+), 451 deletions(-) delete mode 100644 examples/opengl_example/glfw/lib-msvc100/glfw3.lib delete mode 100644 examples/opengl_example/glfw/lib-msvc110/glfw3.lib create mode 100644 examples/opengl_example/glfw/lib-vc2010-32/glfw3.lib diff --git a/examples/opengl3_example/opengl3_example.vcxproj b/examples/opengl3_example/opengl3_example.vcxproj index cda336d2c..3dd9afdfa 100644 --- a/examples/opengl3_example/opengl3_example.vcxproj +++ b/examples/opengl3_example/opengl3_example.vcxproj @@ -54,7 +54,7 @@ true - $(ProjectDir)..\opengl_example\glfw\lib-msvc100;$(ProjectDir)..\opengl_example\glew\lib\Release\Win32;%(AdditionalLibraryDirectories) + $(ProjectDir)..\opengl_example\glfw\lib-vc2010-32;%(AdditionalLibraryDirectories) opengl32.lib;glfw3.lib;%(AdditionalDependencies) Console msvcrt.lib @@ -72,7 +72,7 @@ true true true - $(ProjectDir)..\opengl_example\glfw\lib-msvc100;$(ProjectDir)..\opengl_example\glew\lib\Release\Win32;%(AdditionalLibraryDirectories) + $(ProjectDir)..\opengl_example\glfw\lib-vc2010-32;%(AdditionalLibraryDirectories) opengl32.lib;glfw3.lib;%(AdditionalDependencies) Console diff --git a/examples/opengl_example/glfw/include/GLFW/glfw3.h b/examples/opengl_example/glfw/include/GLFW/glfw3.h index 8b11c2fc0..89414491e 100644 --- a/examples/opengl_example/glfw/include/GLFW/glfw3.h +++ b/examples/opengl_example/glfw/include/GLFW/glfw3.h @@ -1,5 +1,5 @@ /************************************************************************* - * GLFW 3.0 - www.glfw.org + * GLFW 3.1 - www.glfw.org * A library for OpenGL, window and input *------------------------------------------------------------------------ * Copyright (c) 2002-2006 Marcus Geelnard @@ -38,23 +38,27 @@ extern "C" { * Doxygen documentation *************************************************************************/ -/*! @defgroup clipboard Clipboard support - */ /*! @defgroup context Context handling + * + * This is the reference documentation for context related functions. For more + * information, see the @ref context. */ -/*! @defgroup error Error handling - */ -/*! @defgroup init Initialization and version information +/*! @defgroup init Initialization, version and errors + * + * This is the reference documentation for initialization and termination of + * the library, version management and error handling. For more information, + * see the @ref intro. */ /*! @defgroup input Input handling + * + * This is the reference documentation for input related functions and types. + * For more information, see the @ref input. */ /*! @defgroup monitor Monitor handling * * This is the reference documentation for monitor related functions and types. * For more information, see the @ref monitor. */ -/*! @defgroup time Time input - */ /*! @defgroup window Window handling * * This is the reference documentation for window related functions and types, @@ -140,63 +144,81 @@ extern "C" { /* Include the chosen client API headers. */ #if defined(__APPLE_CC__) - #if defined(GLFW_INCLUDE_GLCOREARB) - #include - #elif !defined(GLFW_INCLUDE_NONE) - #define GL_GLEXT_LEGACY - #include + #if defined(GLFW_INCLUDE_GLCOREARB) + #include + #if defined(GLFW_INCLUDE_GLEXT) + #include #endif - #if defined(GLFW_INCLUDE_GLU) - #include + #elif !defined(GLFW_INCLUDE_NONE) + #if !defined(GLFW_INCLUDE_GLEXT) + #define GL_GLEXT_LEGACY #endif + #include + #endif + #if defined(GLFW_INCLUDE_GLU) + #include + #endif #else - #if defined(GLFW_INCLUDE_GLCOREARB) - #include - #elif defined(GLFW_INCLUDE_ES1) - #include - #elif defined(GLFW_INCLUDE_ES2) - #include - #elif defined(GLFW_INCLUDE_ES3) - #include - #elif !defined(GLFW_INCLUDE_NONE) - #include + #if defined(GLFW_INCLUDE_GLCOREARB) + #include + #elif defined(GLFW_INCLUDE_ES1) + #include + #if defined(GLFW_INCLUDE_GLEXT) + #include #endif - #if defined(GLFW_INCLUDE_GLU) - #include + #elif defined(GLFW_INCLUDE_ES2) + #include + #if defined(GLFW_INCLUDE_GLEXT) + #include #endif + #elif defined(GLFW_INCLUDE_ES3) + #include + #if defined(GLFW_INCLUDE_GLEXT) + #include + #endif + #elif defined(GLFW_INCLUDE_ES31) + #include + #if defined(GLFW_INCLUDE_GLEXT) + #include + #endif + #elif !defined(GLFW_INCLUDE_NONE) + #include + #if defined(GLFW_INCLUDE_GLEXT) + #include + #endif + #endif + #if defined(GLFW_INCLUDE_GLU) + #include + #endif #endif #if defined(GLFW_DLL) && defined(_GLFW_BUILD_DLL) - /* GLFW_DLL is defined by users of GLFW when compiling programs that will link - * to the DLL version of the GLFW library. _GLFW_BUILD_DLL is defined by the - * GLFW configuration header when compiling the DLL version of the library. + /* GLFW_DLL must be defined by applications that are linking against the DLL + * version of the GLFW library. _GLFW_BUILD_DLL is defined by the GLFW + * configuration header when compiling the DLL version of the library. */ #error "You must not have both GLFW_DLL and _GLFW_BUILD_DLL defined" #endif +/* GLFWAPI is used to declare public API functions for export + * from the DLL / shared library / dynamic library. + */ #if defined(_WIN32) && defined(_GLFW_BUILD_DLL) - - /* We are building a Win32 DLL */ + /* We are building GLFW as a Win32 DLL */ #define GLFWAPI __declspec(dllexport) - #elif defined(_WIN32) && defined(GLFW_DLL) - - /* We are calling a Win32 DLL */ + /* We are calling GLFW as a Win32 DLL */ #if defined(__LCC__) #define GLFWAPI extern #else #define GLFWAPI __declspec(dllimport) #endif - #elif defined(__GNUC__) && defined(_GLFW_BUILD_DLL) - + /* We are building GLFW as a shared / dynamic library */ #define GLFWAPI __attribute__((visibility("default"))) - #else - - /* We are either building/calling a static lib or we are non-win32 */ + /* We are building or calling GLFW as a static library */ #define GLFWAPI - #endif /* -------------------- END SYSTEM/COMPILER SPECIFIC --------------------- */ @@ -220,27 +242,36 @@ extern "C" { * backward-compatible. * @ingroup init */ -#define GLFW_VERSION_MINOR 0 +#define GLFW_VERSION_MINOR 1 /*! @brief The revision number of the GLFW library. * * This is incremented when a bug fix release is made that does not contain any * API changes. * @ingroup init */ -#define GLFW_VERSION_REVISION 3 +#define GLFW_VERSION_REVISION 0 /*! @} */ /*! @name Key and button actions * @{ */ -/*! @brief The key or button was released. +/*! @brief The key or mouse button was released. + * + * The key or mouse button was released. + * * @ingroup input */ #define GLFW_RELEASE 0 -/*! @brief The key or button was pressed. +/*! @brief The key or mouse button was pressed. + * + * The key or mouse button was pressed. + * * @ingroup input */ #define GLFW_PRESS 1 /*! @brief The key was held down until it repeated. + * + * The key was held down until it repeated. + * * @ingroup input */ #define GLFW_REPEAT 2 @@ -248,20 +279,22 @@ extern "C" { /*! @defgroup keys Keyboard keys * - * These key codes are inspired by the *USB HID Usage Tables v1.12* (p. 53-60), - * but re-arranged to map to 7-bit ASCII for printable keys (function keys are - * put in the 256+ range). + * See [key input](@ref input_key) for how these are used. * - * The naming of the key codes follow these rules: - * - The US keyboard layout is used - * - Names of printable alpha-numeric characters are used (e.g. "A", "R", - * "3", etc.) - * - For non-alphanumeric characters, Unicode:ish names are used (e.g. - * "COMMA", "LEFT_SQUARE_BRACKET", etc.). Note that some names do not - * correspond to the Unicode standard (usually for brevity) - * - Keys that lack a clear US mapping are named "WORLD_x" - * - For non-printable keys, custom names are used (e.g. "F4", - * "BACKSPACE", etc.) + * These key codes are inspired by the _USB HID Usage Tables v1.12_ (p. 53-60), + * but re-arranged to map to 7-bit ASCII for printable keys (function keys are + * put in the 256+ range). + * + * The naming of the key codes follow these rules: + * - The US keyboard layout is used + * - Names of printable alpha-numeric characters are used (e.g. "A", "R", + * "3", etc.) + * - For non-alphanumeric characters, Unicode:ish names are used (e.g. + * "COMMA", "LEFT_SQUARE_BRACKET", etc.). Note that some names do not + * correspond to the Unicode standard (usually for brevity) + * - Keys that lack a clear US mapping are named "WORLD_x" + * - For non-printable keys, custom names are used (e.g. "F4", + * "BACKSPACE", etc.) * * @ingroup input * @{ @@ -398,6 +431,9 @@ extern "C" { /*! @} */ /*! @defgroup mods Modifier key flags + * + * See [key input](@ref input_key) for how these are used. + * * @ingroup input * @{ */ @@ -417,6 +453,9 @@ extern "C" { /*! @} */ /*! @defgroup buttons Mouse buttons + * + * See [mouse button input](@ref input_mouse_button) for how these are used. + * * @ingroup input * @{ */ #define GLFW_MOUSE_BUTTON_1 0 @@ -434,6 +473,9 @@ extern "C" { /*! @} */ /*! @defgroup joysticks Joysticks + * + * See [joystick input](@ref joystick) for how these are used. + * * @ingroup input * @{ */ #define GLFW_JOYSTICK_1 0 @@ -456,36 +498,128 @@ extern "C" { /*! @} */ /*! @defgroup errors Error codes - * @ingroup error + * + * See [error handling](@ref error_handling) for how these are used. + * + * @ingroup init * @{ */ /*! @brief GLFW has not been initialized. + * + * This occurs if a GLFW function was called that may not be called unless the + * library is [initialized](@ref intro_init). + * + * @par Analysis + * Application programmer error. Initialize GLFW before calling any function + * that requires initialization. */ #define GLFW_NOT_INITIALIZED 0x00010001 /*! @brief No context is current for this thread. + * + * This occurs if a GLFW function was called that needs and operates on the + * current OpenGL or OpenGL ES context but no context is current on the calling + * thread. One such function is @ref glfwSwapInterval. + * + * @par Analysis + * Application programmer error. Ensure a context is current before calling + * functions that require a current context. */ #define GLFW_NO_CURRENT_CONTEXT 0x00010002 -/*! @brief One of the enum parameters for the function was given an invalid - * enum. +/*! @brief One of the arguments to the function was an invalid enum value. + * + * One of the arguments to the function was an invalid enum value, for example + * requesting [GLFW_RED_BITS](@ref window_hints_fb) with @ref + * glfwGetWindowAttrib. + * + * @par Analysis + * Application programmer error. Fix the offending call. */ #define GLFW_INVALID_ENUM 0x00010003 -/*! @brief One of the parameters for the function was given an invalid value. +/*! @brief One of the arguments to the function was an invalid value. + * + * One of the arguments to the function was an invalid value, for example + * requesting a non-existent OpenGL or OpenGL ES version like 2.7. + * + * Requesting a valid but unavailable OpenGL or OpenGL ES version will instead + * result in a @ref GLFW_VERSION_UNAVAILABLE error. + * + * @par Analysis + * Application programmer error. Fix the offending call. */ #define GLFW_INVALID_VALUE 0x00010004 /*! @brief A memory allocation failed. + * + * A memory allocation failed. + * + * @par Analysis + * A bug in GLFW or the underlying operating system. Report the bug to our + * [issue tracker](https://github.com/glfw/glfw/issues). */ #define GLFW_OUT_OF_MEMORY 0x00010005 /*! @brief GLFW could not find support for the requested client API on the * system. + * + * GLFW could not find support for the requested client API on the system. + * + * @par Analysis + * The installed graphics driver does not support the requested client API, or + * does not support it via the chosen context creation backend. Below are + * a few examples. + * + * @par + * Some pre-installed Windows graphics drivers do not support OpenGL. AMD only + * supports OpenGL ES via EGL, while Nvidia and Intel only supports it via + * a WGL or GLX extension. OS X does not provide OpenGL ES at all. The Mesa + * EGL, OpenGL and OpenGL ES libraries do not interface with the Nvidia binary + * driver. */ #define GLFW_API_UNAVAILABLE 0x00010006 -/*! @brief The requested client API version is not available. +/*! @brief The requested OpenGL or OpenGL ES version is not available. + * + * The requested OpenGL or OpenGL ES version (including any requested profile + * or context option) is not available on this machine. + * + * @par Analysis + * The machine does not support your requirements. If your application is + * sufficiently flexible, downgrade your requirements and try again. + * Otherwise, inform the user that their machine does not match your + * requirements. + * + * @par + * Future invalid OpenGL and OpenGL ES versions, for example OpenGL 4.8 if 5.0 + * comes out before the 4.x series gets that far, also fail with this error and + * not @ref GLFW_INVALID_VALUE, because GLFW cannot know what future versions + * will exist. */ #define GLFW_VERSION_UNAVAILABLE 0x00010007 /*! @brief A platform-specific error occurred that does not match any of the * more specific categories. + * + * A platform-specific error occurred that does not match any of the more + * specific categories. + * + * @par Analysis + * A bug in GLFW or the underlying operating system. Report the bug to our + * [issue tracker](https://github.com/glfw/glfw/issues). */ #define GLFW_PLATFORM_ERROR 0x00010008 -/*! @brief The clipboard did not contain data in the requested format. +/*! @brief The requested format is not supported or available. + * + * If emitted during window creation, the requested pixel format is not + * supported. + * + * If emitted when querying the clipboard, the contents of the clipboard could + * not be converted to the requested format. + * + * @par Analysis + * If emitted during window creation, one or more + * [hard constraints](@ref window_hints_hard) did not match any of the + * available pixel formats. If your application is sufficiently flexible, + * downgrade your requirements and try again. Otherwise, inform the user that + * their machine does not match your requirements. + * + * @par + * If emitted when querying the clipboard, ignore the error or report it to + * the user, as appropriate. */ #define GLFW_FORMAT_UNAVAILABLE 0x00010009 /*! @} */ @@ -495,6 +629,8 @@ extern "C" { #define GLFW_RESIZABLE 0x00020003 #define GLFW_VISIBLE 0x00020004 #define GLFW_DECORATED 0x00020005 +#define GLFW_AUTO_ICONIFY 0x00020006 +#define GLFW_FLOATING 0x00020007 #define GLFW_RED_BITS 0x00021001 #define GLFW_GREEN_BITS 0x00021002 @@ -511,6 +647,7 @@ extern "C" { #define GLFW_SAMPLES 0x0002100D #define GLFW_SRGB_CAPABLE 0x0002100E #define GLFW_REFRESH_RATE 0x0002100F +#define GLFW_DOUBLEBUFFER 0x00021010 #define GLFW_CLIENT_API 0x00022001 #define GLFW_CONTEXT_VERSION_MAJOR 0x00022002 @@ -520,6 +657,7 @@ extern "C" { #define GLFW_OPENGL_FORWARD_COMPAT 0x00022006 #define GLFW_OPENGL_DEBUG_CONTEXT 0x00022007 #define GLFW_OPENGL_PROFILE 0x00022008 +#define GLFW_CONTEXT_RELEASE_BEHAVIOR 0x00022009 #define GLFW_OPENGL_API 0x00030001 #define GLFW_OPENGL_ES_API 0x00030002 @@ -540,9 +678,54 @@ extern "C" { #define GLFW_CURSOR_HIDDEN 0x00034002 #define GLFW_CURSOR_DISABLED 0x00034003 +#define GLFW_ANY_RELEASE_BEHAVIOR 0 +#define GLFW_RELEASE_BEHAVIOR_FLUSH 0x00035001 +#define GLFW_RELEASE_BEHAVIOR_NONE 0x00035002 + +/*! @defgroup shapes Standard cursor shapes + * + * See [standard cursor creation](@ref cursor_standard) for how these are used. + * + * @ingroup input + * @{ */ + +/*! @brief The regular arrow cursor shape. + * + * The regular arrow cursor. + */ +#define GLFW_ARROW_CURSOR 0x00036001 +/*! @brief The text input I-beam cursor shape. + * + * The text input I-beam cursor shape. + */ +#define GLFW_IBEAM_CURSOR 0x00036002 +/*! @brief The crosshair shape. + * + * The crosshair shape. + */ +#define GLFW_CROSSHAIR_CURSOR 0x00036003 +/*! @brief The hand shape. + * + * The hand shape. + */ +#define GLFW_HAND_CURSOR 0x00036004 +/*! @brief The horizontal resize arrow shape. + * + * The horizontal resize arrow shape. + */ +#define GLFW_HRESIZE_CURSOR 0x00036005 +/*! @brief The vertical resize arrow shape. + * + * The vertical resize arrow shape. + */ +#define GLFW_VRESIZE_CURSOR 0x00036006 +/*! @} */ + #define GLFW_CONNECTED 0x00040001 #define GLFW_DISCONNECTED 0x00040002 +#define GLFW_DONT_CARE -1 + /************************************************************************* * GLFW API types @@ -573,6 +756,14 @@ typedef struct GLFWmonitor GLFWmonitor; */ typedef struct GLFWwindow GLFWwindow; +/*! @brief Opaque cursor object. + * + * Opaque cursor object. + * + * @ingroup cursor + */ +typedef struct GLFWcursor GLFWcursor; + /*! @brief The function signature for error callbacks. * * This is the function signature for error callback functions. @@ -582,7 +773,7 @@ typedef struct GLFWwindow GLFWwindow; * * @sa glfwSetErrorCallback * - * @ingroup error + * @ingroup init */ typedef void (* GLFWerrorfun)(int,const char*); @@ -590,7 +781,7 @@ typedef void (* GLFWerrorfun)(int,const char*); * * This is the function signature for window position callback functions. * - * @param[in] window The window that the user moved. + * @param[in] window The window that was moved. * @param[in] xpos The new x-coordinate, in screen coordinates, of the * upper-left corner of the client area of the window. * @param[in] ypos The new y-coordinate, in screen coordinates, of the @@ -606,7 +797,7 @@ typedef void (* GLFWwindowposfun)(GLFWwindow*,int,int); * * This is the function signature for window size callback functions. * - * @param[in] window The window that the user resized. + * @param[in] window The window that was resized. * @param[in] width The new width, in screen coordinates, of the window. * @param[in] height The new height, in screen coordinates, of the window. * @@ -644,9 +835,9 @@ typedef void (* GLFWwindowrefreshfun)(GLFWwindow*); * * This is the function signature for window focus callback functions. * - * @param[in] window The window that was focused or defocused. - * @param[in] focused `GL_TRUE` if the window was focused, or `GL_FALSE` if - * it was defocused. + * @param[in] window The window that gained or lost input focus. + * @param[in] focused `GL_TRUE` if the window was given input focus, or + * `GL_FALSE` if it lost it. * * @sa glfwSetWindowFocusCallback * @@ -706,8 +897,8 @@ typedef void (* GLFWmousebuttonfun)(GLFWwindow*,int,int,int); * This is the function signature for cursor position callback functions. * * @param[in] window The window that received the event. - * @param[in] xpos The new x-coordinate of the cursor. - * @param[in] ypos The new y-coordinate of the cursor. + * @param[in] xpos The new x-coordinate, in screen coordinates, of the cursor. + * @param[in] ypos The new y-coordinate, in screen coordinates, of the cursor. * * @sa glfwSetCursorPosCallback * @@ -750,7 +941,7 @@ typedef void (* GLFWscrollfun)(GLFWwindow*,double,double); * @param[in] window The window that received the event. * @param[in] key The [keyboard key](@ref keys) that was pressed or released. * @param[in] scancode The system-specific scancode of the key. - * @param[in] action @ref GLFW_PRESS, @ref GLFW_RELEASE or @ref GLFW_REPEAT. + * @param[in] action `GLFW_PRESS`, `GLFW_RELEASE` or `GLFW_REPEAT`. * @param[in] mods Bit field describing which [modifier keys](@ref mods) were * held down. * @@ -765,7 +956,7 @@ typedef void (* GLFWkeyfun)(GLFWwindow*,int,int,int,int); * This is the function signature for Unicode character callback functions. * * @param[in] window The window that received the event. - * @param[in] character The Unicode code point of the character. + * @param[in] codepoint The Unicode code point of the character. * * @sa glfwSetCharCallback * @@ -773,6 +964,38 @@ typedef void (* GLFWkeyfun)(GLFWwindow*,int,int,int,int); */ typedef void (* GLFWcharfun)(GLFWwindow*,unsigned int); +/*! @brief The function signature for Unicode character with modifiers + * callbacks. + * + * This is the function signature for Unicode character with modifiers callback + * functions. It is called for each input character, regardless of what + * modifier keys are held down. + * + * @param[in] window The window that received the event. + * @param[in] codepoint The Unicode code point of the character. + * @param[in] mods Bit field describing which [modifier keys](@ref mods) were + * held down. + * + * @sa glfwSetCharModsCallback + * + * @ingroup input + */ +typedef void (* GLFWcharmodsfun)(GLFWwindow*,unsigned int,int); + +/*! @brief The function signature for file drop callbacks. + * + * This is the function signature for file drop callbacks. + * + * @param[in] window The window that received the event. + * @param[in] count The number of dropped files. + * @param[in] names The UTF-8 encoded path names of the dropped files. + * + * @sa glfwSetDropCallback + * + * @ingroup input + */ +typedef void (* GLFWdropfun)(GLFWwindow*,int,const char**); + /*! @brief The function signature for monitor configuration callbacks. * * This is the function signature for monitor configuration callback functions. @@ -838,6 +1061,21 @@ typedef struct GLFWgammaramp unsigned int size; } GLFWgammaramp; +/*! @brief Image data. + */ +typedef struct GLFWimage +{ + /*! The width, in pixels, of this image. + */ + int width; + /*! The height, in pixels, of this image. + */ + int height; + /*! The pixel data of this image, arranged left-to-right, top-to-bottom. + */ + unsigned char* pixels; +} GLFWimage; + /************************************************************************* * GLFW API functions @@ -846,56 +1084,70 @@ typedef struct GLFWgammaramp /*! @brief Initializes the GLFW library. * * This function initializes the GLFW library. Before most GLFW functions can - * be used, GLFW must be initialized, and before a program terminates GLFW + * be used, GLFW must be initialized, and before an application terminates GLFW * should be terminated in order to free any resources allocated during or * after initialization. * * If this function fails, it calls @ref glfwTerminate before returning. If it - * succeeds, you should call @ref glfwTerminate before the program exits. + * succeeds, you should call @ref glfwTerminate before the application exits. * * Additional calls to this function after successful initialization but before - * termination will succeed but will do nothing. + * termination will return `GL_TRUE` immediately. * - * @return `GL_TRUE` if successful, or `GL_FALSE` if an error occurred. + * @return `GL_TRUE` if successful, or `GL_FALSE` if an + * [error](@ref error_handling) occurred. * - * @par New in GLFW 3 - * This function no longer registers @ref glfwTerminate with `atexit`. - * - * @note This function may only be called from the main thread. - * - * @note This function may take several seconds to complete on some systems, - * while on other systems it may take only a fraction of a second to complete. - * - * @note **Mac OS X:** This function will change the current directory of the + * @remarks __OS X:__ This function will change the current directory of the * application to the `Contents/Resources` subdirectory of the application's - * bundle, if present. + * bundle, if present. This can be disabled with a + * [compile-time option](@ref compile_options_osx). * + * @remarks __X11:__ If the `LC_CTYPE` category of the current locale is set to + * `"C"` then the environment's locale will be applied to that category. This + * is done because character input will not function when `LC_CTYPE` is set to + * `"C"`. If another locale was set before this function was called, it will + * be left untouched. + * + * @par Thread Safety + * This function may only be called from the main thread. + * + * @sa @ref intro_init * @sa glfwTerminate * + * @since Added in GLFW 1.0. + * * @ingroup init */ GLFWAPI int glfwInit(void); /*! @brief Terminates the GLFW library. * - * This function destroys all remaining windows, frees any allocated resources - * and sets the library to an uninitialized state. Once this is called, you - * must again call @ref glfwInit successfully before you will be able to use - * most GLFW functions. + * This function destroys all remaining windows and cursors, restores any + * modified gamma ramps and frees any other allocated resources. Once this + * function is called, you must again call @ref glfwInit successfully before + * you will be able to use most GLFW functions. * * If GLFW has been successfully initialized, this function should be called - * before the program exits. If initialization fails, there is no need to call - * this function, as it is called by @ref glfwInit before it returns failure. + * before the application exits. If initialization fails, there is no need to + * call this function, as it is called by @ref glfwInit before it returns + * failure. * * @remarks This function may be called before @ref glfwInit. * - * @note This function may only be called from the main thread. - * * @warning No window's context may be current on another thread when this * function is called. * + * @par Reentrancy + * This function may not be called from a callback. + * + * @par Thread Safety + * This function may only be called from the main thread. + * + * @sa @ref intro_init * @sa glfwInit * + * @since Added in GLFW 1.0. + * * @ingroup init */ GLFWAPI void glfwTerminate(void); @@ -906,46 +1158,55 @@ GLFWAPI void glfwTerminate(void); * library. It is intended for when you are using GLFW as a shared library and * want to ensure that you are using the minimum required version. * + * Any or all of the version arguments may be `NULL`. This function always + * succeeds. + * * @param[out] major Where to store the major version number, or `NULL`. * @param[out] minor Where to store the minor version number, or `NULL`. * @param[out] rev Where to store the revision number, or `NULL`. * * @remarks This function may be called before @ref glfwInit. * - * @remarks This function may be called from any thread. + * @par Thread Safety + * This function may be called from any thread. * + * @sa @ref intro_version * @sa glfwGetVersionString * + * @since Added in GLFW 1.0. + * * @ingroup init */ GLFWAPI void glfwGetVersion(int* major, int* minor, int* rev); /*! @brief Returns a string describing the compile-time configuration. * - * This function returns a static string generated at compile-time according to - * which configuration macros were defined. This is intended for use when - * submitting bug reports, to allow developers to see which code paths are - * enabled in a binary. + * This function returns the compile-time generated + * [version string](@ref intro_version_string) of the GLFW library binary. It + * describes the version, platform, compiler and any platform-specific + * compile-time options. * - * The format of the string is as follows: - * - The version of GLFW - * - The name of the window system API - * - The name of the context creation API - * - Any additional options or APIs + * __Do not use the version string__ to parse the GLFW library version. The + * @ref glfwGetVersion function already provides the version of the running + * library binary. * - * For example, when compiling GLFW 3.0 with MinGW using the Win32 and WGL - * back ends, the version string may look something like this: - * - * 3.0.0 Win32 WGL MinGW + * This function always succeeds. * * @return The GLFW version string. * * @remarks This function may be called before @ref glfwInit. * - * @remarks This function may be called from any thread. + * @par Pointer Lifetime + * The returned string is static and compile-time generated. * + * @par Thread Safety + * This function may be called from any thread. + * + * @sa @ref intro_version * @sa glfwGetVersion * + * @since Added in GLFW 3.0. + * * @ingroup init */ GLFWAPI const char* glfwGetVersionString(void); @@ -955,23 +1216,31 @@ GLFWAPI const char* glfwGetVersionString(void); * This function sets the error callback, which is called with an error code * and a human-readable description each time a GLFW error occurs. * + * The error callback is called on the thread where the error occurred. If you + * are using GLFW from multiple threads, your error callback needs to be + * written accordingly. + * + * Because the description string may have been generated specifically for that + * error, it is not guaranteed to be valid after the callback has returned. If + * you wish to use it after the callback returns, you need to make a copy. + * + * Once set, the error callback remains set even after the library has been + * terminated. + * * @param[in] cbfun The new callback, or `NULL` to remove the currently set * callback. - * @return The previously set callback, or `NULL` if no callback was set or an - * error occurred. + * @return The previously set callback, or `NULL` if no callback was set. * * @remarks This function may be called before @ref glfwInit. * - * @note The error callback is called by the thread where the error was - * generated. If you are using GLFW from multiple threads, your error callback - * needs to be written accordingly. + * @par Thread Safety + * This function may only be called from the main thread. * - * @note Because the description string provided to the callback may have been - * generated specifically for that error, it is not guaranteed to be valid - * after the callback has returned. If you wish to use it after that, you need - * to make your own copy of it before returning. + * @sa @ref error_handling * - * @ingroup error + * @since Added in GLFW 3.0. + * + * @ingroup init */ GLFWAPI GLFWerrorfun glfwSetErrorCallback(GLFWerrorfun cbfun); @@ -980,19 +1249,25 @@ GLFWAPI GLFWerrorfun glfwSetErrorCallback(GLFWerrorfun cbfun); * This function returns an array of handles for all currently connected * monitors. * - * @param[out] count Where to store the size of the returned array. This is - * set to zero if an error occurred. - * @return An array of monitor handles, or `NULL` if an error occurred. + * @param[out] count Where to store the number of monitors in the returned + * array. This is set to zero if an error occurred. + * @return An array of monitor handles, or `NULL` if an + * [error](@ref error_handling) occurred. * - * @note The returned array is allocated and freed by GLFW. You should not - * free it yourself. + * @par Pointer Lifetime + * The returned array is allocated and freed by GLFW. You should not free it + * yourself. It is guaranteed to be valid only until the monitor configuration + * changes or the library is terminated. * - * @note The returned array is valid only until the monitor configuration - * changes. See @ref glfwSetMonitorCallback to receive notifications of - * configuration changes. + * @par Thread Safety + * This function may only be called from the main thread. * + * @sa @ref monitor_monitors + * @sa @ref monitor_event * @sa glfwGetPrimaryMonitor * + * @since Added in GLFW 3.0. + * * @ingroup monitor */ GLFWAPI GLFWmonitor** glfwGetMonitors(int* count); @@ -1002,10 +1277,17 @@ GLFWAPI GLFWmonitor** glfwGetMonitors(int* count); * This function returns the primary monitor. This is usually the monitor * where elements like the Windows task bar or the OS X menu bar is located. * - * @return The primary monitor, or `NULL` if an error occurred. + * @return The primary monitor, or `NULL` if an [error](@ref error_handling) + * occurred. * + * @par Thread Safety + * This function may only be called from the main thread. + * + * @sa @ref monitor_monitors * @sa glfwGetMonitors * + * @since Added in GLFW 3.0. + * * @ingroup monitor */ GLFWAPI GLFWmonitor* glfwGetPrimaryMonitor(void); @@ -1015,10 +1297,20 @@ GLFWAPI GLFWmonitor* glfwGetPrimaryMonitor(void); * This function returns the position, in screen coordinates, of the upper-left * corner of the specified monitor. * + * Any or all of the position arguments may be `NULL`. If an error occurs, all + * non-`NULL` position arguments will be set to zero. + * * @param[in] monitor The monitor to query. * @param[out] xpos Where to store the monitor x-coordinate, or `NULL`. * @param[out] ypos Where to store the monitor y-coordinate, or `NULL`. * + * @par Thread Safety + * This function may only be called from the main thread. + * + * @sa @ref monitor_properties + * + * @since Added in GLFW 3.0. + * * @ingroup monitor */ GLFWAPI void glfwGetMonitorPos(GLFWmonitor* monitor, int* xpos, int* ypos); @@ -1028,31 +1320,55 @@ GLFWAPI void glfwGetMonitorPos(GLFWmonitor* monitor, int* xpos, int* ypos); * This function returns the size, in millimetres, of the display area of the * specified monitor. * - * @param[in] monitor The monitor to query. - * @param[out] width Where to store the width, in mm, of the monitor's display - * area, or `NULL`. - * @param[out] height Where to store the height, in mm, of the monitor's - * display area, or `NULL`. + * Some systems do not provide accurate monitor size information, either + * because the monitor + * [EDID](https://en.wikipedia.org/wiki/Extended_display_identification_data) + * data is incorrect or because the driver does not report it accurately. * - * @note Some operating systems do not provide accurate information, either - * because the monitor's EDID data is incorrect, or because the driver does not - * report it accurately. + * Any or all of the size arguments may be `NULL`. If an error occurs, all + * non-`NULL` size arguments will be set to zero. + * + * @param[in] monitor The monitor to query. + * @param[out] widthMM Where to store the width, in millimetres, of the + * monitor's display area, or `NULL`. + * @param[out] heightMM Where to store the height, in millimetres, of the + * monitor's display area, or `NULL`. + * + * @remarks __Windows:__ The OS calculates the returned physical size from the + * current resolution and system DPI instead of querying the monitor EDID data. + * + * @par Thread Safety + * This function may only be called from the main thread. + * + * @sa @ref monitor_properties + * + * @since Added in GLFW 3.0. * * @ingroup monitor */ -GLFWAPI void glfwGetMonitorPhysicalSize(GLFWmonitor* monitor, int* width, int* height); +GLFWAPI void glfwGetMonitorPhysicalSize(GLFWmonitor* monitor, int* widthMM, int* heightMM); /*! @brief Returns the name of the specified monitor. * * This function returns a human-readable name, encoded as UTF-8, of the - * specified monitor. + * specified monitor. The name typically reflects the make and model of the + * monitor and is not guaranteed to be unique among the connected monitors. * * @param[in] monitor The monitor to query. - * @return The UTF-8 encoded name of the monitor, or `NULL` if an error - * occurred. + * @return The UTF-8 encoded name of the monitor, or `NULL` if an + * [error](@ref error_handling) occurred. * - * @note The returned string is allocated and freed by GLFW. You should not - * free it yourself. + * @par Pointer Lifetime + * The returned string is allocated and freed by GLFW. You should not free it + * yourself. It is valid until the specified monitor is disconnected or the + * library is terminated. + * + * @par Thread Safety + * This function may only be called from the main thread. + * + * @sa @ref monitor_properties + * + * @since Added in GLFW 3.0. * * @ingroup monitor */ @@ -1066,12 +1382,19 @@ GLFWAPI const char* glfwGetMonitorName(GLFWmonitor* monitor); * * @param[in] cbfun The new callback, or `NULL` to remove the currently set * callback. - * @return The previously set callback, or `NULL` if no callback was set or an - * error occurred. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). * - * @bug **X11:** This callback is not yet called on monitor configuration + * @bug __X11:__ This callback is not yet called on monitor configuration * changes. * + * @par Thread Safety + * This function may only be called from the main thread. + * + * @sa @ref monitor_event + * + * @since Added in GLFW 3.0. + * * @ingroup monitor */ GLFWAPI GLFWmonitorfun glfwSetMonitorCallback(GLFWmonitorfun cbfun); @@ -1086,16 +1409,25 @@ GLFWAPI GLFWmonitorfun glfwSetMonitorCallback(GLFWmonitorfun cbfun); * @param[in] monitor The monitor to query. * @param[out] count Where to store the number of video modes in the returned * array. This is set to zero if an error occurred. - * @return An array of video modes, or `NULL` if an error occurred. + * @return An array of video modes, or `NULL` if an + * [error](@ref error_handling) occurred. * - * @note The returned array is allocated and freed by GLFW. You should not - * free it yourself. + * @par Pointer Lifetime + * The returned array is allocated and freed by GLFW. You should not free it + * yourself. It is valid until the specified monitor is disconnected, this + * function is called again for that monitor or the library is terminated. * - * @note The returned array is valid only until this function is called again - * for the specified monitor. + * @par Thread Safety + * This function may only be called from the main thread. * + * @sa @ref monitor_modes * @sa glfwGetVideoMode * + * @since Added in GLFW 1.0. + * + * @par + * __GLFW 3:__ Changed to return an array of modes for a specific monitor. + * * @ingroup monitor */ GLFWAPI const GLFWvidmode* glfwGetVideoModes(GLFWmonitor* monitor, int* count); @@ -1103,17 +1435,26 @@ GLFWAPI const GLFWvidmode* glfwGetVideoModes(GLFWmonitor* monitor, int* count); /*! @brief Returns the current mode of the specified monitor. * * This function returns the current video mode of the specified monitor. If - * you are using a full screen window, the return value will therefore depend - * on whether it is focused. + * you have created a full screen window for that monitor, the return value + * will depend on whether that window is iconified. * * @param[in] monitor The monitor to query. - * @return The current mode of the monitor, or `NULL` if an error occurred. + * @return The current mode of the monitor, or `NULL` if an + * [error](@ref error_handling) occurred. * - * @note The returned struct is allocated and freed by GLFW. You should not - * free it yourself. + * @par Pointer Lifetime + * The returned array is allocated and freed by GLFW. You should not free it + * yourself. It is valid until the specified monitor is disconnected or the + * library is terminated. * + * @par Thread Safety + * This function may only be called from the main thread. + * + * @sa @ref monitor_modes * @sa glfwGetVideoModes * + * @since Added in GLFW 3.0. Replaces `glfwGetDesktopMode`. + * * @ingroup monitor */ GLFWAPI const GLFWvidmode* glfwGetVideoMode(GLFWmonitor* monitor); @@ -1126,19 +1467,37 @@ GLFWAPI const GLFWvidmode* glfwGetVideoMode(GLFWmonitor* monitor); * @param[in] monitor The monitor whose gamma ramp to set. * @param[in] gamma The desired exponent. * + * @par Thread Safety + * This function may only be called from the main thread. + * + * @sa @ref monitor_gamma + * + * @since Added in GLFW 3.0. + * * @ingroup monitor */ GLFWAPI void glfwSetGamma(GLFWmonitor* monitor, float gamma); -/*! @brief Retrieves the current gamma ramp for the specified monitor. +/*! @brief Returns the current gamma ramp for the specified monitor. * - * This function retrieves the current gamma ramp of the specified monitor. + * This function returns the current gamma ramp of the specified monitor. * * @param[in] monitor The monitor to query. - * @return The current gamma ramp, or `NULL` if an error occurred. + * @return The current gamma ramp, or `NULL` if an + * [error](@ref error_handling) occurred. * - * @note The value arrays of the returned ramp are allocated and freed by GLFW. - * You should not free them yourself. + * @par Pointer Lifetime + * The returned structure and its arrays are allocated and freed by GLFW. You + * should not free them yourself. They are valid until the specified monitor + * is disconnected, this function is called again for that monitor or the + * library is terminated. + * + * @par Thread Safety + * This function may only be called from the main thread. + * + * @sa @ref monitor_gamma + * + * @since Added in GLFW 3.0. * * @ingroup monitor */ @@ -1146,13 +1505,25 @@ GLFWAPI const GLFWgammaramp* glfwGetGammaRamp(GLFWmonitor* monitor); /*! @brief Sets the current gamma ramp for the specified monitor. * - * This function sets the current gamma ramp for the specified monitor. + * This function sets the current gamma ramp for the specified monitor. The + * original gamma ramp for that monitor is saved by GLFW the first time this + * function is called and is restored by @ref glfwTerminate. * * @param[in] monitor The monitor whose gamma ramp to set. * @param[in] ramp The gamma ramp to use. * * @note Gamma ramp sizes other than 256 are not supported by all hardware. * + * @par Pointer Lifetime + * The specified gamma ramp is copied before this function returns. + * + * @par Thread Safety + * This function may only be called from the main thread. + * + * @sa @ref monitor_gamma + * + * @since Added in GLFW 3.0. + * * @ingroup monitor */ GLFWAPI void glfwSetGammaRamp(GLFWmonitor* monitor, const GLFWgammaramp* ramp); @@ -1162,10 +1533,14 @@ GLFWAPI void glfwSetGammaRamp(GLFWmonitor* monitor, const GLFWgammaramp* ramp); * This function resets all window hints to their * [default values](@ref window_hints_values). * - * @note This function may only be called from the main thread. + * @par Thread Safety + * This function may only be called from the main thread. * + * @sa @ref window_hints * @sa glfwWindowHint * + * @since Added in GLFW 3.0. + * * @ingroup window */ GLFWAPI void glfwDefaultWindowHints(void); @@ -1175,52 +1550,70 @@ GLFWAPI void glfwDefaultWindowHints(void); * This function sets hints for the next call to @ref glfwCreateWindow. The * hints, once set, retain their values until changed by a call to @ref * glfwWindowHint or @ref glfwDefaultWindowHints, or until the library is - * terminated with @ref glfwTerminate. + * terminated. * * @param[in] target The [window hint](@ref window_hints) to set. * @param[in] hint The new value of the window hint. * - * @par New in GLFW 3 - * Hints are no longer reset to their default values on window creation. To - * set default hint values, use @ref glfwDefaultWindowHints. - * - * @note This function may only be called from the main thread. + * @par Thread Safety + * This function may only be called from the main thread. * + * @sa @ref window_hints * @sa glfwDefaultWindowHints * + * @since Added in GLFW 3.0. Replaces `glfwOpenWindowHint`. + * * @ingroup window */ GLFWAPI void glfwWindowHint(int target, int hint); /*! @brief Creates a window and its associated context. * - * This function creates a window and its associated context. Most of the - * options controlling how the window and its context should be created are - * specified through @ref glfwWindowHint. + * This function creates a window and its associated OpenGL or OpenGL ES + * context. Most of the options controlling how the window and its context + * should be created are specified with [window hints](@ref window_hints). * * Successful creation does not change which context is current. Before you - * can use the newly created context, you need to make it current using @ref - * glfwMakeContextCurrent. + * can use the newly created context, you need to + * [make it current](@ref context_current). For information about the `share` + * parameter, see @ref context_sharing. * - * Note that the created window and context may differ from what you requested, - * as not all parameters and hints are + * The created window, framebuffer and context may differ from what you + * requested, as not all parameters and hints are * [hard constraints](@ref window_hints_hard). This includes the size of the - * window, especially for full screen windows. To retrieve the actual - * attributes of the created window and context, use queries like @ref + * window, especially for full screen windows. To query the actual attributes + * of the created window, framebuffer and context, use queries like @ref * glfwGetWindowAttrib and @ref glfwGetWindowSize. * - * To create a full screen window, you need to specify the monitor to use. If - * no monitor is specified, windowed mode will be used. Unless you have a way - * for the user to choose a specific monitor, it is recommended that you pick - * the primary monitor. For more information on how to retrieve monitors, see - * @ref monitor_monitors. + * To create a full screen window, you need to specify the monitor the window + * will cover. If no monitor is specified, windowed mode will be used. Unless + * you have a way for the user to choose a specific monitor, it is recommended + * that you pick the primary monitor. For more information on how to query + * connected monitors, see @ref monitor_monitors. * - * To create the window at a specific position, make it initially invisible - * using the `GLFW_VISIBLE` window hint, set its position and then show it. + * For full screen windows, the specified size becomes the resolution of the + * window's _desired video mode_. As long as a full screen window has input + * focus, the supported video mode most closely matching the desired video mode + * is set for the specified monitor. For more information about full screen + * windows, including the creation of so called _windowed full screen_ or + * _borderless full screen_ windows, see @ref window_windowed_full_screen. * - * If a full screen window is active, the screensaver is prohibited from + * By default, newly created windows use the placement recommended by the + * window system. To create the window at a specific position, make it + * initially invisible using the [GLFW_VISIBLE](@ref window_hints_wnd) window + * hint, set its [position](@ref window_pos) and then [show](@ref window_hide) + * it. + * + * If a full screen window has input focus, the screensaver is prohibited from * starting. * + * Window systems put limits on window sizes. Very large or very small window + * dimensions may be overridden by the window system on creation. Check the + * actual [size](@ref window_size) after creation. + * + * The [swap interval](@ref buffer_swap) is not set during window creation and + * the initial value may vary depending on driver settings and defaults. + * * @param[in] width The desired width, in screen coordinates, of the window. * This must be greater than zero. * @param[in] height The desired height, in screen coordinates, of the window. @@ -1230,23 +1623,47 @@ GLFWAPI void glfwWindowHint(int target, int hint); * windowed mode. * @param[in] share The window whose context to share resources with, or `NULL` * to not share resources. - * @return The handle of the created window, or `NULL` if an error occurred. + * @return The handle of the created window, or `NULL` if an + * [error](@ref error_handling) occurred. * - * @remarks **Windows:** If the executable has an icon resource named + * @remarks __Windows:__ Window creation will fail if the Microsoft GDI + * software OpenGL implementation is the only one available. + * + * @remarks __Windows:__ If the executable has an icon resource named * `GLFW_ICON,` it will be set as the icon for the window. If no such icon is * present, the `IDI_WINLOGO` icon will be used instead. * - * @remarks **Mac OS X:** The GLFW window has no icon, as it is not a document + * @remarks __Windows:__ The context to share resources with may not be current + * on any other thread. + * + * @remarks __OS X:__ The GLFW window has no icon, as it is not a document * window, but the dock icon will be the same as the application bundle's icon. - * Also, the first time a window is opened the menu bar is populated with - * common commands like Hide, Quit and About. The (minimal) about dialog uses - * information from the application's bundle. For more information on bundles, - * see the Bundle Programming Guide provided by Apple. + * For more information on bundles, see the + * [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/) + * in the Mac Developer Library. * - * @note This function may only be called from the main thread. + * @remarks __OS X:__ The first time a window is created the menu bar is + * populated with common commands like Hide, Quit and About. The About entry + * opens a minimal about dialog with information from the application's bundle. + * The menu bar can be disabled with a + * [compile-time option](@ref compile_options_osx). * + * @remarks __X11:__ There is no mechanism for setting the window icon yet. + * + * @remarks __X11:__ Some window managers will not respect the placement of + * initially hidden windows. + * + * @par Reentrancy + * This function may not be called from a callback. + * + * @par Thread Safety + * This function may only be called from the main thread. + * + * @sa @ref window_creation * @sa glfwDestroyWindow * + * @since Added in GLFW 3.0. Replaces `glfwOpenWindow`. + * * @ingroup window */ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height, const char* title, GLFWmonitor* monitor, GLFWwindow* share); @@ -1256,19 +1673,25 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height, const char* title, G * This function destroys the specified window and its context. On calling * this function, no further callbacks will be called for that window. * - * @param[in] window The window to destroy. - * - * @note This function may only be called from the main thread. - * - * @note This function may not be called from a callback. - * - * @note If the window's context is current on the main thread, it is + * If the context of the specified window is current on the main thread, it is * detached before being destroyed. * - * @warning The window's context must not be current on any other thread. + * @param[in] window The window to destroy. * + * @note The context of the specified window must not be current on any other + * thread when this function is called. + * + * @par Reentrancy + * This function may not be called from a callback. + * + * @par Thread Safety + * This function may only be called from the main thread. + * + * @sa @ref window_creation * @sa glfwCreateWindow * + * @since Added in GLFW 3.0. Replaces `glfwCloseWindow`. + * * @ingroup window */ GLFWAPI void glfwDestroyWindow(GLFWwindow* window); @@ -1280,7 +1703,12 @@ GLFWAPI void glfwDestroyWindow(GLFWwindow* window); * @param[in] window The window to query. * @return The value of the close flag. * - * @remarks This function may be called from secondary threads. + * @par Thread Safety + * This function may be called from any thread. Access is not synchronized. + * + * @sa @ref window_close + * + * @since Added in GLFW 3.0. * * @ingroup window */ @@ -1295,7 +1723,12 @@ GLFWAPI int glfwWindowShouldClose(GLFWwindow* window); * @param[in] window The window whose flag to change. * @param[in] value The new value. * - * @remarks This function may be called from secondary threads. + * @par Thread Safety + * This function may be called from any thread. Access is not synchronized. + * + * @sa @ref window_close + * + * @since Added in GLFW 3.0. * * @ingroup window */ @@ -1309,7 +1742,15 @@ GLFWAPI void glfwSetWindowShouldClose(GLFWwindow* window, int value); * @param[in] window The window whose title to change. * @param[in] title The UTF-8 encoded window title. * - * @note This function may only be called from the main thread. + * @par Thread Safety + * This function may only be called from the main thread. + * + * @sa @ref window_title + * + * @since Added in GLFW 1.0. + * + * @par + * __GLFW 3:__ Added window handle parameter. * * @ingroup window */ @@ -1320,14 +1761,23 @@ GLFWAPI void glfwSetWindowTitle(GLFWwindow* window, const char* title); * This function retrieves the position, in screen coordinates, of the * upper-left corner of the client area of the specified window. * + * Any or all of the position arguments may be `NULL`. If an error occurs, all + * non-`NULL` position arguments will be set to zero. + * * @param[in] window The window to query. * @param[out] xpos Where to store the x-coordinate of the upper-left corner of * the client area, or `NULL`. * @param[out] ypos Where to store the y-coordinate of the upper-left corner of * the client area, or `NULL`. * + * @par Thread Safety + * This function may only be called from the main thread. + * + * @sa @ref window_pos * @sa glfwSetWindowPos * + * @since Added in GLFW 3.0. + * * @ingroup window */ GLFWAPI void glfwGetWindowPos(GLFWwindow* window, int* xpos, int* ypos); @@ -1335,31 +1785,30 @@ GLFWAPI void glfwGetWindowPos(GLFWwindow* window, int* xpos, int* ypos); /*! @brief Sets the position of the client area of the specified window. * * This function sets the position, in screen coordinates, of the upper-left - * corner of the client area of the window. + * corner of the client area of the specified windowed mode window. If the + * window is a full screen window, this function does nothing. * - * If the specified window is a full screen window, this function does nothing. + * __Do not use this function__ to move an already visible window unless you + * have very good reasons for doing so, as it will confuse and annoy the user. * - * If you wish to set an initial window position you should create a hidden - * window (using @ref glfwWindowHint and `GLFW_VISIBLE`), set its position and - * then show it. + * The window manager may put limits on what positions are allowed. GLFW + * cannot and should not override these limits. * * @param[in] window The window to query. * @param[in] xpos The x-coordinate of the upper-left corner of the client area. * @param[in] ypos The y-coordinate of the upper-left corner of the client area. * - * @note It is very rarely a good idea to move an already visible window, as it - * will confuse and annoy the user. - * - * @note This function may only be called from the main thread. - * - * @note The window manager may put limits on what positions are allowed. - * - * @bug **X11:** Some window managers ignore the set position of hidden (i.e. - * unmapped) windows, instead placing them where it thinks is appropriate once - * they are shown. + * @par Thread Safety + * This function may only be called from the main thread. * + * @sa @ref window_pos * @sa glfwGetWindowPos * + * @since Added in GLFW 1.0. + * + * @par + * __GLFW 3:__ Added window handle parameter. + * * @ingroup window */ GLFWAPI void glfwSetWindowPos(GLFWwindow* window, int xpos, int ypos); @@ -1367,7 +1816,11 @@ GLFWAPI void glfwSetWindowPos(GLFWwindow* window, int xpos, int ypos); /*! @brief Retrieves the size of the client area of the specified window. * * This function retrieves the size, in screen coordinates, of the client area - * of the specified window. + * of the specified window. If you wish to retrieve the size of the + * framebuffer of the window in pixels, see @ref glfwGetFramebufferSize. + * + * Any or all of the size arguments may be `NULL`. If an error occurs, all + * non-`NULL` size arguments will be set to zero. * * @param[in] window The window whose size to retrieve. * @param[out] width Where to store the width, in screen coordinates, of the @@ -1375,8 +1828,17 @@ GLFWAPI void glfwSetWindowPos(GLFWwindow* window, int xpos, int ypos); * @param[out] height Where to store the height, in screen coordinates, of the * client area, or `NULL`. * + * @par Thread Safety + * This function may only be called from the main thread. + * + * @sa @ref window_size * @sa glfwSetWindowSize * + * @since Added in GLFW 1.0. + * + * @par + * __GLFW 3:__ Added window handle parameter. + * * @ingroup window */ GLFWAPI void glfwGetWindowSize(GLFWwindow* window, int* width, int* height); @@ -1391,16 +1853,24 @@ GLFWAPI void glfwGetWindowSize(GLFWwindow* window, int* width, int* height); * the context is unaffected, the bit depths of the framebuffer remain * unchanged. * + * The window manager may put limits on what sizes are allowed. GLFW cannot + * and should not override these limits. + * * @param[in] window The window to resize. * @param[in] width The desired width of the specified window. * @param[in] height The desired height of the specified window. * - * @note This function may only be called from the main thread. - * - * @note The window manager may put limits on what window sizes are allowed. + * @par Thread Safety + * This function may only be called from the main thread. * + * @sa @ref window_size * @sa glfwGetWindowSize * + * @since Added in GLFW 1.0. + * + * @par + * __GLFW 3:__ Added window handle parameter. + * * @ingroup window */ GLFWAPI void glfwSetWindowSize(GLFWwindow* window, int width, int height); @@ -1408,7 +1878,11 @@ GLFWAPI void glfwSetWindowSize(GLFWwindow* window, int width, int height); /*! @brief Retrieves the size of the framebuffer of the specified window. * * This function retrieves the size, in pixels, of the framebuffer of the - * specified window. + * specified window. If you wish to retrieve the size of the window in screen + * coordinates, see @ref glfwGetWindowSize. + * + * Any or all of the size arguments may be `NULL`. If an error occurs, all + * non-`NULL` size arguments will be set to zero. * * @param[in] window The window whose framebuffer to query. * @param[out] width Where to store the width, in pixels, of the framebuffer, @@ -1416,74 +1890,140 @@ GLFWAPI void glfwSetWindowSize(GLFWwindow* window, int width, int height); * @param[out] height Where to store the height, in pixels, of the framebuffer, * or `NULL`. * + * @par Thread Safety + * This function may only be called from the main thread. + * + * @sa @ref window_fbsize * @sa glfwSetFramebufferSizeCallback * + * @since Added in GLFW 3.0. + * * @ingroup window */ GLFWAPI void glfwGetFramebufferSize(GLFWwindow* window, int* width, int* height); +/*! @brief Retrieves the size of the frame of the window. + * + * This function retrieves the size, in screen coordinates, of each edge of the + * frame of the specified window. This size includes the title bar, if the + * window has one. The size of the frame may vary depending on the + * [window-related hints](@ref window_hints_wnd) used to create it. + * + * Because this function retrieves the size of each window frame edge and not + * the offset along a particular coordinate axis, the retrieved values will + * always be zero or positive. + * + * Any or all of the size arguments may be `NULL`. If an error occurs, all + * non-`NULL` size arguments will be set to zero. + * + * @param[in] window The window whose frame size to query. + * @param[out] left Where to store the size, in screen coordinates, of the left + * edge of the window frame, or `NULL`. + * @param[out] top Where to store the size, in screen coordinates, of the top + * edge of the window frame, or `NULL`. + * @param[out] right Where to store the size, in screen coordinates, of the + * right edge of the window frame, or `NULL`. + * @param[out] bottom Where to store the size, in screen coordinates, of the + * bottom edge of the window frame, or `NULL`. + * + * @par Thread Safety + * This function may only be called from the main thread. + * + * @sa @ref window_size + * + * @since Added in GLFW 3.1. + * + * @ingroup window + */ +GLFWAPI void glfwGetWindowFrameSize(GLFWwindow* window, int* left, int* top, int* right, int* bottom); + /*! @brief Iconifies the specified window. * - * This function iconifies/minimizes the specified window, if it was previously - * restored. If it is a full screen window, the original monitor resolution is - * restored until the window is restored. If the window is already iconified, - * this function does nothing. + * This function iconifies (minimizes) the specified window if it was + * previously restored. If the window is already iconified, this function does + * nothing. + * + * If the specified window is a full screen window, the original monitor + * resolution is restored until the window is restored. * * @param[in] window The window to iconify. * - * @note This function may only be called from the main thread. + * @par Thread Safety + * This function may only be called from the main thread. * + * @sa @ref window_iconify * @sa glfwRestoreWindow * + * @since Added in GLFW 2.1. + * + * @par + * __GLFW 3:__ Added window handle parameter. + * * @ingroup window */ GLFWAPI void glfwIconifyWindow(GLFWwindow* window); /*! @brief Restores the specified window. * - * This function restores the specified window, if it was previously - * iconified/minimized. If it is a full screen window, the resolution chosen - * for the window is restored on the selected monitor. If the window is - * already restored, this function does nothing. + * This function restores the specified window if it was previously iconified + * (minimized). If the window is already restored, this function does nothing. + * + * If the specified window is a full screen window, the resolution chosen for + * the window is restored on the selected monitor. * * @param[in] window The window to restore. * - * @note This function may only be called from the main thread. + * @par Thread Safety + * This function may only be called from the main thread. * + * @sa @ref window_iconify * @sa glfwIconifyWindow * + * @since Added in GLFW 2.1. + * + * @par + * __GLFW 3:__ Added window handle parameter. + * * @ingroup window */ GLFWAPI void glfwRestoreWindow(GLFWwindow* window); /*! @brief Makes the specified window visible. * - * This function makes the specified window visible, if it was previously + * This function makes the specified window visible if it was previously * hidden. If the window is already visible or is in full screen mode, this * function does nothing. * * @param[in] window The window to make visible. * - * @note This function may only be called from the main thread. + * @par Thread Safety + * This function may only be called from the main thread. * + * @sa @ref window_hide * @sa glfwHideWindow * + * @since Added in GLFW 3.0. + * * @ingroup window */ GLFWAPI void glfwShowWindow(GLFWwindow* window); /*! @brief Hides the specified window. * - * This function hides the specified window, if it was previously visible. If + * This function hides the specified window if it was previously visible. If * the window is already hidden or is in full screen mode, this function does * nothing. * * @param[in] window The window to hide. * - * @note This function may only be called from the main thread. + * @par Thread Safety + * This function may only be called from the main thread. * + * @sa @ref window_hide * @sa glfwShowWindow * + * @since Added in GLFW 3.0. + * * @ingroup window */ GLFWAPI void glfwHideWindow(GLFWwindow* window); @@ -1494,7 +2034,15 @@ GLFWAPI void glfwHideWindow(GLFWwindow* window); * in full screen on. * * @param[in] window The window to query. - * @return The monitor, or `NULL` if the window is in windowed mode. + * @return The monitor, or `NULL` if the window is in windowed mode or an error + * occurred. + * + * @par Thread Safety + * This function may only be called from the main thread. + * + * @sa @ref window_monitor + * + * @since Added in GLFW 3.0. * * @ingroup window */ @@ -1502,13 +2050,22 @@ GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* window); /*! @brief Returns an attribute of the specified window. * - * This function returns an attribute of the specified window. There are many - * attributes, some related to the window and others to its context. + * This function returns the value of an attribute of the specified window or + * its OpenGL or OpenGL ES context. * * @param[in] window The window to query. * @param[in] attrib The [window attribute](@ref window_attribs) whose value to * return. - * @return The value of the attribute, or zero if an error occurred. + * @return The value of the attribute, or zero if an + * [error](@ref error_handling) occurred. + * + * @par Thread Safety + * This function may only be called from the main thread. + * + * @sa @ref window_attribs + * + * @since Added in GLFW 3.0. Replaces `glfwGetWindowParam` and + * `glfwGetGLVersion`. * * @ingroup window */ @@ -1523,8 +2080,14 @@ GLFWAPI int glfwGetWindowAttrib(GLFWwindow* window, int attrib); * @param[in] window The window whose pointer to set. * @param[in] pointer The new value. * + * @par Thread Safety + * This function may be called from any thread. Access is not synchronized. + * + * @sa @ref window_userptr * @sa glfwGetWindowUserPointer * + * @since Added in GLFW 3.0. + * * @ingroup window */ GLFWAPI void glfwSetWindowUserPointer(GLFWwindow* window, void* pointer); @@ -1536,8 +2099,14 @@ GLFWAPI void glfwSetWindowUserPointer(GLFWwindow* window, void* pointer); * * @param[in] window The window whose pointer to return. * + * @par Thread Safety + * This function may be called from any thread. Access is not synchronized. + * + * @sa @ref window_userptr * @sa glfwSetWindowUserPointer * + * @since Added in GLFW 3.0. + * * @ingroup window */ GLFWAPI void* glfwGetWindowUserPointer(GLFWwindow* window); @@ -1551,8 +2120,15 @@ GLFWAPI void* glfwGetWindowUserPointer(GLFWwindow* window); * @param[in] window The window whose callback to set. * @param[in] cbfun The new callback, or `NULL` to remove the currently set * callback. - * @return The previously set callback, or `NULL` if no callback was set or an - * error occurred. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @par Thread Safety + * This function may only be called from the main thread. + * + * @sa @ref window_pos + * + * @since Added in GLFW 3.0. * * @ingroup window */ @@ -1567,8 +2143,18 @@ GLFWAPI GLFWwindowposfun glfwSetWindowPosCallback(GLFWwindow* window, GLFWwindow * @param[in] window The window whose callback to set. * @param[in] cbfun The new callback, or `NULL` to remove the currently set * callback. - * @return The previously set callback, or `NULL` if no callback was set or an - * error occurred. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @par Thread Safety + * This function may only be called from the main thread. + * + * @sa @ref window_size + * + * @since Added in GLFW 1.0. + * + * @par + * __GLFW 3:__ Added window handle parameter. Updated callback signature. * * @ingroup window */ @@ -1588,12 +2174,22 @@ GLFWAPI GLFWwindowsizefun glfwSetWindowSizeCallback(GLFWwindow* window, GLFWwind * @param[in] window The window whose callback to set. * @param[in] cbfun The new callback, or `NULL` to remove the currently set * callback. - * @return The previously set callback, or `NULL` if no callback was set or an - * error occurred. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). * - * @remarks **Mac OS X:** Selecting Quit from the application menu will + * @remarks __OS X:__ Selecting Quit from the application menu will * trigger the close callback for all windows. * + * @par Thread Safety + * This function may only be called from the main thread. + * + * @sa @ref window_close + * + * @since Added in GLFW 2.5. + * + * @par + * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * * @ingroup window */ GLFWAPI GLFWwindowclosefun glfwSetWindowCloseCallback(GLFWwindow* window, GLFWwindowclosefun cbfun); @@ -1611,12 +2207,18 @@ GLFWAPI GLFWwindowclosefun glfwSetWindowCloseCallback(GLFWwindow* window, GLFWwi * @param[in] window The window whose callback to set. * @param[in] cbfun The new callback, or `NULL` to remove the currently set * callback. - * @return The previously set callback, or `NULL` if no callback was set or an - * error occurred. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). * - * @note On compositing window systems such as Aero, Compiz or Aqua, where the - * window contents are saved off-screen, this callback may be called only very - * infrequently or never at all. + * @par Thread Safety + * This function may only be called from the main thread. + * + * @sa @ref window_refresh + * + * @since Added in GLFW 2.5. + * + * @par + * __GLFW 3:__ Added window handle parameter. Updated callback signature. * * @ingroup window */ @@ -1625,18 +2227,25 @@ GLFWAPI GLFWwindowrefreshfun glfwSetWindowRefreshCallback(GLFWwindow* window, GL /*! @brief Sets the focus callback for the specified window. * * This function sets the focus callback of the specified window, which is - * called when the window gains or loses focus. + * called when the window gains or loses input focus. * - * After the focus callback is called for a window that lost focus, synthetic - * key and mouse button release events will be generated for all such that had - * been pressed. For more information, see @ref glfwSetKeyCallback and @ref - * glfwSetMouseButtonCallback. + * After the focus callback is called for a window that lost input focus, + * synthetic key and mouse button release events will be generated for all such + * that had been pressed. For more information, see @ref glfwSetKeyCallback + * and @ref glfwSetMouseButtonCallback. * * @param[in] window The window whose callback to set. * @param[in] cbfun The new callback, or `NULL` to remove the currently set * callback. - * @return The previously set callback, or `NULL` if no callback was set or an - * error occurred. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @par Thread Safety + * This function may only be called from the main thread. + * + * @sa @ref window_focus + * + * @since Added in GLFW 3.0. * * @ingroup window */ @@ -1650,8 +2259,15 @@ GLFWAPI GLFWwindowfocusfun glfwSetWindowFocusCallback(GLFWwindow* window, GLFWwi * @param[in] window The window whose callback to set. * @param[in] cbfun The new callback, or `NULL` to remove the currently set * callback. - * @return The previously set callback, or `NULL` if no callback was set or an - * error occurred. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @par Thread Safety + * This function may only be called from the main thread. + * + * @sa @ref window_iconify + * + * @since Added in GLFW 3.0. * * @ingroup window */ @@ -1665,8 +2281,15 @@ GLFWAPI GLFWwindowiconifyfun glfwSetWindowIconifyCallback(GLFWwindow* window, GL * @param[in] window The window whose callback to set. * @param[in] cbfun The new callback, or `NULL` to remove the currently set * callback. - * @return The previously set callback, or `NULL` if no callback was set or an - * error occurred. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @par Thread Safety + * This function may only be called from the main thread. + * + * @sa @ref window_fbsize + * + * @since Added in GLFW 3.0. * * @ingroup window */ @@ -1674,99 +2297,164 @@ GLFWAPI GLFWframebuffersizefun glfwSetFramebufferSizeCallback(GLFWwindow* window /*! @brief Processes all pending events. * - * This function processes only those events that have already been received - * and then returns immediately. Processing events will cause the window and - * input callbacks associated with those events to be called. + * This function processes only those events that are already in the event + * queue and then returns immediately. Processing events will cause the window + * and input callbacks associated with those events to be called. * - * This function is not required for joystick input to work. + * On some platforms, a window move, resize or menu operation will cause event + * processing to block. This is due to how event processing is designed on + * those platforms. You can use the + * [window refresh callback](@ref window_refresh) to redraw the contents of + * your window when necessary during such operations. * - * @par New in GLFW 3 - * This function is no longer called by @ref glfwSwapBuffers. You need to call - * it or @ref glfwWaitEvents yourself. + * On some platforms, certain events are sent directly to the application + * without going through the event queue, causing callbacks to be called + * outside of a call to one of the event processing functions. * - * @note This function may only be called from the main thread. + * Event processing is not required for joystick input to work. * - * @note This function may not be called from a callback. + * @par Reentrancy + * This function may not be called from a callback. * - * @note On some platforms, certain callbacks may be called outside of a call - * to one of the event processing functions. + * @par Thread Safety + * This function may only be called from the main thread. * + * @sa @ref events * @sa glfwWaitEvents * + * @since Added in GLFW 1.0. + * * @ingroup window */ GLFWAPI void glfwPollEvents(void); -/*! @brief Waits until events are pending and processes them. +/*! @brief Waits until events are queued and processes them. * - * This function puts the calling thread to sleep until at least one event has - * been received. Once one or more events have been received, it behaves as if - * @ref glfwPollEvents was called, i.e. the events are processed and the - * function then returns immediately. Processing events will cause the window - * and input callbacks associated with those events to be called. + * This function puts the calling thread to sleep until at least one event is + * available in the event queue. Once one or more events are available, + * it behaves exactly like @ref glfwPollEvents, i.e. the events in the queue + * are processed and the function then returns immediately. Processing events + * will cause the window and input callbacks associated with those events to be + * called. * * Since not all events are associated with callbacks, this function may return * without a callback having been called even if you are monitoring all * callbacks. * - * This function is not required for joystick input to work. + * On some platforms, a window move, resize or menu operation will cause event + * processing to block. This is due to how event processing is designed on + * those platforms. You can use the + * [window refresh callback](@ref window_refresh) to redraw the contents of + * your window when necessary during such operations. * - * @note This function may only be called from the main thread. + * On some platforms, certain callbacks may be called outside of a call to one + * of the event processing functions. * - * @note This function may not be called from a callback. + * If no windows exist, this function returns immediately. For synchronization + * of threads in applications that do not create windows, use your threading + * library of choice. * - * @note On some platforms, certain callbacks may be called outside of a call - * to one of the event processing functions. + * Event processing is not required for joystick input to work. * + * @par Reentrancy + * This function may not be called from a callback. + * + * @par Thread Safety + * This function may only be called from the main thread. + * + * @sa @ref events * @sa glfwPollEvents * + * @since Added in GLFW 2.5. + * * @ingroup window */ GLFWAPI void glfwWaitEvents(void); +/*! @brief Posts an empty event to the event queue. + * + * This function posts an empty event from the current thread to the event + * queue, causing @ref glfwWaitEvents to return. + * + * If no windows exist, this function returns immediately. For synchronization + * of threads in applications that do not create windows, use your threading + * library of choice. + * + * @par Thread Safety + * This function may be called from any thread. + * + * @sa @ref events + * @sa glfwWaitEvents + * + * @since Added in GLFW 3.1. + * + * @ingroup window + */ +GLFWAPI void glfwPostEmptyEvent(void); + /*! @brief Returns the value of an input option for the specified window. + * + * This function returns the value of an input option for the specified window. + * The mode must be one of `GLFW_CURSOR`, `GLFW_STICKY_KEYS` or + * `GLFW_STICKY_MOUSE_BUTTONS`. * * @param[in] window The window to query. * @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS` or * `GLFW_STICKY_MOUSE_BUTTONS`. * + * @par Thread Safety + * This function may only be called from the main thread. + * * @sa glfwSetInputMode * + * @since Added in GLFW 3.0. + * * @ingroup input */ GLFWAPI int glfwGetInputMode(GLFWwindow* window, int mode); /*! @brief Sets an input option for the specified window. + * + * This function sets an input mode option for the specified window. The mode + * must be one of `GLFW_CURSOR`, `GLFW_STICKY_KEYS` or + * `GLFW_STICKY_MOUSE_BUTTONS`. + * + * If the mode is `GLFW_CURSOR`, the value must be one of the following cursor + * modes: + * - `GLFW_CURSOR_NORMAL` makes the cursor visible and behaving normally. + * - `GLFW_CURSOR_HIDDEN` makes the cursor invisible when it is over the client + * area of the window but does not restrict the cursor from leaving. + * - `GLFW_CURSOR_DISABLED` hides and grabs the cursor, providing virtual + * and unlimited cursor movement. This is useful for implementing for + * example 3D camera controls. + * + * If the mode is `GLFW_STICKY_KEYS`, the value must be either `GL_TRUE` to + * enable sticky keys, or `GL_FALSE` to disable it. If sticky keys are + * enabled, a key press will ensure that @ref glfwGetKey returns `GLFW_PRESS` + * the next time it is called even if the key had been released before the + * call. This is useful when you are only interested in whether keys have been + * pressed but not when or in which order. + * + * If the mode is `GLFW_STICKY_MOUSE_BUTTONS`, the value must be either + * `GL_TRUE` to enable sticky mouse buttons, or `GL_FALSE` to disable it. If + * sticky mouse buttons are enabled, a mouse button press will ensure that @ref + * glfwGetMouseButton returns `GLFW_PRESS` the next time it is called even if + * the mouse button had been released before the call. This is useful when you + * are only interested in whether mouse buttons have been pressed but not when + * or in which order. + * * @param[in] window The window whose input mode to set. * @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS` or * `GLFW_STICKY_MOUSE_BUTTONS`. * @param[in] value The new value of the specified input mode. * - * If `mode` is `GLFW_CURSOR`, the value must be one of the supported input - * modes: - * - `GLFW_CURSOR_NORMAL` makes the cursor visible and behaving normally. - * - `GLFW_CURSOR_HIDDEN` makes the cursor invisible when it is over the client - * area of the window. - * - `GLFW_CURSOR_DISABLED` disables the cursor and removes any limitations on - * cursor movement. - * - * If `mode` is `GLFW_STICKY_KEYS`, the value must be either `GL_TRUE` to - * enable sticky keys, or `GL_FALSE` to disable it. If sticky keys are - * enabled, a key press will ensure that @ref glfwGetKey returns @ref - * GLFW_PRESS the next time it is called even if the key had been released - * before the call. This is useful when you are only interested in whether - * keys have been pressed but not when or in which order. - * - * If `mode` is `GLFW_STICKY_MOUSE_BUTTONS`, the value must be either `GL_TRUE` - * to enable sticky mouse buttons, or `GL_FALSE` to disable it. If sticky - * mouse buttons are enabled, a mouse button press will ensure that @ref - * glfwGetMouseButton returns @ref GLFW_PRESS the next time it is called even - * if the mouse button had been released before the call. This is useful when - * you are only interested in whether mouse buttons have been pressed but not - * when or in which order. + * @par Thread Safety + * This function may only be called from the main thread. * * @sa glfwGetInputMode * + * @since Added in GLFW 3.0. Replaces `glfwEnable` and `glfwDisable`. + * * @ingroup input */ GLFWAPI void glfwSetInputMode(GLFWwindow* window, int mode, int value); @@ -1776,22 +2464,34 @@ GLFWAPI void glfwSetInputMode(GLFWwindow* window, int mode, int value); * * This function returns the last state reported for the specified key to the * specified window. The returned state is one of `GLFW_PRESS` or - * `GLFW_RELEASE`. The higher-level state `GLFW_REPEAT` is only reported to + * `GLFW_RELEASE`. The higher-level action `GLFW_REPEAT` is only reported to * the key callback. * * If the `GLFW_STICKY_KEYS` input mode is enabled, this function returns - * `GLFW_PRESS` the first time you call this function after a key has been - * pressed, even if the key has already been released. + * `GLFW_PRESS` the first time you call it for a key that was pressed, even if + * that key has already been released. * * The key functions deal with physical keys, with [key tokens](@ref keys) * named after their use on the standard US keyboard layout. If you want to * input text, use the Unicode character callback instead. * + * The [modifier key bit masks](@ref mods) are not key tokens and cannot be + * used with this function. + * * @param[in] window The desired window. - * @param[in] key The desired [keyboard key](@ref keys). + * @param[in] key The desired [keyboard key](@ref keys). `GLFW_KEY_UNKNOWN` is + * not a valid key for this function. * @return One of `GLFW_PRESS` or `GLFW_RELEASE`. * - * @note `GLFW_KEY_UNKNOWN` is not a valid key for this function. + * @par Thread Safety + * This function may only be called from the main thread. + * + * @sa @ref input_key + * + * @since Added in GLFW 1.0. + * + * @par + * __GLFW 3:__ Added window handle parameter. * * @ingroup input */ @@ -1801,25 +2501,37 @@ GLFWAPI int glfwGetKey(GLFWwindow* window, int key); * window. * * This function returns the last state reported for the specified mouse button - * to the specified window. + * to the specified window. The returned state is one of `GLFW_PRESS` or + * `GLFW_RELEASE`. * * If the `GLFW_STICKY_MOUSE_BUTTONS` input mode is enabled, this function - * returns `GLFW_PRESS` the first time you call this function after a mouse - * button has been pressed, even if the mouse button has already been released. + * `GLFW_PRESS` the first time you call it for a mouse button that was pressed, + * even if that mouse button has already been released. * * @param[in] window The desired window. * @param[in] button The desired [mouse button](@ref buttons). * @return One of `GLFW_PRESS` or `GLFW_RELEASE`. * + * @par Thread Safety + * This function may only be called from the main thread. + * + * @sa @ref input_mouse_button + * + * @since Added in GLFW 1.0. + * + * @par + * __GLFW 3:__ Added window handle parameter. + * * @ingroup input */ GLFWAPI int glfwGetMouseButton(GLFWwindow* window, int button); -/*! @brief Retrieves the last reported cursor position, relative to the client - * area of the window. +/*! @brief Retrieves the position of the cursor relative to the client area of + * the window. * - * This function returns the last reported position of the cursor to the - * specified window. + * This function returns the position of the cursor, in screen coordinates, + * relative to the upper-left corner of the client area of the specified + * window. * * If the cursor is disabled (with `GLFW_CURSOR_DISABLED`) then the cursor * position is unbounded and limited only by the minimum and maximum values of @@ -1829,26 +2541,42 @@ GLFWAPI int glfwGetMouseButton(GLFWwindow* window, int button); * `floor` function. Casting directly to an integer type works for positive * coordinates, but fails for negative ones. * + * Any or all of the position arguments may be `NULL`. If an error occurs, all + * non-`NULL` position arguments will be set to zero. + * * @param[in] window The desired window. * @param[out] xpos Where to store the cursor x-coordinate, relative to the * left edge of the client area, or `NULL`. * @param[out] ypos Where to store the cursor y-coordinate, relative to the to * top edge of the client area, or `NULL`. * + * @par Thread Safety + * This function may only be called from the main thread. + * + * @sa @ref cursor_pos * @sa glfwSetCursorPos * + * @since Added in GLFW 3.0. Replaces `glfwGetMousePos`. + * * @ingroup input */ GLFWAPI void glfwGetCursorPos(GLFWwindow* window, double* xpos, double* ypos); -/*! @brief Sets the position of the cursor, relative to the client area of the window. +/*! @brief Sets the position of the cursor, relative to the client area of the + * window. * - * This function sets the position of the cursor. The specified window must be - * focused. If the window does not have focus when this function is called, it - * fails silently. + * This function sets the position, in screen coordinates, of the cursor + * relative to the upper-left corner of the client area of the specified + * window. The window must have input focus. If the window does not have + * input focus when this function is called, it fails silently. * - * If the cursor is disabled (with `GLFW_CURSOR_DISABLED`) then the cursor - * position is unbounded and limited only by the minimum and maximum values of + * __Do not use this function__ to implement things like camera controls. GLFW + * already provides the `GLFW_CURSOR_DISABLED` cursor mode that hides the + * cursor, transparently re-centers it and provides unconstrained cursor + * motion. See @ref glfwSetInputMode for more information. + * + * If the cursor mode is `GLFW_CURSOR_DISABLED` then the cursor position is + * unconstrained and limited only by the minimum and maximum values of * a `double`. * * @param[in] window The desired window. @@ -1857,15 +2585,138 @@ GLFWAPI void glfwGetCursorPos(GLFWwindow* window, double* xpos, double* ypos); * @param[in] ypos The desired y-coordinate, relative to the top edge of the * client area. * + * @remarks __X11:__ Due to the asynchronous nature of a modern X desktop, it + * may take a moment for the window focus event to arrive. This means you will + * not be able to set the cursor position directly after window creation. + * + * @par Thread Safety + * This function may only be called from the main thread. + * + * @sa @ref cursor_pos * @sa glfwGetCursorPos * + * @since Added in GLFW 3.0. Replaces `glfwSetMousePos`. + * * @ingroup input */ GLFWAPI void glfwSetCursorPos(GLFWwindow* window, double xpos, double ypos); +/*! @brief Creates a custom cursor. + * + * Creates a new custom cursor image that can be set for a window with @ref + * glfwSetCursor. The cursor can be destroyed with @ref glfwDestroyCursor. + * Any remaining cursors are destroyed by @ref glfwTerminate. + * + * The pixels are 32-bit little-endian RGBA, i.e. eight bits per channel. They + * are arranged canonically as packed sequential rows, starting from the + * top-left corner. + * + * The cursor hotspot is specified in pixels, relative to the upper-left corner + * of the cursor image. Like all other coordinate systems in GLFW, the X-axis + * points to the right and the Y-axis points down. + * + * @param[in] image The desired cursor image. + * @param[in] xhot The desired x-coordinate, in pixels, of the cursor hotspot. + * @param[in] yhot The desired y-coordinate, in pixels, of the cursor hotspot. + * + * @return The handle of the created cursor, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @par Pointer Lifetime + * The specified image data is copied before this function returns. + * + * @par Reentrancy + * This function may not be called from a callback. + * + * @par Thread Safety + * This function may only be called from the main thread. + * + * @sa @ref cursor_object + * @sa glfwDestroyCursor + * @sa glfwCreateStandardCursor + * + * @since Added in GLFW 3.1. + * + * @ingroup input + */ +GLFWAPI GLFWcursor* glfwCreateCursor(const GLFWimage* image, int xhot, int yhot); + +/*! @brief Creates a cursor with a standard shape. + * + * Returns a cursor with a [standard shape](@ref shapes), that can be set for + * a window with @ref glfwSetCursor. + * + * @param[in] shape One of the [standard shapes](@ref shapes). + * + * @return A new cursor ready to use or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @par Reentrancy + * This function may not be called from a callback. + * + * @par Thread Safety + * This function may only be called from the main thread. + * + * @sa @ref cursor_object + * @sa glfwCreateCursor + * + * @since Added in GLFW 3.1. + * + * @ingroup input + */ +GLFWAPI GLFWcursor* glfwCreateStandardCursor(int shape); + +/*! @brief Destroys a cursor. + * + * This function destroys a cursor previously created with @ref + * glfwCreateCursor. Any remaining cursors will be destroyed by @ref + * glfwTerminate. + * + * @param[in] cursor The cursor object to destroy. + * + * @par Reentrancy + * This function may not be called from a callback. + * + * @par Thread Safety + * This function may only be called from the main thread. + * + * @sa @ref cursor_object + * @sa glfwCreateCursor + * + * @since Added in GLFW 3.1. + * + * @ingroup input + */ +GLFWAPI void glfwDestroyCursor(GLFWcursor* cursor); + +/*! @brief Sets the cursor for the window. + * + * This function sets the cursor image to be used when the cursor is over the + * client area of the specified window. The set cursor will only be visible + * when the [cursor mode](@ref cursor_mode) of the window is + * `GLFW_CURSOR_NORMAL`. + * + * On some platforms, the set cursor may not be visible unless the window also + * has input focus. + * + * @param[in] window The window to set the cursor for. + * @param[in] cursor The cursor to set, or `NULL` to switch back to the default + * arrow cursor. + * + * @par Thread Safety + * This function may only be called from the main thread. + * + * @sa @ref cursor_object + * + * @since Added in GLFW 3.1. + * + * @ingroup input + */ +GLFWAPI void glfwSetCursor(GLFWwindow* window, GLFWcursor* cursor); + /*! @brief Sets the key callback. * - * This function sets the key callback of the specific window, which is called + * This function sets the key callback of the specified window, which is called * when a key is pressed, repeated or released. * * The key functions deal with physical keys, with layout independent @@ -1873,16 +2724,16 @@ GLFWAPI void glfwSetCursorPos(GLFWwindow* window, double xpos, double ypos); * layout. If you want to input text, use the * [character callback](@ref glfwSetCharCallback) instead. * - * When a window loses focus, it will generate synthetic key release events - * for all pressed keys. You can tell these events from user-generated events - * by the fact that the synthetic ones are generated after the window has lost - * focus, i.e. `GLFW_FOCUSED` will be false and the focus callback will have - * already been called. + * When a window loses input focus, it will generate synthetic key release + * events for all pressed keys. You can tell these events from user-generated + * events by the fact that the synthetic ones are generated after the focus + * loss event has been processed, i.e. after the + * [window focus callback](@ref glfwSetWindowFocusCallback) has been called. * * The scancode of a key is specific to that platform or sometimes even to that * machine. Scancodes are intended to allow users to bind keys that don't have * a GLFW key token. Such keys have `key` set to `GLFW_KEY_UNKNOWN`, their - * state is not saved and so it cannot be retrieved with @ref glfwGetKey. + * state is not saved and so it cannot be queried with @ref glfwGetKey. * * Sometimes GLFW needs to generate synthetic key events, in which case the * scancode may be zero. @@ -1890,8 +2741,18 @@ GLFWAPI void glfwSetCursorPos(GLFWwindow* window, double xpos, double ypos); * @param[in] window The window whose callback to set. * @param[in] cbfun The new key callback, or `NULL` to remove the currently * set callback. - * @return The previously set callback, or `NULL` if no callback was set or an - * error occurred. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @par Thread Safety + * This function may only be called from the main thread. + * + * @sa @ref input_key + * + * @since Added in GLFW 1.0. + * + * @par + * __GLFW 3:__ Added window handle parameter. Updated callback signature. * * @ingroup input */ @@ -1899,11 +2760,56 @@ GLFWAPI GLFWkeyfun glfwSetKeyCallback(GLFWwindow* window, GLFWkeyfun cbfun); /*! @brief Sets the Unicode character callback. * - * This function sets the character callback of the specific window, which is + * This function sets the character callback of the specified window, which is * called when a Unicode character is input. * - * The character callback is intended for text input. If you want to know - * whether a specific key was pressed or released, use the + * The character callback is intended for Unicode text input. As it deals with + * characters, it is keyboard layout dependent, whereas the + * [key callback](@ref glfwSetKeyCallback) is not. Characters do not map 1:1 + * to physical keys, as a key may produce zero, one or more characters. If you + * want to know whether a specific physical key was pressed or released, see + * the key callback instead. + * + * The character callback behaves as system text input normally does and will + * not be called if modifier keys are held down that would prevent normal text + * input on that platform, for example a Super (Command) key on OS X or Alt key + * on Windows. There is a + * [character with modifiers callback](@ref glfwSetCharModsCallback) that + * receives these events. + * + * @param[in] window The window whose callback to set. + * @param[in] cbfun The new callback, or `NULL` to remove the currently set + * callback. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @par Thread Safety + * This function may only be called from the main thread. + * + * @sa @ref input_char + * + * @since Added in GLFW 2.4. + * + * @par + * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * + * @ingroup input + */ +GLFWAPI GLFWcharfun glfwSetCharCallback(GLFWwindow* window, GLFWcharfun cbfun); + +/*! @brief Sets the Unicode character with modifiers callback. + * + * This function sets the character with modifiers callback of the specified + * window, which is called when a Unicode character is input regardless of what + * modifier keys are used. + * + * The character with modifiers callback is intended for implementing custom + * Unicode character input. For regular Unicode text input, see the + * [character callback](@ref glfwSetCharCallback). Like the character + * callback, the character with modifiers callback deals with characters and is + * keyboard layout dependent. Characters do not map 1:1 to physical keys, as + * a key may produce zero, one or more characters. If you want to know whether + * a specific physical key was pressed or released, see the * [key callback](@ref glfwSetKeyCallback) instead. * * @param[in] window The window whose callback to set. @@ -1912,26 +2818,43 @@ GLFWAPI GLFWkeyfun glfwSetKeyCallback(GLFWwindow* window, GLFWkeyfun cbfun); * @return The previously set callback, or `NULL` if no callback was set or an * error occurred. * + * @par Thread Safety + * This function may only be called from the main thread. + * + * @sa @ref input_char + * + * @since Added in GLFW 3.1. + * * @ingroup input */ -GLFWAPI GLFWcharfun glfwSetCharCallback(GLFWwindow* window, GLFWcharfun cbfun); +GLFWAPI GLFWcharmodsfun glfwSetCharModsCallback(GLFWwindow* window, GLFWcharmodsfun cbfun); /*! @brief Sets the mouse button callback. * * This function sets the mouse button callback of the specified window, which * is called when a mouse button is pressed or released. * - * When a window loses focus, it will generate synthetic mouse button release - * events for all pressed mouse buttons. You can tell these events from - * user-generated events by the fact that the synthetic ones are generated - * after the window has lost focus, i.e. `GLFW_FOCUSED` will be false and the - * focus callback will have already been called. + * When a window loses input focus, it will generate synthetic mouse button + * release events for all pressed mouse buttons. You can tell these events + * from user-generated events by the fact that the synthetic ones are generated + * after the focus loss event has been processed, i.e. after the + * [window focus callback](@ref glfwSetWindowFocusCallback) has been called. * * @param[in] window The window whose callback to set. * @param[in] cbfun The new callback, or `NULL` to remove the currently set * callback. - * @return The previously set callback, or `NULL` if no callback was set or an - * error occurred. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @par Thread Safety + * This function may only be called from the main thread. + * + * @sa @ref input_mouse_button + * + * @since Added in GLFW 1.0. + * + * @par + * __GLFW 3:__ Added window handle parameter. Updated callback signature. * * @ingroup input */ @@ -1941,13 +2864,21 @@ GLFWAPI GLFWmousebuttonfun glfwSetMouseButtonCallback(GLFWwindow* window, GLFWmo * * This function sets the cursor position callback of the specified window, * which is called when the cursor is moved. The callback is provided with the - * position relative to the upper-left corner of the client area of the window. + * position, in screen coordinates, relative to the upper-left corner of the + * client area of the window. * * @param[in] window The window whose callback to set. * @param[in] cbfun The new callback, or `NULL` to remove the currently set * callback. - * @return The previously set callback, or `NULL` if no callback was set or an - * error occurred. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @par Thread Safety + * This function may only be called from the main thread. + * + * @sa @ref cursor_pos + * + * @since Added in GLFW 3.0. Replaces `glfwSetMousePosCallback`. * * @ingroup input */ @@ -1962,8 +2893,15 @@ GLFWAPI GLFWcursorposfun glfwSetCursorPosCallback(GLFWwindow* window, GLFWcursor * @param[in] window The window whose callback to set. * @param[in] cbfun The new callback, or `NULL` to remove the currently set * callback. - * @return The previously set callback, or `NULL` if no callback was set or an - * error occurred. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @par Thread Safety + * This function may only be called from the main thread. + * + * @sa @ref cursor_enter + * + * @since Added in GLFW 3.0. * * @ingroup input */ @@ -1981,20 +2919,61 @@ GLFWAPI GLFWcursorenterfun glfwSetCursorEnterCallback(GLFWwindow* window, GLFWcu * @param[in] window The window whose callback to set. * @param[in] cbfun The new scroll callback, or `NULL` to remove the currently * set callback. - * @return The previously set callback, or `NULL` if no callback was set or an - * error occurred. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @par Thread Safety + * This function may only be called from the main thread. + * + * @sa @ref scrolling + * + * @since Added in GLFW 3.0. Replaces `glfwSetMouseWheelCallback`. * * @ingroup input */ GLFWAPI GLFWscrollfun glfwSetScrollCallback(GLFWwindow* window, GLFWscrollfun cbfun); +/*! @brief Sets the file drop callback. + * + * This function sets the file drop callback of the specified window, which is + * called when one or more dragged files are dropped on the window. + * + * Because the path array and its strings may have been generated specifically + * for that event, they are not guaranteed to be valid after the callback has + * returned. If you wish to use them after the callback returns, you need to + * make a deep copy. + * + * @param[in] window The window whose callback to set. + * @param[in] cbfun The new file drop callback, or `NULL` to remove the + * currently set callback. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @par Thread Safety + * This function may only be called from the main thread. + * + * @sa @ref path_drop + * + * @since Added in GLFW 3.1. + * + * @ingroup input + */ +GLFWAPI GLFWdropfun glfwSetDropCallback(GLFWwindow* window, GLFWdropfun cbfun); + /*! @brief Returns whether the specified joystick is present. * * This function returns whether the specified joystick is present. * - * @param[in] joy The joystick to query. + * @param[in] joy The [joystick](@ref joysticks) to query. * @return `GL_TRUE` if the joystick is present, or `GL_FALSE` otherwise. * + * @par Thread Safety + * This function may only be called from the main thread. + * + * @sa @ref joystick + * + * @since Added in GLFW 3.0. Replaces `glfwGetJoystickParam`. + * * @ingroup input */ GLFWAPI int glfwJoystickPresent(int joy); @@ -2002,17 +2981,24 @@ GLFWAPI int glfwJoystickPresent(int joy); /*! @brief Returns the values of all axes of the specified joystick. * * This function returns the values of all axes of the specified joystick. + * Each element in the array is a value between -1.0 and 1.0. * - * @param[in] joy The joystick to query. - * @param[out] count Where to store the size of the returned array. This is - * set to zero if an error occurred. + * @param[in] joy The [joystick](@ref joysticks) to query. + * @param[out] count Where to store the number of axis values in the returned + * array. This is set to zero if an error occurred. * @return An array of axis values, or `NULL` if the joystick is not present. * - * @note The returned array is allocated and freed by GLFW. You should not - * free it yourself. + * @par Pointer Lifetime + * The returned array is allocated and freed by GLFW. You should not free it + * yourself. It is valid until the specified joystick is disconnected, this + * function is called again for that joystick or the library is terminated. * - * @note The returned array is valid only until the next call to @ref - * glfwGetJoystickAxes for that joystick. + * @par Thread Safety + * This function may only be called from the main thread. + * + * @sa @ref joystick_axis + * + * @since Added in GLFW 3.0. Replaces `glfwGetJoystickPos`. * * @ingroup input */ @@ -2021,17 +3007,27 @@ GLFWAPI const float* glfwGetJoystickAxes(int joy, int* count); /*! @brief Returns the state of all buttons of the specified joystick. * * This function returns the state of all buttons of the specified joystick. + * Each element in the array is either `GLFW_PRESS` or `GLFW_RELEASE`. * - * @param[in] joy The joystick to query. - * @param[out] count Where to store the size of the returned array. This is - * set to zero if an error occurred. + * @param[in] joy The [joystick](@ref joysticks) to query. + * @param[out] count Where to store the number of button states in the returned + * array. This is set to zero if an error occurred. * @return An array of button states, or `NULL` if the joystick is not present. * - * @note The returned array is allocated and freed by GLFW. You should not - * free it yourself. + * @par Pointer Lifetime + * The returned array is allocated and freed by GLFW. You should not free it + * yourself. It is valid until the specified joystick is disconnected, this + * function is called again for that joystick or the library is terminated. * - * @note The returned array is valid only until the next call to @ref - * glfwGetJoystickButtons for that joystick. + * @par Thread Safety + * This function may only be called from the main thread. + * + * @sa @ref joystick_button + * + * @since Added in GLFW 2.2. + * + * @par + * __GLFW 3:__ Changed to return a dynamic array. * * @ingroup input */ @@ -2040,16 +3036,24 @@ GLFWAPI const unsigned char* glfwGetJoystickButtons(int joy, int* count); /*! @brief Returns the name of the specified joystick. * * This function returns the name, encoded as UTF-8, of the specified joystick. + * The returned string is allocated and freed by GLFW. You should not free it + * yourself. * - * @param[in] joy The joystick to query. + * @param[in] joy The [joystick](@ref joysticks) to query. * @return The UTF-8 encoded name of the joystick, or `NULL` if the joystick * is not present. * - * @note The returned string is allocated and freed by GLFW. You should not - * free it yourself. + * @par Pointer Lifetime + * The returned string is allocated and freed by GLFW. You should not free it + * yourself. It is valid until the specified joystick is disconnected, this + * function is called again for that joystick or the library is terminated. * - * @note The returned string is valid only until the next call to @ref - * glfwGetJoystickName for that joystick. + * @par Thread Safety + * This function may only be called from the main thread. + * + * @sa @ref joystick_name + * + * @since Added in GLFW 3.0. * * @ingroup input */ @@ -2058,40 +3062,50 @@ GLFWAPI const char* glfwGetJoystickName(int joy); /*! @brief Sets the clipboard to the specified string. * * This function sets the system clipboard to the specified, UTF-8 encoded - * string. The string is copied before returning, so you don't have to retain - * it afterwards. + * string. * * @param[in] window The window that will own the clipboard contents. * @param[in] string A UTF-8 encoded string. * - * @note This function may only be called from the main thread. + * @par Pointer Lifetime + * The specified string is copied before this function returns. * + * @par Thread Safety + * This function may only be called from the main thread. + * + * @sa @ref clipboard * @sa glfwGetClipboardString * - * @ingroup clipboard + * @since Added in GLFW 3.0. + * + * @ingroup input */ GLFWAPI void glfwSetClipboardString(GLFWwindow* window, const char* string); -/*! @brief Retrieves the contents of the clipboard as a string. +/*! @brief Returns the contents of the clipboard as a string. * * This function returns the contents of the system clipboard, if it contains * or is convertible to a UTF-8 encoded string. * * @param[in] window The window that will request the clipboard contents. * @return The contents of the clipboard as a UTF-8 encoded string, or `NULL` - * if an error occurred. + * if an [error](@ref error_handling) occurred. * - * @note This function may only be called from the main thread. + * @par Pointer Lifetime + * The returned string is allocated and freed by GLFW. You should not free it + * yourself. It is valid until the next call to @ref + * glfwGetClipboardString or @ref glfwSetClipboardString, or until the library + * is terminated. * - * @note The returned string is allocated and freed by GLFW. You should not - * free it yourself. - * - * @note The returned string is valid only until the next call to @ref - * glfwGetClipboardString or @ref glfwSetClipboardString. + * @par Thread Safety + * This function may only be called from the main thread. * + * @sa @ref clipboard * @sa glfwSetClipboardString * - * @ingroup clipboard + * @since Added in GLFW 3.0. + * + * @ingroup input */ GLFWAPI const char* glfwGetClipboardString(GLFWwindow* window); @@ -2101,15 +3115,21 @@ GLFWAPI const char* glfwGetClipboardString(GLFWwindow* window); * been set using @ref glfwSetTime, the timer measures time elapsed since GLFW * was initialized. * - * @return The current value, in seconds, or zero if an error occurred. + * The resolution of the timer is system dependent, but is usually on the order + * of a few micro- or nanoseconds. It uses the highest-resolution monotonic + * time source on each supported platform. * - * @remarks This function may be called from secondary threads. + * @return The current value, in seconds, or zero if an + * [error](@ref error_handling) occurred. * - * @note The resolution of the timer is system dependent, but is usually on the - * order of a few micro- or nanoseconds. It uses the highest-resolution - * monotonic time source on each supported platform. + * @par Thread Safety + * This function may be called from any thread. Access is not synchronized. * - * @ingroup time + * @sa @ref time + * + * @since Added in GLFW 1.0. + * + * @ingroup input */ GLFWAPI double glfwGetTime(void); @@ -2120,44 +3140,61 @@ GLFWAPI double glfwGetTime(void); * * @param[in] time The new value, in seconds. * - * @note The resolution of the timer is system dependent, but is usually on the - * order of a few micro- or nanoseconds. It uses the highest-resolution - * monotonic time source on each supported platform. + * @par Thread Safety + * This function may only be called from the main thread. * - * @ingroup time + * @sa @ref time + * + * @since Added in GLFW 2.2. + * + * @ingroup input */ GLFWAPI void glfwSetTime(double time); /*! @brief Makes the context of the specified window current for the calling * thread. * - * This function makes the context of the specified window current on the - * calling thread. A context can only be made current on a single thread at - * a time and each thread can have only a single current context at a time. + * This function makes the OpenGL or OpenGL ES context of the specified window + * current on the calling thread. A context can only be made current on + * a single thread at a time and each thread can have only a single current + * context at a time. + * + * By default, making a context non-current implicitly forces a pipeline flush. + * On machines that support `GL_KHR_context_flush_control`, you can control + * whether a context performs this flush by setting the + * [GLFW_CONTEXT_RELEASE_BEHAVIOR](@ref window_hints_ctx) window hint. * * @param[in] window The window whose context to make current, or `NULL` to * detach the current context. * - * @remarks This function may be called from secondary threads. + * @par Thread Safety + * This function may be called from any thread. * + * @sa @ref context_current * @sa glfwGetCurrentContext * + * @since Added in GLFW 3.0. + * * @ingroup context */ GLFWAPI void glfwMakeContextCurrent(GLFWwindow* window); /*! @brief Returns the window whose context is current on the calling thread. * - * This function returns the window whose context is current on the calling - * thread. + * This function returns the window whose OpenGL or OpenGL ES context is + * current on the calling thread. * * @return The window whose context is current, or `NULL` if no window's * context is current. * - * @remarks This function may be called from secondary threads. + * @par Thread Safety + * This function may be called from any thread. * + * @sa @ref context_current * @sa glfwMakeContextCurrent * + * @since Added in GLFW 3.0. + * * @ingroup context */ GLFWAPI GLFWwindow* glfwGetCurrentContext(void); @@ -2170,24 +3207,28 @@ GLFWAPI GLFWwindow* glfwGetCurrentContext(void); * * @param[in] window The window whose buffers to swap. * - * @remarks This function may be called from secondary threads. - * - * @par New in GLFW 3 - * This function no longer calls @ref glfwPollEvents. You need to call it or - * @ref glfwWaitEvents yourself. + * @par Thread Safety + * This function may be called from any thread. * + * @sa @ref buffer_swap * @sa glfwSwapInterval * - * @ingroup context + * @since Added in GLFW 1.0. + * + * @par + * __GLFW 3:__ Added window handle parameter. + * + * @ingroup window */ GLFWAPI void glfwSwapBuffers(GLFWwindow* window); /*! @brief Sets the swap interval for the current context. * * This function sets the swap interval for the current context, i.e. the - * number of screen updates to wait before swapping the buffers of a window and - * returning from @ref glfwSwapBuffers. This is sometimes called 'vertical - * synchronization', 'vertical retrace synchronization' or 'vsync'. + * number of screen updates to wait from the time @ref glfwSwapBuffers was + * called before swapping the buffers and returning. This is sometimes called + * _vertical synchronization_, _vertical retrace synchronization_ or just + * _vsync_. * * Contexts that support either of the `WGL_EXT_swap_control_tear` and * `GLX_EXT_swap_control_tear` extensions also accept negative swap intervals, @@ -2196,17 +3237,29 @@ GLFWAPI void glfwSwapBuffers(GLFWwindow* window); * glfwExtensionSupported. For more information about swap tearing, see the * extension specifications. * + * A context must be current on the calling thread. Calling this function + * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. + * * @param[in] interval The minimum number of screen updates to wait for * until the buffers are swapped by @ref glfwSwapBuffers. * - * @remarks This function may be called from secondary threads. + * @note This function is not called during window creation, leaving the swap + * interval set to whatever is the default on that platform. This is done + * because some swap interval extensions used by GLFW do not allow the swap + * interval to be reset to zero once it has been set to a non-zero value. * * @note Some GPU drivers do not honor the requested swap interval, either * because of user settings that override the request or due to bugs in the * driver. * + * @par Thread Safety + * This function may be called from any thread. + * + * @sa @ref buffer_swap * @sa glfwSwapBuffers * + * @since Added in GLFW 1.0. + * * @ingroup context */ GLFWAPI void glfwSwapInterval(int interval); @@ -2214,19 +3267,28 @@ GLFWAPI void glfwSwapInterval(int interval); /*! @brief Returns whether the specified extension is available. * * This function returns whether the specified - * [OpenGL or context creation API extension](@ref context_glext) is supported - * by the current context. For example, on Windows both the OpenGL and WGL - * extension strings are checked. + * [API extension](@ref context_glext) is supported by the current OpenGL or + * OpenGL ES context. It searches both for OpenGL and OpenGL ES extension and + * platform-specific context creation API extensions. + * + * A context must be current on the calling thread. Calling this function + * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. + * + * As this functions retrieves and searches one or more extension strings each + * call, it is recommended that you cache its results if it is going to be used + * frequently. The extension strings will not change during the lifetime of + * a context, so there is no danger in doing this. * * @param[in] extension The ASCII encoded name of the extension. * @return `GL_TRUE` if the extension is available, or `GL_FALSE` otherwise. * - * @remarks This function may be called from secondary threads. + * @par Thread Safety + * This function may be called from any thread. * - * @note As this functions searches one or more extension strings on each call, - * it is recommended that you cache its results if it's going to be used - * frequently. The extension strings will not change during the lifetime of - * a context, so there is no danger in doing this. + * @sa @ref context_glext + * @sa glfwGetProcAddress + * + * @since Added in GLFW 1.0. * * @ingroup context */ @@ -2239,15 +3301,27 @@ GLFWAPI int glfwExtensionSupported(const char* extension); * [client API or extension function](@ref context_glext), if it is supported * by the current context. * + * A context must be current on the calling thread. Calling this function + * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. + * * @param[in] procname The ASCII encoded name of the function. * @return The address of the function, or `NULL` if the function is - * unavailable. + * unavailable or an [error](@ref error_handling) occurred. * - * @remarks This function may be called from secondary threads. + * @note The addresses of a given function is not guaranteed to be the same + * between contexts. * - * @note The addresses of these functions are not guaranteed to be the same for - * all contexts, especially if they use different client APIs or even different - * context creation hints. + * @par Pointer Lifetime + * The returned function pointer is valid until the context is destroyed or the + * library is terminated. + * + * @par Thread Safety + * This function may be called from any thread. + * + * @sa @ref context_glext + * @sa glfwExtensionSupported + * + * @since Added in GLFW 1.0. * * @ingroup context */ diff --git a/examples/opengl_example/glfw/include/GLFW/glfw3native.h b/examples/opengl_example/glfw/include/GLFW/glfw3native.h index d570f5876..b3ce7482d 100644 --- a/examples/opengl_example/glfw/include/GLFW/glfw3native.h +++ b/examples/opengl_example/glfw/include/GLFW/glfw3native.h @@ -1,5 +1,5 @@ /************************************************************************* - * GLFW 3.0 - www.glfw.org + * GLFW 3.1 - www.glfw.org * A library for OpenGL, window and input *------------------------------------------------------------------------ * Copyright (c) 2002-2006 Marcus Geelnard @@ -40,13 +40,13 @@ extern "C" { /*! @defgroup native Native access * - * **By using the native API, you assert that you know what you're doing and - * how to fix problems caused by using it. If you don't, you shouldn't be - * using it.** + * **By using the native access functions you assert that you know what you're + * doing and how to fix problems caused by using them. If you don't, you + * shouldn't be using them.** * * Before the inclusion of @ref glfw3native.h, you must define exactly one - * window API macro and exactly one context API macro. Failure to do this - * will cause a compile-time error. + * window system API macro and exactly one context creation API macro. Failure + * to do this will cause a compile-time error. * * The available window API macros are: * * `GLFW_EXPOSE_NATIVE_WIN32` @@ -71,8 +71,13 @@ extern "C" { *************************************************************************/ #if defined(GLFW_EXPOSE_NATIVE_WIN32) + // This is a workaround for the fact that glfw3.h needs to export APIENTRY (for + // example to allow applications to correctly declare a GL_ARB_debug_output + // callback) but windows.h assumes no one will define APIENTRY before it does + #undef APIENTRY #include #elif defined(GLFW_EXPOSE_NATIVE_COCOA) + #include #if defined(__OBJC__) #import #else @@ -80,8 +85,9 @@ extern "C" { #endif #elif defined(GLFW_EXPOSE_NATIVE_X11) #include + #include #else - #error "No window API specified" + #error "No window API selected" #endif #if defined(GLFW_EXPOSE_NATIVE_WGL) @@ -93,7 +99,7 @@ extern "C" { #elif defined(GLFW_EXPOSE_NATIVE_EGL) #include #else - #error "No context API specified" + #error "No context API selected" #endif @@ -102,8 +108,49 @@ extern "C" { *************************************************************************/ #if defined(GLFW_EXPOSE_NATIVE_WIN32) +/*! @brief Returns the adapter device name of the specified monitor. + * + * @return The UTF-8 encoded adapter device name (for example `\\.\DISPLAY1`) + * of the specified monitor, or `NULL` if an [error](@ref error_handling) + * occurred. + * + * @par Thread Safety + * This function may be called from any thread. Access is not synchronized. + * + * @par History + * Added in GLFW 3.1. + * + * @ingroup native + */ +GLFWAPI const char* glfwGetWin32Adapter(GLFWmonitor* monitor); + +/*! @brief Returns the display device name of the specified monitor. + * + * @return The UTF-8 encoded display device name (for example + * `\\.\DISPLAY1\Monitor0`) of the specified monitor, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @par Thread Safety + * This function may be called from any thread. Access is not synchronized. + * + * @par History + * Added in GLFW 3.1. + * + * @ingroup native + */ +GLFWAPI const char* glfwGetWin32Monitor(GLFWmonitor* monitor); + /*! @brief Returns the `HWND` of the specified window. - * @return The `HWND` of the specified window. + * + * @return The `HWND` of the specified window, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @par Thread Safety + * This function may be called from any thread. Access is not synchronized. + * + * @par History + * Added in GLFW 3.0. + * * @ingroup native */ GLFWAPI HWND glfwGetWin32Window(GLFWwindow* window); @@ -111,15 +158,48 @@ GLFWAPI HWND glfwGetWin32Window(GLFWwindow* window); #if defined(GLFW_EXPOSE_NATIVE_WGL) /*! @brief Returns the `HGLRC` of the specified window. - * @return The `HGLRC` of the specified window. + * + * @return The `HGLRC` of the specified window, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @par Thread Safety + * This function may be called from any thread. Access is not synchronized. + * + * @par History + * Added in GLFW 3.0. + * * @ingroup native */ GLFWAPI HGLRC glfwGetWGLContext(GLFWwindow* window); #endif #if defined(GLFW_EXPOSE_NATIVE_COCOA) +/*! @brief Returns the `CGDirectDisplayID` of the specified monitor. + * + * @return The `CGDirectDisplayID` of the specified monitor, or + * `kCGNullDirectDisplay` if an [error](@ref error_handling) occurred. + * + * @par Thread Safety + * This function may be called from any thread. Access is not synchronized. + * + * @par History + * Added in GLFW 3.1. + * + * @ingroup native + */ +GLFWAPI CGDirectDisplayID glfwGetCocoaMonitor(GLFWmonitor* monitor); + /*! @brief Returns the `NSWindow` of the specified window. - * @return The `NSWindow` of the specified window. + * + * @return The `NSWindow` of the specified window, or `nil` if an + * [error](@ref error_handling) occurred. + * + * @par Thread Safety + * This function may be called from any thread. Access is not synchronized. + * + * @par History + * Added in GLFW 3.0. + * * @ingroup native */ GLFWAPI id glfwGetCocoaWindow(GLFWwindow* window); @@ -127,7 +207,16 @@ GLFWAPI id glfwGetCocoaWindow(GLFWwindow* window); #if defined(GLFW_EXPOSE_NATIVE_NSGL) /*! @brief Returns the `NSOpenGLContext` of the specified window. - * @return The `NSOpenGLContext` of the specified window. + * + * @return The `NSOpenGLContext` of the specified window, or `nil` if an + * [error](@ref error_handling) occurred. + * + * @par Thread Safety + * This function may be called from any thread. Access is not synchronized. + * + * @par History + * Added in GLFW 3.0. + * * @ingroup native */ GLFWAPI id glfwGetNSGLContext(GLFWwindow* window); @@ -135,12 +224,61 @@ GLFWAPI id glfwGetNSGLContext(GLFWwindow* window); #if defined(GLFW_EXPOSE_NATIVE_X11) /*! @brief Returns the `Display` used by GLFW. - * @return The `Display` used by GLFW. + * + * @return The `Display` used by GLFW, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @par Thread Safety + * This function may be called from any thread. Access is not synchronized. + * + * @par History + * Added in GLFW 3.0. + * * @ingroup native */ GLFWAPI Display* glfwGetX11Display(void); + +/*! @brief Returns the `RRCrtc` of the specified monitor. + * + * @return The `RRCrtc` of the specified monitor, or `None` if an + * [error](@ref error_handling) occurred. + * + * @par Thread Safety + * This function may be called from any thread. Access is not synchronized. + * + * @par History + * Added in GLFW 3.1. + * + * @ingroup native + */ +GLFWAPI RRCrtc glfwGetX11Adapter(GLFWmonitor* monitor); + +/*! @brief Returns the `RROutput` of the specified monitor. + * + * @return The `RROutput` of the specified monitor, or `None` if an + * [error](@ref error_handling) occurred. + * + * @par Thread Safety + * This function may be called from any thread. Access is not synchronized. + * + * @par History + * Added in GLFW 3.1. + * + * @ingroup native + */ +GLFWAPI RROutput glfwGetX11Monitor(GLFWmonitor* monitor); + /*! @brief Returns the `Window` of the specified window. - * @return The `Window` of the specified window. + * + * @return The `Window` of the specified window, or `None` if an + * [error](@ref error_handling) occurred. + * + * @par Thread Safety + * This function may be called from any thread. Access is not synchronized. + * + * @par History + * Added in GLFW 3.0. + * * @ingroup native */ GLFWAPI Window glfwGetX11Window(GLFWwindow* window); @@ -148,7 +286,16 @@ GLFWAPI Window glfwGetX11Window(GLFWwindow* window); #if defined(GLFW_EXPOSE_NATIVE_GLX) /*! @brief Returns the `GLXContext` of the specified window. - * @return The `GLXContext` of the specified window. + * + * @return The `GLXContext` of the specified window, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @par Thread Safety + * This function may be called from any thread. Access is not synchronized. + * + * @par History + * Added in GLFW 3.0. + * * @ingroup native */ GLFWAPI GLXContext glfwGetGLXContext(GLFWwindow* window); @@ -156,17 +303,46 @@ GLFWAPI GLXContext glfwGetGLXContext(GLFWwindow* window); #if defined(GLFW_EXPOSE_NATIVE_EGL) /*! @brief Returns the `EGLDisplay` used by GLFW. - * @return The `EGLDisplay` used by GLFW. + * + * @return The `EGLDisplay` used by GLFW, or `EGL_NO_DISPLAY` if an + * [error](@ref error_handling) occurred. + * + * @par Thread Safety + * This function may be called from any thread. Access is not synchronized. + * + * @par History + * Added in GLFW 3.0. + * * @ingroup native */ GLFWAPI EGLDisplay glfwGetEGLDisplay(void); + /*! @brief Returns the `EGLContext` of the specified window. - * @return The `EGLContext` of the specified window. + * + * @return The `EGLContext` of the specified window, or `EGL_NO_CONTEXT` if an + * [error](@ref error_handling) occurred. + * + * @par Thread Safety + * This function may be called from any thread. Access is not synchronized. + * + * @par History + * Added in GLFW 3.0. + * * @ingroup native */ GLFWAPI EGLContext glfwGetEGLContext(GLFWwindow* window); + /*! @brief Returns the `EGLSurface` of the specified window. - * @return The `EGLSurface` of the specified window. + * + * @return The `EGLSurface` of the specified window, or `EGL_NO_SURFACE` if an + * [error](@ref error_handling) occurred. + * + * @par Thread Safety + * This function may be called from any thread. Access is not synchronized. + * + * @par History + * Added in GLFW 3.0. + * * @ingroup native */ GLFWAPI EGLSurface glfwGetEGLSurface(GLFWwindow* window); diff --git a/examples/opengl_example/glfw/lib-msvc100/glfw3.lib b/examples/opengl_example/glfw/lib-msvc100/glfw3.lib deleted file mode 100644 index 777b5b6cefdb2719f3ed19d69db00c92e30b5a83..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 121560 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 aJT=fh%T6 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

+HU>}u1zHiu1}-8&$Hj;+fL7i?hOR&b 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 diff --git a/examples/opengl_example/glfw/lib-msvc110/glfw3.lib b/examples/opengl_example/glfw/lib-msvc110/glfw3.lib deleted file mode 100644 index c5c9cbae9dc033ef0cf48652aefe05ee324c5105..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 121720 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

cjF(cPU51K2R~pP{N-D-Rg0y4J-g| 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 F1pt74_uK#g diff --git a/examples/opengl_example/glfw/lib-vc2010-32/glfw3.lib b/examples/opengl_example/glfw/lib-vc2010-32/glfw3.lib new file mode 100644 index 0000000000000000000000000000000000000000..014458efed8cff308e876c22c2e4832c705079eb GIT binary patch literal 129546 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 literal 0 HcmV?d00001 diff --git a/examples/opengl_example/opengl_example.vcxproj b/examples/opengl_example/opengl_example.vcxproj index 6dc904542..c92d0acc8 100644 --- a/examples/opengl_example/opengl_example.vcxproj +++ b/examples/opengl_example/opengl_example.vcxproj @@ -54,7 +54,7 @@ true - $(ProjectDir)\glfw\lib-msvc100;$(ProjectDir)\glew\lib\Release\Win32;%(AdditionalLibraryDirectories) + $(ProjectDir)\glfw\lib-vc2010-32;%(AdditionalLibraryDirectories) opengl32.lib;glfw3.lib;%(AdditionalDependencies) Console msvcrt.lib @@ -72,7 +72,7 @@ true true true - $(ProjectDir)\glfw\lib-msvc100;$(ProjectDir)\glew\lib\Release\Win32;%(AdditionalLibraryDirectories) + $(ProjectDir)\glfw\lib-vc2010-32;%(AdditionalLibraryDirectories) opengl32.lib;glfw3.lib;%(AdditionalDependencies) Console From ef957b7878e1ea3d477ab35abb49e0f1c767e91a Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 14 Mar 2015 10:04:30 +0000 Subject: [PATCH 17/44] Examples: Moved GLFW/GL3W to a common libs/ folder --- examples/{opengl3_example => libs}/gl3w/GL/gl3w.c | 0 examples/{opengl3_example => libs}/gl3w/GL/gl3w.h | 0 .../{opengl3_example => libs}/gl3w/GL/glcorearb.h | 0 .../{opengl_example => libs}/glfw/COPYING.txt | 0 .../glfw/include/GLFW/glfw3.h | 0 .../glfw/include/GLFW/glfw3native.h | 0 .../glfw/lib-vc2010-32/glfw3.lib | Bin examples/opengl3_example/opengl3_example.vcxproj | 14 +++++++------- .../opengl3_example.vcxproj.filters | 6 +++--- examples/opengl_example/opengl_example.vcxproj | 8 ++++---- 10 files changed, 14 insertions(+), 14 deletions(-) rename examples/{opengl3_example => libs}/gl3w/GL/gl3w.c (100%) rename examples/{opengl3_example => libs}/gl3w/GL/gl3w.h (100%) rename examples/{opengl3_example => libs}/gl3w/GL/glcorearb.h (100%) rename examples/{opengl_example => libs}/glfw/COPYING.txt (100%) rename examples/{opengl_example => libs}/glfw/include/GLFW/glfw3.h (100%) rename examples/{opengl_example => libs}/glfw/include/GLFW/glfw3native.h (100%) rename examples/{opengl_example => libs}/glfw/lib-vc2010-32/glfw3.lib (100%) diff --git a/examples/opengl3_example/gl3w/GL/gl3w.c b/examples/libs/gl3w/GL/gl3w.c similarity index 100% rename from examples/opengl3_example/gl3w/GL/gl3w.c rename to examples/libs/gl3w/GL/gl3w.c diff --git a/examples/opengl3_example/gl3w/GL/gl3w.h b/examples/libs/gl3w/GL/gl3w.h similarity index 100% rename from examples/opengl3_example/gl3w/GL/gl3w.h rename to examples/libs/gl3w/GL/gl3w.h diff --git a/examples/opengl3_example/gl3w/GL/glcorearb.h b/examples/libs/gl3w/GL/glcorearb.h similarity index 100% rename from examples/opengl3_example/gl3w/GL/glcorearb.h rename to examples/libs/gl3w/GL/glcorearb.h diff --git a/examples/opengl_example/glfw/COPYING.txt b/examples/libs/glfw/COPYING.txt similarity index 100% rename from examples/opengl_example/glfw/COPYING.txt rename to examples/libs/glfw/COPYING.txt diff --git a/examples/opengl_example/glfw/include/GLFW/glfw3.h b/examples/libs/glfw/include/GLFW/glfw3.h similarity index 100% rename from examples/opengl_example/glfw/include/GLFW/glfw3.h rename to examples/libs/glfw/include/GLFW/glfw3.h diff --git a/examples/opengl_example/glfw/include/GLFW/glfw3native.h b/examples/libs/glfw/include/GLFW/glfw3native.h similarity index 100% rename from examples/opengl_example/glfw/include/GLFW/glfw3native.h rename to examples/libs/glfw/include/GLFW/glfw3native.h diff --git a/examples/opengl_example/glfw/lib-vc2010-32/glfw3.lib b/examples/libs/glfw/lib-vc2010-32/glfw3.lib similarity index 100% rename from examples/opengl_example/glfw/lib-vc2010-32/glfw3.lib rename to examples/libs/glfw/lib-vc2010-32/glfw3.lib diff --git a/examples/opengl3_example/opengl3_example.vcxproj b/examples/opengl3_example/opengl3_example.vcxproj index 3dd9afdfa..936c688da 100644 --- a/examples/opengl3_example/opengl3_example.vcxproj +++ b/examples/opengl3_example/opengl3_example.vcxproj @@ -50,11 +50,11 @@ Level3 Disabled - $(ProjectDir)..\opengl_example\glfw\include;gl3w;..\..;%(AdditionalIncludeDirectories) + $(SolutionDir)\libs\glfw\include;$(SolutionDir)\libs\gl3w;..\..;%(AdditionalIncludeDirectories) true - $(ProjectDir)..\opengl_example\glfw\lib-vc2010-32;%(AdditionalLibraryDirectories) + $(SolutionDir)\libs\glfw\lib-vc2010-32;%(AdditionalLibraryDirectories) opengl32.lib;glfw3.lib;%(AdditionalDependencies) Console msvcrt.lib @@ -66,13 +66,13 @@ MaxSpeed true true - $(ProjectDir)..\opengl_example\glfw\include;gl3w;..\..;%(AdditionalIncludeDirectories) + $(SolutionDir)\libs\glfw\include;$(SolutionDir)\libs\gl3w;..\..;%(AdditionalIncludeDirectories) true true true - $(ProjectDir)..\opengl_example\glfw\lib-vc2010-32;%(AdditionalLibraryDirectories) + $(SolutionDir)\libs\glfw\lib-vc2010-32;%(AdditionalLibraryDirectories) opengl32.lib;glfw3.lib;%(AdditionalDependencies) Console @@ -81,15 +81,15 @@ - + - - + + diff --git a/examples/opengl3_example/opengl3_example.vcxproj.filters b/examples/opengl3_example/opengl3_example.vcxproj.filters index 1c00552d4..544bd2e75 100644 --- a/examples/opengl3_example/opengl3_example.vcxproj.filters +++ b/examples/opengl3_example/opengl3_example.vcxproj.filters @@ -22,7 +22,7 @@ sources - + gl3w @@ -36,10 +36,10 @@ sources - + gl3w - + gl3w diff --git a/examples/opengl_example/opengl_example.vcxproj b/examples/opengl_example/opengl_example.vcxproj index c92d0acc8..1d4dbc55d 100644 --- a/examples/opengl_example/opengl_example.vcxproj +++ b/examples/opengl_example/opengl_example.vcxproj @@ -50,11 +50,11 @@ Level3 Disabled - $(ProjectDir)\glfw\include;..\..;%(AdditionalIncludeDirectories) + $(SolutionDir)\libs\glfw\include;..\..;%(AdditionalIncludeDirectories) true - $(ProjectDir)\glfw\lib-vc2010-32;%(AdditionalLibraryDirectories) + $(SolutionDir)\libs\glfw\lib-vc2010-32;%(AdditionalLibraryDirectories) opengl32.lib;glfw3.lib;%(AdditionalDependencies) Console msvcrt.lib @@ -66,13 +66,13 @@ MaxSpeed true true - $(ProjectDir)\glfw\include;..\..;%(AdditionalIncludeDirectories) + $(SolutionDir)\libs\glfw\include;..\..;%(AdditionalIncludeDirectories) true true true - $(ProjectDir)\glfw\lib-vc2010-32;%(AdditionalLibraryDirectories) + $(SolutionDir)\libs\glfw\lib-vc2010-32;%(AdditionalLibraryDirectories) opengl32.lib;glfw3.lib;%(AdditionalDependencies) Console From e2c4ba21bc3f800b8beb7e3ab53b3651cb68f6ca Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 14 Mar 2015 10:09:53 +0000 Subject: [PATCH 18/44] Examples: Added 64-bit projects for MSVC --- .../directx11_example.vcxproj | 63 ++++++++++++++++ .../directx9_example/directx9_example.vcxproj | 63 ++++++++++++++++ examples/imgui_examples_msvc2010.sln | 18 +++++ examples/libs/glfw/lib-vc2010-64/glfw3.lib | Bin 0 -> 202450 bytes .../opengl3_example/opengl3_example.vcxproj | 68 ++++++++++++++++++ .../opengl_example/opengl_example.vcxproj | 68 ++++++++++++++++++ 6 files changed, 280 insertions(+) create mode 100644 examples/libs/glfw/lib-vc2010-64/glfw3.lib diff --git a/examples/directx11_example/directx11_example.vcxproj b/examples/directx11_example/directx11_example.vcxproj index beddb330b..767cbcc2e 100644 --- a/examples/directx11_example/directx11_example.vcxproj +++ b/examples/directx11_example/directx11_example.vcxproj @@ -5,10 +5,18 @@ Debug Win32 + + Debug + x64 + Release Win32 + + Release + x64 + {9F316E83-5AE5-4939-A723-305A94F48005} @@ -20,30 +28,55 @@ true Unicode + + Application + true + Unicode + Application false true Unicode + + Application + false + true + Unicode + + + + + + + $(ProjectDir)$(Configuration)\ $(ProjectDir)$(Configuration)\ + + $(ProjectDir)$(Configuration)\ + $(ProjectDir)$(Configuration)\ + $(ProjectDir)$(Configuration)\ $(ProjectDir)$(Configuration)\ + + $(ProjectDir)$(Configuration)\ + $(ProjectDir)$(Configuration)\ + Level3 @@ -57,6 +90,19 @@ Console + + + Level3 + Disabled + ..\..;$(DXSDK_DIR)/Include;%(AdditionalIncludeDirectories) + + + true + d3d11.lib;d3dcompiler.lib;dxgi.lib;%(AdditionalDependencies) + $(DXSDK_DIR)/Lib/x64;%(AdditionalLibraryDirectories) + Console + + Level3 @@ -74,6 +120,23 @@ Console + + + Level3 + MaxSpeed + true + true + ..\..;$(DXSDK_DIR)/Include;%(AdditionalIncludeDirectories) + + + true + true + true + d3d11.lib;d3dcompiler.lib;dxgi.lib;imm32.lib;%(AdditionalDependencies) + $(DXSDK_DIR)/Lib/x64;%(AdditionalLibraryDirectories) + Console + + diff --git a/examples/directx9_example/directx9_example.vcxproj b/examples/directx9_example/directx9_example.vcxproj index 3b638b7b8..54cc2100f 100644 --- a/examples/directx9_example/directx9_example.vcxproj +++ b/examples/directx9_example/directx9_example.vcxproj @@ -5,10 +5,18 @@ Debug Win32 + + Debug + x64 + Release Win32 + + Release + x64 + {4165A294-21F2-44CA-9B38-E3F935ABADF5} @@ -20,30 +28,55 @@ true Unicode + + Application + true + Unicode + Application false true Unicode + + Application + false + true + Unicode + + + + + + + $(ProjectDir)$(Configuration)\ $(ProjectDir)$(Configuration)\ + + $(ProjectDir)$(Configuration)\ + $(ProjectDir)$(Configuration)\ + $(ProjectDir)$(Configuration)\ $(ProjectDir)$(Configuration)\ + + $(ProjectDir)$(Configuration)\ + $(ProjectDir)$(Configuration)\ + Level3 @@ -57,6 +90,19 @@ Console + + + Level3 + Disabled + ..\..;$(DXSDK_DIR)Include;%(AdditionalIncludeDirectories) + + + true + $(DXSDK_DIR)Lib\x64;%(AdditionalLibraryDirectories) + d3d9.lib;d3dx9d.lib;dxerr.lib;dxguid.lib;%(AdditionalDependencies) + Console + + Level3 @@ -74,6 +120,23 @@ Console + + + Level3 + MaxSpeed + true + true + ..\..;$(DXSDK_DIR)Include;%(AdditionalIncludeDirectories) + + + true + true + true + $(DXSDK_DIR)Lib\x64;%(AdditionalLibraryDirectories) + d3d9.lib;d3dx9d.lib;dxerr.lib;dxguid.lib;%(AdditionalDependencies) + Console + + diff --git a/examples/imgui_examples_msvc2010.sln b/examples/imgui_examples_msvc2010.sln index 1ff205216..e8e0bcad1 100644 --- a/examples/imgui_examples_msvc2010.sln +++ b/examples/imgui_examples_msvc2010.sln @@ -12,25 +12,43 @@ EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 Release|Win32 = Release|Win32 + Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {9CDA7840-B7A5-496D-A527-E95571496D18}.Debug|Win32.ActiveCfg = Debug|Win32 {9CDA7840-B7A5-496D-A527-E95571496D18}.Debug|Win32.Build.0 = Debug|Win32 + {9CDA7840-B7A5-496D-A527-E95571496D18}.Debug|x64.ActiveCfg = Debug|x64 + {9CDA7840-B7A5-496D-A527-E95571496D18}.Debug|x64.Build.0 = Debug|x64 {9CDA7840-B7A5-496D-A527-E95571496D18}.Release|Win32.ActiveCfg = Release|Win32 {9CDA7840-B7A5-496D-A527-E95571496D18}.Release|Win32.Build.0 = Release|Win32 + {9CDA7840-B7A5-496D-A527-E95571496D18}.Release|x64.ActiveCfg = Release|x64 + {9CDA7840-B7A5-496D-A527-E95571496D18}.Release|x64.Build.0 = Release|x64 {4165A294-21F2-44CA-9B38-E3F935ABADF5}.Debug|Win32.ActiveCfg = Debug|Win32 {4165A294-21F2-44CA-9B38-E3F935ABADF5}.Debug|Win32.Build.0 = Debug|Win32 + {4165A294-21F2-44CA-9B38-E3F935ABADF5}.Debug|x64.ActiveCfg = Debug|x64 + {4165A294-21F2-44CA-9B38-E3F935ABADF5}.Debug|x64.Build.0 = Debug|x64 {4165A294-21F2-44CA-9B38-E3F935ABADF5}.Release|Win32.ActiveCfg = Release|Win32 {4165A294-21F2-44CA-9B38-E3F935ABADF5}.Release|Win32.Build.0 = Release|Win32 + {4165A294-21F2-44CA-9B38-E3F935ABADF5}.Release|x64.ActiveCfg = Release|x64 + {4165A294-21F2-44CA-9B38-E3F935ABADF5}.Release|x64.Build.0 = Release|x64 {9F316E83-5AE5-4939-A723-305A94F48005}.Debug|Win32.ActiveCfg = Debug|Win32 {9F316E83-5AE5-4939-A723-305A94F48005}.Debug|Win32.Build.0 = Debug|Win32 + {9F316E83-5AE5-4939-A723-305A94F48005}.Debug|x64.ActiveCfg = Debug|x64 + {9F316E83-5AE5-4939-A723-305A94F48005}.Debug|x64.Build.0 = Debug|x64 {9F316E83-5AE5-4939-A723-305A94F48005}.Release|Win32.ActiveCfg = Release|Win32 {9F316E83-5AE5-4939-A723-305A94F48005}.Release|Win32.Build.0 = Release|Win32 + {9F316E83-5AE5-4939-A723-305A94F48005}.Release|x64.ActiveCfg = Release|x64 + {9F316E83-5AE5-4939-A723-305A94F48005}.Release|x64.Build.0 = Release|x64 {4A1FB5EA-22F5-42A8-AB92-1D2DF5D47FB9}.Debug|Win32.ActiveCfg = Debug|Win32 {4A1FB5EA-22F5-42A8-AB92-1D2DF5D47FB9}.Debug|Win32.Build.0 = Debug|Win32 + {4A1FB5EA-22F5-42A8-AB92-1D2DF5D47FB9}.Debug|x64.ActiveCfg = Debug|x64 + {4A1FB5EA-22F5-42A8-AB92-1D2DF5D47FB9}.Debug|x64.Build.0 = Debug|x64 {4A1FB5EA-22F5-42A8-AB92-1D2DF5D47FB9}.Release|Win32.ActiveCfg = Release|Win32 {4A1FB5EA-22F5-42A8-AB92-1D2DF5D47FB9}.Release|Win32.Build.0 = Release|Win32 + {4A1FB5EA-22F5-42A8-AB92-1D2DF5D47FB9}.Release|x64.ActiveCfg = Release|x64 + {4A1FB5EA-22F5-42A8-AB92-1D2DF5D47FB9}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/examples/libs/glfw/lib-vc2010-64/glfw3.lib b/examples/libs/glfw/lib-vc2010-64/glfw3.lib new file mode 100644 index 0000000000000000000000000000000000000000..8cdda39987fe55d400fa1def0738b4bdc8672d51 GIT binary patch literal 202450 zcmY$iNi0gvu;bEKKm~>-MrOuFX6D8gsNx1tuAza2351=%#lXO*%D@nEYH;EOlNcEA z;q3|x3_}nz`l>Nt;LsWdMqD`Q7y~1@xZjR}k(zklGzP{&jG5%+7-)(UCNMA!7QE#J z0~59IWg!Np!GrDXvnTq8p4RU921 z7+^|W9h`jqy*&I}JRQQ_ec~O1oZ@p!b4oIc6LSl4Qc=~qIrs&*cn5fTyMooaMufx{ zmnRm)C+Fvt6y@ijEB1GHck%ad^8+ge8C;NAk(v{qmS2>cSc0n9!@ z>F5V?qkC#e04PG-!0`cbWM&zLEBzhZ9G!f8JiNU@t^_9#P<*FWl*Fgylon@zV+bSm z101{@{heIA+!3*l8lmw8Mfqu&XerFu*}=)p-NWD44-v6w+KTd%N{dVKQj6h9*xALw z&EMC}*U1y236w0+G^G|BLF_|la&vHZ^L6p^bOiYd6!yp=3DItE>R*tW=k8-~nw+19 z(CO*m=I`p~?e6dH5T2Q5Y=o}4D7B<0Gqo($-qghz6n#Yqtv(L^E`I(_?!KPbwHBwA z*qauo=AZmFB2gTIG=fVYPmIJtu22BsC3;867=box2? z1^D~=dV7GAEJ&v#$UjBpiA5=(B#>K>Sds}2T8N1-orX@{4nEHQE{_`_fJzm3;TK$5P>^3#lA3}l4=NXm@{=7?Qi@WG zi&5o#6SHCNaV{+?O3f=ll?PQdPT)cqO(RGGRtG_}grpYbX67Z9z{~@=6Xa|6)RJ&_ zAE@IQ;^T`_6LTDl(<}@?0LC`~aSRL$AVz_F>y=+wT#}ibjb^WVY6(onu_6_>q*G~0 zNq!z~dB4QmRETA;V1yYPP?TB>4+prXV6w&ViZ;N($<4#v!{5^%dq#qlIpvvoDf#7) zWB{wA104Kay!|{pTzwFFJ@d*Eb23xxO^Zts^HLybw6v%=zX(OEv!jEXpR=2jt0#`q z3RGR#n_yJRMXBkT#U-FJ1mbE~mN0Pkba3_Y z^YwKM@WZ7OR!D*hfYcO(PA>;nZ$~eG7Z)c&Iw6im==68+b#@AHa`g4at}{75uPn8w z1XR?dq=Lc?MXQ&SkB6^64ol%$OEOD9g=-01tBbpXv%8Crlbah3t%*4~`N@eTsrIJn zIr&M6IS8Fz4qk4aE`GkgE(F{Q@n|AUr=gRpgO7`wud~00Be=kE2SvFLh;RcD;UFR& zM0kP-XAt2JBK$xE2*XYCckp!b^Ko|acgATDxV$m|=>lN~hWPm0#NuoR2fx&Gm;BPC zoK%nyIFp(fn5IJWC743ZFOCHTIhD@f6zZFwf|i+}#Tr-^RU1Sm7@Ec*`mw192WJ~p z8Cc1P#aO5mHeK$iCC;$y0BIhgnhKH!n;4LfSzfpynxVm&RcO8h6>VT=f>q&>$7V9b zshFBPGE-6^a;VPqOwP~COsm8u6_B5k<64%QSAypLfc)YT*W7}VO0XoVaY3oYCHX~I zZ3-q3U?6#LfT5ZQ7sl{yaB2y}*|=pe!vU@-1e8V5tjfqQhnR>e9-5bdBlN-(GfTjs zfEGj$Q{3{CON-I#O^6gE*fX(9hGiCmS`ZLN1VIZ=h(70>L|A1Tng=Uak)>dDBdEy< z5r|eX=&hc0Y<>YO^i{B4FiNYx_Xd9z>dz$ zO)bK3c1R|A9UYun0v3eUqt1>F&VF7Ve(nLT*aHgO{w~W*NzJ!6&CO2%H{W1orGc}v zgTGgRr@Onq2THdKUN;nj`;w5pSZIiwy(L1ci-W7Xt80K8az*N%n46nuZ(5X?TVQWm zoLQA>Z<Fn<6?&Sn7qg_D7Ft}h32C)J_1i0*X1hFDP z1PDW;7%5i4_5~&87GMONZ+>28Nq!MVZgWp9fl8s}0{7ICFiXqr5WgA;R8 zp$4M5Avm=J&2`Y?2F;dWWP3r00aBtG8#$&V7L=qGF(8YCmFrH?_DpF+J5SGp8iA$h88+3(k%X zt}b4#el9LJ(l=y;pgc1#Hy3kwz}elw%iqn_+1npSn+;jFXEq__ z>F?w1?&<)t0NhZ{1hK%~tXvQaOyKEUK_cAH$=$)n(b3<-&BF_96gd3B=79}J1Q`YH z#et0{$~=Eh9~U1_e~5XdAOpZ@44itv?Q(Eq$_ONZ$GlL_ypoXofD&j42WbI?hPYX{ z73JrKXQregw@M(g2vLw4kXlFv!<|d{?8)Qhr z;Hn%$F{Bo+#1MxUkw_+hodPO&U{L|`2e>41Nli;E&4IRMJTgJ;Es#3YwkJr$Jr%=m zP+^G2AcJ#YGa)5jN`5&wFyMB>g<+*0ihhu@Q3Npcg%+n41>|RfhKa%UAT=vNI-vmq zaSm7kQX>+i0Ilr^5`vcDNP2=X{OO#SlarK~oDDV--h=~3Bz7rqd|{V@x)Hl1EC}Fs z1mqWER~eL=R+L(tfn72Dgj-b9T*kZ?`qQpvQg8(cFOQ+zGF6WH={Nhx! z${tifCKe$?p}O6QQd2RE1PP*;h$H~j2hOojHINDw;>O^DoXirZfBP=x|ADvL9d6LUZ@4bu*_0hZhl`io&I0*W$o6N@UL3SpuM&qM8i3qUl&nn+;v zFb=pi2T~slZ>hmk95e|y`8l{aIr}*IdipwqfJS|b3sRFa(=tKh%h{=w_NJM|pdLXP zcq|E}q;_}kaCHmtb@KAS(3qQFTAXTcngkv+gBgKbQafiPLTfK@utU1-uHeE29N|c! zzWJag5F{?Z!Y)Pm&?YLF>z#^R4Eus?cFxI6&PLJ^oLrQjlLHPJNEr;V4@m%R`~VbW z&{7ylDX8az*6{}^1POz?uSjtUb{V+!3snId?*k7qqKP?yg9#FiNaK;n2@2#%s4lP% zAzHv5fVQT6F3|EZEx*X#v>*{Qnp2VrZo0vmpaxF94guaC0d7A2;2c$y3dsO@ z`SzyCkTG%4Yyo)Y57f|u>vMK-@bGeVa&`A{ad5OZEr1Tk+gn0&WU{?!YEco$-uz^c zK?sem4o>tRFqf*&B5RnQ)XUfNoHaWVj{)a)xq1v$=l7x z)fM5x#G>@l+|;}h@Z^TQX=+|+F3hXQRt7lxxcd6|_(QBjnsWioAtaVSJYAZXSeBTX z10R|M4g9*hc=~&KJ2_!!OwP#!Tk9C$iO>zV(#6ri&)410%frzXzs@p9a}}Y{&B5E% z*CoKm$H&1nD9AquG<6f|=k4bo?q_cb5it$%_jdKOHw|zM4t9m>^mp)c^l^80@p5zU z2Tdg9r`en4rsn1sRYD>TTvWlz8A#Ap!3K7~DcKbiU*Jpw>i0t2g~o-pszKQd+?WP2 zf>TStI#CibM#I{|&EL!0!@~hI+3<>KrMQVE)q$EDKM!QaC(z{A7W3#Kw9HK{Z`KEJf2pcHL7-p#?; z%h%J>*U25GHaQg)(o?ClW*ol*V)n49fyPAt^gZ_(CFjf zUp=I=gsy`Fi_;D+jQt`FWs%5VXd^G&2uT za+`uA;WmN_Cm&BAM>n?s2k5XUJP{Pzn}P<2AQR}tkU3R^Mpp-KZ)Xoj&{U0EKH6L| zBzJ&YVBqq*xU>MF(a*up)7`_(KfoWGjrn;wmG-8o6`7y`LvUpU*Xio);O^_?>Fnj> z=YY#fB<*m0J`P?!ZXW*5?v4(yWDbf&NKpvQy?zb>o<3gAPW~gVp^<>BXqs?Hat4qW^~x(04e&iQ$1nd#8N zxHt^dT!lsiHZf$?u>Ks%VjPGji1R)35L4pdAzW|~ju3-HX=(~s7}6R<9tQ`N=%DdL zq&aht5SFQOkT7T>95zD^7kdtR(n2^B4@L~%SgV1Fr231A|1|9}>1|9}(FwMxo$iTtC z!@$D;VlgtXGq6Khj11gh7CQqs0~c5xq=uP+k%5_kje(tk8LEqofsFyA7Gxeb0}EIe z7Xv#3CsYMU2R8!;ln1g2WDdv_kO?3=KyCr40%4Fm#3dkCg4_ub;bvfm+6i$VGuVDs z1||kh1`x^2zzJrtGH`=gj0`+b8loN~%gMmVz{J4908+!n0D&NPaWQa$c^nJ~2(g!$ z0RchoWdZZq7?{8i;%`>4%ht#WLCJO-vWE-Fo&=#_0XqeIgUDU`Zs6ie?ye#ix{s(1t$j=e#0&uY zQe&kbT}P3jH434*KBzL{79o2fp+PVhN6gV9=#LkZB#LO7L1X(DGN%GFZf-SY%m* zC`b)REkqW!9thby&?+(v-+=^CJclFzUu%ZB{Sq|$4_m*3qzt@o0yGf>k_WA1fv=mw zw%~w@>#D#j5FlO$uVnzQC&jwB7PL4C9E)IeP_H8|p@WK-7N_D^nT5~|S*i$LKRGZ9 zbsz<)4A0(|c4cc22$ z21QCL*vm+3rolA;R1qvxVFf>$Fu1&jih)`%P$sm*N0x;Ok++&3X|*!UvDg>*BUc+x zw}6^^Fip@(0*wn zn}^ZuMamcGQg~MJL+ypc0JxWct{EaVGIxRDT{{R0I(W?jj!{xKjp?H;KO}S_rm?vZ zcf4y|^c>j2ZoT}ZEU<%66@Ydj$7ey0?ZK(W*eD*dnG~Oj zlAL0^(wVub_~fCRMDQsAZLPp5pORmWT@J6onV>DL*!AJI4Z0#4tW6(s94Ryo6cpg` zWeyhtGYkz3%*@Ob6bvnmjV-|<30x^{feaT}SVAMU7#JiN8Nfgn%fPTp2%<`cfq?;+y_bX;814x})ZwyMfPsPGk1zuRj|iGNEdJ0EVPG&rSBK^g zka-~@3=Apg>advCB*MVZhprCIJP8H{hBYD#3`fw_VKMKK2m`}AbahzF;}K79DK^r)E{W} z1~4!%B#SdJY=)|3!V`YS#TghbL)C%Yhs)lNP&N4MHD_dC_$ki7U?2%mg)iQ6BpDbg zpz841I}NG^Vj|SPXz9fz|aL%hs%ASDrN;#4a}9`^nzw@Edv9?7HI|sLr{idU|;~52X-Hp z^3Pv}fgu`69oRgybPuw(5~>EDy;=+m46QN@4C|q4@!5M;hJoQGk~(bmg7VvUs2Y6s zg37=DG7JpbvJh4H!r5Myfx#Q94&**u_GUuWKumZ4*J)Pb`2BqG#-s)V&fr~?(bM~F}dN-uYbPzNeTKN6{q zTNM%yFcKUeX!%HnnSnu7m4U%g1ELC4wc{$UWHlKWG&LdWaOERVk>Re%z>o}82P&Vz z`5Y~s+AuIM(N><*a$KtF)&gQp2=r+IWRCV_;jvO0mYtA=N6R) z1_lO*Zdc>CKHVQ&Tc7avEn;S1@aUYQas%X(&Mhhv7#JA#fgI`48^Mw`pK>afeOhX zgan{M@(3XjsE`6eNCGOPh!B#23aKE36re&v2q6`)Q0svb_T$bPpmgH6Ll7p5BxM4U zYS@1elov{b9d|gPsOfapY1n@VB*))!hyfH_D^cWI5Ae6FVqjo6?rZ=u=jA+5O78W2 z@3;e0utCx=NDU~lcKd$*c94a?rGb$ zr}H2FZLYsNnfbT5{_S*T;os)^ztfq6f14{?r!x=#HdppeX950gu1uZIBK+H2nLC{& z__w*TbUMrMZ*yhsbXMTs=E~9Otn%$36Wr(D4l;t+V6S!-TR8qd>d}1I;r}tu|7ZAH z5C8f9-=iCnpFFxD`OCHSZHcKzx9@Y;?xUXF*TBK$(R!ei50;BL7#JB|%Xd52cy^z2 z>|}>{bOYmS8JGfiHuvm42az>8;L{Dw;@yxe?$PZl?qPfeVtV5dP!Z)A?-&ywdl*zZ z+A%ONurPoE3)IJ8VVKOozyPYvSQzFqFfdqxWkFE_s%cmljF}i1Kt&-7gBzR`0cT~y zS#@w0C{IFkEP;z{hqF$>S$E;A4{#PUGt4$QILisnN`kZ6m>C!#uJ>hOU@!-}Ig*8e z!3@mGXJKG42D7SI7#Kh!AuJ3nEHJJv7z@4^F;;UyEl_3#MFAEDffOMI4ijmxn?X83x|>m5S3u_p9nB;TmiQYz;=Li;4&W)E+7>kJ3urDV>2J3Qc{tP zL6}jPf&ByP0p(l4oXMWMO1r zabjRVcpP*lsRHN>d(f39dMP&X&9sGY}~K_Vb?Jh~@?8YLdBmr5i&y1O%&V9gtktkSr*$K{N>C+ffVt#fZBB%7$Hqd7fUaeQnuzQ z4u%pwnAU9v9Qj=jHdOIqh&eV_7%fv zWobE3!r=&RLu(v{CTCaxz$++30D$`RHQ*ozl^Kw9>&3vpPze?bf!8|nj0_BAU@=Wb zSZNK47|_@xhz4QM_!OjMhOj`9R1AqEX!-`12aueu;2Nv|Kio(mskB4^c1;uH!U)(T zTRi-Zo19dI%wh%D$y`Y}sgMEyY8>?BBI3-1DaK}=BdB;OPb^ANfF1UflL{@J6ri(I zL|KCFSVXpIJy{~)(LE8AQ=r|D*DS`Dj88)IQ1@vMP`&`?T~Kel103vz3=9nIU=}E- zK|`b<8iYH+K@7?p5Edxd+rVP*yaDO#c>D+Tcp11D7#KiFl!d{gGe(6Y+@tx8LibH@ z#_;I=0j66Il(4kkE){Ipe*lzLAED)Xvb_U345EjU3)4*bkTr3P+CTt8`Mr;KLXLxk~1l#Y?eZ!->VFk#-)&nJK z|1WredRrdd7hp~H)&nI1kU|>aAdl|m4Nx7j9^KubLI$FdA4Oy7apMCX2wk8-Ux+tA zRn}s#H$Y_&gaz^hC^3U*5MBayJjg>37RW=3z+%WAf=4wpMq3Y*3cw2J?#oa?P#hoT zW?*1g54ICj3PMV01qKF&bzm`&jmYB!plTVC!5}PnBb9;;kQgWxHomkIbPNkP zL}4XCcOy92fhsxBG{P ztp`eF(IvnpgE|>p;2v^~iUHV{9^F5X(v1`(`h}sIJ-RP|6}28H)%ECZhZ<3$;Q{IH zLKI73C@x_?)(mnpBUm%7Yyg$w>-l1VPh|f?Wj;Rn- zsNjJVeV5^4w;321AY!i>7#JWrI2a*=k1PxVj4)YKxR@z3>h2v#L1_n@yWMR0$$iOfMY|0--28O3#79$f(OooYp;SpF& z5iVxP1apBO69dD2uxuC;%+1wsv1Yhf9}@$^9k9A7OfVO$ftzxYiGkrJSoR`Z$2Yjx zKe!ktGXujlusVKbm?`SaFt@lcGcbTcn1#WI8RnKkxL74zte2UA0W=>4DvUvRAGq)Z z703`4s6ajf7K8PEn?cIJ_A)Ra)IeCEp5FzqYLF_B*-*t$m8j;P0;^PHWny400aX?Z z3?N+~9Uxl~CPG-C{t?7%kP4Ve5E~+oYBoeAtbqb=`axDgqh7$sP!2wl5Br^tpf(`* z?nZFW5PAnENC#+58EhrEYeWcG9q0s6(CO0XCL zZDWGm0$IWgTSg7PH4}$UxG?(FpKuAJi%dbrW4ZX#F~|vr3@9udfbaR17+fqCgDN=wmWhlE42|}nUZP|771!=FuH8pmyRSIz2DNib zjV!`>T=`uOTZHqLusAlKVC;4mXgyG(Xv?U;%uvb!>BYSkvSk8sxm~+Yzh-mX2};=A z?jo%RN;EAdgX%btdI7NdU5QN$46pfi1~oA-*fI$)Gq~`(Ty$(c!P4z6(R!f7#9}h2 z>@LxDWQGC*gJbvQZhw~MpNyq!E|%#W zCHfx8hyEWr?$Q!45j40D;&l471i(cnfktlKIXse2b-MHf{6FN{dZ0ucE;|LL$EDMy zCBU`yB$AxkLd_5J zYcLwxW$1yVa>Ot!C>uD&#K*-(9|jGTL55*LLp)-PpaIzg(83Tf3pDxwX(=~C2fA3m zRU@d$%>r(<3xU<`fOnihg*-o4>>dLH10R?LO8*d3>X{fAxWQteECLam#l*k>s$N+b z*1}~$gR~IYGoS%ku#W3Y3=C{w)K4AU}xZCRA68~z*@kPz#PD208-Du04g0oLy@4q5_EVE zF=hq1`cwgQ@gZnZuspLQLjigQcxnn-7aCNSSt%g&LdsVRMW9Q;kd+mumMFmPkwqEz zV*qalKvoJnmslad%>~q@Ct071GgupBl`ew=Xf!}CGbO)l6~q7kpm0N8Rtg#~WM%|~ z3M8ChB=V9{Pzl4#2wGGMlZDX8%b!3~-^`4lejrG0*Q@i544||L;(&*|K@4UF1qNmY z@2hF*AS$EH@1l2@OtAvjrX+6X)^lLFfXF(}6UC)u7k~8Wlm< zRdCv+8KG+{NDBi4c;o~%;lIWBWO7*$X^qGsQ4mu zfttP`U0^jR{sIlSAncl>C~Sq$1u6$Xy1;5s>;jE%FvIQIb-C*SLYE>a*@8+XP>7+} z#SapJhvD*T->xBa*+6xH)u7k~jw!HRASH*6oKr^V3Iz#4%S@2385r`RA`A=)3``8j zi(f%yFf$`)atP$71QU*_3=E*$1L8G6b%E4C#P&c%K(eUjfX2I-8DZlY4c{HT5at|* z>H?{On8OUAK#RSgwu!?Kj;+F`# zlmPeXLA4wx-cjNdG}(bDB`#VX~OX z!QlWQAd)7KBmx#fjZ<*0VFWEz0!bEoe0YQ~*&V72qy}QnLZ}ENjj8zfnSpeHFenV! zP)asXNy*FznhODG@|3ynjtJFtARz_@21$%i1-S$fs_n|NmrBAz^*B@)SPe?3g63aP zLlvRxIaC)|4alhs9H7D*%mSqZ5JL(s0`k3zkDm!h6of&(K=l_WO)@ir1_eN2A~w&H z1>r9ps5vqi{sK*HA^dghvs$PO++Pk*U0^jR{sK)WApEs>#mz4WUC~foU^O78GL%C_ zKpc?U7#P}7L{xnIU=>01XaWM13(i_?`;YL~Jg7PH82$o{t|I((A+TOk z9`3JAP+ed(DEp;nrRIw-b4YzBsxP+cH3 zs3{z@><|)PAeGJz#?uhGR6rFn0|Ns{4XQ5COaU_^Xm$^z>yyOZGYDOAP+cH3ObjYM zenzlt0189YPz6m9Ff)RJ9TX!!J@21Egz5~aIjR_;ss<`I;Pr)MtnOJ=c&P4x>H@1l z2~~BlE>H~)ax*BkAavb_>H@0)Ni(p6q8ZGBh&_JX3 zh*Y=6?Sz~rJbWsky1;5s!UweQ5TXm@4%M@fst8>(p}N3oK++7mp(2p74kUCHMFcrF zfqa1)KA>8XnGrPC0V;k>c3q7{`0ESQ932dQ>4IYr(pF($aBK-R*Ma*>1k~sQEtLnU zLGc%O`2aYzfLsak7ebdcR2NtcNSYxTDgyDBijSWmv@^m0ax18DxkW+YEXOuT6lzL&tJ`WoPy9b8LA7c2BqB# zT3Cg!tIfRs9YWVSs4lP?6uUq@b7n?RivpB>l+;d5N9Z~U)dg0AVwV*tUx0G~NS9^P zmb(aDPoTQMYEbL~t&u>)4k*EGeFDPmrls#AvDltK91_p6Z zXNUo^&H@8zMc8%W(7{B6u3J!DAT_AE9Kj(Es(C?n z@zuXvjnKso>Ii~XJu-mAkb5OgU|pb^7o^KM^Uw;A3J{xt!3L@eqz2V4XRt0%JquE) zlqJrF&{YW41yX~m%LS|p)B*(Q(oEVUhS0SFstcqBRhKJR7pPqg(p4*PCLW>dHdGf# z4XQ3Tur5%$5v1$3*iSozE-p~#m4Sf)qy|-&J6IPe&4YA#NgjTK&}9wP1yX~m3)E*} zhPU2juXCJ3=t_s`0;xgOt3ks#F;m7(i-3Wj+IgH&g_q79tXlB7&S&{lFmxY6XE* zOYbbYi!iwistcqBHJm{$Rc1y|ivpyJ&1uCGgsu%xT_80O+mW|MqnZQiYcMl{%1Mwp zQkLmo5#}&}hA0>q7(i-Jb%B=IF*AbNX&_xIQsO)ix~!qPKx!bimqA59YQgo6F{p$E z@j&s;#?Zvez>uC=f-!5vpaSj^t6-Na%>xbhVV6t>pX-NYAj~LJ6)aN88Ht&BDp;i; z4lu#33#$}FmoaW#SfwDk3~}qiDh1Jn#aGbq!IX)QcMtYR%uC5hEppCCP0ohhqU}P? zp~3O-nYjh=X+^22Fk_s39bDYKyxslXT^z#QeLy!MLdK5mO-u6aO+m{o22CAKrTarc*7?@F~tXR2WL1mNDQ5*e@H3Z;qcR< z;HP}x2m!3}$iaY30oWS21lTTc5&#`;3H2o;9Y9Zug4&G|^ypH^cB08af)ILGh>J4= zgkPSXa$c;P3A4;_u<+ z2dcU;7VAK&9+%iEmEx;Dtg!Oh>-&DY7(2kdfu>ww_5ggON{kad5Qk3)cq zi-&K3yPHFKdJc{iL#Scp;o#@&<>Kq(>kf7v<{Bha+j{^=i&)BA8F+g zs^Q)aUj9x#UhaO5Am?LWk%X?p!`;Qn(;bI;*N6~^dT^dY2@hBv!zKew_*kT%DU6JJ z79izJd3sK8Mq*K_PiApRF``~abs5wWXY%hFBI6Ddi2H(3Iy=yYn}G}YcUd@-akUP_ zDekEyF3t>G`o_lKQ@LOSp>w=U%?(W;YC-3CNrKPu;^k#v0IgyLb?lHAT!8qXVbVXK zu`>_{hPg1$@dB+_)rL;Dz?5M-#|t#PbeM&KfeAYG0P1Lh&nrMXUjSs37*q}1JkU8_ zSky^jQ-?H_3(^nrf*hJUu)S#NKtpYctPBjW=^T(gusU!x05S=JK|S>vRtAO+sF@&j z;Bykt&iw$XTLx7F(Fr;y0rOlOP{(=`D+9x8s9KPDxa{R*V_*=4P8WdGVY3&sOaL_H z;tW*>8ZrT^L-TJc69a=U8w0~8=&&Yeyd0OkKR6f|SfB%bxaGcfQ#2YB$=tHsU0;09HP%idPdun0E;!&Rs{Q1IZg7c@L1 z3yMI{Ko9u*2+VWjK;dl7gBUo1yAMlx$>d>RC?#MXXs~ZG4+Fz;bahzFJIcera1mV{ zTKWT-_nwD=ff+iK0}B^2&%x*hkCstz4hH7Ijg%aP!H~xP{y_JkH2(J|)A-+C`s~54 zb)owph&tfdec&^H%pnl_#Ap6UQ2Ju{%pY^=Gk@H{&-^i9{$bE07ARm?7(kN%pri;Y zcN##2l*1v=K@PCJTOPf#6`&2Ry|x=T85sEGLEFbct9rR1iz7Xn4|{l6->-RxwCM?C zE+{v!fcF(cSfIf|(10_@7RU~6SeXEt0Dx>eg0Mi@5i}SJI(P$V7gzHe59HG}TvQA^ zdP7tc{)^rK?dm?+dVqh*!R~_|-99P?@E!2YM?4OLvNdSbkA(qbD8w#X@aN&=?BR`W{*J|%p^j?!aaJ|sBHNA|G!7$n*h+h zA*8cGS{*=(ijzNj^s-uj0<-&;M=#GekOvYRciaHU_1c^OZR@|l!oUF9*kOF&3ZRLv<1Q*Hpcwiu`T(r1^hUSqlF$4Cpnzle%r5{6WKhDm1WFvBqybI? z-7YE`AjXAm*A<`nV=jW&2RxFQKl4Xk{>&e95Uh|t?gB{DXa1NgpZNtv+ChoxKXbS1 z8j$J}-7YFRAjXAm*9{;Vl)x?`8S$Av?gCsZNZSLCWZ@NzC9d7BTRKg!aQDC*gKW}tuu0v*E0{_=x?N9TGspyL&>0X7b=4tkX0^l2VgZ>2@+(Fl zS%A#A(CvB!L=$BeM~QQ{>y2*TJJ_6N12X2INAf8U4GJAl=DP@S8zQv&|1*1ZANT0) z1*Z_$n&Iv_Dh;3{)OZAxlH%iH4}%gfBpHJyHzCOwG~^Fql`t@Xm$0ya_fUZH9}5Gh zz=Gs!(9RS@atGCWkYvoj07_Jl|0d!fYv}W*J`DK0K8aA z7VdUYao}Hkfq&A$4j!v+h`RsGmdrJeyIWKqFfcHz5a4eCZK_G@=HN@#&JY!a){_;i%|AKnSa*VzCLeU^_GwYzmuGNk zJypW#k<5II#e(rQyGJtjF&0aP|I8N;dHz39`UspbdLV%aO&LDDb5uY{!m~SC!Lz$q z!?XKw{9({!C?suw3N1*A08Mj2SfDc#Ago+Q2JlG&Ag?kofZ8FjbO4$#g`@)r3*<~t zdyttyQiYvCC?%gk$Rv+Jh%t+S8)O_tI&cW~XnZ38ifp7puSErPhM-6CO;9!=M;~1OsT@2*k^XU;wQihEzbHlLS2ygCYkL14jwu z6k(XzAX_0iKqf+1pk^1uY>;^{l^`}m9@T7!N=a#E22RE#1}0F&1yafkIW8EIiK(^r z9Mlm48IHinE4xAYikT5qdx3J+o=K}GAm&R!ZU*Usu02QU=zwIH89^jSzHIB$Uc{^& zXl*S>6eNo}*9U6iAaqS|yiPs=GOEl!0k5(ljmM(QSj@;);o$mJk= z^qjOOA>0gFGXoL@twu+k83wgDAZxflI$Ni3?m*}Q&5wh0v17~(gW?)7GYne8#SWht zhON5;t3jC=29-DvT_96IYn>3fKnE{?M8Rr64Di-QFax~$06dBT{sN_U z$od*kG1`#*MjxRIw7&(U3#P-aF@ zMG1;a#f^Ml5I*&Qn#_ygQ_$)^gipWipTf@z_h~9r7g!C7Pr>Wl!7IB#O4@t=svvZA zf`k|t7{F@4D=T5C4&*{qH-pLrW=2q<4ocb8vjd9|Ze9m9M*zdkpmpvDH@|FGHWq-p z`5aUiSPhDsK{*ex9zpnB(N=`6uTWiJHDEV`R;hsk9^^t)H-pyWFf)S6T~JQ@{yy>$ z!p*XvVuFEzK^Vi$ppG5F&E~6`&4l4@wu0&ct3h!ysFH-FC{Q}wwdkrcLRSJ*7g!C- zDk{+04uoBaJCE=obhSZsfz_bc1zID6Sh00;ilQ7s7ig<5C^W!oQ0xM&D@WJ`$|(q4 zm!Nim)u7k~T3G|J3l#8w&*iotbb&SwgX{vU0Wlb)L7oS*Ksg0D7l7h|jlq(cfgvxy zC^s=DvntiGA`>(eS(KWX<6xYIdi|ma{5nO@JO*ge0(Pee`gJ`Bap;r?xZHuynIcIe zkFH{ohm8J#=k38pz@~p-CcrK;LAC~`8f3e0DZ*HFfIPWQ#B@8%T=biGusIMz4K@d& zD?$kdBuUuaJ_Ia+D;2V9*7XH4Knq9IOthIR$bLXbGdaBm+YwR2``ChRfcCk_-%Mq3Uqi z3u+RbhN=OX55m~&1vNY`OENGBfjZLA^9yjy38jzhJjLlxqrebGl28P8@wIF?9|Dwf5 z6$1mqXK4n8Tu^@rd|VIiTR!H?Ffgo!s>2m7phnqAs2Y&lKp30*K=xjhVPNnFk6nR| z3Bqk}qbvhMFH{{qdsjo%fb0ZeZ1#f25w^=RFqA`AD}&4fhYPrv0O^8YkUyr%F)%Dd zQU^8AX$H4FtT^*WvpoWXMJOhI^bWJbFePDaBnCB_azz~YA z4vTrk@(c{^=<2YTw^W{iVI#UaH1j~|=sZ*nB&49}6fIqWj%~dz&%jU$+U-Q3eA%eL zz_1sp4(?wxdqLrHTY-V$Jyad2u>%elGf$aM-CbFvLOC!RTvl3R1Sqh)qwH_2!s8L#eMO53=Bn3wIKgu^9Lv$)aWrV^bk-7 z+L$y=kAYz)x;iZR{IDJa!+EGWeExU~RRi(^2xIdHs6P6t$H2f0T8;xvFWCG6Qpc;$ zz#vUP9jJ+@s?WgS1XTyGkI=#obdFt^J_Ey1bahz#dsCl*;VD!dF8_kUnHe_x4)QE$ z4h7VYLbDe%KrC#)zz_jd3wIwDdvgpJ7%HIZaM=q=FVmoEpw>ce1w^wKblmYg0|o|G zP=!sPz2<1hz~Bp2htJ+@s2Y6s-eY87C^lqZ2n0<#GBAJ^yx_cLaKAAF!)d5GT=s(6 zLobaP7&t)_n$YxuEnR_zo`p>q7_LLrfzl5+U1165WK#x)e9-PvJmokjoO_{aQ2dLf z9X1t19p>#Zpek?+Hg#z62I`jIF=b%*0#yso=UDvl&y<0I3$&M&fIl>#YEb-vW-n-a zmw_1rLmgBtzJB~NGX{oDP<6QC4HSMCpla~hE6m8iaKns&;WcP?ErIs)N(%;tt+E9fo3mg(UO1-1H%DO!3w%z5p)0#j@wh`c``7p z0`2s~6Mmp}#0jVxsI`#t6fOKf<^2;3b(pssg8cCXL!AT0?SUsix2JkCFdP9jxCxY# zM&1kzcA#CPc>DpfHwLN(pFcodfD{aMnCSqNkGip`LyHg4LC^EO85p8Ki&sE5hT@5j zRXz+1+o0-jr2~+?SDDagDF{tOHc(A8lv@1H*d0~d5X4!&^F2w-5aL05;x zyr=*MhBS0_Xzl}rb4vgN!whtFSj^iNz`$?_T^$zl9t1Eje1WP1)mzx|FQ}dUFMxqT z5VSWJJV}jvyhJsSfx!@}4p+E<(!D=a4RU%Rb5$tlkYjI3Zbt(hL5O@+H$`hg85qE4 z!#kialmuU<0Xk0=yb=exxCU}-26hqXO=F;I)f8aLQ5RM^L>~qXwSi`NSr|ZL9iR-w z!T_ovK}nf~0aQ*wSfF(&pc!ly(6w(2pa=yu78t;ni@>4)G|vuMfCOQIq6sv|&CDPv z%EZ7{1X;NPYR7_PK#etKh+jcBg~0DN==D*tfH=4HK#2@!Ehv=hVciV!ekliBDfoPR zkPQ%*ftpdEAu<*QP=N;;qlNed)LnqM7BsK}b1h`X7bFg0f!qYD7?>GgM-GGI0pvFD zVg*n*LR~_f!$3vOQ7j{bbDKPK(3YWmk7J`U4`9)_S0lx%oWPPEdYB5n|a1G87`T6Lgaf|Na{g9{>Im z+^0dhI6&)5;TLOw@+oK~8w&#{EFmn=qCW@=R5C(XpxA)0Kw$xzt^v^?3_9@y5*rW} zC^kSRc%UuVhTr}%5IzL?1L8vn3*3 zA18n=2<;7&@aXo0-7De`-pt^^zwHL3zUcNh0G)R20;-)Iz(U<2Dn2gVJ}NFQpasqz z-Tk2Y?6`}H0VvUQhNx(Chp2df)*5>>pZX6;Sp3@#gG%!R_;!fyIpF(1J(`acKrYw; zl_o3p9u>J0q{jcpxFw@!O{-Fpb*2@>H%61&%nUo z+5OX{yAyN`DcH*s3z!%fj1Pd;V(WnNm;&^6RcM>Vr8`DN!$mtrMFF&bLEA+|#idie zlNl5!D0@WWqYr~BTu5kuvQ`&33_!7oXsv)I3_*Sc;byphAuN!8K`lXM21zky2KFZA z0!Vv>fdSNFLHHMXGQMM|W0)go!93{hCDgQ0Vf@Xv`=>ALX#C@iARmH;M)8^6bF9Av{DWJrX07)$RF5T%YFF_0I94v~2O4MMgPq8^z6bY0l!1(9c zpyo2NFudl1i88cxGeLtHbce2sN7r6{+(iWxmkq~VR6vVo8$g=? zG9c-$J4dC!r8`BXL_0?%!$mtqCC8)NA98`IPxlMZG40rH#(SyFh-gc=ba#V1-rWuI zG^ikr09_Ir(Cwm<0hL^y!%4Y26UQ857Br`zqKk^rsweY=l>@6iRV=40^eKI_p5 zZu~(U2fZxLqxEDdR#z+qUr@jbT2KhOkHF5=_~b6oO_;8|j*R~=Ky|xITvIsoO?&Jq<3&=v|52ZFZ`Ktz1Ik9&4s z^MD>U-+I7-f9kRBW1v)A0ngfvM?h)GG2SuGF&28%JZP~HBuRrJ2$GpWx0gT?_h0y} zD?E%0450lGEDWII=;wozzA7UmgR?LsF*1N}2W0^ts0=#bnuVdBk%0kp;}#3UB>4R+ za~K&IAbLSJtU#)etBec`5Y}5bOM!_2di$FZ69dCkux+5NFQ9|VSr|f@Knp%WsT`Ee zKy&3F8iYYtib1L$2n&?uK=+q2Ge|0PF^Dh=)WU~k2v8`38ss1vgwKIP z4-}#h7Rdc)z+#MOSJZ)93JM;Odrv&Ne;FSDmFEVY-8Vo*p8?d7t^Z5dx?NNZI@vv1 zZ-bd8pb9NU#R8P9;z27dz*oY8Yy{og4srtogD&}ogd~IoatY|taafy{9ei0HIDQjQ z>!bi^UC7#{$YdZ6+cR8$*Z zLKM%SQY-*oiZvfeKps{A9i#{;tw2>Vq!9ulK}iVWK~VJz@gC%6CWr??r5xl|UeM?{ zbO>P+q)G-g<3V1Bln9{2qX24fU=Epp@1Fr(Py^b6>DdkKRCz!nKm!p0I-m$Z9vtb8 zQOWRVKH`Af#sZ~qP-D6|7!?gjjYf3rg0d8-xyZr*3LHp~fG&lF#5m|4M^IctE)2n!ToU%_JFL8HMR2S zn<}6l9HglN>Ze2U324s~XfG&ammVZh>__Q=fR>1Wk^u;VZn=SkB!mSDNlwUJGcxQ9 zyob;m29OgXL4(@Rf&fzP?gA~VffoLtfkDXCI?zIS7iho}LlRtKf=2pasz7}iNKipD z32qLk%#Mbd2x_iDtOF19fp6XcH3nqCEKpq|17?AI3+khQXb=WnoeS|fgaz`sG}!0x zMgr7tAcsLM!|+2eo=k6t3XRcKrRAd z&~7V;s~{|ptMstB3TiE=Ib;Gh2^x$@;ucVG-U$p043I(wstE3C&}cuTr3qRJ4!S}F zdi^Y@qX4T}KY|jn2dF~r{sr+<>wyvrkM2HDCIRIT4~Qrz)$*nB=eekOeCB_4;1j>1j+(F;~NsDpr!z1@Ef#`7o?Vj0aQYO#xOySXJ7y=V1fFHAr|Zb zkT`?|@>C3143;MxLW4nf)IodVy*VlmJsRKqfcE`Bl<^UdPFHrH?jjE3Z?4@xe7awH zbpLYcb*u5{^=&u4rlizO~cWnoanH+bW4oa1suKnOK z-Q%w785sUEq;q76)fss7hPH!7 zG`dfKx`?1#i;=sDmyJ*QbU%P7_icSrqSYPF(#;RKM9#JQAjomh(j24{bV;yh_Zf(C z;{z{24g79)m+o`?>)lye57Y&K>URUr-Y`afc^3u-{%ubG`L}s7IsQL*@F9ms^C1@Q z6a3qp{v3SB0cQLKGaNfPz}mXmL8f>%A7Jt6bWt&Iu|83=57d73QE>pbB0z)(hzI}? z5#25-7M&$34lbQFDlVWVSb$Gwib_PMiwZOcdUl`j>~w`qHGuYvgJRaxvXleX_w{9m zHyRs{fZ`3&^^J}_44R99)F+@BY0$QJ7VzHJ9B>xc%fP^p4Q8EYU|;}U9LmA~>Jnsv z#Xwh^W`J3<7#SGS!K~$s3=9x4(50ae)-gupt}1956UdDqoCi*6pwtIpfl^-@SWHr# zi$Ri69<{4#zyxZOGJuXIKy+0hg>T~_(5!|>_s!;CtmQS(D{(!N4|Pug-4Dm$!F=)m zBk&x|YsFolnT^*{yFgPLuZ4Gk<~CmQ>;g@0yk^}6n%#hBJoq$Cr!xnrlOzcpHrWa4 zB!M#|_%>&S=)>TI3(1`@HOvf*;Hy#@U~2e5`4i-8Obn{gAaf?5K4vR81W;#t>cF83 zDj{pZEKq|F(zgP2?W@3Ipgt=^4Ak{)0h*wEyp!SC*KQnW9i!l9-nQzP7!z zs5rj}b1VUVAspy}y3`bfWQaOYLGID*$pPvTvq5qnxNHU$a1+2D1UU&5@gN$6L03pZ zoCaZmoYoI<8nhD*Hq(+9H0w}m(^we+Dw9i%8+KNJ7S)t!d9+?C;rHnF;s99$tw+JB z1TzVMF6ssqx{$gPw1g2-w1Vmj$fO*ou7HSv+y-4d0b(-D2D=HA%pok0J3(27nE_UF zfU>p(sEw-N0V+Q6cg-C@2`v_s4;eg~PyRPP04l%?JUVMsEIhh@r+r%Q@%^GluL)0#q*{ugkWjtU-1T2}tlk)3I4_JEl0gahm_UJwVPU9Zk=b^FD-3zM!A)M9& zrK(6Wry-)4rYb`vy07m9&2vI{5E9{*?h+LP(7nkPpr!)Ed*J&Y5hDs)!3h8{q5!JV zHi5-JvoVkng;E9vhK*n`(4BOUoB(PKgZ6Z@fUis529{mOz`(E;%mR(6tO2t?mC9-` z3zYUD=7GvQ&=4I9!&L^@klkGd1_n?W#{#|@c^O#8M+OFlrC=7QM1<%C#XD#L9*73v z?eHW3VS$ps60jJf2M2>k2|I&x3L68L2?uCwApn}AASY{s2GBrfL@OlcWELdlCl;k( zW~oHbG1`eGsS4>i`ALa63K`%Nz`@rh;?V^gr-Lhjj?sZ^#5!b$6ost^N=1w>?c_u+ zF)$sM>ah6L0xpvZFVf+nIMQM zpreH#MaD!1*ibNNXc&?vLE~gcz@~soY>2u|@YD$^ry=PI)SH9Ig3{z+unt6;1f?&~ z@C}Ft;Zxvr1uAYJEKpiI02V_lu@UJDmJ*O+9h3+{L)>&NFjE`607oR8l*E!m22g3+ z0IJ6r7)phWFYRPRNgNu7J-Qn~1qi6HJq+qTUSS07W&}kxB(Ok^2d#bt(I5;O6^E4X z5EjTImmwa3mG7XbbC1p(6$wxos1WWL0&S-@ze(u+WqirE`=Mv|3!mB$flY!Nzljk^+j=$z1`kV9aD^t=SQo+U0J`58rhtE2TO|_%Lks8{-sZoIrQ8l3 z>p%kCS6@rCfY$l6zAa(%X#UGoDtHX6k^$i+&+a3R{M-L{bf5D$_(GujI{)??F5QR0 z9(3tG+)=b48Gk*AdP*`gFghiFMD*Kb8LJ7n&1bGu7Y*Ebc3mdDD1xK(tQBQ$DpI= zzzSWBPom4ofZWpf7jzeG=^k)H@FgeAG|%okp50eG4*nMK=sxSx{i5+P$Xc*TF5Mr% zt~|rSz~IuEqoUx_eHavG&3^?-wOox)?h0XqI^Wg!q)YeVT@j$=65Z#(YQZMFoXEn! z(0#$9`L9l?ic7EWRj?>TwIgU63|Va|3wT5TtmI_`3p^F^w|cWMFr+y)|6$~B1>Gmu z?G|Cn1nRnK*n$#QiK0ihA81Vze~S`GS2t{36U3+T;3EYg2^}KB3s!Yh^}~M#1`l0^ zkDzSk3_9zt`GrFXmq+st1OC<xEHh|c`sHKa6 zp$BZn%l}N!NJKb`31kt-Su&0PSwU=eu(MwCHvZ=Taizd+aOpk`?$APt7~=ykw}Qqr zU=H8{JHXZW!0TSH8zzC>;A(u}W!3-x{~4k#Z(iwGC~{Vz&2palniYXlPmgJbtm z?KaRrNg99Nh3>=JZJ?o(H2%C3uQ}5k`SY%(@#mfX%>V4tXZ~j=VL72;AGqP%IS-`P zrE?ufd#MkO{%dy|sIWioqT&E*vmbX+aRG%bs9Ou|yMn##(S7b%8^}~fSV*4%&2EE= zN{BeD6ZLWnBLhPkfA~p{gKq^qy3g_NKMHa=$cdl$<3N=NTxAzT1d8_#^JAbP!EZ6nA{(9-i2+lOF#s`{D{rBjG-g3SRR1f(if9Pyc0hPm^ zpwlQp)fH%9%)q1jtPgDH*rWSg8h>7hib)!Oo{x$F$f+PlfGu@3e&X8w$G7!c9rCGs zkTE+)P-zRZ3>0X+5scl?7Pd?GX~*vCKHUdAy3cxaLl?bybe{(s>d}4PyVK<<10+9s z{y*aQ|G2O9vzisI#!tGZfL-g`eH0d(Aj^flyM2(Jf-ZArVE_%wfOsqn3qTD3aFcc=XfY>vns_q<0|RKbjD-Qz;0*)If`)xS zO>7p1S8!R-cow8#44TXU_0L%t+!+}dM43P+2?Vn~Gcqvng4Ka;jphckKqi2ey0I`Q zF)=WJIt?rgpdybGEDJhW6e5<$#J~WmY*-jTt2Q8FwQ#XHaJ}1^7{E(oSr{HNF)%<( z`3Yz7GsDDG;VdIK%Z`}=x}Kz*nE||vfrX(H&ic#@^V@G`1_n?y$;`k6s>Hy4<6(ih zUYv!2;U75c?N}HX{(@P_aMpAWU_zq@0g|oQW7#O~Q#rWA67(RkoCU7wuHU@_GU@=FyY&aVO!)vfuAsYk3OE9aG zje!AlGB69nEH(y)=U}mIY%mwxgR6T7SI5i_)631yzyRr(NwUMbZI4}g(??)dJ39lzLolnKoq+)&wt$_1;Q?6e2s;A< z4>%T1urn}#8ZFEWXV@7SKy3zQh70Tr418eOE9?vmTwvA>b_ND!FzXIG0|Tf5!OZZ0 zoq>T3EcS$*fdSOUU}kv1&cFalzsw9TI2agyfqPMJI2af}?NMfi4;%~(f52j2I2af} z2h%Y#{NP|<_y89B!@8lJe~{^ zOaSpfi&LO=Cv>O)J|qTG;{X~&5Zc9xypq2YG{fKP13FzB<|_xPCzTopktAb7_fEs(=&@pQi~KI ztG^VIa}tY-;cLL+89W)B8T=VQ1D>E^Ob$?YTmaM^mjEpnQSj{k=?Pk-`O2gFCb*%{ zdY}|^plziOXt6zfv0n2JrjnPXXxKR!oWHj*T&H)XVmZ*S-8{-dy2HrvI<`6C?F+3>s~>rA9amU1!!*80@6@4z68n#pbcS=7GLXu zl6df>6l4LsoJY4TD4l>7Kxx2&!J}K+qxE*_hu30YgCH8wnYfHEUFOkk3u^RwwEpLB z`2w2$>s+G(wxe?kxP1wZ;+>#032O!K1dX@yZ@+QyH9y2M{_P(QzTNq9~2>s zrQ#6#c7eLQ9^L0by`3DD$Qw~I>2%+7vLUk0jH`w+MdfAL4Bi;78SJE(gDaWdMJakq~O zVnJ#592JmvJsOXIA}jtdXfP2nr3Tu74;r3^Z1IA$Q^G+zQo(r?v{EY^%mOW#4g<3$ zF)%Pdbb!hLhz?LH0u4N}Fo5zgWE;j!1_lNQic(o5`08-iZBDR*&tgXIzT2uSfIFqn2oFwm)Q`NV6#I&G0XrqAEX+W*`QUrkSR5g z`5=`b46z&4-4KHpCHTEK&x^=u7xhWX?_E(+dxC8;0YkmFlrJw>42um z%)u;>6`%+P(IA`*4ib=c5EjU>phhUP$OkQ4NY2kK(92B8FI&X`8pmR0Kt5CvRK74X zf~LGcrXjFiN@`MRx(evvY)~thfte9hG9ctZEX;GQLCGHEYNbnIYLLSZLFz!R1JTfP zt&z6Mf@Bb9y?)v1(#{N8M-Ea9-XRHMfYqR!^$KbxK+doQxqfT0w;e(kXd^yI7g!C5 z0dA~=8Q>FiK`c<_0?{B0>VY$WcVvQiAPf-!Wm^yrgdrlJ(S8sQgdrlJYz*QtfK5gY z4Nw>`GlEv|f?S_o8@&e+8e1V+7(gdxGoze*3u-(dLSw?w9ocN~&;U(+fHZ>Dpo9h} z#!>GoN9ei)(gNLH4oRv{p&}p(;tSAHK@bmwAtIpe7KjJJsAqbEmVQA_F9-SS-i-rK z5dM+_MFs-{11HAa@}N~s2!CC4d>g|F_m>V-7g!C7zrd$qGlF~va>wEoH@_fsfyQn? zqF^-)$RQ8PP|S>=<`pOoCdEEGh;U&z)Gi(j7lOu%5H6gsd&zkoxC>!tR)f``xDcFi zQCx`71)8-7xe%-d#9){JwH?Gk4OLL?W@ZHKBLVq#N7c4Igqs&Zb@7AUtm5MbS`5bk z+UyF_#m1oG;|FS6f=}3oi-77T1`q)k0Zp!g7ns6DKvQ7gUA}M;(3VUFP-OrYF$7r# zT4e_kfutYM3@6A3AdKn@P;tx52-;u)%6nWHx04aR0L^NFbbwCYMosgestghG5xo;^ z5oc%AYMS2>x~@TWfz_bc1zG@tu&Z5p_ELndH&9(* zH7It0*6Sh4=Rl+6aW|0;@ss7pSCwgdwPi;>(=*2B9kl zstc?J?9>jZ2#5pm*KD{5=nQs{_%;lY3n(JUxd6PepAl3afo!*0Wi}h((??KUN?@OY zO#TKH!K|r4;|$DU8$`A+@0dY`EEzpi-W=7BeBdGj(s_-Na;pQx; zE;S4{gVvKG-0Zxh@QxbX&E-&CU^OUi1|OTi2#S4BIN$%ZKN6v<8>$Pe2INeJ1yB)4 zID>>X!$m+hQ0O5Y4+LtdF*AZvEJ)o!-G*k63J{xt;UrWSNDU;lu!1TTh$Of@%D^Ci zB7$r(=xj)4Mo`TQ(r|0}{PhTv)u6gSY9J;jKt(`mAtL2)5m3rRHW@Ui&CCc|Pz+N2 zwR^TH!sK?SE|40CIftMkkkCL*y`Y5<%#5Jg6{K>)0tOaD3_gJB(!q#9&;}7i3_cD{ z_tb&M;5(=;uo{#Y1i2Pb{(#z12wlveVuFEz0jvh(B?d{T2#5o68v}zbTm&2%NCygm zdJW8susp6;!aE1y3()W_$P9f*+Zd@P0`1yC_~Jy;9aDX{FJho}fz_b+0u)vVUtF|2 z%8$@h2h{~u1G1E1Ayfp!VFI<0K#d^~hXLef)Y~^e%_m4(9aI9e_H(o#e6a&+juD10 zKn5aw0cxuo!F_QVstc?J#TTGv7{V8zxIpOo3e^Qx19CIy01dF4K`umfGpO;#%m~_H z2a5Jpt)EUK+$;g=A}}y8m}0mY)WAcyx${{klPTQICQw~qH7ITd4Vgi7fgA&Bw;*(d zLv?}GfTS6!p&}p-IOIXz0dc_l0Z@GbJ{N=$H2eW7TYRf}k=p7LpypU$_yQCx5ch!M zOZ8st4hy(1RzY=v)u8wSd@cziti{+M$NCPT>oimsSPdxTLBR`lGsuOgZU&!p!U)=M z2P&d=TJZTILjEn(9BT|W+kkd6fo%u5*|KTNU2C|T*+Gqd1_tov1ZEUBgH~HXT3?{> zIkw`+5`-=ds4lP?kefk?4eVx+3sKz+8h~bI1nsc{*?u-W+XmrgFQ_?o7;XmjF%aRL z^^mQ{4({eus4lP?6gPvWybyKV(!zDK5W3o-y1;5cZia_5$c3nG2JLiUW&{n!g0jWm z#+MujH?M-4&no=GadjhK_JIABE}yt3h!y=-dy~a7O5Q4%G!#19CGcse{8A zGC*kq6wU}; zflyswH7ITdxe(ROptEh589{r z)u6Z;beaa@z9f!U3nw9T9f0Zrs{x1a3#bT)11?DnLFFKb2XZs2FF<7oGb5-q1PTqm z!_$y%Q2GWn#|!KWkbXhXU;~JO(YFHalR%i$VV)O=2n{8uE^n|o$hA3WT8Ehtt)*uL7B~V>pHDLcu zfr@}QklK7PhR9wN5fvXlcu4~C7iu_zPUS;{kN?t=XoOF%K+W-o_!Oy~0GePy6jTo?Q>9^zMLNP3!#e*H1Go+CI`1kkU|x-FA9+|x2FCq4}^!R zB2*Vx4N9njhB;9~6`{)+stc?J6p##QP!SLZoHF4d268iMh=CRjK-!`pUp(1(4rwH? z25L?S*zX|IW&tzq{pL4;2g)Z{1(e}PUML-?!nOl@Km++S0my1;5s`~_;iAyOTv zO^eXA6{-uY2JF`BP!SLZHPwOKjOq)}3U+2j&|W}L?b*6Lwi)4zS5R|eF?<2qc8>7H zqLq5LV&T4E2MvFMrs_d)f#M5ry8>kt6roESstc?JR1+D(s!xy$QQZt0|72zaEg=9U zy0!Q8kwQKIYEA-%n-f9qftRAQ@*iwXfV(*hstc?J#mz}zU9ev5foYLt2wmM!U0^k! zz-Cwr6#;QTse*yw7>3AA43Re&B7ZPMgkhaja6ZjV%`Hv^-C+!}2<%hPcrUEh1BDN2 zh$Vx40ov07GUndyGoKK#EDsU_AM}e}LV}LLLB#S|&o}>);UVS-)dg0A5@MhmSrKU! z)N?`T%7W?wt6@OyFN04RgZJ@SRH91}{pBf8T_826_m+avEi>pg4RAPYW;!2>&~+ZF z3#0}T7o4EMX|PI=Dit3;aH|qjbArMLJVFl6@1WKYTm+m9L9JJ~2&kzKKDQGt0_sG7 z52AsK7=rqxppgTF2*_yA(hQIYGdP8V4FZQe0|RP&Wq{)gG+qiSDR+zB-i(MZ38*hJ z!10b;W`gE25b-rnD{g%TJid&fy1;5s;wuYm7qs!p04iG$xGPhgz5sTLGcA> zk{prhK)yie+7HzQRs#xoaGZjC0CFL!n?cj=%#5JvWl$UOyY1^K2sht@nv;j&W>D>h zaC42Vb4VWC&Htdfz-mz33|i0w=>dV4u;4F3=w9~6b(oVxQs%! z9kdvRnGuu&K+?hO>2DCWi$HaO)IjX=gNlIEqUQHvurI*b4Rj3l-?iHj<|IIMfz&WD zEx*kGxfz_atkl>ML_=w`Y=kx6le&+;DVKFc; zfYd<3&;=?29Z^IYO$99`U}gl3mx6*OWlr^NggHr2T_80ObLK!rKx!c(n^8nmeEeY1 z!2k+F)KCRQ05c3IjbUFbuBWOt@sO)~Mb-ozk3tgx= zH5g;CwcuC=HK9ObDJ7HhoNM5|uz>0Ut3mMvXgL|A=L>RNq|MoH2wh%KU0^k!atvI7 zOlD^Q?=%Fp-xwHTp=v<7L1E6oPy`nN)$btj9t@E+7$T=JM4rM$Kp_S)=NnuEW-=>i zm;odOE&)IcDGU*H6cH64KX7TB%!cd>8@L*f$)L6kXvEeBt_Hbm0qydI^cg|+2jP-K#Q?KA`rhD7%?!sf#x_+ zzGh%ZfSUsg=W+~@ZVZtH7$UncL@r^7ynu^<+>AW31lmZ!%m`W<2qnNzPoDnAP zgz5sR0q0XtG6We4-g<&s&bNVG2wG?f%JTvzLs=1F$P8NYz`(%Jh7pGCU|q0s{^O}R z-EHtNl!fX7t3e4v(CMQHH@7<{e?jQ7gX#jS0lPH;Dgr4tKq(WH<3Lg%H>3Ije6B7d zXhA2aDRJo!E7E*-3DlfU3}1jwNI;|n;n_#8cEWwp1JwmqgW?O&N;gQ^3(5;C1aCDV zbghNz0;@q;9RWHQ8DUqx`ihMRUFV>>z-mzJ0xhye*yW$@x*wtIJyaK14T@c$ecK4T z*ndqsgU}@a>R>T2Fo4yd*wqh?Q&4dU^4A2jx+@4>hEQE#H7It07C<1IdH0P((m0%3$dblUeg&_he z0^)$n1ehlnKyGGZ$dY7WC-l>%^ml>;|iY8|yX6C7&i-OW)qKXk#wdkS{ zwFX$#qKiV*qPhU;Clo=5hXPVlvwc&GixbmR!x4!CDiV^Jo63-ySCU%fR+^Jj3{KU) z`6;O|k7AXA+J#LHVr6h@2_#j55?_3JPFi_DPGU(~eo?M_YKd=tUS>&t5jLr?%#_r8 zu=QX~!Koz(k(|`TvQ#ujf>i}U(kMb@dTI$s9mEB}nN@JlV3B}&1ycs%5yzCQ(qgDz zK$+XMf&p@#HpFmPD4~i$%|sCdyVSWT6_oz-^T5+*5F1>I64M=%lT!;y+%j`giy7?g zK?ufEWb{ zq43O<)L`(L$|%~wk>LUna)!kQD3ylh z6{SLU%t0)22Je@Hmd#*YI8;Eb#-jw{4up2F(a->dWe%v5Aa=t%2{sdl3S?`sD?!l> z&z2#e*}l6I&QQcK+OlS_-CrE@TdTa=n!lwX>c0<$07)^q}0vH%eY$q&gd zKy`6w9;hJ*kw%sA$V^GaCJqq;+nt(%HM66sz~&uPB@iFEraVu@w>*nW-sI zUwamVMUqin4lz6|vp6#;2UcZy7Nd!R%4Jv-2jmx*xaJm=RJxX>!dto^L1=3Rv)qBS zKEXL3(rQ9auSg28`5)A@hc}}k-iI{(L-HX_epDa9+vd1zL{)&zMidoL8(}Sekf|sh za4aausf2g|+-$;@VlmWUvlU$tiY<^@8Db6AgoLU9oB1dzAijbKfzpL%UP@*WsLKYC za7oQcElKrH%0dW1)H-FBJoT_JAop{YbP<@{Z|{X9HeeGrWy=#i`Trm!Iq6rcP-40*{Z;RABQesuEa?fm>&oHo_A# z)?|Yui_Ip4G)ig&3B%6QgtQWI8jh|Emn~@OAf9s0$u9oJ`eW1fZ?M;(m)0_NI_CNMVTxVw7V}PJS}1VejJQ;N|A& z;^*t@g55{Z<0#>tg0|~n1vscUh4~gw++kCOE$*Z~*l=Kz$EHPXrbM&R!0#-i}`WE-pAi6Okn$@d^)3@E}nEIDsIg9M58Sq`Ku7 zWRS@l-#m@P;1^LC9prYJ04-_7-wgjlh?3S6AS)2h?3hI8k6oDE{;C2*9KCm>k zs1kWNEE$~0p;ZN31*ppn^$EBW3muwp&PdEl2Q^4?6N|GQ9Q;z#UGhtla#Ep51gtbT zxhOv;hao<`C^a$1!NkBc)c^?~xeQX;x`F}+YJEsiVsf@`era(kv>5{m53r#SwZ8cv zPeT<$t2yVyf|AmrR3vl31~}(r!gD^TXu?qCoRL_BqzN>H1x*eGrO!Rz_b7bw^U?!Kijczyk_KE7LF0BvCPReb4HU3Bm3_XQE?yknJzCU>wiuql8QC>{>(jsboF&K_>q3l!MM0c=PH zmhWL^!aDrmGzuCR1$h)cB;(}j;N#-v>+J90=m4q)u#L&YgCsmbgfocn2N8ZC0)(My z6PB$Y#TX<+VVNB4MeGWY0|BcFuwKW!#GJ}1SaycQ5KMJIeohWJIm1V9ja9&!uql8I zm*P|aX{#F%G69bQhzW*-Ou(Z6VuAr76Ywa2n1Iuh*a96X7@?(ZW^qAcNpc3FhXYPP zA+XVOs5ok5gePW}phgCYBao%BIRZ%@;s}rc%pxv*Ljz+4Bw%P_WM*t+W^QbbB&eXE zU}#`qW@e_KU}RtpRiD6>(#Fkjk%c9cgN1n9;-HBi(1~>*HViv32sj~6v4g}x+mHI07#Pli=Cl|<=TfBeFqCz!)^qtO->E7J#WkTCfEY2W=5H#8BtpfbKrf z_V7?<28Lp&S`dZHeG{1(80LZ$5OCjas2Y$vKp5-~@TfD02f?7VfQOkG7%oHAf`SKZ zFPb{gy5{H13=Ch;)F~(^=)1VOIfnX#_;@;5DftG6IR}L(p$hu@xcE8xx&|vLfYy_O z&f5pgetR%5f+o5dT&!Y3bi?zDvSZvcOFT-GVn8(^n9w!WGmI%NN(OWEQZkETpcP?E zd1jumQG7{Gv0i>s7K0UojUecNmkZz<0rSfk;k0jNa#4P9ep-owMv$h0e?duRZe~?x zUb+IPVUd}W3R=4eI`$lLOjIZ99!>^^<{$sD90CVEYhL5udy(I_OOGNGqZqqrGjKZd$1T7K*$ zC};@~a#;Y9VTNxy@ON~dfH;5%6ty6Gz-myYvq3hXPG=)@fwujFbb-}?7!07zs9*+U zG99Vp04;`MW(1WTAo&$f&ITeD#(*}$fkZ)Sm>?xShzrG_aAsftEt-J}Fn}k@K`W%d z0-(@9o$d$iXk}&uML$SRW}f;sMEJl$mL1|ka8(92h5?i$5aA=KY?#RopY8|U;R;d( zR)Z2gptwg3AA~N@B?%y1U^O5H1L%}AFax|O5wuti#sj$-)fb>WW{^cDpb+Su_COBd zi|0^nTwq^-IR8Kd6r*l>0xiN~W&~wFkU2#;ov#q)2!PgJfX;t|n*%zt4QdPn69eeT zB5)N8>Sl%b1fw*$;9|&iEld!q3u6Y&)xp=*)79I{(;0hn6IKq`n}+xV+nZ+Q!P=W4 zImM7JJJ{rq)S}$Xyu^}JbVs2|AiE4j22%frV}mqFa*9C{wuw2V z&~6H>rUq2IV`)`@S}Dt!85piX)q*H+?TM6AKt_NHMR3gtDl!Pv+OWe# zK>9!!TdfURR;0$lz_1-^9>{!L_Uf}TFj#{M9Rl`7Le+rm1YrkIs|Tq}0*QfgbRvd2 z2M6RueK2*IM5-&qrVg$30os&W$;!ZR0;(2N_Tlm`3mXH207wA=|LQ^2fZPkhVE>}o z3tB#E#>T*~391%E;j$NW4)HIL0zCGD;t6(m1ISJg2HT4zoK--D97q8aI|w*9klES- ztzz_~ytS2?n@V|e3)I?buvGv>WQi!~+)~)RiJ+TS!EKfQqAx%fV;lf;KmiJBvao`i zNsy)#s9pq#K@vYG4?=^80Tg7Ah6{uRO0S@@9I4^b{6+)G*46_hK^`ER)A-+?JjM!g z7UL%meytN8tp_SOKJiC@bTfS7hnz$M(rEFCKkncsenD0ZRt5%03(KcFM#aLXQ`P`< zlL+XdF_?OYfeZ-MAdk6p-#}Iis&GK9L>6!h4CF0V@QyUlnJX;dGv7c}Gvo+TkSye0 zWk^7Pc8)^CK)b_0XJD}~fOac^#8??XdqF@f$WgZt7HDNEgaryRP%#3cK^PRMkf4LG zKtTsuG>8bgKPx|8@=Xc=ZK-2mVE6!|osnZy2oyxn7zG83!D~)Pbb@@X4Gy6+{`Uty zdGc!=28S;w9WZ?2j|2xN&KL&;2E^H*qjw-IP>T*E&cfgZI)R=6bYeWnBcQSZM1wHo z&>K)Xfv`ZHf*ha22)lu(`HclMIr3|ks3@fIYkVjH`vQ6+G{_eYNWS>QA7=`RdRQDA zpG@P||4=6Wi9hB8h*iw%0lN4JWP5{0_lZv){5r?@HA++zJeUvqXd^|v1-R<~@(U~Y zgm*}kg0>!l#2}ZeLRg>!KtOFp76#B3DTo-zd{F5GqCpsRBnTw>AS{qiK}+zN85jka z83Zzz7+65NT|r729yrsp6!EGe4ID|lL5rRq}W=2p}0hQh-ey>AX zmJK>)0Hg;II+esBQ+O zP-aF@&IGyH{6;3yfk&`2l|cu6qPiJ03WIR-{g(f~`Qg2(NT}^#H7ITd^+O@LK#q~o zte=d~1v)YkBnno8l3GB$aD-2fJzl*L7F!Gqlc08i)PVbqaG!$w#l`@-MlU_JBq*^Q zykr!*&;VHk+J`_Af^;4rb1|t!pyi*5dC95H`K6G_5Kw0V+zraiO)bLgF+oJ3rh+pn zLNRpO#W>B>z|6=bCB-PsFwrtC88#hboR)?(8Dn4o6E`u&5C<)jM0cTE5ok6fFBv)s zfz*#d_B+@~7;?z&MVCa;5u93r(=@moHq&5|&@eDDMwxjsV9+-Njk-emMj(<J6%BO2wP7|22_B7Bw-j!PYQITv^SbMY~!<_I_@z$1A_vz zKmsL1TrF)a4h9A@s5(&10&YQL8J`V-s)0EVtPZV(Z^6vK5W~U1Fa=bwF)%QI_M_mk z7j!sC8>mpi)4~Vk(j`0$3|r9EVd)WG;$dL8hprCIAD|(@KRgT!0-z!b*>G3i! zSfQ&!GY{0b12t-Epz1*33=S8x9tg-EZBR9c@Wbrsfts$m79XH3?;WBH3|pXTL4!rO+;>8hf#C{N9jf&%_NGA9;Imhgk%1vcjDcY)sNf@z?%#_uF#Lw9!(}fh zTS!VUFld4z207la=FddUSPY=7FToN-!`y z1u>BGC0cp`9k}rxss<5$WRJjrc3}EYJOYyo*)&7>APj>;ut)P7gNB_Ip#0*|eX~T> zqxoQk<4#b=%GLOQ@g>lGN}w=+4sjf7hNx^lVi0{8lvY8-DM&HoCNfwEfm(@>UMPeG zO8uZhpP2!Cb#V}r0r+Md(CtDBp^)2t!##S}sC@YO|G!7$8v%9(2ISjvS{c|t7dSrg z=>F-^>7x?h(y0gOGere@Yh~*J{ua===02TUR6N)j7{0YG0VM3ukhJS$? z*$NT{*_{G5`8b5n3>yIg8G09VYvlx2>%XPqj?G6|Ji5<$CSUb9_=p)YNaWG|!K1hL z3+z5opY8{s>!`$_7gZrH%YGREx+k_bL?y+e7Zh|1kh^sthJddn_UJwVzc~_oZ>R_2 z)>P0{zZX2a&w!on(S06tGk3R(iibz1%rS@&p513443AzHl@yQe(;nI>KBXn+n01zpUg0C5mV ziG@$^YzsyP1`yl82VyZ6T|S*Luq(SD@yAjk;@bMHl;5M9&7<1~ezh^OT@Nn{`>#GJ4VF;6#WVR55p1%MuO|Uj7V@0 zAGIFfZ=D0WJGa|KCBUZ}lHgoAEnYLbbgFxFAM@z$1*LEgV@Q1Y^v+QMWdYCbXrzla zV;y7SV-JJc6QE-kSQtP@xPiK5EDWGSNI<*dSr|aA2#6TyIuM8$=+Y0+I0p*@3+P5x za9av=JQC<|3l;`hMh5VdGz)_sBjj*s76vOu1_n?&jfKIRk%0j;62-z04QFLAGBAJ+ zpJ8DD-N6W2x52{D#>fD^V1k7KbSot2&~g?A(4h|yRwok!__!?=hSf} zFX3Vm%naaLyI2_5nHd;BEpk|S0y-c9Ql3Cqpz;J%C^LgEu>h$8ZC?h_pt1;|2Eqb0 ztwG_&%m7jaG8?24gdy^%dO*Xh%nab$fu4Zx<^k&hsRr2!(E&0M!UENE5VJulK<0yJ z5QfO3nhjAYX~fN-nDUxI(c~3_BI6?lp$`HV_zv(CaDz_I1ZibwU;wq>Kr_Y63@!|w z48aTm3_c8w44|VA5wri$<+TdM;N5Yc^#G8I-hFzTKtqonjR!%LkM=?S?SfAH+gTX3 zFO+hCa%t;<(l@P__@^8=3@U~dLc>5;l!0b7kqg}x6$VfV)P2*l`-eyOr@ePTw}gSN z$TPm=(tQ-1Z#;UvD?nLW0a9T!pZcHHnWK^dN%S7A-%8lJT~u;9**seRgP8@L>>k}c z5Obkv-J^SsiU-J^#v>pH#K*-R2DMlrNgOoT2}#bN(;GpyF zr_)76q1*L?M{kIVMyHF4O1CTcE;F#f#lD)_cqAVN$t!sD@;G?(@|*)pwjL;9 z`+wM4zUE;!yY-El6i4eLrRuJ&PfA!_nV-C7bKCdMTM5WLCF} zib5yLxo#H~l}?v)EZr_3C!FKxc2UvkbUDWZnkDIUIVaE!x?9cVoXCH6P=V;++kM>l z64(hK4}d-H*nJh%=dGOo|NjS%n!b)l^MLM0hC6V86>s18DvZh7-SgL7z94>J>a>(bpSaDDKH}ERd5mlw`%a_ zD39)6`(Wut0hFB})et;8fiqGGEF*QdsDKV_cIlp@at4%6dQ?EC#B{o|bhoJ7U|?YI z>Gc=z>2>Gv=nd!SbQf{ylm|xxdQJn^DvS&ap54(3p54V7p52e*4}*FnkRV3nHPFen zkN^YC5I_0AY79b*N(|hf zqwqjlFmoL!v<%o#8+|P*3Sg069=(ATSlU34v=3?n-GF2*k8bGQ+PfeH7wj%=ey~c% z9iYo3pdsVW;n6!q1$18~s;~f9n1z7>MYspz5~LC<0OYd9BOoWogD(n%gdwO}1WhnO zCT$>9D5%r|&C0PbfCjK3)g@@YE(2T+1b8{0FiV|}R6pAyeQWbJbi%S%eQWcC$ z&7e#AKo&8S3L9VA$;iOS08YrzwTK?Qji5$0eAX0nbQ3FhSs%pvAf2GT8i)pAP>UVn zTnG!~T*x6&NVB0D4WOY|2Anp6TIWRD2%3F@*a%^PY=j*31Gf>>k_RP92T)yrRNJY*G0GDq-DOIw7r}Zhrx0e;#Ikj?NwxP!M;!i*&ZA za4<43H2>r;Vr~8@QN(?`1uUfiZXS78fLs^=X%D#?A3*Cqw;m`F#mG=b2VQeR`qhjZ z7(po=>|vzR2GrvAXgmT68RXIiG?cX*oW4QF-+)?3EZ`duLFG3K1L#~|NCo(afq?4N?ih5P4KRpfV5I=uUwoRgf-_YLKlE9Uv1SEKpenF&m@;rV_-4 z$fKGKQ3)v*bs2aWHQ?nUD4;=RLCQsFPDHe?i&IM!%0P#ZDCB|;L7~=UIjAlLxfOvi zm#KpC9%x8r|CX!-$e=MuHOOBe8Z=psI&lb+flL8{2ISVbosdIJdxLIL1L*>*L76xN zwP_JkfX&H#dl0%n^$tiESPh8506Lc*%m7c8BQL`Q*@-&+37Yg|W(0NNK;wjYiwx%> zd;uyMLFN#eEWdqsR~KU18&q6?bb;oOP^bJsDFm|Q6XXur66LQ5U7*q%qzkMDWnvyQ z5snD4uWruA5V|gcv_Jvnyanmr&d*R?U^OUqf##GDc72>z;)AdY zbm25eBUlYe?10icWbrR3CAbIv^g`$|1qm@QfG3_oE@5B@gNiV~7p11dMPL)VjTj=J zi-ke9gD_~QnSo(8Tn%U`G)R0cTm)v$K@<_>MSq}?Do9*_bXtE(dJWUVz;F?&3#0~O zmmq`!odgWJ-41E!6;xg^GlC|SK;{^IEel7OqX^XnQUhVeKq#m=ARSe35tu&E$(0}( z5Qa!Df>0mi);0wSk8hw1{|rHPu~L9;}N6ve&k)M^3vLIEa7f?xov zK}k`do;BobT2NFdvWYD~=u&~|0;>UefWaLq0^)!d0f5GnKpgO{3RJ&?W_y?!L0u|P zzFMLgiL|&r1!|5kI8>1r*MkQ25x%&+Kh_m-Pi8$-7g!C7FF<`3M7~&8AhR5yYavt@ zSPj^%N1!5zd~q8?H&dD#utZXAl)0o0*XQg z1_m(Y%04mwGNTS5~1cuVz?PpZy?<4<FXYJ_Y#;)u*7aVrB%j%|YcU z`)|o8giqf>O_ss%DR@r{e390(itr{GxKG(Z(agXAUYdtm7k~!}QGANf1zH&h@*r3Z zh{50mH3!5&T}lNS=78LO1CrYt>%0Nva}b+>AsMO*qz0S^L8BXBDUeT5{SIn@BAwOE zeYzFl_xVtB6fpb_YRe&F8FW^+0^IMLp}N3oP+}QWG9y|Jpk-1BUFV>>z-qv5eFYT( zaZr5$axTw-TRKt8L-4>VJO)9&K-{;<4=Sqh+|mhZ8-QE} z@&!Vd7E~9cZHV030l5&>&7fg!W=2rk8C3ce%zK0s@@`ObK(}a?B6O{U>H@1lu?tiKBJ5gp-KY+s>j+dASPhC@pjJPk-1wk=p$ehvE>ss- z4ay=m@FHIDou!}{Tvn5G8j*LtLv?}FKq^vGP~#D#5S$B;?-KyUARB`hI|F1R74$?X z#3_Q%6>i`)TbPo_3$rj}HvJ> zG}@kI@S%I)BNK}mR3JO2@u>jMj;o;UO2%RaJ{1r%aJv)P_t-pw<22Q9(0QjBiA5p# zzNI-OnNF1@phFfwEAWucEQFl?13R+^yp;(WK#0x%E~#ai$*InX1+Y`KAluztoDuu! z9UTHZo!wpCy_~@N>0Lm3a9YL%}5COu_UG(773s6rqbawFf3h;Dy z_xEssbQht=Fv1Qpgv`i51VcmI>@A^2L0pFAJP}AD0i7NJI$s6CbImKwg(et?7mGnB zb`pD>EJ}QN76&KhrouxGwAK2?KS( zK?hnDGpOLO9LW%{ZqTmY#G+Jm;oyRt%o3-70BG7l3SgKEp=Vnlc^z&B%9>Q{3JAFl zQn(=L1&{g#CFU03G8{<(4#N>Dz&;0O5wMtJQBh(gEK9hjmO#=FSPE<-SUJos!Koz( z8ElCFRRK1)ps0W(fnZEqVFzfqIJmmIx(2u*AD{ttfxRhc5Y*ljGzw~O3K|BrH%&^l zH#KrVIReKqC9$9cu}~P4q9Nyi7#qQ*psvIw2lhN@1u^Ut9ArhXd;$#ztWsFahG_$v z4chz&OSiDdg%;GPQYd9OsuZN)g%-`IQV?BOr69VnI0EWqOc_|5I664{d3pG`2e@M2 zWm=qCVs8o_5VJQ0jff$YkGZ-Bi0=skzrr} z4Ge;6Y;xBfgF4p4tUCrZrtZU=2Ot}v>pqdX>LAf9Mh1pQ>g z7#Kc*dR*XPP~7K72!Q%3Aj6>;ygn3ZFa#tFYM@A9sKZ=`3+i~;5upy$jSVA09jKd; zLxeg|N4bLtbs&3Z6QK??__dKpb$f|W2a1N1M5qG|;#?*|9jN2-hzNC{;R_~^XF!n% z#SQ|P=YD{8(TVXeFoZ(Yg4(XQ($z#B28Ov%b)a+$PA_Qd8$q3#-B2}9Ya!>Cprz*? zRtAQ{JPZu}pm84t1_sczRk-YZEylp`9Tb5C(z7UNBm-tCXvZ{Y2Qiwxpb0n7~l zwV=TQT=s^FGcY7V)#3ARJyZ?MYH+xq*}Ig1fuUWTfk6k9QNWWY(0mRqHeos;1FInt z3=9cSb-3&W#c!Pi1H&YAby&>XAi=<}2VEUnyn)QSCBeY(4qY7<^LQi~7$iVrAb8>f zlmyJ6YGA&@7A~N9Gbc#~hCfiXps^BM@u4Ecz+eCx`N3l^$RB=CHTdiWUFel0#lUbE zsuq+_aoOuA&A{Lb8au*cFDTt-L)GB37qo-2Sek+18B{H3P#TxL88QqEC7^42`? z=wv;?!oUDp3M+wSf)qT_3>Ek2J^|I!%?sAk3mWWY@aSZ{zye!`>wzwH1Gm%zgjBOF z$Ow>8pbgsmEuh&|k7iqtW(NM2nV=coW?PVY2L2Y%tvDW_8E4SUIl5myK>Si-gvHHZ zIk=mDAZ+hs1r5BR8^r$AYPFB!v^bL&2frD5-Yy{ai4{FkYrYu+(Kq(wF zg3kipK@S>7WMKf+VxZAf7Vs)h&=p%O;FX$?bpxPl??FQ@EDWFv&mlTMi&#K|H!KXG z>!l%LpyezOb)f6@AY!1U6`)}#76#Czln^n{&Q*vy(Bcb-80dr=&=4C71L(pah#2VF z8;Ckkkb}fn85S}yfOqS%Fsy^JSQ+-fS(h0Yz(*{xFo4dAf%x(PRF;L|4FdxMXaJRk z0kjqtVlrr+A7nBM12c357YhRyBg_uaQbdS4ak!WqBLf4daAaXnVT7$>)rQNOGlGWw zL2J-J)ASI%?r_;qMg|5@3yFmxo{@n863(Dp4Qfq-Xb=XKe2_H~5EiJU08b7vz}84$ zOi<_KC#EQrXXfSRDx{U>fe$(^W^gIb^~82wW(q?&LoP!iLjgl3gC0W)Lkn?MXnVL!Ko#n(>+s*i(LXd9m^AoQW;7aiWyQFiWrO;jF1c|$;?f4 zhwfm^%CB@!EeXgkcCBE5v!N`P)H2X8O*jJ{pXjCJ*oWHRJ2 zWCeZn zSwU<1c7PURr**QPV_;y|0m_hRovffWe>*@fN$X?)eVO4ezetf0w_9U!-*b+Ur? zRqp`J)Tec_f|dgA0A=;GPS#r>b3iUi>tqG3`rZNZM_MPV1|tK*4rc}ikiDQ(yu$^; z2CZn>0a`1Y*2xOWEjvJ~*3vpzK{;XvXfty8vu{|MrK|8Q_fDWTd z>tqGxn;oFVnrWS^LLfDuwHaxhte{0EJ3#j|r**RGfW$#}3a53lYJu3GA|tuZg@)u}rVp=CF8%Qr`;bvMV>j#iHXnjIj zC+imw8&o)@b+W2~)PPpTq;;~s0*QleoKNdyRRW2F7E`BnvVH=IgYH#N>tqG3=G*}q zb5HAJl>n&$6>Vvqtf0KV1C*)LI$1&Md3TCR?yi~J3#3tt&>#@q!(1^rggF!f!K>6 zVOs)Xg9@m$PSz(Ncd~*umvpk`F*7ji;DxZ$Kx{?`8?txLVv11_Wn?P*PX85#D)+`Vk6ya%|tWhAg3`9*3$PJ*1BCV4Zv@>7_6GZ$O z$b3*BrFF8}fYg8jAgz-%2&7jMq9z0+4hrnFPF6b*TNxq_DkFD*5@1>y*M*o5+Pt&_6oF}-tP?=upo6>8I$1&c-FJW@C#{op3P{`#qJA2P z4T_MoPSzP9wlPF}7Km*EVb1}vLF+NnI$7s|*k%y%1t2!4T1e|;T?Ar-R?MY!vMvF! zEg@>QfY_jw8)==aAn6^TiXyF(6%@ofK!KOm$qI^w9pMo5b)c}7hOo^*>?jBuw9sY; z=zsu_UXXYML>%PA9iRo!X`QSMAaPJePwQmO0I}I2YT`g_P-aT&WK9CGIU(W^AT}tX zKxqc#PSCMtX`QTTAT}t{K<0qh&JgvWx@-q10@FHK<3QrB5OL5dyB(m&1ep&K2UUxp zGznsZA~vm)73AC3)gOWJ7X@n^GK@CMvi3Dl*fXY@5@J1I9iv_&(1i}K9kPsHAY=W>rIUB+P zts#Z5K%EE(3v@p%gav9BLRg@+au6111sa3}T8{)_fo`dUu#UqUDxhWzMC?9X>@}PP zTC)d{1(gU87C*d+0ZJ7RF;Jd?ut2F5!m@{}1BD<&43wrItYo-sKAcqzXSKswli{rS zaMo%#Ydf5E7|uEmXWfRgp2Jz6;jI5~7U&*Wh^s(bi6AUxCRoEvAI`Fdv)tjVU^put z&dP?f%HgbLI16+XEW{4b?Y9uta=7efIBP$gbsEmP4re`vv);p5zu_#W7x8bbkaMouy>pz^u%?k6IIGm*nXMqmUgV+H&N)N(v zhsy@TS@CdIHk?%sXEnoFpw=X42o6MpFsKa%X<0&8pq3@5J%!e?>;`xJK)q#Fa1jSy z2L1m+w~vZ}@uk)S{H~|E4}v8SWgp0NP%8vPgD|Lt1hEOi0@(y=K_S`HS)w8k4%#1V ze88joqfht2P8Ssoq+OUudp13if3zMbe-cXtO1ni6Fzf4})bOmVo-0dEmx8sHn~b zvp}0FAY!2NcR;-y7KTX-3=E*LKakf!7^DW`eFzKW{dn;Bjv{C=pb3c20PgpKRD*aB zb)fMy2n*CVgKWM4HHtyzgH(brL>@GP24R78r$WqTWny3@$!w5$AoD>q2t!OnH5=jz zMlKcxt`trNt{}DokIozw0nk1q2~hkw7{7(YA4u2&L?G|L?aWcp0Et0&-$G(i2o&x) zDiI#tB`OIX%|{#{(Fq!@0!3#4B)UM_5atnxSYCL<8XtJg>;Z|z0FQ1|TR@!|&?X8N z2GCdnBtAh)e<5PC7#P64R*?T07(io|pfCa9DscFM#33wDn1i-~Ff%YFaxf&Ca53q%n%QP7UDqy0@NXgh=CRuLGm!Dg9Mt-V*!r@fv!1*Z1RDq z19e$JfyTn%3vV)kx_b~YP=GJe$(6tGq1-cOcRTn6e zLY7j4lpL{sFc+Z<)O!Pog4Ceu0!%1(@KOX-@c{p zN9am~MjS{DsxHuYFC@M|rsl6mZAa+Z2-O8rgQ^P@{|H?Q>eA;Bx-LU?fz+Vt0?nE- zGlKjJvg=J&@Op%x`v=vj%#0wFAj#Nmk2DeHXhU^@)IgX4 z5DL2NA36Pim%f8aZ;&wzX_bjf5#}U7b%E62IyZeDR1HWws!u_Khma+aAUUynOV%Mw z-U!tNQiFPSBxvlHnGrOE2ukbnXRqrZ7PbC?>H;l~N6m4dIW$OIfO7an$G0(vh3@9Kp;8YMg@Rgul!3u_D|I8czc0 z04;P!bu*|^L%7*!|C%twl6BBX6-XCY4N55in(ab$GeTD_)P-O*449iTkT*|(26UMj zLCsuHqSH;j5Q%W}RH!+G7P_Yt{CR^|vJUDnf!qw5o574Y zL5O+lSA;Hes4mEob>wXtpt%!7oHiAmibm*)gX#jSL5Wk)kRc?efIP7;IBg?BS1VK( zSPe=o172zlU&tMCv*H&**BYoUuo@J*z)Q`+x%CYwt*P@C?YC8exMO|kOa7{LybYuf^cR=P-_%qaQl@;TSN?MLd_wxWIg|s znLA?fIjBnsvJBJ;LQQp`xiUzog5()&7R^QI%7NMiRs)uv1Qh{szzgr;z5uxy)fb@J zmYEUMYy_3#b0$h#A$+k0Y7U`A?8kboJ|dQF?}O?B4XC5~0@Q0m%{vHP*P*(=YCsNW z_y`q2Y!U&T?GBa#FXRTXgh2%>hyfQ-#}ILVi-5{(6(2uC&`cai6UgtVp#f?cF*AZ% zhoCxAWYvBNL}{F1xP<;xT)_~X!Dl;z!NID{X`Uh%`4#cNOYZO3T7DQXi zmc>096sBMYGDv}%W(*AAZVeNIA3Fm>sApbDNPa*`5d&xmflp>qQDRYMDtyH+njmzc zBC05Ck)peUm%p2%0g+%eIUp9805K5u`#ShL zy9fBV_&Gb^nRZ3h5AR-k+6oCk1 z5Mcx&2s_u;!NoPe%PAnh0cm;{q!sQVUk6uj7bhowA4doHOs{JNiV{m77iaeXKX*5T z3Wz*pfiP&MxF|o_F(suawYV4-Q2`E4zW%P>t}sooX=A8P(0W`fYw{f(TwT0e{ajpd ztX@S<7$zw>;P`=ElLESd50WY?5t{~F9o+mq{e8UMUBS^0j(KoY=YbpoP6J>9Pf(V? zE?j{aj+ErF$w1RR7AZ(*fo@%a7*xrST$GwvlIopW83MWu6P}YWgrR1li-Q*dV_hZy zUG$7c0n|v`D!?+3tq!0~9>L(_sX!N~f;K)dKrMjY)`wdeWQj9DW#DyjupKUhOoJ|% z#;puu8UYU=2LMi^AW??2l?CO}QTUdZkbF=OAui^Gm zEUF+*1DOr77iIqqC~v{`1b~*uqgab7fov6u4A_Yv&0hJH#U+`^*~O534VTp&xPi}uKYxCJ92n}wz8xa6=&w>L8BB>&los)I(T?^xj6Yd zI~d!W7}}c{*qed}l28LoZb=c1H1|6EiEX2TY2-GPC zkC@?JZ~ID!f#Dle9jMO$UZ;w-J{Hvb7ZGM)PyuzR!DGJAb@kw!3vn)p1dWF{2{SPG zp{qkP57ZaR5oTa$Kv##wym`V546D%9p_vEjrJfLGV0eJ84vTsJgc%sPKn_6m2by^x zX$=tu1{)9qSsfPhqC^-N($LkRnFkvGYJsW&g%b#a!x?FO5F`fbqxYbx!?iwku?Pdh zdZ=1l@dmQ@EL081d=SQE?^QH)xa@r+!octYsurKUVxZv;kcCi;%U(G&b-3&`6=h&> zgsR17Z#+~D)LN|T??K_5j;0Qmy>+4t3|&yQ`0QN)RYS<$4QT3c*?U}+f#EV#Ek1ic zLe=227c?UB6HOg1dqu<;7!*LmP{`>XOM140s=;UPX$Hty*@B<|XMn86#AWY!aR!Fl zP<8nH`xB}LpS@og85lrk1bhVzO))SqfTnc7_M+uC&_1W-G7JnZpeYan=b>+sWnkC` zRfo@gcc5zUxewGId?L%hzzZ7ofsTHF-G`-oQIum~(1ohQXRkL@4L*B8!4WLSz>ot~ z3mS(3+lv-1pmDbbIR=JVP<0@Cv8e;~s&~jSFgzll4m80AS`2Ii8n8mX{}-um3vxFo zTvDKFKztC!wr>YyZ?8N9!*-}zT;PMYkKKc(;1M({fgVkY)4|YWc21U>y93J<9;>})>fgzHB zI?z~cxgrC@Qgn4#{Bc;3f#E!oI*FBz)%2H z3o;K}uA!9&pgI3OO$LVjP<5ag6RHfJU1H)&iI*@r_d$E*5f}lzhDss?H;*7iN<)`=xr3=D5T1Lh12;EOzQ`B%+=fx!qm zC4tLcQ2#f;fPoCyeNh9-z&Ppaog{+b)6DR>pe#e*jwR=U{vrw35)nqf-`Hb!UxAfJf_r5*Fi2|1Wg^ z_UJ85;g@GA{oA@ZnZ zgL+NO42lvg3=$<=46G@fDCVP@3egWr#}M;DJ_OkTG8=>;@~GxRR4O8^QU&P(smA4Y zNVtGhz*K_R*vy8ggx>!X09t|R(cSm~blP+4ffA!UEk51Yv=~=Kufy|Br)L1AyFhoE79w z2n$4l@Nrg9E`YE=c?(qDA7=&S0*Dx>-wZMj?}bpoQoV7HBy#gaulR2w{OXJwsTa zC8rS90_chJ91N@AtSxXB=yF|%I#6_hhP6O62p55qGbl(PERcsmwj-hr7HvG>Bjk-Q zfupSPC!+upLw!Vvf8)Xb|Ns7P{>jGQ4%+wSk$eyuncXdoAPYR05B`79DGG|Z!=0j_ z*gD)P3JQ_KouZ(4I@~D=+E048Qxp`ZhdaT;e1{uOI^k3fk{^xKk9Aa1M8hf@1n`rzmI{_Tf%Z&_ddk71(=@-KK4L1+83>P8>+R+GMfi@^ZSfGvl5Ef`}D8$X6 z?UJCQ378o``{f|Apq+~l7HD4~gaz7}31NZuRzg@wjIetmGT|)H)>BA`*Dx}Gx1caH zfbO~hEvRH>XkmohU&PGN!N|bS56-=y^SD6^+nE_a+fzZ8jWaWVHl%`*4>JR33o2+c z1TzC@(UkpX;Z6*I#cMg|7Zf_i3#4U7y7puGdk z44_S?puGdk44_>JpuGdk40{+E7(jamm>CX$E;j(X+R(ww@P?6r0aPwBGk{tGpaUY9A$JlgK+7tR?wh58h+0M=8eC?1w4N-< zH@@W2co3uwUe|yt91rUorR>HhA?$8eP@C2Gq=)rk4}O<}pqnE)!9oyeOIc9B`t*XS z5^!;{ddYn}q?i)g6*VKzA2GSZNFl;MOW+(*{HgRAxX}pacM_1V9BK;si8Mi2=Iv z2vXHUSRmKT2S*mTU1h{%0BXfRgAVImA^h7MdC=-UP%#bh2*?Uh(+xy}FzBcah;Ig8v=xR0dST7aDj-d708pv^}t4ud)tkVplc zXaNau(4I)p;TMoB0;;D#=@o>pgR=uj9Kr&n*{fhNa6>;C3#zWv%-Y@p@0_-+)H-aiVu-fiMP;Ccgf~q?x6I8c>nf%)tL3JODeHGLN z1$nBw5mXU^g}WO;^&glCZ4M&)p0ZXUXl*ViUqG&Uf}|AC786KY2GlIs*c9HVHEW=oAOg*#^uEpaVQW?KfryP+N-;>;ljs5ume8KtrPp z44{!DP!0fLkb5EN5W)hbL(uUmIMN}s`azBfk8Vc;a4ca9RFDqX=&DvaH60z^9wbQ%i8aS#^BaiG&u5RM~k9b{Ohb0Vm5h1X)x zpbRKs7!U9>GN~({+BXXS+!4$C; z7l17RRecZ^$YRhTDF`29&FkR030HFhbgC1#2FGr|kVB?6W<0y$3U#OjnTxKki3kW)aNUxZT}K$j8s=BOO> zXnX@Y0S);^Vpn-+Sa*N&=nk##{)yhhdFjN&z|eYI;TkBNZ+a+jd-$-PVaPm-OUObY4YjxUEb;Xz8gG% z=+PN^z0>t`H!En=snhj)H!En|snhj$H!CO_I$i&Fvw~XGovzH?tf1)VbY<^8$UpUf zB`>If+Ud&O%?cWL;-7l3*%ma2#?a}?-^~gdgyNs-I=|T#G%UlwKhZ7|b$d5>7?ppj>!M~`(6Adrr|a%+R?w&v|5Vq-&9;#XRcFs`&br>LrB6xK3f)c4mCx=HTE11=N!=u}E zIjDhek#^j5J|p8X*F}t-)e@b>GToqkR1BTo3ed23R)L1Svqm>7XmqaASqH4S)7gN3 zo9p}zXAb^tt_wSyIr+D_F79yV;@{@F(*9 zhg}NUeY*8Pi4s@|$WLHK%YhPJBu=TJNB3#4ghw~Tx1bX*AineH_LYa~6%*TanNb_FqKY9G4zBaJ`rM7Qf^F#9wAvy*B3 zc^5wM3wnEe=6`nS6Te_^0Ms#uUzYy=|G%Mj0Yiy&L+v64kM7eYyl}b5|NkN92zqoM ze(3|cO&M~MD7fDWR%LwPrOp5U|3N)rP?Ul8@iQ=hBApd{z!juf2TG5i6bd;=0>T0% z2M7x^mH}abZkC6zKm$t<7U)e0}}(oHgM_a!^FS<86yg1Vqn+` z7E5Ac01wcyFyt{YFo4cKWnn0TtLtH6VAu^-2fDm&GnloCiGg7gn6(M6?j#cf17vvM zHxmN`XtzHLgE%t-cw~cxL4}zCJRHcvV9d+__7w|*Ei(gjG|PaQfdRB?0aT5EFlcBH zQuRVupaK(g5Ey8V6C}^T06O&!!~)fl2sIEEXxM%=xYP$7umv(3q!NT7@~C=df>lCJ z-~n}i5oUvIh3Ej82w{OrXo%S@ObiSl^Fii58gf2^v7U+6j)DsCnEqR1p z6a3SbB6NXfen1+*YEbL~ZDED%vj+L_Wpz9+LKkS58l(%X24(j;D3v1Y5>=ma1)&Sn z$p+~Ht3j~~asmmcRROXq?&#Z>2wk8NP>?RL8Wg)gyR;E@70a<}B6M8=X<=Ys0INZ< z3v{{&!e27KJhBnGKtnemjbJq>c7gI7!meKhVG0Ocpg{(ZF0dLDyFfKQWM?r*{x;K| zj|g3$@){%xRs&*y%V;nIoLWFE(3A>@hU|0(@5_R4!6bM;yCE#zK_Q2_uNibo2{R*X zF@f^dPrnf<6V#Rm8Nvs)3wZ}O=5SoYXEW*uc3JQM^Zsr7afxxGffG(3o4rkEN zFRGhG;BHog>H@1laWiNz7S+uNU7&guH@1laWlw;sBQ*rKw)MCnGcGY z5KZPFgqsCHSr&Xs33}Q9ZQ($;xmNe0qAc9adQe?pH7ITd&C8&=8KDbwCNanbU^OUi z2DuQ`&7i&K$lFzMZlwSp!0s=BH*$PbTBbo z1bh+>XxIua0-8Q$03AyU7Xcjt2p%AYi-7yXpg}#jh%u<-2Mxc2M3_PD0iWgp8r}wp zfL&+^8U_LNAP^#8gBTeY5F#LRelj45fS2Hc`XX>OpoOXopo4f3A|TI$PUJ?2fINQ} z#T=05K|LOX8j$DDqo@IS9@IZVr~!HYAc`80n?a|`Ak=`|yct=IF=#wt4YG&{NCdQC z0Hg~NJ|H)P4lf3YK*9&)X3)R^LImVy(81^k5s;ff$FCzqKyC(2z#&9HZUzlIz(q_z zArD&g01|;DrQZ+=l#D>9ej%;T1`V1pGlF)&fm$BdVoxJosmu;)27)hdMK2{llVXTc zLSbR+78Q6YAqmw5R)bPXfM$acId1Wan_m#RjG(%}YQXOFfr@}QkYW#XXf23`$b&_2 zH6Ry)IhIm=uo}=9idAa)U;<{V9*BZ0$HmE6@i2^a*qQv zgvZPXb^`+g!%9hgS%f*TOO_$$)qu>2#%T^{K|V7hC{KWtynDYLsSQvH5(1xK1B=r( zs0h?ONUOy`bN`SS1leb)j;>pc2vtj{E_1Ls$e{|VHxQu;I@it|9;zNtU0^jR zp$e*75TObxB@nvept`_nKwf7kg^EDjtm5Mb3OcY1$jzvsY6Y4W2A|G{>5E>dIaV0H z0IjJ)^@SDO7jvMxz-mx@0U9hv^#wxLCa5m38n9bWLPaor0dg~{FTm@^8A0=3pc0Ua zSL{6^E*?V7vBmHOXukr&7q)NzEwP3B;ww}aSPhCV?7<-h8ZiJl6BHK+T>?;Huo_T_ zZ3s$jpow{q3nBG8NEc|z94-P%>fl?D;3A-G1s)fKi-58W1E?hf7Xim9XjKMW1Y{Kh z=;8vn2q?P2%R1pAprpmHk%55$E@A|-9<&$$Bm!xZfXXk>l0lFN#Lb|R2z2fmLIk7> zbZRd|1mq_jsNdo7WeD;HXnh?*jXQ=KkjFqHJ_t1_7-~RX1)U@gQKRDHX9O}CvbZvm@0;>U~4UpGCP6kb3Frc~_blC-@i~_m&@Ol}3gqzPo&2fgf8L8d@ zwe}D`4SgZlgV6O1s>=nUs~{z@1Qa#U(+^O6>H_!af2b}{Uj((61X{|1>QjU+dCH@1laWlw;sBQ*btb}m0NSiyvo3}u9 zfz_b688j1#>Slzlt598FH7ITdxe(ROp!2s8Zk{(+u@T|s?@)7mG29GVCyVN4U$~ov zKm(Z!4B)l2sA&U~S5e)J&}9PE1y+ONW{?X}-3%I5N4WXqf>)jhH-|&b3BYhOc;^m$ zL{kn&yx z;pS$jIguD{25kmHb#o-#&5NMAz-mz34BBXc>Slzl6Hr}XH7ITdxe(ROpuH-PQXSOR zLhWt6hnf=ub~C72_y-k%)ThWTSkRI|W=2q*4C)~MvD90E@H^Lv?}GfPJwEDuU??keg9` z0lE=`nGrNM3u=EGJ&mkJ#Kk$NImsBl04@DM_~O9iXt!jzFYZHifz_b+0=)Z=5i)1N zz%bigOBJE(CsY?$4az(bXjv)3F5_z~9}&8QK~p`TYwbX31H~@Tm=t18N_`b?211uE zR2Ntcid~@f3JAL{gxt7?(B%%*1y+M%7iiNGVh$12Ux`p%U^OUqfm)vkyH1Pru^{ZK zhUx;VL9q*bFAF1R_5qX!-)ig^Lg<eosQs!gDVlbjze{U)qqpo1E>fj)ghmp58f~cb~8w!xV*tK#AwDxs4kEiPz#EI zK^`=P1yTr3bs&Z%hDb1mNDf>CW_A@^1U6F9has{OL*y`A1ZK_!xCqRgS8x%Kn)tMw zlG5T-P;v)37PQ)vfq~%=k?^u zc_!!QWu{f)G7v6}!%Ubw!dSPW#N5=R(zLYHBCv(fvvTn$z%Ux!2!viph`A)@CZ^*I z1DGs^u_&6+&2-MmFHQ|gEi6qfF2NNTsA_PSkD>^4cB)HiT4HHV3B-1f%)AnKO28!x zH5rFA!sV_-Mfpf4(Pk#*WLBl7Fo5(SY-5Oz_XGu(Q(|!{Sjr`}xTGk*5~2d;RgfMu z2^3c#Yl)A~%q@sdD@sj;By-rwxv2WV&V)(%CT6EXkD+xgEh~GGhpGa* z6yn6-jQrA^6mYO2yB3Qil8Z5AK|Tylg+>FinJ5w=nI$=B-hyj_$bpo*!_0x_Pnbth zWI#&cx-pcZ$Ux80b@p;_@$&a|b8~lg0ByswH-+rO1D^&D+K6Xw3fYNgZ<>^9Z(5M= z01ha)t>7Go67r~0C@#WO40jS(3Z&RQwFGN!MDj1XJX9Mb2EdYF)1c)5E?K0wgF6|a z8M~Jd@*q>8MG?ea)Z~RK1yUT8T3nJ}l!{F;suW0Za7KPPR3(xxkVTPPk0gxZY9w)x znI4%bFx!#LL>5Id6G<4wOeArTnec#fEGa3A4cG z4H#;$*@3PIY74l~LbQ)?*n?9Qs!h0*f$R#%&&hEuO9izzP;xYqI7nG|VrB_c8B#7m z7DciWNf^aUByo_L0r|xxuDJyzm0*LB^9Z^OlG$idDCVQdf$V_XG5{%NU^W=5V9G%H zFW6)t9RMSoda%hr^cdpQgG~ma#{j1uY%&l%n7%;@FO&d?k9QCDNX$#gNiA~DNKMX$ z-9zH!>fq+?WT5=xqn-InFt$iLmBraTsWEH>`07HWZf2^YcJ+GLR|@dd&i?b%EwZP_q+u1qCQ* zJW)(_&d*EBOlOFXFHTJ^Ey^sZj8D$b&(2Im5dnn_OkCf{%n*770hof{Ltp{s!U;nI z12Z!-1qDMhGfT+D1)zHff*CHcu!KsgFo5@RfO^{4?jhiTjyHhh!5GIq1lDNku-!ud zny@^LrVe}#BPjg9hC>L@ju%Eg28KH5m;h+h6RZxLs32-UBxne186N|~Ca5~l2oLxi zLA3J*L8CvQQHdw$>adu{#LvLM2U=VV9wCF?YkApw7=L)C!n1YunES_?2R zOo6Heg)=UDHwiE>>_buqHV@6eAn7|G0%Rc+gVmw=7c>|DMu34q3$)-F>JMD@dI&Nw zgdnK{n}=pED4dI+YM|C)JueirF1|{Tfng5C!n}rw{_CwWy!UdbXAg|sP zVqkcSt`19j;TC3K5C<)Kh58qpd7$;pros#izUb<(n3pZgz)+5^4lP_j`C}?n4Zd&z z<=>TP>cHWG7H^<69ruY)2U^!5EyBPM3UUDWcn{q7lGKVYFmyuI;R;z`P?tY zz%U!C4&+~K=@}G$JE3au*$bN6JSfJ%AO>2P5A_GGcry`aU~oWEhs|D4{SgOMgU?=2 zIg};Nz_0?U7UU0H_8t>wV7P>&4wt!0{JpQl7S%yst%vMT~Ian>;>)4nkLD>paWW< z3cc|emw(%&7#Jo&)#0)il&&^F)!?%ibTrWpDF%jK=q3r!R5~tuKT0z&{DrE+WiP0_ zmzH5*&<1VKfTmM$d|=6!o-zy!q3G(cl+VR73=Hk)>adu%REB|JBf2^?^FZ!94^@LN zTtLU)-Irlt$OmoofS%TiGhE~t82&=l;SCpg1_o`=77#+=BG14OimndLAE5HDSe}7l zHo7`2;j&Ynf#E2+IyCb@)xl$V28QoYb)Z>1aJ(U{GzNtiC|$uXwgw3>fZB-;4#;zO zAYqU?PSBPQ5C@9E_m^NXPmoA;l0>Kjt({lIrVg$C0PT!+S72bU1#NF(U|;|hNx0%y zS($-BAGDDGIo{C150tKal^Gaf(bZvzk7{KGhIVvyXy$?9W2rI&!%lQ{Sj@Yw%)sy% zT^*WvprVfvwEQ0$7a$50zX}Qp`Yx_+j-fswKAuiiO1{Bi&OsqcsDl1JE`E-_uE9zQ zpz7`;1LUkmHww-Z&xH&lQhcCzx1)eh_d#Yy9%e_5ZZ835FCJzu4(o#@%-RPJJ9ay; zbbGNl@~>y$U(aQIu=KTKw}XhblgMF*V2|cE3Leds0t_DAH%qud8|^_ydMQL7_UH{! zG4SZDQLzA>3&7yf{lla6Kq)uqAaDy0@Cl3_$ssBRKE2?+oZ}8qxO#M-fE~-=EdXJ4 zyMRoo769w(be2G}0hB^PnT!Q|7ZYgdEerUFEKmW$0$!B@+7reCUbPD94T53{gh3@U zWFI_)1=ke&yQL*soWcTPk4vMPy!=OSE)bM0s z0Ifd-Z7l&ggMk6mnFKi#gu&ZF7(n6>7Rc)$easAuA{-1NDI5$UA?yqyCTt8MMgj$( z1L-+Ht`vZ~^5-s48@2l!#7$6+M<+WP-<<;@;L#0sv;@e}79O4Mpp&%};tzx39O6{a zz7Plt)b@g~Kn_KAG-w4dBrQN#AV-6|$jrdV&&I%?!p^{N!p6XF#9aVQ>fJXzx;bGE z@P<1DmRwzpZ~Jsg`*cQg_;f}K_;f}~fC4ZYyubnEG8P6!aA;V#V~8Ut@HCpw{rBj;<hIw>OJRcQl7jx4%HAk4ix|w@+t|N`gywHcxkr zN`X&jiHd?tcd9lISxv=4)ozh-Yf@!wI~QN+diXc2FznDx0L_EG^y>m$Y7zTH2&Ke}{3 zaO{5J*?dsK^ZzOS*4Y35|NC^8s3`b!=cpujf)lO=+~c5P0+fAN7~~llz(VDnh#OQ$ji>a>%{qi{QzqL zO9FEMlK}$*d8K>vPX(XuOW=~3-{r)Pu+Y%Z?=QO#9eg3re8I6((6Lj%u~Vp*B}n^3 z^H0VaX2<^w%|Dq+nH~Q#eLf62iRw70?E^oh6Wc*?-K?Oq3OgA+x>-TzO%r*)^0}*$XUB=pv>9H@cA%kKn2}o!ok7_4jxd?5u_J# zOeMrsAfJN@c@Pc4pzBc}*$Kh|g#zf*PedpXwv82ZB#K8TFPMTI?}lzMA|gNqJ0eOz z!wMjWfH35QZBUdzSRlth&e~>VVPs$d9b^cqFhOOg!f{aD152wO-M>J`RZF5B;Rvd5 zK*f3dVQ`bC^+3t1Zf6NlHR&t>u8km)paD9Fb3r>UA>jmC=Lso*Kn??CUJwn!pi`J2 zAqHWA90}^fGBYr8u`qC%urY8Mu@w*uwayq71&`iH8ISJEV8?lM9|k!|0cXsCYR84p zemMj978a0eKp1qA5yV9h7RW`Q+{w(qsLITsYQh2zItOsDL9>%b_s>!hw9slkq7Z-B zquVnARMi{6s!aa`I4c9fay7o~(HkD&(-{xK2|k_i86Mr|eLCX{pdN`)G4SYhkAMU& z$T5(>m4Yrog_H@9iWIbc48j6!K7p`6WdLYHH7Ff0Fo1?bK%N9)&|y~)k3v`=vsZ(= zCXD(l4EiQ)3~WYBkd_LnXThmM4C-G{FoTX9Rfq?l71&%Ez);HR(HjVB_g)9Lv_PH! zg$P&;qKE@El^`huRFpxS3EJhb9Ue2FaTJhaL3jt)aUhRCSRe<3&gnu+E3GH_TR5O*p>5TU9>5LBW==P3)NP2X8!z0Wa5n(=^ z(GfnK(Fs1C(HTCS(FGpeum+GvH#bb@X($8K*#CSO)GvfY2&iI(ut2_tus~HVgaxYP zAS}?zcL)n~#5{xrDoY?NkOv_wP{@FC42TBdL-0_7ut1>%+K11~z{tnMz-Po|07{Vp zpmwrE7^sPCeA}b@qet?q)=T_-pv~)`UWY#M)(d`fI?Ra$aLj$e*Je2YOu!r?s{+?XW5pmr$ zDh3|i=RhgW0@Ox#0Og4|56Jb1ppp*~AfWAR5Ef_~5`+cH1rQc!(JzDrI{iu7N`vcF&kta$b1kD z!Vq~>vmq+MP5uxL27VKEP?JBwA>Y;J&>a(J&ccdbhfB~&ZmKwdmrJK8h}fy zm!SJ5_`?tI>mMuBIr2W&N(V8K!$eiQQ5%6z`(D$MWum>f#DOs0H_bb zz^}PSrGSZn!G&M5MFn(*%_n{VP>eEsa^V*MZy)CuISDE=Yg8Ou_%(Y}0zjHw_yxcn zY5u5#pZMc`@XNa}Fr@M49ZuudIRBad*?~`v{BZ}sPW;3ldF+!Tf5gEwe*I%*ENT22 z$3A)R>m2xh*rWM4Q(C9{zsBF7t)?{xn(G1>T=+F0Hn{L>K%C>z4RNC0u;3U@h`a81Z@g~h=H17zrbRk;^I4)HHCqJ0dfjD zsDS|*gJEF+ZHWb)P0hjpI+Yeu3>PypFhGjoW>7m8d@x@eBLnz84^TP+VaUnWptJ;G zfl}f_aPb2w>sv3xDP-+F;e8S8CQUx*_q!NT7@~C>AL(C23VF;a}%3#=` z#-LH5&LEMY!5~l)#=v0$X;gqr0+|3B7=V}p8bW}uK%-U=`#>sSDnV?BJgR*Vm6FoT z44jNX3{0S1ETADuCI$wOyWfFb1JcXD@Bq|HWng%a585@$z`*bU%zyCzy@PvVZf>GN zSz=CUszPpQG5G3)^rFI#o;NCUa`K#8D7H}@_k1{Q|@7hsajhdDg{pXYDQ|NsBLBPa|G)D?Ml|8wlV<_U7% z+d6%y+kCot*rD$8wdOff!sGG(;QvFO)@N%zyyo`pG&ut`(b4*9jVh9zlF+c)#mKOgHe2n)2G1Hu9wh$;bA2fF_TA_lsxXg4^ogX%Si80d&o2n$qyL0F)Y z0m1^Eunu7vGBPkgSfB&IA*@2U80c6_h#2UwNC*pbC?|w<7_ROUBLl-xunRy956}=f zB&RSiNP!QT1m!dc3sho&w)!J#OwbV{Al0a9AgVz*4|LxVGXqE!$ZU{G5QfO3>H!_J z3av4r`{O~nK&nBuLUe#kgs?z0Cd6!z3Yba|8zPTtHbf<(Bo~8Z2{(ge2p5B-2`7W3 zk>~^A3xWq6lJj#5^fFWO%T_V`{|~x#0C`yus5oV21eM$%(-BxNB{iuuT?O3Y1$D=m z8A162ArE39Z)pTg5iv7@78HPF?gX19LY7&8cp%q;XwVQXGXt_NkPI^;Xh0am+Wh_& zFG3e+s1~FPbl5KH;gg_>ml?hha`ooRds*O{?_eEZuo{%jT%dLeVnf{Y@+(;gU7-33 zWEWTs%EmF!ATh$OkhwqE5V}B{EkU}#YEbL~#VNurYjt)#gf3768l(%X2E{JWE^dTf zVM%2_5xPJ%B}f-o4T@c$t}J3}BLyUoIx>jAK&E8`RL(~D3v|#LNE@MJEkXW598d{5&K{%-w6Y6zb3G_;LpDo- z+4400i=n?Yl!%#5JrSRkwZeCS2mYzw-c z0%VQ|M*0B_`61E|^EG8l!~vDOkjQ2Lt3gRWpz;F}&Y(CAmkU{k(4`I41y+NS2SHt9 zgk1~XthtQP;kQzK-jhW3$r*vS1VK( zSPhC@ps^N2z9^YsKLMd@AygMw4Ja-Q!6(Ro4+{k?H$l$Jpb=eMCH6k3Int20K$>O- zwG@~cK?}k_ah0@Wbvq)}U4`nB!O#WjBQP_9hE+i2{N8e5E`+YfP+hVRT}V^Gpvgl- z_-ys(6+s+6`5CGUtOg}~K>bTZS_K{NgV4nViXH|?Zz03XcS2lk`KGH9+A;bzdmCK_-zTSIk$)u6Z;G^UQ~W`wRts4lP?lvoD25Y^3~ z0X}9%P|p+;JSo=>-9fmy0%{KAs6gbp8*(rpq;_UtSoHUptTx=uT~J+MH7ITd4QNAr z3Q94mXCqY+x)wuqfz^QA3~MwpfLw^`W>Cu)QOEgbiEl%=c`wu)J&d#gYRy7y2l*6K z$LYb{d=9D$tOmu+pzY}pT_887Zsp@e=z0d#1y%!+X7~>kf#d?@G6CdfR9}D&`e0@R zjdp|DmvO5Wh9P_*32LY^Ffc%l0YnaY&;eZ#_keuSIb-TFL%1)rpt`_nP<#PuFhF#H zoN4!CpD#j}6I2&i4M>^+^&m$TA3u0pfZUAg3s81oW(0KzKwb|yz8L9nD%jDECKz!6 z8b*V-2jmOYFDq}GzJO#TOuFKy-ne2}(Z*UGt#60ILB>Gi-;7z~cgBAXojB*>O*Em&=57KCB0oT<_jV&E<(*Abm(8%-uEvN$M-#g>H?k2hT3WZO*A2LuChz? zDTJ-p#BNRh198t^m7Dijw41c03R902rEUWzcilf z2+sueAbB0HAU$93)KZygJKtG zJO^>)Y0greDuga!PzM)w&>V_gkVE8P{&M`~IT@i#6RHcW2E{JWObDa}3+e@=r(Qmb z&}9qN1y%!!Duy7a2qbqSFUbT=R3Y-$#d{JjKnFaZvx(Lh#w?@Ie zV|bberEt_V4;sT~W(19#fqFibOhEyNG_MXdnb6U5Y)wTWh(qM;p}PD)aeb^Zx!k?g(9tP+ed(D0YDlk%N~%8|11r5xN#Zb%E8O z*aeytMc4&802ZMOe3LZ;WE~M|xeBT`Aw5J;xUVU7K7i2m2x=Et4M>`S2~;_OS)eu~ zh#`w20;;J&H8e;D6gzATW}FNRpn<-`qSUa=l+=9R{FKyUh9bxYXe1Hnj#?uXEK-n- zsaU1JEpHVA+`6zzL3ClU3A$+%QwI4Y5AdNLg~jOc z5>RU~WgynZ7nc;Jlomj@iz4sq1e*_@KyfT8O00yRmx3?}MH0gvWLdBtx1!WkWI<#% zW5^*Jhb{>=%{e1KzZenku+7KNV~Q|jVeyPluOa08BpiBi$wDF=ySd1|KsOemBR{tQ zHTi;tg9~ypOPm4%U}q^nqZu9tpnbRQsU-+us72`FV8g&C6X7|f#yzzppeQppv8WPi z9xN=OrlCus+Jz0U?WI9v00YGu=~5kTN7RDPxg9G6_`+x>~eAha1kIg2M>NP!4R9 zHnQQczyoKtpv2q)G_#S!QO!n3fD;aq*$5esyMt3p5CTYkM-@jh8$|-eY)lzYZihw) z%-vueDB@7FF(l9h;5i1Gdyxz&W>A3?3RtBexf*(G88%&5r69VnI0A=zi@{L^3j>&U z&A^8gAVeX~L>GnFWr|fTx+p{~a@3(DE4Wn{2N=Z17o{fVI2fm;8XyA(sJMxN8Hx-{ z+&C=_S-AmB+{7R?Ee%Nr?0^JkcL#rOA3qN-e@Doiy}c=T(%#+_G;0qzW(hiPZ*K~k zxOYG~PXPZ31K{WY7lP1a<(!e2hd8+m8vWQ5Kms0*0!X+*lLBrN@F;+ofYXV{=?07W zV12M`>RB9|n41dqBSz@}6)$Gs(l@d+fFG-%prAnL#04WmQ)9>x4WJVjN*F*VE?m(< zEJQ(`S_L)EK*LNXp!pOK2ZnK+xR8vd4%>+fUl|w}J_|80ya3I%FfcHHriF0r@G22u zU}ymKuEC9L(2h0(2R*bMRG^mUJg6F&^FTYOkS7X2;-Jp^GBkBydyximVd@?ep$>Fo zssd=v2BZm!!RCR}091ehvb?2Vl!0M3R4u3@40azDf9!;+f$0XTLvtVKq}zjN>Tubs zAjZG|+dYlTUeH9H7ibmy(7lJ@B*q9pS^4#&%g}B;a^aJXN;*IUOcAJqD-e)?Jg^Fq0u5Qr7iVBt4ONTJ-jh%@AblW=%ifD<>Tvn@g*XGl z7pPi%_6mV!3_%t`F*bWar!q@PFff!u)q>2!W$#o828M-5>cHk<$w&L4YM|C)Jy8R6 zZ`W}N28K&Hqcm`Dmavv^xSwORvFiUZyE6~ze9w`Qf0;pQhP&6+8 z&X8hYSOQgt&)!2&H888e?nB$r3!3OVg`v&?BcFp#u6{1Xz~BLzT_q4M1=0)*HBfc< z+&2rV2A}&tgGGxl)M2_0v}EOkGy{VgXdV|@FW?G47a0bI03>zbaKVyZ@}O!^+=o`~ zg35z383u-ZP__8t?U@V%!zZXZeBmMhiWHcoIMNGfcvM1`fgu{I7GxeS|5nN}Ftj46 z!{%R5xv?0k24*!_9h!eZQ!MLc85kZx)q;lVaM}A!mVto@G>;9953qSy!dU^ThLF7) zatsX7P__8%1)Ty=4OIsU7hLwvgsLHA??O2ShAU9D`0RZl$H4Ffst%vMLZF#^n58)4 z7ZlD?@(c{VP__8%O_XO~$c3uIXKy!D4a{nAxL}Fj$?^;g$DnHQ*?UW#f#Dfc9X@+m zKr{0&OY!)ZM}dLC9;z0fy}=3$4DnEP`0TBPs)1RJ%fGD(3=BJqB zd%r=|5VH550t15~X!Qeh$r`SFNrok}?B>9%#)7f%3`+ss^9Epl}XRW?+~KRg2Hwy~+#>C!y-_`S&?g4L*B8Rrz~m z1_n;hniZ%&!08GtpM#cTsH-qA1fZ+K(oe}#VPL32QU?xaEamtNs2Y6k11*JEpu)g# z8mboLU$FbI*!xn2f#EBXI$ZV&gVwRYEX9%jK;a^-%D`X>RSUNlEnK!RFfatGGBB`% z8XnL)(Q&yiTaAIC9I6gv9ya%Z`cYHW7#NnKtHa{o!)go+=h4-ng)_*!w`vRwf6>)p zF;7~Zfk7R#G62_mw6C!#AipeD;cHF)(O=Rz4xe8gNlS?yw zdRajVJ$gmq>U?@#R4hO{)(k%J3+RG`Kk*A@dwk*-fGF)g{fS@DIRI>Cw~LC!Opor< z+J`RwNaN4D06NZQCW!Ny|JkK9{=5^P`JbHxtMuqT4WU6!I1HL-1r4{cFo1d!pg}qo z2G9*x5Ef`J7K8=bcmi7T%)$WL>IN!-SQr`^7#JY39dH(C13YM1I19skxEN@g8${hs z=%^kG!(#>p28el}-ZsQMP+9_w0fJ}{2IV8jrcVe9l5Gm)htG%kw>df@ zX^wH}_2O_fzLW;r9fe!7Bly?}i^gA|J3Y(YU5zfeww^2%_eehEV&TJ)QsU!c;ptE! zeawX;h55CHWAjhOQa+euDT^!rwu>Ighg@4Oxpeq&r0f7SH(mH$Pxy3C^k8CO@NK)Oxus}frY8gO}KS*L=X#S;81l|#k zboh;9_eb#YEzQ5`$~YQ-f%d8usd{ubMldljc(fiUVfufe^;?OsM|V4Dt0zc=z5B99 z_xb-9Ks&4qKzq@^M=HgC20I8e-UxCG2!j>|LL3BPfgA)`1j#7E#vqb{bRbXj8x4={ zM$qO~kPS@#FMy8@02u-uHv%ykAS=#5O(qBnWFTnu7}STLGZmWOXf*#~FV}W$Jy0s( zV&Ujm!sU^C=$H#f4D)LaPA;}d^GV8ADSK@dwYFubrEz|GS1koT2xe5yuaS#^Bv5>2{kbMnxtZVlT zpYD^T0ENYH`0>k~Y9#Bn!9^H-so}HkEj|SvW8gOia z2Gc=lj)ei#9EA7;RO~=n03d&W#$-V>2+xH33Bm&T3Djaj_z5{WK$(yc($<1xRA~FE zR2Ehe^COkDpuz*3p1|%xq$beNJj7j~0U1au1hjw_()Iwk3b{O940j=f1#%&%HHYLv z_(49QzWb;q{a!ye81qBoXxG##T09)n) zmCYRBqYFUWN+1OeD0hR}xF8yYIpN0zKv*EBv4h2s!vy8Wc>76=REKq0Ugog64fz=5Dc86lAiVSyYdi{U_c zAx%!$;fh>Mu+wlyF6h(=h|?e}kkd3!oCb3i543d*PF`RF)H{X57pTgF#0_X2g&x>W ztAlNQ3QVU|?_oTLZEh!U9?C1Qvr?4YQW`u<`)ggmI7^ zXfz2FV4%abAZNOHfKF5cHDp02)fjkm%Yx3O@MyhVVhcKq#=`iUhh?=zsj~4U2Mh2n zo>CrgG6H-2H4l7br?c3?qg&de^>*obNT0p?JXnc`r7dWr2HY0$>6HbsOE`SHr9CaJ zOMiHDvwL)(_v~bbo(BeQtAKnDiG4(;0<`Z8(vSi*&_S{+44@0fA!!3NPy}hofSTdi zV4s6JN)R0r;e$e}7#J9`z_Or&Z9qfruo%bzhc+k%AS{p@0>NU?c_;?Zo=lKxR5cLQ zpz-M2hRCDp z0rliyC!(-}-3!tMQVsGALgEL{I+yPA9-SO6-N!t-uX=Q!@aVqb(a8#u0H@N{1Euh!Y<%D~ zGxUT>19bC2L{NPs2| zKr{$ffa4ex;t&=nOiRIHj2;{e9-u>-Q#cs-L%=7u6`9DVN~GHX)}#g7@P<0szs=0cB1|0D!hXLc9$M6bK8ny{8ZCZBV}q5&)oK zMbHce$nzlF5B4l503a+-05pQd6hXINLz5h+O#xC3l7*-PC1(f=6z{!Y9UxU8^Fb;> z7$T2qb~{)la&iXg0;$GtHb@0bC5Vm9Y=|ph$(f#q1%bw~LF-rV9yS(2Y$yZy9OPE$ zVL?dqFCZDj#w$Ik?(NL*O_ZRx1L*>*LD}R5>c%5B?tzZSLFfWiaUfk_H6RA~e0neg zyipFs0*&;8Xvp?M5DSz=Kr})GH2#1P0WU;`aKR*~dBDK163hk>peeao}l5pE8GnnUP_ zAtQ^rGQ?p)ph^zpCeTO{s+&QsMT9fx2o!{_YN%acH6S;GibIew;I-taZU$8!%#1Kk zO+Rln7vbh9P;&?!F%;&}Gz)Q9&`PK-P<};qGpKSxbu&WOQK&Ak8jzbod>OPSqkpvX;58YH7ITd zEe1t(GeXxIs4lP?6gPuhi0Wq0VoYX6(DVpsUBSu)-~S=P`7qQRLdOt^KT|%3I8f*c zR2OJDBWl_Jbp}w~jL`K4stc?JoF-U74g#}4TfJ3${0u=Ievkmj&8WTrjnXnRf=XFX zZTB*vTOZ*IF{n8T7$Fa8z#~H5+;Z1F#9=||P+ed(C?OA84uUQWM!p*H9AqEBpLI((=+lRNFX<(`T|syK#t4;6@Dh6Y&#LY5C=8D85kG{9UlZbG7E7K z5bO{n&@c~b$b*LYP(vP}%LQr|SPdxTK@J1^2E;&hGbmCJZtfA$vPQT$9%>Gu!-7C= zMjZQ74AliHKv3NbYGt9i8KJ8Wstc?J#myiWqPiJ$WDUa2w>2MrM!0zu)Eq*G1%cd* zI3DK^R2QhXjOu34P&6}2u0-g12-O8vgW_h83sKz+>ggcdEFP(XbTky4efV zZ$hpez()hYYX^{11A`len?chesNw7ece5c>7g!C7n?bz> z)U<)ne8~K% z58TbCp}N3oP}~eY_6Nny2wl&hy1;5cNr!<6mWaT%tN8eV3O%q4$jzv}01dY@GlF6k zuLf0Os zF0dM~FK$CcFns}XGpa8@t6XrUsNYa?LNR;+UYrN_1t>*@!hOLH8d73l0Ivx`t%<@x zEg6)!KH@0)`@#(>g6Rv8n^AoM8vkQv1ob6BC3c7E?eB;bl?*i}0_+Qr(N$0p zh{?!fdZ0tInHeFiaR!E6^5?`5=FEcXiUga3oHC=p{(_83F)-9tT0V<}hsH*zF0dMu zI0a2Lp~fjf*LkQeuo{q)8QwufAZ|u(#ev+68XBN`fS4IU?P^eHtPql4j_?H^Xy}fC zfguLN7vLT@JWd(vWR}FheIW(a1y+ON3vkZ@B~B5#bfLPyYQVm5gomh3|4x&_q*R)b;}Xj&6t*QQ-!+Y!3HLUn=Fpx6bv90qb2ASgwB z=Xx*!p-X@p6#fhhU^OUqfi9du*md>7XJ&*hZKy7=8Wg+0ml47be5+p(qleJt2Gs>t zgJKtWxhy>ON|xVThtQP>)dg0AVi#!E36TelU$QnKbX7rhfz^P$I0Y&K;(*$d3=H$( zBA|9JXhaCqX8_5AQXOh~1~2Vp1WnO_Do@G3myz0ayP)P|W2D0zaEgMJEr*wJS!Ki1 z;c2KYuo@J9fu;%}@da{A+r9K|gs#U>U0^jJX@);g5lG$v35kI$1Tnz7IY9^6K{*T{ zU!eL6bUha2dI*rezWwsmK;$oFs5yBU{sPTqAkv0K`Q+R@xW8&ZR}g`9+{J24Uwkp$S6I>OmC+PmIA%=y6Xi3D3++$u9>VafU7hu>f=~ z8j6f#K|xL>L=J2@iexa%U2tvSQ-UC;y%ndH1eatcXIFZsRu+T20O9$9)&x6&mjo9> zjtK(m@lLITc?@g?LJ;aPR8a)aIU}(MQzt|eLn~Mqp*J|WC_g6$Q#VW;LqAjkVFK7U z&N-RM*_fsv%VC&=B#AH$7S1J^`FWV;p~_;Ih$4+{rfXhFDz;z(rz)r<4ih1=2m@V; z^5I9ip^IV|0agq;`O7`E1RSN{M1*u`8>%=|KZXXVJ((q$i8+~7sVT67%di?5jA9j% zkth;SJCM>HvIvqc_tX-QB76IIXNPzLCqD-lCubigUr%3$kc?D&Q}`-=d(-UHN_*4H zVtZ5QLVkM{M@I*+Q^5xhmKLW%(mgC{p%#LZ0!#+gVq__(1DxF*JY3xZe4V^JFdP70 zZ*Ol3S#S??3fu*d1Om#csNs(!j%qtX0_0MZ%#LINsyLDfC=w_pAO`?k75bTQ5ZfU| z1gr={D2AHnomz=FHxayY0d^uCiVUi&kfosJfC>g22BAu!nuH>UWR!1yN--YeP^B@A zM3ILYiDqbh-# z4=I#!7>zE8YATv6)Id<7g~K>hDOAHy3 zXi|`)DzQpI3S}eQy0A(?bQ$8-g;ffo%K*17tWpqNSUijrn5h1R9A2GPl$wf~NKjRQ zOmqfc_X#QAU?GSpj${#v29%gVm5I;HEr^F6n2j(nxFj(zC9x<4)j~)JL-eDofW#a= z6_DV8gd9FI@Tq{9f!m!J0f6RAECGS0f=l1n(43TWMa|93j3DYk=ZY$W&lR=hXJBXt z_q`Yxu$?Q~1D#=mDqajxiYGy$V_--{SBK_4ka^8~ z3=GrJ)nPGjD<1>HL3DL!=7Hk(K2!}TZb29vzi8Sfmfx{3fR-A7mK?G$fTn*z3olt1KogXpDLNJg&}0v2 z$t?>5Xo3P%46rbO2C+f$%EAB|=mag`nHw_$=GV-i2;O1fz`y|B4dtQzz@rewDi+YS)eH=f^%S6F4XSt{ zr*weU<*+b-=9wU3pxg+mepnc0K~LHNtzBSX0M*&BYy?X5knO1u7O0$rtZkCiXJ(LP zWaAJ3HGM#*T{|!^fJ}p|VM5+~n&i<7u0@P5Iqo>X2@N~2<694u=z8?>u3&%)Hrs-j z3?7}V3m6y}N@byC$4(9gMo5T*b%A$WX&gQV4tYkf5aKWsQ2P+%NLB_=l?YP8!T?%a z3z}eOVF2Y{P@ZLB04>^t$bte1v^;?Ye6A5lj1?3=;HeuH2GD{P&=La{29O%iR2bwC zF3{o$7Vs_c5ZgeLNT8)7kRSv#KVU%!URb~Y5{Ixr>LE*0V7pfR@)dIP^D;~Fi;5M} z@=Nnlkk3BhZ+XJNz+ij;yj#zslXU|F1A|95E2u009Tp_XFYf{pH~|g^ghc5Zk8be3 zJ&+<1k8Zd;s9^DEJy80lTND)7#-b4|_Bp=diw2bIqf>Mn%D+n->&eU!CFDSKh6rW0mOpHU`Ynx{jQLh zgdAXkh(A!72Z{|ytU*|ya=99OyftW1AVdtb=mx?9#Vly|CuGknL<}^A3t=^bjvxf< z1>M33iXj$;IdC!1L2(duphGl3r8En}KBz1Q!wER+A_D^hB<^oO#aI}gGB7Ye($@zD z1_n_4vNC`+nSmO4Am4*9sI-SN4WHv}82t(vi^?=eibmwdd z3j?y*Am2cAfJ}t2K=}`1HnK`wWY>3^c?uMv@=86)6RT?G+IIWL7i3*4XRq0QI_m_bQ(3gjmuKTP+7tgL=;( zD33EUg4$gmT~pfrrXzHL(g8>mqz1eZ0JNf;0kkXyNS7ZK)w4nqW)15yJv2h@yX04=Y>GzXLt zAa_}Ubi{kiEk&3k14>N{3=AMOU~@o48Mt=AGzXNbm>EHBRggJrpMLs>FeeOZ4oD5y z9B|-6s(bKF>qs3^P(PHJ5!9szne!`rZ$84DTBtc7HDGhV6Yije-k9zI+#gDNR1XT7RmV!)u*Rg;f+@1iLUk%j-R)ex+0<@_RvOEJ67|jQ=rXzGs zg6aaR0U5)v3MztF;<6hq0t=7R7$SG!BA|s9@$tzS*~KNGf*sU^V*rO3I0ivhfc%cS zFb34GVP*u?ouGKyW!L%=5*nZmhG$+TC{P)MFhT=VJ|jY7cbEKTA$Vwfg}Mi<1|>8= zU3|nsCeT7|gf7^&HLx0xQyE|z&=8@a3yE5&zmNw2K_whBBgiixtw-+fTnq~@1_l?X zE|40C(+Z#>2$MTeL~>Jei&Mcq2bl&6RTUpUaOwr|LAIcVA*i9w%m`{5fLtGWtd|cG zh9K3mp(cxAgdw=!2Vd~hHnDY+7(5JDLUn=FpoAf)mkX&KKuT2ZBzq%t9RLY2Fo1i) z%qR6k49jXhg2E{H=KNw+GflFf^LKkdP7+4L8U7%JTB5hnLQ4dGx zVg+STc<&c^C=gVpL2?SnIa=qA)gW}qKy`uDpx6cK2O#X4v+mk;gf3&KF0dLDe}Q`X z2)ow3+*pLr$fz^W)f*GK^gFNsLs@a(tL8TBVCwi+1_ae-ZgX&TS zn`6w%0GWdV6+*DpG2n(1c-R9zjh&ua0v3RdgFqLPxVSlZyZX8W`1trZfCo_QjqOdL zBP#Z$5D`=Gn2NnAcu>UwerKMmLx8i7tFMobKV%sSd{o8W6f|^_SOQspQVJbdL1=Vw z@bGeVa&`A{ad5OZg$=dXTf)X#>`lRgE%v66(H6Ky7e@y_Uw1z*4@XxF8zCbw_NI;j zp7y5DF&MZ;XHN%r7f*jrZzm`G8bM2UK<^mp)c^l^80@p5zUFD0t7Pz6mif&AkaOBp1FzXsZNQ-(5X)FiYstRf=y?F6C1KHbTSWJ9Lw#FpgGL4 z;=F>Q%)F8`67Ez)nqmhfdz6(!U;$9A?2?+6SegS}^5~J7R{~vb2wO=Jl3J9TnU`3S z3QN*X&JHdmrBQ4N_B$54$S3{ef4ufKlGWi)8O3~G!%^-mqbCdZQ7?z`}!(!f1eg=k%=<3kS12x^=L)AcB z0=-ESse=a+2knVr2YCj>fnsbk)S!;15fSP@(;n7Dr~^eqDiP{H9n4}P)Pc;a!=?@` z9o%JPVCWHGV8{futQi=IV=7_6J%z_{GS;KB(*$c`alb~v#)}`1up+Slw@Fd3sr~9 zUXXveLH$&irLYwjX#NEaO$kdeFxWuVg3QBZZS05tD!}Tnq(6IU1_p1aI*>oW_F_o~nNT(O+y^@0 zuuz(T;RUGw&A`9_8YseLZ91co`E3d?#s z<+n3XH7Mx{t^Nf~7hJ(mhgq+J>ggZY)S=}M&=9`70s}(fbCI*Hp3WysILFo}!{&=O#!0-(;3W6MOXyFHrUr^wHEQDgPy=dVF z$`%?J>M+9()U0wPLLI1z4ktn#$h;gP)Pej_M}#_1G)y8w9jM&dghd^hE2}^&bKEFc zSp^-5p!hB{&@uo4(BZ!lVU8h=p^jmW;U3Lz0-)=te7YYVXJlkxX7K0)-%kb}B=hJ6 z&k-5l-pK^Iv9|jqNYcT#`-4ySFVNZ51|Ty%AnQ>)x?g}62S{M7yf8ZO5_H z&%WmNV1Dm-oJEBRi1Er!^-1C}g1EWuG zj7orKceI6PceaCP_hZL+$2iAW$C$XopxP0%&WeQrMCyR&{XtV)plTbkJ^-?+3$zs) zbSN8SjTUHq2nz$~HV;rUnT6ppc=mvSfra5Y0|R&+2@3;gDHK?fvYNaqUfK-9Z zhAPHtE~sz7%%I4@#K2JkYBVu`b%At%idKY)5Ee)U#B7iXkoh1Qgdy^v<`aYk(hX6` zD9*(o9wNjbZX(DaK1uk4-~;{(ya%`w{PN)|y}-*>6f*N*E34oV#gJVjswsM4#Nd{g znUk8LP?E1ulv+}hnOc^LON)O&YM#4~f@`p@v#$aJoQK5Jb@ovJFO}(Lv;`%4{ua;~ z=C+_@RRT}J%&@gXMh8I0&L4K^c4TpE{=rxi)9uL7dY~c{#3^NUv_4Sp<=Fg#sg$Ml zK)pkAr2qrM3>Gvq8Y+1h_*+2tHo?**x(cZHOEpFY2AGZfJ%Wr33}9RNJJ=W*7{E4j zHveGd?*~OP*mln5AB_C{p!G72%|Dn+IUTJJ@b}+jU|{GD6llFv;@kL(QGuDEM4|B) z6Ntv?O_1&y_EOpAA567yMd+>s`J+S*q!hQBZby;U10`yRl}ooL$4+zyg4&y)RZ}bspgao6ouE}SptV>m44}ggAY!0( zub_i+SQtPTF+s#Y7a4)pS+OvH7I=UTFk)fgf#+CtMg|7Z${`j8L%0~|&}~rniG?8) zE(SVj95TD!1Q%P%$iM(v1joX#9xir-k%0l!6=7kx1Q!G4D$sBRhz4QEK`@{k24R76 z7-*spamNUB+*|>g+M#3k3aXiUs+kJ#xdr%=NNA;^P?VaJnpm8wkd&H{SeBVzgimRH zQfYBXUTSf%LT-LaDw0aK{G#&2q7;SX{M>@XlFX#coXnC+h5WpnN`=&l%;FNzI#G0o z8S5D+B<7_kBqrsTr7}1}R#hq#6y>L7=A;%A)NF*L8O`fZGmzYeroc5AUdEsY4|bnq z7At_3b{3Zw6yz6y*1aZG!o1@ejOq5oqEvk9VXlG9xqw%_BI3s(6kIolJ2s#BZ~WG$ z`=o348`thXuB`|7Th22wF!*$qs5pRXT@7gcTccv((R@h5wfjS_FJsyS$L2~MhB~h1 zDi#L*7SKwKZYKdpOGgX-)&fwm(H+U-YJ92nb{&U{WzZ8BewT}m-IW5Z|LZuLt6nga zGCTf1^fq3!elBIas*p!qjg z>tPpdrzfub>kl;l|6ju0eO%k=1z5>}=6@jmF>R+e5WZt`r3Azn32mnja4{K(n2fg5 z7r2-LL`*^3=?7d)1tO-R?eqsC*8CG>{y}Xg4hY||xzdE8gtNJd2kgNEuGUwI**to) zZoHN)6>_z{Tf|<vhA!`fMquYxg79?$@r}KX!s9Fg=10)sM!&F_&p;7188Ill-)rXav}*R%R^Y8EDt(I z1t04aku1Q2QQYJXIrF%H8eFVcBtpk%6Ix16<-OL?1T3w38jBN>zwH3|i0x zTBrwEh6^deK`sCl$RHYoLCZ2B%_;~Blq+Zb&WO0-%Il&FE4x7|09 zO({JHYWc>1Qb7qQ10Mlj0|Dd1)+8&$9|rZkK&!1;7(izpL0BOFfX2)~Gzf!M8bbUA zVS)Sxs@9kp82Q;4_*2*!_(2z37;zUsLc0Mp;0s#$d$SbzvKq+M$KZJIus&SE0l%vP ze5EkRP|)>;tPG$YG9-{eeI!W0gH~;UE(r!jH>5TLIShnBO@D~vAS{qMpnVC5>wb|J zd=tEF2;u}#!yn=VP~{GB0?0B@6CFf@FsKrTSPWr-ECwx7L{yp3a45xoV+u~W7Qwr|1s zwq=ZpMV%Kk8+Bja$t=&n@PFD1M#y!=9zNa2eY6ko%Y*vO3=I6+1f2M{@i1s#EM@oj zf1veb>D$&z{4JnervDFH$EaA;?DgnA4=PN-HyJ~2sR1v-g|`k5BX$8G)WIAKu^p74 zK$j(#DnoVQ)8f&6!2^2tQtN?|MueG2`4$urkf;T9Cn3=Y>PkYQ7POxNA_h7Q4#EOu zAJFX;EDYZm7#Qw=QyS!B$(=wVO0|Bnq067;{&hNzzk5q43a_e z@@pRG7Ac5=&Sq#aS_682-wR~Q)>7#+VIW&#-u8jphPssfGBIX2X&@G^iDT?HxXZU*_K`3G}7 zcWHR@Zji^BYWyIEt4)N}0x-jwN;Sb&2p@000n)9&%mDS!Yb_`P?6cMbC0r0Cpur2M z%xiWi1E$0lVoeyD9~yrLH8C)h@*Hoz!^pq@8i#l-?AZ7_5hTb35d@7wFGDrC?q9(g&}F484AG1X48Os$35*O35Otu7(IB#Qj0_Av zz_QJ7+39doPBSuqH!HC)fD$=G?-RHzDDQw~EI>2}gYGJYHYEzSV*it=+9+ zc$5JMm>{OIl+>is^!WVJl7i9_2G_ijqDqB={LH)(*uY|94rtS7Qc-?(Y92#+jyvce zKG2CanGCestAo6H6*N)A%m^A41}%Y6uYBWzSiK4l$;xVuUWx9yd^g zgVms{Q3fS?#Cqu2P4e>*x}X~gpySlYQ~#iZg0Rb`xu6uG3)Bn**#%aEVi#!95;G&H zqY9Fb*);t>Lf1l&5OhZk>aHYER}ykqFi1(#2}f7N`u;s2AqEBpkQ&g^2nKLN4Jych zx=#rdZ_JD!H-O|1&dG5{n8OSj8GtTBgP5ZW6#=P*h`_Gt0(HJoO$Idwm>EG!Y(T1= zzMt8HFc~xo2@(aVftb^RVlwhh22dG}*eUceVLfv(+0)deao5SRIxUvd47u*)B+3#0~B7bveWGlFKn zKz3W&D|P!2OAY>3a=d@WLXUJW&e&{baf4#CEVOS$$#b%90?P!E>}jnN=V^<5o` z4hUVa-4|drC_7I;!*__h)A)Sb6NIjxP`kitQ1T8a#+ex*;tUK@^Vabqbcung7X}9K z+$Cxa0&1`z>&PuHLX<68P;*o;$`;UI6U25r&7h^W zxULzH1vTFo7#Iw|ZU%*hE>r{(KFBRt(0DL2BWR=&l%O2Fcl9IU)D5bO&;?+}ZeB7& zT;&xG)dkv&jhZq+tyF~HLHP@zD<7&0tOn#{h7PC*#LdVt2y!!OXn+EWnGrOI25JeJ zCePF&^pcLR{sw6RHc8sZo6aT44fduYz(=)Ya$a2wk_Jy1;5sN^DRG zhe$0ee2XoOwU^LKwl*kujX1y+M% z7pSv~%dTjsF0dLDe}PH^gk8UX=b9kws)p(Ut3j~~bm9`iF4?-kX9!)hp}N3oQ0xND zh9K-JSt7a)p=&o(7g!C7U7%TfL|@9lKxZOB9Df?Y5J zR)b;}Xt)?*7c1+$UkF{&&`t(e4T@c$wFd})UCfrWN9eMK>H@1lu?y5zMC2yW;rj?( zkx*S=H7G4%(D6Zt-JTLLXOP;N6;NFuHK;8sQ2mQ&KgUl^Lh8$Ggz5sR0o85{46mRf zkemz3%v_+Z7>EI0G_K;~X9UXUAOTR$Ma|2gITU6_(4Z-(L^|RVlGq{SPhCVK!)yOkiMm1hosK1~nys&P7A)t4~Y~pM}sR z4()D&)S&7D4WBVHf_gn5^OLq2PeH?`j)dfnW%#5Hq2c&D>3?mMN zuK!S7AT{8Yl?f=VgVcf21{(wDl97VMqT*EOu0QBTKIraALltatkS&zh<-h|>Dh7D; zVV8sG!)6mwE^=yqUd9|u=w7Y{FAZ(r~}Qs`PH*fvtr%sj;QT<~UP&^BApR@ma= zh{%hTD*$Ik(})(aGUNXypjO+o9{>`lQ7*WmhG{2cr|-96m=1N#o5afOTfAY!#C-J zBHP&w5x8*uF0KyV-p(G5{vM7veG1yIpO;@^Z(3YhfY9jZ;OFD%T=G=&o54Ob3#p;CMsAZAq5o< zNl1xfj87*HNr+CYHX>&PG^c{qqvkI>ISanW9-B6>7;Kw2=+Jx6DVcdC(3A!#m>>nY zXPzr;Y84`YVkJZfiyCBa;8FxH42w&O7(g4peG{`&p-ymyI0$ALE?KBGIHXa0iN$cR zJZR@X>=+J^IhdgVt;%pnA~^w5D@adpd18T6XBSd^m3fXqNdB5X}5ENBfOrww3J07?CL6hP9kCHVM$+y>y5hv+vapdYt9 zM87Ek{kY{J`XPri;C4T5d5C_<0SvhH_<9i$Rtav4>zvxBR@ zled?PvoB0BV$vB^rK^L#hi8C?hp!h*CGuo6idtt!2Ok$lN5241UkC6cwY@2LmKxMr l0PlZE%z+#^1DU8s(d*|B;OXP#?Bws_08RjqGCvcd1^@!cl3)M; literal 0 HcmV?d00001 diff --git a/examples/opengl3_example/opengl3_example.vcxproj b/examples/opengl3_example/opengl3_example.vcxproj index 936c688da..2a2c0b4f9 100644 --- a/examples/opengl3_example/opengl3_example.vcxproj +++ b/examples/opengl3_example/opengl3_example.vcxproj @@ -5,10 +5,18 @@ Debug Win32 + + Debug + x64 + Release Win32 + + Release + x64 + {4a1fb5ea-22f5-42a8-ab92-1d2df5d47fb9} @@ -20,32 +28,59 @@ true MultiByte + + Application + true + MultiByte + Application false true MultiByte + + Application + false + true + MultiByte + + + + + + + $(ProjectDir)$(Configuration)\ $(ProjectDir)$(Configuration)\ $(IncludePath) + + $(ProjectDir)$(Configuration)\ + $(ProjectDir)$(Configuration)\ + $(IncludePath) + $(ProjectDir)$(Configuration)\ $(ProjectDir)$(Configuration)\ $(IncludePath) + + $(ProjectDir)$(Configuration)\ + $(ProjectDir)$(Configuration)\ + $(IncludePath) + Level3 @@ -60,6 +95,20 @@ msvcrt.lib + + + Level3 + Disabled + $(SolutionDir)\libs\glfw\include;$(SolutionDir)\libs\gl3w;..\..;%(AdditionalIncludeDirectories) + + + true + $(SolutionDir)\libs\glfw\lib-vc2010-64;%(AdditionalLibraryDirectories) + opengl32.lib;glfw3.lib;%(AdditionalDependencies) + Console + msvcrt.lib + + Level3 @@ -79,6 +128,25 @@ + + + Level3 + MaxSpeed + true + true + $(SolutionDir)\libs\glfw\include;$(SolutionDir)\libs\gl3w;..\..;%(AdditionalIncludeDirectories) + + + true + true + true + $(SolutionDir)\libs\glfw\lib-vc2010-64;%(AdditionalLibraryDirectories) + opengl32.lib;glfw3.lib;%(AdditionalDependencies) + Console + + + + diff --git a/examples/opengl_example/opengl_example.vcxproj b/examples/opengl_example/opengl_example.vcxproj index 1d4dbc55d..f39a929f6 100644 --- a/examples/opengl_example/opengl_example.vcxproj +++ b/examples/opengl_example/opengl_example.vcxproj @@ -5,10 +5,18 @@ Debug Win32 + + Debug + x64 + Release Win32 + + Release + x64 + {9CDA7840-B7A5-496D-A527-E95571496D18} @@ -20,32 +28,59 @@ true MultiByte + + Application + true + MultiByte + Application false true MultiByte + + Application + false + true + MultiByte + + + + + + + $(ProjectDir)$(Configuration)\ $(ProjectDir)$(Configuration)\ $(IncludePath) + + $(ProjectDir)$(Configuration)\ + $(ProjectDir)$(Configuration)\ + $(IncludePath) + $(ProjectDir)$(Configuration)\ $(ProjectDir)$(Configuration)\ $(IncludePath) + + $(ProjectDir)$(Configuration)\ + $(ProjectDir)$(Configuration)\ + $(IncludePath) + Level3 @@ -60,6 +95,20 @@ msvcrt.lib + + + Level3 + Disabled + $(SolutionDir)\libs\glfw\include;..\..;%(AdditionalIncludeDirectories) + + + true + $(SolutionDir)\libs\glfw\lib-vc2010-64;%(AdditionalLibraryDirectories) + opengl32.lib;glfw3.lib;%(AdditionalDependencies) + Console + msvcrt.lib + + Level3 @@ -79,6 +128,25 @@ + + + Level3 + MaxSpeed + true + true + $(SolutionDir)\libs\glfw\include;..\..;%(AdditionalIncludeDirectories) + + + true + true + true + $(SolutionDir)\libs\glfw\lib-vc2010-64;%(AdditionalLibraryDirectories) + opengl32.lib;glfw3.lib;%(AdditionalDependencies) + Console + + + + From 8e0f04638d3f9b253d9c8985e4edf978792fdbf7 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 14 Mar 2015 10:24:35 +0000 Subject: [PATCH 19/44] Examples: Fix includes order to avoid conflicts between DXSDK_DIR and Windows SDK --- examples/directx11_example/directx11_example.vcxproj | 8 ++++---- examples/directx9_example/directx9_example.vcxproj | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/examples/directx11_example/directx11_example.vcxproj b/examples/directx11_example/directx11_example.vcxproj index 767cbcc2e..556b04278 100644 --- a/examples/directx11_example/directx11_example.vcxproj +++ b/examples/directx11_example/directx11_example.vcxproj @@ -81,7 +81,7 @@ Level3 Disabled - ..\..;$(DXSDK_DIR)/Include;%(AdditionalIncludeDirectories) + ..\..;%(AdditionalIncludeDirectories);$(DXSDK_DIR)Include; true @@ -94,7 +94,7 @@ Level3 Disabled - ..\..;$(DXSDK_DIR)/Include;%(AdditionalIncludeDirectories) + ..\..;%(AdditionalIncludeDirectories);$(DXSDK_DIR)Include; true @@ -109,7 +109,7 @@ MaxSpeed true true - ..\..;$(DXSDK_DIR)/Include;%(AdditionalIncludeDirectories) + ..\..;%(AdditionalIncludeDirectories);$(DXSDK_DIR)Include; true @@ -126,7 +126,7 @@ MaxSpeed true true - ..\..;$(DXSDK_DIR)/Include;%(AdditionalIncludeDirectories) + ..\..;%(AdditionalIncludeDirectories);$(DXSDK_DIR)Include; true diff --git a/examples/directx9_example/directx9_example.vcxproj b/examples/directx9_example/directx9_example.vcxproj index 54cc2100f..f4dd7ed33 100644 --- a/examples/directx9_example/directx9_example.vcxproj +++ b/examples/directx9_example/directx9_example.vcxproj @@ -81,7 +81,7 @@ Level3 Disabled - ..\..;$(DXSDK_DIR)Include;%(AdditionalIncludeDirectories) + ..\..;%(AdditionalIncludeDirectories);$(DXSDK_DIR)Include; true @@ -94,7 +94,7 @@ Level3 Disabled - ..\..;$(DXSDK_DIR)Include;%(AdditionalIncludeDirectories) + ..\..;%(AdditionalIncludeDirectories);$(DXSDK_DIR)Include; true @@ -109,7 +109,7 @@ MaxSpeed true true - ..\..;$(DXSDK_DIR)Include;%(AdditionalIncludeDirectories) + ..\..;%(AdditionalIncludeDirectories);$(DXSDK_DIR)Include; true @@ -126,7 +126,7 @@ MaxSpeed true true - ..\..;$(DXSDK_DIR)Include;%(AdditionalIncludeDirectories) + ..\..;%(AdditionalIncludeDirectories);$(DXSDK_DIR)Include; true From 60591dd7c6725b888d0a6f4740d43f8784ad98fc Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 14 Mar 2015 10:30:07 +0000 Subject: [PATCH 20/44] Fixed warning and split bit of SliderFloat() into a private ParseFormat() function --- imgui.cpp | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 36c3f0f51..3d09a3304 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4714,6 +4714,25 @@ static bool SliderFloatAsInputText(const char* label, float* v, const ImGuiID& i return value_changed; } +// Parse display precision back from the display format string +static void ParseFormat(const char* fmt, int& decimal_precision) +{ + while ((fmt = strchr(fmt, '%')) != NULL) + { + fmt++; + if (fmt[0] == '%') { fmt++; continue; } // Ignore "%%" + while (*fmt >= '0' && *fmt <= '9') + fmt++; + if (*fmt == '.') + { + decimal_precision = atoi(fmt + 1); + if (decimal_precision < 0 || decimal_precision > 10) + decimal_precision = 3; + } + break; + } +} + // Use power!=1.0 for logarithmic sliders. // Adjust display_format to decorate the value with a prefix or a suffix. // "%.3f" 1.234 @@ -4732,23 +4751,8 @@ bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, c if (!display_format) display_format = "%.3f"; - - // Parse display precision back from the display format string int decimal_precision = 3; - for (const char* p = display_format; p = strchr(p, '%'); ) - { - p++; - if (p[0] == '%') { p ++; continue; } // Ignore "%%" - while (*p >= '0' && *p <= '9') - p++; - if (*p == '.') - { - decimal_precision = atoi(p+1); - if (decimal_precision < 0 || decimal_precision > 10) - decimal_precision = 3; - } - break; - } + ParseFormat(display_format, decimal_precision); const ImVec2 label_size = CalcTextSize(label, NULL, true); const ImGuiAabb frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y) + style.FramePadding*2.0f); From 2b0acc128c6c4dd0f5fe15257442481bbf4e83ad Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 14 Mar 2015 10:32:29 +0000 Subject: [PATCH 21/44] Examples: MSVC: increase warning level from /W3 to /W4 for DirectX examples --- examples/directx11_example/directx11_example.vcxproj | 8 ++++---- examples/directx11_example/imgui_impl_dx11.cpp | 2 +- examples/directx11_example/main.cpp | 3 +++ examples/directx9_example/directx9_example.vcxproj | 8 ++++---- examples/directx9_example/imgui_impl_dx9.cpp | 2 +- examples/directx9_example/main.cpp | 3 +++ 6 files changed, 16 insertions(+), 10 deletions(-) diff --git a/examples/directx11_example/directx11_example.vcxproj b/examples/directx11_example/directx11_example.vcxproj index 556b04278..0ad66c4f1 100644 --- a/examples/directx11_example/directx11_example.vcxproj +++ b/examples/directx11_example/directx11_example.vcxproj @@ -79,7 +79,7 @@ - Level3 + Level4 Disabled ..\..;%(AdditionalIncludeDirectories);$(DXSDK_DIR)Include; @@ -92,7 +92,7 @@ - Level3 + Level4 Disabled ..\..;%(AdditionalIncludeDirectories);$(DXSDK_DIR)Include; @@ -105,7 +105,7 @@ - Level3 + Level4 MaxSpeed true true @@ -122,7 +122,7 @@ - Level3 + Level4 MaxSpeed true true diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index f6ee6b5de..4e209c871 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -146,7 +146,7 @@ static void ImGui_ImplDX11_RenderDrawLists(ImDrawList** const cmd_lists, int cmd g_pd3dDeviceContext->VSSetShader(NULL, NULL, 0); } -LRESULT ImGui_ImplDX11_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) +LRESULT ImGui_ImplDX11_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) { ImGuiIO& io = ImGui::GetIO(); switch (msg) diff --git a/examples/directx11_example/main.cpp b/examples/directx11_example/main.cpp index 571fe1da2..3bf4924f5 100644 --- a/examples/directx11_example/main.cpp +++ b/examples/directx11_example/main.cpp @@ -130,6 +130,9 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) int main(int argc, char** argv) { + (void)argc; + (void)argv; + // Create application window WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, WndProc, 0L, 0L, GetModuleHandle(NULL), NULL, LoadCursor(NULL, IDC_ARROW), NULL, NULL, L"ImGui Example", NULL }; RegisterClassEx(&wc); diff --git a/examples/directx9_example/directx9_example.vcxproj b/examples/directx9_example/directx9_example.vcxproj index f4dd7ed33..beaf53eac 100644 --- a/examples/directx9_example/directx9_example.vcxproj +++ b/examples/directx9_example/directx9_example.vcxproj @@ -79,7 +79,7 @@ - Level3 + Level4 Disabled ..\..;%(AdditionalIncludeDirectories);$(DXSDK_DIR)Include; @@ -92,7 +92,7 @@ - Level3 + Level4 Disabled ..\..;%(AdditionalIncludeDirectories);$(DXSDK_DIR)Include; @@ -105,7 +105,7 @@ - Level3 + Level4 MaxSpeed true true @@ -122,7 +122,7 @@ - Level3 + Level4 MaxSpeed true true diff --git a/examples/directx9_example/imgui_impl_dx9.cpp b/examples/directx9_example/imgui_impl_dx9.cpp index b64b70eba..f6f2a11a6 100644 --- a/examples/directx9_example/imgui_impl_dx9.cpp +++ b/examples/directx9_example/imgui_impl_dx9.cpp @@ -110,7 +110,7 @@ static void ImGui_ImplDX9_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_ } } -LRESULT ImGui_ImplDX9_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) +LRESULT ImGui_ImplDX9_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) { ImGuiIO& io = ImGui::GetIO(); switch (msg) diff --git a/examples/directx9_example/main.cpp b/examples/directx9_example/main.cpp index 5e0e58d64..07fbb7b4f 100644 --- a/examples/directx9_example/main.cpp +++ b/examples/directx9_example/main.cpp @@ -43,6 +43,9 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) int main(int argc, char** argv) { + (void)argc; + (void)argv; + // Create application window WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, WndProc, 0L, 0L, GetModuleHandle(NULL), NULL, LoadCursor(NULL, IDC_ARROW), NULL, NULL, L"ImGui Example", NULL }; RegisterClassEx(&wc); From 7c9bd7151248c2e03c9f4cf7f68d75df9fc5eff2 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 14 Mar 2015 10:41:42 +0000 Subject: [PATCH 22/44] Examples: MSVC: increase warning level from /W3 to /W4 for OpenGL examples --- examples/directx11_example/main.cpp | 5 +---- examples/directx9_example/main.cpp | 5 +---- examples/libs/gl3w/GL/gl3w.c | 5 +++++ examples/opengl3_example/imgui_impl_glfw_gl3.cpp | 8 ++++---- examples/opengl3_example/main.cpp | 4 ++-- examples/opengl3_example/opengl3_example.vcxproj | 8 ++++---- examples/opengl_example/imgui_impl_glfw.cpp | 8 ++++---- examples/opengl_example/main.cpp | 4 ++-- examples/opengl_example/opengl_example.vcxproj | 8 ++++---- 9 files changed, 27 insertions(+), 28 deletions(-) diff --git a/examples/directx11_example/main.cpp b/examples/directx11_example/main.cpp index 3bf4924f5..b051fd248 100644 --- a/examples/directx11_example/main.cpp +++ b/examples/directx11_example/main.cpp @@ -128,11 +128,8 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) return DefWindowProc(hWnd, msg, wParam, lParam); } -int main(int argc, char** argv) +int main(int, char**) { - (void)argc; - (void)argv; - // Create application window WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, WndProc, 0L, 0L, GetModuleHandle(NULL), NULL, LoadCursor(NULL, IDC_ARROW), NULL, NULL, L"ImGui Example", NULL }; RegisterClassEx(&wc); diff --git a/examples/directx9_example/main.cpp b/examples/directx9_example/main.cpp index 07fbb7b4f..9a01ba31e 100644 --- a/examples/directx9_example/main.cpp +++ b/examples/directx9_example/main.cpp @@ -41,11 +41,8 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) return DefWindowProc(hWnd, msg, wParam, lParam); } -int main(int argc, char** argv) +int main(int, char**) { - (void)argc; - (void)argv; - // Create application window WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, WndProc, 0L, 0L, GetModuleHandle(NULL), NULL, LoadCursor(NULL, IDC_ARROW), NULL, NULL, L"ImGui Example", NULL }; RegisterClassEx(&wc); diff --git a/examples/libs/gl3w/GL/gl3w.c b/examples/libs/gl3w/GL/gl3w.c index d66b972f1..bea6e40e4 100644 --- a/examples/libs/gl3w/GL/gl3w.c +++ b/examples/libs/gl3w/GL/gl3w.c @@ -1,5 +1,10 @@ #include +#ifdef _MSC_VER +#pragma warning (disable: 4055) // warning C4055: 'type cast' : from data pointer 'void *' to function pointer +#pragma warning (disable: 4152) // warning C4152: nonstandard extension, function/data pointer conversion in expression +#endif + #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN 1 #include diff --git a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp index fa669d9c8..07bf5a579 100644 --- a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp +++ b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp @@ -123,18 +123,18 @@ static void ImGui_ImplGlfwGL3_SetClipboardText(const char* text) glfwSetClipboardString(g_Window, text); } -void ImGui_ImplGlfwGL3_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods) +void ImGui_ImplGlfwGL3_MouseButtonCallback(GLFWwindow*, int button, int action, int /*mods*/) { if (action == GLFW_PRESS && button >= 0 && button < 3) g_MousePressed[button] = true; } -void ImGui_ImplGlfwGL3_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset) +void ImGui_ImplGlfwGL3_ScrollCallback(GLFWwindow*, double /*xoffset*/, double yoffset) { g_MouseWheel += (float)yoffset; // Use fractional mouse wheel, 1.0 unit 5 lines. } -void ImGui_ImplGlfwGL3_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods) +void ImGui_ImplGlfwGL3_KeyCallback(GLFWwindow*, int key, int, int action, int mods) { ImGuiIO& io = ImGui::GetIO(); if (action == GLFW_PRESS) @@ -146,7 +146,7 @@ void ImGui_ImplGlfwGL3_KeyCallback(GLFWwindow* window, int key, int scancode, in io.KeyAlt = (mods & GLFW_MOD_ALT) != 0; } -void ImGui_ImplGlfwGL3_CharCallback(GLFWwindow* window, unsigned int c) +void ImGui_ImplGlfwGL3_CharCallback(GLFWwindow*, unsigned int c) { ImGuiIO& io = ImGui::GetIO(); if (c > 0 && c < 0x10000) diff --git a/examples/opengl3_example/main.cpp b/examples/opengl3_example/main.cpp index 9651970b3..dc88a7c66 100644 --- a/examples/opengl3_example/main.cpp +++ b/examples/opengl3_example/main.cpp @@ -8,10 +8,10 @@ static void error_callback(int error, const char* description) { - fprintf(stderr, "Error: %s\n", description); + fprintf(stderr, "Error %d: %s\n", error, description); } -int main(int argc, char** argv) +int main(int, char**) { // Setup window glfwSetErrorCallback(error_callback); diff --git a/examples/opengl3_example/opengl3_example.vcxproj b/examples/opengl3_example/opengl3_example.vcxproj index 2a2c0b4f9..202c5f734 100644 --- a/examples/opengl3_example/opengl3_example.vcxproj +++ b/examples/opengl3_example/opengl3_example.vcxproj @@ -83,7 +83,7 @@ - Level3 + Level4 Disabled $(SolutionDir)\libs\glfw\include;$(SolutionDir)\libs\gl3w;..\..;%(AdditionalIncludeDirectories) @@ -97,7 +97,7 @@ - Level3 + Level4 Disabled $(SolutionDir)\libs\glfw\include;$(SolutionDir)\libs\gl3w;..\..;%(AdditionalIncludeDirectories) @@ -111,7 +111,7 @@ - Level3 + Level4 MaxSpeed true true @@ -130,7 +130,7 @@ - Level3 + Level4 MaxSpeed true true diff --git a/examples/opengl_example/imgui_impl_glfw.cpp b/examples/opengl_example/imgui_impl_glfw.cpp index a6b9cb40a..00313e453 100644 --- a/examples/opengl_example/imgui_impl_glfw.cpp +++ b/examples/opengl_example/imgui_impl_glfw.cpp @@ -103,18 +103,18 @@ static void ImGui_ImplGlfw_SetClipboardText(const char* text) glfwSetClipboardString(g_Window, text); } -void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods) +void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow*, int button, int action, int /*mods*/) { if (action == GLFW_PRESS && button >= 0 && button < 3) g_MousePressed[button] = true; } -void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset) +void ImGui_ImplGlfw_ScrollCallback(GLFWwindow*, double /*xoffset*/, double yoffset) { g_MouseWheel += (float)yoffset; // Use fractional mouse wheel, 1.0 unit 5 lines. } -void ImGui_ImplGlFw_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods) +void ImGui_ImplGlFw_KeyCallback(GLFWwindow*, int key, int, int action, int mods) { ImGuiIO& io = ImGui::GetIO(); if (action == GLFW_PRESS) @@ -126,7 +126,7 @@ void ImGui_ImplGlFw_KeyCallback(GLFWwindow* window, int key, int scancode, int a io.KeyAlt = (mods & GLFW_MOD_ALT) != 0; } -void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c) +void ImGui_ImplGlfw_CharCallback(GLFWwindow*, unsigned int c) { ImGuiIO& io = ImGui::GetIO(); if (c > 0 && c < 0x10000) diff --git a/examples/opengl_example/main.cpp b/examples/opengl_example/main.cpp index c9d303d04..471f9a29a 100644 --- a/examples/opengl_example/main.cpp +++ b/examples/opengl_example/main.cpp @@ -7,10 +7,10 @@ static void error_callback(int error, const char* description) { - fprintf(stderr, "Error: %s\n", description); + fprintf(stderr, "Error %d: %s\n", error, description); } -int main(int argc, char** argv) +int main(int, char**) { // Setup window glfwSetErrorCallback(error_callback); diff --git a/examples/opengl_example/opengl_example.vcxproj b/examples/opengl_example/opengl_example.vcxproj index f39a929f6..718fedc56 100644 --- a/examples/opengl_example/opengl_example.vcxproj +++ b/examples/opengl_example/opengl_example.vcxproj @@ -83,7 +83,7 @@ - Level3 + Level4 Disabled $(SolutionDir)\libs\glfw\include;..\..;%(AdditionalIncludeDirectories) @@ -97,7 +97,7 @@ - Level3 + Level4 Disabled $(SolutionDir)\libs\glfw\include;..\..;%(AdditionalIncludeDirectories) @@ -111,7 +111,7 @@ - Level3 + Level4 MaxSpeed true true @@ -130,7 +130,7 @@ - Level3 + Level4 MaxSpeed true true From e97d02a294434d12419fc267cb9c350d752994bd Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 14 Mar 2015 10:49:26 +0000 Subject: [PATCH 23/44] Examples: Fixed Clang warnings in DirectX examples --- examples/directx11_example/imgui_impl_dx11.cpp | 4 ++-- examples/directx9_example/imgui_impl_dx9.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index 4e209c871..2502b98dc 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -171,11 +171,11 @@ LRESULT ImGui_ImplDX11_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lPar io.MousePos.y = (signed short)(lParam >> 16); return true; case WM_KEYDOWN: - if (wParam >= 0 && wParam < 256) + if (wParam < 256) io.KeysDown[wParam] = 1; return true; case WM_KEYUP: - if (wParam >= 0 && wParam < 256) + if (wParam < 256) io.KeysDown[wParam] = 0; return true; case WM_CHAR: diff --git a/examples/directx9_example/imgui_impl_dx9.cpp b/examples/directx9_example/imgui_impl_dx9.cpp index f6f2a11a6..60302d4cd 100644 --- a/examples/directx9_example/imgui_impl_dx9.cpp +++ b/examples/directx9_example/imgui_impl_dx9.cpp @@ -135,11 +135,11 @@ LRESULT ImGui_ImplDX9_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lPara io.MousePos.y = (signed short)(lParam >> 16); return true; case WM_KEYDOWN: - if (wParam >= 0 && wParam < 256) + if (wParam < 256) io.KeysDown[wParam] = 1; return true; case WM_KEYUP: - if (wParam >= 0 && wParam < 256) + if (wParam < 256) io.KeysDown[wParam] = 0; return true; case WM_CHAR: From 55edd522c2788ba6461e6cd7e4cac499001f2ccb Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 14 Mar 2015 11:24:53 +0000 Subject: [PATCH 24/44] Examples: Fixed Makefile --- examples/opengl3_example/Makefile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/examples/opengl3_example/Makefile b/examples/opengl3_example/Makefile index 208d279f6..4357e331f 100644 --- a/examples/opengl3_example/Makefile +++ b/examples/opengl3_example/Makefile @@ -10,8 +10,9 @@ #CXX = g++ -OBJS = main.o imgui_impl_glfw_gl3.o gl3w/GL/gl3w.o +OBJS = main.o imgui_impl_glfw_gl3.o OBJS += ../../imgui.o +OBJS += ../libs/gl3w/GL/gl3w.o UNAME_S := $(shell uname -s) @@ -31,7 +32,7 @@ ifeq ($(UNAME_S), Darwin) #APPLE LIBS += -L/usr/local/lib LIBS += -lglfw3 - CXXFLAGS = -I../../ -Igl3w -I/usr/local/Cellar/glew/1.10.0/include -I/usr/local/include + CXXFLAGS = -I../../ -I../libs/gl3w -I/usr/local/Cellar/glew/1.10.0/include -I/usr/local/include CXXFLAGS += -Wall # CXXFLAGS += -D__APPLE__ CFLAGS = $(CXXFLAGS) From 06fbeed41a0423a134082d3db7e337a87d0491a5 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 14 Mar 2015 11:29:09 +0000 Subject: [PATCH 25/44] Examples: Fixed Makefile --- examples/opengl3_example/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/opengl3_example/Makefile b/examples/opengl3_example/Makefile index 4357e331f..cc7ec31e4 100644 --- a/examples/opengl3_example/Makefile +++ b/examples/opengl3_example/Makefile @@ -21,7 +21,7 @@ ifeq ($(UNAME_S), Linux) #LINUX ECHO_MESSAGE = "Linux" LIBS = `pkg-config --static --libs glfw3` - CXXFLAGS = -I../../ -Igl3w `pkg-config --cflags glfw3` + CXXFLAGS = -I../../ -I../libs/gl3w `pkg-config --cflags glfw3` CXXFLAGS += -Wall CFLAGS = $(CXXFLAGS) endif From 93befadc0bd7008a06d8691a5470b4cc81c53f1a Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 14 Mar 2015 23:33:12 +0000 Subject: [PATCH 26/44] Slider code tweaks --- imgui.cpp | 160 +++++++++++++++++++++++++++--------------------------- 1 file changed, 79 insertions(+), 81 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 3d09a3304..2689f631a 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4680,6 +4680,7 @@ static void ApplyNumericalTextInput(const char* buf, float *v) *v = op_v; } +// Create text input in place of a slider (when CTRL+Clicking on slider) static bool SliderFloatAsInputText(const char* label, float* v, const ImGuiID& id, int decimal_precision) { ImGuiState& g = *GImGui; @@ -4749,11 +4750,6 @@ bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, c const ImGuiID id = window->GetID(label); const float w = ImGui::CalcItemWidth(); - if (!display_format) - display_format = "%.3f"; - int decimal_precision = 3; - ParseFormat(display_format, decimal_precision); - const ImVec2 label_size = CalcTextSize(label, NULL, true); const ImGuiAabb frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y) + style.FramePadding*2.0f); const ImGuiAabb slider_bb(frame_bb.Min + style.FramePadding, frame_bb.Max - style.FramePadding); @@ -4766,10 +4762,37 @@ bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, c return false; } - const bool tab_focus_requested = window->FocusItemRegister(g.ActiveId == id); + const bool hovered = IsHovered(slider_bb, id); + if (hovered) + g.HoveredId = id; - const bool is_unbound = v_min == -FLT_MAX || v_min == FLT_MAX || v_max == -FLT_MAX || v_max == FLT_MAX; - const bool is_logarithmic = abs(power - 1.0f) > 0.0001f; + if (!display_format) + display_format = "%.3f"; + int decimal_precision = 3; + ParseFormat(display_format, decimal_precision); + + const bool tab_focus_requested = window->FocusItemRegister(g.ActiveId == id); + const bool is_unbound = (v_min == -FLT_MAX || v_min == FLT_MAX || v_max == -FLT_MAX || v_max == FLT_MAX); + + bool start_text_input = false; + if (tab_focus_requested || (hovered && g.IO.MouseClicked[0])) + { + SetActiveId(id); + FocusWindow(window); + + const bool is_ctrl_down = g.IO.KeyCtrl; + if (tab_focus_requested || is_ctrl_down || is_unbound) + { + start_text_input = true; + g.SliderAsInputTextId = 0; + } + } + + // Tabbing or CTRL-clicking through slider turns into an input box + if (start_text_input || (g.ActiveId == id && id == g.SliderAsInputTextId)) + return SliderFloatAsInputText(label, v, id, decimal_precision); + + ItemSize(bb); const float grab_size_in_units = 1.0f; // In 'v' units. Probably needs to be parametrized, based on a 'v_step' value? decimal precision? float grab_size_in_pixels; @@ -4799,95 +4822,70 @@ bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, c } } - const bool hovered = IsHovered(slider_bb, id); - if (hovered) - g.HoveredId = id; - - bool start_text_input = false; - if (tab_focus_requested || (hovered && g.IO.MouseClicked[0])) - { - SetActiveId(id); - FocusWindow(window); - - const bool is_ctrl_down = g.IO.KeyCtrl; - if (tab_focus_requested || is_ctrl_down || is_unbound) - { - start_text_input = true; - g.SliderAsInputTextId = 0; - } - } - - // Tabbing or CTRL-clicking through slider turns into an input box - bool value_changed = false; - if (start_text_input || (g.ActiveId == id && id == g.SliderAsInputTextId)) - { - value_changed = SliderFloatAsInputText(label, v, id, decimal_precision); - return value_changed; - } - - ItemSize(bb); RenderFrame(frame_bb.Min, frame_bb.Max, window->Color(ImGuiCol_FrameBg), true, style.FrameRounding); - // Process clicking on the slider - if (g.ActiveId == id) + const bool is_logarithmic = abs(power - 1.0f) > 0.0001f; + bool value_changed = false; + if (!is_unbound) { - if (!is_unbound && g.IO.MouseDown[0]) + // Process clicking on the slider + if (g.ActiveId == id) { - const float normalized_pos = ImClamp((g.IO.MousePos.x - slider_effective_x1) / slider_effective_w, 0.0f, 1.0f); - - float new_value; - if (is_logarithmic) + if (g.IO.MouseDown[0]) { - // Account for logarithmic scale on both sides of the zero - if (normalized_pos < linear_zero_pos) + const float normalized_pos = ImClamp((g.IO.MousePos.x - slider_effective_x1) / slider_effective_w, 0.0f, 1.0f); + + float new_value; + if (is_logarithmic) { - // Negative: rescale to the negative range before powering - float a = 1.0f - (normalized_pos / linear_zero_pos); - a = powf(a, power); - new_value = ImLerp(ImMin(v_max,0.f), v_min, a); + // Account for logarithmic scale on both sides of the zero + if (normalized_pos < linear_zero_pos) + { + // Negative: rescale to the negative range before powering + float a = 1.0f - (normalized_pos / linear_zero_pos); + a = powf(a, power); + new_value = ImLerp(ImMin(v_max,0.f), v_min, a); + } + else + { + // Positive: rescale to the positive range before powering + float a; + if (fabsf(linear_zero_pos - 1.0f) > 1.e-6) + a = (normalized_pos - linear_zero_pos) / (1.0f - linear_zero_pos); + else + a = normalized_pos; + a = powf(a, power); + new_value = ImLerp(ImMax(v_min,0.0f), v_max, a); + } } else { - // Positive: rescale to the positive range before powering - float a; - if (fabsf(linear_zero_pos - 1.0f) > 1.e-6) - a = (normalized_pos - linear_zero_pos) / (1.0f - linear_zero_pos); - else - a = normalized_pos; - a = powf(a, power); - new_value = ImLerp(ImMax(v_min,0.0f), v_max, a); + // Linear slider + new_value = ImLerp(v_min, v_max, normalized_pos); + } + + // Round past decimal precision + // 0->1, 1->0.1, 2->0.01, etc. + // So when our value is 1.99999 with a precision of 0.001 we'll end up rounding to 2.0 + const float min_step = 1.0f / powf(10.0f, (float)decimal_precision); + const float remainder = fmodf(new_value, min_step); + if (remainder <= min_step*0.5f) + new_value -= remainder; + else + new_value += (min_step - remainder); + + if (*v != new_value) + { + *v = new_value; + value_changed = true; } } else { - // Linear slider - new_value = ImLerp(v_min, v_max, normalized_pos); - } - - // Round past decimal precision - // 0->1, 1->0.1, 2->0.01, etc. - // So when our value is 1.99999 with a precision of 0.001 we'll end up rounding to 2.0 - const float min_step = 1.0f / powf(10.0f, (float)decimal_precision); - const float remainder = fmodf(new_value, min_step); - if (remainder <= min_step*0.5f) - new_value -= remainder; - else - new_value += (min_step - remainder); - - if (*v != new_value) - { - *v = new_value; - value_changed = true; + SetActiveId(0); } } - else - { - SetActiveId(0); - } - } - if (!is_unbound) - { // Calculate slider grab positioning float grab_t; if (is_logarithmic) From ce87c69c38d3a60bedc6e6ef78bfdac1c4da5b97 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 14 Mar 2015 23:44:32 +0000 Subject: [PATCH 27/44] Passing ImGuiID by copy (32-bits) --- imgui.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 2689f631a..96a9dba20 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -420,7 +420,7 @@ struct ImGuiIniData; struct ImGuiState; struct ImGuiWindow; -static bool ButtonBehaviour(const ImGuiAabb& bb, const ImGuiID& id, bool* out_hovered, bool* out_held, bool allow_key_modifiers, bool repeat = false, bool pressed_on_click = false); +static bool ButtonBehaviour(const ImGuiAabb& bb, ImGuiID id, bool* out_hovered, bool* out_held, bool allow_key_modifiers, bool repeat = false, bool pressed_on_click = false); static void LogText(const ImVec2& ref_pos, const char* text, const char* text_end = NULL); static void RenderText(ImVec2 pos, const char* text, const char* text_end = NULL, bool hide_text_after_hash = true); @@ -1206,7 +1206,7 @@ static void SetActiveId(ImGuiID id) g.ActiveIdIsFocusedOnly = false; } -static void RegisterAliveId(const ImGuiID& id) +static void RegisterAliveId(ImGuiID id) { ImGuiState& g = *GImGui; if (g.ActiveId == id) @@ -4015,7 +4015,7 @@ void ImGui::LabelText(const char* label, const char* fmt, ...) va_end(args); } -static bool IsHovered(const ImGuiAabb& bb, const ImGuiID& id) +static bool IsHovered(const ImGuiAabb& bb, ImGuiID id) { ImGuiState& g = *GImGui; if (g.HoveredId == 0) @@ -4030,7 +4030,7 @@ static bool IsHovered(const ImGuiAabb& bb, const ImGuiID& id) return false; } -static bool ButtonBehaviour(const ImGuiAabb& bb, const ImGuiID& id, bool* out_hovered, bool* out_held, bool allow_key_modifiers, bool repeat, bool pressed_on_click) +static bool ButtonBehaviour(const ImGuiAabb& bb, ImGuiID id, bool* out_hovered, bool* out_held, bool allow_key_modifiers, bool repeat, bool pressed_on_click) { ImGuiState& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); @@ -4681,7 +4681,7 @@ static void ApplyNumericalTextInput(const char* buf, float *v) } // Create text input in place of a slider (when CTRL+Clicking on slider) -static bool SliderFloatAsInputText(const char* label, float* v, const ImGuiID& id, int decimal_precision) +static bool SliderFloatAsInputText(const char* label, float* v, ImGuiID id, int decimal_precision) { ImGuiState& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); From 1ef789bb689a3473947c944822b8f3fe6a7a6e4e Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 14 Mar 2015 23:55:07 +0000 Subject: [PATCH 28/44] Slider code tweaks, split into a SliderBehaviour() function --- imgui.cpp | 150 +++++++++++++++++++++++++++++------------------------- 1 file changed, 81 insertions(+), 69 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 96a9dba20..bbf50fa35 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4734,80 +4734,34 @@ static void ParseFormat(const char* fmt, int& decimal_precision) } } -// Use power!=1.0 for logarithmic sliders. -// Adjust display_format to decorate the value with a prefix or a suffix. -// "%.3f" 1.234 -// "%5.2f secs" 01.23 secs -// "Gold: %.0f" Gold: 1 -bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, const char* display_format, float power) +static bool SliderBehaviour(const ImGuiAabb& frame_bb, const ImGuiAabb& slider_bb, ImGuiID id, float* v, float v_min, float v_max, float power, int decimal_precision) { ImGuiState& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems) - return false; - const ImGuiStyle& style = g.Style; - const ImGuiID id = window->GetID(label); - const float w = ImGui::CalcItemWidth(); - const ImVec2 label_size = CalcTextSize(label, NULL, true); - const ImGuiAabb frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y) + style.FramePadding*2.0f); - const ImGuiAabb slider_bb(frame_bb.Min + style.FramePadding, frame_bb.Max - style.FramePadding); - const ImGuiAabb bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f)); + // Draw frame + RenderFrame(frame_bb.Min, frame_bb.Max, window->Color(ImGuiCol_FrameBg), true, style.FrameRounding); - // NB- we don't call ItemSize() yet becausae we may turn into a text edit box later in the function - if (!ItemAdd(slider_bb, &id)) - { - ItemSize(bb); - return false; - } + const bool is_finite = (v_min != -FLT_MAX && v_min != FLT_MAX && v_max != -FLT_MAX && v_max != FLT_MAX); + const bool is_non_linear = abs(power - 1.0f) > 0.0001f; - const bool hovered = IsHovered(slider_bb, id); - if (hovered) - g.HoveredId = id; - - if (!display_format) - display_format = "%.3f"; - int decimal_precision = 3; - ParseFormat(display_format, decimal_precision); - - const bool tab_focus_requested = window->FocusItemRegister(g.ActiveId == id); - const bool is_unbound = (v_min == -FLT_MAX || v_min == FLT_MAX || v_max == -FLT_MAX || v_max == FLT_MAX); - - bool start_text_input = false; - if (tab_focus_requested || (hovered && g.IO.MouseClicked[0])) - { - SetActiveId(id); - FocusWindow(window); - - const bool is_ctrl_down = g.IO.KeyCtrl; - if (tab_focus_requested || is_ctrl_down || is_unbound) - { - start_text_input = true; - g.SliderAsInputTextId = 0; - } - } - - // Tabbing or CTRL-clicking through slider turns into an input box - if (start_text_input || (g.ActiveId == id && id == g.SliderAsInputTextId)) - return SliderFloatAsInputText(label, v, id, decimal_precision); - - ItemSize(bb); - - const float grab_size_in_units = 1.0f; // In 'v' units. Probably needs to be parametrized, based on a 'v_step' value? decimal precision? + const float slider_w = slider_bb.GetWidth(); float grab_size_in_pixels; - if (decimal_precision > 0 || is_unbound) + if (decimal_precision > 0 || !is_finite) grab_size_in_pixels = style.GrabMinSize; else - grab_size_in_pixels = ImMax(grab_size_in_units * (w / (v_max-v_min+1.0f)), style.GrabMinSize); // Integer sliders + grab_size_in_pixels = ImMax(1.0f * (slider_w / (v_max-v_min+1.0f)), style.GrabMinSize); // Integer sliders, if possible have the grab size represent 1 unit const float slider_effective_w = slider_bb.GetWidth() - grab_size_in_pixels; const float slider_effective_x1 = slider_bb.Min.x + grab_size_in_pixels*0.5f; const float slider_effective_x2 = slider_bb.Max.x - grab_size_in_pixels*0.5f; - // For logarithmic sliders that cross over sign boundary we want the exponential increase to be symmetric around 0.0f - float linear_zero_pos = 0.0f; // 0.0->1.0f - if (!is_unbound) + bool value_changed = false; + + if (is_finite) { + // For logarithmic sliders that cross over sign boundary we want the exponential increase to be symmetric around 0.0f + float linear_zero_pos = 0.0f; // 0.0->1.0f if (v_min * v_max < 0.0f) { // Different sign @@ -4820,23 +4774,16 @@ bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, c // Same sign linear_zero_pos = v_min < 0.0f ? 1.0f : 0.0f; } - } - RenderFrame(frame_bb.Min, frame_bb.Max, window->Color(ImGuiCol_FrameBg), true, style.FrameRounding); - - const bool is_logarithmic = abs(power - 1.0f) > 0.0001f; - bool value_changed = false; - if (!is_unbound) - { // Process clicking on the slider if (g.ActiveId == id) { if (g.IO.MouseDown[0]) { const float normalized_pos = ImClamp((g.IO.MousePos.x - slider_effective_x1) / slider_effective_w, 0.0f, 1.0f); - + float new_value; - if (is_logarithmic) + if (is_non_linear) { // Account for logarithmic scale on both sides of the zero if (normalized_pos < linear_zero_pos) @@ -4888,7 +4835,7 @@ bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, c // Calculate slider grab positioning float grab_t; - if (is_logarithmic) + if (is_non_linear) { float v_clamped = ImClamp(*v, v_min, v_max); if (v_clamped < 0.0f) @@ -4914,6 +4861,71 @@ bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, c window->DrawList->AddRectFilled(grab_bb.Min, grab_bb.Max, window->Color(g.ActiveId == id ? ImGuiCol_SliderGrabActive : ImGuiCol_SliderGrab)); } + return value_changed; +} + +// Use power!=1.0 for logarithmic sliders. +// Adjust display_format to decorate the value with a prefix or a suffix. +// "%.3f" 1.234 +// "%5.2f secs" 01.23 secs +// "Gold: %.0f" Gold: 1 +bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, const char* display_format, float power) +{ + ImGuiState& g = *GImGui; + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return false; + + const ImGuiStyle& style = g.Style; + const ImGuiID id = window->GetID(label); + const float w = ImGui::CalcItemWidth(); + + const ImVec2 label_size = CalcTextSize(label, NULL, true); + const ImGuiAabb frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y) + style.FramePadding*2.0f); + const ImGuiAabb slider_bb(frame_bb.Min + style.FramePadding, frame_bb.Max - style.FramePadding); + const ImGuiAabb bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f)); + + // NB- we don't call ItemSize() yet becausae we may turn into a text edit box below + if (!ItemAdd(slider_bb, &id)) + { + ItemSize(bb); + return false; + } + + const bool hovered = IsHovered(slider_bb, id); + if (hovered) + g.HoveredId = id; + + if (!display_format) + display_format = "%.3f"; + int decimal_precision = 3; + ParseFormat(display_format, decimal_precision); + + const bool tab_focus_requested = window->FocusItemRegister(g.ActiveId == id); + const bool is_finite = (v_min != -FLT_MAX && v_min != FLT_MAX && v_max != -FLT_MAX && v_max != FLT_MAX); + + // Tabbing or CTRL-clicking through slider turns into an input box + bool start_text_input = false; + if (tab_focus_requested || (hovered && g.IO.MouseClicked[0])) + { + SetActiveId(id); + FocusWindow(window); + + const bool is_ctrl_down = g.IO.KeyCtrl; + if (tab_focus_requested || is_ctrl_down || !is_finite) + { + start_text_input = true; + g.SliderAsInputTextId = 0; + } + } + if (start_text_input || (g.ActiveId == id && id == g.SliderAsInputTextId)) + return SliderFloatAsInputText(label, v, id, decimal_precision); + + ItemSize(bb); + + // Actual slider behavior + render grab + bool value_changed = SliderBehaviour(frame_bb, slider_bb, id, v, v_min, v_max, power, decimal_precision); + // Display value using user-provided display format so user can add prefix/suffix/decorations to the value. char value_buf[64]; char* value_buf_end = value_buf + ImFormatString(value_buf, IM_ARRAYSIZE(value_buf), display_format, *v); From 98eeeab0255f1839962457582439b53823675bb3 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 15 Mar 2015 01:23:56 +0000 Subject: [PATCH 29/44] Added ImGuiStyleVar_GrabMinSize enum value for PushStyleVar() --- imgui.cpp | 1 + imgui.h | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index bbf50fa35..5d54e062c 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3382,6 +3382,7 @@ static float* GetStyleVarFloatAddr(ImGuiStyleVar idx) case ImGuiStyleVar_ChildWindowRounding: return &g.Style.ChildWindowRounding; case ImGuiStyleVar_FrameRounding: return &g.Style.FrameRounding; case ImGuiStyleVar_TreeNodeSpacing: return &g.Style.TreeNodeSpacing; + case ImGuiStyleVar_GrabMinSize: return &g.Style.GrabMinSize; } return NULL; } diff --git a/imgui.h b/imgui.h index 0ad58bf1a..f3c51b6de 100644 --- a/imgui.h +++ b/imgui.h @@ -502,7 +502,8 @@ enum ImGuiStyleVar_ ImGuiStyleVar_FrameRounding, // float ImGuiStyleVar_ItemSpacing, // ImVec2 ImGuiStyleVar_ItemInnerSpacing, // ImVec2 - ImGuiStyleVar_TreeNodeSpacing // float + ImGuiStyleVar_TreeNodeSpacing, // float + ImGuiStyleVar_GrabMinSize // float }; // Enumeration for ColorEditMode() From 6da83cd5b7420feb80be05430f62673c0e2d2e9c Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 15 Mar 2015 01:27:37 +0000 Subject: [PATCH 30/44] Plot: size provided to PlotHistogram(), PlotLines() include the padding (sorry users). --- imgui.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 5d54e062c..5dbc408a9 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5074,11 +5074,11 @@ static void Plot(ImGuiPlotType plot_type, const char* label, float (*values_gett const ImVec2 label_size = ImGui::CalcTextSize(label, NULL, true); if (graph_size.x == 0.0f) - graph_size.x = ImGui::CalcItemWidth(); + graph_size.x = ImGui::CalcItemWidth() + (style.FramePadding.x * 2); if (graph_size.y == 0.0f) - graph_size.y = label_size.y; + graph_size.y = label_size.y + (style.FramePadding.y * 2); - const ImGuiAabb frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(graph_size.x, graph_size.y) + style.FramePadding*2.0f); + const ImGuiAabb frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(graph_size.x, graph_size.y)); const ImGuiAabb graph_bb(frame_bb.Min + style.FramePadding, frame_bb.Max - style.FramePadding); const ImGuiAabb bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0)); ItemSize(bb); @@ -9026,10 +9026,10 @@ void ImGui::ShowTestWindow(bool* opened) phase += 0.10f*values_offset; } } - ImGui::PlotLines("Frame Times", &values.front(), (int)values.size(), (int)values_offset, "avg 0.0", -1.0f, 1.0f, ImVec2(0,70)); + ImGui::PlotLines("Frame Times", &values.front(), (int)values.size(), (int)values_offset, "avg 0.0", -1.0f, 1.0f, ImVec2(0,80)); ImGui::SameLine(); ImGui::Checkbox("pause", &pause); - ImGui::PlotHistogram("Histogram", arr, IM_ARRAYSIZE(arr), 0, NULL, 0.0f, 1.0f, ImVec2(0,70)); + ImGui::PlotHistogram("Histogram", arr, IM_ARRAYSIZE(arr), 0, NULL, 0.0f, 1.0f, ImVec2(0,80)); } if (ImGui::CollapsingHeader("Horizontal Layout")) From ce8150ce6969aec0d85b74bfb52ad3f6ee1f1e80 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 15 Mar 2015 01:36:29 +0000 Subject: [PATCH 31/44] Slider fix hovering bounding test excluding padding between outer frame and grab --- imgui.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 5dbc408a9..dbc7b2513 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4887,13 +4887,13 @@ bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, c const ImGuiAabb bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f)); // NB- we don't call ItemSize() yet becausae we may turn into a text edit box below - if (!ItemAdd(slider_bb, &id)) + if (!ItemAdd(frame_bb, &id)) { ItemSize(bb); return false; } - const bool hovered = IsHovered(slider_bb, id); + const bool hovered = IsHovered(frame_bb, id); if (hovered) g.HoveredId = id; From c1547dd79ed4533a73c8bf4d2c3b4dadaefc8030 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 15 Mar 2015 01:47:12 +0000 Subject: [PATCH 32/44] Internal SliderBehaviour() function now supports vertical sliders --- imgui.cpp | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index dbc7b2513..bbc67c94b 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4735,7 +4735,7 @@ static void ParseFormat(const char* fmt, int& decimal_precision) } } -static bool SliderBehaviour(const ImGuiAabb& frame_bb, const ImGuiAabb& slider_bb, ImGuiID id, float* v, float v_min, float v_max, float power, int decimal_precision) +static bool SliderBehaviour(const ImGuiAabb& frame_bb, const ImGuiAabb& slider_bb, ImGuiID id, float* v, float v_min, float v_max, float power, int decimal_precision, bool horizontal) { ImGuiState& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); @@ -4747,15 +4747,15 @@ static bool SliderBehaviour(const ImGuiAabb& frame_bb, const ImGuiAabb& slider_b const bool is_finite = (v_min != -FLT_MAX && v_min != FLT_MAX && v_max != -FLT_MAX && v_max != FLT_MAX); const bool is_non_linear = abs(power - 1.0f) > 0.0001f; - const float slider_w = slider_bb.GetWidth(); - float grab_size_in_pixels; + const float slider_sz = horizontal ? slider_bb.GetWidth() : slider_bb.GetHeight(); + float grab_sz; if (decimal_precision > 0 || !is_finite) - grab_size_in_pixels = style.GrabMinSize; + grab_sz = style.GrabMinSize; else - grab_size_in_pixels = ImMax(1.0f * (slider_w / (v_max-v_min+1.0f)), style.GrabMinSize); // Integer sliders, if possible have the grab size represent 1 unit - const float slider_effective_w = slider_bb.GetWidth() - grab_size_in_pixels; - const float slider_effective_x1 = slider_bb.Min.x + grab_size_in_pixels*0.5f; - const float slider_effective_x2 = slider_bb.Max.x - grab_size_in_pixels*0.5f; + grab_sz = ImMax(1.0f * (slider_sz / (v_max-v_min+1.0f)), style.GrabMinSize); // Integer sliders, if possible have the grab size represent 1 unit + const float slider_usable_sz = slider_sz - grab_sz; + const float slider_usable_pos_min = (horizontal ? slider_bb.Min.x : slider_bb.Min.y) + grab_sz*0.5f; + const float slider_usable_pos_max = (horizontal ? slider_bb.Max.x : slider_bb.Max.y) - grab_sz*0.5f; bool value_changed = false; @@ -4781,7 +4781,10 @@ static bool SliderBehaviour(const ImGuiAabb& frame_bb, const ImGuiAabb& slider_b { if (g.IO.MouseDown[0]) { - const float normalized_pos = ImClamp((g.IO.MousePos.x - slider_effective_x1) / slider_effective_w, 0.0f, 1.0f); + const float mouse_abs_pos = horizontal ? g.IO.MousePos.x : g.IO.MousePos.y; + float normalized_pos = ImClamp((mouse_abs_pos - slider_usable_pos_min) / slider_usable_sz, 0.0f, 1.0f); + if (!horizontal) + normalized_pos = 1.0f - normalized_pos; float new_value; if (is_non_linear) @@ -4857,8 +4860,14 @@ static bool SliderBehaviour(const ImGuiAabb& frame_bb, const ImGuiAabb& slider_b } // Draw - const float grab_x = ImLerp(slider_effective_x1, slider_effective_x2, grab_t); - const ImGuiAabb grab_bb(ImVec2(grab_x-grab_size_in_pixels*0.5f,frame_bb.Min.y+2.0f), ImVec2(grab_x+grab_size_in_pixels*0.5f,frame_bb.Max.y-2.0f)); + if (!horizontal) + grab_t = 1.0f - grab_t; + const float grab_pos = ImLerp(slider_usable_pos_min, slider_usable_pos_max, grab_t); + ImGuiAabb grab_bb; + if (horizontal) + grab_bb = ImGuiAabb(ImVec2(grab_pos - grab_sz*0.5f, frame_bb.Min.y + 2.0f), ImVec2(grab_pos + grab_sz*0.5f, frame_bb.Max.y - 2.0f)); + else + grab_bb = ImGuiAabb(ImVec2(frame_bb.Min.x + 2.0f, grab_pos - grab_sz*0.5f), ImVec2(frame_bb.Max.x - 2.0f, grab_pos + grab_sz*0.5f)); window->DrawList->AddRectFilled(grab_bb.Min, grab_bb.Max, window->Color(g.ActiveId == id ? ImGuiCol_SliderGrabActive : ImGuiCol_SliderGrab)); } @@ -4925,7 +4934,7 @@ bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, c ItemSize(bb); // Actual slider behavior + render grab - bool value_changed = SliderBehaviour(frame_bb, slider_bb, id, v, v_min, v_max, power, decimal_precision); + bool value_changed = SliderBehaviour(frame_bb, slider_bb, id, v, v_min, v_max, power, decimal_precision, true); // Display value using user-provided display format so user can add prefix/suffix/decorations to the value. char value_buf[64]; From 7019cb10f7983b1e5fb40cf13d5ed4d3a0029493 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 15 Mar 2015 01:48:59 +0000 Subject: [PATCH 33/44] "behaviour" -> "behavior" to behave like the greatest number --- imgui.cpp | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index bbc67c94b..4a85f59f8 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -420,7 +420,7 @@ struct ImGuiIniData; struct ImGuiState; struct ImGuiWindow; -static bool ButtonBehaviour(const ImGuiAabb& bb, ImGuiID id, bool* out_hovered, bool* out_held, bool allow_key_modifiers, bool repeat = false, bool pressed_on_click = false); +static bool ButtonBehavior(const ImGuiAabb& bb, ImGuiID id, bool* out_hovered, bool* out_held, bool allow_key_modifiers, bool repeat = false, bool pressed_on_click = false); static void LogText(const ImVec2& ref_pos, const char* text, const char* text_end = NULL); static void RenderText(ImVec2 pos, const char* text, const char* text_end = NULL, bool hide_text_after_hash = true); @@ -1912,7 +1912,7 @@ void ImGui::NewFrame() ImGui::Begin("Debug", NULL, ImVec2(400,400)); } -// NB: behaviour of ImGui after Shutdown() is not tested/guaranteed at the moment. This function is merely here to free heap allocations. +// NB: behavior of ImGui after Shutdown() is not tested/guaranteed at the moment. This function is merely here to free heap allocations. void ImGui::Shutdown() { ImGuiState& g = *GImGui; @@ -2980,7 +2980,7 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size, float bg const ImGuiAabb resize_aabb(window->Aabb().GetBR()-ImVec2(18,18), window->Aabb().GetBR()); const ImGuiID resize_id = window->GetID("#RESIZE"); bool hovered, held; - ButtonBehaviour(resize_aabb, resize_id, &hovered, &held, true); + ButtonBehavior(resize_aabb, resize_id, &hovered, &held, true); resize_col = window->Color(held ? ImGuiCol_ResizeGripActive : hovered ? ImGuiCol_ResizeGripHovered : ImGuiCol_ResizeGrip); if (g.HoveredWindow == window && held && g.IO.MouseDoubleClicked[0]) @@ -3196,7 +3196,7 @@ static void Scrollbar(ImGuiWindow* window) bool held = false; bool hovered = false; const bool previously_held = (g.ActiveId == id); - ButtonBehaviour(bb, id, &hovered, &held, true); + ButtonBehavior(bb, id, &hovered, &held, true); const float scroll_max = ImMax(1.0f, window->SizeContents.y - window->Size.y); float scroll_ratio = ImSaturate(window->ScrollY / scroll_max); @@ -4031,7 +4031,7 @@ static bool IsHovered(const ImGuiAabb& bb, ImGuiID id) return false; } -static bool ButtonBehaviour(const ImGuiAabb& bb, ImGuiID id, bool* out_hovered, bool* out_held, bool allow_key_modifiers, bool repeat, bool pressed_on_click) +static bool ButtonBehavior(const ImGuiAabb& bb, ImGuiID id, bool* out_hovered, bool* out_held, bool allow_key_modifiers, bool repeat, bool pressed_on_click) { ImGuiState& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); @@ -4102,7 +4102,7 @@ bool ImGui::Button(const char* label, const ImVec2& size_arg, bool repeat_when_h return false; bool hovered, held; - bool pressed = ButtonBehaviour(bb, id, &hovered, &held, true, repeat_when_held); + bool pressed = ButtonBehavior(bb, id, &hovered, &held, true, repeat_when_held); // Render const ImU32 col = window->Color((hovered && held) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button); @@ -4132,7 +4132,7 @@ bool ImGui::SmallButton(const char* label) return false; bool hovered, held; - bool pressed = ButtonBehaviour(bb, id, &hovered, &held, true); + bool pressed = ButtonBehavior(bb, id, &hovered, &held, true); // Render const ImU32 col = window->Color((hovered && held) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button); @@ -4157,7 +4157,7 @@ bool ImGui::InvisibleButton(const char* str_id, const ImVec2& size) return false; bool hovered, held; - bool pressed = ButtonBehaviour(bb, id, &hovered, &held, true); + bool pressed = ButtonBehavior(bb, id, &hovered, &held, true); return pressed; } @@ -4172,7 +4172,7 @@ static bool CloseWindowButton(bool* p_opened) const ImGuiAabb bb(window->Aabb().GetTR() + ImVec2(-3.0f-size,2.0f), window->Aabb().GetTR() + ImVec2(-3.0f,2.0f+size)); bool hovered, held; - bool pressed = ButtonBehaviour(bb, id, &hovered, &held, true); + bool pressed = ButtonBehavior(bb, id, &hovered, &held, true); // Render const ImU32 col = window->Color((held && hovered) ? ImGuiCol_CloseButtonActive : hovered ? ImGuiCol_CloseButtonHovered : ImGuiCol_CloseButton); @@ -4243,7 +4243,7 @@ bool ImGui::ImageButton(ImTextureID user_texture_id, const ImVec2& size, const I return false; bool hovered, held; - bool pressed = ButtonBehaviour(bb, id, &hovered, &held, true); + bool pressed = ButtonBehavior(bb, id, &hovered, &held, true); // Render const ImU32 col = window->Color((hovered && held) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button); @@ -4424,7 +4424,7 @@ bool ImGui::CollapsingHeader(const char* label, const char* str_id, bool display const ImGuiAabb text_bb(bb.Min, bb.Min + ImVec2(window->FontSize() + style.FramePadding.x*2*2,0) + label_size); ItemSize(ImVec2(text_bb.GetSize().x, bb.GetSize().y)); // NB: we don't provide our width so that it doesn't get feed back into AutoFit - // When logging is enabled, if automatically expand tree nodes (but *NOT* collapsing headers.. seems like sensible behaviour). + // When logging is enabled, if automatically expand tree nodes (but *NOT* collapsing headers.. seems like sensible behavior). // NB- If we are above max depth we still allow manually opened nodes to be logged. if (g.LogEnabled && !display_frame && window->DC.TreeDepth < g.LogAutoExpandMaxDepth) opened = true; @@ -4433,7 +4433,7 @@ bool ImGui::CollapsingHeader(const char* label, const char* str_id, bool display return opened; bool hovered, held; - bool pressed = ButtonBehaviour(display_frame ? bb : text_bb, id, &hovered, &held, false); + bool pressed = ButtonBehavior(display_frame ? bb : text_bb, id, &hovered, &held, false); if (pressed) { opened = !opened; @@ -4735,7 +4735,7 @@ static void ParseFormat(const char* fmt, int& decimal_precision) } } -static bool SliderBehaviour(const ImGuiAabb& frame_bb, const ImGuiAabb& slider_bb, ImGuiID id, float* v, float v_min, float v_max, float power, int decimal_precision, bool horizontal) +static bool SliderBehavior(const ImGuiAabb& frame_bb, const ImGuiAabb& slider_bb, ImGuiID id, float* v, float v_min, float v_max, float power, int decimal_precision, bool horizontal) { ImGuiState& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); @@ -4934,7 +4934,7 @@ bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, c ItemSize(bb); // Actual slider behavior + render grab - bool value_changed = SliderBehaviour(frame_bb, slider_bb, id, v, v_min, v_max, power, decimal_precision, true); + bool value_changed = SliderBehavior(frame_bb, slider_bb, id, v, v_min, v_max, power, decimal_precision, true); // Display value using user-provided display format so user can add prefix/suffix/decorations to the value. char value_buf[64]; @@ -5233,7 +5233,7 @@ bool ImGui::Checkbox(const char* label, bool* v) return false; bool hovered, held; - bool pressed = ButtonBehaviour(total_bb, id, &hovered, &held, true); + bool pressed = ButtonBehavior(total_bb, id, &hovered, &held, true); if (pressed) *v = !(*v); @@ -5296,7 +5296,7 @@ bool ImGui::RadioButton(const char* label, bool active) const float radius = check_bb.GetHeight() * 0.5f; bool hovered, held; - bool pressed = ButtonBehaviour(total_bb, id, &hovered, &held, true); + bool pressed = ButtonBehavior(total_bb, id, &hovered, &held, true); window->DrawList->AddCircleFilled(center, radius, window->Color((held && hovered) ? ImGuiCol_CheckActive : hovered ? ImGuiCol_CheckHovered : ImGuiCol_FrameBg), 16); if (active) @@ -6215,7 +6215,7 @@ bool ImGui::Selectable(const char* label, bool selected, const ImVec2& size_arg) return false; bool hovered, held; - bool pressed = ButtonBehaviour(bb_with_spacing, id, &hovered, &held, true, false, false); + bool pressed = ButtonBehavior(bb_with_spacing, id, &hovered, &held, true, false, false); // Render if (hovered || selected) @@ -6346,7 +6346,7 @@ bool ImGui::ColorButton(const ImVec4& col, bool small_height, bool outline_borde return false; bool hovered, held; - bool pressed = ButtonBehaviour(bb, id, &hovered, &held, true); + bool pressed = ButtonBehavior(bb, id, &hovered, &held, true); RenderFrame(bb.Min, bb.Max, window->Color(col), outline_border, style.FrameRounding); if (hovered) @@ -6622,7 +6622,7 @@ static bool ItemAdd(const ImGuiAabb& bb, const ImGuiID* id) // This is a sensible default, but widgets are free to override it after calling ItemAdd() const bool hovered = IsMouseHoveringBox(bb); - //const bool hovered = (g.ActiveId == 0 || (id && g.ActiveId == *id) || g.ActiveIdIsFocusedOnly) && IsMouseHoveringBox(bb); // matching the behaviour of IsHovered(), not always what the user wants? + //const bool hovered = (g.ActiveId == 0 || (id && g.ActiveId == *id) || g.ActiveIdIsFocusedOnly) && IsMouseHoveringBox(bb); // matching the behavior of IsHovered(), not always what the user wants? window->DC.LastItemHovered = hovered; return true; } @@ -6787,7 +6787,7 @@ void ImGui::Columns(int columns_count, const char* id, bool border) continue; bool hovered, held; - ButtonBehaviour(column_aabb, column_id, &hovered, &held, true); + ButtonBehavior(column_aabb, column_id, &hovered, &held, true); // Draw before resize so our items positioning are in sync with the line being drawn const ImU32 col = window->Color(held ? ImGuiCol_ColumnActive : hovered ? ImGuiCol_ColumnHovered : ImGuiCol_Column); From 1ac4f33736d5122f7dcb1a20433d22bd21378d77 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 15 Mar 2015 01:58:14 +0000 Subject: [PATCH 34/44] Added VSliderFloat() --- imgui.cpp | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ imgui.h | 1 + 2 files changed, 82 insertions(+) diff --git a/imgui.cpp b/imgui.cpp index 4a85f59f8..53b24a1a4 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4947,6 +4947,56 @@ bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, c return value_changed; } +bool ImGui::VSliderFloat(const char* label, const ImVec2& size, float* v, float v_min, float v_max, const char* display_format, float power) +{ + ImGuiState& g = *GImGui; + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return false; + + const ImGuiStyle& style = g.Style; + const ImGuiID id = window->GetID(label); + + const ImVec2 label_size = CalcTextSize(label, NULL, true); + const ImGuiAabb frame_bb(window->DC.CursorPos, window->DC.CursorPos + size); + const ImGuiAabb slider_bb(frame_bb.Min + style.FramePadding, frame_bb.Max - style.FramePadding); + const ImGuiAabb bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f)); + + ItemSize(bb); + if (!ItemAdd(frame_bb, &id)) + return false; + + const bool hovered = IsHovered(frame_bb, id); + if (hovered) + g.HoveredId = id; + + if (!display_format) + display_format = "%.3f"; + int decimal_precision = 3; + ParseFormat(display_format, decimal_precision); + + if (hovered && g.IO.MouseClicked[0]) + { + SetActiveId(id); + FocusWindow(window); + } + + // Actual slider behavior + render grab + bool value_changed = SliderBehavior(frame_bb, slider_bb, id, v, v_min, v_max, power, decimal_precision, false); + + // Display value using user-provided display format so user can add prefix/suffix/decorations to the value. + // For the vertical slider we allow centered text to overlap the frame padding + char value_buf[64]; + char* value_buf_end = value_buf + ImFormatString(value_buf, IM_ARRAYSIZE(value_buf), display_format, *v); + const ImVec2 value_text_size = CalcTextSize(value_buf, value_buf_end, true); + RenderTextClipped(ImVec2(ImMax(frame_bb.Min.x, slider_bb.GetCenter().x - value_text_size.x*0.5f), frame_bb.Min.y + style.FramePadding.y), value_buf, value_buf_end, &value_text_size, frame_bb.Max); + + if (label_size.x > 0.0f) + RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, slider_bb.Min.y), label); + + return value_changed; +} + bool ImGui::SliderAngle(const char* label, float* v, float v_degrees_min, float v_degrees_max) { float v_deg = *v * 360.0f / (2*PI); @@ -9012,6 +9062,37 @@ void ImGui::ShowTestWindow(bool* opened) //ImGui::PushItemWidth(-1); //ImGui::ListBox("##listbox2", &listbox_item_current2, listbox_items, IM_ARRAYSIZE(listbox_items), 4); //ImGui::PopItemWidth(); + + if (ImGui::TreeNode("Vertical Sliders")) + { + const int spacing = 4; + + ImGui::PushID("set1"); + static float values[4] = { 0.0f, 0.60f, 0.35f, 0.9f }; + for (size_t i = 0; i < IM_ARRAYSIZE(values); i++) + { + if (i > 0) ImGui::SameLine(0, spacing); + ImGui::PushID(i); + ImGui::VSliderFloat("##v", ImVec2(18,160), &values[i], 0.0f, 1.0f, ""); + ImGui::PopID(); + } + ImGui::PopID(); + + ImGui::SameLine(); + ImGui::PushID("set2"); + ImGui::PushStyleVar(ImGuiStyleVar_GrabMinSize, 40); + for (size_t i = 0; i < IM_ARRAYSIZE(values); i++) + { + if (i > 0) ImGui::SameLine(0, spacing); + ImGui::PushID(i); + ImGui::VSliderFloat("##v", ImVec2(40,160), &values[i], 0.0f, 1.0f, "%.2f"); + ImGui::PopID(); + } + ImGui::PopStyleVar(); + ImGui::PopID(); + + ImGui::TreePop(); + } } if (ImGui::CollapsingHeader("Graphs widgets")) diff --git a/imgui.h b/imgui.h index f3c51b6de..54b5a90de 100644 --- a/imgui.h +++ b/imgui.h @@ -283,6 +283,7 @@ namespace ImGui IMGUI_API bool SliderInt2(const char* label, int v[2], int v_min, int v_max, const char* display_format = "%.0f"); IMGUI_API bool SliderInt3(const char* label, int v[3], int v_min, int v_max, const char* display_format = "%.0f"); IMGUI_API bool SliderInt4(const char* label, int v[4], int v_min, int v_max, const char* display_format = "%.0f"); + IMGUI_API bool VSliderFloat(const char* label, const ImVec2& size, float* v, float v_min, float v_max, const char* display_format = "%.3f", float power = 1.0f); IMGUI_API void PlotLines(const char* label, const float* values, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0,0), size_t stride = sizeof(float)); IMGUI_API void PlotLines(const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0,0)); IMGUI_API void PlotHistogram(const char* label, const float* values, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0,0), size_t stride = sizeof(float)); From b443c7ebe981d5dd281009df49cb69d86e7a28d3 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 15 Mar 2015 10:38:19 +0000 Subject: [PATCH 35/44] Tweak VSliderFloat() Not really happy about them --- imgui.cpp | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 53b24a1a4..d988cc1f9 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -269,6 +269,8 @@ - input number: holding [-]/[+] buttons could increase the step speed non-linearly (or user-controlled) - input number: use mouse wheel to step up/down - input number: non-decimal input. + - text: vertical alignment (e.g. for Text after a large widget) + - text: proper horizontal centering - layout: horizontal layout helper (github issue #97) - layout: more generic alignment state (left/right/centered) for single items? - layout: clean up the InputFloatN/SliderFloatN/ColorEdit4 layout code. item width should include frame padding. @@ -9067,28 +9069,35 @@ void ImGui::ShowTestWindow(bool* opened) { const int spacing = 4; + static float values[7] = { 0.0f, 0.60f, 0.35f, 0.9f, 0.70f, 0.20f, 0.0f }; ImGui::PushID("set1"); - static float values[4] = { 0.0f, 0.60f, 0.35f, 0.9f }; - for (size_t i = 0; i < IM_ARRAYSIZE(values); i++) + for (int i = 0; i < 7; i++) { if (i > 0) ImGui::SameLine(0, spacing); ImGui::PushID(i); + ImGui::PushStyleColor(ImGuiCol_FrameBg, ImColor::HSV(i/7.0f, 0.5f, 0.5f)); + ImGui::PushStyleColor(ImGuiCol_SliderGrab, ImColor::HSV(i/7.0f, 0.9f, 0.9f)); + ImGui::PushStyleColor(ImGuiCol_SliderGrabActive, ImColor::HSV(i/7.0f, 1.0f, 1.0f)); ImGui::VSliderFloat("##v", ImVec2(18,160), &values[i], 0.0f, 1.0f, ""); + if (ImGui::IsItemActive() || ImGui::IsItemHovered()) + ImGui::SetTooltip("%.3f", values[i]); + ImGui::PopStyleColor(3); ImGui::PopID(); } ImGui::PopID(); ImGui::SameLine(); + ImGui::PushID("set2"); - ImGui::PushStyleVar(ImGuiStyleVar_GrabMinSize, 40); - for (size_t i = 0; i < IM_ARRAYSIZE(values); i++) + for (size_t i = 0; i < 4; i++) { if (i > 0) ImGui::SameLine(0, spacing); ImGui::PushID(i); + ImGui::PushStyleVar(ImGuiStyleVar_GrabMinSize, 40); ImGui::VSliderFloat("##v", ImVec2(40,160), &values[i], 0.0f, 1.0f, "%.2f"); + ImGui::PopStyleVar(); ImGui::PopID(); } - ImGui::PopStyleVar(); ImGui::PopID(); ImGui::TreePop(); From 304d19a0d88c4408a8cb486c0b9e888706dc79c2 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 15 Mar 2015 11:03:55 +0000 Subject: [PATCH 36/44] ShowTestWindow() added multi-components sliders in a sub-node + right align all widgets --- imgui.cpp | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index d988cc1f9..974877fac 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8706,9 +8706,9 @@ void ImGui::ShowTestWindow(bool* opened) ImGui::End(); return; } - - ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.65f); // 2/3 of the space for widget and 1/3 for labels - //ImGui::PushItemWidth(-140); // Right align, keep 140 pixels for labels + + //ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.65f); // 2/3 of the space for widget and 1/3 for labels + ImGui::PushItemWidth(-140); // Right align, keep 140 pixels for labels ImGui::Text("ImGui says hello."); //ImGui::Text("MousePos (%g, %g)", ImGui::GetIO().MousePos.x, ImGui::GetIO().MousePos.y); @@ -9041,16 +9041,6 @@ void ImGui::ShowTestWindow(bool* opened) static float angle = 0.0f; ImGui::SliderAngle("angle", &angle); - static float vec4b[4] = { 0.10f, 0.20f, 0.30f, 0.40f }; - //ImGui::SliderFloat2("slider float2", vec4b, 0.0f, 1.0f); - ImGui::SliderFloat3("slider float3", vec4b, 0.0f, 1.0f); - //ImGui::SliderFloat4("slider float4", vec4b, 0.0f, 1.0f); - - //static int vec4i[4] = { 1, 5, 100, 255 }; - //ImGui::SliderInt2("slider int2", vec4i, 0, 255); - //ImGui::SliderInt3("slider int3", vec4i, 0, 255); - //ImGui::SliderInt4("slider int4", vec4i, 0, 255); - static float col1[3] = { 1.0f,0.0f,0.2f }; static float col2[4] = { 0.4f,0.7f,0.0f,0.5f }; ImGui::ColorEdit3("color 1", col1); @@ -9065,15 +9055,30 @@ void ImGui::ShowTestWindow(bool* opened) //ImGui::ListBox("##listbox2", &listbox_item_current2, listbox_items, IM_ARRAYSIZE(listbox_items), 4); //ImGui::PopItemWidth(); + if (ImGui::TreeNode("Multi-component Sliders")) + { + ImGui::TreePop(); // Intentionally undo the tree-node tab early on + + static float vec4b[4] = { 0.10f, 0.20f, 0.30f, 0.40f }; + ImGui::SliderFloat2("slider float2", vec4b, 0.0f, 1.0f); + ImGui::SliderFloat3("slider float3", vec4b, 0.0f, 1.0f); + ImGui::SliderFloat4("slider float4", vec4b, 0.0f, 1.0f); + + static int vec4i[4] = { 1, 5, 100, 255 }; + ImGui::SliderInt2("slider int2", vec4i, 0, 255); + ImGui::SliderInt3("slider int3", vec4i, 0, 255); + ImGui::SliderInt4("slider int4", vec4i, 0, 255); + } + if (ImGui::TreeNode("Vertical Sliders")) { - const int spacing = 4; + ImGui::TreePop(); // Intentionally undo the tree-node tab early on static float values[7] = { 0.0f, 0.60f, 0.35f, 0.9f, 0.70f, 0.20f, 0.0f }; ImGui::PushID("set1"); for (int i = 0; i < 7; i++) { - if (i > 0) ImGui::SameLine(0, spacing); + if (i > 0) ImGui::SameLine(0, 4); ImGui::PushID(i); ImGui::PushStyleColor(ImGuiCol_FrameBg, ImColor::HSV(i/7.0f, 0.5f, 0.5f)); ImGui::PushStyleColor(ImGuiCol_SliderGrab, ImColor::HSV(i/7.0f, 0.9f, 0.9f)); @@ -9091,7 +9096,7 @@ void ImGui::ShowTestWindow(bool* opened) ImGui::PushID("set2"); for (size_t i = 0; i < 4; i++) { - if (i > 0) ImGui::SameLine(0, spacing); + if (i > 0) ImGui::SameLine(0, 4); ImGui::PushID(i); ImGui::PushStyleVar(ImGuiStyleVar_GrabMinSize, 40); ImGui::VSliderFloat("##v", ImVec2(40,160), &values[i], 0.0f, 1.0f, "%.2f"); @@ -9099,8 +9104,6 @@ void ImGui::ShowTestWindow(bool* opened) ImGui::PopID(); } ImGui::PopID(); - - ImGui::TreePop(); } } From edde703f8f241f16743dbf83a9146184c257a4f3 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 15 Mar 2015 11:10:48 +0000 Subject: [PATCH 37/44] Renamed style.TreeNodeSpacing to style.IndentSpacing, ImGuiStyleVar_TreeNodeSpacing to ImGuiStyleVar_IndentSpacing --- imgui.cpp | 15 ++++++++------- imgui.h | 4 ++-- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 974877fac..c46c4b0fd 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -129,6 +129,7 @@ Occasionally introducing changes that are breaking the API. The breakage are generally minor and easy to fix. 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. + - 2015/03/15 (1.36) - renamed style.TreeNodeSpacing to style.IndentSpacing, ImGuiStyleVar_TreeNodeSpacing to ImGuiStyleVar_IndentSpacing - 2015/03/13 (1.36) - renamed GetWindowIsFocused() to IsWindowFocused(). Kept inline redirection function. - 2015/03/08 (1.35) - renamed style.ScrollBarWidth to style.ScrollbarWidth - 2015/02/27 (1.34) - renamed OpenNextNode(bool) to SetNextTreeNodeOpened(bool, ImGuiSetCond). Kept inline redirection function. @@ -506,7 +507,7 @@ ImGuiStyle::ImGuiStyle() TouchExtraPadding = ImVec2(0,0); // Expand bounding box for touch-based system where touch position is not accurate enough (unnecessary for mouse inputs). Unfortunately we don't sort widgets so priority on overlap will always be given to the first widget running. So dont grow this too much! AutoFitPadding = ImVec2(8,8); // Extra space after auto-fit (double-clicking on resize grip) WindowFillAlphaDefault = 0.70f; // Default alpha of window background, if not specified in ImGui::Begin() - TreeNodeSpacing = 22.0f; // Horizontal spacing when entering a tree node + IndentSpacing = 22.0f; // Horizontal spacing when e.g. entering a tree node ColumnsMinSpacing = 6.0f; // Minimum horizontal spacing between two columns ScrollbarWidth = 16.0f; // Width of the vertical scrollbar GrabMinSize = 10.0f; // Minimum width/height of a slider or scrollbar grab @@ -3383,7 +3384,7 @@ static float* GetStyleVarFloatAddr(ImGuiStyleVar idx) case ImGuiStyleVar_WindowRounding: return &g.Style.WindowRounding; case ImGuiStyleVar_ChildWindowRounding: return &g.Style.ChildWindowRounding; case ImGuiStyleVar_FrameRounding: return &g.Style.FrameRounding; - case ImGuiStyleVar_TreeNodeSpacing: return &g.Style.TreeNodeSpacing; + case ImGuiStyleVar_IndentSpacing: return &g.Style.IndentSpacing; case ImGuiStyleVar_GrabMinSize: return &g.Style.GrabMinSize; } return NULL; @@ -4542,7 +4543,7 @@ bool ImGui::TreeNodeV(const char* str_id, const char* fmt, va_list args) str_id = fmt; ImGui::PushID(str_id); - const bool opened = ImGui::CollapsingHeader(buf, "", false); // do not add to the ID so that TreeNodeSetOpen can access + const bool opened = ImGui::CollapsingHeader(buf, "", false); ImGui::PopID(); if (opened) @@ -6894,7 +6895,7 @@ void ImGui::TreePush(const char* str_id) { ImGuiState& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); - window->DC.ColumnsStartX += g.Style.TreeNodeSpacing; + window->DC.ColumnsStartX += g.Style.IndentSpacing; window->DC.CursorPos.x = window->Pos.x + window->DC.ColumnsStartX + window->DC.ColumnsOffsetX; window->DC.TreeDepth++; PushID(str_id ? str_id : "#TreePush"); @@ -6904,7 +6905,7 @@ void ImGui::TreePush(const void* ptr_id) { ImGuiState& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); - window->DC.ColumnsStartX += g.Style.TreeNodeSpacing; + window->DC.ColumnsStartX += g.Style.IndentSpacing; window->DC.CursorPos.x = window->Pos.x + window->DC.ColumnsStartX + window->DC.ColumnsOffsetX; window->DC.TreeDepth++; PushID(ptr_id ? ptr_id : (const void*)"#TreePush"); @@ -6914,7 +6915,7 @@ void ImGui::TreePop() { ImGuiState& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); - window->DC.ColumnsStartX -= g.Style.TreeNodeSpacing; + window->DC.ColumnsStartX -= g.Style.IndentSpacing; window->DC.CursorPos.x = window->Pos.x + window->DC.ColumnsStartX + window->DC.ColumnsOffsetX; window->DC.TreeDepth--; PopID(); @@ -8585,7 +8586,7 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) ImGui::SliderFloat2("ItemSpacing", (float*)&style.ItemSpacing, 0.0f, 20.0f, "%.0f"); ImGui::SliderFloat2("ItemInnerSpacing", (float*)&style.ItemInnerSpacing, 0.0f, 20.0f, "%.0f"); ImGui::SliderFloat2("TouchExtraPadding", (float*)&style.TouchExtraPadding, 0.0f, 10.0f, "%.0f"); - ImGui::SliderFloat("TreeNodeSpacing", &style.TreeNodeSpacing, 0.0f, 20.0f, "%.0f"); + ImGui::SliderFloat("IndentSpacing", &style.IndentSpacing, 0.0f, 20.0f, "%.0f"); ImGui::SliderFloat("ScrollBarWidth", &style.ScrollbarWidth, 1.0f, 20.0f, "%.0f"); ImGui::SliderFloat("GrabMinSize", &style.GrabMinSize, 1.0f, 20.0f, "%.0f"); ImGui::TreePop(); diff --git a/imgui.h b/imgui.h index 54b5a90de..37c8c1e74 100644 --- a/imgui.h +++ b/imgui.h @@ -503,7 +503,7 @@ enum ImGuiStyleVar_ ImGuiStyleVar_FrameRounding, // float ImGuiStyleVar_ItemSpacing, // ImVec2 ImGuiStyleVar_ItemInnerSpacing, // ImVec2 - ImGuiStyleVar_TreeNodeSpacing, // float + ImGuiStyleVar_IndentSpacing, // float ImGuiStyleVar_GrabMinSize // float }; @@ -540,7 +540,7 @@ struct ImGuiStyle ImVec2 TouchExtraPadding; // Expand bounding box for touch-based system where touch position is not accurate enough (unnecessary for mouse inputs). Unfortunately we don't sort widgets so priority on overlap will always be given to the first widget running. So dont grow this too much! ImVec2 AutoFitPadding; // Extra space after auto-fit (double-clicking on resize grip) float WindowFillAlphaDefault; // Default alpha of window background, if not specified in ImGui::Begin() - float TreeNodeSpacing; // Horizontal spacing when entering a tree node + float IndentSpacing; // Horizontal indentation when e.g. entering a tree node float ColumnsMinSpacing; // Minimum horizontal spacing between two columns float ScrollbarWidth; // Width of the vertical scrollbar float GrabMinSize; // Minimum width/height of a slider or scrollbar grab From 44826972c05277fed62a09ed432a5289f0822fbf Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 15 Mar 2015 11:19:10 +0000 Subject: [PATCH 38/44] Added Indent(), Unindent() --- imgui.cpp | 25 ++++++++++++++++++------- imgui.h | 4 +++- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index c46c4b0fd..0a4b2698d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6891,32 +6891,43 @@ void ImGui::Columns(int columns_count, const char* id, bool border) } } -void ImGui::TreePush(const char* str_id) + +inline void ImGui::Indent() { ImGuiState& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); window->DC.ColumnsStartX += g.Style.IndentSpacing; window->DC.CursorPos.x = window->Pos.x + window->DC.ColumnsStartX + window->DC.ColumnsOffsetX; +} + +inline void ImGui::Unindent() +{ + ImGuiState& g = *GImGui; + ImGuiWindow* window = GetCurrentWindow(); + window->DC.ColumnsStartX -= g.Style.IndentSpacing; + window->DC.CursorPos.x = window->Pos.x + window->DC.ColumnsStartX + window->DC.ColumnsOffsetX; +} + +void ImGui::TreePush(const char* str_id) +{ + ImGuiWindow* window = GetCurrentWindow(); + ImGui::Indent(); window->DC.TreeDepth++; PushID(str_id ? str_id : "#TreePush"); } void ImGui::TreePush(const void* ptr_id) { - ImGuiState& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); - window->DC.ColumnsStartX += g.Style.IndentSpacing; - window->DC.CursorPos.x = window->Pos.x + window->DC.ColumnsStartX + window->DC.ColumnsOffsetX; + ImGui::Indent(); window->DC.TreeDepth++; PushID(ptr_id ? ptr_id : (const void*)"#TreePush"); } void ImGui::TreePop() { - ImGuiState& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); - window->DC.ColumnsStartX -= g.Style.IndentSpacing; - window->DC.CursorPos.x = window->Pos.x + window->DC.ColumnsStartX + window->DC.ColumnsOffsetX; + ImGui::Unindent(); window->DC.TreeDepth--; PopID(); } diff --git a/imgui.h b/imgui.h index 37c8c1e74..7b520d334 100644 --- a/imgui.h +++ b/imgui.h @@ -225,7 +225,9 @@ namespace ImGui // Layout IMGUI_API void Separator(); // horizontal line IMGUI_API void SameLine(int column_x = 0, int spacing_w = -1); // call between widgets to layout them horizontally - IMGUI_API void Spacing(); + IMGUI_API void Spacing(); // add vertical spacing + IMGUI_API void Indent(); // move content position toward the right by style.IndentSpacing pixels + IMGUI_API void Unindent(); // move content position back to the left (cancel Indent) IMGUI_API void Columns(int count = 1, const char* id = NULL, bool border=true); // setup number of columns IMGUI_API void NextColumn(); // next column IMGUI_API int GetColumnIndex(); // get current column index From 9c6c8a1ab9e9eff4c14b517ffb8128d8ce8f8548 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 15 Mar 2015 11:21:59 +0000 Subject: [PATCH 39/44] ShowTestWindow() using Unindent() / Indent() instead of an explicit TreePop --- imgui.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 0a4b2698d..e0203b456 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9069,7 +9069,7 @@ void ImGui::ShowTestWindow(bool* opened) if (ImGui::TreeNode("Multi-component Sliders")) { - ImGui::TreePop(); // Intentionally undo the tree-node tab early on + ImGui::Unindent(); static float vec4b[4] = { 0.10f, 0.20f, 0.30f, 0.40f }; ImGui::SliderFloat2("slider float2", vec4b, 0.0f, 1.0f); @@ -9080,11 +9080,14 @@ void ImGui::ShowTestWindow(bool* opened) ImGui::SliderInt2("slider int2", vec4i, 0, 255); ImGui::SliderInt3("slider int3", vec4i, 0, 255); ImGui::SliderInt4("slider int4", vec4i, 0, 255); + + ImGui::Indent(); + ImGui::TreePop(); } if (ImGui::TreeNode("Vertical Sliders")) { - ImGui::TreePop(); // Intentionally undo the tree-node tab early on + ImGui::Unindent(); static float values[7] = { 0.0f, 0.60f, 0.35f, 0.9f, 0.70f, 0.20f, 0.0f }; ImGui::PushID("set1"); @@ -9116,6 +9119,9 @@ void ImGui::ShowTestWindow(bool* opened) ImGui::PopID(); } ImGui::PopID(); + + ImGui::Indent(); + ImGui::TreePop(); } } From 0fc9168439a3e21f8a0516d36f3c0a2bb004e995 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 15 Mar 2015 11:30:00 +0000 Subject: [PATCH 40/44] Added InputInt2(), InputInt3(), InputInt4() --- imgui.cpp | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++----- imgui.h | 3 +++ 2 files changed, 67 insertions(+), 6 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index e0203b456..e8033cb47 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6084,6 +6084,56 @@ bool ImGui::InputFloat4(const char* label, float v[4], int decimal_precision) return InputFloatN(label, v, 4, decimal_precision); } +static bool InputIntN(const char* label, int* v, int components) +{ + ImGuiState& g = *GImGui; + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return false; + + const ImGuiStyle& style = g.Style; + const float w_full = ImGui::CalcItemWidth(); + const float w_item_one = ImMax(1.0f, (float)(int)((w_full - (style.FramePadding.x*2.0f + style.ItemInnerSpacing.x) * (components-1)) / (float)components)); + const float w_item_last = ImMax(1.0f, (float)(int)(w_full - (w_item_one + style.FramePadding.x*2.0f + style.ItemInnerSpacing.x) * (components-1))); + + bool value_changed = false; + ImGui::PushID(label); + ImGui::PushItemWidth(w_item_one); + for (int i = 0; i < components; i++) + { + ImGui::PushID(i); + if (i + 1 == components) + { + ImGui::PopItemWidth(); + ImGui::PushItemWidth(w_item_last); + } + value_changed |= ImGui::InputInt("##v", &v[i], 0, 0); + ImGui::SameLine(0, (int)style.ItemInnerSpacing.x); + ImGui::PopID(); + } + ImGui::PopItemWidth(); + ImGui::PopID(); + + ImGui::TextUnformatted(label, FindTextDisplayEnd(label)); + + return value_changed; +} + +bool ImGui::InputInt2(const char* label, int v[2]) +{ + return InputIntN(label, v, 2); +} + +bool ImGui::InputInt3(const char* label, int v[3]) +{ + return InputIntN(label, v, 3); +} + +bool ImGui::InputInt4(const char* label, int v[4]) +{ + return InputIntN(label, v, 4); +} + static bool Items_ArrayGetter(void* data, int idx, const char** out_text) { const char** items = (const char**)data; @@ -9067,18 +9117,26 @@ void ImGui::ShowTestWindow(bool* opened) //ImGui::ListBox("##listbox2", &listbox_item_current2, listbox_items, IM_ARRAYSIZE(listbox_items), 4); //ImGui::PopItemWidth(); - if (ImGui::TreeNode("Multi-component Sliders")) + if (ImGui::TreeNode("Multi-component Widgets")) { ImGui::Unindent(); - static float vec4b[4] = { 0.10f, 0.20f, 0.30f, 0.40f }; - ImGui::SliderFloat2("slider float2", vec4b, 0.0f, 1.0f); - ImGui::SliderFloat3("slider float3", vec4b, 0.0f, 1.0f); - ImGui::SliderFloat4("slider float4", vec4b, 0.0f, 1.0f); - + static float vec4f[4] = { 0.10f, 0.20f, 0.30f, 0.44f }; static int vec4i[4] = { 1, 5, 100, 255 }; + + ImGui::InputFloat2("input float2", vec4f); + ImGui::SliderFloat2("slider float2", vec4f, 0.0f, 1.0f); + ImGui::InputInt2("input int2", vec4i); ImGui::SliderInt2("slider int2", vec4i, 0, 255); + + ImGui::InputFloat3("input float3", vec4f); + ImGui::SliderFloat3("slider float3", vec4f, 0.0f, 1.0f); + ImGui::InputInt3("input int3", vec4i); ImGui::SliderInt3("slider int3", vec4i, 0, 255); + + ImGui::InputFloat4("input float4", vec4f); + ImGui::SliderFloat4("slider float4", vec4f, 0.0f, 1.0f); + ImGui::InputInt4("input int4", vec4i); ImGui::SliderInt4("slider int4", vec4i, 0, 255); ImGui::Indent(); diff --git a/imgui.h b/imgui.h index 7b520d334..53e66b708 100644 --- a/imgui.h +++ b/imgui.h @@ -300,6 +300,9 @@ namespace ImGui IMGUI_API bool InputFloat3(const char* label, float v[3], int decimal_precision = -1); IMGUI_API bool InputFloat4(const char* label, float v[4], int decimal_precision = -1); IMGUI_API bool InputInt(const char* label, int* v, int step = 1, int step_fast = 100, ImGuiInputTextFlags extra_flags = 0); + IMGUI_API bool InputInt2(const char* label, int v[2]); + IMGUI_API bool InputInt3(const char* label, int v[3]); + IMGUI_API bool InputInt4(const char* label, int v[4]); IMGUI_API bool Combo(const char* label, int* current_item, const char** items, int items_count, int height_in_items = -1); IMGUI_API bool Combo(const char* label, int* current_item, const char* items_separated_by_zeros, int height_in_items = -1); // separate items with \0, end item-list with \0\0 IMGUI_API bool Combo(const char* label, int* current_item, bool (*items_getter)(void* data, int idx, const char** out_text), void* data, int items_count, int height_in_items = -1); From d08ce58876740e19c121739363f7ac9df9a577ec Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 16 Mar 2015 00:46:03 +0000 Subject: [PATCH 41/44] TreeNodeV() early out if SkipItems is set (avoid formatting string only to be discarded later) --- imgui.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/imgui.cpp b/imgui.cpp index e8033cb47..02635a456 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3992,6 +3992,7 @@ void ImGui::LabelTextV(const char* label, const char* fmt, va_list args) ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return; + const ImGuiStyle& style = g.Style; const float w = ImGui::CalcItemWidth(); @@ -4536,6 +4537,10 @@ void ImGui::BulletText(const char* fmt, ...) // If returning 'true' the node is open and the user is responsible for calling TreePop bool ImGui::TreeNodeV(const char* str_id, const char* fmt, va_list args) { + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return false; + static char buf[1024]; ImFormatStringV(buf, IM_ARRAYSIZE(buf), fmt, args); @@ -4564,6 +4569,10 @@ bool ImGui::TreeNode(const char* str_id, const char* fmt, ...) // If returning 'true' the node is open and the user is responsible for calling TreePop bool ImGui::TreeNodeV(const void* ptr_id, const char* fmt, va_list args) { + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return false; + static char buf[1024]; ImFormatStringV(buf, IM_ARRAYSIZE(buf), fmt, args); From 733eedc4773f126f157c3a264790eca305a38dde Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 16 Mar 2015 09:45:32 +0000 Subject: [PATCH 42/44] Moved static buffer into state --- imgui.cpp | 43 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 9 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 02635a456..31d9d7cd4 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1068,6 +1068,8 @@ struct ImGuiState float FramerateSecPerFrame[120]; // calculate estimate of framerate for user int FramerateSecPerFrameIdx; float FramerateSecPerFrameAccum; + bool TempBufferLocked; + char TempBuffer[1024*3+1]; // temporary text buffer ImGuiState() { @@ -1216,6 +1218,26 @@ static void RegisterAliveId(ImGuiID id) g.ActiveIdIsAlive = true; } +static char* TempBufferLock() +{ + ImGuiState& g = *GImGui; + IM_ASSERT(!g.TempBufferLocked); + g.TempBufferLocked = true; + return g.TempBuffer; +} + +static void TempBufferUnlock() +{ + ImGuiState& g = *GImGui; + IM_ASSERT(g.TempBufferLocked); + g.TempBufferLocked = false; +} + +static size_t TempBufferSize() +{ + return sizeof(GImGui->TempBuffer); +} + //----------------------------------------------------------------------------- // Helper: Key->value storage @@ -5805,7 +5827,6 @@ bool ImGui::InputText(const char* label, char* buf, size_t buf_size, ImGuiInputT bool value_changed = false; bool cancel_edit = false; bool enter_pressed = false; - static char text_tmp_utf8[IM_ARRAYSIZE(edit_state.InitialText)]; if (g.ActiveId == id) { // Edit in progress @@ -5878,8 +5899,10 @@ bool ImGui::InputText(const char* label, char* buf, size_t buf_size, ImGuiInputT { const int ib = edit_state.HasSelection() ? ImMin(edit_state.StbState.select_start, edit_state.StbState.select_end) : 0; const int ie = edit_state.HasSelection() ? ImMax(edit_state.StbState.select_start, edit_state.StbState.select_end) : (int)edit_state.CurLenW; - ImTextStrToUtf8(text_tmp_utf8, IM_ARRAYSIZE(text_tmp_utf8), edit_state.Text+ib, edit_state.Text+ie); - g.IO.SetClipboardTextFn(text_tmp_utf8); + char* tmp_buf = TempBufferLock(); + ImTextStrToUtf8(tmp_buf, TempBufferSize(), edit_state.Text+ib, edit_state.Text+ie); + g.IO.SetClipboardTextFn(tmp_buf); + TempBufferUnlock(); } if (cut) @@ -5931,7 +5954,8 @@ bool ImGui::InputText(const char* label, char* buf, size_t buf_size, ImGuiInputT // Note that as soon as we can focus into the input box, the in-widget value gets priority over any underlying modification of the input buffer // FIXME: We actually always render 'buf' in RenderTextScrolledClipped // FIXME-OPT: CPU waste to do this every time the widget is active, should mark dirty state from the stb_textedit callbacks - ImTextStrToUtf8(text_tmp_utf8, IM_ARRAYSIZE(text_tmp_utf8), edit_state.Text, NULL); + char* tmp_buf = TempBufferLock(); + ImTextStrToUtf8(tmp_buf, TempBufferSize(), edit_state.Text, NULL); // User callback if ((flags & (ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_CallbackHistory | ImGuiInputTextFlags_CallbackAlways)) != 0) @@ -5962,7 +5986,7 @@ bool ImGui::InputText(const char* label, char* buf, size_t buf_size, ImGuiInputT ImGuiTextEditCallbackData callback_data; callback_data.EventFlag = event_flag; callback_data.EventKey = event_key; - callback_data.Buf = text_tmp_utf8; + callback_data.Buf = tmp_buf; callback_data.BufSize = edit_state.BufSizeA; callback_data.BufDirty = false; callback_data.Flags = flags; @@ -5977,7 +6001,7 @@ bool ImGui::InputText(const char* label, char* buf, size_t buf_size, ImGuiInputT callback(&callback_data); // Read back what user may have modified - IM_ASSERT(callback_data.Buf == text_tmp_utf8); // Invalid to modify those fields + IM_ASSERT(callback_data.Buf == tmp_buf); // Invalid to modify those fields IM_ASSERT(callback_data.BufSize == edit_state.BufSizeA); IM_ASSERT(callback_data.Flags == flags); if (callback_data.CursorPos != utf8_cursor_pos) edit_state.StbState.cursor = ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.CursorPos); @@ -5985,17 +6009,18 @@ bool ImGui::InputText(const char* label, char* buf, size_t buf_size, ImGuiInputT if (callback_data.SelectionEnd != utf8_selection_end) edit_state.StbState.select_end = ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.SelectionEnd); if (callback_data.BufDirty) { - ImTextStrFromUtf8(edit_state.Text, IM_ARRAYSIZE(edit_state.Text), text_tmp_utf8, NULL); + ImTextStrFromUtf8(edit_state.Text, IM_ARRAYSIZE(edit_state.Text), tmp_buf, NULL); edit_state.CursorAnimReset(); } } } - if (strcmp(text_tmp_utf8, buf) != 0) + if (strcmp(tmp_buf, buf) != 0) { - ImFormatString(buf, buf_size, "%s", text_tmp_utf8); + ImFormatString(buf, buf_size, "%s", tmp_buf); value_changed = true; } + TempBufferUnlock(); } } From f4970d0e00836b61f2100e9db4820667e10024bb Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 16 Mar 2015 09:54:28 +0000 Subject: [PATCH 43/44] Moved static buffers into state No recursion in any of those functions. Tho keeping a lock api may be preferable? --- imgui.cpp | 69 +++++++++++++++++-------------------------------------- 1 file changed, 21 insertions(+), 48 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 31d9d7cd4..b2c8d11cd 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1068,7 +1068,6 @@ struct ImGuiState float FramerateSecPerFrame[120]; // calculate estimate of framerate for user int FramerateSecPerFrameIdx; float FramerateSecPerFrameAccum; - bool TempBufferLocked; char TempBuffer[1024*3+1]; // temporary text buffer ImGuiState() @@ -1218,26 +1217,6 @@ static void RegisterAliveId(ImGuiID id) g.ActiveIdIsAlive = true; } -static char* TempBufferLock() -{ - ImGuiState& g = *GImGui; - IM_ASSERT(!g.TempBufferLocked); - g.TempBufferLocked = true; - return g.TempBuffer; -} - -static void TempBufferUnlock() -{ - ImGuiState& g = *GImGui; - IM_ASSERT(g.TempBufferLocked); - g.TempBufferLocked = false; -} - -static size_t TempBufferSize() -{ - return sizeof(GImGui->TempBuffer); -} - //----------------------------------------------------------------------------- // Helper: Key->value storage @@ -3847,13 +3826,13 @@ ImGuiStorage* ImGui::GetStateStorage() void ImGui::TextV(const char* fmt, va_list args) { + ImGuiState& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return; - static char buf[1024]; - const char* text_end = buf + ImFormatStringV(buf, IM_ARRAYSIZE(buf), fmt, args); - TextUnformatted(buf, text_end); + const char* text_end = g.TempBuffer + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args); + TextUnformatted(g.TempBuffer, text_end); } void ImGui::Text(const char* fmt, ...) @@ -4018,9 +3997,8 @@ void ImGui::LabelTextV(const char* label, const char* fmt, va_list args) const ImGuiStyle& style = g.Style; const float w = ImGui::CalcItemWidth(); - static char buf[1024]; - const char* value_text_begin = &buf[0]; - const char* value_text_end = value_text_begin + ImFormatStringV(buf, IM_ARRAYSIZE(buf), fmt, args); + const char* value_text_begin = &g.TempBuffer[0]; + const char* value_text_end = value_text_begin + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args); const ImVec2 label_size = CalcTextSize(label, NULL, true); const ImGuiAabb value_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w + style.FramePadding.x*2, label_size.y)); @@ -4530,9 +4508,8 @@ void ImGui::BulletTextV(const char* fmt, va_list args) if (window->SkipItems) return; - static char buf[1024]; - const char* text_begin = buf; - const char* text_end = text_begin + ImFormatStringV(buf, IM_ARRAYSIZE(buf), fmt, args); + const char* text_begin = g.TempBuffer; + const char* text_end = text_begin + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args); const ImGuiStyle& style = g.Style; const float line_height = window->FontSize(); @@ -4559,18 +4536,18 @@ void ImGui::BulletText(const char* fmt, ...) // If returning 'true' the node is open and the user is responsible for calling TreePop bool ImGui::TreeNodeV(const char* str_id, const char* fmt, va_list args) { + ImGuiState& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return false; - static char buf[1024]; - ImFormatStringV(buf, IM_ARRAYSIZE(buf), fmt, args); + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args); if (!str_id || !str_id[0]) str_id = fmt; ImGui::PushID(str_id); - const bool opened = ImGui::CollapsingHeader(buf, "", false); + const bool opened = ImGui::CollapsingHeader(g.TempBuffer, "", false); ImGui::PopID(); if (opened) @@ -4591,18 +4568,18 @@ bool ImGui::TreeNode(const char* str_id, const char* fmt, ...) // If returning 'true' the node is open and the user is responsible for calling TreePop bool ImGui::TreeNodeV(const void* ptr_id, const char* fmt, va_list args) { + ImGuiState& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return false; - static char buf[1024]; - ImFormatStringV(buf, IM_ARRAYSIZE(buf), fmt, args); + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args); if (!ptr_id) ptr_id = fmt; ImGui::PushID(ptr_id); - const bool opened = ImGui::CollapsingHeader(buf, "", false); + const bool opened = ImGui::CollapsingHeader(g.TempBuffer, "", false); ImGui::PopID(); if (opened) @@ -5899,10 +5876,8 @@ bool ImGui::InputText(const char* label, char* buf, size_t buf_size, ImGuiInputT { const int ib = edit_state.HasSelection() ? ImMin(edit_state.StbState.select_start, edit_state.StbState.select_end) : 0; const int ie = edit_state.HasSelection() ? ImMax(edit_state.StbState.select_start, edit_state.StbState.select_end) : (int)edit_state.CurLenW; - char* tmp_buf = TempBufferLock(); - ImTextStrToUtf8(tmp_buf, TempBufferSize(), edit_state.Text+ib, edit_state.Text+ie); - g.IO.SetClipboardTextFn(tmp_buf); - TempBufferUnlock(); + ImTextStrToUtf8(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), edit_state.Text+ib, edit_state.Text+ie); + g.IO.SetClipboardTextFn(g.TempBuffer); } if (cut) @@ -5954,8 +5929,7 @@ bool ImGui::InputText(const char* label, char* buf, size_t buf_size, ImGuiInputT // Note that as soon as we can focus into the input box, the in-widget value gets priority over any underlying modification of the input buffer // FIXME: We actually always render 'buf' in RenderTextScrolledClipped // FIXME-OPT: CPU waste to do this every time the widget is active, should mark dirty state from the stb_textedit callbacks - char* tmp_buf = TempBufferLock(); - ImTextStrToUtf8(tmp_buf, TempBufferSize(), edit_state.Text, NULL); + ImTextStrToUtf8(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), edit_state.Text, NULL); // User callback if ((flags & (ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_CallbackHistory | ImGuiInputTextFlags_CallbackAlways)) != 0) @@ -5986,7 +5960,7 @@ bool ImGui::InputText(const char* label, char* buf, size_t buf_size, ImGuiInputT ImGuiTextEditCallbackData callback_data; callback_data.EventFlag = event_flag; callback_data.EventKey = event_key; - callback_data.Buf = tmp_buf; + callback_data.Buf = g.TempBuffer; callback_data.BufSize = edit_state.BufSizeA; callback_data.BufDirty = false; callback_data.Flags = flags; @@ -6001,7 +5975,7 @@ bool ImGui::InputText(const char* label, char* buf, size_t buf_size, ImGuiInputT callback(&callback_data); // Read back what user may have modified - IM_ASSERT(callback_data.Buf == tmp_buf); // Invalid to modify those fields + IM_ASSERT(callback_data.Buf == g.TempBuffer); // Invalid to modify those fields IM_ASSERT(callback_data.BufSize == edit_state.BufSizeA); IM_ASSERT(callback_data.Flags == flags); if (callback_data.CursorPos != utf8_cursor_pos) edit_state.StbState.cursor = ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.CursorPos); @@ -6009,18 +5983,17 @@ bool ImGui::InputText(const char* label, char* buf, size_t buf_size, ImGuiInputT if (callback_data.SelectionEnd != utf8_selection_end) edit_state.StbState.select_end = ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.SelectionEnd); if (callback_data.BufDirty) { - ImTextStrFromUtf8(edit_state.Text, IM_ARRAYSIZE(edit_state.Text), tmp_buf, NULL); + ImTextStrFromUtf8(edit_state.Text, IM_ARRAYSIZE(edit_state.Text), g.TempBuffer, NULL); edit_state.CursorAnimReset(); } } } - if (strcmp(tmp_buf, buf) != 0) + if (strcmp(g.TempBuffer, buf) != 0) { - ImFormatString(buf, buf_size, "%s", tmp_buf); + ImFormatString(buf, buf_size, "%s", g.TempBuffer); value_changed = true; } - TempBufferUnlock(); } } From d3e444dfd96338b4cfda56420b3ca9819e940c6a Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 16 Mar 2015 10:02:10 +0000 Subject: [PATCH 44/44] Examples: DirectX9: fixed duplicate creation of vertex buffer. Size of static vertex buffer at top of the code. --- examples/directx11_example/imgui_impl_dx11.cpp | 3 ++- examples/directx9_example/imgui_impl_dx9.cpp | 6 ++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index 2502b98dc..ba8d3d8b3 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -27,6 +27,7 @@ static ID3D11PixelShader* g_pPixelShader = NULL; static ID3D11SamplerState* g_pFontSampler = NULL; static ID3D11ShaderResourceView*g_pFontTextureView = NULL; static ID3D11BlendState* g_blendState = NULL; +static int VERTEX_BUFFER_SIZE = 30000; // TODO: Make vertex buffer smaller and grow dynamically as needed. struct CUSTOMVERTEX { @@ -358,7 +359,7 @@ bool ImGui_ImplDX11_CreateDeviceObjects() D3D11_BUFFER_DESC bufferDesc; memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC)); bufferDesc.Usage = D3D11_USAGE_DYNAMIC; - bufferDesc.ByteWidth = 100000 * sizeof(CUSTOMVERTEX); // Maybe we should handle that more dynamically? + bufferDesc.ByteWidth = VERTEX_BUFFER_SIZE * sizeof(CUSTOMVERTEX); bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; bufferDesc.MiscFlags = 0; diff --git a/examples/directx9_example/imgui_impl_dx9.cpp b/examples/directx9_example/imgui_impl_dx9.cpp index 60302d4cd..b726e50ed 100644 --- a/examples/directx9_example/imgui_impl_dx9.cpp +++ b/examples/directx9_example/imgui_impl_dx9.cpp @@ -15,6 +15,7 @@ static INT64 g_Time = 0; static INT64 g_TicksPerSecond = 0; static LPDIRECT3DDEVICE9 g_pd3dDevice = NULL; static LPDIRECT3DVERTEXBUFFER9 g_pVB = NULL; +static int VERTEX_BUFFER_SIZE = 30000; // TODO: Make vertex buffer smaller and grow dynamically as needed. struct CUSTOMVERTEX { @@ -183,9 +184,6 @@ bool ImGui_ImplDX9_Init(void* hwnd, IDirect3DDevice9* device) io.RenderDrawListsFn = ImGui_ImplDX9_RenderDrawLists; io.ImeWindowHandle = g_hWnd; - if (g_pd3dDevice->CreateVertexBuffer(10000 * sizeof(CUSTOMVERTEX), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVB, NULL) < 0) - return false; - return true; } @@ -232,7 +230,7 @@ bool ImGui_ImplDX9_CreateDeviceObjects() if (!g_pd3dDevice) return false; - if (g_pd3dDevice->CreateVertexBuffer(10000 * sizeof(CUSTOMVERTEX), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVB, NULL) < 0) + if (g_pd3dDevice->CreateVertexBuffer(VERTEX_BUFFER_SIZE * sizeof(CUSTOMVERTEX), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVB, NULL) < 0) return false; ImGui_ImplDX9_CreateFontsTexture();