Skip to content

Commit

Permalink
Fix and cleanup helper script. Move part settings to the collection p…
Browse files Browse the repository at this point in the history
…roperties (static prerender, material override). Remove (disabled) lightmap merging
  • Loading branch information
vbousquet committed Aug 22, 2023
1 parent 132089c commit e36f68e
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 109 deletions.
29 changes: 12 additions & 17 deletions addons/vpx_lightmapper/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,9 +226,11 @@ class VLM_Collection_props(PropertyGroup):
default='group'
)
is_opaque: BoolProperty(name="Opaque", description="Wether this collection only contains opaque objects which do not require blending", default = True)
use_static_rendering: BoolProperty(name="Static Rendering", description="Mark this baked part to be statically pre-rendered in VPX", default = True)
depth_bias: IntProperty(name="Depth Bias", description="Depth Bias applied to the layer when exported to VPX. Set to 0 for playfield, Negative for layer above playfield, positive for layers under playfield.", default = 0)
refraction_probe: StringProperty(name="Refraction Probe", description="Identifier of the refraction probe to be used on export", default = '')
reflection_probe: StringProperty(name="Reflection Probe", description="Identifier of the reflection probe to be used on export", default = '')
depth_bias: IntProperty(name="Depth Bias", description="Depth Bias applied to the layer when exported to VPX. Set to 0 for playfield, Negative for layer above playfield, positive for layers under playfield.", default = 0)
vpx_material: StringProperty(name="VPX Material", description="Name of a material to be used when exporting this collection instead of the default ones", default = '')
# Light scenario collection
light_mode: EnumProperty(
items=[
Expand Down Expand Up @@ -269,19 +271,10 @@ class VLM_Object_props(PropertyGroup):
use_obj_pos: BoolProperty(name="Use Obj Pos", description="Use ObjRot instead of Rot when exporting", default = False)
# Bake result properties (for object inside the bake result collection)
bake_lighting: StringProperty(name="Lighting", description="Lighting scenario", default="")
bake_collections: StringProperty(name="Bake", description="Bake collections included in this bake/lightmap", default="")
bake_collections: StringProperty(name="Bake", description="Bake collection that generated this bake/lightmap", default="")
bake_sync_light: StringProperty(name="Sync Light", description="Object to sync light state on", default="")
bake_sync_trans: StringProperty(name="Pivot", description="Pivot point if defined", default="")
bake_type: EnumProperty(
items=[
('default', 'Default', 'Default opaque bake', '', 0),
('static', 'Static', 'Static opaque bake', '', 1),
('active', 'Transparent', "'Active', i.e. non opaque, non static, transparent bake", '', 2),
('lightmap', 'Lightmap', 'Additive lightmap', '', 3),
],
name="Bake Type",
default='default'
)
is_lightmap: BoolProperty(name="Lightmap", description="This baked part is a lightmap (additive bake to be applied over a base mesh)", default = False)
bake_hdr_range: FloatProperty(name="HDR Range", description="HDR range of this bake", default=-1)
bake_nestmap: IntProperty(name="Nestmap", description="ID of output nestmap (multiple bakes may share a nestmap)", default = -1)

Expand Down Expand Up @@ -847,11 +840,13 @@ def draw(self, context):
light_col = vlm_collections.get_collection(context.scene.collection, 'VLM.Lights', create=False)
if bake_col and col.name in bake_col.children:
layout.prop(col.vlmSettings, 'bake_mode', expand=True)
layout.prop(col.vlmSettings, 'vpx_material', expand=True)
layout.prop(col.vlmSettings, 'is_opaque', expand=True)
sub = layout.column()
sub.enabled = not col.vlmSettings.is_opaque
sub.prop(col.vlmSettings, 'depth_bias', expand=True)
sub.prop(col.vlmSettings, 'refraction_probe', expand=True)
if col.vlmSettings.is_opaque:
layout.prop(col.vlmSettings, 'use_static_rendering', expand=True)
else:
layout.prop(col.vlmSettings, 'depth_bias', expand=True)
layout.prop(col.vlmSettings, 'refraction_probe', expand=True)
layout.prop(col.vlmSettings, 'reflection_probe', expand=True)
elif light_col and col.name in light_col.children:
layout.prop(col.vlmSettings, 'light_mode', expand=True)
Expand Down Expand Up @@ -1101,7 +1096,7 @@ def draw(self, context):
col.enabled = False
col.prop(props, 'bake_collections')
col.prop(props, 'bake_sync_trans')
col.prop(props, 'bake_type')
col.prop(props, 'is_lightmap')
col.separator()
col.prop(props, 'bake_lighting')
col.prop(props, 'bake_sync_light')
Expand Down
91 changes: 38 additions & 53 deletions addons/vpx_lightmapper/vlm_export.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,29 +82,24 @@ def push_map_array(name, parts):
return code


def get_script_arrays(result_col):
def get_script_arrays(bake_col, result_col):
code = '\' VLM Arrays - Start\n'
# Per Parts
code += '\' Arrays per baked part with a pivot point defined\n'
all_sync_trans = sorted(list({obj.vlmSettings.bake_sync_trans for obj in result_col.all_objects if obj.vlmSettings.bake_sync_trans != '' and bpy.data.objects.get(obj.vlmSettings.bake_sync_trans)}))
for sync_trans in all_sync_trans:
code += push_map_array(f'BP_{export_name(bpy.data.objects[sync_trans].name)}', sorted([obj for obj in result_col.all_objects if sync_trans == obj.vlmSettings.bake_sync_trans], key=lambda x: x.vlmSettings.bake_sync_light))
code += '\' Arrays per baked part without a pivot point defined\n'
all_bake_cols = sorted(list({obj.vlmSettings.bake_collections for obj in result_col.all_objects if obj.vlmSettings.bake_sync_trans == ''}))
for bake_col in all_bake_cols:
code += push_map_array(f'BP_{export_name(bake_col)}', sorted([obj for obj in result_col.all_objects if bake_col == obj.vlmSettings.bake_collections and obj.vlmSettings.bake_sync_trans == ''], key=lambda x: x.vlmSettings.bake_sync_light))
code += '\' Arrays per baked part\n'
all_parts = sorted(list({(obj.vlmSettings.bake_collections, bpy.data.objects.get(obj.vlmSettings.bake_sync_trans), export_name(obj.vlmSettings.bake_collections if bpy.data.objects.get(obj.vlmSettings.bake_sync_trans) is None or vlm_collections.get_collection(bake_col, obj.vlmSettings.bake_collections, create=False).vlmSettings.bake_mode == 'group' else bpy.data.objects.get(obj.vlmSettings.bake_sync_trans).name)) for obj in result_col.all_objects}), key=lambda x: x[2])
for col_name, pivot, name in all_parts:
col = vlm_collections.get_collection(bake_col, col_name, create=False)
bakes = sorted([obj for obj in result_col.all_objects if col_name == obj.vlmSettings.bake_collections and bpy.data.objects.get(obj.vlmSettings.bake_sync_trans) == pivot], key=lambda x: x.vlmSettings.bake_sync_light)
code += push_map_array(f'BP_{name}', bakes)
# Per Lightmaps
code += '\' Arrays per lighting scenario\n'
all_lightmaps = sorted(list({obj.vlmSettings.bake_lighting for obj in result_col.all_objects if obj.vlmSettings.bake_lighting != ''}))
for lightmap in all_lightmaps:
code += push_map_array(f'BL_{export_name(lightmap)}', sorted([obj for obj in result_col.all_objects if lightmap == obj.vlmSettings.bake_lighting], key=lambda x: x.name))
# Globals arrays per bake type
# Globals arrays
code += '\' Global arrays\n'
code += push_map_array('BG_Bakemap', sorted([obj for obj in result_col.all_objects if obj.vlmSettings.bake_type != 'lightmap'], key=lambda x: x.name))
code += push_map_array('BG_Default', sorted([obj for obj in result_col.all_objects if obj.vlmSettings.bake_type == 'default'], key=lambda x: x.name))
code += push_map_array('BG_Static', sorted([obj for obj in result_col.all_objects if obj.vlmSettings.bake_type == 'static'], key=lambda x: x.name))
code += push_map_array('BG_Active', sorted([obj for obj in result_col.all_objects if obj.vlmSettings.bake_type == 'active'], key=lambda x: x.name))
code += push_map_array('BG_Lightmap', sorted([obj for obj in result_col.all_objects if obj.vlmSettings.bake_type == 'lightmap'], key=lambda x: x.name))
code += push_map_array('BG_Bakemap', sorted([obj for obj in result_col.all_objects if not obj.vlmSettings.is_lightmap], key=lambda x: x.name))
code += push_map_array('BG_Lightmap', sorted([obj for obj in result_col.all_objects if obj.vlmSettings.is_lightmap], key=lambda x: x.name))
code += push_map_array('BG_All', sorted([obj for obj in result_col.all_objects], key=lambda x: x.name))
code += '\' VLM Arrays - End\n'
return code
Expand Down Expand Up @@ -334,7 +329,7 @@ def append_structure(src_path, mode, hashed):


# Add new bake models and default playfield collider if needed
meshes_to_export = sorted([obj for obj in result_col.all_objects], key=lambda x: f'{x.vlmSettings.bake_type == "lightmap"}-{x.name}')
meshes_to_export = sorted([obj for obj in result_col.all_objects], key=lambda x: f'{x.vlmSettings.is_lightmap}-{x.name}')

pfobj = None
pf_friction = pf_elasticity = pf_falloff = pf_scatter = 0
Expand Down Expand Up @@ -372,40 +367,15 @@ def append_structure(src_path, mode, hashed):
if not uv_layer_nested:
logger.info(f'. Missing nested uv map for {obj.name}')
continue
is_lightmap = obj.vlmSettings.bake_type == 'lightmap'
is_active = obj.vlmSettings.bake_type == 'active'
is_static = obj.vlmSettings.bake_type == 'static'
is_lightmap = obj.vlmSettings.is_lightmap and obj != pfobj
has_normalmap = next((mat for mat in obj.data.materials if mat.get('VLM.HasNormalMap') == True and mat['VLM.IsLightmap'] == False), None) is not None
depth_bias = None
reflection_probe = None
refraction_probe = None
for col_name in obj.vlmSettings.bake_collections.split(';'):
col = vlm_collections.get_collection(bake_col, col_name, create=False)
if col:
if depth_bias != None and depth_bias != col.vlmSettings.depth_bias:
logger.error(f'ERROR: {obj.name} merges multiple bake collections with different depth bias settings {obj.vlmSettings.bake_collections}')
depth_bias = col.vlmSettings.depth_bias
if reflection_probe != None and reflection_probe != col.vlmSettings.reflection_probe:
logger.error(f'ERROR: {obj.name} merges multiple bake collections with different reflection_probe settings {obj.vlmSettings.bake_collections}')
reflection_probe = col.vlmSettings.reflection_probe
if refraction_probe != None and refraction_probe != col.vlmSettings.refraction_probe:
logger.error(f'ERROR: {obj.name} merges multiple bake collections with different refraction_probe settings {obj.vlmSettings.bake_collections}')
refraction_probe = col.vlmSettings.refraction_probe
elif obj != pfobj:
logger.error(f'ERROR: {obj.name} contains object of missing bake collection {col}')
if not depth_bias: depth_bias = 0
if not reflection_probe: reflection_probe = ''
if not refraction_probe: refraction_probe = ''
if is_lightmap: depth_bias = depth_bias - 10
col = vlm_collections.get_collection(bake_col, obj.vlmSettings.bake_collections, create=False)
writer = biff_io.BIFF_writer()
writer.write_u32(19)
writer.write_tagged_padded_vector(b'VPOS', obj.location[0]/global_scale, -obj.location[1]/global_scale, obj.location[2]/global_scale)
writer.write_tagged_padded_vector(b'VSIZ', obj.scale[0], obj.scale[1], obj.scale[2])
use_obj_pos = False
if obj.vlmSettings.bake_sync_trans:
sync_obj = bpy.data.objects.get(obj.vlmSettings.bake_sync_trans)
if sync_obj:
use_obj_pos = sync_obj.vlmSettings.use_obj_pos
sync_obj = bpy.data.objects.get(obj.vlmSettings.bake_sync_trans)
use_obj_pos = sync_obj.vlmSettings.use_obj_pos if sync_obj else False
if use_obj_pos:
# RotX / RotY / RotZ
writer.write_tagged_float(b'RTV0', 0)
Expand Down Expand Up @@ -436,7 +406,15 @@ def append_structure(src_path, mode, hashed):
writer.write_tagged_string(b'NRMA', f'VLM.Nestmap{obj.vlmSettings.bake_nestmap} - NM' if has_normalmap else '')
writer.write_tagged_u32(b'SIDS', 4)
writer.write_tagged_wide_string(b'NAME', 'playfield_mesh' if obj == pfobj else export_name(obj.name))
writer.write_tagged_string(b'MATR', '' if is_lightmap or (obj == pfobj) else 'VLM.Bake.Active' if is_active else 'VLM.Bake.Solid')
if is_lightmap or (obj == pfobj):
mat = ''
elif col.vlmSettings.vpx_material != '':
mat = col.vlmSettings.vpx_material
elif col.vlmSettings.is_opaque:
mat = 'VLM.Bake.Solid'
else:
mat = 'VLM.Bake.Active'
writer.write_tagged_string(b'MATR', mat)
writer.write_tagged_u32(b'SCOL', 0xFFFFFF)
writer.write_tagged_bool(b'TVIS', obj != pfobj)
writer.write_tagged_bool(b'DTXI', False)
Expand All @@ -451,7 +429,7 @@ def append_structure(src_path, mode, hashed):
writer.write_tagged_bool(b'CLDR', obj == pfobj)
writer.write_tagged_bool(b'ISTO', obj != pfobj)
writer.write_tagged_bool(b'U3DM', True)
writer.write_tagged_bool(b'STRE', is_static)
writer.write_tagged_bool(b'STRE', obj == pfobj or (not is_lightmap and col.vlmSettings.use_static_rendering))
writer.write_tagged_u32(b'DILI', 255) # 255 is 1.0 for disable lighting
writer.write_tagged_float(b'DILB', 1.0) # also disable lighting from below
writer.write_tagged_bool(b'REEN', False)
Expand Down Expand Up @@ -505,20 +483,27 @@ def append_structure(src_path, mode, hashed):
compressed_indices = zlib.compress(struct.pack(f'<{n_indices}H', *indices))
writer.write_tagged_u32(b'M3CJ', len(compressed_indices))
writer.write_tagged_data(b'M3CI', compressed_indices)
print(3)
if (obj == pfobj) or col.vlmSettings.is_opaque:
depth_bias = 0
elif is_lightmap:
depth_bias = col.vlmSettings.depth_bias - 1
else:
depth_bias = col.vlmSettings.depth_bias
writer.write_tagged_float(b'PIDB', depth_bias)
writer.write_tagged_bool(b'ADDB', is_lightmap)
writer.write_tagged_float(b'FALP', 100)
writer.write_tagged_u32(b'COLR', 0xFFFFFF)
writer.write_tagged_bool(b'LOCK', True)
writer.write_tagged_bool(b'LVIS', True)
writer.write_tagged_bool(b'ZMSK', False if (is_active or is_lightmap) else True)
writer.write_tagged_bool(b'ZMSK', True if (is_lightmap or (obj == pfobj) or not col.vlmSettings.is_opaque) else False)
writer.write_tagged_u32(b'LAYR', 0)
writer.write_tagged_string(b'LANR', 'VLM.Lightmaps' if is_lightmap else 'VLM.Visuals')
if is_lightmap:
sync_light, _ = get_vpx_sync_light(obj, context, light_col)
writer.write_tagged_string(b'LMAP', sync_light if sync_light else '')
writer.write_tagged_string(b'REFL', reflection_probe)
writer.write_tagged_string(b'REFR', refraction_probe)
writer.write_tagged_string(b'REFL', '' if is_lightmap or (obj == pfobj) else col.vlmSettings.reflection_probe)
writer.write_tagged_string(b'REFR', '' if is_lightmap or (obj == pfobj) or col.vlmSettings.is_opaque else col.vlmSettings.refraction_probe)
writer.close()
dst_stream = dst_gamestg.CreateStream(f'GameItem{n_game_items}', storagecon.STGM_DIRECT | storagecon.STGM_READWRITE | storagecon.STGM_SHARE_EXCLUSIVE | storagecon.STGM_CREATE, 0, 0)
dst_stream.Write(writer.get_data())
Expand Down Expand Up @@ -554,7 +539,7 @@ def append_structure(src_path, mode, hashed):
objects = [obj for obj in result_col.all_objects if obj.vlmSettings.bake_nestmap == nestmap_index]
if not objects:
break
is_hdr = next( (o for o in objects if o.vlmSettings.bake_type == 'lightmap' and o.vlmSettings.bake_hdr_range > 1.0), None) is not None
is_hdr = next( (o for o in objects if o.vlmSettings.is_lightmap and o.vlmSettings.bake_hdr_range > 1.0), None) is not None
base_path = bpy.path.abspath(f'{bakepath}Export/Nestmap {nestmap_index}')
nestmap_path = f'{base_path}.exr' if is_hdr else f'{base_path}.webp'
if not os.path.exists(nestmap_path):
Expand Down Expand Up @@ -685,7 +670,7 @@ def append_structure(src_path, mode, hashed):
for line in code.splitlines():
if '\' VLM Arrays - End' in line:
# End of old arrays: add new ones
new_code += get_script_arrays(result_col)
new_code += get_script_arrays(bake_col, result_col)
in_old_arrays = 2
elif in_old_arrays == 1:
# Old arrays: just remove them
Expand All @@ -697,7 +682,7 @@ def append_structure(src_path, mode, hashed):
new_code += line
new_code += '\n'
if in_old_arrays < 2:
new_code += '\n' + get_script_arrays(result_col)
new_code += '\n' + get_script_arrays(bake_col, result_col)
wr = biff_io.BIFF_writer()
wr.write_string(new_code)
br.insert_data(wr.get_data())
Expand Down
Loading

0 comments on commit e36f68e

Please sign in to comment.