Skip to content

Commit bdb2344

Browse files
committed
ImGuiStorage helper can store float + added functions to get pointer to data. Exposed ImGui::GetId() - may be misleading?
1 parent 0a07692 commit bdb2344

File tree

2 files changed

+83
-32
lines changed

2 files changed

+83
-32
lines changed

imgui.cpp

Lines changed: 52 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -924,46 +924,66 @@ static ImVector<ImGuiStorage::Pair>::iterator LowerBound(ImVector<ImGuiStorage::
924924
return first;
925925
}
926926

927-
int* ImGuiStorage::Find(ImU32 key)
927+
int ImGuiStorage::GetInt(ImU32 key, int default_val) const
928928
{
929-
ImVector<Pair>::iterator it = LowerBound(Data, key);
930-
if (it == Data.end())
931-
return NULL;
932-
if (it->key != key)
933-
return NULL;
934-
return &it->val;
929+
ImVector<Pair>::iterator it = LowerBound(const_cast<ImVector<ImGuiStorage::Pair>&>(Data), key);
930+
if (it == Data.end() || it->key != key)
931+
return default_val;
932+
return it->val_i;
935933
}
936934

937-
int ImGuiStorage::GetInt(ImU32 key, int default_val)
935+
float ImGuiStorage::GetFloat(ImU32 key, float default_val) const
938936
{
939-
int* pval = Find(key);
940-
if (!pval)
937+
ImVector<Pair>::iterator it = LowerBound(const_cast<ImVector<ImGuiStorage::Pair>&>(Data), key);
938+
if (it == Data.end() || it->key != key)
941939
return default_val;
942-
return *pval;
940+
return it->val_f;
941+
}
942+
943+
int* ImGuiStorage::GetIntPtr(ImGuiID key, int default_val)
944+
{
945+
ImVector<Pair>::iterator it = LowerBound(Data, key);
946+
if (it == Data.end() || it->key != key)
947+
it = Data.insert(it, Pair(key, default_val));
948+
return &it->val_i;
943949
}
944950

945-
// FIXME-OPT: We are wasting time because all SetInt() are preceeded by GetInt() calls so we should have the result from lower_bound already in place.
951+
float* ImGuiStorage::GetFloatPtr(ImGuiID key, float default_val)
952+
{
953+
ImVector<Pair>::iterator it = LowerBound(Data, key);
954+
if (it == Data.end() || it->key != key)
955+
it = Data.insert(it, Pair(key, default_val));
956+
return &it->val_f;
957+
}
958+
959+
// FIXME-OPT: Wasting CPU because all SetInt() are preceeded by GetInt() calls so we should have the result from lower_bound already in place.
946960
// However we only use SetInt() on explicit user action (so that's maximum once a frame) so the optimisation isn't much needed.
947961
void ImGuiStorage::SetInt(ImU32 key, int val)
948962
{
949963
ImVector<Pair>::iterator it = LowerBound(Data, key);
950-
if (it != Data.end() && it->key == key)
964+
if (it == Data.end() || it->key != key)
951965
{
952-
it->val = val;
966+
Data.insert(it, Pair(key, val));
967+
return;
953968
}
954-
else
969+
it->val_i = val;
970+
}
971+
972+
void ImGuiStorage::SetFloat(ImU32 key, float val)
973+
{
974+
ImVector<Pair>::iterator it = LowerBound(Data, key);
975+
if (it == Data.end() || it->key != key)
955976
{
956-
Pair pair_key;
957-
pair_key.key = key;
958-
pair_key.val = val;
959-
Data.insert(it, pair_key);
977+
Data.insert(it, Pair(key, val));
978+
return;
960979
}
980+
it->val_f = val;
961981
}
962982

963983
void ImGuiStorage::SetAllInt(int v)
964984
{
965985
for (size_t i = 0; i < Data.size(); i++)
966-
Data[i].val = v;
986+
Data[i].val_i = v;
967987
}
968988

969989
//-----------------------------------------------------------------------------
@@ -3550,6 +3570,18 @@ void ImGui::PopID()
35503570
window->IDStack.pop_back();
35513571
}
35523572

3573+
ImGuiID ImGui::GetID(const char* str_id)
3574+
{
3575+
ImGuiWindow* window = GetCurrentWindow();
3576+
return window->GetID(str_id);
3577+
}
3578+
3579+
ImGuiID ImGui::GetID(const void* ptr_id)
3580+
{
3581+
ImGuiWindow* window = GetCurrentWindow();
3582+
return window->GetID(ptr_id);
3583+
}
3584+
35533585
// User can input math operators (e.g. +100) to edit a numerical values.
35543586
// NB: only call right after InputText because we are using its InitialValue storage
35553587
static void ApplyNumericalTextInput(const char* buf, float *v)

imgui.h

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ class ImVector
117117
inline void pop_back() { IM_ASSERT(Size > 0); Size--; }
118118

119119
inline iterator erase(const_iterator it) { IM_ASSERT(it >= begin() && it < end()); const ptrdiff_t off = it - begin(); memmove(Data + off, Data + off + 1, (Size - (size_t)off - 1) * sizeof(value_type)); Size--; return Data + off; }
120-
inline void insert(const_iterator it, const value_type& v) { IM_ASSERT(it >= begin() && it <= end()); const ptrdiff_t off = it - begin(); if (Size == Capacity) reserve(Capacity ? Capacity * 2 : 4); if (off < (int)Size) memmove(Data + off + 1, Data + off, (Size - (size_t)off) * sizeof(value_type)); Data[off] = v; Size++; }
120+
inline iterator insert(const_iterator it, const value_type& v) { IM_ASSERT(it >= begin() && it <= end()); const ptrdiff_t off = it - begin(); if (Size == Capacity) reserve(Capacity ? Capacity * 2 : 4); if (off < (int)Size) memmove(Data + off + 1, Data + off, (Size - (size_t)off) * sizeof(value_type)); Data[off] = v; Size++; return Data + off; }
121121
};
122122
#endif // #ifndef ImVector
123123

@@ -204,10 +204,13 @@ namespace ImGui
204204
IMGUI_API float GetTextLineHeight();
205205

206206
// ID scopes
207-
IMGUI_API void PushID(const char* str_id);
207+
// If you are creating repeated widgets in a loop you most likely want to push a unique identifier so ImGui can differentiate them.
208+
IMGUI_API void PushID(const char* str_id); // push identifier into the ID stack. IDs are hash of the *entire* stack!
208209
IMGUI_API void PushID(const void* ptr_id);
209210
IMGUI_API void PushID(const int int_id);
210211
IMGUI_API void PopID();
212+
IMGUI_API ImGuiID GetID(const char* str_id); // calculate unique ID (hash of whole ID stack + given parameter). useful if you want to query into ImGuiStorage yourself. otherwise rarely needed.
213+
IMGUI_API ImGuiID GetID(const void* ptr_id);
211214

212215
// Widgets
213216
IMGUI_API void Text(const char* fmt, ...);
@@ -587,22 +590,38 @@ struct ImGuiTextBuffer
587590
};
588591

589592
// Helper: Key->value storage
590-
// - Store collapse state for a tree
591-
// - Store color edit options, etc.
593+
// - Store collapse state for a tree (Int 0/1)
594+
// - Store color edit options (Int using values in ImGuiColorEditMode enum).
595+
// - Custom user storage for temporary values.
592596
// Typically you don't have to worry about this since a storage is held within each Window.
593-
// Declare your own storage if you want to manipulate the open/close state of a particular sub-tree in your interface.
597+
// Declare your own storage if:
598+
// - You want to manipulate the open/close state of a particular sub-tree in your interface (tree node uses Int 0/1 to store their state).
599+
// - You want to store custom debug data easily without adding or editing structures in your code.
594600
struct ImGuiStorage
595601
{
596-
struct Pair { ImU32 key; int val; };
602+
struct Pair
603+
{
604+
ImGuiID key;
605+
union { int val_i; float val_f; };
606+
Pair(ImGuiID _key, int _val_i) { key = _key; val_i = _val_i; }
607+
Pair(ImGuiID _key, float _val_f) { key = _key; val_f = _val_f; }
608+
};
597609
ImVector<Pair> Data;
598610

611+
// - Get***() functions find pair, never add/allocate. Pairs are sorted so a query is O(log N)
612+
// - Set***() functions find pair, insertion on demand if missing.
613+
// - Get***Ptr() functions find pair, insertion on demand if missing, return pointer. Useful if you intend to do Get+Set.
614+
// A typical use case where this is very convenient:
615+
// ImGui::SliderInt("tmp adjustment", GetIntPtr(key), 0, 100); some_var += *GetIntPtr(key);
616+
// - Sorted insertion is costly but should amortize. A typical frame shouldn't need to insert any new pair.
599617
IMGUI_API void Clear();
600-
IMGUI_API int GetInt(ImU32 key, int default_val = 0);
601-
IMGUI_API void SetInt(ImU32 key, int val);
602-
IMGUI_API void SetAllInt(int val);
603-
604-
IMGUI_API int* Find(ImU32 key);
605-
IMGUI_API void Insert(ImU32 key, int val);
618+
IMGUI_API int GetInt(ImGuiID key, int default_val = 0) const;
619+
IMGUI_API void SetInt(ImGuiID key, int val);
620+
IMGUI_API int* GetIntPtr(ImGuiID key, int default_val = 0);
621+
IMGUI_API float GetFloat(ImGuiID key, float default_val = 0.0f) const;
622+
IMGUI_API void SetFloat(ImGuiID key, float val);
623+
IMGUI_API float* GetFloatPtr(ImGuiID key, float default_val = 0);
624+
IMGUI_API void SetAllInt(int val); // Use on your own storage if you know only integer are being stored.
606625
};
607626

608627
// Shared state of InputText(), passed to callback when a ImGuiInputTextFlags_Callback* flag is used.

0 commit comments

Comments
 (0)