Last active
April 9, 2020 06:40
-
-
Save kudaba/01337c088a0bcef0c2e22a4e846f729c to your computer and use it in GitHub Desktop.
Improved number editing control for ImGui
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// WARNING: Revision 5+ Requires unreleased code from imgui, stick to 3 or 2 for now (don't look at revision 4) | |
#define IMGUI_DEFINE_MATH_OPERATORS | |
#include <imgui.h> | |
#include <imgui_internal.h> | |
#include "iminputvalue.h" | |
namespace ImGui | |
{ | |
//------------------------------------------------------------------------------------------------- | |
// Customized number box with mouse drag support and condensed arrow buttons | |
//------------------------------------------------------------------------------------------------- | |
template <typename T> | |
bool InputValue(T& aValue, T aStep, ImGuiDataType aType, char const* aFormat, ImGuiInputTextFlags aFlags) | |
{ | |
float width = CalcItemWidth(); | |
float height = GetFrameHeight(); | |
BeginGroup(); | |
// Only show buttons if there's enough space | |
bool hasButtons = width > height * 4; | |
int buttonStep = 0; | |
if (hasButtons) | |
{ | |
width -= height; | |
PushItemWidth(width); | |
} | |
bool changed = InputScalar("", aType, &aValue, nullptr, nullptr, aFormat, aFlags); | |
ImGuiID id = GetItemID(); | |
SetActiveItemUsesMouseWheel(id); | |
if (hasButtons) | |
{ | |
PopItemWidth(); | |
PushStyleVar(ImGuiStyleVar_FramePadding, { 0, 0 }); | |
PushStyleVar(ImGuiStyleVar_ItemSpacing, { 0, 0 }); | |
SameLine(); | |
BeginGroup(); | |
if (ButtonEx("###up", { height, height / 2 }, ImGuiButtonFlags_NoNavFocus)) | |
{ | |
buttonStep = 1; | |
} | |
SetActiveItemUsesMouseWheel(id); | |
float offset = height - GetFontSize(); | |
ImVec2 pos = GetItemRectMin(); | |
RenderArrow(GetWindowDrawList(), { pos.x + offset / 2, pos.y + offset / 4 }, GetColorU32(ImGuiCol_Text), ImGuiDir_Up, 0.5f); | |
if (ButtonEx("###down", { height, height / 2 + 1 }, ImGuiButtonFlags_NoNavFocus)) | |
{ | |
buttonStep = -1; | |
} | |
SetActiveItemUsesMouseWheel(id); | |
pos = ImGui::GetItemRectMin(); | |
RenderArrow(GetWindowDrawList(), { pos.x + offset / 2, pos.y + 1 }, GetColorU32(ImGuiCol_Text), ImGuiDir_Down, 0.5f); | |
EndGroup(); | |
PopStyleVar(2); | |
} | |
EndGroup(); | |
if (buttonStep) | |
{ | |
if (ApplyStep(aValue, aStep, aType, buttonStep)) | |
{ | |
changed = true; | |
SetKeyboardFocusHere(-1); | |
} | |
} | |
// Drag support | |
{ | |
GC_MouseDragHelper& helper = ImGuiHelpers::GetStorageSlot()->GetOrCreate<GC_MouseDragHelper>(true); | |
if (helper.HasMouse() || IsItemHovered()) | |
{ | |
if (helper.Update(GetIO().KeyShift ? GC_MouseKey::Left : GC_MouseKey::Middle)) | |
SetKeyboardFocusHere(-1); | |
} | |
if (helper.HasMouse()) | |
{ | |
GC_Vector2i delta = GC_InputMouse::Instance().Movement(); | |
if (ApplyStep(aValue, aStep, aType, delta.x - delta.y)) | |
{ | |
changed = true; | |
if (GImGui->InputTextState.ID == id) | |
GImGui->InputTextState.Reinitialize = true; | |
} | |
} | |
} | |
// Mouse wheel support | |
{ | |
if (IsItemHovered() && IsItemActive()) | |
{ | |
if (float scroll = GetIO().InputCurrentFrame->MouseWheel) | |
{ | |
if (ApplyStep(aValue, aStep, aType, scroll)) | |
{ | |
changed = true; | |
if (GImGui->InputTextState.ID == id) | |
GImGui->InputTextState.Reinitialize = true; | |
} | |
} | |
} | |
} | |
return changed; | |
} | |
//------------------------------------------------------------------------------------------------- | |
template <typename T> | |
bool InputValues(char const* label, int components, ImGuiDataType data_type, T* aValue, T const* aStep, ImGuiInputTextFlags aFlags, char const* aFormat) | |
{ | |
ImGuiWindow* window = GetCurrentWindow(); | |
if (window->SkipItems) | |
return false; | |
ImGuiContext& g = *GImGui; | |
bool value_changed = false; | |
BeginGroup(); | |
PushID(label); | |
PushMultiItemsWidths(components, CalcItemWidth()); | |
for (int i = 0; i < components; i++) | |
{ | |
PushID(i); | |
if (i > 0) | |
SameLine(0, g.Style.ItemInnerSpacing.x); | |
value_changed |= InputValue(aValue[i], aStep[i], data_type, aFormat, aFlags); | |
PopID(); | |
PopItemWidth(); | |
} | |
PopID(); | |
const char* label_end = FindRenderedTextEnd(label); | |
if (label != label_end) | |
{ | |
SameLine(0.0f, g.Style.ItemInnerSpacing.x); | |
TextEx(label, label_end); | |
} | |
EndGroup(); | |
return value_changed; | |
} | |
//------------------------------------------------------------------------------------------------- | |
// All the value hooks into the custom edit box | |
//------------------------------------------------------------------------------------------------- | |
bool Input(char const* aName, float& aValue, float aStep, ImGuiInputTextFlags aFlags, char const* aFormat) | |
{ | |
return InputValues(aName, 1, ImGuiDataType_Float, &aValue, &aStep, aFlags, aFormat); | |
} | |
bool Input(char const* aName, double& aValue, double aStep, ImGuiInputTextFlags aFlags, char const* aFormat) | |
{ | |
return InputValues(aName, 1, ImGuiDataType_Double, &aValue, &aStep, aFlags, aFormat); | |
} | |
bool Input(char const* aName, s8& aValue, s8 aStep, ImGuiInputTextFlags aFlags, char const* aFormat) | |
{ | |
return InputValues(aName, 1, ImGuiDataType_S8, &aValue, &aStep, aFlags, aFormat); | |
} | |
bool Input(char const* aName, s16& aValue, s16 aStep, ImGuiInputTextFlags aFlags, char const* aFormat) | |
{ | |
return InputValues(aName, 1, ImGuiDataType_S16, &aValue, &aStep, aFlags, aFormat); | |
} | |
bool Input(char const* aName, s32& aValue, s32 aStep, ImGuiInputTextFlags aFlags, char const* aFormat) | |
{ | |
return InputValues(aName, 1, ImGuiDataType_S32, &aValue, &aStep, aFlags, aFormat); | |
} | |
bool Input(char const* aName, s64& aValue, s64 aStep, ImGuiInputTextFlags aFlags, char const* aFormat) | |
{ | |
return InputValues(aName, 1, ImGuiDataType_S64, &aValue, &aStep, aFlags, aFormat); | |
} | |
bool Input(char const* aName, u8& aValue, u8 aStep, ImGuiInputTextFlags aFlags, char const* aFormat) | |
{ | |
return InputValues(aName, 1, ImGuiDataType_U8, &aValue, &aStep, aFlags, aFormat); | |
} | |
bool Input(char const* aName, u16& aValue, u16 aStep, ImGuiInputTextFlags aFlags, char const* aFormat) | |
{ | |
return InputValues(aName, 1, ImGuiDataType_U16, &aValue, &aStep, aFlags, aFormat); | |
} | |
bool Input(char const* aName, u32& aValue, u32 aStep, ImGuiInputTextFlags aFlags, char const* aFormat) | |
{ | |
return InputValues(aName, 1, ImGuiDataType_U32, &aValue, &aStep, aFlags, aFormat); | |
} | |
bool Input(char const* aName, u64& aValue, u64 aStep, ImGuiInputTextFlags aFlags, char const* aFormat) | |
{ | |
return InputValues(aName, 1, ImGuiDataType_U64, &aValue, &aStep, aFlags, aFormat); | |
} | |
// Example for vector/math types | |
bool Input(char const* aName, Vector3<float>& aValue, u64 aStep, ImGuiInputTextFlags aFlags, char const* aFormat) | |
{ | |
return InputValues(aName, 3, ImGuiDataType_Float, &aValue, &aStep, aFlags, aFormat); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// WARNING: Revision 5+ Requires unreleased code from imgui, stick to 3 or 2 for now (don't look at revision 4) | |
namespace ImGui | |
{ | |
//------------------------------------------------------------------------------------------------- | |
// All the value hooks into the custom edit box | |
//------------------------------------------------------------------------------------------------- | |
bool Input(char const* aName, float& aValue, float aStep, ImGuiInputTextFlags aFlags, char const* aFormat); | |
bool Input(char const* aName, double& aValue, double aStep, ImGuiInputTextFlags aFlags, char const* aFormat); | |
bool Input(char const* aName, s8& aValue, s8 aStep, ImGuiInputTextFlags aFlags, char const* aFormat); | |
bool Input(char const* aName, s16& aValue, s16 aStep, ImGuiInputTextFlags aFlags, char const* aFormat); | |
bool Input(char const* aName, s32& aValue, s32 aStep, ImGuiInputTextFlags aFlags, char const* aFormat); | |
bool Input(char const* aName, s64& aValue, s64 aStep, ImGuiInputTextFlags aFlags, char const* aFormat); | |
bool Input(char const* aName, u8& aValue, u8 aStep, ImGuiInputTextFlags aFlags, char const* aFormat); | |
bool Input(char const* aName, u16& aValue, u16 aStep, ImGuiInputTextFlags aFlags, char const* aFormat); | |
bool Input(char const* aName, u32& aValue, u32 aStep, ImGuiInputTextFlags aFlags, char const* aFormat); | |
bool Input(char const* aName, u64& aValue, u64 aStep, ImGuiInputTextFlags aFlags, char const* aFormat); | |
// Example for vector/math types | |
bool Input(char const* aName, Vector3<float>& aValue, u64 aStep, ImGuiInputTextFlags aFlags, char const* aFormat); | |
} |
Author
kudaba
commented
Nov 5, 2019
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment