-
Notifications
You must be signed in to change notification settings - Fork 3
/
batch_bfb.py
136 lines (127 loc) · 4.53 KB
/
batch_bfb.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
import bpy
import os
import mathutils
import time
def select_layer(layer_nr): return tuple(i == layer_nr for i in range(0, 20))
def create_empty(parent,name,matrix):
empty = bpy.data.objects.new(name, None)
bpy.context.scene.objects.link(empty)
if parent:
empty.parent = parent
empty.matrix_local = matrix
empty.empty_draw_type="ARROWS"
return empty
def clear_scene():
#set the visible layers for this scene
bpy.context.scene.layers = [True for i in range(0,20)]
bpy.ops.object.select_all(action='SELECT')
bpy.ops.object.delete(use_global=True)
for cat in (bpy.data.objects, bpy.data.materials, ):
for thing in cat:
thing.user_clear()
cat.remove(thing)
def get_children(childlist):
global oblist
for child in childlist:
oblist.append(child)
get_children(child.children)
def add_lods(numlods, rate):
bpy.context.scene.layers = [True for i in range(0,20)]
try: bpy.ops.object.mode_set(mode="OBJECT")
except:
bpy.context.scene.objects.active = bpy.context.scene.objects[0]
bpy.ops.object.mode_set(mode="OBJECT")
obs = bpy.context.scene.objects
root = None
meshes = []
lodgroup = None
for ob in obs:
ob.select = False
if type(ob.data) in (type(None), bpy.types.Armature):
if ob.name.startswith("lodgroup"):
print("BFB model already has lodgroups!")
ob.select = True
lodgroup = ob
if not ob.parent:
root = ob
#lodgroup mustn't be the root!
if not root:
root = create_empty(None,"AutoRoot",mathutils.Matrix())
#delete the existing lodgroup and low detail lods
if lodgroup:
try:
#parent lod0 to lodgroup
lod0 = lodgroup.children[0]
lod0.parent = lodgroup.parent
global oblist
oblist = []
get_children(lodgroup.children)
for ob in oblist: ob.select = True
except:
print("Deleted lonely lodgroup with no LOD levels!")
bpy.ops.object.delete(use_global=True)
for ob in obs:
#if we have more than one mesh we have to add a lod group node
#in some cases, a model is our root (eg. fence), then we add the lodgroup as the new root
if type(ob.data) == bpy.types.Mesh:
if ob.name.startswith('sphere') or ob.name.startswith('orientedbox') or ob.name.startswith('capsule'): pass
else:
#special cases
if ob.parent_type == 'BONE':
#sometimes the main mesh is child of a bone...
ob.matrix_local = mathutils.Matrix()
#it has to be some NIF dummy object, so delete it!
if not ob.vertex_groups: ob.select = True
else: meshes.append(ob)
else: meshes.append(ob)
bpy.ops.object.delete(use_global=True)
#only add a lodgroup if needed
if numlods > 1:
lodgroup = create_empty(root,"lodgroup",mathutils.Matrix())
lodgroup.layers = select_layer(5)
#when obs are parented to empties with offset it will cause trouble!
#decide what the parent should be
for i in range(0,numlods):
#create lod level if needed
if len(meshes) > 1:
lodlevel = create_empty(lodgroup,"LOD"+str(i),mathutils.Matrix())
parent = lodlevel
else:
parent = lodgroup
#copy for new lod levels, assign high detail to lodgroup
#could also try to copy the empties here, but not much need for that
for ob in meshes:
if i > 0:
lod = ob.copy()
lod.data = ob.data.copy()
lod.name = ob.name + "_LOD"+str(i)
bpy.context.scene.objects.link(lod)
lod.layers = select_layer(i)
lod.parent = parent
mod = lod.modifiers.new('Decimator', 'DECIMATE')
mod.ratio = 1/(i+rate)
else:
ob.parent = parent
#maybe a final cleanup
#if armature > clear any empties without children
def process(operator, context, files = [], filepath = "", numlods = 1, rate = 1):
dir = os.path.dirname(filepath)
starttime = time.clock()
clear_scene()
print("Starting Batch Processing")
for file in files:
if file.name.endswith(".bfb"):
bpy.ops.import_scene.bluefang_bfb(filepath = os.path.join(dir, file.name), use_custom_normals = True)
add_lods(numlods, rate)
bpy.ops.export_scene.bluefang_bfb(filepath = os.path.join(dir, file.name)+"new.bfb", author_name="HENDRIX", export_materials = False)
elif file.name.endswith(".nif"):
try:
bpy.ops.import_scene.nif(filepath = os.path.join(dir, file.name), combine_vertices = True, axis_forward='X', axis_up='Y')
add_lods(numlods, rate)
bpy.ops.export_scene.bluefang_bfb(filepath = os.path.join(dir, file.name).replace(".nif",".bfb"), author_name="HENDRIX", export_materials = True, fix_root_bones = True)
except: print("NIF import didn't work")
else: continue
clear_scene()
success = '\nFinished Batch LOD processing in %.2f seconds\n' %(time.clock()-starttime)
print(success)
return {'FINISHED'}