Hello.
I’m an experienced coder. But, not with python.
I’m trying to write a Blender script that, on button press, iterates through each scene within a blend file and exports specific armatures each as separate FBX files.
For some reason, if I uncomment the fbx export line, it crashes with an EAV error.
I’m not sure if I need to make a timer to wait for each export to finish before moving the loop forward? Other examples on the web seem to suggest that its ok to export multiple separate files without wait/timer schemes…
Or, does the FBX export trigger some kind of clean-up that causes some of my references to break? I read something about broken references causing EAV errors. But, I don’t follow that 100%. I tried a lot of experiments with references and cutting code up into functions, etc. But, no fix there.
Here is the relevant part of the code:
import bpy
import os
selected_objs = []
current_mode = ''
current_scene = None
fCount = 0
mCount = 0
bCount = 0
def record_state():
global selected_objs
global current_mode
global current_scene
# Record selected objects
selected_objs = bpy.context.selected_objects
# Record current mode
current_mode = bpy.context.object.mode
# Record current scene
current_scene = bpy.context.scene
# Switch to Object mode
bpy.ops.object.mode_set ( mode = 'OBJECT' )
def restore_state():
global selected_objs
global current_mode
global current_scene
# Return to mode we were in
bpy.ops.object.mode_set ( mode = current_mode )
# Restore scene
bpy.context.window.scene = current_scene
# Restore the selections we had
for o in selected_objs:
o.select_set(True)
def publishObject(myObject, myScene):
global selected_objs
global current_mode
global current_scene
global fCount
global mCount
global gCount
if myObject.type == 'ARMATURE':
prefix = myObject.name[:9]
if prefix == "FO4Export" and myObject.library == None:
print("Found: > " + myObject.name_full)
# Create parent dictionary
parent = dict()
for c in bpy.data.collections:
parent[c] = None
for c in bpy.data.collections:
for ch in c.children:
parent[ch] = c
if myScene.name[:5] == "Scene":
# Store title based on file name
title = bpy.path.basename(bpy.context.blend_data.filepath)[:-6]
else:
# Store title based on scene name
title = myScene.name
print("TITLE: " + title)
# Store racecode based on the export armature name
raceCode = myObject.name[10:]
# Trim gender code off of racecode
raceCode = raceCode[:2]
if parent[myObject.users_collection[0]] == None:
# Set gender as blank/unknown
gender = ""
else:
# Get gender from root collection name
gender = parent[myObject.users_collection[0]].name[:1]
# Track the number of each gender
if gender == "F":
fCount = fCount + 1
gCount = fCount
elif gender == "M":
mCount = mCount + 1
gCount = mCount
else:
bCount = bCount + 1
gCount = bCount
# Record object visibility
current_visibility = myObject.visible_get(view_layer=myScene.view_layers[0])
# Unhide the target object
myObject.hide_set(False, view_layer=myScene.view_layers[0])
# Deselect all objects
bpy.ops.object.select_all(action='DESELECT')
# Select the target object
myObject.select_set(True, view_layer=myScene.view_layers[0])
# Create the relative file path
file_path = bpy.path.abspath("//")
# Create the path to parent based on removing "scenes\"
parent_path = file_path[:-7]
# If the parent path can be followed to confirm existence of "compile" folder, output to that folder
# Otherwise, just use the relative path we made earlier
if os.path.exists(os.path.join(parent_path, "compile")) == True:
file_path = os.path.join(parent_path, "compile")
cName = bpy.path.clean_name(title + "-" + raceCode + "-" + gender + str(gCount))
# Create the full output path and file name
obj_path = os.path.join(file_path, cName)
print("EXPORT: " + obj_path)
# Export the scene, using the selection
bpy.ops.export_scene.fbx(filepath=obj_path + ".fbx", use_selection=True)
# Return visibility of the target object to what it was before
myObject.hide_set(current_visibility == False, view_layer=myScene.view_layers[0])
def publishScene(myScene):
global fCount
global mCount
global gCount
fCount = 0
mCount = 0
bCount = 0
print("Found: " + myScene.name_full)
bpy.context.window.scene = myScene
objectList = myScene.collection.all_objects
for obj in objectList:
publishObject(obj, myScene)
# Selects each deform armature and publishes it as a separate FBX
class PublishOperator(bpy.types.Operator):
bl_space_type = 'VIEW_3D'
bl_region_type = 'TOOL_PROPS'
bl_idname = "publish.fo4"
bl_label = "Publish"
bl_category = "Tools"
def execute(self, context):
self.report({'INFO'}, 'Started Fallout 4 publish.')
record_state()
sceneList = bpy.data.scenes
for scene in sceneList:
publishScene(scene)
restore_state()
self.report({'INFO'}, 'Fallout 4 publish complete.')
return {'FINISHED'}
Any help would be greatly appreciated!