From fc063ad39f5254aa5566dd02312974e91d82cbbb Mon Sep 17 00:00:00 2001 From: maelstrom Date: Sat, 18 Jan 2025 16:27:43 +0100 Subject: [PATCH] fix: Hierarchy now updates properly --- editor/explorermodel.cpp | 35 +++++++++++++++++++++++++++++++++++ editor/explorermodel.h | 1 + editor/mainwindow.cpp | 2 ++ src/common.cpp | 4 +++- src/common.h | 11 ++++++++++- src/objects/base/instance.cpp | 5 +++++ 6 files changed, 56 insertions(+), 2 deletions(-) diff --git a/editor/explorermodel.cpp b/editor/explorermodel.cpp index 763017b..d39742b 100644 --- a/editor/explorermodel.cpp +++ b/editor/explorermodel.cpp @@ -3,12 +3,35 @@ #include "qcontainerfwd.h" #include "qobject.h" #include "qwidget.h" +#include "common.h" +#include +#include // https://doc.qt.io/qt-6/qtwidgets-itemviews-simpletreemodel-example.html#testing-the-model ExplorerModel::ExplorerModel(InstanceRef dataRoot, QWidget *parent) : QAbstractItemModel(parent) , rootItem(dataRoot) { + // TODO: Don't use lambdas and handlers like that + hierarchyPreUpdateHandler = [&](InstanceRef object, std::optional oldParent, std::optional newParent) { + if (oldParent.has_value()) { + auto children = oldParent.value()->GetChildren(); + size_t idx = std::find(children.begin(), children.end(), object) - children.end(); + beginRemoveRows(toIndex(oldParent.value()), idx, idx); + } + + if (newParent.has_value()) { + size_t size = newParent.value()->GetChildren().size(); + beginInsertRows(toIndex(newParent.value()), size, size); + } else { + // TODO: + } + }; + + hierarchyPostUpdateHandler = [&](InstanceRef object, std::optional oldParent, std::optional newParent) { + if (newParent.has_value()) endInsertRows(); + if (oldParent.has_value()) endRemoveRows(); + }; } ExplorerModel::~ExplorerModel() = default; @@ -26,6 +49,18 @@ QModelIndex ExplorerModel::index(int row, int column, const QModelIndex &parent) return {}; } +QModelIndex ExplorerModel::toIndex(InstanceRef item) { + if (item == rootItem) + return {}; + + InstanceRef parentItem = item->GetParent().value(); + // Check above ensures this item is not root, so value() must be valid + for (int i = 0; i < parentItem->GetChildren().size(); i++) + if (parentItem->GetChildren()[i] == item) + return createIndex(i, 0, item.get()); + return QModelIndex{}; +} + QModelIndex ExplorerModel::parent(const QModelIndex &index) const { if (!index.isValid()) return {}; diff --git a/editor/explorermodel.h b/editor/explorermodel.h index c7a43be..80cc004 100644 --- a/editor/explorermodel.h +++ b/editor/explorermodel.h @@ -29,6 +29,7 @@ public: private: InstanceRef rootItem; + QModelIndex toIndex(InstanceRef item); }; #endif // EXPLORERMODEL_H diff --git a/editor/mainwindow.cpp b/editor/mainwindow.cpp index d93b79e..aff9e84 100644 --- a/editor/mainwindow.cpp +++ b/editor/mainwindow.cpp @@ -8,6 +8,8 @@ #include #include #include +#include +#include #include #include "common.h" diff --git a/src/common.cpp b/src/common.cpp index a0f8d13..cd35566 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -5,4 +5,6 @@ Camera camera(glm::vec3(0.0, 0.0, 3.0)); //std::vector parts; -std::shared_ptr workspace = Workspace::New(); \ No newline at end of file +std::shared_ptr workspace = Workspace::New(); +std::optional hierarchyPreUpdateHandler; +std::optional hierarchyPostUpdateHandler; \ No newline at end of file diff --git a/src/common.h b/src/common.h index efd0d50..ef3886f 100644 --- a/src/common.h +++ b/src/common.h @@ -1,8 +1,17 @@ #pragma once #include "objects/workspace.h" #include "camera.h" +#include +#include + +class Instance; +// typedef std::function element, std::optional> newParent)> HierarchyUpdateHandler; +typedef std::function oldParent, std::optional newParent)> HierarchyPreUpdateHandler; +typedef std::function oldParent, std::optional newParent)> HierarchyPostUpdateHandler; // TEMPORARY COMMON DATA FOR DIFFERENT INTERNAL COMPONENTS extern Camera camera; -extern std::shared_ptr workspace; \ No newline at end of file +extern std::shared_ptr workspace; +extern std::optional hierarchyPreUpdateHandler; +extern std::optional hierarchyPostUpdateHandler; \ No newline at end of file diff --git a/src/objects/base/instance.cpp b/src/objects/base/instance.cpp index 1fdc358..e9c84f5 100644 --- a/src/objects/base/instance.cpp +++ b/src/objects/base/instance.cpp @@ -1,4 +1,5 @@ #include "instance.h" +#include "../../common.h" #include #include #include @@ -25,6 +26,8 @@ Instance::~Instance () { } void Instance::SetParent(std::optional> newParent) { + auto lastParent = GetParent(); + if (hierarchyPreUpdateHandler.has_value()) hierarchyPreUpdateHandler.value()(this->shared_from_this(), lastParent, newParent); // If we currently have a parent, remove ourselves from it before adding ourselves to the new one if (this->parent.has_value() && !this->parent.value().expired()) { auto oldParent = this->parent.value().lock(); @@ -36,6 +39,8 @@ void Instance::SetParent(std::optional> newParent) { } this->parent = newParent; // TODO: Add code for sending signals for parent updates + // TODO: Yeahhh maybe this isn't the best way of doing this? + if (hierarchyPostUpdateHandler.has_value()) hierarchyPostUpdateHandler.value()(this->shared_from_this(), lastParent, newParent); } std::optional> Instance::GetParent() {