Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 21 additions & 17 deletions src/dearpygui_commands.h
Original file line number Diff line number Diff line change
Expand Up @@ -2519,8 +2519,9 @@ setup_dearpygui(PyObject* self, PyObject* args, PyObject* kwargs)
return nullptr;
}

while (!GContext->itemRegistry->containers.empty())
GContext->itemRegistry->containers.pop();
// Clear the containers stack. Unfortunately std::stack doesn't have a clear() call,
// but assigning a new empty stack does just the same.
mvItemRegistry::threadContext.containers = {};
GContext->started = true;
GContext->running = true;
GContext->future = std::async(std::launch::async, []() {return mvRunCallbacks(); });
Expand Down Expand Up @@ -2924,18 +2925,19 @@ pop_container_stack(PyObject* self, PyObject* args, PyObject* kwargs)

mvPySafeLockGuard lk(GContext->mutex);

if (GContext->itemRegistry->containers.empty())
auto& containers = mvItemRegistry::threadContext.containers;
if (containers.empty())
{
mvThrowPythonError(mvErrorCode::mvContainerStackEmpty, "No container to pop.");
assert(false);
return nullptr;
}

mvAppItem* item = GContext->itemRegistry->containers.top();
GContext->itemRegistry->containers.pop();
mvAppItem* item = containers.top();
containers.pop();

if (item)
return ToPyUUID(item->uuid);
return ToPyUUID(item);
else
return GetPyNone();

Expand All @@ -2945,8 +2947,9 @@ static PyObject*
empty_container_stack(PyObject* self, PyObject* args, PyObject* kwargs)
{
mvPySafeLockGuard lk(GContext->mutex);
while (!GContext->itemRegistry->containers.empty())
GContext->itemRegistry->containers.pop();
// Clear the containers stack. Unfortunately std::stack doesn't have a clear() call,
// but assigning a new empty stack does just the same.
mvItemRegistry::threadContext.containers = {};
return GetPyNone();
}

Expand All @@ -2956,11 +2959,12 @@ top_container_stack(PyObject* self, PyObject* args, PyObject* kwargs)
mvPySafeLockGuard lk(GContext->mutex);

mvAppItem* item = nullptr;
if (!GContext->itemRegistry->containers.empty())
item = GContext->itemRegistry->containers.top();
auto& containers = mvItemRegistry::threadContext.containers;
if (!containers.empty())
item = containers.top();

if (item)
return ToPyUUID(item->uuid);
return ToPyUUID(item);
else
return GetPyNone();
}
Expand All @@ -2970,23 +2974,23 @@ last_item(PyObject* self, PyObject* args, PyObject* kwargs)
{
mvPySafeLockGuard lk(GContext->mutex);

return ToPyUUID(GContext->itemRegistry->lastItemAdded);
return ToPyUUID(mvItemRegistry::threadContext.lastItemAdded);
}

static PyObject*
last_container(PyObject* self, PyObject* args, PyObject* kwargs)
{
mvPySafeLockGuard lk(GContext->mutex);

return ToPyUUID(GContext->itemRegistry->lastContainerAdded);
return ToPyUUID(mvItemRegistry::threadContext.lastContainerAdded);
}

static PyObject*
last_root(PyObject* self, PyObject* args, PyObject* kwargs)
{
mvPySafeLockGuard lk(GContext->mutex);

return ToPyUUID(GContext->itemRegistry->lastRootAdded);
return ToPyUUID(mvItemRegistry::threadContext.lastRootAdded);
}

static PyObject*
Expand All @@ -3006,7 +3010,7 @@ push_container_stack(PyObject* self, PyObject* args, PyObject* kwargs)
{
if (DearPyGui::GetEntityDesciptionFlags(parent->type) & MV_ITEM_DESC_CONTAINER)
{
GContext->itemRegistry->containers.push(parent);
mvItemRegistry::threadContext.containers.push(parent);
return ToPyBool(true);
}
}
Expand Down Expand Up @@ -4164,8 +4168,8 @@ capture_next_item(PyObject* self, PyObject* args, PyObject* kwargs)

mvPySafeLockGuard lk(GContext->mutex);

GContext->itemRegistry->captureCallback = mvPyObject(callable == Py_None? nullptr : callable, true);
GContext->itemRegistry->captureCallbackUserData = mvPyObject(user_data, true);
mvItemRegistry::threadContext.captureCallback = mvPyObject(callable == Py_None? nullptr : callable, true);
mvItemRegistry::threadContext.captureCallbackUserData = mvPyObject(user_data, true);

return GetPyNone();
}
Expand Down
2 changes: 1 addition & 1 deletion src/mvContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ struct mvContext
double time = 0.0; // total time since starting
int frame = 0; // frame count
int framerate = 0; // frame rate
mvUUID id = MV_START_UUID; // current ID
std::atomic<mvUUID> id = MV_START_UUID; // current ID
mvViewport* viewport = nullptr;
mvGraphics graphics;
bool resetTheme = false;
Expand Down
50 changes: 26 additions & 24 deletions src/mvItemRegistry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@

#include "mvProfiler.h"

thread_local mvThreadContext mvItemRegistry::threadContext;

mvItemRegistry::mvItemRegistry()
{
// We seldom need to do a GetItem(0), and an explicit check for uuid == 0 in GetItem
Expand All @@ -36,17 +38,12 @@ DebugItem(const char* label, const char* item) {
ImGui::TextColored(ImVec4(1.0f, 0.0f, 1.0f, 1.0f), "%s", item);
}

static void
PushParent(mvItemRegistry& registry, mvAppItem* item)
{
registry.containers.push(item);
}

static mvAppItem*
TopParent(mvItemRegistry& registry)
{
if (!registry.containers.empty())
return registry.containers.top();
auto& containers = mvItemRegistry::threadContext.containers;
if (!containers.empty())
return containers.top();
return nullptr;
}

Expand Down Expand Up @@ -328,9 +325,10 @@ DeleteItem(mvItemRegistry& registry, mvUUID uuid, b8 childrenOnly, i32 slot)
}

// See if it is the captured item
if (registry.capturedItem && registry.capturedItem.get() == item)
auto& capturedItem = mvItemRegistry::threadContext.capturedItem;
if (capturedItem && capturedItem.get() == item)
{
registry.capturedItem = nullptr;
capturedItem = nullptr;
return true;
}

Expand All @@ -352,10 +350,11 @@ MoveItem(mvItemRegistry& registry, mvUUID uuid, mvUUID parent, mvUUID before)

std::shared_ptr<mvAppItem> child = nullptr;

if (registry.capturedItem && registry.capturedItem->uuid == uuid)
auto& capturedItem = mvItemRegistry::threadContext.capturedItem;
if (capturedItem && capturedItem->uuid == uuid)
{
child = registry.capturedItem;
registry.capturedItem = nullptr;
child = capturedItem;
capturedItem = nullptr;
}
else
{
Expand Down Expand Up @@ -652,8 +651,9 @@ mvAppItem*
GetItem(mvItemRegistry& registry, mvUUID uuid)
{
// check captured
if (registry.capturedItem && registry.capturedItem->uuid == uuid)
return registry.capturedItem.get();
auto& capturedItem = mvItemRegistry::threadContext.capturedItem;
if (capturedItem && capturedItem->uuid == uuid)
return capturedItem.get();

auto found = registry.allItems.find(uuid);
return found != registry.allItems.end()? found->second : nullptr;
Expand Down Expand Up @@ -706,16 +706,18 @@ b8
AddItemWithRuntimeChecks(mvItemRegistry& registry, std::shared_ptr<mvAppItem> item, mvUUID parent, mvUUID before)
{

if(registry.captureCallback)
auto& threadContext = mvItemRegistry::threadContext;

if (threadContext.captureCallback)
{

// this is a unique situation in that the caller always has the GIL
registry.capturedItem = item;
threadContext.capturedItem = item;
// resetting captureCallback in advance in order to avoid recursion (if the callback
// attempts to add another item or move an item)
mvPyObject captureCallback(std::move(registry.captureCallback));
registry.captureCallback = nullptr;
mvRunCallback(captureCallback, nullptr, registry.capturedItem->uuid);
mvPyObject captureCallback(std::move(threadContext.captureCallback));
threadContext.captureCallback = nullptr;
mvRunCallback(captureCallback, nullptr, threadContext.capturedItem->uuid);
return true;
}

Expand All @@ -733,13 +735,13 @@ AddItemWithRuntimeChecks(mvItemRegistry& registry, std::shared_ptr<mvAppItem> it
//---------------------------------------------------------------------------
if (DearPyGui::GetEntityDesciptionFlags(item->type) & MV_ITEM_DESC_ROOT)
{
registry.lastRootAdded = item->uuid;
registry.lastContainerAdded = item->uuid;
threadContext.lastRootAdded = item->uuid;
threadContext.lastContainerAdded = item->uuid;
}
else if (DearPyGui::GetEntityDesciptionFlags(item->type) & MV_ITEM_DESC_CONTAINER)
registry.lastContainerAdded = item->uuid;
threadContext.lastContainerAdded = item->uuid;

registry.lastItemAdded = item->uuid;
threadContext.lastItemAdded = item->uuid;

//---------------------------------------------------------------------------
// STEP 1: check if an item with this name exists (NO LONGER NEEDED)
Expand Down
34 changes: 24 additions & 10 deletions src/mvItemRegistry.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,25 @@ b8 AddItemWithRuntimeChecks(mvItemRegistry& registry, std::shared_
void ResetTheme (mvItemRegistry& registry);
b8 ReorderChildren (mvItemRegistry& registry, mvUUID parent, i32 slot, const std::vector<mvUUID>& new_order);

//-----------------------------------------------------------------------------
// mvThreadContext
// - Holds thread-local data used together with mvItemRegistry
//-----------------------------------------------------------------------------

struct mvThreadContext
{
// "last item" state
mvUUID lastItemAdded = 0;
mvUUID lastContainerAdded = 0;
mvUUID lastRootAdded = 0;

std::stack<mvAppItem*> containers; // parent stack, top of stack becomes widget's parent

std::shared_ptr<mvAppItem> capturedItem = nullptr;
mvPyObject captureCallback = nullptr;
mvPyObject captureCallbackUserData = nullptr;
};

//-----------------------------------------------------------------------------
// mvItemRegistry
// - Responsibilities:
Expand All @@ -61,21 +80,16 @@ b8 ReorderChildren (mvItemRegistry& registry, mvUUID paren
struct mvItemRegistry
{

// "last item" state
mvUUID lastItemAdded = 0;
mvUUID lastContainerAdded = 0;
mvUUID lastRootAdded = 0;

// misc
std::stack<mvAppItem*> containers; // parent stack, top of stack becomes widget's parent
std::unordered_map<std::string, mvUUID> aliases;
std::unordered_map<mvUUID, mvAppItem*> allItems; // used for quick access to items by UUID

static thread_local mvThreadContext threadContext;

// debug items
b8 showImGuiDebug = false;
b8 showImPlotDebug = false;
std::vector<std::shared_ptr<mvAppItem>> debugWindows;
std::shared_ptr<mvAppItem> capturedItem = nullptr;
mvPyObject captureCallback = nullptr;
mvPyObject captureCallbackUserData = nullptr;
std::vector<std::shared_ptr<mvAppItem>> debugWindows;

// roots
std::vector<std::shared_ptr<mvAppItem>> colormapRoots;
Expand Down
Loading