Announcements
Attention for Customers without Multi-Factor Authentication or Single Sign-On - OTP Verification rolls out April 2025. Read all about it here.

Align face to XY axis - just need the last step

aelqabbany
Advocate

Align face to XY axis - just need the last step

aelqabbany
Advocate
Advocate

Hi,

 

I am trying to align the largest face of a body to the root component's XY axis. The script works wonderfully, if not for the dialog box at the end. How can I get Fusion360 to execute the command without any pop-ups?

 

Much appreciated.

import adsk.core, adsk.fusion, adsk.cam, traceback

def run(context):
    ui = None
    try:
        app = adsk.core.Application.get()
        ui  = app.userInterface 
        des = app.activeProduct
        rootComp = des.rootComponent
        TargetBody = rootComp.bRepBodies.item(0)

        maxface = 0
        maxfacearea = 0
        for bFace in TargetBody.faces:
            if bFace.geometry.objectType == adsk.core.Plane.classType() and bFace.area > maxfacearea:
                print(str(bFace.area) + bFace.objectType)
                maxfacearea = bFace.area
                maxface = bFace
        
        ui.activeSelections.clear
        ui.activeSelections.add(maxface)
        ui.activeSelections.add(rootComp.xYConstructionPlane)
        alignCommand = ui.commandDefinitions.itemById(id="AlignCmd")
        alignCommand.execute()
        #The issue occurs here. How do I have the script move past the dialog box?
         

    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
0 Likes
Reply
Accepted solutions (3)
438 Views
7 Replies
Replies (7)

j.han97
Advocate
Advocate
Accepted solution

Hi @aelqabbany ,

 

I have managed to make your script work but with some limitations. First and foremost, this line of code is used to replace the action of clicking 'Ok' button:

app.executeTextCommand('Commands.Start CommitCommand')

which utilize the text command. Note that text commands are not officially supported and subject to change in future versions. (I expected getting the CommitCommand through ui.commandDefinitions and executing it will work, but it doesn't).

 

Second, I guess that the AlignCmd needs one more input to fully define its operation: the object type. Searching through the list of command definitions, I found these: AlignComponentsCmd and AlignGeometryCmd alongside with AlignCmd. They should correspond to the 'Components' or 'Bodies' input of the AlignCmd. Since your target is a body in this case, I used AlignGeometryCmd, and it worked as expected.

 

Summary:

1. Execute CommitCommand works only through text command, which could change in future versions (Prone to error).

2. For the AlignCmd, the object type needs to be known (although not difficult) before calling the correct align command.

 

Below is the code:

import adsk.core, adsk.fusion, adsk.cam, traceback

def run(context):
    ui = None
    try:
        app = adsk.core.Application.get()
        ui  = app.userInterface 
        des = app.activeProduct
        rootComp = des.rootComponent
        TargetBody = rootComp.bRepBodies.item(0)

        maxface = 0
        maxfacearea = 0
        for bFace in TargetBody.faces:
            if bFace.geometry.objectType == adsk.core.Plane.classType() and bFace.area > maxfacearea:
                print(str(bFace.area) + bFace.objectType)
                maxfacearea = bFace.area
                maxface = bFace
        
        ui.activeSelections.clear
        ui.activeSelections.add(maxface)
        ui.activeSelections.add(rootComp.xYConstructionPlane)
        #Use AlignGeometryCmd for bodies, AlignComponentsCmd for components
        alignCommand = ui.commandDefinitions.itemById(id="AlignGeometryCmd")
        alignCommand.execute()
        
        #Commit Command is equivalent to clicking OK
        #But this does not work
        #ui.commandDefinitions.itemById('CommitCommand').execute()
        app.executeTextCommand('Commands.Start CommitCommand') #Text command works
        
    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

 

1 Like

aelqabbany
Advocate
Advocate
Thank you very much for the solution and for the explanation.

I spent hours searching for a command to click okay. Do you have a resource where I can read more about it?

I really appreciate it!
0 Likes

j.han97
Advocate
Advocate
Accepted solution

As far as I know there is no documented introduction to all the command definitions. There are two ways to study them:

 

1. Print all command definitions to file. This one is pretty simple, you just access the command definitions with:

allCommandDefinitons = ui.commandDefinitions

  Then you can output their names/ids/other properties.

 

2. Monitor what command is being called. You can add a handler to ui.commandStarting event and print the triggered command. A simple add-in as follow will do:

import adsk.core, adsk.fusion, adsk.cam, traceback

class commandStartingHandler(adsk.core.ApplicationCommandEventHandler):
    def __init__(self):
        super().__init__()
    
    def notify(self, args):
        eventArgs = adsk.core.ApplicationCommandEventArgs.cast(args)
        _app.log('Command triggered: %s'%eventArgs.commandId)

_app: adsk.core.Application = adsk.core.Application.get()
_ui: adsk.core.UserInterface = _app.userInterface
_handlers = []

def run(context):
    try:
        onCommandStarting = commandStartingHandler()
        _ui.commandStarting.add(onCommandStarting)
        _handlers.append(onCommandStarting)
        

    except:
        if _ui:
            _ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

def stop(context):
    try:
        _ui.messageBox('Stop addin')

    except:
        if _ui:
            _ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

 

You will need to open the text command window (output is printed here) and perform actions manually on the user interface. Then just read the output to check which command is triggered.

 

Hope this helps!

1 Like

aelqabbany
Advocate
Advocate
Thank you again. You are my hero!
0 Likes

aelqabbany
Advocate
Advocate

I had a follow-up question @j.han97.

 

This command seems to work the first time in the script only.

 

app.executeTextCommand('Commands.Start CommitCommand')

 

 

I am performing three body alignment actions in the script below, and the script only performs the first alignment correctly. However, if I comment out any two alignments, the third works fine. I've tried waiting a few seconds (

time.sleep(2)) and running a adsk.doEvents() between commands, but neither worked.
 

 

import adsk.core, adsk.fusion, adsk.cam, traceback
import time

def run(context):
    ui = None
    try:
        app = adsk.core.Application.get()
        ui  = app.userInterface 
        des = app.activeProduct
        rootComp = des.rootComponent
        TargetBody = rootComp.bRepBodies.item(0)

        maxface = 0
        maxfacearea = 0
        for bFace in TargetBody.faces:
            if bFace.geometry.objectType == adsk.core.Plane.classType() and bFace.area > maxfacearea:
                print(str(bFace.area) + bFace.objectType)
                maxfacearea = bFace.area
                maxface = bFace
        
        maxline = 0
        maxlinelen = 0
        for bline in maxface.edges:
            if bline.length > maxlinelen:
                print(str(bline.length) + bline.objectType)
                maxlinelen = bline.length
                maxline = bline
        
        oVertex = bline.startVertex
        
        ui.activeSelections.clear
        ui.activeSelections.add(oVertex)
        ui.activeSelections.add(rootComp.originConstructionPoint)
        alignCommand = ui.commandDefinitions.itemById(id="AlignGeometryCmd")
        alignCommand.execute()
        app.executeTextCommand('Commands.Start CommitCommand') 
        
        adsk.doEvents() #This didn't work
        time.sleep(2) #Neither did this

        ui.activeSelections.clear
        ui.activeSelections.add(maxface)
        ui.activeSelections.add(rootComp.xYConstructionPlane)
        alignCommand = ui.commandDefinitions.itemById(id="AlignGeometryCmd")
        alignCommand.execute()
        app.executeTextCommand('Commands.Start CommitCommand') 
        
        adsk.doEvents() #This didn't work
        time.sleep(2) #Neither did this
        
        ui.activeSelections.clear
        ui.activeSelections.add(bline)
        ui.activeSelections.add(rootComp.xConstructionAxis)
        alignCommand = ui.commandDefinitions.itemById(id="AlignGeometryCmd")
        alignCommand.execute()
        app.executeTextCommand('Commands.Start CommitCommand') 

    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

 

0 Likes

kandennti
Mentor
Mentor
Accepted solution

Hi @aelqabbany .

 

CommandDefinitions.execute method are executed together just before the end of the script. This seems to be a specification of the API.

 

If you want to execute the command in the middle of the process, you can do the following to invoke the command at the intended timing.

Application.executeTextCommand('Commands.Start <Command ID>')

 

In this case, you can do it like this.

・・・
        ui.activeSelections.add(rootComp.xYConstructionPlane)
        # alignCommand = ui.commandDefinitions.itemById(id="AlignGeometryCmd")
        # alignCommand.execute()
        app.executeTextCommand('Commands.Start AlignGeometryCmd')
        app.executeTextCommand('Commands.Start CommitCommand')
・・・

 

You can find some useful information at this link.

https://github.com/kantoku-code/Fusion360_Small_Tools_for_Developers/tree/master/TextCommands 

 

For text commands, you will not get any official announcements.
The only way is for us users to share information with each other, so if you find out something, please leave it in the forum.
This will help those who want to do the same process later on.

 

2 Likes

aelqabbany
Advocate
Advocate

Thank you very much!

0 Likes