That makes total sense @ferdinand.
Kind of have to start at the beginning to understand where I'm coming from. I found myself exporting individual .fbx files on a more regular basis but only a couple at a time so it was not a problem to do it in the interface. I added the Export Selected Objects As to my toolbar for ease of use as it fills in the fbx file name with the selected objects name by default. I have my fbx export preferences preset to Selection Only. This work flow has gotten me into a habit of clicking a button to open the export panel and then clicking ok. Easy.
That brings us to this week where I have to export 160 objects. Writing a script to do exactly what I was doing was easy enough. But then I got greedy and wanted to collect the textures as well. We don't use embedded textures in our fbx so collecting them for transfer has been a manual process. That's when I was faced with two options.
- Get a cake (I love that analogy by the way) I do this for many of my other exports like .c4d, .obj and .gltf
- Leverage the built in Selection Only aspect of the fbx exporter and then simply use Python to copy some texture files from my tex folder to my delivery folder. It felt like it would be a simpler, lower overhead solution versus creating a 'donor' doc. Or at least it feels like it should be simple. There's even a function called GetAllTextures and an option to have it restricted to a single model rather than from the entire doc.
I'm ok with how I had to make it in the end but now I'm really curious how the GetAllTextures() works in case I can leverage it for this or something else down the road.
The FBX exporter is unique in Cinema since Maxon added the Selection Only option to it. If it weren't for that thing I'd be at the bakery....all.....day.....long
import c4d
import os
from c4d import gui
from c4d import documents
from c4d import plugins
def listModels():
selected = []
rawSelection = doc.GetActiveObjects(c4d.GETACTIVEOBJECTFLAGS_NONE)
for item in rawSelection:
if item.CheckType(5100) or item.CheckType(5140): # PolygonalObject or Null
selected.append(item)
rawSelection = []
return selected
models = listModels()
if models == []:
message = "You must select at least one object"
c4d.gui.MessageDialog(message, c4d.GEMB_OK)
else:
gui.SetMousePointer(c4d.MOUSE_BUSY)
c4d.StatusSetSpin()
# Get fbx export plugin,
plug = plugins.FindPlugin(c4d.FORMAT_FBX_EXPORT, c4d.PLUGINTYPE_SCENESAVER)
if plug is None:
print("noPlug")
op = {}
# Send MSG_RETRIEVEPRIVATEDATA to fbx export plugin
if plug.Message(c4d.MSG_RETRIEVEPRIVATEDATA, op):
# BaseList2D object stored in "imexporter" key holds the settings
fbxExport = op["imexporter"]
# Define the settings
fbxExport[c4d.FBXEXPORT_FBX_VERSION] = c4d.FBX_EXPORTVERSION_NATIVE
fbxExport[c4d.FBXEXPORT_SELECTION_ONLY] = True
fbxExport[c4d.FBXEXPORT_TRIANGULATE] = True
fbxExport[c4d.FBXEXPORT_SAVE_NORMALS] = True
fbxExport[c4d.FBXEXPORT_UP_AXIS] = c4d.FBXEXPORT_UP_AXIS_Y
fbxExport[c4d.FBXEXPORT_FLIP_Z_AXIS] = False
fbxExport[c4d.FBXEXPORT_MATERIALS] = True
fbxExport[c4d.FBXEXPORT_EMBED_TEXTURES] = False
fbxExport[c4d.FBXEXPORT_BAKE_MATERIALS] = False
#check for target directory
targetPath = os.path.join(doc.GetDocumentPath(), "FBX_Exports")
if os.path.exists(targetPath) == False: #makes a new directory to store the converted files in
os.mkdir(targetPath)
for obj in (models):
fbxName = c4d.BaseList2D.GetName(obj) + ".fbx" #get the name of the model
fbxPath = os.path.join(targetPath,fbxName)
# Get the texture files and a save a c4d file for rendering
theTextures = doc.GetAllTextures(False, [obj])
print(theTextures)
# if I can get the textures I will write some shutil.copyFile type of stuff here
#export the fbx
if c4d.documents.SaveDocument(newDoc, fbxPath, c4d.SAVEDOCUMENTFLAGS_DONTADDTORECENTLIST, c4d.FORMAT_FBX_EXPORT) == False:
if gui.MessageDialog("Export failed!" + " - " + fbxName, c4d.GEMB_OKCANCEL) == c4d.GEMB_R_CANCEL:
break
c4d.gui.SetMousePointer(c4d.MOUSE_NORMAL)
gui.MessageDialog("Export Complete", c4d.GEMB_OK)
c4d.StatusClear()