I'm am trying to create a simple command to move a Brep body inside a component that will snap a triad to the center of the selected cylinder. I am not sure what I am doing wrong, the translation works correctly but when I try to rotate, it behaves unexpectedly.
import adsk.core,adsk.fusion,adsk.cam,traceback
from ...lib import fusion360utils as futil
app = adsk.core.Application.get()
ui = app.userInterface
local_handlers = []
activeBody:adsk.fusion.BRepBody = None
def command_created(args: adsk.core.CommandCreatedEventArgs):
'''Function that is called when a user clicks the corresponding button in the UI. This defines the contents of the command dialog and connects to the command related events.'''
cmd = args.command
inputs = cmd.commandInputs
cmd.setDialogSize(300,0)
cmd.isPositionDependent = True
selection = inputs.addSelectionInput("brepSelector","Part Selection","")
selection.addSelectionFilter("SolidBodies")
selection.setSelectionLimits(1,1)
#Triad Control
triad = cmd.commandInputs.addTriadCommandInput("partTransformer",adsk.core.Matrix3D.create())
triad.setFullVisibility(False)
triad.setPlanarMoveVisibility(True)
triad.setRotateVisibility(True)
futil.add_handler(args.command.execute, command_execute, local_handlers=local_handlers)
futil.add_handler(args.command.destroy, command_destroy, local_handlers=local_handlers)
futil.add_handler(args.command.executePreview, command_preview, local_handlers=local_handlers)
futil.add_handler(args.command.inputChanged, command_inputChanged, local_handlers=local_handlers)
def command_execute(args: adsk.core.CommandEventArgs):
global activeBody
triad:adsk.core.TriadCommandInput = args.command.commandInputs.itemById("partTransformer")
move = activeBody.parentComponent.features.moveFeatures
objects = adsk.core.ObjectCollection.create()
objects.add(activeBody)
moveInput = move.createInput2(objects)
moveInput.defineAsFreeMove(triad.transform)
move.add(moveInput)
def command_inputChanged(args: adsk.core.InputChangedEventArgs):
global activeBody
inputs = args.inputs
triad:adsk.core.TriadCommandInput = inputs.itemById("partTransformer")
selector:adsk.core.SelectionCommandInput = inputs.itemById("brepSelector")
#get the selected cylinder and position the traid on the center
if args.input == selector:
selectedBody = selector.selection(0).entity
if selectedBody != activeBody:
activeBody = selectedBody
for face in activeBody.faces:
if face.geometry.surfaceType == adsk.core.SurfaceTypes.CylinderSurfaceType:
cylinderFace = face
if face.geometry.surfaceType == adsk.core.SurfaceTypes.PlaneSurfaceType:
app.log("found flat")
planeFace = face
origin = cylinderFace.centroid
vector = planeFace.geometry.evaluator.getNormalAtPoint(planeFace.centroid)[1]
mat = adsk.core.Matrix3D.create()
mat.setToRotateTo(adsk.core.Vector3D.create(0,0,1),vector)
mat.translation = adsk.core.Point3D.create(0,0,0).vectorTo(origin)
triad.transform = mat
def command_preview(args: adsk.core.CommandEventArgs):
global activeBody
try:
triad:adsk.core.TriadCommandInput = args.command.commandInputs.itemById("partTransformer")
#get the change that occurred in the triad
fo,fx,fy,fz = triad.lastTransform.getAsCoordinateSystem()
to,tx,ty,tz = triad.transform.getAsCoordinateSystem()
transform = adsk.core.Matrix3D.create()
transform.setToAlignCoordinateSystems(fo,fx,fy,fz,to,tx,ty,tz)
#move the activeBody by the transform
move = activeBody.parentComponent.features.moveFeatures
objects = adsk.core.ObjectCollection.create()
objects.add(activeBody)
moveInput = move.createInput2(objects)
moveInput.defineAsFreeMove(transform)
move.add(moveInput)
#Reposition the triad on the center of the cylinder
for face in activeBody.faces:
if face.geometry.surfaceType == adsk.core.SurfaceTypes.CylinderSurfaceType:
cylinderFace = face
if face.geometry.surfaceType == adsk.core.SurfaceTypes.PlaneSurfaceType:
planeFace = face
origin = cylinderFace.centroid
vector = planeFace.centroid.vectorTo(origin)
mat = adsk.core.Matrix3D.create()
mat.setToRotateTo(adsk.core.Vector3D.create(0,0,1),vector)
mat.translation = adsk.core.Point3D.create(0,0,0).vectorTo(origin)
triad.transform = mat
except:
app.log('Failed:\n{}'.format(traceback.format_exc()))
def command_destroy(args: adsk.core.CommandEventArgs):
global local_handlers,activeBody
local_handlers = []
activeBody = None
app.log("Complete")
Solved! Go to Solution.
Solved by kandennti. Go to Solution.
Hi @Joshua.mursic -San.
The cause is the transaction of the executePreview event.
After moving and then rotating, it appears to be reverting back to its pre-move state.
If you record and use the matrix3D when the body is selected, you should be able to get the desired movement.
# Matrix3D when body is selected
_mat: adsk.core.Matrix3D = None
def command_created(args: adsk.core.CommandCreatedEventArgs):
'''Function that is called when a user clicks the corresponding button in the UI. This defines the contents of the command dialog and connects to the command related events.'''
cmd = args.command
inputs = cmd.commandInputs
cmd.setDialogSize(300,0)
cmd.isPositionDependent = True
selection = inputs.addSelectionInput("brepSelector","Part Selection","")
selection.addSelectionFilter("SolidBodies")
selection.setSelectionLimits(1,1)
#Triad Control
triad = cmd.commandInputs.addTriadCommandInput("partTransformer",adsk.core.Matrix3D.create())
triad.setFullVisibility(False)
triad.setPlanarMoveVisibility(True)
triad.setRotateVisibility(True)
# futil.add_handler(args.command.execute, command_execute, local_handlers=local_handlers)
futil.add_handler(args.command.destroy, command_destroy, local_handlers=local_handlers)
futil.add_handler(args.command.executePreview, command_preview, local_handlers=local_handlers)
futil.add_handler(args.command.inputChanged, command_inputChanged, local_handlers=local_handlers)
# def command_execute(args: adsk.core.CommandEventArgs):
# global activeBody
# triad:adsk.core.TriadCommandInput = args.command.commandInputs.itemById("partTransformer")
# move = activeBody.parentComponent.features.moveFeatures
# objects = adsk.core.ObjectCollection.create()
# objects.add(activeBody)
# moveInput = move.createInput2(objects)
# moveInput.defineAsFreeMove(triad.transform)
# move.add(moveInput)
def command_inputChanged(args: adsk.core.InputChangedEventArgs):
global activeBody
inputs = args.inputs
triad:adsk.core.TriadCommandInput = inputs.itemById("partTransformer")
selector:adsk.core.SelectionCommandInput = inputs.itemById("brepSelector")
#get the selected cylinder and position the traid on the center
if args.input == selector:
selectedBody = selector.selection(0).entity
if selectedBody != activeBody:
activeBody = selectedBody
for face in activeBody.faces:
if face.geometry.surfaceType == adsk.core.SurfaceTypes.CylinderSurfaceType:
cylinderFace = face
if face.geometry.surfaceType == adsk.core.SurfaceTypes.PlaneSurfaceType:
app.log("found flat")
planeFace = face
origin = cylinderFace.centroid
vector = planeFace.geometry.evaluator.getNormalAtPoint(planeFace.centroid)[1]
mat = adsk.core.Matrix3D.create()
mat.setToRotateTo(adsk.core.Vector3D.create(0,0,1),vector)
mat.translation = adsk.core.Point3D.create(0,0,0).vectorTo(origin)
triad.transform = mat
global _mat
_mat = mat
def command_preview(args: adsk.core.CommandEventArgs):
global activeBody
try:
triad:adsk.core.TriadCommandInput = args.command.commandInputs.itemById("partTransformer")
#get the change that occurred in the triad
# fo,fx,fy,fz = triad.lastTransform.getAsCoordinateSystem()
global _mat
fo,fx,fy,fz = _mat.getAsCoordinateSystem()
to,tx,ty,tz = triad.transform.getAsCoordinateSystem()
transform = adsk.core.Matrix3D.create()
transform.setToAlignCoordinateSystems(fo,fx,fy,fz,to,tx,ty,tz)
#move the activeBody by the transform
move = activeBody.parentComponent.features.moveFeatures
objects = adsk.core.ObjectCollection.create()
objects.add(activeBody)
moveInput = move.createInput2(objects)
moveInput.defineAsFreeMove(transform)
move.add(moveInput)
#Reposition the triad on the center of the cylinder
for face in activeBody.faces:
if face.geometry.surfaceType == adsk.core.SurfaceTypes.CylinderSurfaceType:
cylinderFace = face
if face.geometry.surfaceType == adsk.core.SurfaceTypes.PlaneSurfaceType:
planeFace = face
origin = cylinderFace.centroid
vector = planeFace.centroid.vectorTo(origin)
mat = adsk.core.Matrix3D.create()
mat.setToRotateTo(adsk.core.Vector3D.create(0,0,1),vector)
mat.translation = adsk.core.Point3D.create(0,0,0).vectorTo(origin)
triad.transform = mat
args.isValidResult = True
except:
app.log('Failed:\n{}'.format(traceback.format_exc()))
def command_destroy(args: adsk.core.CommandEventArgs):
global local_handlers,activeBody
local_handlers = []
activeBody = None
app.log("Complete")
Can't find what you're looking for? Ask the community or share your knowledge.