opening/exporting nested linked components

opening/exporting nested linked components

danielWNW3M
Contributor Contributor
374 Views
1 Reply
Message 1 of 2

opening/exporting nested linked components

danielWNW3M
Contributor
Contributor

I'm working on a plugin to export data about a given design, including stls of each component. This was simple enough to make, and works well... unless some of the components are linked. Exporting stls of linked components doesn't seem to work correctly, so I tried to work around it by opening the original document containing the linked part, and exporting it from there. This works well... unless the linked component is nested in another linked component, then I get the following error: 

RuntimeError: 3 : Cannot get allDocumentReferences of a non-top-level document.

 

To work around that, I wrote a recursive function to find the highest level linked component above the one I want, activate it's doc, then repeat until I've directly opened the component I want and exported its stl from its own file. In theory. In practice, even when I'm referencing a linked component from a file in which it is a top level component, I still get the same error from above. At this point I'm at my wits end. I've posted the code below, if anyone can find my error I'd appreciate it greatly.

 

Thanks

# This takes a given occurence and outputs all of it's associated bodies as a single stl
def export_as_stl(occ, path, uuid, exportMgr, label):
    if os.path.exists(path+"/design-package/payload/components/" + uuid) == False:
        os.mkdir(path+"/design-package/payload/components/" + uuid) 
    os.mkdir(path+"/design-package/payload/components/" + uuid + "/models")

    if occ.isReferencedComponent:
        occ = open_linked_components(occ, occ, path, uuid, exportMgr, label)

    else:
        fileName = path + "/design-package/payload/components/" + uuid + "/models/" + label
        stlExportOptions = exportMgr.createSTLExportOptions(occ, fileName)

        stlExportOptions.sendToPrintUtility = False
        exportMgr.execute(stlExportOptions)

 

# recursively open any linked components up the tree chain
def open_linked_components(current_occ, target_occ, path, uuid, exportMgr, label):

    # get the relevant data to my current active doc
    app: adsk.core.Application = adsk.core.Application.get()
    des: adsk.fusion.Design = app.activeProduct
    root: adsk.fusion.Component = des.rootComponent
    ui = app.userInterface
    ui.messageBox("context: "+root.name+"\ncurrent_occ: "+current_occ.name+"\ntarget_occ: "+target_occ.name)

    # update current_occ to make sure it's pulling from the current root
    current_occ = root.allOccurrences.itemByName(current_occ.name)

    # find the parent of the current_occ
    parent = current_occ.assemblyContext
    if parent != None:
        ui.messageBox("parent: "+parent.name)
    else:
        ui.messageBox("parent: None")

    if parent != None and parent.isReferencedComponent:
        # if the parent is a reference recurse up the tree with the parent as the current_occ
        ui.messageBox("parent is a reference, time to recurse up the tree!")

        if parent.component.id == root.id:
            ui.messageBox("somehow the parent is the root component, but also a reference. What?")
            if root.isReferencedComponent:
                ui.messageBox("root is a reference. I'm ****ing lost")
                raise "nothing makes sense"
            else:
                open_linked_components(root, target_occ, path, uuid, exportMgr, label)
        else:
            open_linked_components(parent, target_occ, path, uuid, exportMgr, label)


    else:
        ui.messageBox("Parent isn't a reference, time to recurse down!")
        # if the parent isn't a reference, it's time to recurse down, opening the file of this top-level reference
        
        # save the parent so I can get back where I came from
        des: adsk.fusion.Design = app.activeProduct
        p_doc = des.parentDocument

        # open the source document for the referenced component, and activate the root
        doc = current_occ.documentReference.referencedDocument
        doc.activate()
        app: adsk.core.Application = doc.parent
        des: adsk.fusion.Design = app.activeProduct
        root: adsk.fusion.Component = des.rootComponent
        ui.messageBox("current_occ:"+root.id+", "+root.name + "\ntarget_occ:"+target_occ.component.id+", "+target_occ.name)

        # check if the root is the target_occ
        if root.id == target_occ.component.id:
            # if it is, export the stl

            # turn off subcomponents so we only get the stl for the one we're looking at
            lightStateList = []
            for subcomp in root.allOccurrences:
                lightStateList.append((subcomp, subcomp.isLightBulbOn))
                subcomp.isLightBulbOn = False

            fileName = path + "/design-package/payload/components/" + uuid + "/models/" + label
            stlExportOptions = exportMgr.createSTLExportOptions(current_occ, fileName)

            stlExportOptions.sendToPrintUtility = False
            exportMgr.execute(stlExportOptions)

            # turn the subcomponents back on
            restore_light_state(lightStateList)
        else:
            # in the context of the parent document, I reset to target_occ in both fields. This resets
            # the search, so I'll recurse up the new tree in the new doc, just like I did the first
            open_linked_components(target_occ, target_occ, path, uuid, exportMgr, label)

        # once that's resolved, I close the document I just opened and reactivate it's parent to clean up after myself
        doc.close(False)
        p_doc.activate()
0 Likes
Reply (1)
Message 2 of 2

danielWNW3M
Contributor
Contributor

Another couple days of struggling have given me a bit more info to share for anyone in the future who runs into this problem. 

 

The root problem here isn't in opening the document, it's in figuring out which one to open. The .documentReference method I'm running on the occurrence itself is what's calling the allDocumentReferences that's throwing the error. This means that for any nested linked component this method always fails and crashes the script/plugin calling it. 

 

Since I can still see a list of all the referenced documents, I can manually figure out which one contains the component I'm looking for, open it directly, and then export it. 

 

Hopefully this helps someone in the future, I still have no idea why the recursive function didn't work though.

Screenshot 2024-08-12 at 11.33.54 AM.png

0 Likes