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: 

Error while setting transform in Occurrences.addNewComponentCopy

13 REPLIES 13
SOLVED
Reply
Message 1 of 14
brent.hagany
524 Views, 13 Replies

Error while setting transform in Occurrences.addNewComponentCopy

I'm pretty new to the API, and only barely understand proxies, so I'm hoping that there is a simple solution that I've overlooked.  When I am dealing with occurrences that are direct children of the root component, I have no issues with setting their transform2 properties directly, or with adding new component copies via the Occurrences.addNewComponentCopy method.

 

However, when I am dealing with occurrences that are nested within other occurrences (that is, not direct children of the root component), I begin to encounter issues with transform2.  I believe I have figured out how to make this work using a proxy occurrence when setting transform2 directly, but I get the same transform error when using addNewComponentCopy in a nested occurrence, and I don't see a way around this.

 

I've created a minimal script that demonstrates the problem:

 

import adsk.core, adsk.fusion, traceback, math


def run(context):
    ui = None
    try:
        app = adsk.core.Application.get()
        ui  = app.userInterface

        ###
        # setting up parent and child occurrences / components
        ###
        rootComponent = app.activeProduct.rootComponent
        parentOccurrence = rootComponent.occurrences.addNewComponent(adsk.core.Matrix3D.create())
        parentComponent = parentOccurrence.component
        childOccurrence = parentComponent.occurrences.addNewComponent(adsk.core.Matrix3D.create())


        ###
        # here's the demonstration part
        ###

        # setting transform works
        childOccurrence.transform = adsk.core.Matrix3D.create()

        # setting transform2 fails with
        # "RuntimeError: 3 : transform overrides can only be set on Occurrence proxy from root component"
        childOccurrence.transform2 = adsk.core.Matrix3D.create()

        # setting transform2 won't work unless I create a proxy occurrence
        # this works, but I'm not sure it's completely correct
        childOccurrenceProxy = childOccurrence.createForAssemblyContext(parentOccurrence)
        childOccurrenceProxy.transform2 = adsk.core.Matrix3D.create()

        # however, using addNewComponentCopy fails with the same error as
        # setting transform2 without a proxy
        childOccurrenceCopy = parentComponent.occurrences.addNewComponentCopy(
            childOccurrenceProxy.component,
            adsk.core.Matrix3D.create())
    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

 

The error I get (if you comment out the first naive attempt to set transform2) is this:

 

brenthagany_0-1670627152376.png

 

Does anyone have any insight about how to work around this problem?

 

Thanks,

Brent

 

13 REPLIES 13
Message 2 of 14
kandennti
in reply to: brent.hagany

Hi @brent.hagany .

 

I think your understanding of proxies is correct.

 

I did a little testing.

Running the following script will end up with the image.

 

# Fusion360API Python script
import traceback
import adsk.fusion
import adsk.core

def run(context):
    ui = None
    try:
        app = adsk.core.Application.get()
        ui  = app.userInterface

        mat: adsk.core.Matrix3D = adsk.core.Matrix3D.create()
        mat.translation = adsk.core.Vector3D.create(-1,-1,-1)

        rootComponent: adsk.fusion.Component = app.activeProduct.rootComponent
        rootComponent.isOriginFolderLightBulbOn = True

        parentOccurrence: adsk.fusion.Occurrence = rootComponent.occurrences.addNewComponent(
            mat
        )
        parentComponent: adsk.fusion.Component = parentOccurrence.component
        parentComponent.isOriginFolderLightBulbOn = True

        childOccurrence: adsk.fusion.Occurrence  = parentComponent.occurrences.addNewComponent(
            mat
        )
        childOccurrence.component.isOriginFolderLightBulbOn = True

        print(f'version:{app.version}\n')
        dumpMatrix3D('**childOccurrence.transform**', childOccurrence.transform)
        dumpMatrix3D('**childOccurrence.transform2**', childOccurrence.transform2)
        print(f'**childOccurrence.name**\n{childOccurrence.name}\n')
        print(f'**childOccurrence.fullPathName**\n{childOccurrence.fullPathName}')

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


def dumpMatrix3D(msg: str, mat: adsk.core.Matrix3D):
    origin, xAxis, yAxis, zAxis = mat.getAsCoordinateSystem()
    msgLst = [
        f'origin:{origin.asArray()}',
        f'xAxis:{xAxis.asArray()}',
        f'yAxis:{yAxis.asArray()}',
        f'zAxis:{zAxis.asArray()}',
        ''
    ]
    print(msg)
    print('\n'.join(msgLst))

 

1.png

The result of the print is as follows.

 

version:2.0.15027

**childOccurrence.transform**
origin:(-1.0, -1.0, -1.0)
xAxis:(1.0, 0.0, 0.0)
yAxis:(0.0, 1.0, 0.0)
zAxis:(0.0, 0.0, 1.0)

**childOccurrence.transform2**
origin:(-1.0, -1.0, -1.0)
xAxis:(1.0, 0.0, 0.0)
yAxis:(0.0, 1.0, 0.0)
zAxis:(0.0, 0.0, 1.0)

**childOccurrence.name**
Component2:1

**childOccurrence.fullPathName**
Component2:1

 

 

The result I expected is as follows

 

version:2.0.15027

**childOccurrence.transform**
origin:(-1.0, -1.0, -1.0)
xAxis:(1.0, 0.0, 0.0)
yAxis:(0.0, 1.0, 0.0)
zAxis:(0.0, 0.0, 1.0)

**childOccurrence.transform2**
origin:(-2.0, -2.0, -2.0)
xAxis:(1.0, 0.0, 0.0)
yAxis:(0.0, 1.0, 0.0)
zAxis:(0.0, 0.0, 1.0)

**childOccurrence.name**
Component2:1

**childOccurrence.fullPathName**
Component1:1+Component2:1

 

 

I think "transform2" and "fullPathName" are not working correctly.

Message 3 of 14
brent.hagany
in reply to: kandennti

Interesting! There is definitely something I don't understand about the history behind transform and transform2, so I'm not coming to this with any expectations about how they should work. The fullPathName thing definitely doesn't match my expectations though. Thank you for looking into this! If there is indeed a bug here, is there a process for reporting it?
Message 4 of 14
kandennti
in reply to: brent.hagany

Message 5 of 14
brent.hagany
in reply to: kandennti

Many thanks!

Message 6 of 14
kandennti
in reply to: brent.hagany

@brent.hagany .

 

I had made a big mistake.
"transform2" and "fullPathName" are working correctly.

# Fusion360API Python script
import traceback
import adsk.fusion
import adsk.core

def run(context):
    ui = None
    try:
        app = adsk.core.Application.get()
        ui  = app.userInterface

        mat: adsk.core.Matrix3D = adsk.core.Matrix3D.create()
        mat.translation = adsk.core.Vector3D.create(-1,-1,-1)

        rootComponent: adsk.fusion.Component = app.activeProduct.rootComponent
        rootComponent.isOriginFolderLightBulbOn = True

        parentOccurrence: adsk.fusion.Occurrence = rootComponent.occurrences.addNewComponent(
            mat
        )
        parentComponent: adsk.fusion.Component = parentOccurrence.component
        parentComponent.isOriginFolderLightBulbOn = True

        childOccurrence: adsk.fusion.Occurrence = parentComponent.occurrences.addNewComponent(
            mat
        )
        childOccurrence.component.isOriginFolderLightBulbOn = True

        # Fixed the following
        childOccProxy: adsk.fusion.Occurrence = childOccurrence.createForAssemblyContext(parentOccurrence)

        print(f'version:{app.version}\n')
        dumpMatrix3D('**childOccurrence.transform**', childOccProxy.transform)
        dumpMatrix3D('**childOccurrence.transform2**', childOccProxy.transform2)
        print(f'**childOccurrence.name**\n{childOccProxy.name}\n')
        print(f'**childOccurrence.fullPathName**\n{childOccProxy.fullPathName}')

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

 

It is not mentioned in the documentation, but I feel that the reassignment of childOccurrenceProxy.transform2 is not allowed, as per the error message.

Message 7 of 14
kandennti
in reply to: kandennti

@brent.hagany .

 

Regarding the Occurrences.addNewComponentCopy method, when I do the same thing as the script in the GUI, I get a warning in position.

1.png

 

Although it is not mentioned in the documentation, I felt that the only components that can be used with the addNewComponentCopy method are those in rootComponent.occurrences.

https://help.autodesk.com/view/fusion360/ENU/?guid=GUID-2E04975A-94C1-4C85-8077-A01DAC1B12F1 

Message 8 of 14
brent.hagany
in reply to: brent.hagany

Thanks for following up @kanndenti.  I'm pretty confused by both of your messages, though.  I'll try to be clear about why, for each.

 

First confusion

 

In message 6 of this thread, you said "I feel that the reassignment of childOccurrenceProxy.transform2 is not allowed, as per the error message."  But I don't get an error when reassigning childOccurrenceProxy.transform2 (to be specific, line 33 of my script above does not throw an error) -- it appears to work correctly.  I didn't have a problem with this part, I was just demonstrating what I knew to work.

 

Second confusion

 

In message 7, you show an error from following steps in the GUI.  However, my script is trying to recreate steps I can do without error in the GUI.  Specifically, I follow these steps in a new document:

  • Create a new component (Component1)
  • With Component1 selected, create a second new component (Component2) as a child of Component1
  • Right click Component2 in the browser, and select "Copy"
  • Right click Component1 in the browser, and select "Paste New".  This creates a second child of Component1, called Component3.

When I follow these steps, the timeline for the document looks like this

brenthagany_0-1671048333278.png

and my browser looks like this

brenthagany_1-1671048358478.png

I'm confused about several things here:

  • what steps did you take to try to recreate my script?
  • where is the position feature in your timeline coming from?
  • since I can copy Component2 and "Paste New" to create Component3 in the GUI, and the documentation for addNewComponentCopy says 'This is the equivalent of copying and using the "Paste New" command in the user interface,' I feel I must be missing something to recreate the GUI interaction I just described.

Thanks again for your help and patience

Message 9 of 14
brent.hagany
in reply to: brent.hagany

For clarity -- recreating the GUI steps I outlined in the last message is my goal, and I am not primarily concerned with transforms.  I am only talking about transforms because addNewComponentCopy throws an error about transforms when I try to use it.

 

More concretely, the following script is trying to recreate the GUI steps I outlined in message 8, but it fails with "RuntimeError: 3 : transform overrides can only be set on Occurrence proxy from root component".  I would be very pleased if I could make something like this work

import adsk.core, adsk.fusion, traceback, math


def run(context):
    ui = None
    try:
        app = adsk.core.Application.get()
        ui  = app.userInterface

        ###
        # setting up parent and child occurrences / components
        ###
        rootComponent = app.activeProduct.rootComponent
        parentOccurrence = rootComponent.occurrences.addNewComponent(adsk.core.Matrix3D.create())
        parentComponent = parentOccurrence.component
        childOccurrence = parentComponent.occurrences.addNewComponent(adsk.core.Matrix3D.create())

        ###
        # Fails with "RuntimeError: 3 : transform overrides can only be set on Occurrence proxy from root component"
        ###
        childOccurrenceCopy = parentComponent.occurrences.addNewComponentCopy(
            childOccurrence.component,
            adsk.core.Matrix3D.create())
    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

 

Message 10 of 14
kandennti
in reply to: brent.hagany

@brent.hagany .

 

I was confused because I had tried so many things.

 

First confusion

The proxy was working correctly.

 

Second confusion

I was getting different results because I was trying a Matrix3D that I was moving around, like this

        mat: adsk.core.Matrix3D = adsk.core.Matrix3D.create()
        mat.translation = adsk.core.Vector3D.create(-1,-1,-1)

 

Indeed, when the same process was performed in the GUI, no warning was issued. I do not know why.

Message 11 of 14
kandennti
in reply to: brent.hagany

@brent.hagany .

 

I don't know the cause, but so far it seems that the only way to avoid stopping with an error is to use Try or a text command.

import adsk.core, adsk.fusion, traceback

def run(context):
    ui = None
    try:
        app = adsk.core.Application.get()
        ui  = app.userInterface

        ###
        # setting up parent and child occurrences / components
        ###
        rootComponent = app.activeProduct.rootComponent
        parentOccurrence = rootComponent.occurrences.addNewComponent(adsk.core.Matrix3D.create())

        parentComponent = parentOccurrence.component
        childOccurrence = parentComponent.occurrences.addNewComponent(adsk.core.Matrix3D.create())
        childOccurrenceProxy = childOccurrence.createForAssemblyContext(parentOccurrence)

        ###
        # Fails with "RuntimeError: 3 : transform overrides can only be set on Occurrence proxy from root component"
        ###
        try:
            childOccurrenceCopy = parentComponent.occurrences.addNewComponentCopy(
                childOccurrence.component,
                adsk.core.Matrix3D.create())
        except:
            pass

        childOccurrenceCopy_from_textCmd = exec_addNewComponentCopy(childOccurrenceProxy, parentOccurrence)

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


def exec_addNewComponentCopy(
    refarenceOcc: adsk.fusion.Occurrence,
    targetOcc: adsk.fusion.Occurrence) -> adsk.fusion.Occurrence:

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

    sels.clear()
    sels.add(refarenceOcc)
    app.executeTextCommand(u'Commands.Start CopyCommand')

    sels.clear()
    sels.add(targetOcc)
    app.executeTextCommand(u'Commands.Start FusionPasteNewCommand')
    app.executeTextCommand(u'NuCommands.CommitCmd')

    return targetOcc.component.occurrences[-1]
Message 12 of 14
brent.hagany
in reply to: brent.hagany

@kandennti thank you again for spending so much time on this.  I hadn't even heard of text commands before, so I'm delighted at this workaround.  Hopefully a solution for the original addNewComponentCopy issue will soon reveal itself, but in the meantime, I'm more than satisfied at making it work this way.  Thanks again!

Message 13 of 14
kandennti
in reply to: brent.hagany

Message 14 of 14
brent.hagany
in reply to: brent.hagany

@kandennti no apologies are necessary, I assure you!  You have been a great help

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