Refactor PushStyleVar/PopStyleVar so it is constant time + can receive integers (yet unused) (#842)

This commit is contained in:
ocornut 2016-09-25 11:06:14 +02:00
parent 35c6fd682f
commit c5b8c6303a
3 changed files with 74 additions and 52 deletions

105
imgui.cpp
View File

@ -563,7 +563,6 @@
- style: color-box not always square? - style: color-box not always square?
- style: a concept of "compact style" that the end-user can easily rely on (e.g. PushStyleCompact()?) that maps to other settings? avoid implementing duplicate helpers such as SmallCheckbox(), etc. - style: a concept of "compact style" that the end-user can easily rely on (e.g. PushStyleCompact()?) that maps to other settings? avoid implementing duplicate helpers such as SmallCheckbox(), etc.
- style: try to make PushStyleVar() more robust to incorrect parameters (to be more friendly to edit & continues situation). - style: try to make PushStyleVar() more robust to incorrect parameters (to be more friendly to edit & continues situation).
- style/opt: PopStyleVar could be optimized by having GetStyleVar returns the type, using a table mapping stylevar enum to data type.
- style: global scale setting. - style: global scale setting.
- style: WindowPadding needs to be EVEN needs the 0.5 multiplier probably have a subtle effect on clip rectangle - style: WindowPadding needs to be EVEN needs the 0.5 multiplier probably have a subtle effect on clip rectangle
- text: simple markup language for color change? - text: simple markup language for color change?
@ -4646,7 +4645,7 @@ void ImGui::PushStyleColor(ImGuiCol idx, const ImVec4& col)
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImGuiColMod backup; ImGuiColMod backup;
backup.Col = idx; backup.Col = idx;
backup.PreviousValue = g.Style.Colors[idx]; backup.BackupValue = g.Style.Colors[idx];
g.ColorModifiers.push_back(backup); g.ColorModifiers.push_back(backup);
g.Style.Colors[idx] = col; g.Style.Colors[idx] = col;
} }
@ -4657,64 +4656,78 @@ void ImGui::PopStyleColor(int count)
while (count > 0) while (count > 0)
{ {
ImGuiColMod& backup = g.ColorModifiers.back(); ImGuiColMod& backup = g.ColorModifiers.back();
g.Style.Colors[backup.Col] = backup.PreviousValue; g.Style.Colors[backup.Col] = backup.BackupValue;
g.ColorModifiers.pop_back(); g.ColorModifiers.pop_back();
count--; count--;
} }
} }
static float* GetStyleVarFloatAddr(ImGuiStyleVar idx) struct ImGuiStyleVarInfo
{ {
ImGuiContext& g = *GImGui; ImGuiDataType Type;
switch (idx) ImU32 Offset;
{ void* GetVarPtr() const { return (void*)((unsigned char*)&GImGui->Style + Offset); }
case ImGuiStyleVar_Alpha: return &g.Style.Alpha; };
case ImGuiStyleVar_WindowRounding: return &g.Style.WindowRounding;
case ImGuiStyleVar_ChildWindowRounding: return &g.Style.ChildWindowRounding; static const ImGuiStyleVarInfo GStyleVarInfo[ImGuiStyleVar_Count_] =
case ImGuiStyleVar_FrameRounding: return &g.Style.FrameRounding; {
case ImGuiStyleVar_IndentSpacing: return &g.Style.IndentSpacing; { ImGuiDataType_Float, (ImU32)IM_OFFSETOF(ImGuiStyle, Alpha) },
case ImGuiStyleVar_GrabMinSize: return &g.Style.GrabMinSize; { ImGuiDataType_Float2, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowPadding) },
} { ImGuiDataType_Float, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowRounding) },
return NULL; { ImGuiDataType_Float2, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowMinSize) },
{ ImGuiDataType_Float, (ImU32)IM_OFFSETOF(ImGuiStyle, ChildWindowRounding) },
{ ImGuiDataType_Float2, (ImU32)IM_OFFSETOF(ImGuiStyle, FramePadding) },
{ ImGuiDataType_Float, (ImU32)IM_OFFSETOF(ImGuiStyle, FrameRounding) },
{ ImGuiDataType_Float2, (ImU32)IM_OFFSETOF(ImGuiStyle, ItemSpacing) },
{ ImGuiDataType_Float2, (ImU32)IM_OFFSETOF(ImGuiStyle, ItemInnerSpacing) },
{ ImGuiDataType_Float, (ImU32)IM_OFFSETOF(ImGuiStyle, IndentSpacing) },
{ ImGuiDataType_Float, (ImU32)IM_OFFSETOF(ImGuiStyle, GrabMinSize) },
};
static const void* GetStyleVarPtr(ImGuiStyleVar idx, ImGuiDataType type)
{
IM_ASSERT(idx >= 0 && idx < ImGuiStyleVar_Count_);
const ImGuiStyleVarInfo* info = &GStyleVarInfo[idx];
return (info->Type == type) ? info->GetVarPtr() : NULL;
} }
static ImVec2* GetStyleVarVec2Addr(ImGuiStyleVar idx) void ImGui::PushStyleVar(ImGuiStyleVar idx, int val)
{ {
ImGuiContext& g = *GImGui; if (int* pvar = (int*)GetStyleVarPtr(idx, ImGuiDataType_Int))
switch (idx)
{ {
case ImGuiStyleVar_WindowPadding: return &g.Style.WindowPadding; GImGui->StyleModifiers.push_back(ImGuiStyleMod(idx, *pvar));
case ImGuiStyleVar_WindowMinSize: return &g.Style.WindowMinSize; *pvar = val;
case ImGuiStyleVar_FramePadding: return &g.Style.FramePadding; return;
case ImGuiStyleVar_ItemSpacing: return &g.Style.ItemSpacing;
case ImGuiStyleVar_ItemInnerSpacing: return &g.Style.ItemInnerSpacing;
} }
return NULL; if (float* pvarf = (float*)GetStyleVarPtr(idx, ImGuiDataType_Float))
{
GImGui->StyleModifiers.push_back(ImGuiStyleMod(idx, *pvarf));
*pvarf = (float)val;
return;
}
IM_ASSERT(0); // Called function with wrong-type? Variable is not a int.
} }
void ImGui::PushStyleVar(ImGuiStyleVar idx, float val) void ImGui::PushStyleVar(ImGuiStyleVar idx, float val)
{ {
ImGuiContext& g = *GImGui; if (float* pvar = (float*)GetStyleVarPtr(idx, ImGuiDataType_Float))
float* pvar = GetStyleVarFloatAddr(idx); {
IM_ASSERT(pvar != NULL); // Called function with wrong-type? Variable is not a float. GImGui->StyleModifiers.push_back(ImGuiStyleMod(idx, *pvar));
ImGuiStyleMod backup; *pvar = val;
backup.Var = idx; return;
backup.PreviousValue = ImVec2(*pvar, 0.0f); }
g.StyleModifiers.push_back(backup); IM_ASSERT(0); // Called function with wrong-type? Variable is not a float.
*pvar = val;
} }
void ImGui::PushStyleVar(ImGuiStyleVar idx, const ImVec2& val) void ImGui::PushStyleVar(ImGuiStyleVar idx, const ImVec2& val)
{ {
ImGuiContext& g = *GImGui; if (ImVec2* pvar = (ImVec2*)GetStyleVarPtr(idx, ImGuiDataType_Float2))
ImVec2* pvar = GetStyleVarVec2Addr(idx); {
IM_ASSERT(pvar != NULL); // Called function with wrong-type? Variable is not a ImVec2. GImGui->StyleModifiers.push_back(ImGuiStyleMod(idx, *pvar));
ImGuiStyleMod backup; *pvar = val;
backup.Var = idx; return;
backup.PreviousValue = *pvar; }
g.StyleModifiers.push_back(backup); IM_ASSERT(0); // Called function with wrong-type? Variable is not a ImVec2.
*pvar = val;
} }
void ImGui::PopStyleVar(int count) void ImGui::PopStyleVar(int count)
@ -4723,10 +4736,12 @@ void ImGui::PopStyleVar(int count)
while (count > 0) while (count > 0)
{ {
ImGuiStyleMod& backup = g.StyleModifiers.back(); ImGuiStyleMod& backup = g.StyleModifiers.back();
if (float* pvar_f = GetStyleVarFloatAddr(backup.Var)) IM_ASSERT(backup.VarIdx >= 0 && backup.VarIdx < ImGuiStyleVar_Count_);
*pvar_f = backup.PreviousValue.x; const ImGuiStyleVarInfo* info = &GStyleVarInfo[backup.VarIdx];
else if (ImVec2* pvar_v = GetStyleVarVec2Addr(backup.Var)) void* pvar = info->GetVarPtr();
*pvar_v = backup.PreviousValue; if (info->Type == ImGuiDataType_Float) (*(float*)pvar) = backup.BackupFloat[0];
else if (info->Type == ImGuiDataType_Float2) (*(ImVec2*)pvar) = ImVec2(backup.BackupFloat[0], backup.BackupFloat[1]);
else if (info->Type == ImGuiDataType_Int) (*(int*)pvar) = backup.BackupInt[0];
g.StyleModifiers.pop_back(); g.StyleModifiers.pop_back();
count--; count--;
} }

View File

@ -176,6 +176,7 @@ namespace ImGui
IMGUI_API void PopFont(); IMGUI_API void PopFont();
IMGUI_API void PushStyleColor(ImGuiCol idx, const ImVec4& col); IMGUI_API void PushStyleColor(ImGuiCol idx, const ImVec4& col);
IMGUI_API void PopStyleColor(int count = 1); IMGUI_API void PopStyleColor(int count = 1);
IMGUI_API void PushStyleVar(ImGuiStyleVar idx, int val);
IMGUI_API void PushStyleVar(ImGuiStyleVar idx, float val); IMGUI_API void PushStyleVar(ImGuiStyleVar idx, float val);
IMGUI_API void PushStyleVar(ImGuiStyleVar idx, const ImVec2& val); IMGUI_API void PushStyleVar(ImGuiStyleVar idx, const ImVec2& val);
IMGUI_API void PopStyleVar(int count = 1); IMGUI_API void PopStyleVar(int count = 1);
@ -646,7 +647,8 @@ enum ImGuiStyleVar_
ImGuiStyleVar_ItemSpacing, // ImVec2 ImGuiStyleVar_ItemSpacing, // ImVec2
ImGuiStyleVar_ItemInnerSpacing, // ImVec2 ImGuiStyleVar_ItemInnerSpacing, // ImVec2
ImGuiStyleVar_IndentSpacing, // float ImGuiStyleVar_IndentSpacing, // float
ImGuiStyleVar_GrabMinSize // float ImGuiStyleVar_GrabMinSize, // float
ImGuiStyleVar_Count_
}; };
enum ImGuiAlign_ enum ImGuiAlign_

View File

@ -75,6 +75,7 @@ extern IMGUI_API ImGuiContext* GImGui; // current implicit ImGui context po
#define IM_ARRAYSIZE(_ARR) ((int)(sizeof(_ARR)/sizeof(*_ARR))) #define IM_ARRAYSIZE(_ARR) ((int)(sizeof(_ARR)/sizeof(*_ARR)))
#define IM_PI 3.14159265358979323846f #define IM_PI 3.14159265358979323846f
#define IM_OFFSETOF(_TYPE,_ELM) ((size_t)&(((_TYPE*)0)->_ELM))
// Helpers: UTF-8 <> wchar // Helpers: UTF-8 <> wchar
IMGUI_API int ImTextStrToUtf8(char* buf, int buf_size, const ImWchar* in_text, const ImWchar* in_text_end); // return output UTF-8 bytes count IMGUI_API int ImTextStrToUtf8(char* buf, int buf_size, const ImWchar* in_text, const ImWchar* in_text_end); // return output UTF-8 bytes count
@ -192,7 +193,8 @@ enum ImGuiPlotType
enum ImGuiDataType enum ImGuiDataType
{ {
ImGuiDataType_Int, ImGuiDataType_Int,
ImGuiDataType_Float ImGuiDataType_Float,
ImGuiDataType_Float2,
}; };
// 2D axis aligned bounding-box // 2D axis aligned bounding-box
@ -241,14 +243,17 @@ struct IMGUI_API ImRect
struct ImGuiColMod struct ImGuiColMod
{ {
ImGuiCol Col; ImGuiCol Col;
ImVec4 PreviousValue; ImVec4 BackupValue;
}; };
// Stacked style modifier, backup of modified data so we can restore it // Stacked style modifier, backup of modified data so we can restore it. Data type inferred from the variable.
struct ImGuiStyleMod struct ImGuiStyleMod
{ {
ImGuiStyleVar Var; ImGuiStyleVar VarIdx;
ImVec2 PreviousValue; union { int BackupInt[2]; float BackupFloat[2]; };
ImGuiStyleMod(ImGuiStyleVar idx, int v) { VarIdx = idx; BackupInt[0] = v; }
ImGuiStyleMod(ImGuiStyleVar idx, float v) { VarIdx = idx; BackupFloat[0] = v; }
ImGuiStyleMod(ImGuiStyleVar idx, ImVec2 v) { VarIdx = idx; BackupFloat[0] = v.x; BackupFloat[1] = v.y; }
}; };
// Stacked data for BeginGroup()/EndGroup() // Stacked data for BeginGroup()/EndGroup()
@ -705,7 +710,7 @@ namespace ImGui
IMGUI_API void OpenPopupEx(const char* str_id, bool reopen_existing); IMGUI_API void OpenPopupEx(const char* str_id, bool reopen_existing);
// NB: All position are in absolute pixels coordinates (not window coordinates) // NB: All position are in absolute pixels coordinates (not window coordinates)
// FIXME: All those functions are a mess and needs to be refactored into something decent. Avoid use outside of imgui.cpp! // FIXME: All those functions are a mess and needs to be refactored into something decent. AVOID USING OUTSIDE OF IMGUI.CPP! NOT FOR PUBLIC CONSUMPTION.
// We need: a sort of symbol library, preferably baked into font atlas when possible + decent text rendering helpers. // We need: a sort of symbol library, preferably baked into font atlas when possible + decent text rendering helpers.
IMGUI_API void RenderText(ImVec2 pos, const char* text, const char* text_end = NULL, bool hide_text_after_hash = true); IMGUI_API void RenderText(ImVec2 pos, const char* text, const char* text_end = NULL, bool hide_text_after_hash = true);
IMGUI_API void RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end, float wrap_width); IMGUI_API void RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end, float wrap_width);