Community
Fusion API and Scripts
Got a new add-in to share? Need something specialized to be scripted? Ask questions or share what you’ve discovered with the community.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Use TextCommands

13 REPLIES 13
Reply
Message 1 of 14
kandennti
3327 Views, 13 Replies

Use TextCommands

Those who are aware of the methods described below feel like they are not here.
I believe that it will bring great benefits to add-in developers and would like to share information.

 

Since Ver2.0.8335, it is possible to use text commands with API with "Application.executeTextCommand".

https://help.autodesk.com/view/fusion360/ENU/?guid=GUID-4DA98A57-C8E0-479E-B2FF-EB3C10BAE13F 

 

The contents described from here are all about the TextCommandS(Txt).
I don't know C++, so it's written in python, but it should be available in C++.

Also, I can't speak English at all. If there is an inappropriate description, it would be helpful if someone could supplement it.

 

〇Display a list of TextCommands

As far as I know, I can hardly find any information about TextCommands.
Probably not a feature for the end user.
Therefore, I discovered it while trying various things. I had a hard time.

 

Here is the command to display all commands and a brief description.

TextCommands.List /hidden

However, this is not necessarily all commands. Because this is displayed.

TextCommands.LoadDll          - [/unload] <FileName> Loads a DLL (that may contain new text commands!)

I can't figure out which DLL file is pointing to.

 

Also, although it is not compared in detail, it seems that the number of commands increases or decreases with each update.
The old version (Ver2_0_8176) is up here. You can understand by comparing them.

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

 

 

〇Execute the "executeTextCommand" method

I have answered several times using "Application.executeTextCommand" in the forum, but I would like to show you how to use it that seems to have merit.

 

PipeFeature Object is provided by API, but it is a typical one that cannot be instantiated.

https://help.autodesk.com/view/fusion360/ENU/?guid=GUID-6449ACAC-F731-4D10-8EC4-8477120B197F 

As you can see, there are no methods like "add" or "create".

 

However, as you can see if you execute the following script, you can create PipeFeature.

#Fusion360API python script
#Author-kantoku
#Description-create PipeFeature sample

import adsk.core, adsk.fusion, traceback

_app = adsk.core.Application.cast(None)
_ui = adsk.core.UserInterface.cast(None)

def run(context):
    try:
        global _app, _ui
        _app = adsk.core.Application.get()
        _ui = _app.userInterface

        # new doc
        _app.documents.add(adsk.core.DocumentTypes.FusionDesignDocumentType)
        des  :adsk.fusion.Design = _app.activeProduct
        des.designType = adsk.fusion.DesignTypes.ParametricDesignType
        root :adsk.fusion.Component = des.rootComponent

        # create sketch
        crv = initSktCircle(root)

        # create pipe
        initPipe(crv)

        # create sketch
        crv = initSktSpline(root)

        # create pipe
        initPipe(crv)

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

def initSktSpline(comp :adsk.fusion.Component):
    skt :adsk.fusion.Sketch = comp.sketches.add(comp.xYConstructionPlane)

    poss = [[-1,2,5], [2,1,0], [0,-4,2]]

    pnt3D = adsk.core.Point3D
    objs = adsk.core.ObjectCollection.create()
    [objs.add(pnt3D.create(x,y,z)) for (x,y,z) in poss]
        
    crvs :adsk.fusion.SketchCurves = skt.sketchCurves
    crv = crvs.sketchFittedSplines.add(objs)

    return crv

def initSktCircle(comp :adsk.fusion.Component):
    skt :adsk.fusion.Sketch = comp.sketches.add(comp.xYConstructionPlane)

    pnt3D = adsk.core.Point3D
    crvs :adsk.fusion.SketchCurves = skt.sketchCurves
    crv = crvs.sketchCircles.addByCenterRadius(pnt3D.create(-5.0,-5,0), 4.0)

    return crv

def initPipe(path):

    sels :adsk.core.Selections = _ui.activeSelections
    sels.clear()
    sels.add(path)

    txtCmds = [
        u'Commands.Start PrimitivePipe', # show dialog
        u'Commands.SetDouble SWEEP_POP_ALONG 1.0', # input distance
        u'Commands.SetDouble SectionRadius 0.5', # input radius
        u'NuCommands.CommitCmd' # execute command
    ]
    
    for cmd in txtCmds:
        _app.executeTextCommand(cmd)

    sels.clear()

1.png

 

13 REPLIES 13
Message 2 of 14
kandennti
in reply to: kandennti

Most are the source code for creating sketches. The part I want to explain is the list "txtCmds" in the initPipe function.

 

・'Commands.Start PrimitivePipe'
"Commands.Start <commandID>" displays a dialog with the specified command ID.
There is a “CommandDefinition.execute” method that performs similar processing, but the execute method is executed collectively after the script ends, whereas “Commands.Start” is executed immediately.
Therefore, it can be used even in the middle of the script.
(This is a big difference)

 

"PrimitivePipe" is the command ID of the pipe command.

 

・'Commands.SetDouble SWEEP_POP_ALONG 1.0'
・'Commands.SetDouble SectionRadius 0.5'
“Commands.SetDouble <commandInputsID> <value>” sets a real number to the Command Inputs of the specified dialog.

2.png

The ID of Command Inputs is like this.
Distance → SWEEP_POP_ALONG
Section Size → SectionRadius

 

 

・'NuCommands.CommitCmd'
This is the process of pressing the OK button in the dialog and executing the command.

3.png

 

 

〇Find ID
To do these things, you need to find the <commandID> or <commandInputsID>.
Next, I will explain how to check these IDs.

 

・commandID
I think there are several ways to check the commandID. Since it's a break, let's use a text command.
4.png
Display the dialog of the arbitrary command, display the TextCommand(Txt), and execute the following.

"UI.CurrentCommandInfo" 

Many characters are output, but you can find "commandID" by checking near the beginning.

 

 

・commandInputsID
You can confirm it by executing "UI.CurrentCommandInfo" in the same way.
(Hidden Inputs are also listed)
The output characters are probably in JSON format.

 

InputsID corresponding to "Distance" displayed in the dialog can be found by searching the output characters.
5.png
In the case of "Distance", it was found in multiple places. What is the desired ID?
...There seems to be no way other than actually trying this.

 

Message 3 of 14
kandennti
in reply to: kandennti

〇Set value
I haven't found everything out, but I think that Commands.Set~ mainly applies.

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

 

6.png

・A
Probably "SelectionCommandInput".
In the first sample, we used the method of selecting the element in advance and calling the command dialog.

 

But if you have multiple SelectionCommandInputs it shouldn't work.
In that case, use "Commands.Select".

Commands.Select <InputsID> <ONK>

 

Commands.Select                        - Select an object using ONK.

What does "ONK" stand for? I didn't understand, but the way to get "ONK" is like this.
1)Select an element.
2)Run the text command "ObjectPaths.Onk".
Characters starting with "ONK::" are output, but all these characters seem to be "ONK".

 

・B
Probably "BoolValueCommandInput".
I will not explain it in particular.

Commands.SetBool <InputsID> <0 or 1>

"0"-ON seems to be "1"-OFF.

 

・C
I was not sure what type this was.
However, it's clear that setting a number is fine.

Commands.SetDouble <InputsID> <double>

In some cases it may be necessary to distinguish between integers and real numbers.

 

・D
Probably "DropDownCommandInput".
I haven't found a way to toggle the value of this Inputs yet.
If anyone is found, it would be very helpful if you could tell me.

 

 

〇Finally
Up to now, I explained the "Pipe" command as an example, but I don't think there is much point in creating a PipeFeature.
Although there is an unknown part and it is incomplete, I think that you can feel that processing equivalent to GUI operation can be performed.
I have not tried it, but I strongly feel that "Is it possible to develop Scripts and Add-ins even in workspaces that do not provide API?"

 

Also, in the above example, I focused on "executing commands", but it seems that TextCommands has many other functions.
Even if you take a quick look at the list
・FusionDoc - It seems to be related to Drawing.
 I have confirmed that it is possible to draw a line using "ExecuteAcadCommand" and it will also be saved to a file.
・PCB
・SheetMetal
・Sim~ - I think it's related to simulation.
Using these not only executes commands,I feel the possibility to get the value in the existing data.

 

However, I felt that there were some things to note when I tried it.
・"TextCommands" are unstable
Is the command usage wrong? Is it a command that doesn't work? There are many things I do not understand.
In addition, Fusion 360 often crashed and no characters were output. (The only way to recover is to restart Fusion 360)

 

If the function is provided as an API object or method, it should be handled by the API.

 

・Changed with Update
Some commands are changed by Update.
Of course, it will be changed without notice, so it seems necessary to check with the latest version.

 

 

 

There are many shortfalls, but thank you for reading the long explanation to the end.
We hope you find it useful in the Scripts and Add-ins you develop in the future.

Message 4 of 14
Anonymous
in reply to: kandennti

Thanks a lot for finding this trick! I want to clarify: how exactly did you output this JSON file?  Or did you just copy-paste everything that was output from 'UI.CurrentCommandInfo'?

Message 5 of 14
kandennti
in reply to: Anonymous

The output from 'UI.CurrentCommandInfo' is
I used the linked service because it was difficult to see.

http://kimihiro-n.site44.com/json_dump/index.html 

 

The service is mainly in Japanese because I am Japanese,

but I'm sure you can find similar services in other languages as well.

Message 6 of 14
Anonymous
in reply to: kandennti

Hey, I also want to clarify on ONK you mentioned. I am trying to use this now with the simulation mode but it is not successful. Basically, what I want is:

(1) user is prompt to select the face (done);

(2) python switches to simulation mode (done); 
(3) python calls on thermal loads commands and now *program waits for input*. What if, for examples, I want to input that face for thermal load? 

I looked up ONK of this face, and it gave me this weird long string: 

CmpInst=Study 1 - Thermal/Cmp=Study 1 - Thermal/CmpInsts/CmpInst=Simulation Model 1:1/Cmp=Simulation Model 1/Bds/Bd=Body2/LeafType:64=(3, -0.19999, 1)

 

Hence, I am unsure what to specify. 
any chance you could help?

 

# Author - Svitlana Midianko
# Description-

import adsk.core, adsk.fusion, adsk.cam, traceback
#import sys
#sys.path.append('/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7')
#import statistics as stats

def executeCommand(str_command, ui):
    cmd = ui.commandDefinitions.itemById(str_command)
    cmd.execute()
    
def run(context):
    '''Main program that is executed when  the script is run from Fusion360 env.'''
    ui = None
    try:
        ### -- SETTING UP: 
        app = adsk.core.Application.get()
        ui  = app.userInterface
        design = app.activeProduct
        # ensuring that there is model built & active:
        if not design:
            ui.messageBox('No active Fusion design', 'No Design')
            return
        # Get the root component of the active design:
        rootComp = design.rootComponent
        holes = rootComp.features.holeFeatures
        ### --

        ### Running simulation with the current design
        app = adsk.core.Application.get()
        ui  = app.userInterface
        selected_face = ui.selectEntity("Please, choose faces which need better heat dissipation.\
             \n If needed, choose all the faces under the upper case.", "Faces")

        ### SIMULATION 
        app.executeTextCommand('Asset.Activate "Simulation Studies"')
        executeCommand('Commands.Select simSelectedEntities CmpInst=Study 1 - Thermal/Cmp=Study 1 - Thermal/CmpInsts/CmpInst=Simulation Model 1:1/Cmp=Simulation Model 1/Bds/Bd=Body2/LeafType:64=(3, -0.19999, 1)', ui)

        #txtCmds = ['SimThermalLoadsCmd', simSelectedEntities  u'NuCommands.CommitCmd'] # those needed to input the thermal loads

        #  for cmd in txtCmds:
        #     executeCommand(cmd, ui)

        executeCommand('SimThermalLoadsCmd', ui)


        ui.messageBox("here")

        
        
 
      


                    

                    

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

            #transform_mat = adsk.core.Matrix3D.create()
            #transform_mat.setToRotation(3.14159, normal, adsk.core.Point3D.create(0,0,0))
            #reversed_normal = normal.transformBy(transform_mat)

 

Also, my design is a very simple box: 

svitlana96MQ7_0-1596571061599.png

 

 

 

Message 7 of 14
kandennti
in reply to: Anonymous

Probably none of us end users know how to do this.

However, there are some things I am working on and feeling.
"It's very difficult to develop."
"It's better to use the API if it's provided in the API."
"Don't write the code out of the blue, test it many times with TextCommands."
"It's about checking them one at a time."


That's what I found out after trying a few things.
This is a good way to switch up your workspace.
        simWs = ui.workspaces.itemById('SimulationEnvironment')
        simWs.activate()
However, you may need to create a Sutdy in advance.

The call to the command dialog should look like this
        app.executeTextCommand('Commands.Start SimThermalLoadsCmd')

But I couldn't find a way to set up "Selection".
1.png
Message 8 of 14
thomasa88
in reply to: kandennti

Interesting!

As a side note, I want to add that if you want to execute() commands you can likely continue after, if you add a callback at the end of the event queue, using app.fireCustomEvent().

Message 9 of 14
thomasa88
in reply to: thomasa88

With regards to DLLs, I did some grepping.

 

It seems that command strings are found in DLLs that have an accompanying XML that looks a bit like this (From %localappdata%\Autodesk\webdeploy\production\857e9b22c3aee8f76d8c95036c0e01aeea4aa86a\NsAppUtils10.xml)

 

<?xml version="1.0" encoding="utf-16" standalone="no"?>
<root DllName="NsAppUtils10" Identifier="AppUtils" IsCoreAddIn="1" IsUIAddIn="0" Name="AppUtils">
  <NeededAddIns>
    <NeededAddIn>Scene</NeededAddIn>
    <NeededAddIn>CommonData</NeededAddIn>
    <NeededAddIn>Body</NeededAddIn>
    <NeededAddIn>Geometry</NeededAddIn>
    <NeededAddIn>Component</NeededAddIn>
    <NeededAddIn>ASMInterface</NeededAddIn>
  </NeededAddIns>
</root>

 

So maybe all of those are loadable? Unfortunately, I have not found any file listing the commands (but if the load, maybe "?" works) and I have not found the files containing the command descriptions.

 

All strings in the DLLs seem to be prefixed with ".?".

Listing of strings in NsDataModel10.dll, starting with AV text, limited to those around CopyPreview. I used the "Git Bash" terminal.

grep -az --color '\.?AV' NsDataModel10.dll | sed 's/\x0/\n/g' | grep -C 10 CopyPreview
.?AVTextCmdPDocumentOpen@?A0x963bc3ae@@
.?AVJSII_neuServeropenDocument@?A0x963bc3ae@@
.?AVTextCmdPDocumentCreate@?A0x963bc3ae@@
.?AVJSII_neuServernewDocument@?A0x963bc3ae@@
.?AVTextCmdPDocumentCloseAll@?A0x963bc3ae@@
.?AVJSII_neuServercloseAllDocuments@?A0x963bc3ae@@
.?AVTextCmdPDocumentGetProperties@?A0x963bc3ae@@
.?AVJSII_neuServergetDocumentProperties@?A0x963bc3ae@@
.?AVTextCmdPDocumentSetProperties@?A0x963bc3ae@@
.?AVJSII_neuServersetDocumentProperties@?A0x963bc3ae@@
.?AVTextCmdPDocumentCopyPreviews@?A0x963bc3ae@@
.?AVTextCmdPDocumentCheckDocumentDirty@?A0x963bc3ae@@
.?AVTestdocumentWorkFlowUnitTests@@
.?AVTestdocumentLoadEmptyBulkDataUnitTests@@
.?AVTestcopyAssetsToDocNonPersistedMembersInAssetUnitTests@@
.?AVTestTestGetDocumentBySessionWideId@@
.?AVTestexternalLinkedFileMgrUnitTests@@
.?AVIDeletable@DataModel@Ns@@
.?AVIExportable@DataModel@Ns@@
.?AVIPasteSink@DataModel@Ns@@
.?AVIPasteSource@DataModel@Ns@@

 

 

 

Message 10 of 14
kandennti
in reply to: thomasa88

Thanks for the information.

 

It's too much for one person to research, and I hope you can gather as much information as possible.

Message 11 of 14
ysz77jp
in reply to: kandennti

Commands.Select <InputsID> <ONK>

I found out that by using Commands,Select, I can specify components such as points and faces using ONK strings. So I also used Commands,Select. However, maybe the ONK itself is not correct, but I could not select it.

There were no spaces in the ONK string, so I just used it.

Also, when the command failed, nothing was displayed in the text command palette. When I type the next command, nothing is displayed.

What I'm trying to do is to input 3 objects in the next operation dialog.

ysz77jp_0-1637128457628.png

I also tried to select last object with a manual command, but no error message appeared and no selection was made.

the command is as follows

"Commands.Select view_origin_point ONK::CmpInst=%28%E6%9C%AA%E4%BF%9D%E5%AD%98%29/Cmp=%28%E6%9C%AA%E4%BF%9D%E5%AD%98%29/Sketches/Sketch=スケッチ1/Point:1:23=(1.2303124999999999,-10.826921201908867,0)"

If anyone has any tips, I'd be happy to hear from anyone who can give me some advice.

 

Message 12 of 14
kandennti
in reply to: ysz77jp

Hi @ysz77jp .

 

I have not found a way to select geometry in CAM.

If you get it right, please leave a note.

Message 13 of 14
ericUAP62
in reply to: kandennti


・D
Probably "DropDownCommandInput".
I haven't found a way to toggle the value of this Inputs yet.
If anyone is found, it would be very helpful if you could tell me.


I found out that you can set the DropDownCommandInput with

Commands.SetString <InputsID> <str>

To find out what string represents the option you want, you can choose the option first, then use "Edit Expression" after clicking the option icon (three points) next to the label .


But the lay out of the commandInput won't change after the edit. Maybe it's dued to not triggering the inputChanged event. I haven't been able to work around that.

---

@kandennti 

Thank you so much for your research and share

Message 14 of 14
kandennti
in reply to: ericUAP62

Hi @ericUAP62 .

 

Thanks for the valuable information.
Actually, there is a continuing topic.

https://forums.autodesk.com/t5/fusion-360-api-and-scripts/use-textcommands2/m-p/9937161 

 

@thomasa88 found important information and investigated further.

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report