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: 

Moving selected bodies to a single new component

6 REPLIES 6
Reply
Message 1 of 7
darran
812 Views, 6 Replies

Moving selected bodies to a single new component

 
I have a component with lots and lots of constituent bodies. I'm trying to write a script – and its my first so please bear with me – that moves all currently selected bodies into a new component under the root level. For example, I want to be able to click on a handful of bodies out of the many, run the script and see a new component created with the selected bodies now moved within this new component.
 
It seems pretty straight forward. And I can do it in Python via the "View | Text Commands" dialog. But I can't reliably do it via the script below. Sometimes it works ... and then on the next selection and run, it doesn't. It doesn't help that I can't seem to log the script output to aid in debugging.
 
Can someone please take a look and point out my error?
 

 

from adsk.core import *
from adsk.fusion import *
import traceback

try:
    app = adsk.core.Application.get() 
    ui  = app.userInterface 
    design = adsk.fusion.Design.cast(app.activeProduct) 
    root = design.rootComponent 

    # empty list to contain references to selected bodies
    bodies = []

    # iterate over all selections (which may or may not be Bodies)
    for selection in ui.activeSelections:

    	entity = selection.entity 
    	if entity.objectType == adsk.fusion.BRepBody.classType():
            bodies.append(entity)

    # if there are bodies to move, create a new child component under the top level
    if len(bodies):
        occurence = root.occurrences.addNewComponent(adsk.core.Matrix3D.create()) 
        occurence.isLightBulbOn = False

        for body in bodies:
    		body.moveToComponent(occurence) 
            
except:
    ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

 

6 REPLIES 6
Message 2 of 7
kandennti
in reply to: darran

Hi @darran .

 

Requires a "run" function.

from adsk.core import *
from adsk.fusion import *
import traceback

def run(context):
    try:
        app = adsk.core.Application.get() 
・・・

 

Message 3 of 7
darran
in reply to: kandennti

Hmm, I thought use of the run function was only required for Add-ins, and was optional for Scripts. Anyway, I've updated the code to that shown below. Unfortunately I wasn't seeing anything happen when launching the script ... so I added the messageBox to get some visual feedback. And it doesn't show either ... which makes me think that either (i) Fusion isn't picking up the changes to the script; or (ii) there's a syntax error in the script that prevents execution. 

 

 

from adsk.core import *
from adsk.fusion import *
import traceback

def run(context):

    app = adsk.core.Application.get() 
    ui  = app.userInterface 
    ui.messageBox("Here we go ...")

    try:
        design = adsk.fusion.Design.cast(app.activeProduct) 
        root = design.rootComponent 

        # empty list to contain reference to selected bodies
        bodies = []

        # iterate over all selections (which may or may not be Bodies)
        for selection in ui.activeSelections:

        	entity = selection.entity 
        	if entity.objectType == adsk.fusion.BRepBody.classType():
                bodies.append(entity)

        # if there are bodies to move, create a new child component under the top level
        if len(bodies):
            occurence = root.occurrences.addNewComponent(adsk.core.Matrix3D.create()) 
            occurence.isLightBulbOn = False

            for body in bodies:
        		body.moveToComponent(occurence) 

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

 

 

Message 4 of 7
darran
in reply to: darran

Okay, I found and resolved the issue ... but I don't really understand why it happens. The issue is trying to add entity objects to a python list that isn't created as a global variable. Here's the code that now works:

 

 

 

from adsk.core import *
from adsk.fusion import *
import traceback

# empty list to contain reference to selected bodies
# for some reason this needs to be a global variable
bodies = []

def run(context):

    try:

        app = adsk.core.Application.get() 
        ui  = app.userInterface 
        design = adsk.fusion.Design.cast(app.activeProduct) 
        root = design.rootComponent 

        # iterate over all selections (which may or may not be Bodies)
        for selection in ui.activeSelections:
            entity = selection.entity
            if entity.objectType == adsk.fusion.BRepBody.classType():
                bodies.append(entity)

        # if there are bodies to move, create a new child component under the top level
        if len(bodies):
            occurence = root.occurrences.addNewComponent(adsk.core.Matrix3D.create())
            occurence.isLightBulbOn = False

            for body in bodies:
                body.moveToComponent(occurence)
            
    except:
        ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

 

 

I can't see anything implying that the above is required in the Python-specific documentation.

 

Message 5 of 7
adminTCYL2
in reply to: darran

This is a nice peace of code and I used it to bring lots of bodies out of a component in lots of new occurences each for one body. 
But I want to give the new components the name of the bodies (they are all named).
How can I do this? 
And why does the code not run without that bodies-array?... (the two lines that I comanded out.) 

bodies = []
            for i in range(0,len(new_component.bRepBodies)):  
                body = new_component.bRepBodies[i]
                #bodies.append(body)
            #for body in bodies:
                occurence = root_comp.occurrences.addNewComponent(adsk.core.Matrix3D.create())
                body.moveToComponent(occurence)
                _ui.messageBox(body.name)



Message 6 of 7
BrianEkins
in reply to: adminTCYL2

I don't know what the original problem with the list was because when I try the original code it works fine for me.

 

As far as setting the name of the new component just add the second line shown below.

 

occurence = root_comp.occurrences.addNewComponent(adsk.core.Matrix3D.create())
occurence.component.name = body.name

 

 

---------------------------------------------------------------
Brian Ekins
Inventor and Fusion 360 API Expert
Website/Blog: https://EkinsSolutions.com
Message 7 of 7
adminTCYL2
in reply to: BrianEkins

I found a working way by myself now. The failure seems the i in new_component.bRepBodies[i]
What I do is: I take 5 Bodies that are in a box named "new_component" in five seperat boxes. 
So I take the first and put it in the first box. 
Now I say: "take the second and put it in the second box"--- but the computer takes the third. Why? Because there are only 4 Bodies in the box anymore and the second of these was the third at the beginning. 

The right way is allways to take the first named new_component.bRepBodies[0]
Here is the corrected skript: 

----
def BodiesToComponents():
    j = len(new_component.bRepBodies)   
    for i in range(0,j):  
        body = new_component.bRepBodies[0]
        new_occurrence = root_comp.occurrences.addNewComponent(adsk.core.Matrix3D.create())
        new_occurrence.component.name = body.name
        body.moveToComponent(new_occurrence)
----

 

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

Post to forums  

Autodesk DevCon in Munich May 28-29th


Autodesk Design & Make Report