| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | import os |
| | import FreeCAD as App |
| |
|
| | from PySide.QtCore import QT_TRANSLATE_NOOP |
| |
|
| | if App.GuiUp: |
| | import FreeCADGui as Gui |
| | from PySide import QtCore, QtGui, QtWidgets |
| |
|
| | import JointObject |
| | from JointObject import TaskAssemblyCreateJoint |
| | import UtilsAssembly |
| | import Assembly_rc |
| |
|
| | |
| |
|
| | __title__ = "Assembly Commands to Create Joints" |
| | __author__ = "Ondsel" |
| | __url__ = "https://www.freecad.org" |
| |
|
| |
|
| | def noOtherTaskActive(): |
| | return UtilsAssembly.isAssemblyCommandActive() or JointObject.activeTask is not None |
| |
|
| |
|
| | def isCreateJointActive(): |
| | return UtilsAssembly.assembly_has_at_least_n_parts(1) and noOtherTaskActive() |
| |
|
| |
|
| | def activateJoint(index): |
| | if JointObject.activeTask: |
| | JointObject.activeTask.reject() |
| |
|
| | Gui.addModule("JointObject") |
| | Gui.doCommand(f"panel = JointObject.TaskAssemblyCreateJoint({index})") |
| | Gui.doCommandGui("dialog = Gui.Control.showDialog(panel)") |
| | dialog = Gui.doCommandEval("dialog") |
| | if dialog is not None: |
| | dialog.setAutoCloseOnTransactionChange(True) |
| | dialog.setAutoCloseOnDeletedDocument(True) |
| | dialog.setDocumentName(App.ActiveDocument.Name) |
| |
|
| |
|
| | class CommandCreateJointFixed: |
| | def __init__(self): |
| | pass |
| |
|
| | def GetResources(self): |
| | return { |
| | "Pixmap": "Assembly_CreateJointFixed", |
| | "MenuText": QT_TRANSLATE_NOOP( |
| | "Assembly_CreateJointFixed", |
| | "Fixed Joint", |
| | ), |
| | "Accel": "F", |
| | "ToolTip": QT_TRANSLATE_NOOP( |
| | "Assembly_CreateJointFixed", |
| | "<p>1 - If an assembly is active : Creates a joint permanently locking two parts together, preventing any movement or rotation</p>" |
| | "<p>2 - If a part is active: Positions sub-parts by matching selected coordinate systems. The second part selected will move.</p>", |
| | ), |
| | "CmdType": "ForEdit", |
| | } |
| |
|
| | def IsActive(self): |
| | if UtilsAssembly.activePart() is not None: |
| | return UtilsAssembly.assembly_has_at_least_n_parts(2) |
| |
|
| | return isCreateJointActive() |
| |
|
| | def Activated(self): |
| | activateJoint(0) |
| |
|
| |
|
| | class CommandCreateJointRevolute: |
| | def __init__(self): |
| | pass |
| |
|
| | def GetResources(self): |
| | return { |
| | "Pixmap": "Assembly_CreateJointRevolute", |
| | "MenuText": QT_TRANSLATE_NOOP("Assembly_CreateJointRevolute", "Revolute Joint"), |
| | "Accel": "R", |
| | "ToolTip": QT_TRANSLATE_NOOP( |
| | "Assembly_CreateJointRevolute", |
| | "Creates a revolute joint allowing rotation around a single axis between selected parts", |
| | ), |
| | "CmdType": "ForEdit", |
| | } |
| |
|
| | def IsActive(self): |
| | return isCreateJointActive() |
| |
|
| | def Activated(self): |
| | activateJoint(1) |
| |
|
| |
|
| | class CommandCreateJointCylindrical: |
| | def __init__(self): |
| | pass |
| |
|
| | def GetResources(self): |
| | return { |
| | "Pixmap": "Assembly_CreateJointCylindrical", |
| | "MenuText": QT_TRANSLATE_NOOP("Assembly_CreateJointCylindrical", "Cylindrical Joint"), |
| | "Accel": "C", |
| | "ToolTip": QT_TRANSLATE_NOOP( |
| | "Assembly_CreateJointCylindrical", |
| | "Creates a cylindrical joint that allows rotation around and translation along a single axis between assembled parts", |
| | ), |
| | "CmdType": "ForEdit", |
| | } |
| |
|
| | def IsActive(self): |
| | return isCreateJointActive() |
| |
|
| | def Activated(self): |
| | activateJoint(2) |
| |
|
| |
|
| | class CommandCreateJointSlider: |
| | def __init__(self): |
| | pass |
| |
|
| | def GetResources(self): |
| | return { |
| | "Pixmap": "Assembly_CreateJointSlider", |
| | "MenuText": QT_TRANSLATE_NOOP("Assembly_CreateJointSlider", "Slider Joint"), |
| | "Accel": "S", |
| | "ToolTip": QT_TRANSLATE_NOOP( |
| | "Assembly_CreateJointSlider", |
| | "Creates a slider joint that allows linear movement along a single axis, but restricts rotation between selected parts", |
| | ), |
| | "CmdType": "ForEdit", |
| | } |
| |
|
| | def IsActive(self): |
| | return isCreateJointActive() |
| |
|
| | def Activated(self): |
| | activateJoint(3) |
| |
|
| |
|
| | class CommandCreateJointBall: |
| | def __init__(self): |
| | pass |
| |
|
| | def GetResources(self): |
| | return { |
| | "Pixmap": "Assembly_CreateJointBall", |
| | "MenuText": QT_TRANSLATE_NOOP("Assembly_CreateJointBall", "Ball Joint"), |
| | "Accel": "B", |
| | "ToolTip": QT_TRANSLATE_NOOP( |
| | "Assembly_CreateJointBall", |
| | "Creates a ball joint that connects parts at a point, allowing unrestricted movement as long as the connection points remain in contact", |
| | ), |
| | "CmdType": "ForEdit", |
| | } |
| |
|
| | def IsActive(self): |
| | return isCreateJointActive() |
| |
|
| | def Activated(self): |
| | activateJoint(4) |
| |
|
| |
|
| | class CommandCreateJointDistance: |
| | def __init__(self): |
| | pass |
| |
|
| | def GetResources(self): |
| | return { |
| | "Pixmap": "Assembly_CreateJointDistance", |
| | "MenuText": QT_TRANSLATE_NOOP("Assembly_CreateJointDistance", "Distance Joint"), |
| | "Accel": "D", |
| | "ToolTip": QT_TRANSLATE_NOOP( |
| | "Assembly_CreateJointDistance", |
| | "<p>Creates a distance joint that fixes the distance between the selected objects</p>" |
| | "<p>Creates one of several different joints based on the selection. " |
| | "For example, a distance of 0 between a plane and a cylinder creates a tangent joint. A distance of 0 between planes will make them co-planar.</p>", |
| | ), |
| | "CmdType": "ForEdit", |
| | } |
| |
|
| | def IsActive(self): |
| | return isCreateJointActive() |
| |
|
| | def Activated(self): |
| | activateJoint(5) |
| |
|
| |
|
| | class CommandCreateJointParallel: |
| | def __init__(self): |
| | pass |
| |
|
| | def GetResources(self): |
| | return { |
| | "Pixmap": "Assembly_CreateJointParallel", |
| | "MenuText": QT_TRANSLATE_NOOP("Assembly_CreateJointParallel", "Parallel Joint"), |
| | "Accel": "N", |
| | "ToolTip": QT_TRANSLATE_NOOP( |
| | "Assembly_CreateJointParallel", |
| | "Creates a parallel joint that makes the Z-axis of the selected coordinate systems parallel", |
| | ), |
| | "CmdType": "ForEdit", |
| | } |
| |
|
| | def IsActive(self): |
| | return isCreateJointActive() |
| |
|
| | def Activated(self): |
| | activateJoint(6) |
| |
|
| |
|
| | class CommandCreateJointPerpendicular: |
| | def __init__(self): |
| | pass |
| |
|
| | def GetResources(self): |
| | return { |
| | "Pixmap": "Assembly_CreateJointPerpendicular", |
| | "MenuText": QT_TRANSLATE_NOOP( |
| | "Assembly_CreateJointPerpendicular", "Perpendicular Joint" |
| | ), |
| | "Accel": "M", |
| | "ToolTip": QT_TRANSLATE_NOOP( |
| | "Assembly_CreateJointPerpendicular", |
| | "Creates a perpendicular joint that makes the Z-axis of the selected coordinate systems perpendicular", |
| | ), |
| | "CmdType": "ForEdit", |
| | } |
| |
|
| | def IsActive(self): |
| | return isCreateJointActive() |
| |
|
| | def Activated(self): |
| | activateJoint(7) |
| |
|
| |
|
| | class CommandCreateJointAngle: |
| | def __init__(self): |
| | pass |
| |
|
| | def GetResources(self): |
| | return { |
| | "Pixmap": "Assembly_CreateJointAngle", |
| | "MenuText": QT_TRANSLATE_NOOP("Assembly_CreateJointAngle", "Angle Joint"), |
| | "Accel": "X", |
| | "ToolTip": QT_TRANSLATE_NOOP( |
| | "Assembly_CreateJointAngle", |
| | "Creates an angle joint that fixes the angle between the Z-axis of the selected coordinate systems", |
| | ), |
| | "CmdType": "ForEdit", |
| | } |
| |
|
| | def IsActive(self): |
| | return isCreateJointActive() |
| |
|
| | def Activated(self): |
| | activateJoint(8) |
| |
|
| |
|
| | class CommandCreateJointRackPinion: |
| | def __init__(self): |
| | pass |
| |
|
| | def GetResources(self): |
| | return { |
| | "Pixmap": "Assembly_CreateJointRackPinion", |
| | "MenuText": QT_TRANSLATE_NOOP( |
| | "Assembly_CreateJointRackPinion", "Rack and Pinion Joint" |
| | ), |
| | "Accel": "Q", |
| | "ToolTip": QT_TRANSLATE_NOOP( |
| | "Assembly_CreateJointRackPinion", |
| | "<p>Creates a rack and pinion joint that links a part with a slider joint to a part with a revolute joint</p>" |
| | "<p>Select the same coordinate systems as the revolute and slider joints. The pitch radius defines the movement ratio between the rack and the pinion.</p>", |
| | ), |
| | "CmdType": "ForEdit", |
| | } |
| |
|
| | def IsActive(self): |
| | return isCreateJointActive() |
| |
|
| | def Activated(self): |
| | activateJoint(9) |
| |
|
| |
|
| | class CommandCreateJointScrew: |
| | def __init__(self): |
| | pass |
| |
|
| | def GetResources(self): |
| | return { |
| | "Pixmap": "Assembly_CreateJointScrew", |
| | "MenuText": QT_TRANSLATE_NOOP("Assembly_CreateJointScrew", "Screw Joint"), |
| | "Accel": "W", |
| | "ToolTip": QT_TRANSLATE_NOOP( |
| | "Assembly_CreateJointScrew", |
| | "<p>Creates a screw joint that links a part with a slider joint to a part with a revolute joint</p>" |
| | "<p>Select the same coordinate systems as the revolute and slider joints. The pitch radius defines the movement ratio between the rotating screw and the sliding part.</p>", |
| | ), |
| | "CmdType": "ForEdit", |
| | } |
| |
|
| | def IsActive(self): |
| | return isCreateJointActive() |
| |
|
| | def Activated(self): |
| | activateJoint(10) |
| |
|
| |
|
| | class CommandCreateJointGears: |
| | def __init__(self): |
| | pass |
| |
|
| | def GetResources(self): |
| | return { |
| | "Pixmap": "Assembly_CreateJointGears", |
| | "MenuText": QT_TRANSLATE_NOOP("Assembly_CreateJointGears", "Gears Joint"), |
| | "Accel": "T", |
| | "ToolTip": QT_TRANSLATE_NOOP( |
| | "Assembly_CreateJointGears", |
| | "<p>Creates a gears joint that links 2 rotating gears together. They will have inverse rotation direction.</p>" |
| | "<p>Select the same coordinate systems as the revolute joints.</p>", |
| | ), |
| | "CmdType": "ForEdit", |
| | } |
| |
|
| | def IsActive(self): |
| | return isCreateJointActive() |
| |
|
| | def Activated(self): |
| | activateJoint(11) |
| |
|
| |
|
| | class CommandCreateJointBelt: |
| | def __init__(self): |
| | pass |
| |
|
| | def GetResources(self): |
| | return { |
| | "Pixmap": "Assembly_CreateJointPulleys", |
| | "MenuText": QT_TRANSLATE_NOOP("Assembly_CreateJointBelt", "Belt Joint"), |
| | "Accel": "L", |
| | "ToolTip": QT_TRANSLATE_NOOP( |
| | "Assembly_CreateJointBelt", |
| | "<p>Creates a belt joint that links 2 rotating objects together. They will have the same rotation direction.</p>" |
| | "<p>Select the same coordinate systems as the revolute joints.</p>", |
| | ), |
| | "CmdType": "ForEdit", |
| | } |
| |
|
| | def IsActive(self): |
| | return isCreateJointActive() |
| |
|
| | def Activated(self): |
| | activateJoint(12) |
| |
|
| |
|
| | class CommandGroupGearBelt: |
| | def GetCommands(self): |
| | return ("Assembly_CreateJointGears", "Assembly_CreateJointBelt") |
| |
|
| | def GetResources(self): |
| | """Set icon, menu and tooltip.""" |
| | return { |
| | "Pixmap": "Assembly_CreateJointGears", |
| | "MenuText": QT_TRANSLATE_NOOP("Assembly_CreateJointGearBelt", "Gears/Belt Joint"), |
| | "ToolTip": QT_TRANSLATE_NOOP( |
| | "Assembly_CreateJointGearBelt", |
| | "<p>Creates a gears or belt joint that links 2 rotating gears together</p>" |
| | "<p>Select the same coordinate systems as the revolute joints.</p>", |
| | ), |
| | "CmdType": "ForEdit", |
| | } |
| |
|
| | def IsActive(self): |
| | return isCreateJointActive() |
| |
|
| |
|
| | def createGroundedJoint(obj): |
| | if not UtilsAssembly.activeAssembly(): |
| | return |
| |
|
| | Gui.addModule("UtilsAssembly") |
| | Gui.addModule("JointObject") |
| | commands = ( |
| | f'obj = App.ActiveDocument.getObject("{obj.Name}")\n' |
| | "assembly = UtilsAssembly.activeAssembly()\n" |
| | "joint_group = UtilsAssembly.getJointGroup(assembly)\n" |
| | 'ground = joint_group.newObject("App::FeaturePython", "GroundedJoint")\n' |
| | "JointObject.GroundedJoint(ground, obj)" |
| | ) |
| | Gui.doCommand(commands) |
| | Gui.doCommandGui("JointObject.ViewProviderGroundedJoint(ground.ViewObject)") |
| | return Gui.doCommandEval("ground") |
| |
|
| |
|
| | class CommandToggleGrounded: |
| | def __init__(self): |
| | pass |
| |
|
| | def GetResources(self): |
| | return { |
| | "Pixmap": "Assembly_ToggleGrounded", |
| | "MenuText": QT_TRANSLATE_NOOP("Assembly_ToggleGrounded", "Toggle Grounded"), |
| | "Accel": "G", |
| | "ToolTip": QT_TRANSLATE_NOOP( |
| | "Assembly_ToggleGrounded", |
| | "<p>Toggles the grounding of a part.</p>" |
| | "<p>Grounding a part permanently locks its position in the assembly, preventing any movement or rotation.", |
| | ), |
| | "CmdType": "ForEdit", |
| | } |
| |
|
| | def IsActive(self): |
| | return ( |
| | UtilsAssembly.isAssemblyCommandActive() |
| | and UtilsAssembly.assembly_has_at_least_n_parts(1) |
| | ) |
| |
|
| | def Activated(self): |
| | assembly = UtilsAssembly.activeAssembly() |
| | if not assembly: |
| | return |
| |
|
| | joint_group = UtilsAssembly.getJointGroup(assembly) |
| |
|
| | selection = Gui.Selection.getSelectionEx("*", 0) |
| | if not selection: |
| | return |
| |
|
| | App.setActiveTransaction("Toggle grounded") |
| | for sel in selection: |
| | |
| | |
| | for sub in sel.SubElementNames: |
| | |
| | resolved = sel.Object.resolveSubElement(sub) |
| | if resolved: |
| | obj = resolved[0] |
| | if hasattr(obj, "ObjectToGround"): |
| | commands = ( |
| | "doc = App.ActiveDocument\n" |
| | f'doc.removeObject("{obj.Name}")\n' |
| | "doc.recompute()\n" |
| | ) |
| | Gui.doCommand(commands) |
| | continue |
| |
|
| | ref = [sel.Object, [sub, sub]] |
| | moving_part = UtilsAssembly.getMovingPart(assembly, ref) |
| |
|
| | |
| | if moving_part is None: |
| | continue |
| |
|
| | |
| | ungrounded = False |
| | for joint in joint_group.Group: |
| | if hasattr(joint, "ObjectToGround") and joint.ObjectToGround == moving_part: |
| | commands = ( |
| | "doc = App.ActiveDocument\n" |
| | f'doc.removeObject("{joint.Name}")\n' |
| | "doc.recompute()\n" |
| | ) |
| | Gui.doCommand(commands) |
| | ungrounded = True |
| | break |
| | if ungrounded: |
| | continue |
| |
|
| | |
| | createGroundedJoint(moving_part) |
| | App.closeActiveTransaction() |
| |
|
| |
|
| | if App.GuiUp: |
| | Gui.addCommand("Assembly_ToggleGrounded", CommandToggleGrounded()) |
| | Gui.addCommand("Assembly_CreateJointFixed", CommandCreateJointFixed()) |
| | Gui.addCommand("Assembly_CreateJointRevolute", CommandCreateJointRevolute()) |
| | Gui.addCommand("Assembly_CreateJointCylindrical", CommandCreateJointCylindrical()) |
| | Gui.addCommand("Assembly_CreateJointSlider", CommandCreateJointSlider()) |
| | Gui.addCommand("Assembly_CreateJointBall", CommandCreateJointBall()) |
| | Gui.addCommand("Assembly_CreateJointDistance", CommandCreateJointDistance()) |
| | Gui.addCommand("Assembly_CreateJointParallel", CommandCreateJointParallel()) |
| | Gui.addCommand("Assembly_CreateJointPerpendicular", CommandCreateJointPerpendicular()) |
| | Gui.addCommand("Assembly_CreateJointAngle", CommandCreateJointAngle()) |
| | Gui.addCommand("Assembly_CreateJointRackPinion", CommandCreateJointRackPinion()) |
| | Gui.addCommand("Assembly_CreateJointScrew", CommandCreateJointScrew()) |
| | Gui.addCommand("Assembly_CreateJointGears", CommandCreateJointGears()) |
| | Gui.addCommand("Assembly_CreateJointBelt", CommandCreateJointBelt()) |
| | Gui.addCommand("Assembly_CreateJointGearBelt", CommandGroupGearBelt()) |
| |
|