Created
March 23, 2021 21:16
-
-
Save nothke/0982c182c629cca17adfa622e093edd8 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
bl_info = { | |
"name": "Hof Vehicle Export", | |
"category": "Object", | |
"blender": (2, 80, 0) | |
} | |
import bpy | |
import os | |
from bpy.props import IntProperty | |
from bpy.props import StringProperty | |
# OPERATOR | |
def get_root_dir(): | |
return os.path.dirname(bpy.data.filepath) | |
def is_saved(): | |
basedir = os.path.dirname(bpy.data.filepath) | |
return basedir != None | |
def find_layer_collection(layerColl, collName): | |
found = None | |
if (layerColl.name == collName): | |
return layerColl | |
for layer in layerColl.children: | |
found = find_layer_collection(layer, collName) | |
if found: | |
return found | |
def select_all_in_collection(layerColl): | |
# select all in collection (and child collections) | |
objs = layerColl.collection.all_objects | |
for ob in objs: | |
ob.select_set(True) | |
def set_active(obj): | |
bpy.context.view_layer.objects.active = obj | |
def select(obj): | |
obj.select_set(True) | |
def validate_selected_objects(): | |
# make sure all objects.. | |
for ob in bpy.context.selected_editable_objects: | |
# ..are meshes, | |
if ob.type == "EMPTY": | |
continue | |
if ob.type != "MESH": | |
raise Exception("Object " + ob.name + " is of type " + ob.type + ", but only EMPTY and MESH are valid") | |
# ..have at least 1 material slot, | |
if not ob.material_slots: | |
raise Exception("Object " + ob.name + " has no materials!") | |
# ..have materials assigned to all slots, | |
for slot in ob.material_slots: | |
if slot.material is None: | |
raise Exception(ob.name + " has an empty slot without assigned material") | |
# ..are not vertexless | |
#if len(ob.data.vertices) > 0: | |
#raise Exception("Object " + ob.name + " has no vertices") | |
# ..don't have more than 65535 vertices | |
if len(ob.data.vertices) > 65535: | |
raise Exception("Object " + ob.name + " has more than 65535 vertices") | |
# EXPORT OPERATOR | |
class NOTHKE_OT_HoFExportVehicle(bpy.types.Operator): | |
"""Tooltip""" | |
bl_idname = "object.hof_export_vehicle" | |
bl_label = "Export Vehicle" | |
# Unused | |
collectionName: StringProperty(default='EXPORT') | |
filename: StringProperty(default='hof_export') | |
def execute(self, context): | |
# Get current file directory | |
basedir = os.path.dirname(bpy.data.filepath) | |
if not basedir: | |
raise Exception("Blend file is not saved") | |
# Name is current selected collection | |
name = context.view_layer.active_layer_collection.name | |
fpath = basedir + '/vehicles/' + name + '/' | |
lc = bpy.context.view_layer.layer_collection | |
# Find glass and dummies collections | |
glassColl = find_layer_collection(lc, name + '_glass') | |
dummyColl = find_layer_collection(lc, name + '_dummies') | |
# Check if collections exist | |
if glassColl is not None: | |
print('Found glass collection') | |
else: | |
raise Exception(name + "_glass collection not found") | |
if dummyColl is not None: | |
print('Found dummies collection') | |
else: | |
raise Exception(name + "_dummies collection not found") | |
# 1. Turn off name_dummy and name_glass collections | |
glassColl.hide_viewport = True | |
dummyColl.hide_viewport = True | |
# 2. Select all | |
bpy.ops.object.select_all(action='SELECT') | |
# Intermezzo - Validate! | |
validate_selected_objects() | |
# 3. Make sure name_body is active | |
bodyObj = bpy.data.objects[name + '_body'] | |
set_active(bodyObj) | |
# 4. Save ? | |
# 5. Bake id map | |
if bpy.ops.object.bake_id_map is None: | |
raise Exception('ID Baker not found!') | |
bpy.ops.object.bake_id_map() | |
# 6. Remove all material slots | |
bpy.ops.view3d.materialutilities_remove_all_material_slots(only_active=False) | |
# 7. Create a new material name_body | |
bodyMat = bpy.data.materials.new(name + "_body") | |
bpy.ops.object.material_slot_add() | |
bodyObj.active_material = bodyMat | |
# 8 Copy material to others | |
bpy.ops.view3d.materialutilities_copy_material_to_others() | |
# 9 Turn on dummies | |
dummyColl.hide_viewport = False | |
# 10 Select all | |
bpy.ops.object.select_all(action='SELECT') | |
# 11 Export as vehicles/name/name_for_subs.fbx with HoF option | |
bpy.ops.export_scene.fbx( | |
filepath = fpath + name + "_for_subs.fbx", | |
#version = 'BIN7400', | |
#use_active_collection = True, | |
use_selection = True, | |
global_scale = 1, | |
apply_unit_scale = False, | |
apply_scale_options = 'FBX_SCALE_UNITS', | |
object_types = {'EMPTY', 'MESH', 'OTHER'}) | |
# 12 Turn on glass | |
glassColl.hide_viewport = False | |
# 13 Turn off dummies | |
dummyColl.hide_viewport = True | |
# 13.5 Select all | |
bpy.ops.object.select_all(action='SELECT') | |
# 14 Export as name.fbx | |
bpy.ops.export_scene.fbx( | |
filepath = fpath + name + ".fbx", | |
#version = 'BIN7400', | |
#use_active_collection = True, | |
use_selection = True, | |
global_scale = 1, | |
apply_unit_scale = False, | |
apply_scale_options = 'FBX_SCALE_UNITS', | |
object_types = {'EMPTY', 'MESH', 'OTHER'}) | |
# 15 Revert? | |
print('Finished export to ' + fpath + ' for: ' + name) | |
return {'FINISHED'} | |
# UI PANEL | |
class NOTHKE_PT_HoFExport(bpy.types.Panel): | |
"""Creates a Panel in the Object properties window""" | |
bl_label = "HoF Exporter" | |
bl_idname = "NOTHKE_PT_HoFExport" | |
bl_space_type = 'VIEW_3D' | |
bl_region_type = 'UI' #'TOOLS' | |
bl_category = 'HoF' | |
def draw(self, context): | |
scene = context.scene | |
layout = self.layout | |
# Not using properties for now | |
#row = layout.row() | |
#row.prop(scene, 'hofexport_collectionName') | |
#row = layout.row() | |
#row.prop(scene, 'hofexport_filename') | |
collName = context.view_layer.active_layer_collection.name | |
row = layout.row() | |
row.label(text = 'SELECTED: ' + collName) | |
# export button, create operator | |
row = layout.row() | |
op = row.operator('object.hof_export_vehicle', text='Bake ID and Export') | |
# set properties to operator values | |
op.collectionName = scene.hofexport_collectionName | |
op.filename = scene.hofexport_filename | |
row = layout.row() | |
row.label(text = 'Important:') | |
row = layout.row() | |
row.label(text = 'Save before pressing export') | |
row = layout.row() | |
row.label(text = 'Revert after export!') | |
def register(): | |
bpy.utils.register_class(NOTHKE_OT_HoFExportVehicle) | |
print('operator registered') | |
# register properties | |
bpy.types.Scene.hofexport_layer = bpy.props.IntProperty( | |
name="Layer", | |
description="Export all objects from this layer", | |
default = 1) | |
bpy.types.Scene.hofexport_collectionName = bpy.props.StringProperty( | |
name="Collection", | |
description="Export all objects from this collection", | |
default='EXPORT') | |
bpy.types.Scene.hofexport_filename = bpy.props.StringProperty( | |
name="Filename", | |
description="Filename", | |
default = 'hof_export') | |
print('properties registered') | |
bpy.utils.register_class(NOTHKE_PT_HoFExport) | |
print('panel registered') | |
def unregister(): | |
bpy.utils.unregister_class(NOTHKE_PT_HoFExport) | |
bpy.utils.unregister_class(NOTHKE_OT_HoFExportVehicle) | |
del bpy.types.Scene.hofexport_layer | |
del bpy.types.Scene.hofexport_filename | |
if __name__ == "__main__": | |
register() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment