Assembly: Explode temporarily (#25456)

This commit is contained in:
PaddleStroke
2026-01-31 15:57:22 +01:00
committed by GitHub
parent cd8fd9ace5
commit 964e7387e3
4 changed files with 96 additions and 0 deletions

View File

@@ -126,6 +126,12 @@ class ExplodedView:
return positions
def explodeTemporarily(self, viewObj):
self.initialPlcs = UtilsAssembly.saveAssemblyPartsPlacements(self.getAssembly(viewObj))
self.applyMoves(viewObj)
for move in viewObj.Group:
move.Visibility = True
def getAssembly(self, viewObj):
for obj in viewObj.InList:
if obj.isDerivedFrom("Assembly::AssemblyObject"):
@@ -162,6 +168,9 @@ class ExplodedView:
UtilsAssembly.restoreAssemblyPartsPlacements(self.getAssembly(viewObj), self.initialPlcs)
for move in viewObj.Group:
move.Visibility = False
def _calculateExplodedPlacements(self, viewObj):
"""
Internal helper to calculate final placements for an exploded view without
@@ -464,6 +473,7 @@ class ExplodedViewStep:
if move.ViewObject:
endPos = UtilsAssembly.getCenterOfBoundingBox([obj], [ref])
positions.append([startPos, endPos])
obj.purgeTouched()
if move.ViewObject:
move.ViewObject.Proxy.redrawLines(move, positions)
@@ -647,6 +657,8 @@ class TaskAssemblyCreateView(QtCore.QObject):
self.currentStep = None
self.radialExplosion = False
self.viewObj.purgeTouched()
def accept(self):
self.deactivate()
UtilsAssembly.restoreAssemblyPartsPlacements(self.assembly, self.initialPlcs)
@@ -658,6 +670,8 @@ class TaskAssemblyCreateView(QtCore.QObject):
commands = commands + more
Gui.doCommand(commands[:-1]) # Don't use the last \n
App.closeActiveTransaction()
self.viewObj.purgeTouched()
return True
def reject(self):

View File

@@ -1226,11 +1226,19 @@ void ViewProviderAssembly::onSelectionChanged(const Gui::SelectionChanges& msg)
isolateJointReferences(obj);
return;
}
else if (explodeTemporarily(obj)) {
return;
}
}
else {
clearIsolate();
clearTemporaryExplosion();
}
}
if (msg.Type == Gui::SelectionChanges::ClrSelection
|| msg.Type == Gui::SelectionChanges::RmvSelection) {
clearIsolate();
clearTemporaryExplosion();
}
if (!isInEditMode()) {
@@ -1609,6 +1617,76 @@ void ViewProviderAssembly::slotAboutToOpenTransaction(const std::string& cmdName
{
Q_UNUSED(cmdName);
this->clearIsolate();
this->clearTemporaryExplosion();
}
bool ViewProviderAssembly::explodeTemporarily(App::DocumentObject* explodedView)
{
if (!explodedView || temporaryExplosion == explodedView) {
return false;
}
clearTemporaryExplosion();
Base::PyGILStateLocker lock;
App::PropertyPythonObject* proxy = explodedView
? dynamic_cast<App::PropertyPythonObject*>(explodedView->getPropertyByName("Proxy"))
: nullptr;
if (!proxy) {
return false;
}
Py::Object jointPy = proxy->getValue();
if (!jointPy.hasAttr("explodeTemporarily")) {
return false;
}
Py::Object attr = jointPy.getAttr("explodeTemporarily");
if (attr.ptr() && attr.isCallable()) {
Py::Tuple args(1);
args.setItem(0, Py::asObject(explodedView->getPyObject()));
Py::Callable(attr).apply(args);
temporaryExplosion = explodedView;
temporaryExplosion->purgeTouched();
return true;
}
return false;
}
void ViewProviderAssembly::clearTemporaryExplosion()
{
if (!temporaryExplosion) {
return;
}
Base::PyGILStateLocker lock;
App::PropertyPythonObject* proxy = temporaryExplosion
? dynamic_cast<App::PropertyPythonObject*>(temporaryExplosion->getPropertyByName("Proxy"))
: nullptr;
if (!proxy) {
return;
}
Py::Object jointPy = proxy->getValue();
if (!jointPy.hasAttr("restoreAssembly")) {
return;
}
Py::Object attr = jointPy.getAttr("restoreAssembly");
if (attr.ptr() && attr.isCallable()) {
Py::Tuple args(1);
args.setItem(0, Py::asObject(temporaryExplosion->getPyObject()));
Py::Callable(attr).apply(args);
temporaryExplosion->purgeTouched();
temporaryExplosion = nullptr;
}
}
// UTILS

View File

@@ -217,6 +217,8 @@ public:
void isolateComponents(std::set<App::DocumentObject*>& parts, IsolateMode mode);
void isolateJointReferences(App::DocumentObject* joint, IsolateMode mode = IsolateMode::Transparent);
void clearIsolate();
bool explodeTemporarily(App::DocumentObject* explodedView);
void clearTemporaryExplosion();
DragMode dragMode;
bool canStartDragging;
@@ -276,6 +278,7 @@ private:
};
std::unordered_map<App::DocumentObject*, ComponentState> stateBackup;
App::DocumentObject* temporaryExplosion {nullptr};
App::DocumentObject* isolatedJoint {nullptr};
bool isolatedJointVisibilityBackup {false};

View File

@@ -1163,6 +1163,7 @@ def restoreAssemblyPartsPlacements(assembly, initialPlcs):
for part in assemblyParts:
if part.Name in initialPlcs:
part.Placement = initialPlcs[part.Name]
part.purgeTouched()
def getComAndSize(assembly):