Assembly: Change Object1/2 from strings to PropertyXLinkSub and Remove Element1/2 and Vertex1/2

This commit is contained in:
PaddleStroke
2024-06-10 18:45:00 +02:00
committed by Chris Hennes
parent e38259c307
commit f5a6e0fd32
6 changed files with 201 additions and 237 deletions

View File

@@ -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