Announcements
Autodesk Community will be read-only between April 26 and April 27 as we complete essential maintenance. We will remove this banner once completed. Thanks for your understanding

Is it possible to use text command within a script to run the meshbody cut command

yosef.ali.omar
Participant

Is it possible to use text command within a script to run the meshbody cut command

yosef.ali.omar
Participant
Participant

Hi 

I am trying to create a script that takes in a meshbody and use the plane cut command that is available in the UI. However I am very new to the F360 API and don't know the text command for this feature. I have went through some resources in the forum but couldn't find a list of text commands where this mesh body plane cut is available. 

 

can some one guide me into this realm, oh wise shamans show us the way 

0 Likes
Reply
Accepted solutions (1)
1,000 Views
4 Replies
Replies (4)

yosef.ali.omar
Participant
Participant

I am trying to run a automated command of the meshbodycut command avaliable in the UI 

I took this code from the forum 

 

def  _MeshPlaneCutCommand (
            self,
            mesh: adsk.fusion.MeshBody,
            plane: adsk.fusion.ConstructionPlanešŸ˜ž

            app: adsk.core.Application = adsk.core.Application.get ()
            ui: adsk.core.UserInterface = app.userInterface
            sels: adsk.core.Selections = ui.activeSelections

            sels.clear ()
            app.executeTextCommand ( u'Commands.Start MeshPlaneCutCommand' )

            app.executeTextCommand ( u'UI.EnableCommandInput MeshPlaneCutBodySel' )
            sels.add (mesh)

            app.executeTextCommand ( u'UI.EnableCommandInput MeshPlaneCutPlaneSel' )
            sels.add (plane)

            app.executeTextCommand ( u'Commands.SetString infoCutType MeshPlaneCutSplitBody' )
            app.executeTextCommand ( u'Commands.SetString infoFillType MeshPlaneCutFillNone' )

            app.executeTextCommand ( u'NuCommands.CommitCmd' )
 
 
however the command is simply not executing, I am creating a plane using API calls then using that plane in the 
function above, but it is not executing the cut, the plane gets created and all 
0 Likes

kandennti
Mentor
Mentor
Accepted solution

Hi @yosef.ali.omar .

 

I believe all the command IDs, etc. were changed when the mesh function switched from preview function to official function.

We have corrected this so that it will still function in Ver 2.0.12392.

 

# Fusion360API Python script
# Author-kantoku
# Description-Split Mesh and convert to BRepBody

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
        des :adsk.fusion.Design = _app.activeProduct

        if des.designType == adsk.fusion.DesignTypes.ParametricDesignType:
            query = _ui.messageBox(
                'Switch to direct mode.\nIs it OK?',
                'Need to switch to direct mode',
                adsk.core.MessageBoxButtonTypes.OKCancelButtonType,
                adsk.core.MessageBoxIconTypes.QuestionIconType)

            if query == adsk.core.DialogResults.DialogCancel:
                return
            else:
                des.designType = adsk.fusion.DesignTypes.DirectDesignType

        msg :str = 'Please select a mesh body!'
        selFiltter :str = 'MeshBodies'
        sel :adsk.core.Selection = selectEnt(msg ,selFiltter)
        if not sel: return
        mesh = sel.entity

        fact = Mesh2BRepFactry(mesh)
        bodies = fact.toBrep()

        _ui.messageBox(f'{len(bodies)} BRep body created')

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

def selectEnt(
    msg :str, 
    filtterStr :str
    ) -> adsk.core.Selection :

    try:
        sel = _ui.selectEntity(msg, filtterStr)
        return sel
    except:
        return None


class Mesh2BRepFactry:
    def __init__(self, mesh :adsk.fusion.MeshBody):
        self.mesh = mesh

    def toBrep(self, maxCount = 10000) -> list:
        comp :adsk.fusion.Component = self.mesh.parentComponent

        if maxCount > 10000:
            maxCount = 10000

        # split
        meshLst = self._MeshsSplit(self.mesh, maxCount)

        # toBrep
        return self._Mesh2BRepCommand(meshLst)


    def _Mesh2BRepCommand(
        self,
        meshLst :list) -> list:

        app :adsk.core.Application = adsk.core.Application.get()
        ui :adsk.core.UserInterface = app.userInterface
        sels :adsk.core.Selections = ui.activeSelections
        comp :adsk.fusion.Component = self.mesh.parentComponent
        exceptionLst = [b for b in comp.bRepBodies]

        for mesh in meshLst:
            sels.clear()
            sels.add(mesh)
            app.executeTextCommand(u'Commands.Start ParaMeshConvertCommand')
            app.executeTextCommand(u'NuCommands.CommitCmd')

            adsk.doEvents()
        
        return self._list_difference([b for b in comp.bRepBodies], exceptionLst)


    def _MeshsSplit(
        self,
        mesh :adsk.fusion.MeshBody,
        maxCount) -> list:

        comp :adsk.fusion.Component = self.mesh.parentComponent

        meshLst = [self.mesh]

        exceptionLst = [m for m in comp.meshBodies]
        exceptionLst.remove(self.mesh)

        global _app
        reOpeFG = False
        while True:
            for mesh in meshLst:
                _app.log(f'{mesh.name}:{mesh.displayMesh.triangleCount}')

                if maxCount < mesh.displayMesh.triangleCount:
                    tool :adsk.fusion.ConstructionPlane = self._getSplitPlane(mesh)
                    self._MeshPlaneCutCommand(mesh, tool)
                    tool.deleteMe()
                    reOpeFG = True

                adsk.doEvents()
            
            if reOpeFG:
                meshLst = self._list_difference([m for m in comp.meshBodies], exceptionLst)
                reOpeFG = False
            else:
                break
        
        return meshLst


    def  _MeshPlaneCutCommand(
        self,
        mesh: adsk.fusion.MeshBody,
        plane: adsk.fusion.ConstructionPlane):

        app: adsk.core.Application = adsk.core.Application.get()
        ui: adsk.core.UserInterface = app.userInterface
        sels: adsk.core.Selections = ui.activeSelections

        sels.clear()
        app.executeTextCommand(u'Commands.Start ParaMeshPlaneCutCommand')

        app.executeTextCommand(u'UI.EnableCommandInput infoBodyToModify')
        sels.add(mesh)

        app.executeTextCommand(u'UI.EnableCommandInput planeSelectionInfo')
        sels.add(plane)

        app.executeTextCommand(u'Commands.SetString infoCutType infoCutTypeSplitBody')
        app.executeTextCommand(u'Commands.SetString infoFillType infoFillTypeNoFill')

        app.executeTextCommand(u'NuCommands.CommitCmd')


    def _list_difference(self, list1, list2):
        result = list1.copy()
        for value in list2:
            if value in result:
                result.remove(value)

        return result


    def _getSplitPlane(
        self,
        mesh :adsk.fusion.MeshBody) -> adsk.fusion.ConstructionPlane:

        comp :adsk.fusion.Component = mesh.parentComponent

        pnts = [p for p in mesh.displayMesh.nodeCoordinates]
        bound = adsk.core.BoundingBox3D.create(pnts[0], pnts[1])
        for p in pnts[2:]:
            bound.expand(p)

        pntMin :adsk.core.Point3D = bound.minPoint
        pntMax :adsk.core.Point3D = bound.maxPoint

        pntMid = adsk.core.Point3D.create(
            (pntMin.x + pntMax.x) * 0.5,
            (pntMin.y + pntMax.y) * 0.5,
            (pntMin.z + pntMax.z) * 0.5)

        width = [abs(pntMax.x) + abs(pntMin.x), comp.xConstructionAxis]
        length = [abs(pntMax.y) + abs(pntMin.y), comp.yConstructionAxis]
        height = [abs(pntMax.z) + abs(pntMin.z), comp.zConstructionAxis]

        direction = max([width, length, height], key=(lambda x: x[0]))

        plane = adsk.core.Plane.create(pntMid, direction[1].geometry.direction)
        conPlanes :adsk.fusion.ConstructionPlanes = comp.constructionPlanes
        planeIpt :adsk.fusion.ConstructionPlaneInput = conPlanes.createInput()
        planeIpt.setByPlane(plane)

        return conPlanes.add(planeIpt)
0 Likes

yosef.ali.omar
Participant
Participant

@kandennti 

Thank you very much, yes after editing the text command it works fine. However, how can one know the new text commands is there a document or a github page that details the text commands for features, I have already looked at the document prepared by you "Text Commands 2" but how about the text commands inside a feature like what happened with meshbodycutplane where the problem was the text commands to specify the mesh, plane, and cut type 

 

I apologize if my English is terrible 

0 Likes

kandennti
Mentor
Mentor

@yosef.ali.omar .

 

The method for obtaining a command list of text commands is described here.

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

Unfortunately, we also wrote a topic called "Use TextCommands" but it seems to have been removed.

 

You can use this add-in and save the list to a file by pressing this button.

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

1.png

 

 

 

This is basically how to invoke a command using the command ID.

    app: adsk.core.Application = adsk.core.Application.get()
    ui: adsk.core.UserInterface = app.userInterface

    cmdDef: adsk.core.CommandDefinition = ui.commandDefinitions.itemById('**Command_ID**')
    if cmdDef:
        cmdDef.execute()

However, this method calls the commands together at the end of the script, so they cannot be called at the required timing.

 

Therefore, the following method can be used to call the commands at the necessary timing.

    app: adsk.core.Application = adsk.core.Application.get()
    app.executeTextCommand(u'Commands.Start **Command_ID**')

 

For '**Command_ID**', if you turn on the add-in here and actually operate the GUI, it will output the command name and command ID to the text command window.

1.png

 

You can also check the '**Command_ID**' by clicking this button in the add-in.

https://github.com/AutodeskFusion360/Fusion360DevTools 

1.png

0 Likes