Updated ImGui.

This commit is contained in:
Branimir Karadžić 2017-10-19 22:00:45 -07:00
parent 974fe0891d
commit 3ed5d4bafb
3 changed files with 101 additions and 52 deletions

View File

@ -48,7 +48,8 @@
- Minimize setup and maintenance - Minimize setup and maintenance
- Minimize state storage on user side - Minimize state storage on user side
- Portable, minimize dependencies, run on target (consoles, phones, etc.) - Portable, minimize dependencies, run on target (consoles, phones, etc.)
- Efficient runtime and memory consumption (NB- we do allocate when "growing" content - creating a window / opening a tree node for the first time, etc. - but a typical frame won't allocate anything) - Efficient runtime and memory consumption (NB- we do allocate when "growing" content e.g. creating a window, opening a tree node
for the first time, etc. but a typical frame won't allocate anything)
Designed for developers and content-creators, not the typical end-user! Some of the weaknesses includes: Designed for developers and content-creators, not the typical end-user! Some of the weaknesses includes:
- Doesn't look fancy, doesn't animate - Doesn't look fancy, doesn't animate
@ -85,7 +86,8 @@
READ FIRST READ FIRST
- Read the FAQ below this section! - Read the FAQ below this section!
- Your code creates the UI, if your code doesn't run the UI is gone! == very dynamic UI, no construction/destructions steps, less data retention on your side, no state duplication, less sync, less bugs. - Your code creates the UI, if your code doesn't run the UI is gone! == very dynamic UI, no construction/destructions steps, less data retention
on your side, no state duplication, less sync, less bugs.
- Call and read ImGui::ShowTestWindow() for demo code demonstrating most features. - Call and read ImGui::ShowTestWindow() for demo code demonstrating most features.
- You can learn about immediate-mode gui principles at http://www.johno.se/book/imgui.html or watch http://mollyrocket.com/861 - You can learn about immediate-mode gui principles at http://www.johno.se/book/imgui.html or watch http://mollyrocket.com/861
@ -100,25 +102,28 @@
GETTING STARTED WITH INTEGRATING DEAR IMGUI IN YOUR CODE/ENGINE GETTING STARTED WITH INTEGRATING DEAR IMGUI IN YOUR CODE/ENGINE
- Add the Dear ImGui source files to your projects, using your preferred build system. It is recommended you build the .cpp files as part of your project and not as a library. - Add the Dear ImGui source files to your projects, using your preferred build system.
It is recommended you build the .cpp files as part of your project and not as a library.
- You can later customize the imconfig.h file to tweak some compilation time behavior, such as integrating imgui types with your own maths types. - You can later customize the imconfig.h file to tweak some compilation time behavior, such as integrating imgui types with your own maths types.
- See examples/ folder for standalone sample applications. To understand the integration process, you can read examples/opengl2_example/ because it is short, - See examples/ folder for standalone sample applications. To understand the integration process, you can read examples/opengl2_example/ because
then switch to the one more appropriate to your use case. it is short, then switch to the one more appropriate to your use case.
- You may be able to grab and copy a ready made imgui_impl_*** file from the examples/. - You may be able to grab and copy a ready made imgui_impl_*** file from the examples/.
- When using Dear ImGui, your programming IDE is your friend: follow the declaration of variables, functions and types to find comments about them. - When using Dear ImGui, your programming IDE is your friend: follow the declaration of variables, functions and types to find comments about them.
- Init: retrieve the ImGuiIO structure with ImGui::GetIO() and fill the fields marked 'Settings': at minimum you need to set io.DisplaySize (application resolution). - Init: retrieve the ImGuiIO structure with ImGui::GetIO() and fill the fields marked 'Settings': at minimum you need to set io.DisplaySize
Later on you will fill your keyboard mapping, clipboard handlers, and other advanced features but for a basic integration you don't need to worry about it all. (application resolution). Later on you will fill your keyboard mapping, clipboard handlers, and other advanced features but for a basic
integration you don't need to worry about it all.
- Init: call io.Fonts->GetTexDataAsRGBA32(...), it will build the font atlas texture, then load the texture pixels into graphics memory. - Init: call io.Fonts->GetTexDataAsRGBA32(...), it will build the font atlas texture, then load the texture pixels into graphics memory.
- Every frame: - Every frame:
- In your main loop as early a possible, fill the IO fields marked 'Input' (e.g. mouse position, buttons, keyboard info, etc.) - In your main loop as early a possible, fill the IO fields marked 'Input' (e.g. mouse position, buttons, keyboard info, etc.)
- Call ImGui::NewFrame() to begin the frame - Call ImGui::NewFrame() to begin the frame
- You can use any ImGui function you want between NewFrame() and Render() - You can use any ImGui function you want between NewFrame() and Render()
- Call ImGui::Render() as late as you can to end the frame and finalize render data. it will call your io.RenderDrawListFn handler. - Call ImGui::Render() as late as you can to end the frame and finalize render data. it will call your io.RenderDrawListFn handler.
(if you don't need to render, you still need to call Render() and ignore the callback, or call EndFrame() instead. if you call neither some aspects of windows focusing/moving will appear broken.) (Even if you don't render, call Render() and ignore the callback, or call EndFrame() instead. Otherwhise some features will break)
- All rendering information are stored into command-lists until ImGui::Render() is called. - All rendering information are stored into command-lists until ImGui::Render() is called.
- Dear ImGui never touches or knows about your GPU state. the only function that knows about GPU is the RenderDrawListFn handler that you provide. - Dear ImGui never touches or knows about your GPU state. the only function that knows about GPU is the RenderDrawListFn handler that you provide.
- Effectively it means you can create widgets at any time in your code, regardless of considerations of being in "update" vs "render" phases of your own application. - Effectively it means you can create widgets at any time in your code, regardless of considerations of being in "update" vs "render" phases
of your own application.
- Refer to the examples applications in the examples/ folder for instruction on how to setup your code. - Refer to the examples applications in the examples/ folder for instruction on how to setup your code.
- A minimal application skeleton may be: - A minimal application skeleton may be:
@ -126,7 +131,7 @@
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
io.DisplaySize.x = 1920.0f; io.DisplaySize.x = 1920.0f;
io.DisplaySize.y = 1280.0f; io.DisplaySize.y = 1280.0f;
io.RenderDrawListsFn = MyRenderFunction; // Setup a render function, or set to NULL and call GetDrawData() after Render() to access the render data. io.RenderDrawListsFn = MyRenderFunction; // Setup a render function, or set to NULL and call GetDrawData() after Render() to access render data.
// TODO: Fill others settings of the io structure later. // TODO: Fill others settings of the io structure later.
// Load texture atlas (there is a default font so you don't need to care about choosing a font yet) // Load texture atlas (there is a default font so you don't need to care about choosing a font yet)
@ -180,9 +185,16 @@
} }
else else
{ {
// Render 'pcmd->ElemCount/3' texture triangles // The texture for the draw call is specified by pcmd->TextureId.
// The vast majority of draw calls with use the imgui texture atlas, which value you have set yourself during initialization.
MyEngineBindTexture(pcmd->TextureId); MyEngineBindTexture(pcmd->TextureId);
// We are using scissoring to clip some objects. All low-level graphics API supports it.
// If your engine doesn't support scissoring yet, you will get some small glitches (some elements outside their bounds) which you can fix later.
MyEngineScissor((int)pcmd->ClipRect.x, (int)pcmd->ClipRect.y, (int)(pcmd->ClipRect.z - pcmd->ClipRect.x), (int)(pcmd->ClipRect.w - pcmd->ClipRect.y)); MyEngineScissor((int)pcmd->ClipRect.x, (int)pcmd->ClipRect.y, (int)(pcmd->ClipRect.z - pcmd->ClipRect.x), (int)(pcmd->ClipRect.w - pcmd->ClipRect.y));
// Render 'pcmd->ElemCount/3' indexed triangles.
// By default the indices ImDrawIdx are 16-bits, you can change them to 32-bits if your engine doesn't support 16-bits indices.
MyEngineDrawIndexedTriangles(pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer, vtx_buffer); MyEngineDrawIndexedTriangles(pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer, vtx_buffer);
} }
idx_buffer += pcmd->ElemCount; idx_buffer += pcmd->ElemCount;
@ -360,21 +372,22 @@
Also make sure your orthographic projection matrix and io.DisplaySize matches your actual framebuffer dimension. Also make sure your orthographic projection matrix and io.DisplaySize matches your actual framebuffer dimension.
Q: I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around.. Q: I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around..
A: Most likely you are mishandling the clipping rectangles in your render function. Rectangles provided by ImGui are defined as (x1=left,y1=top,x2=right,y2=bottom) and NOT as (x1,y1,width,height). A: You are probably mishandling the clipping rectangles in your render function.
Rectangles provided by ImGui are defined as (x1=left,y1=top,x2=right,y2=bottom) and NOT as (x1,y1,width,height).
Q: Can I have multiple widgets with the same label? Can I have widget without a label? Q: Can I have multiple widgets with the same label? Can I have widget without a label?
A: Yes. A primer on the use of labels/IDs in Dear ImGui.. A: Yes. A primer on the use of labels/IDs in Dear ImGui..
- Elements that are not clickable, such as Text() items don't need an ID. - Elements that are not clickable, such as Text() items don't need an ID.
- Interactive widgets require state to be carried over multiple frames (most typically Dear ImGui often needs to remember what is the "active" widget). - Interactive widgets require state to be carried over multiple frames (most typically Dear ImGui often needs to remember what is
to do so they need a unique ID. unique ID are typically derived from a string label, an integer index or a pointer. the "active" widget). to do so they need a unique ID. unique ID are typically derived from a string label, an integer index or a pointer.
Button("OK"); // Label = "OK", ID = hash of "OK" Button("OK"); // Label = "OK", ID = hash of "OK"
Button("Cancel"); // Label = "Cancel", ID = hash of "Cancel" Button("Cancel"); // Label = "Cancel", ID = hash of "Cancel"
- ID are uniquely scoped within windows, tree nodes, etc. so no conflict can happen if you have two buttons called "OK" in two different windows - ID are uniquely scoped within windows, tree nodes, etc. so no conflict can happen if you have two buttons called "OK"
or in two different locations of a tree. in two different windows or in two different locations of a tree.
- If you have a same ID twice in the same location, you'll have a conflict: - If you have a same ID twice in the same location, you'll have a conflict:
@ -383,8 +396,8 @@
Fear not! this is easy to solve and there are many ways to solve it! Fear not! this is easy to solve and there are many ways to solve it!
- When passing a label you can optionally specify extra unique ID information within string itself. This helps solving the simpler collision cases. - When passing a label you can optionally specify extra unique ID information within string itself.
use "##" to pass a complement to the ID that won't be visible to the end-user: This helps solving the simpler collision cases. Use "##" to pass a complement to the ID that won't be visible to the end-user:
Button("Play"); // Label = "Play", ID = hash of "Play" Button("Play"); // Label = "Play", ID = hash of "Play"
Button("Play##foo1"); // Label = "Play", ID = hash of "Play##foo1" (different from above) Button("Play##foo1"); // Label = "Play", ID = hash of "Play##foo1" (different from above)
@ -452,18 +465,22 @@
- When working with trees, ID are used to preserve the open/close state of each tree node. - When working with trees, ID are used to preserve the open/close state of each tree node.
Depending on your use cases you may want to use strings, indices or pointers as ID. Depending on your use cases you may want to use strings, indices or pointers as ID.
e.g. when displaying a single object that may change over time (1-1 relationship), using a static string as ID will preserve your node open/closed state when the targeted object change. e.g. when displaying a single object that may change over time (dynamic 1-1 relationship), using a static string as ID will preserve your
e.g. when displaying a list of objects, using indices or pointers as ID will preserve the node open/closed state differently. experiment and see what makes more sense! node open/closed state when the targeted object change.
e.g. when displaying a list of objects, using indices or pointers as ID will preserve the node open/closed state differently.
experiment and see what makes more sense!
Q: How can I tell when Dear ImGui wants my mouse/keyboard inputs VS when I can pass them to my application? Q: How can I tell when Dear ImGui wants my mouse/keyboard inputs VS when I can pass them to my application?
A: You can read the 'io.WantCaptureMouse'/'io.WantCaptureKeyboard'/'ioWantTextInput' flags from the ImGuiIO structure. A: You can read the 'io.WantCaptureMouse'/'io.WantCaptureKeyboard'/'ioWantTextInput' flags from the ImGuiIO structure.
- When 'io.WantCaptureMouse' or 'io.WantCaptureKeyboard' flags are set you may want to discard/hide the inputs from the rest of your application. - When 'io.WantCaptureMouse' or 'io.WantCaptureKeyboard' flags are set you may want to discard/hide the inputs from the rest of your application.
- When 'io.WantTextInput' is set to may want to notify your OS to popup an on-screen keyboard, if available (e.g. on a mobile phone, or console without a keyboard). - When 'io.WantTextInput' is set to may want to notify your OS to popup an on-screen keyboard, if available (e.g. on a mobile phone, or console OS).
Preferably read the flags after calling ImGui::NewFrame() to avoid them lagging by one frame. But reading those flags before calling NewFrame() is also generally ok, Preferably read the flags after calling ImGui::NewFrame() to avoid them lagging by one frame. But reading those flags before calling NewFrame() is
as the bool toggles fairly rarely and you don't generally expect to interact with either Dear ImGui or your application during the same frame when that transition occurs. also generally ok, as the bool toggles fairly rarely and you don't generally expect to interact with either Dear ImGui or your application during
Dear ImGui is tracking dragging and widget activity that may occur outside the boundary of a window, so 'io.WantCaptureMouse' is more accurate and correct than checking if a window is hovered. the same frame when that transition occurs. Dear ImGui is tracking dragging and widget activity that may occur outside the boundary of a window,
(Advanced note: text input releases focus on Return 'KeyDown', so the following Return 'KeyUp' event that your application receive will typically have 'io.WantCaptureKeyboard=false'. so 'io.WantCaptureMouse' is more accurate and correct than checking if a window is hovered.
Depending on your application logic it may or not be inconvenient. You might want to track which key-downs were for Dear ImGui (e.g. with an array of bool) and filter out the corresponding key-ups.) (Advanced note: text input releases focus on Return 'KeyDown', so the following Return 'KeyUp' event that your application receive will typically
have 'io.WantCaptureKeyboard=false'. Depending on your application logic it may or not be inconvenient. You might want to track which key-downs
were for Dear ImGui, e.g. with an array of bool, and filter out the corresponding key-ups.)
Q: How can I load a different font than the default? (default is an embedded version of ProggyClean.ttf, rendered at size 13) Q: How can I load a different font than the default? (default is an embedded version of ProggyClean.ttf, rendered at size 13)
A: Use the font atlas to load the TTF/OTF file you want: A: Use the font atlas to load the TTF/OTF file you want:
@ -473,8 +490,8 @@
io.Fonts->GetTexDataAsRGBA32() or GetTexDataAsAlpha8() io.Fonts->GetTexDataAsRGBA32() or GetTexDataAsAlpha8()
Q: How can I easily use icons in my application? Q: How can I easily use icons in my application?
A: The most convenient and practical way is to merge an icon font such as FontAwesome inside you main font. Then you can refer to icons within your strings. A: The most convenient and practical way is to merge an icon font such as FontAwesome inside you main font. Then you can refer to icons within your
Read 'How can I load multiple fonts?' and the file 'extra_fonts/README.txt' for instructions. strings. Read 'How can I load multiple fonts?' and the file 'extra_fonts/README.txt' for instructions and useful header files.
Q: How can I load multiple fonts? Q: How can I load multiple fonts?
A: Use the font atlas to pack them into a single texture: A: Use the font atlas to pack them into a single texture:
@ -524,19 +541,24 @@
Otherwise you can convert yourself to UTF-8 or load text data from file already saved as UTF-8. Otherwise you can convert yourself to UTF-8 or load text data from file already saved as UTF-8.
Text input: it is up to your application to pass the right character code to io.AddInputCharacter(). The applications in examples/ are doing that. Text input: it is up to your application to pass the right character code to io.AddInputCharacter(). The applications in examples/ are doing that.
For languages using IME, on Windows you can copy the Hwnd of your application to io.ImeWindowHandle. The default implementation of io.ImeSetInputScreenPosFn() on Windows will set your IME position correctly. For languages using IME, on Windows you can copy the Hwnd of your application to io.ImeWindowHandle.
The default implementation of io.ImeSetInputScreenPosFn() on Windows will set your IME position correctly.
Q: How can I preserve my Dear ImGui context across reloading a DLL? (loss of the global/static variables) Q: How can I preserve my Dear ImGui context across reloading a DLL? (loss of the global/static variables)
A: Create your own context 'ctx = CreateContext()' + 'SetCurrentContext(ctx)' and your own font atlas 'ctx->GetIO().Fonts = new ImFontAtlas()' so you don't rely on the default globals. A: Create your own context 'ctx = CreateContext()' + 'SetCurrentContext(ctx)' and your own font atlas 'ctx->GetIO().Fonts = new ImFontAtlas()'
so you don't rely on the default globals.
Q: How can I use the drawing facilities without an ImGui window? (using ImDrawList API) Q: How can I use the drawing facilities without an ImGui window? (using ImDrawList API)
A: The easiest way is to create a dummy window. Call Begin() with NoTitleBar|NoResize|NoMove|NoScrollbar|NoSavedSettings|NoInputs flag, zero background alpha, A: The easiest way is to create a dummy window. Call Begin() with NoTitleBar|NoResize|NoMove|NoScrollbar|NoSavedSettings|NoInputs flag,
then retrieve the ImDrawList* via GetWindowDrawList() and draw to it in any way you like. zero background alpha, then retrieve the ImDrawList* via GetWindowDrawList() and draw to it in any way you like.
You can also perfectly create a standalone ImDrawList instance _but_ you need ImGui to be initialized because ImDrawList pulls from ImGui data to retrieve the coordinates of the white pixel. You can also perfectly create a standalone ImDrawList instance _but_ you need ImGui to be initialized because ImDrawList pulls from ImGui
data to retrieve the coordinates of the white pixel.
- tip: the construct 'IMGUI_ONCE_UPON_A_FRAME { ... }' will run the block of code only once a frame. You can use it to quickly add custom UI in the middle of a deep nested inner loop in your code. - tip: you can call Begin() multiple times with the same name during the same frame, it will keep appending to the same window.
- tip: you can create widgets without a Begin()/End() block, they will go in an implicit window called "Debug" this is also useful to set yourself in the context of another window (to get/set other settings)
- tip: you can call Begin() multiple times with the same name during the same frame, it will keep appending to the same window. this is also useful to set yourself in the context of another window (to get/set other settings) - tip: you can create widgets without a Begin()/End() block, they will go in an implicit window called "Debug".
- tip: the ImGuiOnceUponAFrame helper will allow run the block of code only once a frame. You can use it to quickly add custom UI in the middle
of a deep nested inner loop in your code.
- tip: you can call Render() multiple times (e.g for VR renders). - tip: you can call Render() multiple times (e.g for VR renders).
- tip: call and read the ShowTestWindow() code in imgui_demo.cpp for more example of how to use ImGui! - tip: call and read the ShowTestWindow() code in imgui_demo.cpp for more example of how to use ImGui!
@ -9668,21 +9690,6 @@ static void RenderArrowsForVerticalBar(ImDrawList* draw_list, ImVec2 pos, ImVec2
RenderArrow(draw_list, ImVec2(pos.x + bar_w - half_sz.x, pos.y), half_sz, ImGuiDir_Left, IM_COL32_WHITE); RenderArrow(draw_list, ImVec2(pos.x + bar_w - half_sz.x, pos.y), half_sz, ImGuiDir_Left, IM_COL32_WHITE);
} }
static void PaintVertsLinearGradientKeepAlpha(ImDrawVert* vert_start, ImDrawVert* vert_end, ImVec2 gradient_p0, ImVec2 gradient_p1, ImU32 col0, ImU32 col1)
{
ImVec2 gradient_extent = gradient_p1 - gradient_p0;
float gradient_inv_length2 = 1.0f / ImLengthSqr(gradient_extent);
for (ImDrawVert* vert = vert_start; vert < vert_end; vert++)
{
float d = ImDot(vert->pos - gradient_p0, gradient_extent);
float t = ImClamp(d * gradient_inv_length2, 0.0f, 1.0f);
int r = ImLerp((int)(col0 >> IM_COL32_R_SHIFT) & 0xFF, (int)(col1 >> IM_COL32_R_SHIFT) & 0xFF, t);
int g = ImLerp((int)(col0 >> IM_COL32_G_SHIFT) & 0xFF, (int)(col1 >> IM_COL32_G_SHIFT) & 0xFF, t);
int b = ImLerp((int)(col0 >> IM_COL32_B_SHIFT) & 0xFF, (int)(col1 >> IM_COL32_B_SHIFT) & 0xFF, t);
vert->col = (r << IM_COL32_R_SHIFT) | (g << IM_COL32_G_SHIFT) | (b << IM_COL32_B_SHIFT) | (vert->col & IM_COL32_A_MASK);
}
}
// ColorPicker // ColorPicker
// Note: only access 3 floats if ImGuiColorEditFlags_NoAlpha flag is set. // Note: only access 3 floats if ImGuiColorEditFlags_NoAlpha flag is set.
// FIXME: we adjust the big color square height based on item width, which may cause a flickering feedback loop (if automatic height makes a vertical scrollbar appears, affecting automatic width..) // FIXME: we adjust the big color square height based on item width, which may cause a flickering feedback loop (if automatic height makes a vertical scrollbar appears, affecting automatic width..)
@ -9900,7 +9907,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
// Paint colors over existing vertices // Paint colors over existing vertices
ImVec2 gradient_p0(wheel_center.x + cosf(a0) * wheel_r_inner, wheel_center.y + sinf(a0) * wheel_r_inner); ImVec2 gradient_p0(wheel_center.x + cosf(a0) * wheel_r_inner, wheel_center.y + sinf(a0) * wheel_r_inner);
ImVec2 gradient_p1(wheel_center.x + cosf(a1) * wheel_r_inner, wheel_center.y + sinf(a1) * wheel_r_inner); ImVec2 gradient_p1(wheel_center.x + cosf(a1) * wheel_r_inner, wheel_center.y + sinf(a1) * wheel_r_inner);
PaintVertsLinearGradientKeepAlpha(draw_list->_VtxWritePtr - (draw_list->_VtxCurrentIdx - vert_start_idx), draw_list->_VtxWritePtr, gradient_p0, gradient_p1, hue_colors[n], hue_colors[n+1]); ShadeVertsLinearColorGradientKeepAlpha(draw_list->_VtxWritePtr - (draw_list->_VtxCurrentIdx - vert_start_idx), draw_list->_VtxWritePtr, gradient_p0, gradient_p1, hue_colors[n], hue_colors[n+1]);
} }
// Render Cursor + preview on Hue Wheel // Render Cursor + preview on Hue Wheel

View File

@ -1036,6 +1036,43 @@ void ImDrawData::ScaleClipRects(const ImVec2& scale)
} }
} }
//-----------------------------------------------------------------------------
// Shade functions
//-----------------------------------------------------------------------------
// Generic linear color gradient, write to RGB fields, leave A untouched.
void ImGui::ShadeVertsLinearColorGradientKeepAlpha(ImDrawVert* vert_start, ImDrawVert* vert_end, ImVec2 gradient_p0, ImVec2 gradient_p1, ImU32 col0, ImU32 col1)
{
ImVec2 gradient_extent = gradient_p1 - gradient_p0;
float gradient_inv_length2 = 1.0f / ImLengthSqr(gradient_extent);
for (ImDrawVert* vert = vert_start; vert < vert_end; vert++)
{
float d = ImDot(vert->pos - gradient_p0, gradient_extent);
float t = ImClamp(d * gradient_inv_length2, 0.0f, 1.0f);
int r = ImLerp((int)(col0 >> IM_COL32_R_SHIFT) & 0xFF, (int)(col1 >> IM_COL32_R_SHIFT) & 0xFF, t);
int g = ImLerp((int)(col0 >> IM_COL32_G_SHIFT) & 0xFF, (int)(col1 >> IM_COL32_G_SHIFT) & 0xFF, t);
int b = ImLerp((int)(col0 >> IM_COL32_B_SHIFT) & 0xFF, (int)(col1 >> IM_COL32_B_SHIFT) & 0xFF, t);
vert->col = (r << IM_COL32_R_SHIFT) | (g << IM_COL32_G_SHIFT) | (b << IM_COL32_B_SHIFT) | (vert->col & IM_COL32_A_MASK);
}
}
// Scan and shade backward from the end of given vertices. Assume vertices are text only (= vert_start..vert_end going left to right) so we can break as soon as we are out the gradient bounds.
void ImGui::ShadeVertsLinearAlphaGradientForLeftToRightText(ImDrawVert* vert_start, ImDrawVert* vert_end, float gradient_p0_x, float gradient_p1_x)
{
float gradient_extent_x = gradient_p1_x - gradient_p0_x;
float gradient_inv_length2 = 1.0f / (gradient_extent_x * gradient_extent_x);
int full_alpha_count = 0;
for (ImDrawVert* vert = vert_end - 1; vert >= vert_start; vert--)
{
float d = (vert->pos.x - gradient_p0_x) * (gradient_extent_x);
float alpha_mul = 1.0f - ImClamp(d * gradient_inv_length2, 0.0f, 1.0f);
if (alpha_mul >= 1.0f && ++full_alpha_count > 2)
return; // Early out
int a = (int)(((vert->col >> IM_COL32_A_SHIFT) & 0xFF) * alpha_mul);
vert->col = (vert->col & ~IM_COL32_A_MASK) | (a << IM_COL32_A_SHIFT);
}
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// ImFontConfig // ImFontConfig
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------

View File

@ -154,6 +154,7 @@ static inline float ImFloor(float f)
static inline ImVec2 ImFloor(const ImVec2& v) { return ImVec2((float)(int)v.x, (float)(int)v.y); } static inline ImVec2 ImFloor(const ImVec2& v) { return ImVec2((float)(int)v.x, (float)(int)v.y); }
static inline float ImDot(const ImVec2& a, const ImVec2& b) { return a.x * b.x + a.y * b.y; } static inline float ImDot(const ImVec2& a, const ImVec2& b) { return a.x * b.x + a.y * b.y; }
static inline ImVec2 ImRotate(const ImVec2& v, float cos_a, float sin_a) { return ImVec2(v.x * cos_a - v.y * sin_a, v.x * sin_a + v.y * cos_a); } static inline ImVec2 ImRotate(const ImVec2& v, float cos_a, float sin_a) { return ImVec2(v.x * cos_a - v.y * sin_a, v.x * sin_a + v.y * cos_a); }
static inline float ImLinearSweep(float current, float target, float speed) { if (current < target) return ImMin(current + speed, target); if (current > target) return ImMax(current - speed, target); return current; }
// We call C++ constructor on own allocated memory via the placement "new(ptr) Type()" syntax. // We call C++ constructor on own allocated memory via the placement "new(ptr) Type()" syntax.
// Defining a custom placement new() with a dummy parameter allows us to bypass including <new> which on some platforms complains when user has disabled exceptions. // Defining a custom placement new() with a dummy parameter allows us to bypass including <new> which on some platforms complains when user has disabled exceptions.
@ -859,6 +860,10 @@ namespace ImGui
IMGUI_API int ParseFormatPrecision(const char* fmt, int default_value); IMGUI_API int ParseFormatPrecision(const char* fmt, int default_value);
IMGUI_API float RoundScalar(float value, int decimal_precision); IMGUI_API float RoundScalar(float value, int decimal_precision);
// Shade functions
IMGUI_API void ShadeVertsLinearColorGradientKeepAlpha(ImDrawVert* vert_start, ImDrawVert* vert_end, ImVec2 gradient_p0, ImVec2 gradient_p1, ImU32 col0, ImU32 col1);
IMGUI_API void ShadeVertsLinearAlphaGradientForLeftToRightText(ImDrawVert* vert_start, ImDrawVert* vert_end, float gradient_p0_x, float gradient_p1_x);
} // namespace ImGui } // namespace ImGui
// ImFontAtlas internals // ImFontAtlas internals