Script to export a list of objects


#1

Hi,
I’ve seen that in cinema4D r20 there’s the feature “File->Export Selected Object as…”

It’s very usefull to export 1 hierarchy but if I wanna export a list of objects (for example: 100 objects) in single scenes, is there a way to do it?

A python script maybe?


#2

Just select them, copy them into a new scene, and save that?
In the R21, the menu item says “objects”, plural, anyway, and saves all selected objects in the new scene.


#3

Yes, but for 100 or 10000 objects that I want in 100 or 10000 different scenes I have to copy and paste and save hand by hand?

Is there a more simple and fast way?


#4

paste this code into python editor.
change the path, as mentioned in code.
select your items in your scene.
execute.
should work.

EDIT:
code caused c4d-crashes when illegal type was part of selection.
updated the code. see the next posts.


#5

edit: deleted. talking to myself. where no context, there no sense.


#6

so, here’s a cleaner version that’s more tolerant if non-basetype objects are selected.
furthermore, the selected objects will be saved in a folder that’s being created at the path of your scenefile. the name of that folder will be the name of your scenefile + “_objExport” - the name of the objects that are being saved within that folder are derived form the objectnamess.

import c4d, os
import c4d.documents as docs
from c4d import gui
# Welcome to the world of Python


# Main function
def main():

    # the doc
    doc = docs.GetActiveDocument()
    docPath = doc.GetDocumentPath()
    docName = doc.GetDocumentName()
    # list-stuff
    objList = doc.GetSelection()
    tmpList= []
    itemCounter = 0

    # check if anything is selected
    if not objList:
        gui.MessageDialog('Nothing selected -> nothing saved')
    else:
        # create folder, if not present
        setupFolder = docPath + "\\" + docName[0:len(docName)-4] + "_objExport" + "\\"
        if not os.path.exists(setupFolder):
            os.makedirs(setupFolder)
        # check each obj in selection and save in file after type-check
        for obj in objList:
            # check type
            if not isinstance(obj, c4d.BaseObject):
                print "Expected c4d.BaseObject, got %s." % obj.__class__.__name__ + " attached to: "\
                      + obj.GetObject().GetName()
            else:
                # some list-stuff
                tmpList.insert(0,obj)
                # create temp doc and insert selected obj into it
                theTempDoc = docs.IsolateObjects(doc, tmpList)
                # save temp doc in folder using the original project-filename & objectname
                path = str(setupFolder + obj.GetName() + ".c4d")
                docs.SaveDocument(theTempDoc, path, c4d.SAVEDOCUMENTFLAGS_DONTADDTORECENTLIST, format=c4d.FORMAT_C4DEXPORT)
                # some list-stuff
                tmpList.remove(obj)
                # kill temp doc
                docs.KillDocument(theTempDoc)
                itemCounter += 1

        gui.MessageDialog(str(itemCounter) + '  selected items saved to: ' + setupFolder)


# Execute main()
if __name__=='__main__':
    main()

#7

Hey Mesutcapkin your script works very very fine!!
thank you!!

But it save the selected objects as .c4d scenes, how could it save in .FBX too?


#8

you’re welcome.
well, i was not aware that you wanted a different format other than c4d.
i can look into that; unfortunately it’ll have to wait until later this evening.


#9

so, here’s another version of the script.
same handling as before, only this time you choose your desired exportformat after executing the script.
it does not offer access to export-settings, so if there’s specific settings you’d want to see being applied, you’d need to set them globally via your preferences before executing the script.

import c4d, os
import c4d.documents as docs
from c4d import gui
# Welcome to the world of Python


# fileFormatMenu
def chooseExportMethodMenu():

    # menu items id
    IDM_MENU1 = c4d.FIRST_POPUP_ID
    IDM_MENU2 = c4d.FIRST_POPUP_ID + 1
    IDM_MENU3 = c4d.FIRST_POPUP_ID + 2
    IDM_MENU4 = c4d.FIRST_POPUP_ID + 3
    IDM_MENU5 = c4d.FIRST_POPUP_ID + 4
    IDM_MENU6 = c4d.FIRST_POPUP_ID + 5
    IDM_MENU7 = c4d.FIRST_POPUP_ID + 6
    IDM_MENU8 = c4d.FIRST_POPUP_ID + 7
    IDM_MENU9 = c4d.FIRST_POPUP_ID + 8
    IDM_MENU10 = c4d.FIRST_POPUP_ID + 9
    IDM_MENU11 = c4d.FIRST_POPUP_ID + 10
    IDM_MENU12 = c4d.FIRST_POPUP_ID + 11
    IDM_MENU13 = c4d.FIRST_POPUP_ID + 12
    IDM_MENU14 = c4d.FIRST_POPUP_ID + 13
    IDM_MENU15 = c4d.FIRST_POPUP_ID + 14

    # main menu
    menu = c4d.BaseContainer()
    menu.InsData(IDM_MENU1, "Cinema 4D (*.c4d)")
    menu.InsData(0, '')  # Append separator
    menu.InsData(IDM_MENU2, "3D Studio (*.3ds)")
    menu.InsData(IDM_MENU3, "Alembic (*.abc)")
    menu.InsData(IDM_MENU4, "Allplan (*.xml)")
    menu.InsData(IDM_MENU5, "Bullet (*.bullet)")
    menu.InsData(0, '')  # Append separator
    menu.InsData(IDM_MENU6, "COLLADA 1.4 (*.dae)")
    menu.InsData(IDM_MENU7, "COLLADA 1.5 (*.dae)")
    menu.InsData(0, '')  # Append separator
    menu.InsData(IDM_MENU8, "Direct 3D (*.x)")
    menu.InsData(IDM_MENU9, "DXF (*.dxf)")
    menu.InsData(IDM_MENU10, "FBX (*.fbx)")
    menu.InsData(IDM_MENU11, "Illustrator (*.ai)")
    menu.InsData(IDM_MENU12, "STL (*.stl)")
    menu.InsData(IDM_MENU13, "Volume (*.vdb)")
    menu.InsData(IDM_MENU14, "VRML 2 (*.wrl)")
    menu.InsData(IDM_MENU15, "Wavefront OBJ (*.obj)")

    # show dialog
    result = gui.ShowPopupDialog(cd=None, bc=menu, x=c4d.MOUSEPOS, y=c4d.MOUSEPOS)
    return result


def exportItems(objList, setupFolder, fileFormatEnding, cmdNr):

    tmpList = []
    itemCounter = 0
    saveCounter = 0

    for obj in objList:
        # check type
        if not isinstance(obj, c4d.BaseObject):
            print "Expected c4d.BaseObject, got %s." % obj.__class__.__name__ + " attached to: " \
                  + obj.GetObject().GetName()
        else:
            # some list-stuff
            tmpList.insert(0, obj)
            # create temp doc and insert selected obj into it
            theTempDoc = docs.IsolateObjects(doc, tmpList)
            # save temp doc in folder using the original project-filename & objectname
            path = str(setupFolder + obj.GetName() + str(fileFormatEnding))
            if docs.SaveDocument(theTempDoc, path, c4d.SAVEDOCUMENTFLAGS_DONTADDTORECENTLIST, cmdNr):
                saveCounter += 1
            # some list-stuff
            tmpList.remove(obj)
            # kill temp doc
            docs.KillDocument(theTempDoc)
            itemCounter += 1

    if itemCounter == saveCounter:
        print itemCounter, saveCounter
        gui.MessageDialog(str(itemCounter) + "  Selected items saved to: " + setupFolder)
    else:
        print itemCounter, saveCounter
        gui.MessageDialog("Something went wrong!\n" + "Out of " + str(itemCounter) + " items, "
                          + str(saveCounter) + " were saved to " + setupFolder)


# main
def main():

    # dict with menu id, formatending, command-code
    fileFormatDict = {900000: [".c4d", 1001026],
                  900001: [".3ds", 1001038],
                  900002: [".abc", 1028082],
                  900003: [".xml", 1016440],
                  900004: [".bullet", 180000105],
                  900005: [".dae", 1022316],
                  900006: [".dae", 1025755],
                  900007: [".x", 1001047],
                  900008: [".dxf", 1001036],
                  900009: [".fbx", 1026370],
                  900010: [".ai", 1012074],
                  900011: [".stl", 1001021],
                  900012: [".vdb", 1039865],
                  900013: [".wrl", 1001034],
                  900014: [".obj", 1030178]}

    # the doc
    doc = docs.GetActiveDocument()
    docPath = doc.GetDocumentPath()
    docName = doc.GetDocumentName()
    # list-stuff
    objList = doc.GetSelection()

    chosenExportMethod = chooseExportMethodMenu()

    # check if anything is selected
    if not objList:
        gui.MessageDialog("Nothing selected -> nothing saved")

    else:
        if chosenExportMethod in fileFormatDict:
            # create folder, if not present
            setupFolder = docPath + "\\" + docName[0:len(docName)-4] + "_objExport" + "\\"
            if not os.path.exists(setupFolder):
                os.makedirs(setupFolder)
            exportItems(objList, setupFolder, fileFormatDict[chosenExportMethod][0],
                          fileFormatDict[chosenExportMethod][1])
        else:
            pass



if __name__=='__main__':
    main()

#10

OMG!! Man, you rock!!!

Thank you 10000k


#11

you’re welcome.


#12

Great work, Thanks .


#13

Hi! thanks a lot for your script, it´s working great! the only problem I am having is that the documents that it creates won´t have the same render settings that I have in my original scene, :frowning: I tryied setting the default file and template with the render settings I need, but it still won´t pick them up, Do you Know how I could change those temp docs default renders settings?

Thanks a lot in advance!!


#14

sure, here you go.
same script, only now the active rendersettings (incl. children) are being stolen and set active in the saved document (only if c4d-format is chosen, obviously).

import c4d, os
import c4d.documents as docs
from c4d import gui
# Welcome to the world of Python


# fileFormatMenu
def chooseExportMethodMenu():

    # menu items id
    IDM_MENU1 = c4d.FIRST_POPUP_ID
    IDM_MENU2 = c4d.FIRST_POPUP_ID + 1
    IDM_MENU3 = c4d.FIRST_POPUP_ID + 2
    IDM_MENU4 = c4d.FIRST_POPUP_ID + 3
    IDM_MENU5 = c4d.FIRST_POPUP_ID + 4
    IDM_MENU6 = c4d.FIRST_POPUP_ID + 5
    IDM_MENU7 = c4d.FIRST_POPUP_ID + 6
    IDM_MENU8 = c4d.FIRST_POPUP_ID + 7
    IDM_MENU9 = c4d.FIRST_POPUP_ID + 8
    IDM_MENU10 = c4d.FIRST_POPUP_ID + 9
    IDM_MENU11 = c4d.FIRST_POPUP_ID + 10
    IDM_MENU12 = c4d.FIRST_POPUP_ID + 11
    IDM_MENU13 = c4d.FIRST_POPUP_ID + 12
    IDM_MENU14 = c4d.FIRST_POPUP_ID + 13
    IDM_MENU15 = c4d.FIRST_POPUP_ID + 14

    # main menu
    menu = c4d.BaseContainer()
    menu.InsData(IDM_MENU1, "Cinema 4D (*.c4d)")
    menu.InsData(0, '')  # Append separator
    menu.InsData(IDM_MENU2, "3D Studio (*.3ds)")
    menu.InsData(IDM_MENU3, "Alembic (*.abc)")
    menu.InsData(IDM_MENU4, "Allplan (*.xml)")
    menu.InsData(IDM_MENU5, "Bullet (*.bullet)")
    menu.InsData(0, '')  # Append separator
    menu.InsData(IDM_MENU6, "COLLADA 1.4 (*.dae)")
    menu.InsData(IDM_MENU7, "COLLADA 1.5 (*.dae)")
    menu.InsData(0, '')  # Append separator
    menu.InsData(IDM_MENU8, "Direct 3D (*.x)")
    menu.InsData(IDM_MENU9, "DXF (*.dxf)")
    menu.InsData(IDM_MENU10, "FBX (*.fbx)")
    menu.InsData(IDM_MENU11, "Illustrator (*.ai)")
    menu.InsData(IDM_MENU12, "STL (*.stl)")
    menu.InsData(IDM_MENU13, "Volume (*.vdb)")
    menu.InsData(IDM_MENU14, "VRML 2 (*.wrl)")
    menu.InsData(IDM_MENU15, "Wavefront OBJ (*.obj)")

    # show dialog
    result = gui.ShowPopupDialog(cd=None, bc=menu, x=c4d.MOUSEPOS, y=c4d.MOUSEPOS)
    return result


def exportItems(objList, setupFolder, fileFormatEnding, cmdNr):

    tmpList = []
    itemCounter = 0
    saveCounter = 0

    for obj in objList:
        # check type
        if not isinstance(obj, c4d.BaseObject):
            print "Expected c4d.BaseObject, got %s." % obj.__class__.__name__ + " attached to: " \
                  + obj.GetObject().GetName()
        else:
            # some list-stuff
            tmpList.insert(0, obj)
            # create temp doc and insert selected obj into it
            theTempDoc = docs.IsolateObjects(doc, tmpList)

            # steal active rendersettings (incl. children) & set them active in saved doc
            if fileFormatEnding == ".c4d":
                myRendersettings = doc.GetActiveRenderData().GetClone()
                theTempDoc.InsertRenderData(myRendersettings)
                myRendersettings.SetBit(c4d.BIT_ACTIVERENDERDATA)

            # save temp doc in folder using the original project-filename & objectname
            path = str(setupFolder + obj.GetName() + str(fileFormatEnding))
            if docs.SaveDocument(theTempDoc, path, c4d.SAVEDOCUMENTFLAGS_DONTADDTORECENTLIST, cmdNr):
                saveCounter += 1
            # some list-stuff
            tmpList.remove(obj)
            # kill temp doc
            docs.KillDocument(theTempDoc)
            itemCounter += 1

    if itemCounter == saveCounter:
        gui.MessageDialog(str(itemCounter) + "  Selected items saved to: " + setupFolder)
    else:
        gui.MessageDialog("Something went wrong!\n" + "Out of " + str(itemCounter) + " items, "
                          + str(saveCounter) + " were saved to " + setupFolder)


# main
def main():

    # dict with menu id, formatending, command-code
    fileFormatDict = {900000: [".c4d", 1001026],
                  900001: [".3ds", 1001038],
                  900002: [".abc", 1028082],
                  900003: [".xml", 1016440],
                  900004: [".bullet", 180000105],
                  900005: [".dae", 1022316],
                  900006: [".dae", 1025755],
                  900007: [".x", 1001047],
                  900008: [".dxf", 1001036],
                  900009: [".fbx", 1026370],
                  900010: [".ai", 1012074],
                  900011: [".stl", 1001021],
                  900012: [".vdb", 1039865],
                  900013: [".wrl", 1001034],
                  900014: [".obj", 1030178]}

    # the doc
    doc = docs.GetActiveDocument()
    docPath = doc.GetDocumentPath()
    docName = doc.GetDocumentName()
    # list-stuff
    objList = doc.GetSelection()

    chosenExportMethod = chooseExportMethodMenu()

    # check if anything is selected
    if not objList:
        gui.MessageDialog("Nothing selected -> nothing saved")

    else:
        if chosenExportMethod in fileFormatDict:
            # create folder, if not present
            setupFolder = docPath + "\\" + docName[0:len(docName)-4] + "_objExport" + "\\"
            if not os.path.exists(setupFolder):
                os.makedirs(setupFolder)
            exportItems(objList, setupFolder, fileFormatDict[chosenExportMethod][0],
                          fileFormatDict[chosenExportMethod][1])
        else:
            pass



if __name__=='__main__':
    main()

#15

There is plugin for this issue


#16

Wow mesutcapkin, this is a great script!
Thank you for sharing it :slight_smile:

Could you please upgrade it so it can batch import files from the selected folder (one at a time), merge them with an open scene (let’s call it the main scene), and export new scenes in the desired format?

So if the main scene is empty, it will act as a converter (as it does now but for the objects in separate files), but if the main scene has a prepared studio setup and defined render settings, the new files will have objects merged in that scene.
New files can than be named for example - [selected_file]-[main_scene]

Thank you! :smiley:


#17

sorry for being late to the party.
glad, that script comes in handy.

of course i cannot guarantee, i understood what your goal is.
having said that, i suspect it to be somewhat obvious that it’s quite a bit of a different goal than the script originally had aimed for.
while not being impossible to implement your wishes, i guess it would take a bit of time, which is a resource i posess not much of, these days.

maybe someone else wants to fill tha gap.

otherwise: contacting one of those skillful ppl on this forum, that are able and willing to code customized solutions for given problems, seems to be the most efficient way to achieving your goal.

best,
mesut.