From 19b6489476629e22a5f723ba01477bb258fbd561 Mon Sep 17 00:00:00 2001 From: maelstrom Date: Fri, 30 May 2025 02:15:44 +0200 Subject: [PATCH] feat(model): added model container object for parts --- assets/icons/model.png | Bin 0 -> 825 bytes core/src/objects/meta.cpp | 4 +++- core/src/objects/model.cpp | 4 ++++ core/src/objects/model.h | 18 +++++++++++++++++ editor/mainwindow.cpp | 40 +++++++++++++++++++++++++++++++++++++ editor/mainwindow.ui | 36 +++++++++++++++++++++++++++++++++ 6 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 assets/icons/model.png create mode 100644 core/src/objects/model.cpp create mode 100644 core/src/objects/model.h diff --git a/assets/icons/model.png b/assets/icons/model.png new file mode 100644 index 0000000000000000000000000000000000000000..0905f933b87ab32f21098d7db8d603209730c753 GIT binary patch literal 825 zcmV-91IGM`P)wd|HNMlZ|>D)M67h? zOIjz3DJbk0=97q(mSBd~-ilc0Oupt^z$#N6O&at_s8u-PL@9M^gQuq(+UH^IB$&*DHP!HzH+vkEzC?S52tN1$mKhziPkOR=y$ zhl#aO1Xly_M?EkN>tM6E5T&Ht4dh{0oQr6Q1b3J=sM^ACOsvD=TSP81#0oTC1v|Df zgpp-GhL(KrE_8t&(jeFR1W%(osQ12tvSpHp_}~HR_8G{VUO;FILQv(P-b)es=)ZlJM#c>{Wx-rgY3D#Ol9rJl39A<60Xo5cneo(9g5a4q>ayzV-7%Ue2}0_ z&TIets{Cl`n(nefrZ+9F8|N&Kp}^StU2b+&pVj;XvgEdBL3Wlp00000NkvXXu0mjf DwZ3{L literal 0 HcmV?d00001 diff --git a/core/src/objects/meta.cpp b/core/src/objects/meta.cpp index 5bdbd1c..613ead5 100644 --- a/core/src/objects/meta.cpp +++ b/core/src/objects/meta.cpp @@ -5,6 +5,7 @@ #include "objects/joint/rotatev.h" #include "objects/joint/weld.h" #include "objects/jointsservice.h" +#include "objects/model.h" #include "objects/part.h" #include "objects/joint/snap.h" #include "objects/script.h" @@ -24,7 +25,8 @@ std::map INSTANCE_MAP = { { "RotateV", &RotateV::TYPE }, { "JointInstance", &JointInstance::TYPE }, { "Script", &Script::TYPE }, - { "Folder", &Folder::TYPE }, + { "Model", &Model::TYPE }, + // { "Folder", &Folder::TYPE }, // Services diff --git a/core/src/objects/model.cpp b/core/src/objects/model.cpp new file mode 100644 index 0000000..1354ad6 --- /dev/null +++ b/core/src/objects/model.cpp @@ -0,0 +1,4 @@ +#include "model.h" + +Model::Model(): Instance(&TYPE) {} +Model::~Model() = default; \ No newline at end of file diff --git a/core/src/objects/model.h b/core/src/objects/model.h new file mode 100644 index 0000000..4e9381c --- /dev/null +++ b/core/src/objects/model.h @@ -0,0 +1,18 @@ +#pragma once + +#include "objects/annotation.h" +#include "objects/base/instance.h" +#include + +// Group object for Parts + +class DEF_INST_(explorer_icon="model") Model : public Instance { + AUTOGEN_PREAMBLE + +public: + Model(); + ~Model(); + + static inline std::shared_ptr New() { return std::make_shared(); }; + static inline std::shared_ptr Create() { return std::make_shared(); }; +}; \ No newline at end of file diff --git a/editor/mainwindow.cpp b/editor/mainwindow.cpp index 7d2c3c8..33514de 100644 --- a/editor/mainwindow.cpp +++ b/editor/mainwindow.cpp @@ -3,6 +3,7 @@ #include "common.h" #include "logger.h" #include "objects/datamodel.h" +#include "objects/model.h" #include "placedocument.h" #include "script/scriptdocument.h" #include @@ -19,6 +20,7 @@ #include #include #include +#include #ifdef _NDEBUG #define NDEBUG @@ -364,6 +366,44 @@ void MainWindow::connectActionHandlers() { } }); + connect(ui->actionGroupObjects, &QAction::triggered, this, [&]() { + auto model = Model::New(); + std::shared_ptr firstParent; + + for (auto object : getSelection()) { + if (firstParent == nullptr && object->GetParent().has_value()) firstParent = object->GetParent().value(); + object->SetParent(model); + } + + if (model->GetChildren().size() == 0) + return; + + // Technically not how it works in the actual studio, but it's not an API-breaking change + // and I think this implementation is more useful so I'm sticking with it + if (firstParent == nullptr) firstParent = gWorkspace(); + model->SetParent(firstParent); + + setSelection({ model }); + }); + + connect(ui->actionUngroupObjects, &QAction::triggered, this, [&]() { + std::vector> newSelection; + + for (auto model : getSelection()) { + // Not a model, skip + if (!model->IsA()) { newSelection.push_back(model); continue; } + + for (auto object : model->GetChildren()) { + object->SetParent(model->GetParent()); + newSelection.push_back(object); + } + + model->Destroy(); + } + + setSelection(newSelection); + }); + connect(ui->actionSaveModel, &QAction::triggered, this, [&]() { std::optional path = openFileDialog("Openblocks Model (*.obm)", ".obm", QFileDialog::AcceptSave); if (!path) return; diff --git a/editor/mainwindow.ui b/editor/mainwindow.ui index ee3ea39..ecfa3ba 100644 --- a/editor/mainwindow.ui +++ b/editor/mainwindow.ui @@ -176,6 +176,8 @@ + + @@ -768,6 +770,40 @@ QAction::MenuRole::NoRole + + + + + + Group Objects + + + Group objects under a Model + + + Ctrl+G + + + QAction::MenuRole::NoRole + + + + + + + + Ungroup Objects + + + Ungroup objects inside selected Model + + + Ctrl+U + + + QAction::MenuRole::NoRole + +