ImGuiStorage helper can store float + added functions to get pointer to data. Exposed ImGui::GetId() - may be misleading?

This commit is contained in:
omar 2014-12-08 17:14:54 +00:00
parent 0a0769227d
commit bdb2344db0
2 changed files with 83 additions and 32 deletions

View File

@ -924,46 +924,66 @@ static ImVector<ImGuiStorage::Pair>::iterator LowerBound(ImVector<ImGuiStorage::
return first; return first;
} }
int* ImGuiStorage::Find(ImU32 key) int ImGuiStorage::GetInt(ImU32 key, int default_val) const
{
ImVector<Pair>::iterator it = LowerBound(const_cast<ImVector<ImGuiStorage::Pair>&>(Data), key);
if (it == Data.end() || it->key != key)
return default_val;
return it->val_i;
}
float ImGuiStorage::GetFloat(ImU32 key, float default_val) const
{
ImVector<Pair>::iterator it = LowerBound(const_cast<ImVector<ImGuiStorage::Pair>&>(Data), key);
if (it == Data.end() || it->key != key)
return default_val;
return it->val_f;
}
int* ImGuiStorage::GetIntPtr(ImGuiID key, int default_val)
{ {
ImVector<Pair>::iterator it = LowerBound(Data, key); ImVector<Pair>::iterator it = LowerBound(Data, key);
if (it == Data.end()) if (it == Data.end() || it->key != key)
return NULL; it = Data.insert(it, Pair(key, default_val));
if (it->key != key) return &it->val_i;
return NULL;
return &it->val;
} }
int ImGuiStorage::GetInt(ImU32 key, int default_val) float* ImGuiStorage::GetFloatPtr(ImGuiID key, float default_val)
{ {
int* pval = Find(key); ImVector<Pair>::iterator it = LowerBound(Data, key);
if (!pval) if (it == Data.end() || it->key != key)
return default_val; it = Data.insert(it, Pair(key, default_val));
return *pval; return &it->val_f;
} }
// 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. // FIXME-OPT: Wasting CPU because all SetInt() are preceeded by GetInt() calls so we should have the result from lower_bound already in place.
// However we only use SetInt() on explicit user action (so that's maximum once a frame) so the optimisation isn't much needed. // However we only use SetInt() on explicit user action (so that's maximum once a frame) so the optimisation isn't much needed.
void ImGuiStorage::SetInt(ImU32 key, int val) void ImGuiStorage::SetInt(ImU32 key, int val)
{ {
ImVector<Pair>::iterator it = LowerBound(Data, key); ImVector<Pair>::iterator it = LowerBound(Data, key);
if (it != Data.end() && it->key == key) if (it == Data.end() || it->key != key)
{ {
it->val = val; Data.insert(it, Pair(key, val));
return;
} }
else it->val_i = val;
}
void ImGuiStorage::SetFloat(ImU32 key, float val)
{
ImVector<Pair>::iterator it = LowerBound(Data, key);
if (it == Data.end() || it->key != key)
{ {
Pair pair_key; Data.insert(it, Pair(key, val));
pair_key.key = key; return;
pair_key.val = val;
Data.insert(it, pair_key);
} }
it->val_f = val;
} }
void ImGuiStorage::SetAllInt(int v) void ImGuiStorage::SetAllInt(int v)
{ {
for (size_t i = 0; i < Data.size(); i++) for (size_t i = 0; i < Data.size(); i++)
Data[i].val = v; Data[i].val_i = v;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -3550,6 +3570,18 @@ void ImGui::PopID()
window->IDStack.pop_back(); window->IDStack.pop_back();
} }
ImGuiID ImGui::GetID(const char* str_id)
{
ImGuiWindow* window = GetCurrentWindow();
return window->GetID(str_id);
}
ImGuiID ImGui::GetID(const void* ptr_id)
{
ImGuiWindow* window = GetCurrentWindow();
return window->GetID(ptr_id);
}
// User can input math operators (e.g. +100) to edit a numerical values. // User can input math operators (e.g. +100) to edit a numerical values.
// NB: only call right after InputText because we are using its InitialValue storage // NB: only call right after InputText because we are using its InitialValue storage
static void ApplyNumericalTextInput(const char* buf, float *v) static void ApplyNumericalTextInput(const char* buf, float *v)

43
imgui.h
View File

@ -117,7 +117,7 @@ public:
inline void pop_back() { IM_ASSERT(Size > 0); Size--; } inline void pop_back() { IM_ASSERT(Size > 0); Size--; }
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; } 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; }
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++; } 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; }
}; };
#endif // #ifndef ImVector #endif // #ifndef ImVector
@ -204,10 +204,13 @@ namespace ImGui
IMGUI_API float GetTextLineHeight(); IMGUI_API float GetTextLineHeight();
// ID scopes // ID scopes
IMGUI_API void PushID(const char* str_id); // If you are creating repeated widgets in a loop you most likely want to push a unique identifier so ImGui can differentiate them.
IMGUI_API void PushID(const char* str_id); // push identifier into the ID stack. IDs are hash of the *entire* stack!
IMGUI_API void PushID(const void* ptr_id); IMGUI_API void PushID(const void* ptr_id);
IMGUI_API void PushID(const int int_id); IMGUI_API void PushID(const int int_id);
IMGUI_API void PopID(); IMGUI_API void PopID();
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.
IMGUI_API ImGuiID GetID(const void* ptr_id);
// Widgets // Widgets
IMGUI_API void Text(const char* fmt, ...); IMGUI_API void Text(const char* fmt, ...);
@ -587,22 +590,38 @@ struct ImGuiTextBuffer
}; };
// Helper: Key->value storage // Helper: Key->value storage
// - Store collapse state for a tree // - Store collapse state for a tree (Int 0/1)
// - Store color edit options, etc. // - Store color edit options (Int using values in ImGuiColorEditMode enum).
// - Custom user storage for temporary values.
// Typically you don't have to worry about this since a storage is held within each Window. // Typically you don't have to worry about this since a storage is held within each Window.
// Declare your own storage if you want to manipulate the open/close state of a particular sub-tree in your interface. // Declare your own storage if:
// - 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).
// - You want to store custom debug data easily without adding or editing structures in your code.
struct ImGuiStorage struct ImGuiStorage
{ {
struct Pair { ImU32 key; int val; }; struct Pair
{
ImGuiID key;
union { int val_i; float val_f; };
Pair(ImGuiID _key, int _val_i) { key = _key; val_i = _val_i; }
Pair(ImGuiID _key, float _val_f) { key = _key; val_f = _val_f; }
};
ImVector<Pair> Data; ImVector<Pair> Data;
// - Get***() functions find pair, never add/allocate. Pairs are sorted so a query is O(log N)
// - Set***() functions find pair, insertion on demand if missing.
// - Get***Ptr() functions find pair, insertion on demand if missing, return pointer. Useful if you intend to do Get+Set.
// A typical use case where this is very convenient:
// ImGui::SliderInt("tmp adjustment", GetIntPtr(key), 0, 100); some_var += *GetIntPtr(key);
// - Sorted insertion is costly but should amortize. A typical frame shouldn't need to insert any new pair.
IMGUI_API void Clear(); IMGUI_API void Clear();
IMGUI_API int GetInt(ImU32 key, int default_val = 0); IMGUI_API int GetInt(ImGuiID key, int default_val = 0) const;
IMGUI_API void SetInt(ImU32 key, int val); IMGUI_API void SetInt(ImGuiID key, int val);
IMGUI_API void SetAllInt(int val); IMGUI_API int* GetIntPtr(ImGuiID key, int default_val = 0);
IMGUI_API float GetFloat(ImGuiID key, float default_val = 0.0f) const;
IMGUI_API int* Find(ImU32 key); IMGUI_API void SetFloat(ImGuiID key, float val);
IMGUI_API void Insert(ImU32 key, int val); IMGUI_API float* GetFloatPtr(ImGuiID key, float default_val = 0);
IMGUI_API void SetAllInt(int val); // Use on your own storage if you know only integer are being stored.
}; };
// Shared state of InputText(), passed to callback when a ImGuiInputTextFlags_Callback* flag is used. // Shared state of InputText(), passed to callback when a ImGuiInputTextFlags_Callback* flag is used.