From f5a6e0fd3260a322e25bef8aabe89599f05e6e89 Mon Sep 17 00:00:00 2001 From: PaddleStroke Date: Mon, 10 Jun 2024 18:45:00 +0200 Subject: [PATCH] Assembly: Change Object1/2 from strings to PropertyXLinkSub and Remove Element1/2 and Vertex1/2 --- src/Mod/Assembly/App/AssemblyObject.cpp | 162 +++++------- src/Mod/Assembly/App/AssemblyObject.h | 8 +- src/Mod/Assembly/AssemblyTests/TestCore.py | 10 +- src/Mod/Assembly/Gui/ViewProviderAssembly.cpp | 10 +- src/Mod/Assembly/JointObject.py | 236 ++++++++++-------- src/Mod/Assembly/UtilsAssembly.py | 12 +- 6 files changed, 201 insertions(+), 237 deletions(-) diff --git a/src/Mod/Assembly/App/AssemblyObject.cpp b/src/Mod/Assembly/App/AssemblyObject.cpp index 336538ca86..aa53438354 100644 --- a/src/Mod/Assembly/App/AssemblyObject.cpp +++ b/src/Mod/Assembly/App/AssemblyObject.cpp @@ -434,8 +434,8 @@ App::DocumentObject* AssemblyObject::getJointOfPartConnectingToGround(App::Docum if (!joint) { continue; } - App::DocumentObject* part1 = getLinkObjFromProp(joint, "Part1"); - App::DocumentObject* part2 = getLinkObjFromProp(joint, "Part2"); + App::DocumentObject* part1 = getObjFromProp(joint, "Part1"); + App::DocumentObject* part2 = getObjFromProp(joint, "Part2"); if (!part1 || !part2) { continue; } @@ -507,8 +507,8 @@ std::vector AssemblyObject::getJoints(bool updateJCS, bool continue; } - auto* part1 = getLinkObjFromProp(joint, "Part1"); - auto* part2 = getLinkObjFromProp(joint, "Part2"); + auto* part1 = getObjFromProp(joint, "Part1"); + auto* part2 = getObjFromProp(joint, "Part2"); if (!part1 || !part2 || part1->getFullName() == part2->getFullName()) { // Remove incomplete joints. Left-over when the user delets a part. // Remove incoherent joints (self-pointing joints) @@ -571,8 +571,8 @@ std::vector AssemblyObject::getJointsOfObj(App::DocumentOb std::vector jointsOf; for (auto joint : joints) { - App::DocumentObject* obj1 = getObjFromNameProp(joint, "object1", "Part1"); - App::DocumentObject* obj2 = getObjFromNameProp(joint, "Object2", "Part2"); + App::DocumentObject* obj1 = getObjFromProp(joint, "object1"); + App::DocumentObject* obj2 = getObjFromProp(joint, "Object2"); if (obj == obj1 || obj == obj2) { jointsOf.push_back(obj); } @@ -587,8 +587,8 @@ std::vector AssemblyObject::getJointsOfPart(App::DocumentO std::vector jointsOf; for (auto joint : joints) { - App::DocumentObject* part1 = getLinkObjFromProp(joint, "Part1"); - App::DocumentObject* part2 = getLinkObjFromProp(joint, "Part2"); + App::DocumentObject* part1 = getObjFromProp(joint, "Part1"); + App::DocumentObject* part2 = getObjFromProp(joint, "Part2"); if (part == part1 || part == part2) { jointsOf.push_back(joint); } @@ -748,8 +748,8 @@ void AssemblyObject::removeUnconnectedJoints(std::vector& joints.begin(), joints.end(), [&connectedParts](App::DocumentObject* joint) { - App::DocumentObject* obj1 = getLinkObjFromProp(joint, "Part1"); - App::DocumentObject* obj2 = getLinkObjFromProp(joint, "Part2"); + App::DocumentObject* obj1 = getObjFromProp(joint, "Part1"); + App::DocumentObject* obj2 = getObjFromProp(joint, "Part2"); if ((connectedParts.find(obj1) == connectedParts.end()) || (connectedParts.find(obj2) == connectedParts.end())) { Base::Console().Warning( @@ -786,8 +786,8 @@ AssemblyObject::getConnectedParts(App::DocumentObject* part, continue; } - App::DocumentObject* obj1 = getLinkObjFromProp(joint, "Part1"); - App::DocumentObject* obj2 = getLinkObjFromProp(joint, "Part2"); + App::DocumentObject* obj1 = getObjFromProp(joint, "Part1"); + App::DocumentObject* obj2 = getObjFromProp(joint, "Part2"); if (obj1 == part) { connectedParts.push_back(obj2); } @@ -928,10 +928,10 @@ std::shared_ptr AssemblyObject::makeMbdJointDistance(App::DocumentObj { DistanceType type = getDistanceType(joint); - const char* elt1 = getElementFromProp(joint, "Element1"); - const char* elt2 = getElementFromProp(joint, "Element2"); - auto* obj1 = getLinkedObjFromNameProp(joint, "Object1", "Part1"); - auto* obj2 = getLinkedObjFromNameProp(joint, "Object2", "Part2"); + const char* elt1 = getElementFromProp(joint, "Object1"); + const char* elt2 = getElementFromProp(joint, "Object2"); + auto* obj1 = getLinkedObjFromProp(joint, "Object1"); + auto* obj2 = getLinkedObjFromProp(joint, "Object2"); if (type == DistanceType::PointPoint) { // Point to point distance, or ball joint if distance=0. @@ -1250,8 +1250,8 @@ std::string AssemblyObject::handleOneSideOfJoint(App::DocumentObject* joint, const char* propPartName, const char* propPlcName) { - App::DocumentObject* part = getLinkObjFromProp(joint, propPartName); - App::DocumentObject* obj = getObjFromNameProp(joint, propObjName, propPartName); + App::DocumentObject* part = getObjFromProp(joint, propPartName); + App::DocumentObject* obj = getObjFromProp(joint, propObjName); if (!part || !obj) { Base::Console().Warning("The property %s of Joint %s is empty.", @@ -1302,12 +1302,12 @@ void AssemblyObject::getRackPinionMarkers(App::DocumentObject* joint, swapJCS(joint); // make sure that rack is first. } - App::DocumentObject* part1 = getLinkObjFromProp(joint, "Part1"); - App::DocumentObject* obj1 = getObjFromNameProp(joint, "Object1", "Part1"); + App::DocumentObject* part1 = getObjFromProp(joint, "Part1"); + App::DocumentObject* obj1 = getObjFromProp(joint, "Object1"); Base::Placement plc1 = getPlacementFromProp(joint, "Placement1"); - App::DocumentObject* part2 = getLinkObjFromProp(joint, "Part2"); - App::DocumentObject* obj2 = getObjFromNameProp(joint, "Object2", "Part2"); + App::DocumentObject* part2 = getObjFromProp(joint, "Part2"); + App::DocumentObject* obj2 = getObjFromProp(joint, "Object2"); Base::Placement plc2 = getPlacementFromProp(joint, "Placement2"); if (!part1 || !obj1) { @@ -1370,21 +1370,21 @@ void AssemblyObject::getRackPinionMarkers(App::DocumentObject* joint, int AssemblyObject::slidingPartIndex(App::DocumentObject* joint) { - App::DocumentObject* part1 = getLinkObjFromProp(joint, "Part1"); - App::DocumentObject* obj1 = getObjFromNameProp(joint, "Object1", "Part1"); + App::DocumentObject* part1 = getObjFromProp(joint, "Part1"); + App::DocumentObject* obj1 = getObjFromProp(joint, "Object1"); boost::ignore_unused(obj1); Base::Placement plc1 = getPlacementFromProp(joint, "Placement1"); - App::DocumentObject* part2 = getLinkObjFromProp(joint, "Part2"); - App::DocumentObject* obj2 = getObjFromNameProp(joint, "Object2", "Part2"); + App::DocumentObject* part2 = getObjFromProp(joint, "Part2"); + App::DocumentObject* obj2 = getObjFromProp(joint, "Object2"); boost::ignore_unused(obj2); Base::Placement plc2 = getPlacementFromProp(joint, "Placement2"); int slidingFound = 0; for (auto* jt : getJoints(false, false)) { if (getJointType(jt) == JointType::Slider) { - App::DocumentObject* jpart1 = getLinkObjFromProp(jt, "Part1"); - App::DocumentObject* jpart2 = getLinkObjFromProp(jt, "Part2"); + App::DocumentObject* jpart1 = getObjFromProp(jt, "Part1"); + App::DocumentObject* jpart2 = getObjFromProp(jt, "Part2"); int found = 0; Base::Placement plcjt, plci; if (jpart1 == part1 || jpart1 == part2) { @@ -1527,8 +1527,8 @@ std::vector AssemblyObject::getDownstreamParts(App::Docume auto it = std::remove(jointsOfPart.begin(), jointsOfPart.end(), connectingJoint); jointsOfPart.erase(it, jointsOfPart.end()); for (auto joint : jointsOfPart) { - App::DocumentObject* part1 = getLinkObjFromProp(joint, "Part1"); - App::DocumentObject* part2 = getLinkObjFromProp(joint, "Part2"); + App::DocumentObject* part1 = getObjFromProp(joint, "Part1"); + App::DocumentObject* part2 = getObjFromProp(joint, "Part2"); bool firstIsDown = part->getFullName() == part2->getFullName(); App::DocumentObject* downstreamPart = firstIsDown ? part1 : part2; @@ -1574,7 +1574,7 @@ std::vector AssemblyObject::getUpstreamParts(App::Document std::string name; App::DocumentObject* connectingJoint = getJointOfPartConnectingToGround(part, name); App::DocumentObject* upPart = - getLinkObjFromProp(connectingJoint, name == "Part1" ? "Part2" : "Part1"); + getObjFromProp(connectingJoint, name == "Part1" ? "Part2" : "Part1"); std::vector upstreamParts = getUpstreamParts(upPart, limit); upstreamParts.push_back(part); @@ -1595,7 +1595,7 @@ App::DocumentObject* AssemblyObject::getUpstreamMovingPart(App::DocumentObject* } App::DocumentObject* upPart = - getLinkObjFromProp(connectingJoint, name == "Part1" ? "Part2" : "Part1"); + getObjFromProp(connectingJoint, name == "Part1" ? "Part2" : "Part1"); return getUpstreamMovingPart(upPart); } @@ -1659,20 +1659,6 @@ void AssemblyObject::updateGroundedJointsPlacements() void AssemblyObject::swapJCS(App::DocumentObject* joint) { - auto propElement1 = dynamic_cast(joint->getPropertyByName("Element1")); - auto propElement2 = dynamic_cast(joint->getPropertyByName("Element2")); - if (propElement1 && propElement2) { - auto temp = std::string(propElement1->getValue()); - propElement1->setValue(propElement2->getValue()); - propElement2->setValue(temp); - } - auto propVertex1 = dynamic_cast(joint->getPropertyByName("Vertex1")); - auto propVertex2 = dynamic_cast(joint->getPropertyByName("Vertex2")); - if (propVertex1 && propVertex2) { - auto temp = std::string(propVertex1->getValue()); - propVertex1->setValue(propVertex2->getValue()); - propVertex2->setValue(temp); - } auto propPlacement1 = dynamic_cast(joint->getPropertyByName("Placement1")); auto propPlacement2 = @@ -1682,12 +1668,16 @@ void AssemblyObject::swapJCS(App::DocumentObject* joint) propPlacement1->setValue(propPlacement2->getValue()); propPlacement2->setValue(temp); } - auto propObject1 = dynamic_cast(joint->getPropertyByName("Object1")); - auto propObject2 = dynamic_cast(joint->getPropertyByName("Object2")); + auto propObject1 = dynamic_cast(joint->getPropertyByName("Object1")); + auto propObject2 = dynamic_cast(joint->getPropertyByName("Object2")); if (propObject1 && propObject2) { - auto temp = std::string(propObject1->getValue()); + auto temp = propObject1->getValue(); + auto subs1 = propObject1->getSubValues(); + auto subs2 = propObject2->getSubValues(); propObject1->setValue(propObject2->getValue()); + propObject1->setSubValues(std::move(subs2)); propObject2->setValue(temp); + propObject2->setSubValues(std::move(subs1)); } auto propPart1 = dynamic_cast(joint->getPropertyByName("Part1")); auto propPart2 = dynamic_cast(joint->getPropertyByName("Part2")); @@ -1771,12 +1761,12 @@ double AssemblyObject::getEdgeRadius(App::DocumentObject* obj, const char* elt) DistanceType AssemblyObject::getDistanceType(App::DocumentObject* joint) { - std::string type1 = getElementTypeFromProp(joint, "Element1"); - std::string type2 = getElementTypeFromProp(joint, "Element2"); - std::string elt1 = getElementFromProp(joint, "Element1"); - std::string elt2 = getElementFromProp(joint, "Element2"); - auto* obj1 = getLinkedObjFromNameProp(joint, "Object1", "Part1"); - auto* obj2 = getLinkedObjFromNameProp(joint, "Object2", "Part2"); + std::string type1 = getElementTypeFromProp(joint, "Object1"); + std::string type2 = getElementTypeFromProp(joint, "Object2"); + std::string elt1 = getElementFromProp(joint, "Object1"); + std::string elt2 = getElementFromProp(joint, "Object2"); + auto* obj1 = getLinkedObjFromProp(joint, "Object1"); + auto* obj2 = getLinkedObjFromProp(joint, "Object2"); if (type1 == "Vertex" && type2 == "Vertex") { return DistanceType::PointPoint; @@ -2118,8 +2108,8 @@ Base::Placement AssemblyObject::getGlobalPlacement(App::DocumentObject* joint, const char* targetObj, const char* container) { - App::DocumentObject* obj = getObjFromNameProp(joint, targetObj, container); - App::DocumentObject* part = getLinkObjFromProp(joint, container); + App::DocumentObject* obj = getObjFromProp(joint, targetObj); + App::DocumentObject* part = getObjFromProp(joint, container); return getGlobalPlacement(obj, part); } @@ -2161,12 +2151,17 @@ JointType AssemblyObject::getJointType(App::DocumentObject* joint) const char* AssemblyObject::getElementFromProp(App::DocumentObject* obj, const char* propName) { - auto* prop = dynamic_cast(obj->getPropertyByName(propName)); + auto* prop = dynamic_cast(obj->getPropertyByName(propName)); if (!prop) { return ""; } - return prop->getValue(); + auto subs = prop->getSubValues(); + if (subs.empty()) { + return ""; + } + + return subs[0].c_str(); } std::string AssemblyObject::getElementTypeFromProp(App::DocumentObject* obj, const char* propName) @@ -2181,58 +2176,19 @@ std::string AssemblyObject::getElementTypeFromProp(App::DocumentObject* obj, con return elementType; } -App::DocumentObject* AssemblyObject::getLinkObjFromProp(App::DocumentObject* joint, - const char* propLinkName) +App::DocumentObject* AssemblyObject::getObjFromProp(App::DocumentObject* joint, const char* pName) { - auto* propObj = dynamic_cast(joint->getPropertyByName(propLinkName)); + auto* propObj = dynamic_cast(joint->getPropertyByName(pName)); if (!propObj) { return nullptr; } return propObj->getValue(); } -App::DocumentObject* AssemblyObject::getObjFromNameProp(App::DocumentObject* joint, - const char* pObjName, - const char* pPart) +App::DocumentObject* AssemblyObject::getLinkedObjFromProp(App::DocumentObject* joint, + const char* pObj) { - auto* propObjName = dynamic_cast(joint->getPropertyByName(pObjName)); - if (!propObjName) { - return nullptr; - } - std::string objName = std::string(propObjName->getValue()); - - App::DocumentObject* containingPart = getLinkObjFromProp(joint, pPart); - if (!containingPart) { - return nullptr; - } - - if (objName == containingPart->getNameInDocument()) { - return containingPart; - } - - /*if (containingPart->getTypeId().isDerivedFrom(App::Link::getClassTypeId())) { - App::Link* link = dynamic_cast(containingPart); - - containingPart = link->getLinkedObject(); - if (!containingPart) { - return nullptr; - } - }*/ - - for (auto obj : containingPart->getOutListRecursive()) { - if (objName == obj->getNameInDocument()) { - return obj; - } - } - - return nullptr; -} - -App::DocumentObject* AssemblyObject::getLinkedObjFromNameProp(App::DocumentObject* joint, - const char* pObjName, - const char* pPart) -{ - auto* obj = getObjFromNameProp(joint, pObjName, pPart); + auto* obj = getObjFromProp(joint, pObj); if (obj) { return obj->getLinkedObject(true); } diff --git a/src/Mod/Assembly/App/AssemblyObject.h b/src/Mod/Assembly/App/AssemblyObject.h index 4a8753f7ec..fd6f376877 100644 --- a/src/Mod/Assembly/App/AssemblyObject.h +++ b/src/Mod/Assembly/App/AssemblyObject.h @@ -252,12 +252,8 @@ public: static JointType getJointType(App::DocumentObject* joint); static const char* getElementFromProp(App::DocumentObject* obj, const char* propName); static std::string getElementTypeFromProp(App::DocumentObject* obj, const char* propName); - static App::DocumentObject* getLinkObjFromProp(App::DocumentObject* joint, - const char* propName); - static App::DocumentObject* - getObjFromNameProp(App::DocumentObject* joint, const char* pObjName, const char* pPart); - static App::DocumentObject* - getLinkedObjFromNameProp(App::DocumentObject* joint, const char* pObjName, const char* pPart); + static App::DocumentObject* getObjFromProp(App::DocumentObject* joint, const char* propName); + static App::DocumentObject* getLinkedObjFromProp(App::DocumentObject* joint, const char* pObj); static Base::Placement getPlacementFromProp(App::DocumentObject* obj, const char* propName); static bool getTargetPlacementRelativeTo(Base::Placement& foundPlc, App::DocumentObject* targetObj, diff --git a/src/Mod/Assembly/AssemblyTests/TestCore.py b/src/Mod/Assembly/AssemblyTests/TestCore.py index 4a50bd8bcf..1682606380 100644 --- a/src/Mod/Assembly/AssemblyTests/TestCore.py +++ b/src/Mod/Assembly/AssemblyTests/TestCore.py @@ -149,29 +149,29 @@ class TestCore(unittest.TestCase): box.Placement = App.Placement(App.Vector(10, 20, 30), App.Rotation(15, 25, 35)) # Step 0 : box with placement. No element selected - plc = joint.Proxy.findPlacement(joint, box.Name, box, "", "") + plc = joint.Proxy.findPlacement(joint, box, box, "", "") targetPlc = App.Placement(App.Vector(), App.Rotation()) self.assertTrue(plc.isSame(targetPlc, 1e-6), "'{}' failed - Step 0".format(operation)) # Step 1 : box with placement. Face + Vertex - plc = joint.Proxy.findPlacement(joint, box.Name, box, "Face6", "Vertex7") + plc = joint.Proxy.findPlacement(joint, box, box, "Face6", "Vertex7") targetPlc = App.Placement(App.Vector(L, W, H), App.Rotation()) self.assertTrue(plc.isSame(targetPlc, 1e-6), "'{}' failed - Step 1".format(operation)) # Step 2 : box with placement. Edge + Vertex - plc = joint.Proxy.findPlacement(joint, box.Name, box, "Edge8", "Vertex8") + plc = joint.Proxy.findPlacement(joint, box, box, "Edge8", "Vertex8") targetPlc = App.Placement(App.Vector(L, W, 0), App.Rotation(0, -90, 270)) self.assertTrue(plc.isSame(targetPlc, 1e-6), "'{}' failed - Step 2".format(operation)) # Step 3 : box with placement. Vertex - plc = joint.Proxy.findPlacement(joint, box.Name, box, "Vertex3", "Vertex3") + plc = joint.Proxy.findPlacement(joint, box, box, "Vertex3", "Vertex3") targetPlc = App.Placement(App.Vector(0, W, H), App.Rotation()) _msg(" plc '{}'".format(plc)) _msg(" targetPlc '{}'".format(targetPlc)) self.assertTrue(plc.isSame(targetPlc, 1e-6), "'{}' failed - Step 3".format(operation)) # Step 4 : box with placement. Face - plc = joint.Proxy.findPlacement(joint, box.Name, box, "Face2", "Face2") + plc = joint.Proxy.findPlacement(joint, box, box, "Face2", "Face2") targetPlc = App.Placement(App.Vector(L, W / 2, H / 2), App.Rotation(0, -90, 180)) _msg(" plc '{}'".format(plc)) _msg(" targetPlc '{}'".format(targetPlc)) diff --git a/src/Mod/Assembly/Gui/ViewProviderAssembly.cpp b/src/Mod/Assembly/Gui/ViewProviderAssembly.cpp index 22e647b42f..ada7a71d9b 100644 --- a/src/Mod/Assembly/Gui/ViewProviderAssembly.cpp +++ b/src/Mod/Assembly/Gui/ViewProviderAssembly.cpp @@ -150,11 +150,11 @@ bool ViewProviderAssembly::canDragObject(App::DocumentObject* obj) const Gui::Command::openCommand(tr("Delete associated joints").toStdString().c_str()); for (auto joint : allJoints) { // getLinkObjFromProp returns nullptr if the property doesn't exist. - App::DocumentObject* obj1 = AssemblyObject::getObjFromNameProp(joint, "Object1", "Part1"); - App::DocumentObject* obj2 = AssemblyObject::getObjFromNameProp(joint, "Object2", "Part2"); - App::DocumentObject* part1 = AssemblyObject::getLinkObjFromProp(joint, "Part1"); - App::DocumentObject* part2 = AssemblyObject::getLinkObjFromProp(joint, "Part2"); - App::DocumentObject* obj3 = AssemblyObject::getLinkObjFromProp(joint, "ObjectToGround"); + App::DocumentObject* obj1 = AssemblyObject::getObjFromProp(joint, "Object1"); + App::DocumentObject* obj2 = AssemblyObject::getObjFromProp(joint, "Object2"); + App::DocumentObject* part1 = AssemblyObject::getObjFromProp(joint, "Part1"); + App::DocumentObject* part2 = AssemblyObject::getObjFromProp(joint, "Part2"); + App::DocumentObject* obj3 = AssemblyObject::getObjFromProp(joint, "ObjectToGround"); if (obj == obj1 || obj == obj2 || obj == part1 || obj == part2 || obj == obj3) { if (!prompted) { prompted = true; diff --git a/src/Mod/Assembly/JointObject.py b/src/Mod/Assembly/JointObject.py index 58eaa03080..20be467ae3 100644 --- a/src/Mod/Assembly/JointObject.py +++ b/src/Mod/Assembly/JointObject.py @@ -172,9 +172,7 @@ def get_active_view(gui_doc): # The joint object consists of 2 JCS (joint coordinate systems) and a Joint Type. # A JCS is a placement that is computed (unless it is detached) from : -# - An Object name: this is the name of the solid. It can be any Part::Feature solid. -# Or a PartDesign Body. Or a App::Link to those. We use the name and not directly the DocumentObject -# because the object can be external. +# - An Object: this can be any Part::Feature solid. Or a PartDesign Body. Or a App::Link to those. # - A Part DocumentObject : This is the lowest level containing part. It can be either the Object itself if it # stands alone. Or a App::Part. Or a App::Link to a App::Part. # For example : @@ -204,10 +202,12 @@ class Joint: self.createProperties(joint) def createProperties(self, joint): + self.migrationScript(joint) + # First Joint Connector if not hasattr(joint, "Object1"): joint.addProperty( - "App::PropertyString", # Not PropertyLink because they don't support external objects + "App::PropertyXLinkSub", "Object1", "Joint Connector 1", QT_TRANSLATE_NOOP("App::Property", "The first object of the joint"), @@ -221,22 +221,6 @@ class Joint: QT_TRANSLATE_NOOP("App::Property", "The first part of the joint"), ) - if not hasattr(joint, "Element1"): - joint.addProperty( - "App::PropertyString", - "Element1", - "Joint Connector 1", - QT_TRANSLATE_NOOP("App::Property", "The selected element of the first object"), - ) - - if not hasattr(joint, "Vertex1"): - joint.addProperty( - "App::PropertyString", - "Vertex1", - "Joint Connector 1", - QT_TRANSLATE_NOOP("App::Property", "The selected vertex of the first object"), - ) - if not hasattr(joint, "Placement1"): joint.addProperty( "App::PropertyPlacement", @@ -262,7 +246,7 @@ class Joint: # Second Joint Connector if not hasattr(joint, "Object2"): joint.addProperty( - "App::PropertyString", + "App::PropertyXLinkSub", "Object2", "Joint Connector 2", QT_TRANSLATE_NOOP("App::Property", "The second object of the joint"), @@ -276,22 +260,6 @@ class Joint: QT_TRANSLATE_NOOP("App::Property", "The second part of the joint"), ) - if not hasattr(joint, "Element2"): - joint.addProperty( - "App::PropertyString", - "Element2", - "Joint Connector 2", - QT_TRANSLATE_NOOP("App::Property", "The selected element of the second object"), - ) - - if not hasattr(joint, "Vertex2"): - joint.addProperty( - "App::PropertyString", - "Vertex2", - "Joint Connector 2", - QT_TRANSLATE_NOOP("App::Property", "The selected vertex of the second object"), - ) - if not hasattr(joint, "Placement2"): joint.addProperty( "App::PropertyPlacement", @@ -314,6 +282,7 @@ class Joint: ), ) + # Other properties if not hasattr(joint, "Distance"): joint.addProperty( "App::PropertyFloat", @@ -462,6 +431,45 @@ class Joint: ), ) + def migrationScript(self, joint): + if hasattr(joint, "Object1") and isinstance(joint.Object1, str): + objName = joint.Object1 + obj1 = UtilsAssembly.getObjectInPart(objName, joint.Part1) + el1 = joint.Element1 + vtx1 = joint.Vertex1 + + joint.removeProperty("Object1") + joint.removeProperty("Element1") + joint.removeProperty("Vertex1") + + joint.addProperty( + "App::PropertyXLinkSub", + "Object1", + "Joint Connector 1", + QT_TRANSLATE_NOOP("App::Property", "The first object of the joint"), + ) + + joint.Object1 = [obj1, [el1, vtx1]] + + if hasattr(joint, "Object2") and isinstance(joint.Object2, str): + objName = joint.Object2 + obj2 = UtilsAssembly.getObjectInPart(objName, joint.Part2) + el2 = joint.Element2 + vtx2 = joint.Vertex2 + + joint.removeProperty("Object2") + joint.removeProperty("Element2") + joint.removeProperty("Vertex2") + + joint.addProperty( + "App::PropertyXLinkSub", + "Object2", + "Joint Connector 2", + QT_TRANSLATE_NOOP("App::Property", "The second object of the joint"), + ) + + joint.Object2 = [obj2, [el2, vtx2]] + def dumps(self): return None @@ -482,30 +490,28 @@ class Joint: """Do something when a property has changed""" # App.Console.PrintMessage("Change property: " + str(prop) + "\n") + # during loading the onchanged may be triggered before full init. + if App.isRestoring(): + return + if prop == "Rotation" or prop == "Offset": - # during loading the onchanged may be triggered before full init. - if hasattr(joint, "Vertex1"): # so we check Vertex1 + self.updateJCSPlacements(joint) + if joint.Object1 is None or joint.Object2 is None: + return + + presolved = self.preSolve(joint, False) + + isAssembly = self.getAssembly(joint).Type == "Assembly" + if isAssembly and not presolved: + solveIfAllowed(self.getAssembly(joint)) + else: self.updateJCSPlacements(joint) - obj1 = UtilsAssembly.getObjectInPart(joint.Object1, joint.Part1) - obj2 = UtilsAssembly.getObjectInPart(joint.Object2, joint.Part2) - if obj1 is None or obj2 is None: - return - - presolved = self.preSolve(joint, False) - - isAssembly = self.getAssembly(joint).Type == "Assembly" - if isAssembly and not presolved: - solveIfAllowed(self.getAssembly(joint)) - else: - self.updateJCSPlacements(joint) if prop == "Distance" and (joint.JointType == "Distance" or joint.JointType == "Angle"): - # during loading the onchanged may be triggered before full init. - if hasattr(joint, "Vertex1"): # so we check Vertex1 - if joint.Part1 and joint.Part2: - if joint.JointType == "Angle" and joint.Distance != 0.0: - self.preventParallel(joint) - solveIfAllowed(self.getAssembly(joint)) + if joint.Part1 and joint.Part2: + if joint.JointType == "Angle" and joint.Distance != 0.0: + self.preventParallel(joint) + solveIfAllowed(self.getAssembly(joint)) def execute(self, fp): """Do something when doing a recomputation, this method is mandatory""" @@ -518,28 +524,28 @@ class Joint: isAssembly = assembly.Type == "Assembly" if len(current_selection) >= 1: - joint.Object1 = current_selection[0]["object"].Name + joint.Object1 = [ + current_selection[0]["object"], + [current_selection[0]["element_name"], current_selection[0]["vertex_name"]], + ] joint.Part1 = current_selection[0]["part"] - joint.Element1 = current_selection[0]["element_name"] - joint.Vertex1 = current_selection[0]["vertex_name"] joint.Placement1 = self.findPlacement( - joint, joint.Object1, joint.Part1, joint.Element1, joint.Vertex1 + joint, joint.Object1[0], joint.Part1, joint.Object1[1][0], joint.Object1[1][1] ) else: - joint.Object1 = "" + joint.Object1 = None joint.Part1 = None - joint.Element1 = "" - joint.Vertex1 = "" joint.Placement1 = App.Placement() self.partMovedByPresolved = None if len(current_selection) >= 2: - joint.Object2 = current_selection[1]["object"].Name + joint.Object2 = [ + current_selection[1]["object"], + [current_selection[1]["element_name"], current_selection[1]["vertex_name"]], + ] joint.Part2 = current_selection[1]["part"] - joint.Element2 = current_selection[1]["element_name"] - joint.Vertex2 = current_selection[1]["vertex_name"] joint.Placement2 = self.findPlacement( - joint, joint.Object2, joint.Part2, joint.Element2, joint.Vertex2, True + joint, joint.Object2[0], joint.Part2, joint.Object2[1][0], joint.Object2[1][1], True ) if joint.JointType in JointUsingPreSolve: self.preSolve(joint) @@ -552,10 +558,8 @@ class Joint: self.updateJCSPlacements(joint) else: - joint.Object2 = "" + joint.Object2 = None joint.Part2 = None - joint.Element2 = "" - joint.Vertex2 = "" joint.Placement2 = App.Placement() if isAssembly: assembly.undoSolve() @@ -564,12 +568,12 @@ class Joint: def updateJCSPlacements(self, joint): if not joint.Detach1: joint.Placement1 = self.findPlacement( - joint, joint.Object1, joint.Part1, joint.Element1, joint.Vertex1 + joint, joint.Object1[0], joint.Part1, joint.Object1[1][0], joint.Object1[1][1] ) if not joint.Detach2: joint.Placement2 = self.findPlacement( - joint, joint.Object2, joint.Part2, joint.Element2, joint.Vertex2, True + joint, joint.Object2[0], joint.Part2, joint.Object2[1][0], joint.Object2[1][1], True ) """ @@ -582,12 +586,10 @@ class Joint: - if elt is a cylindrical face, vtx can also be the center of the arcs of the cylindrical face. """ - def findPlacement(self, joint, objName, part, elt, vtx, isSecond=False): - if not objName or not part: + def findPlacement(self, joint, obj, part, elt, vtx, isSecond=False): + if not obj or not part: return App.Placement() - obj = UtilsAssembly.getObjectInPart(objName, part) - ignoreVertex = joint.JointType == "Distance" plc = UtilsAssembly.findPlacement(obj, part, elt, vtx, ignoreVertex) @@ -607,20 +609,20 @@ class Joint: part2Grounded = assembly.isPartGrounded(joint.Part2) if part2ConnectedByJoint and not part2Grounded: jcsPlc = UtilsAssembly.getJcsPlcRelativeToPart( - joint.Placement2, joint.Object2, joint.Part2 + joint.Placement2, joint.Object2[0], joint.Part2 ) globalJcsPlc = UtilsAssembly.getJcsGlobalPlc( - joint.Placement2, joint.Object2, joint.Part2 + joint.Placement2, joint.Object2[0], joint.Part2 ) jcsPlc = UtilsAssembly.flipPlacement(jcsPlc) joint.Part2.Placement = globalJcsPlc * jcsPlc.inverse() elif not part1Grounded: jcsPlc = UtilsAssembly.getJcsPlcRelativeToPart( - joint.Placement1, joint.Object1, joint.Part1 + joint.Placement1, joint.Object1[0], joint.Part1 ) globalJcsPlc = UtilsAssembly.getJcsGlobalPlc( - joint.Placement1, joint.Object1, joint.Part1 + joint.Placement1, joint.Object1[0], joint.Part1 ) jcsPlc = UtilsAssembly.flipPlacement(jcsPlc) joint.Part1.Placement = globalJcsPlc * jcsPlc.inverse() @@ -650,10 +652,10 @@ class Joint: self.presolveBackupPlc = joint.Part2.Placement globalJcsPlc1 = UtilsAssembly.getJcsGlobalPlc( - joint.Placement1, joint.Object1, joint.Part1 + joint.Placement1, joint.Object1[0], joint.Part1 ) jcsPlc2 = UtilsAssembly.getJcsPlcRelativeToPart( - joint.Placement2, joint.Object2, joint.Part2 + joint.Placement2, joint.Object2[0], joint.Part2 ) if not sameDir: jcsPlc2 = UtilsAssembly.flipPlacement(jcsPlc2) @@ -666,10 +668,10 @@ class Joint: self.presolveBackupPlc = joint.Part1.Placement globalJcsPlc2 = UtilsAssembly.getJcsGlobalPlc( - joint.Placement2, joint.Object2, joint.Part2 + joint.Placement2, joint.Object2[0], joint.Part2 ) jcsPlc1 = UtilsAssembly.getJcsPlcRelativeToPart( - joint.Placement1, joint.Object1, joint.Part1 + joint.Placement1, joint.Object1[0], joint.Part1 ) if not sameDir: jcsPlc1 = UtilsAssembly.flipPlacement(jcsPlc1) @@ -716,14 +718,22 @@ class Joint: ) def areJcsSameDir(self, joint): - globalJcsPlc1 = UtilsAssembly.getJcsGlobalPlc(joint.Placement1, joint.Object1, joint.Part1) - globalJcsPlc2 = UtilsAssembly.getJcsGlobalPlc(joint.Placement2, joint.Object2, joint.Part2) + globalJcsPlc1 = UtilsAssembly.getJcsGlobalPlc( + joint.Placement1, joint.Object1[0], joint.Part1 + ) + globalJcsPlc2 = UtilsAssembly.getJcsGlobalPlc( + joint.Placement2, joint.Object2[0], joint.Part2 + ) return UtilsAssembly.arePlacementSameDir(globalJcsPlc1, globalJcsPlc2) def areJcsZParallel(self, joint): - globalJcsPlc1 = UtilsAssembly.getJcsGlobalPlc(joint.Placement1, joint.Object1, joint.Part1) - globalJcsPlc2 = UtilsAssembly.getJcsGlobalPlc(joint.Placement2, joint.Object2, joint.Part2) + globalJcsPlc1 = UtilsAssembly.getJcsGlobalPlc( + joint.Placement1, joint.Object1[0], joint.Part1 + ) + globalJcsPlc2 = UtilsAssembly.getJcsGlobalPlc( + joint.Placement2, joint.Object2[0], joint.Part2 + ) return UtilsAssembly.arePlacementZParallel(globalJcsPlc1, globalJcsPlc2) @@ -862,9 +872,8 @@ class ViewProviderJoint: def get_JCS_size(self): return get_camera_height(self.gui_doc) / 20 - def set_JCS_placement(self, soTransform, placement, objName, part): + def set_JCS_placement(self, soTransform, placement, obj, part): # change plc to be relative to the origin of the document. - obj = UtilsAssembly.getObjectInPart(objName, part) global_plc = UtilsAssembly.getGlobalPlacement(obj, part) placement = global_plc * placement @@ -883,7 +892,7 @@ class ViewProviderJoint: self.switch_JCS1.whichChild = coin.SO_SWITCH_ALL if joint.Part1: - self.set_JCS_placement(self.transform1, plc, joint.Object1, joint.Part1) + self.set_JCS_placement(self.transform1, plc, joint.Object1[0], joint.Part1) else: self.switch_JCS1.whichChild = coin.SO_SWITCH_NONE @@ -893,14 +902,14 @@ class ViewProviderJoint: self.switch_JCS2.whichChild = coin.SO_SWITCH_ALL if joint.Part2: - self.set_JCS_placement(self.transform2, plc, joint.Object2, joint.Part2) + self.set_JCS_placement(self.transform2, plc, joint.Object2[0], joint.Part2) else: self.switch_JCS2.whichChild = coin.SO_SWITCH_NONE - def showPreviewJCS(self, visible, placement=None, objName="", part=None): + def showPreviewJCS(self, visible, placement=None, obj=None, part=None): if visible: self.switch_JCS_preview.whichChild = coin.SO_SWITCH_ALL - self.set_JCS_placement(self.transform3, placement, objName, part) + self.set_JCS_placement(self.transform3, placement, obj, part) else: self.switch_JCS_preview.whichChild = coin.SO_SWITCH_NONE @@ -1626,21 +1635,28 @@ class TaskAssemblyCreateJoint(QtCore.QObject): self.current_selection = [] self.preselection_dict = None - obj1 = UtilsAssembly.getObjectInPart(self.joint.Object1, self.joint.Part1) - obj2 = UtilsAssembly.getObjectInPart(self.joint.Object2, self.joint.Part2) + obj1 = self.joint.Object1[0] + part1 = self.joint.Part1 + el1 = self.joint.Object1[1][0] + vtx1 = self.joint.Object1[1][1] + + obj2 = self.joint.Object2[0] + part2 = self.joint.Part2 + el2 = self.joint.Object2[1][0] + vtx2 = self.joint.Object2[1][1] selection_dict1 = { "object": obj1, - "part": self.joint.Part1, - "element_name": self.joint.Element1, - "vertex_name": self.joint.Vertex1, + "part": part1, + "element_name": el1, + "vertex_name": vtx1, } selection_dict2 = { "object": obj2, - "part": self.joint.Part2, - "element_name": self.joint.Element2, - "vertex_name": self.joint.Vertex2, + "part": part2, + "element_name": el2, + "vertex_name": vtx2, } self.current_selection.append(selection_dict1) @@ -1651,11 +1667,11 @@ class TaskAssemblyCreateJoint(QtCore.QObject): # Because obj1 can be external in which case addSelection will fail. And # Gui.Selection.addSelection(obj1.Document.Name, obj1.Name, elName) # will not select in the assembly doc. - elName = self.getSubnameForSelection(obj1, self.joint.Part1, self.joint.Element1) - Gui.Selection.addSelection(self.doc.Name, self.joint.Part1.Name, elName) + elName = self.getSubnameForSelection(obj1, part1, el1) + Gui.Selection.addSelection(self.doc.Name, part1.Name, elName) - elName = self.getSubnameForSelection(obj2, self.joint.Part2, self.joint.Element2) - Gui.Selection.addSelection(self.doc.Name, self.joint.Part2.Name, elName) + elName = self.getSubnameForSelection(obj2, part2, el2) + Gui.Selection.addSelection(self.doc.Name, part2.Name, elName) self.form.distanceSpinbox.setProperty("rawValue", self.joint.Distance) self.form.distanceSpinbox2.setProperty("rawValue", self.joint.Distance2) @@ -1791,17 +1807,17 @@ class TaskAssemblyCreateJoint(QtCore.QObject): ) isSecond = len(self.current_selection) == 1 - objName = self.preselection_dict["object"].Name + obj = self.preselection_dict["object"] part = self.preselection_dict["part"] placement = self.joint.Proxy.findPlacement( self.joint, - objName, + obj, part, self.preselection_dict["element_name"], self.preselection_dict["vertex_name"], isSecond, ) - self.joint.ViewObject.Proxy.showPreviewJCS(True, placement, objName, part) + self.joint.ViewObject.Proxy.showPreviewJCS(True, placement, obj, part) self.previewJCSVisible = True # 3D view keyboard handler diff --git a/src/Mod/Assembly/UtilsAssembly.py b/src/Mod/Assembly/UtilsAssembly.py index 8f778d1ba6..7669d4faab 100644 --- a/src/Mod/Assembly/UtilsAssembly.py +++ b/src/Mod/Assembly/UtilsAssembly.py @@ -268,9 +268,7 @@ def getObjectInPart(objName, part): # get the placement of Obj relative to its containing Part # Example : assembly.part1.part2.partn.body1 : placement of Obj relative to part1 -def getObjPlcRelativeToPart(objName, part): - obj = getObjectInPart(objName, part) - +def getObjPlcRelativeToPart(obj, part): # we need plc to be relative to the containing part obj_global_plc = getGlobalPlacement(obj, part) part_global_plc = getGlobalPlacement(part) @@ -280,15 +278,13 @@ def getObjPlcRelativeToPart(objName, part): # Example : assembly.part1.part2.partn.body1 : jcsPlc is relative to body1 # This function returns jcsPlc relative to part1 -def getJcsPlcRelativeToPart(jcsPlc, objName, part): - obj_relative_plc = getObjPlcRelativeToPart(objName, part) +def getJcsPlcRelativeToPart(jcsPlc, obj, part): + obj_relative_plc = getObjPlcRelativeToPart(obj, part) return obj_relative_plc * jcsPlc # Return the jcs global placement -def getJcsGlobalPlc(jcsPlc, objName, part): - obj = getObjectInPart(objName, part) - +def getJcsGlobalPlc(jcsPlc, obj, part): obj_global_plc = getGlobalPlacement(obj, part) return obj_global_plc * jcsPlc