Update lightmapper to v0.6
parent
f775305b64
commit
3ab8b81d66
Binary file not shown.
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 24 KiB |
|
@ -0,0 +1,7 @@
|
|||
from . import keymap
|
||||
|
||||
def register():
|
||||
keymap.register()
|
||||
|
||||
def unregister():
|
||||
keymap.unregister()
|
|
@ -23,8 +23,21 @@ classes = [
|
|||
tlm.TLM_CleanBuildEnvironmentProbes,
|
||||
tlm.TLM_PrepareUVMaps,
|
||||
tlm.TLM_LoadLightmaps,
|
||||
tlm.TLM_DisableSpecularity,
|
||||
tlm.TLM_DisableMetallic,
|
||||
tlm.TLM_RemoveEmptyImages,
|
||||
tlm.TLM_AddCollectionsPost,
|
||||
tlm.TLM_AddSelectedCollectionsPost,
|
||||
tlm.TLM_PostAtlasSpecialsMenu,
|
||||
tlm.TLM_AddCollections,
|
||||
tlm.TLM_AddSelectedCollections,
|
||||
tlm.TLM_AtlasSpecialsMenu,
|
||||
tlm.TLM_Reset,
|
||||
tlm.TLM_CalcTexDex,
|
||||
imagetools.TLM_ImageUpscale,
|
||||
imagetools.TLM_ImageDownscale
|
||||
imagetools.TLM_ImageDownscale,
|
||||
tlm.TLM_AddGLTFNode,
|
||||
tlm.TLM_ShiftMultiplyLinks
|
||||
|
||||
]
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ class TLM_Install_OpenCV(bpy.types.Operator):
|
|||
if platform.system() == "Windows":
|
||||
pythonlibpath = os.path.join(os.path.dirname(os.path.dirname(pythonbinpath)), "lib")
|
||||
else:
|
||||
pythonlibpath = os.path.join(os.path.dirname(os.path.dirname(pythonbinpath)), "lib", os.path.basename(pythonbinpath)[:-1])
|
||||
pythonlibpath = os.path.join(os.path.dirname(os.path.dirname(pythonbinpath)), "lib", os.path.basename(pythonbinpath))
|
||||
|
||||
ensurepippath = os.path.join(pythonlibpath, "ensurepip")
|
||||
|
||||
|
@ -78,4 +78,4 @@ class TLM_Install_OpenCV(bpy.types.Operator):
|
|||
print("Sucessfully installed OpenCV!\n")
|
||||
ShowMessageBox("Please restart blender to enable OpenCV filtering", "Restart", 'PREFERENCES')
|
||||
|
||||
return{'FINISHED'}
|
||||
return{'FINISHED'}
|
||||
|
|
|
@ -75,9 +75,11 @@ class TLM_CleanLightmaps(bpy.types.Operator):
|
|||
|
||||
filepath = bpy.data.filepath
|
||||
dirpath = os.path.join(os.path.dirname(bpy.data.filepath), scene.TLM_EngineProperties.tlm_lightmap_savedir)
|
||||
if os.path.isdir(dirpath):
|
||||
for file in os.listdir(dirpath):
|
||||
os.remove(os.path.join(dirpath + "/" + file))
|
||||
|
||||
if not bpy.context.scene.TLM_SceneProperties.tlm_keep_baked_files:
|
||||
if os.path.isdir(dirpath):
|
||||
for file in os.listdir(dirpath):
|
||||
os.remove(os.path.join(dirpath + "/" + file))
|
||||
|
||||
for obj in bpy.context.scene.objects:
|
||||
if obj.type == 'MESH' and obj.name in bpy.context.view_layer.objects:
|
||||
|
@ -89,6 +91,13 @@ class TLM_CleanLightmaps(bpy.types.Operator):
|
|||
if obj.TLM_ObjectProperties.tlm_mesh_lightmap_use:
|
||||
cache.backup_material_rename(obj)
|
||||
|
||||
for obj in bpy.context.scene.objects:
|
||||
if obj.type == 'MESH' and obj.name in bpy.context.view_layer.objects:
|
||||
if obj.TLM_ObjectProperties.tlm_mesh_lightmap_use:
|
||||
for vertex_layer in obj.data.vertex_colors:
|
||||
if vertex_layer.name == "TLM":
|
||||
obj.data.vertex_colors.remove(vertex_layer)
|
||||
|
||||
for mat in bpy.data.materials:
|
||||
if mat.users < 1:
|
||||
bpy.data.materials.remove(mat)
|
||||
|
@ -146,6 +155,27 @@ class TLM_CleanLightmaps(bpy.types.Operator):
|
|||
if "Lightmap" in obj:
|
||||
del obj["Lightmap"]
|
||||
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_repartition_on_clean:
|
||||
|
||||
mats = bpy.data.materials
|
||||
|
||||
for obj in bpy.context.scene.objects:
|
||||
if obj.type == 'MESH' and obj.name in bpy.context.view_layer.objects:
|
||||
if obj.TLM_ObjectProperties.tlm_mesh_lightmap_use:
|
||||
|
||||
print("Repartitioning materials")
|
||||
|
||||
for slt in obj.material_slots:
|
||||
print("Repartitioning material: " + str(slt.name))
|
||||
part = slt.name.rpartition('.')
|
||||
if part[2].isnumeric() and part[0] in mats:
|
||||
slt.material = mats.get(part[0])
|
||||
|
||||
for slt in obj.material_slots:
|
||||
if slt.name.endswith(tuple(["001","002","003","004","005","006","007","008","009"])): #Do regex instead
|
||||
if not slt.name[:-4] in mats:
|
||||
slt.material.name = slt.name[:-4]
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
class TLM_ExploreLightmaps(bpy.types.Operator):
|
||||
|
@ -484,6 +514,19 @@ class TLM_SelectLightmapped(bpy.types.Operator):
|
|||
|
||||
return{'FINISHED'}
|
||||
|
||||
class TLM_GroupListNewItem(bpy.types.Operator):
|
||||
# Add a new item to the list
|
||||
bl_idname = "tlm_grouplist.new_item"
|
||||
bl_label = "Add a new lightmap group"
|
||||
bl_description = "Create a new lightmap group"
|
||||
|
||||
def execute(self, context):
|
||||
scene = context.scene
|
||||
scene.TLM_GroupList.add()
|
||||
scene.TLM_GroupListItem = len(scene.TLM_GroupList) - 1
|
||||
|
||||
scene.TLM_GroupList[len(scene.TLM_GroupList) - 1].name = "LightmapGroup"
|
||||
|
||||
class TLM_AtlasListNewItem(bpy.types.Operator):
|
||||
# Add a new item to the list
|
||||
bl_idname = "tlm_atlaslist.new_item"
|
||||
|
@ -952,8 +995,6 @@ class TLM_PrepareUVMaps(bpy.types.Operator):
|
|||
|
||||
scene = context.scene
|
||||
|
||||
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
class TLM_LoadLightmaps(bpy.types.Operator):
|
||||
|
@ -968,7 +1009,9 @@ class TLM_LoadLightmaps(bpy.types.Operator):
|
|||
|
||||
utility.transfer_load()
|
||||
|
||||
build.finish_assemble()
|
||||
print("Transfer finished")
|
||||
|
||||
build.finish_assemble(self, 1, 1)
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
|
@ -1029,6 +1072,582 @@ class TLM_ToggleTexelDensity(bpy.types.Operator):
|
|||
|
||||
return {'FINISHED'}
|
||||
|
||||
class TLM_DisableSpecularity(bpy.types.Operator):
|
||||
bl_idname = "tlm.disable_specularity"
|
||||
bl_label = "Disable specularity"
|
||||
bl_description = "Disables specularity from set"
|
||||
bl_options = {'REGISTER', 'UNDO'}
|
||||
|
||||
def execute(self, context):
|
||||
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_utility_set == "Scene":
|
||||
for obj in bpy.context.scene.objects:
|
||||
if obj.type == "MESH":
|
||||
|
||||
for slot in obj.material_slots:
|
||||
|
||||
mat = slot.material
|
||||
|
||||
if mat.node_tree:
|
||||
|
||||
for node in mat.node_tree.nodes:
|
||||
|
||||
if node.type == "BSDF_PRINCIPLED":
|
||||
|
||||
for inp in node.inputs:
|
||||
|
||||
if inp.name == "Specular":
|
||||
|
||||
inp.default_value = 0.0
|
||||
|
||||
if inp.links and bpy.context.scene.TLM_SceneProperties.tlm_remove_met_spec_link:
|
||||
|
||||
mat.node_tree.links.remove(inp.links[0])
|
||||
|
||||
elif bpy.context.scene.TLM_SceneProperties.tlm_utility_set == "Selection":
|
||||
for obj in bpy.context.selected_objects:
|
||||
if obj.type == "MESH":
|
||||
|
||||
for slot in obj.material_slots:
|
||||
|
||||
mat = slot.material
|
||||
|
||||
if mat.node_tree:
|
||||
|
||||
for node in mat.node_tree.nodes:
|
||||
|
||||
if node.type == "BSDF_PRINCIPLED":
|
||||
|
||||
for inp in node.inputs:
|
||||
|
||||
if inp.name == "Specular":
|
||||
|
||||
inp.default_value = 0.0
|
||||
|
||||
if inp.links and bpy.context.scene.TLM_SceneProperties.tlm_remove_met_spec_link:
|
||||
|
||||
mat.node_tree.links.remove(inp.links[0])
|
||||
|
||||
else: #Enabled
|
||||
for obj in bpy.context.scene.objects:
|
||||
if obj.type == "MESH":
|
||||
if obj.TLM_ObjectProperties.tlm_mesh_lightmap_use:
|
||||
|
||||
for slot in obj.material_slots:
|
||||
|
||||
mat = slot.material
|
||||
|
||||
if mat.node_tree:
|
||||
|
||||
for node in mat.node_tree.nodes:
|
||||
|
||||
if node.type == "BSDF_PRINCIPLED":
|
||||
|
||||
for inp in node.inputs:
|
||||
|
||||
if inp.name == "Specular":
|
||||
|
||||
inp.default_value = 0.0
|
||||
|
||||
if inp.links and bpy.context.scene.TLM_SceneProperties.tlm_remove_met_spec_link:
|
||||
|
||||
mat.node_tree.links.remove(inp.links[0])
|
||||
|
||||
return{'FINISHED'}
|
||||
|
||||
class TLM_DisableMetallic(bpy.types.Operator):
|
||||
bl_idname = "tlm.disable_metallic"
|
||||
bl_label = "Disable metallic"
|
||||
bl_description = "Disables metallic from set"
|
||||
bl_options = {'REGISTER', 'UNDO'}
|
||||
|
||||
def execute(self, context):
|
||||
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_utility_set == "Scene":
|
||||
for obj in bpy.context.scene.objects:
|
||||
if obj.type == "MESH":
|
||||
|
||||
for slot in obj.material_slots:
|
||||
|
||||
mat = slot.material
|
||||
|
||||
for node in mat.node_tree.nodes:
|
||||
|
||||
if node.type == "BSDF_PRINCIPLED":
|
||||
|
||||
for inp in node.inputs:
|
||||
|
||||
if inp.name == "Metallic":
|
||||
|
||||
inp.default_value = 0.0
|
||||
|
||||
if inp.links and bpy.context.scene.TLM_SceneProperties.tlm_remove_met_spec_link:
|
||||
|
||||
mat.node_tree.links.remove(inp.links[0])
|
||||
|
||||
elif bpy.context.scene.TLM_SceneProperties.tlm_utility_set == "Selection":
|
||||
for obj in bpy.context.selected_objects:
|
||||
if obj.type == "MESH":
|
||||
|
||||
for slot in obj.material_slots:
|
||||
|
||||
mat = slot.material
|
||||
|
||||
for node in mat.node_tree.nodes:
|
||||
|
||||
if node.type == "BSDF_PRINCIPLED":
|
||||
|
||||
for inp in node.inputs:
|
||||
|
||||
if inp.name == "Metallic":
|
||||
|
||||
inp.default_value = 0.0
|
||||
|
||||
if inp.links and bpy.context.scene.TLM_SceneProperties.tlm_remove_met_spec_link:
|
||||
|
||||
mat.node_tree.links.remove(inp.links[0])
|
||||
|
||||
else: #Enabled
|
||||
for obj in bpy.context.scene.objects:
|
||||
if obj.type == "MESH":
|
||||
if obj.TLM_ObjectProperties.tlm_mesh_lightmap_use:
|
||||
|
||||
for slot in obj.material_slots:
|
||||
|
||||
mat = slot.material
|
||||
|
||||
for node in mat.node_tree.nodes:
|
||||
|
||||
if node.type == "BSDF_PRINCIPLED":
|
||||
|
||||
for inp in node.inputs:
|
||||
|
||||
if inp.name == "Metallic":
|
||||
|
||||
inp.default_value = 0.0
|
||||
|
||||
if inp.links and bpy.context.scene.TLM_SceneProperties.tlm_remove_met_spec_link:
|
||||
|
||||
mat.node_tree.links.remove(inp.links[0])
|
||||
|
||||
return{'FINISHED'}
|
||||
|
||||
class TLM_RemoveEmptyImages(bpy.types.Operator):
|
||||
|
||||
bl_idname = "tlm.remove_empty_images"
|
||||
bl_label = "Remove Empty Images"
|
||||
bl_description = "Removes empty images from scene materials"
|
||||
bl_options = {'REGISTER', 'UNDO'}
|
||||
|
||||
def execute(self, context):
|
||||
|
||||
for mat in bpy.data.materials:
|
||||
|
||||
nodetree = mat.node_tree
|
||||
|
||||
if nodetree:
|
||||
|
||||
for node in nodetree.nodes:
|
||||
|
||||
if node.name == "Baked Image":
|
||||
|
||||
print(node.name)
|
||||
|
||||
nodetree.nodes.remove(node)
|
||||
|
||||
return{'FINISHED'}
|
||||
|
||||
|
||||
class TLM_PostAtlasSpecialsMenu(bpy.types.Menu):
|
||||
bl_label = "Lightmap"
|
||||
bl_idname = "TLM_MT_PostAtlasListSpecials"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.operator("tlm.add_collections_post")
|
||||
layout.operator("tlm.add_selected_collections_post")
|
||||
|
||||
class TLM_AddCollectionsPost(bpy.types.Operator):
|
||||
bl_idname = "tlm.add_collections_post"
|
||||
bl_label = "Add collections"
|
||||
bl_description = "Adds all collections to atlases"
|
||||
bl_options = {'REGISTER', 'UNDO'}
|
||||
|
||||
resolution : bpy.props.EnumProperty(
|
||||
items = [('32', '32', 'TODO'),
|
||||
('64', '64', 'TODO'),
|
||||
('128', '128', 'TODO'),
|
||||
('256', '256', 'TODO'),
|
||||
('512', '512', 'TODO'),
|
||||
('1024', '1024', 'TODO'),
|
||||
('2048', '2048', 'TODO'),
|
||||
('4096', '4096', 'TODO'),
|
||||
('8192', '8192', 'TODO')],
|
||||
name = "Atlas Lightmap Resolution",
|
||||
description="Atlas lightmap resolution",
|
||||
default='256')
|
||||
|
||||
unwrap_modes = [('Lightmap', 'Lightmap', 'Use Blender Lightmap Pack algorithm'),
|
||||
('SmartProject', 'Smart Project', 'Use Blender Smart Project algorithm')]
|
||||
|
||||
if "blender_xatlas" in bpy.context.preferences.addons.keys():
|
||||
unwrap_modes.append(('Xatlas', 'Xatlas', 'Use Xatlas addon packing algorithm'))
|
||||
|
||||
unwrap : bpy.props.EnumProperty(
|
||||
items = unwrap_modes,
|
||||
name = "Unwrap Mode",
|
||||
description="Atlas unwrapping method",
|
||||
default='SmartProject')
|
||||
|
||||
margin : bpy.props.FloatProperty(
|
||||
name="Unwrap Margin",
|
||||
default=0.1,
|
||||
min=0.0,
|
||||
max=1.0,
|
||||
subtype='FACTOR')
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return True
|
||||
|
||||
def execute(self, context):
|
||||
|
||||
for collection in bpy.context.scene.collection.children:
|
||||
|
||||
#Add a new atlas with collection name
|
||||
#Traverse before adding
|
||||
scene = bpy.context.scene
|
||||
scene.TLM_PostAtlasList.add()
|
||||
scene.TLM_PostAtlasListItem = len(scene.TLM_PostAtlasList) - 1
|
||||
|
||||
scene.TLM_PostAtlasList[len(scene.TLM_PostAtlasList) - 1].name = collection.name
|
||||
scene.TLM_PostAtlasList[collection.name].tlm_atlas_lightmap_unwrap_mode = self.unwrap
|
||||
scene.TLM_PostAtlasList[collection.name].tlm_atlas_lightmap_resolution = self.resolution
|
||||
scene.TLM_PostAtlasList[collection.name].tlm_atlas_unwrap_margin = self.margin
|
||||
|
||||
for obj in collection.objects:
|
||||
if obj.type == "MESH":
|
||||
obj.TLM_ObjectProperties.tlm_mesh_lightmap_use = True
|
||||
obj.TLM_ObjectProperties.tlm_postpack_object = True
|
||||
obj.TLM_ObjectProperties.tlm_postatlas_pointer = collection.name
|
||||
|
||||
return{'FINISHED'}
|
||||
|
||||
def invoke(self, context, event):
|
||||
return context.window_manager.invoke_props_dialog(self)
|
||||
|
||||
def draw(self, context):
|
||||
row = self.layout
|
||||
row.prop(self, "unwrap", text="Unwrap mode")
|
||||
row.prop(self, "resolution", text="Resolution")
|
||||
row.prop(self, "margin", text="Margin")
|
||||
|
||||
class TLM_AddSelectedCollectionsPost(bpy.types.Operator):
|
||||
bl_idname = "tlm.add_selected_collections_post"
|
||||
bl_label = "Add selected collections"
|
||||
bl_description = "Add the collections of the selected objects"
|
||||
bl_options = {'REGISTER', 'UNDO'}
|
||||
|
||||
resolution : bpy.props.EnumProperty(
|
||||
items = [('32', '32', 'TODO'),
|
||||
('64', '64', 'TODO'),
|
||||
('128', '128', 'TODO'),
|
||||
('256', '256', 'TODO'),
|
||||
('512', '512', 'TODO'),
|
||||
('1024', '1024', 'TODO'),
|
||||
('2048', '2048', 'TODO'),
|
||||
('4096', '4096', 'TODO'),
|
||||
('8192', '8192', 'TODO')],
|
||||
name = "Atlas Lightmap Resolution",
|
||||
description="Atlas lightmap resolution",
|
||||
default='256')
|
||||
|
||||
unwrap_modes = [('Lightmap', 'Lightmap', 'Use Blender Lightmap Pack algorithm'),
|
||||
('SmartProject', 'Smart Project', 'Use Blender Smart Project algorithm')]
|
||||
|
||||
if "blender_xatlas" in bpy.context.preferences.addons.keys():
|
||||
unwrap_modes.append(('Xatlas', 'Xatlas', 'Use Xatlas addon packing algorithm'))
|
||||
|
||||
unwrap : bpy.props.EnumProperty(
|
||||
items = unwrap_modes,
|
||||
name = "Unwrap Mode",
|
||||
description="Atlas unwrapping method",
|
||||
default='SmartProject')
|
||||
|
||||
margin : bpy.props.FloatProperty(
|
||||
name="Unwrap Margin",
|
||||
default=0.1,
|
||||
min=0.0,
|
||||
max=1.0,
|
||||
subtype='FACTOR')
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return True
|
||||
|
||||
def execute(self, context):
|
||||
|
||||
collections = []
|
||||
|
||||
for obj in bpy.context.selected_objects:
|
||||
|
||||
obj_collection = obj.users_collection[0]
|
||||
|
||||
if obj_collection.name not in collections:
|
||||
|
||||
collections.append(obj_collection.name)
|
||||
|
||||
print("Collections:" + str(collections))
|
||||
|
||||
for collection in bpy.context.scene.collection.children:
|
||||
|
||||
if collection.name in collections:
|
||||
|
||||
#Add a new atlas with collection name
|
||||
#Traverse before adding
|
||||
scene = bpy.context.scene
|
||||
scene.TLM_PostAtlasList.add()
|
||||
scene.TLM_PostAtlasListItem = len(scene.TLM_PostAtlasList) - 1
|
||||
|
||||
scene.TLM_PostAtlasList[len(scene.TLM_PostAtlasList) - 1].name = collection.name
|
||||
scene.TLM_PostAtlasList[collection.name].tlm_atlas_lightmap_unwrap_mode = self.unwrap
|
||||
scene.TLM_PostAtlasList[collection.name].tlm_atlas_lightmap_resolution = self.resolution
|
||||
scene.TLM_PostAtlasList[collection.name].tlm_atlas_unwrap_margin = self.margin
|
||||
|
||||
for obj in collection.objects:
|
||||
if obj.type == "MESH":
|
||||
obj.TLM_ObjectProperties.tlm_mesh_lightmap_use = True
|
||||
obj.TLM_ObjectProperties.tlm_postpack_object = True
|
||||
obj.TLM_ObjectProperties.tlm_postatlas_pointer = collection.name
|
||||
|
||||
return{'FINISHED'}
|
||||
|
||||
def invoke(self, context, event):
|
||||
return context.window_manager.invoke_props_dialog(self)
|
||||
|
||||
def draw(self, context):
|
||||
row = self.layout
|
||||
row.prop(self, "unwrap", text="Unwrap mode")
|
||||
row.prop(self, "resolution", text="Resolution")
|
||||
row.prop(self, "margin", text="Margin")
|
||||
|
||||
class TLM_AtlasSpecialsMenu(bpy.types.Menu):
|
||||
bl_label = "Lightmap"
|
||||
bl_idname = "TLM_MT_AtlasListSpecials"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.operator("tlm.add_collections")
|
||||
layout.operator("tlm.add_selected_collections")
|
||||
|
||||
class TLM_AddCollections(bpy.types.Operator):
|
||||
bl_idname = "tlm.add_collections"
|
||||
bl_label = "Add all collections"
|
||||
bl_description = "Adds all collections to atlases"
|
||||
bl_options = {'REGISTER', 'UNDO'}
|
||||
|
||||
resolution : bpy.props.EnumProperty(
|
||||
items = [('32', '32', 'TODO'),
|
||||
('64', '64', 'TODO'),
|
||||
('128', '128', 'TODO'),
|
||||
('256', '256', 'TODO'),
|
||||
('512', '512', 'TODO'),
|
||||
('1024', '1024', 'TODO'),
|
||||
('2048', '2048', 'TODO'),
|
||||
('4096', '4096', 'TODO'),
|
||||
('8192', '8192', 'TODO')],
|
||||
name = "Atlas Lightmap Resolution",
|
||||
description="Atlas lightmap resolution",
|
||||
default='256')
|
||||
|
||||
unwrap_modes = [('Lightmap', 'Lightmap', 'Use Blender Lightmap Pack algorithm'),
|
||||
('SmartProject', 'Smart Project', 'Use Blender Smart Project algorithm'),
|
||||
('Copy', 'Copy existing', 'Use the existing UV channel')]
|
||||
|
||||
if "blender_xatlas" in bpy.context.preferences.addons.keys():
|
||||
unwrap_modes.append(('Xatlas', 'Xatlas', 'Use Xatlas addon packing algorithm'))
|
||||
|
||||
unwrap : bpy.props.EnumProperty(
|
||||
items = unwrap_modes,
|
||||
name = "Unwrap Mode",
|
||||
description="Atlas unwrapping method",
|
||||
default='SmartProject')
|
||||
|
||||
margin : bpy.props.FloatProperty(
|
||||
name="Unwrap Margin",
|
||||
default=0.1,
|
||||
min=0.0,
|
||||
max=1.0,
|
||||
subtype='FACTOR')
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return True
|
||||
|
||||
def execute(self, context):
|
||||
|
||||
for collection in bpy.context.scene.collection.children:
|
||||
|
||||
#Add a new atlas with collection name
|
||||
#Traverse before adding
|
||||
scene = bpy.context.scene
|
||||
scene.TLM_AtlasList.add()
|
||||
scene.TLM_AtlasListItem = len(scene.TLM_AtlasList) - 1
|
||||
|
||||
scene.TLM_AtlasList[len(scene.TLM_AtlasList) - 1].name = collection.name
|
||||
scene.TLM_AtlasList[collection.name].tlm_atlas_lightmap_unwrap_mode = self.unwrap
|
||||
scene.TLM_AtlasList[collection.name].tlm_atlas_lightmap_resolution = self.resolution
|
||||
scene.TLM_AtlasList[collection.name].tlm_atlas_unwrap_margin = self.margin
|
||||
|
||||
for obj in collection.objects:
|
||||
if obj.type == "MESH":
|
||||
obj.TLM_ObjectProperties.tlm_mesh_lightmap_use = True
|
||||
obj.TLM_ObjectProperties.tlm_mesh_lightmap_unwrap_mode = "AtlasGroupA"
|
||||
obj.TLM_ObjectProperties.tlm_atlas_pointer = collection.name
|
||||
|
||||
return{'FINISHED'}
|
||||
|
||||
def invoke(self, context, event):
|
||||
return context.window_manager.invoke_props_dialog(self)
|
||||
|
||||
def draw(self, context):
|
||||
row = self.layout
|
||||
row.prop(self, "unwrap", text="Unwrap mode")
|
||||
row.prop(self, "resolution", text="Resolution")
|
||||
row.prop(self, "margin", text="Margin")
|
||||
|
||||
class TLM_AddSelectedCollections(bpy.types.Operator):
|
||||
bl_idname = "tlm.add_selected_collections"
|
||||
bl_label = "Add the collections of the selected objects"
|
||||
bl_description = "Add the collections of the selected objects"
|
||||
bl_options = {'REGISTER', 'UNDO'}
|
||||
|
||||
resolution : bpy.props.EnumProperty(
|
||||
items = [('32', '32', 'TODO'),
|
||||
('64', '64', 'TODO'),
|
||||
('128', '128', 'TODO'),
|
||||
('256', '256', 'TODO'),
|
||||
('512', '512', 'TODO'),
|
||||
('1024', '1024', 'TODO'),
|
||||
('2048', '2048', 'TODO'),
|
||||
('4096', '4096', 'TODO'),
|
||||
('8192', '8192', 'TODO')],
|
||||
name = "Atlas Lightmap Resolution",
|
||||
description="Atlas lightmap resolution",
|
||||
default='256')
|
||||
|
||||
unwrap_modes = [('Lightmap', 'Lightmap', 'Use Blender Lightmap Pack algorithm'),
|
||||
('SmartProject', 'Smart Project', 'Use Blender Smart Project algorithm'),
|
||||
('Copy', 'Copy existing', 'Use the existing UV channel')]
|
||||
|
||||
if "blender_xatlas" in bpy.context.preferences.addons.keys():
|
||||
unwrap_modes.append(('Xatlas', 'Xatlas', 'Use Xatlas addon packing algorithm'))
|
||||
|
||||
unwrap : bpy.props.EnumProperty(
|
||||
items = unwrap_modes,
|
||||
name = "Unwrap Mode",
|
||||
description="Atlas unwrapping method",
|
||||
default='SmartProject')
|
||||
|
||||
margin : bpy.props.FloatProperty(
|
||||
name="Unwrap Margin",
|
||||
default=0.1,
|
||||
min=0.0,
|
||||
max=1.0,
|
||||
subtype='FACTOR')
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return True
|
||||
|
||||
def execute(self, context):
|
||||
|
||||
collections = []
|
||||
|
||||
for obj in bpy.context.selected_objects:
|
||||
|
||||
obj_collection = obj.users_collection[0]
|
||||
|
||||
if obj_collection.name not in collections:
|
||||
|
||||
collections.append(obj_collection.name)
|
||||
|
||||
print("Collections:" + str(collections))
|
||||
|
||||
for collection in bpy.context.scene.collection.children:
|
||||
|
||||
if collection.name in collections:
|
||||
|
||||
#Add a new atlas with collection name
|
||||
#Traverse before adding
|
||||
scene = bpy.context.scene
|
||||
scene.TLM_AtlasList.add()
|
||||
scene.TLM_AtlasListItem = len(scene.TLM_AtlasList) - 1
|
||||
|
||||
scene.TLM_AtlasList[len(scene.TLM_AtlasList) - 1].name = collection.name
|
||||
scene.TLM_AtlasList[collection.name].tlm_atlas_lightmap_unwrap_mode = self.unwrap
|
||||
scene.TLM_AtlasList[collection.name].tlm_atlas_lightmap_resolution = self.resolution
|
||||
scene.TLM_AtlasList[collection.name].tlm_atlas_unwrap_margin = self.margin
|
||||
|
||||
for obj in collection.objects:
|
||||
if obj.type == "MESH":
|
||||
obj.TLM_ObjectProperties.tlm_mesh_lightmap_use = True
|
||||
obj.TLM_ObjectProperties.tlm_mesh_lightmap_unwrap_mode = "AtlasGroupA"
|
||||
obj.TLM_ObjectProperties.tlm_atlas_pointer = collection.name
|
||||
|
||||
return{'FINISHED'}
|
||||
|
||||
def invoke(self, context, event):
|
||||
return context.window_manager.invoke_props_dialog(self)
|
||||
|
||||
def draw(self, context):
|
||||
row = self.layout
|
||||
row.prop(self, "unwrap", text="Unwrap mode")
|
||||
row.prop(self, "resolution", text="Resolution")
|
||||
row.prop(self, "margin", text="Margin")
|
||||
|
||||
#Atlas disable objects
|
||||
|
||||
class TLM_Reset(bpy.types.Operator):
|
||||
bl_idname = "tlm.reset"
|
||||
bl_label = "Resets all UI and settings"
|
||||
bl_description = "Reset UI and objects"
|
||||
bl_options = {'REGISTER', 'UNDO'}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return True
|
||||
|
||||
def execute(self, context):
|
||||
self.report({'INFO'}, "YES!")
|
||||
return {'FINISHED'}
|
||||
|
||||
def invoke(self, context, event):
|
||||
return context.window_manager.invoke_confirm(self, event)
|
||||
|
||||
# class TLM_Reset2(bpy.types.Operator):
|
||||
# bl_idname = "tlm.reset2"
|
||||
# bl_label = "Do you really want to do that?"
|
||||
# bl_options = {'REGISTER', 'INTERNAL'}
|
||||
|
||||
# prop1: bpy.props.BoolProperty()
|
||||
# prop2: bpy.props.BoolProperty()
|
||||
|
||||
# @classmethod
|
||||
# def poll(cls, context):
|
||||
# return True
|
||||
|
||||
# def execute(self, context):
|
||||
# self.report({'INFO'}, "YES!")
|
||||
# return {'FINISHED'}
|
||||
|
||||
# def invoke(self, context, event):
|
||||
# return context.window_manager.invoke_props_dialog(self)
|
||||
|
||||
# def draw(self, context):
|
||||
# row = self.layout
|
||||
# row.prop(self, "prop1", text="Property A")
|
||||
# row.prop(self, "prop2", text="Property B")
|
||||
|
||||
def TLM_DoubleResolution():
|
||||
pass
|
||||
|
@ -1037,4 +1656,76 @@ def TLM_HalfResolution():
|
|||
pass
|
||||
|
||||
def TLM_DivideLMGroups():
|
||||
pass
|
||||
pass
|
||||
|
||||
class TLM_CalcTexDex(bpy.types.Operator):
|
||||
bl_idname = "tlm.calctexdex"
|
||||
bl_label = "Calculate Texel Density"
|
||||
bl_description = "Calculates Texel Density of selected object"
|
||||
bl_options = {'REGISTER', 'UNDO'}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return True
|
||||
|
||||
def execute(self, context):
|
||||
return {'FINISHED'}
|
||||
|
||||
class TLM_AddGLTFNode(bpy.types.Operator):
|
||||
bl_idname = "tlm.add_gltf_node"
|
||||
bl_label = "Add GLTF Node"
|
||||
bl_description = "Add to GLTF node to active material and connect lightmap if present"
|
||||
bl_options = {'REGISTER', 'UNDO'}
|
||||
|
||||
def execute(self, context):
|
||||
|
||||
scene = context.scene
|
||||
cycles = scene.cycles
|
||||
material = bpy.context.active_object.active_material
|
||||
|
||||
nodes = material.node_tree.nodes
|
||||
# create group data
|
||||
gltf_settings = bpy.data.node_groups.get('glTF Settings')
|
||||
if gltf_settings is None:
|
||||
bpy.data.node_groups.new('glTF Settings', 'ShaderNodeTree')
|
||||
|
||||
# add group to node tree
|
||||
gltf_settings_node = nodes.get('glTF Settings')
|
||||
if gltf_settings_node is None:
|
||||
gltf_settings_node = nodes.new('ShaderNodeGroup')
|
||||
gltf_settings_node.name = 'glTF Settings'
|
||||
gltf_settings_node.node_tree = bpy.data.node_groups['glTF Settings']
|
||||
|
||||
# create group inputs
|
||||
if gltf_settings_node.inputs.get('Occlusion') is None:
|
||||
gltf_settings_node.inputs.new('NodeSocketFloat','Occlusion')
|
||||
|
||||
#return gltf_settings_node
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
class TLM_ShiftMultiplyLinks(bpy.types.Operator):
|
||||
bl_idname = "tlm.shift_multiply_links"
|
||||
bl_label = "Shift multiply links"
|
||||
bl_description = "Shift multiply links for active material"
|
||||
bl_options = {'REGISTER', 'UNDO'}
|
||||
|
||||
def execute(self, context):
|
||||
|
||||
scene = context.scene
|
||||
cycles = scene.cycles
|
||||
material = bpy.context.active_object.active_material
|
||||
|
||||
nodes = material.node_tree.nodes
|
||||
|
||||
LM_Node = nodes.get("TLM_Lightmap")
|
||||
Multi_Node = nodes.get("Lightmap_Multiplication")
|
||||
Base_Node = nodes.get("Lightmap_BasecolorNode_A")
|
||||
|
||||
material.node_tree.links.remove(LM_Node.outputs[0].links[0])
|
||||
material.node_tree.links.remove(Base_Node.outputs[0].links[0])
|
||||
|
||||
material.node_tree.links.new(LM_Node.outputs[0], Multi_Node.inputs[2])
|
||||
material.node_tree.links.new(Base_Node.outputs[0], Multi_Node.inputs[1])
|
||||
|
||||
return {'FINISHED'}
|
||||
|
|
|
@ -93,6 +93,14 @@ class TLM_PT_ObjectMenu(bpy.types.Panel):
|
|||
row = layout.row(align=True)
|
||||
row.prop(obj.TLM_ObjectProperties, "tlm_mesh_filtering_iterations")
|
||||
|
||||
#If UV Packer installed
|
||||
if "UV-Packer" in bpy.context.preferences.addons.keys():
|
||||
row.prop(obj.TLM_ObjectProperties, "tlm_use_uv_packer")
|
||||
if obj.TLM_ObjectProperties.tlm_use_uv_packer:
|
||||
row = layout.row(align=True)
|
||||
row.prop(obj.TLM_ObjectProperties, "tlm_uv_packer_padding")
|
||||
row = layout.row(align=True)
|
||||
row.prop(obj.TLM_ObjectProperties, "tlm_uv_packer_packing_engine")
|
||||
|
||||
class TLM_PT_MaterialMenu(bpy.types.Panel):
|
||||
bl_label = "The Lightmapper"
|
||||
|
|
|
@ -4,6 +4,50 @@ from bpy.types import Menu, Panel
|
|||
from .. utility import icon
|
||||
from .. properties.denoiser import oidn, optix
|
||||
|
||||
class TLM_PT_Panel(bpy.types.Panel):
|
||||
bl_label = "The Lightmapper"
|
||||
bl_space_type = "PROPERTIES"
|
||||
bl_region_type = "WINDOW"
|
||||
bl_context = "render"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
scene = context.scene
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
sceneProperties = scene.TLM_SceneProperties
|
||||
|
||||
class TLM_PT_Groups(bpy.types.Panel):
|
||||
bl_label = "Lightmap Groups"
|
||||
bl_space_type = "PROPERTIES"
|
||||
bl_region_type = "WINDOW"
|
||||
bl_context = "render"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
bl_parent_id = "TLM_PT_Panel"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
scene = context.scene
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
sceneProperties = scene.TLM_SceneProperties
|
||||
|
||||
if sceneProperties.tlm_lightmap_engine == "Cycles":
|
||||
|
||||
rows = 2
|
||||
#if len(atlasList) > 1:
|
||||
# rows = 4
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.label(text="Lightmap Group List")
|
||||
row = layout.row(align=True)
|
||||
row.template_list("TLM_UL_GroupList", "Lightmap Groups", scene, "TLM_GroupList", scene, "TLM_GroupListItem", rows=rows)
|
||||
col = row.column(align=True)
|
||||
col.operator("tlm_atlaslist.new_item", icon='ADD', text="")
|
||||
#col.operator("tlm_atlaslist.delete_item", icon='REMOVE', text="")
|
||||
#col.menu("TLM_MT_AtlasListSpecials", icon='DOWNARROW_HLT', text="")
|
||||
|
||||
class TLM_PT_Settings(bpy.types.Panel):
|
||||
bl_label = "Settings"
|
||||
bl_space_type = "PROPERTIES"
|
||||
|
@ -64,6 +108,14 @@ class TLM_PT_Settings(bpy.types.Panel):
|
|||
row.prop(sceneProperties, "tlm_override_color")
|
||||
row = layout.row(align=True)
|
||||
row.prop(sceneProperties, "tlm_reset_uv")
|
||||
row = layout.row(align=True)
|
||||
row.prop(sceneProperties, "tlm_apply_modifiers")
|
||||
row = layout.row(align=True)
|
||||
row.prop(sceneProperties, "tlm_keep_baked_files")
|
||||
row = layout.row(align=True)
|
||||
row.prop(sceneProperties, "tlm_repartition_on_clean")
|
||||
row = layout.row(align=True)
|
||||
row.prop(sceneProperties, "tlm_save_preprocess_lightmaps")
|
||||
|
||||
row = layout.row(align=True)
|
||||
try:
|
||||
|
@ -259,9 +311,7 @@ class TLM_PT_Filtering(bpy.types.Panel):
|
|||
|
||||
if cv2 is None:
|
||||
row = layout.row(align=True)
|
||||
row.label(text="OpenCV is not installed. Please install it as an administrator.")
|
||||
row = layout.row(align=True)
|
||||
row.operator("tlm.install_opencv_lightmaps")
|
||||
row.label(text="OpenCV is not installed. Install it through preferences.")
|
||||
else:
|
||||
row = layout.row(align=True)
|
||||
row.prop(scene.TLM_SceneProperties, "tlm_filtering_mode")
|
||||
|
@ -357,6 +407,9 @@ class TLM_PT_Encoding(bpy.types.Panel):
|
|||
if sceneProperties.tlm_encoding_mode_b == "LogLuv" and sceneProperties.tlm_encoding_device == "GPU":
|
||||
row = layout.row(align=True)
|
||||
row.prop(sceneProperties, "tlm_decoder_setup")
|
||||
if sceneProperties.tlm_decoder_setup:
|
||||
row = layout.row(align=True)
|
||||
row.prop(sceneProperties, "tlm_split_premultiplied")
|
||||
if sceneProperties.tlm_encoding_mode_b == "HDR":
|
||||
row = layout.row(align=True)
|
||||
row.prop(sceneProperties, "tlm_format")
|
||||
|
@ -384,30 +437,183 @@ class TLM_PT_Utility(bpy.types.Panel):
|
|||
row = layout.row(align=True)
|
||||
row.label(text="Enable Lightmaps for set")
|
||||
row = layout.row(align=True)
|
||||
row.operator("tlm.enable_set")
|
||||
row.prop(sceneProperties, "tlm_utility_context")
|
||||
row = layout.row(align=True)
|
||||
row.prop(sceneProperties, "tlm_utility_set")
|
||||
row = layout.row(align=True)
|
||||
#row.label(text="ABCD")
|
||||
row.prop(sceneProperties, "tlm_mesh_lightmap_unwrap_mode")
|
||||
|
||||
if sceneProperties.tlm_mesh_lightmap_unwrap_mode == "AtlasGroupA":
|
||||
if sceneProperties.tlm_utility_context == "SetBatching":
|
||||
|
||||
row.operator("tlm.enable_set")
|
||||
row = layout.row(align=True)
|
||||
row.prop(sceneProperties, "tlm_utility_set")
|
||||
row = layout.row(align=True)
|
||||
#row.label(text="ABCD")
|
||||
row.prop(sceneProperties, "tlm_mesh_lightmap_unwrap_mode")
|
||||
|
||||
if sceneProperties.tlm_mesh_lightmap_unwrap_mode == "AtlasGroupA":
|
||||
|
||||
if scene.TLM_AtlasListItem >= 0 and len(scene.TLM_AtlasList) > 0:
|
||||
row = layout.row()
|
||||
item = scene.TLM_AtlasList[scene.TLM_AtlasListItem]
|
||||
row.prop_search(sceneProperties, "tlm_atlas_pointer", scene, "TLM_AtlasList", text='Atlas Group')
|
||||
else:
|
||||
row = layout.label(text="Add Atlas Groups from the scene lightmapping settings.")
|
||||
|
||||
if scene.TLM_AtlasListItem >= 0 and len(scene.TLM_AtlasList) > 0:
|
||||
row = layout.row()
|
||||
item = scene.TLM_AtlasList[scene.TLM_AtlasListItem]
|
||||
row.prop_search(sceneProperties, "tlm_atlas_pointer", scene, "TLM_AtlasList", text='Atlas Group')
|
||||
else:
|
||||
row = layout.label(text="Add Atlas Groups from the scene lightmapping settings.")
|
||||
|
||||
else:
|
||||
row = layout.row()
|
||||
row.prop(sceneProperties, "tlm_postpack_object")
|
||||
row = layout.row()
|
||||
|
||||
if sceneProperties.tlm_postpack_object and sceneProperties.tlm_mesh_lightmap_unwrap_mode != "AtlasGroupA":
|
||||
|
||||
if scene.TLM_PostAtlasListItem >= 0 and len(scene.TLM_PostAtlasList) > 0:
|
||||
row = layout.row()
|
||||
item = scene.TLM_PostAtlasList[scene.TLM_PostAtlasListItem]
|
||||
row.prop_search(sceneProperties, "tlm_postatlas_pointer", scene, "TLM_PostAtlasList", text='Atlas Group')
|
||||
row = layout.row()
|
||||
|
||||
else:
|
||||
row = layout.label(text="Add Atlas Groups from the scene lightmapping settings.")
|
||||
row = layout.row()
|
||||
|
||||
row.prop(sceneProperties, "tlm_mesh_unwrap_margin")
|
||||
row = layout.row()
|
||||
row.prop(sceneProperties, "tlm_resolution_weight")
|
||||
|
||||
if sceneProperties.tlm_resolution_weight == "Single":
|
||||
row = layout.row()
|
||||
row.prop(sceneProperties, "tlm_mesh_lightmap_resolution")
|
||||
else:
|
||||
row = layout.row()
|
||||
row.prop(sceneProperties, "tlm_resolution_min")
|
||||
row = layout.row()
|
||||
row.prop(sceneProperties, "tlm_resolution_max")
|
||||
|
||||
row = layout.row()
|
||||
row.prop(sceneProperties, "tlm_postpack_object")
|
||||
row = layout.row()
|
||||
row.operator("tlm.disable_selection")
|
||||
row = layout.row(align=True)
|
||||
row.operator("tlm.select_lightmapped_objects")
|
||||
row = layout.row(align=True)
|
||||
row.operator("tlm.remove_uv_selection")
|
||||
|
||||
if sceneProperties.tlm_postpack_object and sceneProperties.tlm_mesh_lightmap_unwrap_mode != "AtlasGroupA":
|
||||
elif sceneProperties.tlm_utility_context == "EnvironmentProbes":
|
||||
|
||||
row.label(text="Environment Probes")
|
||||
row = layout.row()
|
||||
row.operator("tlm.build_environmentprobe")
|
||||
row = layout.row()
|
||||
row.operator("tlm.clean_environmentprobe")
|
||||
row = layout.row()
|
||||
row.prop(sceneProperties, "tlm_environment_probe_engine")
|
||||
row = layout.row()
|
||||
row.prop(sceneProperties, "tlm_cmft_path")
|
||||
row = layout.row()
|
||||
row.prop(sceneProperties, "tlm_environment_probe_resolution")
|
||||
row = layout.row()
|
||||
row.prop(sceneProperties, "tlm_create_spherical")
|
||||
|
||||
if sceneProperties.tlm_create_spherical:
|
||||
|
||||
row = layout.row()
|
||||
row.prop(sceneProperties, "tlm_invert_direction")
|
||||
row = layout.row()
|
||||
row.prop(sceneProperties, "tlm_write_sh")
|
||||
row = layout.row()
|
||||
row.prop(sceneProperties, "tlm_write_radiance")
|
||||
|
||||
elif sceneProperties.tlm_utility_context == "LoadLightmaps":
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.label(text="Load lightmaps")
|
||||
row = layout.row()
|
||||
row.prop(sceneProperties, "tlm_load_folder")
|
||||
row = layout.row()
|
||||
row.operator("tlm.load_lightmaps")
|
||||
row = layout.row()
|
||||
row.prop(sceneProperties, "tlm_load_atlas")
|
||||
|
||||
elif sceneProperties.tlm_utility_context == "MaterialAdjustment":
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.prop(sceneProperties, "tlm_utility_set")
|
||||
row = layout.row(align=True)
|
||||
row.operator("tlm.disable_specularity")
|
||||
row.operator("tlm.disable_metallic")
|
||||
row = layout.row(align=True)
|
||||
row.prop(sceneProperties, "tlm_remove_met_spec_link")
|
||||
row = layout.row(align=True)
|
||||
row.operator("tlm.remove_empty_images")
|
||||
row = layout.row(align=True)
|
||||
|
||||
elif sceneProperties.tlm_utility_context == "NetworkRender":
|
||||
|
||||
row.label(text="Network Rendering")
|
||||
row = layout.row()
|
||||
row.operator("tlm.start_server")
|
||||
layout.label(text="Atlas Groups")
|
||||
|
||||
elif sceneProperties.tlm_utility_context == "TexelDensity":
|
||||
|
||||
row.label(text="Texel Density Utilies")
|
||||
row = layout.row()
|
||||
|
||||
elif sceneProperties.tlm_utility_context == "GLTFUtil":
|
||||
|
||||
row.label(text="GLTF material utilities")
|
||||
row = layout.row()
|
||||
row.operator("tlm.add_gltf_node")
|
||||
row = layout.row()
|
||||
row.operator("tlm.shift_multiply_links")
|
||||
|
||||
class TLM_PT_Selection(bpy.types.Panel):
|
||||
bl_label = "Selection"
|
||||
bl_space_type = "PROPERTIES"
|
||||
bl_region_type = "WINDOW"
|
||||
bl_context = "render"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
bl_parent_id = "ARM_PT_BakePanel"
|
||||
|
||||
@classmethod
|
||||
def poll(self, context):
|
||||
scene = context.scene
|
||||
return scene.arm_bakemode == "Lightmap"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
scene = context.scene
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
sceneProperties = scene.TLM_SceneProperties
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.operator("tlm.enable_selection")
|
||||
row = layout.row(align=True)
|
||||
row.operator("tlm.disable_selection")
|
||||
row = layout.row(align=True)
|
||||
row.prop(sceneProperties, "tlm_override_object_settings")
|
||||
|
||||
if sceneProperties.tlm_override_object_settings:
|
||||
|
||||
row = layout.row(align=True)
|
||||
row = layout.row()
|
||||
row.prop(sceneProperties, "tlm_mesh_lightmap_unwrap_mode")
|
||||
row = layout.row()
|
||||
|
||||
if sceneProperties.tlm_mesh_lightmap_unwrap_mode == "AtlasGroupA":
|
||||
|
||||
if scene.TLM_AtlasListItem >= 0 and len(scene.TLM_AtlasList) > 0:
|
||||
row = layout.row()
|
||||
item = scene.TLM_AtlasList[scene.TLM_AtlasListItem]
|
||||
row.prop_search(sceneProperties, "tlm_atlas_pointer", scene, "TLM_AtlasList", text='Atlas Group')
|
||||
else:
|
||||
row = layout.label(text="Add Atlas Groups from the scene lightmapping settings.")
|
||||
|
||||
else:
|
||||
row = layout.row()
|
||||
row.prop(sceneProperties, "tlm_postpack_object")
|
||||
row = layout.row()
|
||||
|
||||
if sceneProperties.tlm_postpack_object and sceneProperties.tlm_mesh_lightmap_unwrap_mode != "AtlasGroupA":
|
||||
if scene.TLM_PostAtlasListItem >= 0 and len(scene.TLM_PostAtlasList) > 0:
|
||||
row = layout.row()
|
||||
item = scene.TLM_PostAtlasList[scene.TLM_PostAtlasListItem]
|
||||
|
@ -418,57 +624,20 @@ class TLM_PT_Utility(bpy.types.Panel):
|
|||
row = layout.label(text="Add Atlas Groups from the scene lightmapping settings.")
|
||||
row = layout.row()
|
||||
|
||||
row.prop(sceneProperties, "tlm_mesh_unwrap_margin")
|
||||
row = layout.row()
|
||||
row.prop(sceneProperties, "tlm_resolution_weight")
|
||||
|
||||
if sceneProperties.tlm_resolution_weight == "Single":
|
||||
row = layout.row()
|
||||
if sceneProperties.tlm_mesh_lightmap_unwrap_mode != "AtlasGroupA":
|
||||
row.prop(sceneProperties, "tlm_mesh_lightmap_resolution")
|
||||
else:
|
||||
row = layout.row()
|
||||
row.prop(sceneProperties, "tlm_resolution_min")
|
||||
row = layout.row()
|
||||
row.prop(sceneProperties, "tlm_resolution_max")
|
||||
row.prop(sceneProperties, "tlm_mesh_unwrap_margin")
|
||||
|
||||
row = layout.row()
|
||||
row.operator("tlm.disable_selection")
|
||||
row = layout.row(align=True)
|
||||
row.operator("tlm.select_lightmapped_objects")
|
||||
row = layout.row(align=True)
|
||||
row.operator("tlm.remove_uv_selection")
|
||||
row = layout.row(align=True)
|
||||
|
||||
|
||||
row.label(text="Environment Probes")
|
||||
row = layout.row()
|
||||
row.operator("tlm.build_environmentprobe")
|
||||
row = layout.row()
|
||||
row.operator("tlm.clean_environmentprobe")
|
||||
row = layout.row()
|
||||
row.prop(sceneProperties, "tlm_environment_probe_engine")
|
||||
row = layout.row()
|
||||
row.prop(sceneProperties, "tlm_cmft_path")
|
||||
row = layout.row()
|
||||
row.prop(sceneProperties, "tlm_environment_probe_resolution")
|
||||
row = layout.row()
|
||||
row.prop(sceneProperties, "tlm_create_spherical")
|
||||
|
||||
if sceneProperties.tlm_create_spherical:
|
||||
|
||||
row = layout.row()
|
||||
row.prop(sceneProperties, "tlm_invert_direction")
|
||||
row = layout.row()
|
||||
row.prop(sceneProperties, "tlm_write_sh")
|
||||
row = layout.row()
|
||||
row.prop(sceneProperties, "tlm_write_radiance")
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.label(text="Load lightmaps")
|
||||
row = layout.row()
|
||||
row.prop(sceneProperties, "tlm_load_folder")
|
||||
row = layout.row()
|
||||
row.operator("tlm.load_lightmaps")
|
||||
row.operator("tlm.select_lightmapped_objects")
|
||||
# row = layout.row(align=True)
|
||||
# for addon in bpy.context.preferences.addons.keys():
|
||||
# if addon.startswith("Texel_Density"):
|
||||
# row.operator("tlm.toggle_texel_density")
|
||||
# row = layout.row(align=True)
|
||||
|
||||
class TLM_PT_Additional(bpy.types.Panel):
|
||||
bl_label = "Additional"
|
||||
|
@ -492,10 +661,6 @@ class TLM_PT_Additional(bpy.types.Panel):
|
|||
postatlasListItem = scene.TLM_PostAtlasListItem
|
||||
postatlasList = scene.TLM_PostAtlasList
|
||||
|
||||
layout.label(text="Network Rendering")
|
||||
row = layout.row()
|
||||
row.operator("tlm.start_server")
|
||||
layout.label(text="Atlas Groups")
|
||||
row = layout.row()
|
||||
row.prop(sceneProperties, "tlm_atlas_mode", expand=True)
|
||||
|
||||
|
@ -509,6 +674,7 @@ class TLM_PT_Additional(bpy.types.Panel):
|
|||
col = row.column(align=True)
|
||||
col.operator("tlm_atlaslist.new_item", icon='ADD', text="")
|
||||
col.operator("tlm_atlaslist.delete_item", icon='REMOVE', text="")
|
||||
col.menu("TLM_MT_AtlasListSpecials", icon='DOWNARROW_HLT', text="")
|
||||
|
||||
if atlasListItem >= 0 and len(atlasList) > 0:
|
||||
item = atlasList[atlasListItem]
|
||||
|
@ -525,6 +691,11 @@ class TLM_PT_Additional(bpy.types.Panel):
|
|||
amount = amount + 1
|
||||
|
||||
layout.label(text="Objects: " + str(amount))
|
||||
layout.prop(item, "tlm_atlas_merge_samemat")
|
||||
|
||||
layout.prop(item, "tlm_use_uv_packer")
|
||||
layout.prop(item, "tlm_uv_packer_padding")
|
||||
layout.prop(item, "tlm_uv_packer_packing_engine")
|
||||
|
||||
else:
|
||||
|
||||
|
@ -547,6 +718,7 @@ class TLM_PT_Additional(bpy.types.Panel):
|
|||
col = row.column(align=True)
|
||||
col.operator("tlm_postatlaslist.new_item", icon='ADD', text="")
|
||||
col.operator("tlm_postatlaslist.delete_item", icon='REMOVE', text="")
|
||||
col.menu("TLM_MT_PostAtlasListSpecials", icon='DOWNARROW_HLT', text="")
|
||||
|
||||
if postatlasListItem >= 0 and len(postatlasList) > 0:
|
||||
item = postatlasList[postatlasListItem]
|
||||
|
@ -581,4 +753,4 @@ class TLM_PT_Additional(bpy.types.Panel):
|
|||
layout.label(text="Utilized: " + str(utilized * 100) + "%")
|
||||
|
||||
if (utilized * 100) > 100:
|
||||
layout.label(text="Warning! Overflow not yet supported")
|
||||
layout.label(text="Warning! Overflow not yet supported")
|
||||
|
|
|
@ -1,12 +1,19 @@
|
|||
import bpy, platform
|
||||
from os.path import basename, dirname
|
||||
from bpy.types import AddonPreferences
|
||||
from bpy.props import *
|
||||
from .. operators import installopencv
|
||||
from . import addon_preferences
|
||||
import importlib
|
||||
|
||||
class TLM_AddonPreferences(AddonPreferences):
|
||||
|
||||
bl_idname = "thelightmapper"
|
||||
bl_idname = __name__.split(".")[0]
|
||||
|
||||
tlm_ui_mode: EnumProperty(
|
||||
items=[('simple', 'Simple', 'Simple UI'),
|
||||
('advanced', 'Advanced', 'Advanced UI')],
|
||||
name='UI mode', default='simple', description='Choose UI mode')
|
||||
|
||||
def draw(self, context):
|
||||
|
||||
|
@ -14,6 +21,15 @@ class TLM_AddonPreferences(AddonPreferences):
|
|||
|
||||
box = layout.box()
|
||||
row = box.row()
|
||||
|
||||
row.label(text="UI Mode")
|
||||
row.prop(self, "tlm_ui_mode")
|
||||
row = box.row()
|
||||
row.label(text="Simple: Only the basic setup for Blender/Eevee baking with non-experimental features.")
|
||||
row = box.row()
|
||||
row.label(text="Full set of options available.")
|
||||
row = box.row()
|
||||
|
||||
row.label(text="OpenCV")
|
||||
|
||||
cv2 = importlib.util.find_spec("cv2")
|
||||
|
@ -48,6 +64,21 @@ class TLM_AddonPreferences(AddonPreferences):
|
|||
row.label(text="UVPackmaster")
|
||||
row.label(text="Coming soon")
|
||||
|
||||
uvpacker_addon = False
|
||||
for addon in bpy.context.preferences.addons.keys():
|
||||
if addon.startswith("UV-Packer"):
|
||||
uvpacker_addon = True
|
||||
|
||||
box = layout.box()
|
||||
row = box.row()
|
||||
row.label(text="UV Packer")
|
||||
if uvpacker_addon:
|
||||
row.label(text="UV Packer installed and available")
|
||||
else:
|
||||
row.label(text="UV Packer not installed", icon_value=2)
|
||||
row = box.row()
|
||||
row.label(text="Github: https://www.uv-packer.com/blender/")
|
||||
|
||||
texel_density_addon = False
|
||||
for addon in bpy.context.preferences.addons.keys():
|
||||
if addon.startswith("Texel_Density"):
|
||||
|
|
|
@ -16,7 +16,9 @@ classes = [
|
|||
atlas.TLM_UL_AtlasList,
|
||||
atlas.TLM_PostAtlasListItem,
|
||||
atlas.TLM_UL_PostAtlasList,
|
||||
image.TLM_ImageProperties
|
||||
image.TLM_ImageProperties,
|
||||
scene.TLM_UL_GroupList,
|
||||
scene.TLM_GroupListItem
|
||||
]
|
||||
|
||||
def register():
|
||||
|
@ -35,6 +37,8 @@ def register():
|
|||
bpy.types.Scene.TLM_PostAtlasListItem = bpy.props.IntProperty(name="Index for my_list", default=0)
|
||||
bpy.types.Scene.TLM_PostAtlasList = bpy.props.CollectionProperty(type=atlas.TLM_PostAtlasListItem)
|
||||
bpy.types.Image.TLM_ImageProperties = bpy.props.PointerProperty(type=image.TLM_ImageProperties)
|
||||
bpy.types.Scene.TLM_GroupListItem = bpy.props.IntProperty(name="Index for my_list", default=0)
|
||||
bpy.types.Scene.TLM_GroupList = bpy.props.CollectionProperty(type=scene.TLM_GroupListItem)
|
||||
|
||||
bpy.types.Material.TLM_ignore = bpy.props.BoolProperty(name="Skip material", description="Ignore material for lightmapped object", default=False)
|
||||
|
||||
|
@ -53,4 +57,6 @@ def unregister():
|
|||
del bpy.types.Scene.TLM_AtlasList
|
||||
del bpy.types.Scene.TLM_PostAtlasListItem
|
||||
del bpy.types.Scene.TLM_PostAtlasList
|
||||
del bpy.types.Image.TLM_ImageProperties
|
||||
del bpy.types.Image.TLM_ImageProperties
|
||||
del bpy.types.Scene.TLM_GroupListItem
|
||||
del bpy.types.Scene.TLM_GroupList
|
|
@ -35,11 +35,17 @@ class TLM_PostAtlasListItem(bpy.types.PropertyGroup):
|
|||
subtype='FACTOR')
|
||||
|
||||
unwrap_modes = [('Lightmap', 'Lightmap', 'Use Blender Lightmap Pack algorithm'),
|
||||
('SmartProject', 'Smart Project', 'Use Blender Smart Project algorithm')]
|
||||
('SmartProject', 'Smart Project', 'Use Blender Smart Project algorithm'),
|
||||
('Copy', 'Copy existing', 'Use the existing UV channel')]
|
||||
|
||||
if "blender_xatlas" in bpy.context.preferences.addons.keys():
|
||||
unwrap_modes.append(('Xatlas', 'Xatlas', 'Use Xatlas addon packing algorithm'))
|
||||
|
||||
tlm_atlas_merge_samemat : BoolProperty(
|
||||
name="Merge materials",
|
||||
description="Merge objects with same materials.",
|
||||
default=True)
|
||||
|
||||
tlm_postatlas_lightmap_unwrap_mode : EnumProperty(
|
||||
items = unwrap_modes,
|
||||
name = "Unwrap Mode",
|
||||
|
@ -109,6 +115,30 @@ class TLM_AtlasListItem(bpy.types.PropertyGroup):
|
|||
description="Atlas unwrapping method",
|
||||
default='SmartProject')
|
||||
|
||||
tlm_atlas_merge_samemat : BoolProperty(
|
||||
name="Merge materials",
|
||||
description="Merge objects with same materials.",
|
||||
default=True)
|
||||
|
||||
tlm_use_uv_packer : BoolProperty(
|
||||
name="Use UV Packer",
|
||||
description="UV Packer will be utilized after initial UV mapping for optimized packing.",
|
||||
default=False)
|
||||
|
||||
tlm_uv_packer_padding : FloatProperty(
|
||||
name="Padding",
|
||||
default=2.0,
|
||||
min=0.0,
|
||||
max=100.0,
|
||||
subtype='FACTOR')
|
||||
|
||||
tlm_uv_packer_packing_engine : EnumProperty(
|
||||
items = [('OP0', 'Efficient', 'Best compromise for speed and space usage.'),
|
||||
('OP1', 'High Quality', 'Slowest, but maximum space usage.')],
|
||||
name = "Packing Engine",
|
||||
description="Which UV Packer engine to use.",
|
||||
default='OP0')
|
||||
|
||||
class TLM_UL_AtlasList(bpy.types.UIList):
|
||||
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
|
||||
custom_icon = 'OBJECT_DATAMODE'
|
||||
|
|
|
@ -51,7 +51,8 @@ class TLM_ObjectProperties(bpy.types.PropertyGroup):
|
|||
|
||||
unwrap_modes = [('Lightmap', 'Lightmap', 'TODO'),
|
||||
('SmartProject', 'Smart Project', 'TODO'),
|
||||
('AtlasGroupA', 'Atlas Group (Prepack)', 'Attaches the object to a prepack Atlas group. Will overwrite UV map on build.')]
|
||||
('AtlasGroupA', 'Atlas Group (Prepack)', 'Attaches the object to a prepack Atlas group. Will overwrite UV map on build.'),
|
||||
('Copy', 'Copy existing', 'Use the existing UV channel')]
|
||||
|
||||
tlm_postpack_object : BoolProperty( #CHECK INSTEAD OF ATLASGROUPB
|
||||
name="Postpack object",
|
||||
|
@ -154,4 +155,28 @@ class TLM_ObjectProperties(bpy.types.PropertyGroup):
|
|||
tlm_uv_channel : StringProperty(
|
||||
name = "UV Channel",
|
||||
description = "Use any custom UV Channel for the lightmap",
|
||||
default = "UVMap")
|
||||
default = "UVMap")
|
||||
|
||||
tlm_use_uv_packer : BoolProperty(
|
||||
name="Use UV Packer",
|
||||
description="UV Packer will be utilized after initial UV mapping for optimized packing.",
|
||||
default=False)
|
||||
|
||||
tlm_uv_packer_padding : FloatProperty(
|
||||
name="Padding",
|
||||
default=2.0,
|
||||
min=0.0,
|
||||
max=100.0,
|
||||
subtype='FACTOR')
|
||||
|
||||
tlm_uv_packer_packing_engine : EnumProperty(
|
||||
items = [('OP0', 'Efficient', 'Best compromise for speed and space usage.'),
|
||||
('OP1', 'High Quality', 'Slowest, but maximum space usage.')],
|
||||
name = "Packing Engine",
|
||||
description="Which UV Packer engine to use.",
|
||||
default='OP0')
|
||||
|
||||
#Padding
|
||||
#Type
|
||||
#Rescale
|
||||
#Pre-rotate
|
|
@ -102,7 +102,7 @@ class TLM_CyclesSceneProperties(bpy.types.PropertyGroup):
|
|||
items = [('combined', 'Combined', 'Bake combined lighting'),
|
||||
('combinedao', 'Combined+AO', 'Bake combined lighting with Ambient Occlusion'),
|
||||
('indirect', 'Indirect', 'Bake indirect lighting'),
|
||||
# ('indirectao', 'Indirect+AO', 'Bake indirect lighting with Ambient Occlusion'),
|
||||
('indirectao', 'Indirect+AO', 'Bake indirect lighting with Ambient Occlusion'),
|
||||
('ao', 'AO', 'Bake only Ambient Occlusion'),
|
||||
('complete', 'Complete', 'Bake complete map')],
|
||||
name = "Lighting mode",
|
||||
|
|
|
@ -45,6 +45,16 @@ class TLM_SceneProperties(bpy.types.PropertyGroup):
|
|||
description="Keep cache files (non-filtered and non-denoised)",
|
||||
default=True)
|
||||
|
||||
tlm_keep_baked_files : BoolProperty(
|
||||
name="Keep bake files",
|
||||
description="Keep the baked lightmap files when cleaning",
|
||||
default=False)
|
||||
|
||||
tlm_repartition_on_clean : BoolProperty(
|
||||
name="Repartition on clean",
|
||||
description="Repartition material names on clean",
|
||||
default=False)
|
||||
|
||||
tlm_setting_renderer : EnumProperty(
|
||||
items = [('CPU', 'CPU', 'Bake using the processor'),
|
||||
('GPU', 'GPU', 'Bake using the graphics card')],
|
||||
|
@ -103,6 +113,11 @@ class TLM_SceneProperties(bpy.types.PropertyGroup):
|
|||
name="Apply scale",
|
||||
description="TODO",
|
||||
default=False)
|
||||
|
||||
tlm_save_preprocess_lightmaps : BoolProperty(
|
||||
name="Save preprocessed lightmaps",
|
||||
description="TODO",
|
||||
default=False)
|
||||
|
||||
#DENOISE SETTINGS GROUP
|
||||
tlm_denoise_use : BoolProperty(
|
||||
|
@ -179,7 +194,7 @@ class TLM_SceneProperties(bpy.types.PropertyGroup):
|
|||
max=100)
|
||||
|
||||
tlm_filtering_bilateral_coordinate_deviation : IntProperty(
|
||||
name="Color deviation",
|
||||
name="Coordinate deviation",
|
||||
default=75,
|
||||
min=1,
|
||||
max=100)
|
||||
|
@ -233,7 +248,7 @@ class TLM_SceneProperties(bpy.types.PropertyGroup):
|
|||
tlm_encoding_mode_b : EnumProperty(
|
||||
items = encoding_modes_2,
|
||||
name = "Encoding Mode",
|
||||
description="TODO",
|
||||
description="RGBE 32-bit Radiance HDR File",
|
||||
default='HDR')
|
||||
|
||||
tlm_encoding_range : IntProperty(
|
||||
|
@ -245,7 +260,12 @@ class TLM_SceneProperties(bpy.types.PropertyGroup):
|
|||
|
||||
tlm_decoder_setup : BoolProperty(
|
||||
name="Use decoder",
|
||||
description="TODO",
|
||||
description="Apply a node for decoding.",
|
||||
default=False)
|
||||
|
||||
tlm_split_premultiplied : BoolProperty(
|
||||
name="Split for premultiplied",
|
||||
description="Some game engines doesn't support non-premultiplied files. This splits the alpha channel to a separate file.",
|
||||
default=False)
|
||||
|
||||
tlm_encoding_colorspace : EnumProperty(
|
||||
|
@ -385,6 +405,16 @@ class TLM_SceneProperties(bpy.types.PropertyGroup):
|
|||
description="Remove existing UV maps for lightmaps.",
|
||||
default=False)
|
||||
|
||||
tlm_apply_modifiers : BoolProperty(
|
||||
name="Apply modifiers",
|
||||
description="Apply all modifiers to objects.",
|
||||
default=True)
|
||||
|
||||
tlm_batch_mode : BoolProperty(
|
||||
name="Batch mode",
|
||||
description="Batch collections.",
|
||||
default=False)
|
||||
|
||||
tlm_network_render : BoolProperty(
|
||||
name="Enable network rendering",
|
||||
description="Enable network rendering (Unstable).",
|
||||
|
@ -453,6 +483,11 @@ class TLM_SceneProperties(bpy.types.PropertyGroup):
|
|||
description="Load existing lightmaps from folder",
|
||||
subtype="DIR_PATH")
|
||||
|
||||
tlm_load_atlas : BoolProperty(
|
||||
name="Load lightmaps based on atlas sets",
|
||||
description="Use the current Atlas list.",
|
||||
default=False)
|
||||
|
||||
tlm_utility_set : EnumProperty(
|
||||
items = [('Scene', 'Scene', 'Set for all objects in the scene.'),
|
||||
('Selection', 'Selection', 'Set for selected objects.'),
|
||||
|
@ -494,4 +529,57 @@ class TLM_SceneProperties(bpy.types.PropertyGroup):
|
|||
('4096', '4096', 'TODO')],
|
||||
name = "Maximum resolution",
|
||||
description="Maximum distributed resolution",
|
||||
default='256')
|
||||
default='256')
|
||||
|
||||
tlm_remove_met_spec_link : BoolProperty(
|
||||
name="Remove image link",
|
||||
description="Removes the connected node on metallic or specularity set disable",
|
||||
default=False)
|
||||
|
||||
tlm_utility_context : EnumProperty(
|
||||
items = [('SetBatching', 'Set Batching', 'Set batching options. Allows to set lightmap options for multiple objects.'),
|
||||
('EnvironmentProbes', 'Environment Probes', 'Options for rendering environment probes. Cubemaps and panoramic HDRs for external engines'),
|
||||
('LoadLightmaps', 'Load Lightmaps', 'Options for loading pre-built lightmaps.'),
|
||||
('NetworkRender', 'Network Rendering', 'Distribute lightmap building across multiple machines.'),
|
||||
('MaterialAdjustment', 'Material Adjustment', 'Allows adjustment of multiple materials at once.'),
|
||||
('TexelDensity', 'Texel Density', 'Allows setting texel densities of the UV.'),
|
||||
('GLTFUtil', 'GLTF Utilities', 'GLTF related material utilities.')],
|
||||
name = "Utility Context",
|
||||
description="Set Utility Context",
|
||||
default='SetBatching')
|
||||
|
||||
tlm_addon_uimode : EnumProperty(
|
||||
items = [('Simple', 'Simple', 'TODO'),
|
||||
('Advanced', 'Advanced', 'TODO')],
|
||||
name = "UI Mode",
|
||||
description="TODO",
|
||||
default='Simple')
|
||||
|
||||
class TLM_GroupListItem(bpy.types.PropertyGroup):
|
||||
obj: PointerProperty(type=bpy.types.Object, description="The object to bake")
|
||||
|
||||
class TLM_UL_GroupList(bpy.types.UIList):
|
||||
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
|
||||
custom_icon = 'OBJECT_DATAMODE'
|
||||
|
||||
if self.layout_type in {'DEFAULT', 'COMPACT'}:
|
||||
|
||||
amount = 0
|
||||
|
||||
for obj in bpy.context.scene.objects:
|
||||
if obj.TLM_ObjectProperties.tlm_mesh_lightmap_use:
|
||||
if obj.TLM_ObjectProperties.tlm_mesh_lightmap_unwrap_mode == "AtlasGroupA":
|
||||
if obj.TLM_ObjectProperties.tlm_atlas_pointer == item.name:
|
||||
amount = amount + 1
|
||||
|
||||
row = layout.row()
|
||||
row.prop(item, "name", text="", emboss=False, icon=custom_icon)
|
||||
col = row.column()
|
||||
col.label(text=item.tlm_atlas_lightmap_resolution)
|
||||
col = row.column()
|
||||
col.alignment = 'RIGHT'
|
||||
col.label(text=str(amount))
|
||||
|
||||
elif self.layout_type in {'GRID'}:
|
||||
layout.alignment = 'CENTER'
|
||||
layout.label(text="", icon = custom_icon)
|
|
@ -1,6 +1,6 @@
|
|||
import bpy, os, subprocess, sys, platform, aud, json, datetime, socket
|
||||
|
||||
from . import encoding, pack
|
||||
from . import encoding, pack, log
|
||||
from . cycles import lightmap, prepare, nodes, cache
|
||||
from . luxcore import setup
|
||||
from . octane import configure, lightmap2
|
||||
|
@ -16,9 +16,15 @@ from importlib import util
|
|||
|
||||
previous_settings = {}
|
||||
postprocess_shutdown = False
|
||||
logging = True
|
||||
|
||||
def prepare_build(self=0, background_mode=False, shutdown_after_build=False):
|
||||
|
||||
global tlm_log
|
||||
tlm_log = log.TLM_Logman()
|
||||
bpy.app.driver_namespace["logman"] = tlm_log
|
||||
tlm_log.append("Preparing build")
|
||||
|
||||
if shutdown_after_build:
|
||||
postprocess_shutdown = True
|
||||
|
||||
|
@ -46,29 +52,33 @@ def prepare_build(self=0, background_mode=False, shutdown_after_build=False):
|
|||
scene = bpy.context.scene
|
||||
sceneProperties = scene.TLM_SceneProperties
|
||||
|
||||
if not background_mode and bpy.context.scene.TLM_EngineProperties.tlm_lighting_mode != "combinedao":
|
||||
if not background_mode and bpy.context.scene.TLM_EngineProperties.tlm_lighting_mode != "combinedao" and bpy.context.scene.TLM_EngineProperties.tlm_lighting_mode != "indirectao":
|
||||
#pass
|
||||
setGui(1)
|
||||
|
||||
if check_save():
|
||||
print("Please save your file first")
|
||||
self.report({'INFO'}, "Please save your file first")
|
||||
setGui(0)
|
||||
return{'FINISHED'}
|
||||
|
||||
if check_denoiser():
|
||||
print("No denoise OIDN path assigned")
|
||||
self.report({'INFO'}, "No denoise OIDN path assigned")
|
||||
self.report({'INFO'}, "No denoise OIDN path assigned. Check that it points to the correct executable.")
|
||||
setGui(0)
|
||||
return{'FINISHED'}
|
||||
|
||||
if check_materials():
|
||||
print("Error with material")
|
||||
self.report({'INFO'}, "Error with material")
|
||||
setGui(0)
|
||||
return{'FINISHED'}
|
||||
|
||||
if opencv_check():
|
||||
if sceneProperties.tlm_filtering_use:
|
||||
print("Error:Filtering - OpenCV not installed")
|
||||
self.report({'INFO'}, "Error:Filtering - OpenCV not installed")
|
||||
setGui(0)
|
||||
return{'FINISHED'}
|
||||
|
||||
setMode()
|
||||
|
@ -174,6 +184,7 @@ def distribute_building():
|
|||
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
print("No process file - Creating one...")
|
||||
tlm_log.append("No process file - Creating one...")
|
||||
|
||||
write_directory = os.path.join(os.path.dirname(bpy.data.filepath), bpy.context.scene.TLM_EngineProperties.tlm_lightmap_savedir)
|
||||
|
||||
|
@ -197,6 +208,7 @@ def distribute_building():
|
|||
bpy.app.driver_namespace["tlm_process"] = subprocess.Popen([bpy.app.binary_path,"-b", blendPath,"--python-expr",'import bpy; import thelightmapper; thelightmapper.addon.utility.build.prepare_build(0, True);'], shell=False, stdout=subprocess.PIPE)
|
||||
else:
|
||||
bpy.app.driver_namespace["tlm_process"] = subprocess.Popen([bpy.app.binary_path,"-b", blendPath,"--python-expr",'import bpy; import thelightmapper; thelightmapper.addon.utility.build.prepare_build(0, True);'], shell=False, stderr=subprocess.DEVNULL, stdout=subprocess.DEVNULL)
|
||||
tlm_log.append("Started process: " + str(bpy.app.driver_namespace["tlm_process"]) + " at " + str(datetime.datetime.now()))
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
print("Started process: " + str(bpy.app.driver_namespace["tlm_process"]) + " at " + str(datetime.datetime.now()))
|
||||
|
||||
|
@ -208,6 +220,7 @@ def distribute_building():
|
|||
|
||||
if process_status[1]["completed"]:
|
||||
|
||||
tlm_log.append("Baking finished from process. Status: Completed.")
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
print("Baking finished")
|
||||
|
||||
|
@ -218,21 +231,31 @@ def distribute_building():
|
|||
else:
|
||||
|
||||
#Open the json and check the status!
|
||||
tlm_log.append("Process check: Baking in progress.")
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
print("Baking in progress")
|
||||
|
||||
process_status = json.loads(open(os.path.join(write_directory, "process.tlm")).read())
|
||||
|
||||
tlm_log.append(process_status)
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
print(process_status)
|
||||
|
||||
return 1.0
|
||||
|
||||
|
||||
def finish_assemble(self=0):
|
||||
def finish_assemble(self=0, background_pass=0, load_atlas=0):
|
||||
|
||||
print("Finishing assembly")
|
||||
|
||||
tlm_log = log.TLM_Logman()
|
||||
tlm_log.append("Preparing build")
|
||||
|
||||
if load_atlas:
|
||||
print("Assembly in Atlas load mode")
|
||||
tlm_log.append("Assembly in Atlas load mode")
|
||||
|
||||
tlm_log.append("Background baking finished")
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
print("Background baking finished")
|
||||
|
||||
|
@ -253,7 +276,10 @@ def finish_assemble(self=0):
|
|||
global start_time
|
||||
start_time = time()
|
||||
|
||||
manage_build(True)
|
||||
if background_pass:
|
||||
manage_build(True, load_atlas)
|
||||
else:
|
||||
manage_build(False, load_atlas)
|
||||
|
||||
def begin_build():
|
||||
|
||||
|
@ -266,7 +292,18 @@ def begin_build():
|
|||
|
||||
if sceneProperties.tlm_lightmap_engine == "Cycles":
|
||||
|
||||
lightmap.bake()
|
||||
try:
|
||||
lightmap.bake()
|
||||
except Exception as e:
|
||||
|
||||
print("An error occured during lightmap baking. See the line below for more detail:")
|
||||
print(f"{type(e).__name__} at line {e.__traceback__.tb_lineno} of {__file__}: {e}")
|
||||
|
||||
tlm_log.append("An error occured during lightmap baking. See the line below for more detail:")
|
||||
tlm_log.append(f"{type(e).__name__} at line {e.__traceback__.tb_lineno} of {__file__}: {e}")
|
||||
|
||||
if not bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
print("Turn on verbose mode to get more detail.")
|
||||
|
||||
if sceneProperties.tlm_lightmap_engine == "LuxCoreRender":
|
||||
pass
|
||||
|
@ -288,6 +325,7 @@ def begin_build():
|
|||
if file.endswith("_baked.hdr"):
|
||||
baked_image_array.append(file)
|
||||
|
||||
tlm_log.append(baked_image_array)
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
print(baked_image_array)
|
||||
|
||||
|
@ -313,7 +351,18 @@ def begin_build():
|
|||
|
||||
denoiser = oidn.TLM_OIDN_Denoise(oidnProperties, baked_image_array, dirpath)
|
||||
|
||||
denoiser.denoise()
|
||||
try:
|
||||
denoiser.denoise()
|
||||
except Exception as e:
|
||||
|
||||
print("An error occured during denoising. See the line below for more detail:")
|
||||
print(f"{type(e).__name__} at line {e.__traceback__.tb_lineno} of {__file__}: {e}")
|
||||
|
||||
tlm_log.append("An error occured during denoising. See the line below for more detail:")
|
||||
tlm_log.append(f"{type(e).__name__} at line {e.__traceback__.tb_lineno} of {__file__}: {e}")
|
||||
|
||||
if not bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
print("Turn on verbose mode to get more detail.")
|
||||
|
||||
denoiser.clean()
|
||||
|
||||
|
@ -349,7 +398,19 @@ def begin_build():
|
|||
|
||||
filter = opencv.TLM_CV_Filtering
|
||||
|
||||
filter.init(dirpath, useDenoise)
|
||||
try:
|
||||
filter.init(dirpath, useDenoise)
|
||||
|
||||
except Exception as e:
|
||||
|
||||
print("An error occured during filtering. See the line below for more detail:")
|
||||
print(f"{type(e).__name__} at line {e.__traceback__.tb_lineno} of {__file__}: {e}")
|
||||
|
||||
tlm_log.append("An error occured during filtering. See the line below for more detail:")
|
||||
tlm_log.append(f"{type(e).__name__} at line {e.__traceback__.tb_lineno} of {__file__}: {e}")
|
||||
|
||||
if not bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
print("Turn on verbose mode to get more detail.")
|
||||
|
||||
#Encoding
|
||||
if sceneProperties.tlm_encoding_use and scene.TLM_EngineProperties.tlm_bake_mode != "Background":
|
||||
|
@ -360,7 +421,9 @@ def begin_build():
|
|||
|
||||
if sceneProperties.tlm_format == "EXR":
|
||||
|
||||
tlm_log.append("EXR Format")
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
|
||||
print("EXR Format")
|
||||
|
||||
ren = bpy.context.scene.render
|
||||
|
@ -390,7 +453,9 @@ def begin_build():
|
|||
|
||||
if sceneProperties.tlm_encoding_mode_a == "RGBM":
|
||||
|
||||
tlm_log.append("ENCODING RGBM")
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
|
||||
print("ENCODING RGBM")
|
||||
|
||||
dirfiles = [f for f in listdir(dirpath) if isfile(join(dirpath, f))]
|
||||
|
@ -410,13 +475,16 @@ def begin_build():
|
|||
|
||||
img = bpy.data.images.load(os.path.join(dirpath, file), check_existing=False)
|
||||
|
||||
tlm_log.append("Encoding:" + str(file))
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
print("Encoding:" + str(file))
|
||||
encoding.encodeImageRGBMCPU(img, sceneProperties.tlm_encoding_range, dirpath, 0)
|
||||
|
||||
if sceneProperties.tlm_encoding_mode_a == "RGBD":
|
||||
|
||||
tlm_log.append("ENCODING RGBD")
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
|
||||
print("ENCODING RGBD")
|
||||
|
||||
dirfiles = [f for f in listdir(dirpath) if isfile(join(dirpath, f))]
|
||||
|
@ -437,12 +505,15 @@ def begin_build():
|
|||
img = bpy.data.images.load(os.path.join(dirpath, file), check_existing=False)
|
||||
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
tlm_log.append("Encoding:" + str(file))
|
||||
print("Encoding:" + str(file))
|
||||
encoding.encodeImageRGBDCPU(img, sceneProperties.tlm_encoding_range, dirpath, 0)
|
||||
|
||||
if sceneProperties.tlm_encoding_mode_a == "SDR":
|
||||
|
||||
tlm_log.append("EXR Format")
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
|
||||
print("EXR Format")
|
||||
|
||||
ren = bpy.context.scene.render
|
||||
|
@ -476,7 +547,9 @@ def begin_build():
|
|||
|
||||
if sceneProperties.tlm_format == "EXR":
|
||||
|
||||
tlm_log.append("EXR Format")
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
|
||||
print("EXR Format")
|
||||
|
||||
ren = bpy.context.scene.render
|
||||
|
@ -518,6 +591,7 @@ def begin_build():
|
|||
|
||||
end = "_filtered"
|
||||
|
||||
#CHECK FOR ATLAS MAPS!
|
||||
for file in dirfiles:
|
||||
if file.endswith(end + ".hdr"):
|
||||
|
||||
|
@ -525,9 +599,23 @@ def begin_build():
|
|||
|
||||
encoding.encodeLogLuvGPU(img, dirpath, 0)
|
||||
|
||||
if sceneProperties.tlm_split_premultiplied:
|
||||
|
||||
image_name = img.name
|
||||
|
||||
if image_name[-4:] == '.exr' or image_name[-4:] == '.hdr':
|
||||
image_name = image_name[:-4]
|
||||
|
||||
image_name = image_name + '_encoded.png'
|
||||
|
||||
print("SPLIT PREMULTIPLIED: " + image_name)
|
||||
encoding.splitLogLuvAlpha(os.path.join(dirpath, image_name), dirpath, 0)
|
||||
|
||||
if sceneProperties.tlm_encoding_mode_b == "RGBM":
|
||||
|
||||
tlm_log.append("ENCODING RGBM")
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
|
||||
print("ENCODING RGBM")
|
||||
|
||||
dirfiles = [f for f in listdir(dirpath) if isfile(join(dirpath, f))]
|
||||
|
@ -606,19 +694,50 @@ def begin_build():
|
|||
|
||||
manage_build()
|
||||
|
||||
def manage_build(background_pass=False):
|
||||
def manage_build(background_pass=False, load_atlas=0):
|
||||
|
||||
print("Managing build")
|
||||
|
||||
if load_atlas:
|
||||
print("Managing in load atlas mode")
|
||||
|
||||
scene = bpy.context.scene
|
||||
sceneProperties = scene.TLM_SceneProperties
|
||||
|
||||
if sceneProperties.tlm_lightmap_engine == "Cycles":
|
||||
|
||||
if background_pass:
|
||||
nodes.apply_lightmaps()
|
||||
print("In background pass")
|
||||
|
||||
nodes.apply_materials() #From here the name is changed...
|
||||
try:
|
||||
|
||||
nodes.apply_lightmaps()
|
||||
|
||||
except Exception as e:
|
||||
|
||||
print("An error occured during lightmap application. See the line below for more detail:")
|
||||
print(f"{type(e).__name__} at line {e.__traceback__.tb_lineno} of {__file__}: {e}")
|
||||
|
||||
tlm_log.append("An error occured during lightmap application. See the line below for more detail:")
|
||||
tlm_log.append(f"{type(e).__name__} at line {e.__traceback__.tb_lineno} of {__file__}: {e}")
|
||||
|
||||
if not bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
print("Turn on verbose mode to get more detail.")
|
||||
|
||||
|
||||
try:
|
||||
nodes.apply_materials(load_atlas) #From here the name is changed...
|
||||
|
||||
except Exception as e:
|
||||
|
||||
print("An error occured during material application. See the line below for more detail:")
|
||||
print(f"{type(e).__name__} at line {e.__traceback__.tb_lineno} of {__file__}: {e}")
|
||||
|
||||
tlm_log.append("An error occured during material application. See the line below for more detail:")
|
||||
tlm_log.append(f"{type(e).__name__} at line {e.__traceback__.tb_lineno} of {__file__}: {e}")
|
||||
|
||||
if not bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
print("Turn on verbose mode to get more detail.")
|
||||
|
||||
end = "_baked"
|
||||
|
||||
|
@ -693,6 +812,111 @@ def manage_build(background_pass=False):
|
|||
supersampling_scale = 1
|
||||
|
||||
pack.postpack()
|
||||
#We need to also make sure out postpacked atlases gets split w. premultiplied
|
||||
#CHECK FOR ATLAS MAPS!
|
||||
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_encoding_use and bpy.context.scene.TLM_SceneProperties.tlm_encoding_device == "GPU":
|
||||
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_split_premultiplied and bpy.context.scene.TLM_SceneProperties.tlm_encoding_use and bpy.context.scene.TLM_SceneProperties.tlm_encoding_device == "GPU" and bpy.context.scene.TLM_SceneProperties.tlm_encoding_mode_b == "LogLuv":
|
||||
|
||||
dirpath = os.path.join(os.path.dirname(bpy.data.filepath), scene.TLM_EngineProperties.tlm_lightmap_savedir)
|
||||
dirfiles = [f for f in listdir(dirpath) if isfile(join(dirpath, f))]
|
||||
|
||||
for atlas in bpy.context.scene.TLM_PostAtlasList:
|
||||
|
||||
for file in dirfiles:
|
||||
if file.startswith(atlas.name):
|
||||
|
||||
print("TODO: SPLIT LOGLUV FOR: " + str(file))
|
||||
encoding.splitLogLuvAlpha(os.path.join(dirpath, file), dirpath, 0)
|
||||
|
||||
#Need to update file list for some reason?
|
||||
dirfiles = [f for f in listdir(dirpath) if isfile(join(dirpath, f))]
|
||||
|
||||
for atlas in bpy.context.scene.TLM_PostAtlasList:
|
||||
|
||||
#FIND SOME WAY TO FIND THE RIGTH FILE! TOO TIRED NOW!
|
||||
for obj in bpy.context.scene.objects:
|
||||
if obj.TLM_ObjectProperties.tlm_postpack_object:
|
||||
if obj.TLM_ObjectProperties.tlm_postatlas_pointer == atlas.name:
|
||||
for slot in obj.material_slots:
|
||||
|
||||
mat = slot.material
|
||||
|
||||
node_tree = mat.node_tree
|
||||
|
||||
foundBakedNode = False
|
||||
|
||||
#for file in dirfiles:
|
||||
# if file.startswith(atlas.name):
|
||||
# if file.endswith("XYZ"):
|
||||
|
||||
#Find nodes
|
||||
for node in node_tree.nodes:
|
||||
|
||||
if node.name == "TLM_Lightmap":
|
||||
|
||||
print("Found the main lightmap node: LOGLUV")
|
||||
|
||||
for file in dirfiles:
|
||||
if file.startswith(atlas.name) and file.endswith("XYZ.png"):
|
||||
print("Found an atlas file: " + str(file))
|
||||
node.image.filepath_raw = os.path.join(dirpath, file)
|
||||
print("CHANGED LIGHTMAP MAIN INTO XYZ: " + str(file))
|
||||
|
||||
if node.name == "TLM_Lightmap_Extra":
|
||||
|
||||
print("Found the main lightmap node: LOGLUV")
|
||||
|
||||
for file in dirfiles:
|
||||
if file.startswith(atlas.name) and file.endswith("W.png"):
|
||||
print("Found an atlas file: " + str(file))
|
||||
node.image.filepath_raw = os.path.join(dirpath, file)
|
||||
print("CHANGED LIGHTMAP MAIN INTO W: " + str(file))
|
||||
|
||||
#print("Found the extra lightmap node: LOGLUV")
|
||||
# if node.image.filepath_raw.startswith(atlas.name):
|
||||
# if node.image.filepath_raw.endswith("W.png"):
|
||||
# print("ALREADY W: " + str(node.image.filepath_raw))
|
||||
|
||||
# else:
|
||||
|
||||
# for file in dirfiles:
|
||||
# if file.startswith(atlas.name):
|
||||
# if file.endswith("W.png"):
|
||||
|
||||
# node.image.filepath_raw = os.path.join(dirpath, file)
|
||||
# print("CHANGED LIGHTMAP MAIN INTO W: " + str(file))
|
||||
|
||||
#for file in dirfiles:
|
||||
# if file.endswith(end + ".hdr"):
|
||||
|
||||
#for atlas in bpy.context.scene.TLM_PostAtlasList:
|
||||
|
||||
|
||||
|
||||
#print("TODO: SPLIT LOGLUV FOR: " + str(atlas.name) + "..file?")
|
||||
|
||||
#CHECK FOR ATLAS MAPS!
|
||||
#dirfiles = [f for f in listdir(dirpath) if isfile(join(dirpath, f))]
|
||||
# for file in dirfiles:
|
||||
# if file.endswith(end + ".hdr"):
|
||||
|
||||
# img = bpy.data.images.load(os.path.join(dirpath, file), check_existing=False)
|
||||
|
||||
# encoding.encodeLogLuvGPU(img, dirpath, 0)
|
||||
|
||||
# if sceneProperties.tlm_split_premultiplied:
|
||||
|
||||
# image_name = img.name
|
||||
|
||||
# if image_name[-4:] == '.exr' or image_name[-4:] == '.hdr':
|
||||
# image_name = image_name[:-4]
|
||||
|
||||
# image_name = image_name + '_encoded.png'
|
||||
|
||||
# print("SPLIT PREMULTIPLIED: " + image_name)
|
||||
# encoding.splitLogLuvAlpha(os.path.join(dirpath, image_name), dirpath, 0)
|
||||
|
||||
for image in bpy.data.images:
|
||||
if image.users < 1:
|
||||
|
@ -815,7 +1039,9 @@ def manage_build(background_pass=False):
|
|||
print("Second AO pass complete")
|
||||
|
||||
total_time = sec_to_hours((time() - start_time))
|
||||
tlm_log.append(total_time)
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
|
||||
print(total_time)
|
||||
|
||||
bpy.context.scene["TLM_Buildstat"] = total_time
|
||||
|
@ -835,6 +1061,7 @@ def manage_build(background_pass=False):
|
|||
else:
|
||||
|
||||
total_time = sec_to_hours((time() - start_time))
|
||||
tlm_log.append(total_time)
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
print(total_time)
|
||||
|
||||
|
@ -842,6 +1069,8 @@ def manage_build(background_pass=False):
|
|||
|
||||
reset_settings(previous_settings["settings"])
|
||||
|
||||
tlm_log.append("Lightmap building finished")
|
||||
tlm_log.append("--------------------------")
|
||||
print("Lightmap building finished")
|
||||
|
||||
if sceneProperties.tlm_lightmap_engine == "LuxCoreRender":
|
||||
|
@ -855,7 +1084,7 @@ def manage_build(background_pass=False):
|
|||
if bpy.context.scene.TLM_EngineProperties.tlm_bake_mode == "Background":
|
||||
pass
|
||||
|
||||
if not background_pass and bpy.context.scene.TLM_EngineProperties.tlm_lighting_mode != "combinedao":
|
||||
if not background_pass and scene.TLM_EngineProperties.tlm_bake_mode != "Background" and bpy.context.scene.TLM_EngineProperties.tlm_lighting_mode != "combinedao":
|
||||
#pass
|
||||
setGui(0)
|
||||
|
||||
|
@ -879,6 +1108,10 @@ def manage_build(background_pass=False):
|
|||
sound = aud.Sound.file(sound_path)
|
||||
device.play(sound)
|
||||
|
||||
if logging:
|
||||
print("Log file output:")
|
||||
tlm_log.dumpLog()
|
||||
|
||||
if bpy.app.background:
|
||||
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
|
@ -945,6 +1178,8 @@ def naming_check():
|
|||
obj.name = obj.name.replace("æ","ae")
|
||||
if "å" in obj.name:
|
||||
obj.name = obj.name.replace("å","aa")
|
||||
if "/" in obj.name:
|
||||
obj.name = obj.name.replace("/",".")
|
||||
|
||||
for slot in obj.material_slots:
|
||||
if "_" in slot.material.name:
|
||||
|
@ -961,6 +1196,8 @@ def naming_check():
|
|||
slot.material.name = slot.material.name.replace("æ","ae")
|
||||
if "å" in slot.material.name:
|
||||
slot.material.name = slot.material.name.replace("å","aa")
|
||||
if "/" in slot.material.name:
|
||||
slot.material.name = slot.material.name.replace("/",".")
|
||||
|
||||
def opencv_check():
|
||||
|
||||
|
@ -999,6 +1236,11 @@ def check_denoiser():
|
|||
if platform.system() == "Windows":
|
||||
if not scene.TLM_OIDNEngineProperties.tlm_oidn_path.endswith(".exe"):
|
||||
return 1
|
||||
else:
|
||||
if os.path.isfile(bpy.path.abspath(scene.TLM_OIDNEngineProperties.tlm_oidn_path)):
|
||||
return 0
|
||||
else:
|
||||
return 1
|
||||
else:
|
||||
return 0
|
||||
|
||||
|
@ -1034,7 +1276,17 @@ def setMode():
|
|||
bpy.context.view_layer.objects.active = obj
|
||||
obj.select_set(True)
|
||||
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
hidden = False
|
||||
|
||||
if obj.hide_get():
|
||||
hidden = True
|
||||
if obj.hide_viewport:
|
||||
hidden = True
|
||||
if obj.hide_render:
|
||||
hidden = True
|
||||
|
||||
if not hidden:
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
|
||||
#TODO Make some checks that returns to previous selection
|
||||
|
||||
|
@ -1092,5 +1344,4 @@ def checkAtlasSize():
|
|||
if overflow == True:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
return False
|
|
@ -4,6 +4,9 @@ from time import time, sleep
|
|||
|
||||
def bake(plus_pass=0):
|
||||
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
print("Initializing lightmap baking.")
|
||||
|
||||
for obj in bpy.context.scene.objects:
|
||||
bpy.ops.object.select_all(action='DESELECT')
|
||||
obj.select_set(False)
|
||||
|
@ -13,15 +16,74 @@ def bake(plus_pass=0):
|
|||
|
||||
for obj in bpy.context.scene.objects:
|
||||
if obj.type == 'MESH' and obj.name in bpy.context.view_layer.objects:
|
||||
if obj.TLM_ObjectProperties.tlm_mesh_lightmap_use:
|
||||
iterNum = iterNum + 1
|
||||
|
||||
hidden = False
|
||||
|
||||
#We check if the object is hidden
|
||||
if obj.hide_get():
|
||||
hidden = True
|
||||
if obj.hide_viewport:
|
||||
hidden = True
|
||||
if obj.hide_render:
|
||||
hidden = True
|
||||
|
||||
#We check if the object's collection is hidden
|
||||
collections = obj.users_collection
|
||||
|
||||
for collection in collections:
|
||||
|
||||
if collection.hide_viewport:
|
||||
hidden = True
|
||||
if collection.hide_render:
|
||||
hidden = True
|
||||
|
||||
try:
|
||||
if collection.name in bpy.context.scene.view_layers[0].layer_collection.children:
|
||||
if bpy.context.scene.view_layers[0].layer_collection.children[collection.name].hide_viewport:
|
||||
hidden = True
|
||||
except:
|
||||
print("Error: Could not find collection: " + collection.name)
|
||||
|
||||
if obj.TLM_ObjectProperties.tlm_mesh_lightmap_use and not hidden:
|
||||
iterNum = iterNum + 1
|
||||
|
||||
if iterNum > 1:
|
||||
iterNum = iterNum - 1
|
||||
|
||||
for obj in bpy.context.scene.objects:
|
||||
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
print("Checking visibility status for object and collections: " + obj.name)
|
||||
|
||||
hidden = False
|
||||
|
||||
#We check if the object is hidden
|
||||
if obj.hide_get():
|
||||
hidden = True
|
||||
if obj.hide_viewport:
|
||||
hidden = True
|
||||
if obj.hide_render:
|
||||
hidden = True
|
||||
|
||||
#We check if the object's collection is hidden
|
||||
collections = obj.users_collection
|
||||
|
||||
for collection in collections:
|
||||
|
||||
if collection.hide_viewport:
|
||||
hidden = True
|
||||
if collection.hide_render:
|
||||
hidden = True
|
||||
|
||||
try:
|
||||
if collection.name in bpy.context.scene.view_layers[0].layer_collection.children:
|
||||
if bpy.context.scene.view_layers[0].layer_collection.children[collection.name].hide_viewport:
|
||||
hidden = True
|
||||
except:
|
||||
print("Error: Could not find collection: " + collection.name)
|
||||
|
||||
if obj.type == 'MESH' and obj.name in bpy.context.view_layer.objects:
|
||||
if obj.TLM_ObjectProperties.tlm_mesh_lightmap_use:
|
||||
if obj.TLM_ObjectProperties.tlm_mesh_lightmap_use and not hidden:
|
||||
|
||||
scene = bpy.context.scene
|
||||
|
||||
|
@ -52,13 +114,16 @@ def bake(plus_pass=0):
|
|||
#print("Remaining: " + str(remaining))
|
||||
|
||||
if scene.TLM_EngineProperties.tlm_target == "vertex":
|
||||
scene.render.bake_target = "VERTEX_COLORS"
|
||||
scene.render.bake.target = "VERTEX_COLORS"
|
||||
|
||||
if scene.TLM_EngineProperties.tlm_lighting_mode == "combined":
|
||||
print("Baking combined: Direct + Indirect")
|
||||
bpy.ops.object.bake(type="DIFFUSE", pass_filter={"DIRECT","INDIRECT"}, margin=scene.TLM_EngineProperties.tlm_dilation_margin, use_clear=False)
|
||||
elif scene.TLM_EngineProperties.tlm_lighting_mode == "indirect":
|
||||
print("Baking combined: Indirect")
|
||||
bpy.ops.object.bake(type="DIFFUSE", pass_filter={"INDIRECT"}, margin=scene.TLM_EngineProperties.tlm_dilation_margin, use_clear=False)
|
||||
elif scene.TLM_EngineProperties.tlm_lighting_mode == "ao":
|
||||
print("Baking combined: AO")
|
||||
bpy.ops.object.bake(type="AO", margin=scene.TLM_EngineProperties.tlm_dilation_margin, use_clear=False)
|
||||
elif scene.TLM_EngineProperties.tlm_lighting_mode == "combinedao":
|
||||
|
||||
|
@ -67,12 +132,35 @@ def bake(plus_pass=0):
|
|||
elif bpy.app.driver_namespace["tlm_plus_mode"] == 2:
|
||||
bpy.ops.object.bake(type="AO", margin=scene.TLM_EngineProperties.tlm_dilation_margin, use_clear=False)
|
||||
|
||||
elif scene.TLM_EngineProperties.tlm_lighting_mode == "indirectao":
|
||||
|
||||
print("IndirAO")
|
||||
|
||||
if bpy.app.driver_namespace["tlm_plus_mode"] == 1:
|
||||
bpy.ops.object.bake(type="DIFFUSE", pass_filter={"DIRECT","INDIRECT"}, margin=scene.TLM_EngineProperties.tlm_dilation_margin, use_clear=False)
|
||||
elif bpy.app.driver_namespace["tlm_plus_mode"] == 2:
|
||||
bpy.ops.object.bake(type="AO", margin=scene.TLM_EngineProperties.tlm_dilation_margin, use_clear=False)
|
||||
|
||||
elif scene.TLM_EngineProperties.tlm_lighting_mode == "complete":
|
||||
bpy.ops.object.bake(type="COMBINED", margin=scene.TLM_EngineProperties.tlm_dilation_margin, use_clear=False)
|
||||
else:
|
||||
bpy.ops.object.bake(type="DIFFUSE", pass_filter={"DIRECT","INDIRECT"}, margin=scene.TLM_EngineProperties.tlm_dilation_margin, use_clear=False)
|
||||
|
||||
|
||||
#Save image between
|
||||
if scene.TLM_SceneProperties.tlm_save_preprocess_lightmaps:
|
||||
for image in bpy.data.images:
|
||||
if image.name.endswith("_baked"):
|
||||
|
||||
saveDir = os.path.join(os.path.dirname(bpy.data.filepath), bpy.context.scene.TLM_EngineProperties.tlm_lightmap_savedir)
|
||||
bakemap_path = os.path.join(saveDir, image.name)
|
||||
filepath_ext = ".hdr"
|
||||
image.filepath_raw = bakemap_path + filepath_ext
|
||||
image.file_format = "HDR"
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
print("Saving to: " + image.filepath_raw)
|
||||
image.save()
|
||||
|
||||
bpy.ops.object.select_all(action='DESELECT')
|
||||
currentIterNum = currentIterNum + 1
|
||||
|
||||
|
@ -86,4 +174,4 @@ def bake(plus_pass=0):
|
|||
image.file_format = "HDR"
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
print("Saving to: " + image.filepath_raw)
|
||||
image.save()
|
||||
image.save()
|
||||
|
|
|
@ -4,271 +4,447 @@ def apply_lightmaps():
|
|||
for obj in bpy.context.scene.objects:
|
||||
if obj.type == 'MESH' and obj.name in bpy.context.view_layer.objects:
|
||||
if obj.TLM_ObjectProperties.tlm_mesh_lightmap_use:
|
||||
for slot in obj.material_slots:
|
||||
mat = slot.material
|
||||
node_tree = mat.node_tree
|
||||
nodes = mat.node_tree.nodes
|
||||
|
||||
scene = bpy.context.scene
|
||||
hidden = False
|
||||
|
||||
dirpath = os.path.join(os.path.dirname(bpy.data.filepath), scene.TLM_EngineProperties.tlm_lightmap_savedir)
|
||||
if obj.hide_get():
|
||||
hidden = True
|
||||
if obj.hide_viewport:
|
||||
hidden = True
|
||||
if obj.hide_render:
|
||||
hidden = True
|
||||
|
||||
#Find nodes
|
||||
for node in nodes:
|
||||
if node.name == "Baked Image":
|
||||
|
||||
extension = ".hdr"
|
||||
|
||||
postfix = "_baked"
|
||||
|
||||
if scene.TLM_SceneProperties.tlm_denoise_use:
|
||||
postfix = "_denoised"
|
||||
if scene.TLM_SceneProperties.tlm_filtering_use:
|
||||
postfix = "_filtered"
|
||||
|
||||
node.image.source = "FILE"
|
||||
image_name = obj.name + postfix + extension #TODO FIX EXTENSION
|
||||
node.image.filepath_raw = os.path.join(dirpath, image_name)
|
||||
|
||||
|
||||
def apply_materials():
|
||||
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
print("Applying materials")
|
||||
|
||||
for obj in bpy.context.scene.objects:
|
||||
if obj.type == 'MESH' and obj.name in bpy.context.view_layer.objects:
|
||||
if obj.TLM_ObjectProperties.tlm_mesh_lightmap_use:
|
||||
|
||||
uv_layers = obj.data.uv_layers
|
||||
uv_layers.active_index = 0
|
||||
scene = bpy.context.scene
|
||||
|
||||
decoding = False
|
||||
|
||||
#Sort name
|
||||
for slot in obj.material_slots:
|
||||
mat = slot.material
|
||||
if mat.name.endswith('_temp'):
|
||||
old = slot.material
|
||||
slot.material = bpy.data.materials[old.name.split('_' + obj.name)[0]]
|
||||
|
||||
if(scene.TLM_SceneProperties.tlm_decoder_setup):
|
||||
|
||||
tlm_rgbm = bpy.data.node_groups.get('RGBM Decode')
|
||||
tlm_rgbd = bpy.data.node_groups.get('RGBD Decode')
|
||||
tlm_logluv = bpy.data.node_groups.get('LogLuv Decode')
|
||||
|
||||
if tlm_rgbm == None:
|
||||
load_library('RGBM Decode')
|
||||
|
||||
if tlm_rgbd == None:
|
||||
load_library('RGBD Decode')
|
||||
|
||||
if tlm_logluv == None:
|
||||
load_library('LogLuv Decode')
|
||||
|
||||
if(scene.TLM_EngineProperties.tlm_exposure_multiplier > 0):
|
||||
tlm_exposure = bpy.data.node_groups.get("Exposure")
|
||||
|
||||
if tlm_exposure == None:
|
||||
load_library("Exposure")
|
||||
|
||||
#Apply materials
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
print(obj.name)
|
||||
for slot in obj.material_slots:
|
||||
|
||||
mat = slot.material
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
print(slot.material)
|
||||
|
||||
if not mat.TLM_ignore:
|
||||
if not hidden:
|
||||
|
||||
for slot in obj.material_slots:
|
||||
mat = slot.material
|
||||
node_tree = mat.node_tree
|
||||
nodes = mat.node_tree.nodes
|
||||
|
||||
foundBakedNode = False
|
||||
scene = bpy.context.scene
|
||||
|
||||
dirpath = os.path.join(os.path.dirname(bpy.data.filepath), scene.TLM_EngineProperties.tlm_lightmap_savedir)
|
||||
|
||||
#Find nodes
|
||||
for node in nodes:
|
||||
if node.name == "Baked Image":
|
||||
lightmapNode = node
|
||||
lightmapNode.location = -1200, 300
|
||||
lightmapNode.name = "TLM_Lightmap"
|
||||
foundBakedNode = True
|
||||
|
||||
img_name = obj.name + '_baked'
|
||||
|
||||
if not foundBakedNode:
|
||||
lightmapNode = node_tree.nodes.new(type="ShaderNodeTexImage")
|
||||
lightmapNode.location = -1200, 300
|
||||
lightmapNode.name = "TLM_Lightmap"
|
||||
lightmapNode.interpolation = bpy.context.scene.TLM_SceneProperties.tlm_texture_interpolation
|
||||
lightmapNode.extension = bpy.context.scene.TLM_SceneProperties.tlm_texture_extrapolation
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
print("Finding node source for material: " + mat.name + " @ " + obj.name)
|
||||
|
||||
if (obj.TLM_ObjectProperties.tlm_mesh_lightmap_unwrap_mode == "AtlasGroupA" and obj.TLM_ObjectProperties.tlm_atlas_pointer != ""):
|
||||
lightmapNode.image = bpy.data.images[obj.TLM_ObjectProperties.tlm_atlas_pointer + "_baked"]
|
||||
else:
|
||||
lightmapNode.image = bpy.data.images[img_name]
|
||||
extension = ".hdr"
|
||||
|
||||
#Find output node
|
||||
outputNode = nodes[0]
|
||||
if(outputNode.type != "OUTPUT_MATERIAL"):
|
||||
for node in node_tree.nodes:
|
||||
if node.type == "OUTPUT_MATERIAL":
|
||||
outputNode = node
|
||||
break
|
||||
postfix = "_baked"
|
||||
|
||||
#Find mainnode
|
||||
mainNode = outputNode.inputs[0].links[0].from_node
|
||||
if scene.TLM_SceneProperties.tlm_denoise_use:
|
||||
postfix = "_denoised"
|
||||
if scene.TLM_SceneProperties.tlm_filtering_use:
|
||||
postfix = "_filtered"
|
||||
|
||||
#Add all nodes first
|
||||
#Add lightmap multipliction texture
|
||||
mixNode = node_tree.nodes.new(type="ShaderNodeMixRGB")
|
||||
mixNode.name = "Lightmap_Multiplication"
|
||||
mixNode.location = -800, 300
|
||||
if scene.TLM_EngineProperties.tlm_lighting_mode == "indirect" or scene.TLM_EngineProperties.tlm_lighting_mode == "indirectAO":
|
||||
mixNode.blend_type = 'ADD'
|
||||
else:
|
||||
mixNode.blend_type = 'MULTIPLY'
|
||||
|
||||
if scene.TLM_EngineProperties.tlm_lighting_mode == "complete":
|
||||
mixNode.inputs[0].default_value = 0.0
|
||||
else:
|
||||
mixNode.inputs[0].default_value = 1.0
|
||||
if node.image:
|
||||
node.image.source = "FILE"
|
||||
|
||||
UVLightmap = node_tree.nodes.new(type="ShaderNodeUVMap")
|
||||
if obj.TLM_ObjectProperties.tlm_mesh_lightmap_unwrap_mode == "AtlasGroupA":
|
||||
print("Atlas object image")
|
||||
image_name = obj.TLM_ObjectProperties.tlm_atlas_pointer + postfix + extension #TODO FIX EXTENSION
|
||||
elif obj.TLM_ObjectProperties.tlm_postpack_object:
|
||||
print("Atlas object image (postpack)")
|
||||
image_name = obj.TLM_ObjectProperties.tlm_postatlas_pointer + postfix + extension #TODO FIX EXTENSION
|
||||
else:
|
||||
print("Baked object image")
|
||||
image_name = obj.name + postfix + extension #TODO FIX EXTENSION
|
||||
|
||||
node.image.filepath_raw = os.path.join(dirpath, image_name)
|
||||
|
||||
if not obj.TLM_ObjectProperties.tlm_use_default_channel:
|
||||
uv_channel = obj.TLM_ObjectProperties.tlm_uv_channel
|
||||
else:
|
||||
uv_channel = "UVMap_Lightmap"
|
||||
|
||||
UVLightmap.uv_map = uv_channel
|
||||
|
||||
UVLightmap.name = "Lightmap_UV"
|
||||
UVLightmap.location = -1500, 300
|
||||
|
||||
if(scene.TLM_SceneProperties.tlm_decoder_setup):
|
||||
if scene.TLM_SceneProperties.tlm_encoding_device == "CPU":
|
||||
if scene.TLM_SceneProperties.tlm_encoding_mode_a == 'RGBM':
|
||||
DecodeNode = node_tree.nodes.new(type="ShaderNodeGroup")
|
||||
DecodeNode.node_tree = bpy.data.node_groups["RGBM Decode"]
|
||||
DecodeNode.location = -400, 300
|
||||
DecodeNode.name = "Lightmap_RGBM_Decode"
|
||||
decoding = True
|
||||
if scene.TLM_SceneProperties.tlm_encoding_mode_b == "RGBD":
|
||||
DecodeNode = node_tree.nodes.new(type="ShaderNodeGroup")
|
||||
DecodeNode.node_tree = bpy.data.node_groups["RGBD Decode"]
|
||||
DecodeNode.location = -400, 300
|
||||
DecodeNode.name = "Lightmap_RGBD_Decode"
|
||||
decoding = True
|
||||
else:
|
||||
if scene.TLM_SceneProperties.tlm_encoding_mode_b == 'RGBM':
|
||||
DecodeNode = node_tree.nodes.new(type="ShaderNodeGroup")
|
||||
DecodeNode.node_tree = bpy.data.node_groups["RGBM Decode"]
|
||||
DecodeNode.location = -400, 300
|
||||
DecodeNode.name = "Lightmap_RGBM_Decode"
|
||||
decoding = True
|
||||
if scene.TLM_SceneProperties.tlm_encoding_mode_b == "RGBD":
|
||||
DecodeNode = node_tree.nodes.new(type="ShaderNodeGroup")
|
||||
DecodeNode.node_tree = bpy.data.node_groups["RGBD Decode"]
|
||||
DecodeNode.location = -400, 300
|
||||
DecodeNode.name = "Lightmap_RGBD_Decode"
|
||||
decoding = True
|
||||
if scene.TLM_SceneProperties.tlm_encoding_mode_b == "LogLuv":
|
||||
DecodeNode = node_tree.nodes.new(type="ShaderNodeGroup")
|
||||
DecodeNode.node_tree = bpy.data.node_groups["LogLuv Decode"]
|
||||
DecodeNode.location = -400, 300
|
||||
DecodeNode.name = "Lightmap_LogLuv_Decode"
|
||||
decoding = True
|
||||
|
||||
if(scene.TLM_EngineProperties.tlm_exposure_multiplier > 0):
|
||||
ExposureNode = node_tree.nodes.new(type="ShaderNodeGroup")
|
||||
ExposureNode.node_tree = bpy.data.node_groups["Exposure"]
|
||||
ExposureNode.inputs[1].default_value = scene.TLM_EngineProperties.tlm_exposure_multiplier
|
||||
ExposureNode.location = -500, 300
|
||||
ExposureNode.name = "Lightmap_Exposure"
|
||||
|
||||
#Add Basecolor node
|
||||
if len(mainNode.inputs[0].links) == 0:
|
||||
baseColorValue = mainNode.inputs[0].default_value
|
||||
baseColorNode = node_tree.nodes.new(type="ShaderNodeRGB")
|
||||
baseColorNode.outputs[0].default_value = baseColorValue
|
||||
baseColorNode.location = ((mainNode.location[0] - 1100, mainNode.location[1] - 300))
|
||||
baseColorNode.name = "Lightmap_BasecolorNode_A"
|
||||
else:
|
||||
baseColorNode = mainNode.inputs[0].links[0].from_node
|
||||
baseColorNode.name = "LM_P"
|
||||
|
||||
#Linking
|
||||
|
||||
if decoding and scene.TLM_SceneProperties.tlm_encoding_use:
|
||||
|
||||
if(scene.TLM_EngineProperties.tlm_exposure_multiplier > 0):
|
||||
|
||||
mat.node_tree.links.new(lightmapNode.outputs[0], DecodeNode.inputs[0]) #Connect lightmap node to mixnode
|
||||
mat.node_tree.links.new(lightmapNode.outputs[1], DecodeNode.inputs[1]) #Connect lightmap node to mixnode
|
||||
|
||||
mat.node_tree.links.new(DecodeNode.outputs[0], mixNode.inputs[1]) #Connect lightmap node to mixnode
|
||||
mat.node_tree.links.new(ExposureNode.outputs[0], mixNode.inputs[1]) #Connect lightmap node to mixnode
|
||||
|
||||
else:
|
||||
mat.node_tree.links.new(lightmapNode.outputs[0], DecodeNode.inputs[0]) #Connect lightmap node to mixnode
|
||||
mat.node_tree.links.new(lightmapNode.outputs[1], DecodeNode.inputs[1]) #Connect lightmap node to mixnode
|
||||
|
||||
mat.node_tree.links.new(DecodeNode.outputs[0], mixNode.inputs[1]) #Connect lightmap node to mixnode
|
||||
|
||||
mat.node_tree.links.new(baseColorNode.outputs[0], mixNode.inputs[2]) #Connect basecolor to pbr node
|
||||
mat.node_tree.links.new(mixNode.outputs[0], mainNode.inputs[0]) #Connect mixnode to pbr node
|
||||
mat.node_tree.links.new(UVLightmap.outputs[0], lightmapNode.inputs[0]) #Connect uvnode to lightmapnode
|
||||
|
||||
else:
|
||||
|
||||
if(scene.TLM_EngineProperties.tlm_exposure_multiplier > 0):
|
||||
mat.node_tree.links.new(lightmapNode.outputs[0], ExposureNode.inputs[0]) #Connect lightmap node to mixnode
|
||||
mat.node_tree.links.new(ExposureNode.outputs[0], mixNode.inputs[1]) #Connect lightmap node to mixnode
|
||||
else:
|
||||
mat.node_tree.links.new(lightmapNode.outputs[0], mixNode.inputs[1]) #Connect lightmap node to mixnode
|
||||
mat.node_tree.links.new(baseColorNode.outputs[0], mixNode.inputs[2]) #Connect basecolor to pbr node
|
||||
mat.node_tree.links.new(mixNode.outputs[0], mainNode.inputs[0]) #Connect mixnode to pbr node
|
||||
mat.node_tree.links.new(UVLightmap.outputs[0], lightmapNode.inputs[0]) #Connect uvnode to lightmapnode
|
||||
|
||||
#If skip metallic
|
||||
if scene.TLM_SceneProperties.tlm_metallic_clamp == "skip":
|
||||
if mainNode.inputs[4].default_value > 0.1: #DELIMITER
|
||||
moutput = mainNode.inputs[0].links[0].from_node
|
||||
mat.node_tree.links.remove(moutput.outputs[0].links[0])
|
||||
|
||||
def exchangeLightmapsToPostfix(ext_postfix, new_postfix, formatHDR=".hdr"):
|
||||
def apply_materials(load_atlas=0):
|
||||
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
print(ext_postfix, new_postfix, formatHDR)
|
||||
print("Applying materials")
|
||||
if load_atlas:
|
||||
print("- In load Atlas mode")
|
||||
|
||||
for obj in bpy.context.scene.objects:
|
||||
if obj.type == 'MESH' and obj.name in bpy.context.view_layer.objects:
|
||||
if obj.TLM_ObjectProperties.tlm_mesh_lightmap_use:
|
||||
for slot in obj.material_slots:
|
||||
mat = slot.material
|
||||
node_tree = mat.node_tree
|
||||
nodes = mat.node_tree.nodes
|
||||
|
||||
for node in nodes:
|
||||
if node.name == "Baked Image" or node.name == "TLM_Lightmap":
|
||||
img_name = node.image.filepath_raw
|
||||
cutLen = len(ext_postfix + formatHDR)
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
print("Len:" + str(len(ext_postfix + formatHDR)) + "|" + ext_postfix + ".." + formatHDR)
|
||||
hidden = False
|
||||
|
||||
#Simple way to sort out objects with multiple materials
|
||||
if formatHDR == ".hdr" or formatHDR == ".exr":
|
||||
if not node.image.filepath_raw.endswith(new_postfix + formatHDR):
|
||||
node.image.filepath_raw = img_name[:-cutLen] + new_postfix + formatHDR
|
||||
if obj.hide_get():
|
||||
hidden = True
|
||||
if obj.hide_viewport:
|
||||
hidden = True
|
||||
if obj.hide_render:
|
||||
hidden = True
|
||||
|
||||
if not hidden:
|
||||
|
||||
uv_layers = obj.data.uv_layers
|
||||
uv_layers.active_index = 0
|
||||
scene = bpy.context.scene
|
||||
|
||||
decoding = False
|
||||
|
||||
#Sort name
|
||||
for slot in obj.material_slots:
|
||||
mat = slot.material
|
||||
if mat.name.endswith('_temp'):
|
||||
old = slot.material
|
||||
slot.material = bpy.data.materials[old.name.split('_' + obj.name)[0]]
|
||||
|
||||
if(scene.TLM_SceneProperties.tlm_decoder_setup):
|
||||
|
||||
tlm_rgbm = bpy.data.node_groups.get('RGBM Decode')
|
||||
tlm_rgbd = bpy.data.node_groups.get('RGBD Decode')
|
||||
tlm_logluv = bpy.data.node_groups.get('LogLuv Decode')
|
||||
|
||||
if tlm_rgbm == None:
|
||||
load_library('RGBM Decode')
|
||||
|
||||
if tlm_rgbd == None:
|
||||
load_library('RGBD Decode')
|
||||
|
||||
if tlm_logluv == None:
|
||||
load_library('LogLuv Decode')
|
||||
|
||||
if(scene.TLM_EngineProperties.tlm_exposure_multiplier > 0):
|
||||
tlm_exposure = bpy.data.node_groups.get("Exposure")
|
||||
|
||||
if tlm_exposure == None:
|
||||
load_library("Exposure")
|
||||
|
||||
#Apply materials
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
print(obj.name)
|
||||
for slot in obj.material_slots:
|
||||
|
||||
mat = slot.material
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
print(slot.material)
|
||||
|
||||
|
||||
if not mat.TLM_ignore:
|
||||
|
||||
node_tree = mat.node_tree
|
||||
nodes = mat.node_tree.nodes
|
||||
|
||||
foundBakedNode = False
|
||||
|
||||
#Find nodes
|
||||
for node in nodes:
|
||||
if node.name == "Baked Image":
|
||||
lightmapNode = node
|
||||
lightmapNode.location = -1200, 300
|
||||
lightmapNode.name = "TLM_Lightmap"
|
||||
foundBakedNode = True
|
||||
|
||||
# if load_atlas:
|
||||
# print("Load Atlas for: " + obj.name)
|
||||
# img_name = obj.TLM_ObjectProperties.tlm_atlas_pointer + '_baked'
|
||||
# print("Src: " + img_name)
|
||||
# else:
|
||||
# img_name = obj.name + '_baked'
|
||||
|
||||
img_name = obj.name + '_baked'
|
||||
|
||||
if not foundBakedNode:
|
||||
|
||||
if scene.TLM_EngineProperties.tlm_target == "vertex":
|
||||
|
||||
lightmapNode = node_tree.nodes.new(type="ShaderNodeVertexColor")
|
||||
lightmapNode.location = -1200, 300
|
||||
lightmapNode.name = "TLM_Lightmap"
|
||||
|
||||
else:
|
||||
|
||||
lightmapNode = node_tree.nodes.new(type="ShaderNodeTexImage")
|
||||
lightmapNode.location = -1200, 300
|
||||
lightmapNode.name = "TLM_Lightmap"
|
||||
lightmapNode.interpolation = bpy.context.scene.TLM_SceneProperties.tlm_texture_interpolation
|
||||
lightmapNode.extension = bpy.context.scene.TLM_SceneProperties.tlm_texture_extrapolation
|
||||
|
||||
if (obj.TLM_ObjectProperties.tlm_mesh_lightmap_unwrap_mode == "AtlasGroupA" and obj.TLM_ObjectProperties.tlm_atlas_pointer != ""):
|
||||
lightmapNode.image = bpy.data.images[obj.TLM_ObjectProperties.tlm_atlas_pointer + "_baked"]
|
||||
else:
|
||||
lightmapNode.image = bpy.data.images[img_name]
|
||||
|
||||
#Find output node
|
||||
outputNode = nodes[0]
|
||||
if(outputNode.type != "OUTPUT_MATERIAL"):
|
||||
for node in node_tree.nodes:
|
||||
if node.type == "OUTPUT_MATERIAL":
|
||||
outputNode = node
|
||||
break
|
||||
|
||||
#Find mainnode
|
||||
mainNode = outputNode.inputs[0].links[0].from_node
|
||||
|
||||
if (mainNode.type == "MIX_SHADER"):
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
print("Mix shader found")
|
||||
|
||||
#TODO SHIFT BETWEEN from node input 1 or 2 based on which type
|
||||
mainNode = outputNode.inputs[0].links[0].from_node.inputs[1].links[0].from_node
|
||||
|
||||
if (mainNode.type == "ADD_SHADER"):
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
print("Mix shader found")
|
||||
|
||||
mainNode = outputNode.inputs[0].links[0].from_node.inputs[0].links[0].from_node
|
||||
|
||||
if (mainNode.type == "ShaderNodeMixRGB"):
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
print("Mix RGB shader found")
|
||||
|
||||
mainNode = outputNode.inputs[0].links[0].from_node.inputs[0].links[0].from_node
|
||||
|
||||
#Add all nodes first
|
||||
#Add lightmap multipliction texture
|
||||
mixNode = node_tree.nodes.new(type="ShaderNodeMixRGB")
|
||||
mixNode.name = "Lightmap_Multiplication"
|
||||
mixNode.location = -800, 300
|
||||
if scene.TLM_EngineProperties.tlm_lighting_mode == "indirect" or scene.TLM_EngineProperties.tlm_lighting_mode == "indirectAO":
|
||||
mixNode.blend_type = 'MULTIPLY'
|
||||
else:
|
||||
cutLen = len(ext_postfix + ".hdr")
|
||||
if not node.image.filepath_raw.endswith(new_postfix + formatHDR):
|
||||
node.image.filepath_raw = img_name[:-cutLen] + new_postfix + formatHDR
|
||||
mixNode.blend_type = 'MULTIPLY'
|
||||
|
||||
if scene.TLM_EngineProperties.tlm_lighting_mode == "complete":
|
||||
mixNode.inputs[0].default_value = 0.0
|
||||
else:
|
||||
mixNode.inputs[0].default_value = 1.0
|
||||
|
||||
UVLightmap = node_tree.nodes.new(type="ShaderNodeUVMap")
|
||||
|
||||
if not obj.TLM_ObjectProperties.tlm_use_default_channel:
|
||||
uv_channel = obj.TLM_ObjectProperties.tlm_uv_channel
|
||||
else:
|
||||
uv_channel = "UVMap_Lightmap"
|
||||
|
||||
UVLightmap.uv_map = uv_channel
|
||||
|
||||
UVLightmap.name = "Lightmap_UV"
|
||||
UVLightmap.location = -1500, 300
|
||||
|
||||
if(scene.TLM_SceneProperties.tlm_decoder_setup):
|
||||
if scene.TLM_SceneProperties.tlm_encoding_device == "CPU":
|
||||
if scene.TLM_SceneProperties.tlm_encoding_mode_a == 'RGBM':
|
||||
DecodeNode = node_tree.nodes.new(type="ShaderNodeGroup")
|
||||
DecodeNode.node_tree = bpy.data.node_groups["RGBM Decode"]
|
||||
DecodeNode.location = -400, 300
|
||||
DecodeNode.name = "Lightmap_RGBM_Decode"
|
||||
decoding = True
|
||||
if scene.TLM_SceneProperties.tlm_encoding_mode_b == "RGBD":
|
||||
DecodeNode = node_tree.nodes.new(type="ShaderNodeGroup")
|
||||
DecodeNode.node_tree = bpy.data.node_groups["RGBD Decode"]
|
||||
DecodeNode.location = -400, 300
|
||||
DecodeNode.name = "Lightmap_RGBD_Decode"
|
||||
decoding = True
|
||||
else:
|
||||
if scene.TLM_SceneProperties.tlm_encoding_mode_b == 'RGBM':
|
||||
DecodeNode = node_tree.nodes.new(type="ShaderNodeGroup")
|
||||
DecodeNode.node_tree = bpy.data.node_groups["RGBM Decode"]
|
||||
DecodeNode.location = -400, 300
|
||||
DecodeNode.name = "Lightmap_RGBM_Decode"
|
||||
decoding = True
|
||||
if scene.TLM_SceneProperties.tlm_encoding_mode_b == "RGBD":
|
||||
DecodeNode = node_tree.nodes.new(type="ShaderNodeGroup")
|
||||
DecodeNode.node_tree = bpy.data.node_groups["RGBD Decode"]
|
||||
DecodeNode.location = -400, 300
|
||||
DecodeNode.name = "Lightmap_RGBD_Decode"
|
||||
decoding = True
|
||||
if scene.TLM_SceneProperties.tlm_encoding_mode_b == "LogLuv":
|
||||
DecodeNode = node_tree.nodes.new(type="ShaderNodeGroup")
|
||||
DecodeNode.node_tree = bpy.data.node_groups["LogLuv Decode"]
|
||||
DecodeNode.location = -400, 300
|
||||
DecodeNode.name = "Lightmap_LogLuv_Decode"
|
||||
decoding = True
|
||||
|
||||
if scene.TLM_SceneProperties.tlm_split_premultiplied:
|
||||
|
||||
lightmapNodeExtra = node_tree.nodes.new(type="ShaderNodeTexImage")
|
||||
lightmapNodeExtra.location = -1200, 800
|
||||
lightmapNodeExtra.name = "TLM_Lightmap_Extra"
|
||||
lightmapNodeExtra.interpolation = bpy.context.scene.TLM_SceneProperties.tlm_texture_interpolation
|
||||
lightmapNodeExtra.extension = bpy.context.scene.TLM_SceneProperties.tlm_texture_extrapolation
|
||||
lightmapNodeExtra.image = lightmapNode.image
|
||||
|
||||
# #IF OBJ IS USING ATLAS?
|
||||
# if (obj.TLM_ObjectProperties.tlm_mesh_lightmap_unwrap_mode == "AtlasGroupA" and obj.TLM_ObjectProperties.tlm_atlas_pointer != ""):
|
||||
# #lightmapNode.image = bpy.data.images[obj.TLM_ObjectProperties.tlm_atlas_pointer + "_baked"]
|
||||
# #print("OBS! OBJ IS USING ATLAS, RESULT WILL BE WRONG!")
|
||||
# #bpy.app.driver_namespace["logman"].append("OBS! OBJ IS USING ATLAS, RESULT WILL BE WRONG!")
|
||||
# pass
|
||||
# if (obj.TLM_ObjectProperties.tlm_postpack_object and obj.TLM_ObjectProperties.tlm_postatlas_pointer != ""):
|
||||
# #print("OBS! OBJ IS USING ATLAS, RESULT WILL BE WRONG!")
|
||||
# #bpy.app.driver_namespace["logman"].append("OBS! OBJ IS USING ATLAS, RESULT WILL BE WRONG!")
|
||||
# print()
|
||||
# lightmapNodeExtra.image = lightmapNode.image
|
||||
|
||||
#lightmapPath = lightmapNode.image.filepath_raw
|
||||
#print("PREM: " + lightmapPath)
|
||||
|
||||
if(scene.TLM_EngineProperties.tlm_exposure_multiplier > 0):
|
||||
ExposureNode = node_tree.nodes.new(type="ShaderNodeGroup")
|
||||
ExposureNode.node_tree = bpy.data.node_groups["Exposure"]
|
||||
ExposureNode.inputs[1].default_value = scene.TLM_EngineProperties.tlm_exposure_multiplier
|
||||
ExposureNode.location = -500, 300
|
||||
ExposureNode.name = "Lightmap_Exposure"
|
||||
|
||||
#Add Basecolor node
|
||||
if len(mainNode.inputs[0].links) == 0:
|
||||
baseColorValue = mainNode.inputs[0].default_value
|
||||
baseColorNode = node_tree.nodes.new(type="ShaderNodeRGB")
|
||||
baseColorNode.outputs[0].default_value = baseColorValue
|
||||
baseColorNode.location = ((mainNode.location[0] - 1100, mainNode.location[1] - 300))
|
||||
baseColorNode.name = "Lightmap_BasecolorNode_A"
|
||||
else:
|
||||
baseColorNode = mainNode.inputs[0].links[0].from_node
|
||||
baseColorNode.name = "LM_P"
|
||||
|
||||
#Linking
|
||||
if decoding and scene.TLM_SceneProperties.tlm_encoding_use:
|
||||
|
||||
if(scene.TLM_EngineProperties.tlm_exposure_multiplier > 0):
|
||||
|
||||
mat.node_tree.links.new(lightmapNode.outputs[0], DecodeNode.inputs[0]) #Connect lightmap node to decodenode
|
||||
|
||||
if scene.TLM_SceneProperties.tlm_split_premultiplied:
|
||||
mat.node_tree.links.new(lightmapNodeExtra.outputs[0], DecodeNode.inputs[1]) #Connect lightmap node to decodenode
|
||||
else:
|
||||
mat.node_tree.links.new(lightmapNode.outputs[1], DecodeNode.inputs[1]) #Connect lightmap node to decodenode
|
||||
|
||||
mat.node_tree.links.new(DecodeNode.outputs[0], mixNode.inputs[1]) #Connect decode node to mixnode
|
||||
mat.node_tree.links.new(ExposureNode.outputs[0], mixNode.inputs[1]) #Connect exposure node to mixnode
|
||||
|
||||
else:
|
||||
|
||||
mat.node_tree.links.new(lightmapNode.outputs[0], DecodeNode.inputs[0]) #Connect lightmap node to decodenode
|
||||
if scene.TLM_SceneProperties.tlm_split_premultiplied:
|
||||
mat.node_tree.links.new(lightmapNodeExtra.outputs[0], DecodeNode.inputs[1]) #Connect lightmap node to decodenode
|
||||
else:
|
||||
mat.node_tree.links.new(lightmapNode.outputs[1], DecodeNode.inputs[1]) #Connect lightmap node to decodenode
|
||||
|
||||
mat.node_tree.links.new(DecodeNode.outputs[0], mixNode.inputs[1]) #Connect lightmap node to mixnode
|
||||
|
||||
mat.node_tree.links.new(baseColorNode.outputs[0], mixNode.inputs[2]) #Connect basecolor to pbr node
|
||||
mat.node_tree.links.new(mixNode.outputs[0], mainNode.inputs[0]) #Connect mixnode to pbr node
|
||||
|
||||
if not scene.TLM_EngineProperties.tlm_target == "vertex":
|
||||
mat.node_tree.links.new(UVLightmap.outputs[0], lightmapNode.inputs[0]) #Connect uvnode to lightmapnode
|
||||
|
||||
if scene.TLM_SceneProperties.tlm_split_premultiplied:
|
||||
mat.node_tree.links.new(UVLightmap.outputs[0], lightmapNodeExtra.inputs[0]) #Connect uvnode to lightmapnode
|
||||
|
||||
else:
|
||||
|
||||
if(scene.TLM_EngineProperties.tlm_exposure_multiplier > 0):
|
||||
mat.node_tree.links.new(lightmapNode.outputs[0], ExposureNode.inputs[0]) #Connect lightmap node to mixnode
|
||||
mat.node_tree.links.new(ExposureNode.outputs[0], mixNode.inputs[1]) #Connect lightmap node to mixnode
|
||||
else:
|
||||
mat.node_tree.links.new(lightmapNode.outputs[0], mixNode.inputs[1]) #Connect lightmap node to mixnode
|
||||
mat.node_tree.links.new(baseColorNode.outputs[0], mixNode.inputs[2]) #Connect basecolor to pbr node
|
||||
mat.node_tree.links.new(mixNode.outputs[0], mainNode.inputs[0]) #Connect mixnode to pbr node
|
||||
if not scene.TLM_EngineProperties.tlm_target == "vertex":
|
||||
mat.node_tree.links.new(UVLightmap.outputs[0], lightmapNode.inputs[0]) #Connect uvnode to lightmapnode
|
||||
|
||||
#If skip metallic
|
||||
if scene.TLM_SceneProperties.tlm_metallic_clamp == "skip":
|
||||
if mainNode.inputs[4].default_value > 0.1: #DELIMITER
|
||||
moutput = mainNode.inputs[0].links[0].from_node
|
||||
mat.node_tree.links.remove(moutput.outputs[0].links[0])
|
||||
|
||||
def exchangeLightmapsToPostfix(ext_postfix, new_postfix, formatHDR=".hdr"):
|
||||
|
||||
if not bpy.context.scene.TLM_EngineProperties.tlm_target == "vertex":
|
||||
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
print(ext_postfix, new_postfix, formatHDR)
|
||||
|
||||
for obj in bpy.context.scene.objects:
|
||||
if obj.type == 'MESH' and obj.name in bpy.context.view_layer.objects:
|
||||
if obj.TLM_ObjectProperties.tlm_mesh_lightmap_use:
|
||||
|
||||
#Here
|
||||
#If the object is part of atlas
|
||||
print("CHECKING FOR REPART")
|
||||
if obj.TLM_ObjectProperties.tlm_mesh_lightmap_unwrap_mode == "AtlasGroupA": #TODO, ALSO CONFIGURE FOR POSTATLAS
|
||||
|
||||
if bpy.context.scene.TLM_AtlasList[obj.TLM_ObjectProperties.tlm_atlas_pointer].tlm_atlas_merge_samemat:
|
||||
|
||||
#For each material we check if it ends with a number
|
||||
for slot in obj.material_slots:
|
||||
|
||||
part = slot.name.rpartition('.')
|
||||
if part[2].isnumeric() and part[0] in bpy.data.materials:
|
||||
|
||||
print("Material for obj: " + obj.name + " was numeric, and the material: " + part[0] + " was found.")
|
||||
slot.material = bpy.data.materials.get(part[0])
|
||||
|
||||
|
||||
|
||||
# for slot in obj.material_slots:
|
||||
# mat = slot.material
|
||||
# node_tree = mat.node_tree
|
||||
# nodes = mat.node_tree.nodes
|
||||
|
||||
try:
|
||||
|
||||
hidden = False
|
||||
|
||||
if obj.hide_get():
|
||||
hidden = True
|
||||
if obj.hide_viewport:
|
||||
hidden = True
|
||||
if obj.hide_render:
|
||||
hidden = True
|
||||
|
||||
if not hidden:
|
||||
|
||||
for slot in obj.material_slots:
|
||||
mat = slot.material
|
||||
node_tree = mat.node_tree
|
||||
nodes = mat.node_tree.nodes
|
||||
|
||||
for node in nodes:
|
||||
if node.name == "Baked Image" or node.name == "TLM_Lightmap":
|
||||
img_name = node.image.filepath_raw
|
||||
cutLen = len(ext_postfix + formatHDR)
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
print("Len:" + str(len(ext_postfix + formatHDR)) + "|" + ext_postfix + ".." + formatHDR)
|
||||
|
||||
#Simple way to sort out objects with multiple materials
|
||||
if formatHDR == ".hdr" or formatHDR == ".exr":
|
||||
if not node.image.filepath_raw.endswith(new_postfix + formatHDR):
|
||||
print("Node1: " + node.image.filepath_raw + " => " + img_name[:-cutLen] + new_postfix + formatHDR)
|
||||
node.image.filepath_raw = img_name[:-cutLen] + new_postfix + formatHDR
|
||||
else:
|
||||
cutLen = len(ext_postfix + ".hdr")
|
||||
if not node.image.filepath_raw.endswith(new_postfix + formatHDR):
|
||||
if not node.image.filepath_raw.endswith("_XYZ.png"):
|
||||
print("Node2: " + node.image.filepath_raw + " => " + img_name[:-cutLen] + new_postfix + formatHDR)
|
||||
node.image.filepath_raw = img_name[:-cutLen] + new_postfix + formatHDR
|
||||
|
||||
for node in nodes:
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_encoding_use and bpy.context.scene.TLM_SceneProperties.tlm_encoding_mode_b == "LogLuv":
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_split_premultiplied:
|
||||
if node.name == "TLM_Lightmap":
|
||||
img_name = node.image.filepath_raw
|
||||
print("PREM Main: " + img_name)
|
||||
if node.image.filepath_raw.endswith("_encoded.png"):
|
||||
print(node.image.filepath_raw + " => " + node.image.filepath_raw[:-4] + "_XYZ.png")
|
||||
if not node.image.filepath_raw.endswith("_XYZ.png"):
|
||||
node.image.filepath_raw = node.image.filepath_raw[:-4] + "_XYZ.png"
|
||||
if node.name == "TLM_Lightmap_Extra":
|
||||
img_path = node.image.filepath_raw[:-8] + "_W.png"
|
||||
img = bpy.data.images.load(img_path)
|
||||
node.image = img
|
||||
bpy.data.images.load(img_path)
|
||||
print("PREM Extra: " + img_path)
|
||||
node.image.filepath_raw = img_path
|
||||
node.image.colorspace_settings.name = "Linear"
|
||||
|
||||
except:
|
||||
|
||||
print("Error occured with postfix change for obj: " + obj.name)
|
||||
|
||||
for image in bpy.data.images:
|
||||
image.reload()
|
||||
|
@ -278,47 +454,59 @@ def applyAOPass():
|
|||
for obj in bpy.context.scene.objects:
|
||||
if obj.type == 'MESH' and obj.name in bpy.context.view_layer.objects:
|
||||
if obj.TLM_ObjectProperties.tlm_mesh_lightmap_use:
|
||||
for slot in obj.material_slots:
|
||||
mat = slot.material
|
||||
node_tree = mat.node_tree
|
||||
nodes = mat.node_tree.nodes
|
||||
|
||||
for node in nodes:
|
||||
if node.name == "Baked Image" or node.name == "TLM_Lightmap":
|
||||
hidden = False
|
||||
|
||||
filepath = bpy.data.filepath
|
||||
dirpath = os.path.join(os.path.dirname(bpy.data.filepath), bpy.context.scene.TLM_EngineProperties.tlm_lightmap_savedir)
|
||||
if obj.hide_get():
|
||||
hidden = True
|
||||
if obj.hide_viewport:
|
||||
hidden = True
|
||||
if obj.hide_render:
|
||||
hidden = True
|
||||
|
||||
LightmapPath = node.image.filepath_raw
|
||||
if not hidden:
|
||||
|
||||
filebase = os.path.basename(LightmapPath)
|
||||
filename = os.path.splitext(filebase)[0]
|
||||
extension = os.path.splitext(filebase)[1]
|
||||
AOImagefile = filename[:-4] + "_ao"
|
||||
AOImagePath = os.path.join(dirpath, AOImagefile + extension)
|
||||
for slot in obj.material_slots:
|
||||
mat = slot.material
|
||||
node_tree = mat.node_tree
|
||||
nodes = mat.node_tree.nodes
|
||||
|
||||
AOMap = nodes.new('ShaderNodeTexImage')
|
||||
AOMap.name = "TLM_AOMap"
|
||||
AOImage = bpy.data.images.load(AOImagePath)
|
||||
AOMap.image = AOImage
|
||||
AOMap.location = -800, 0
|
||||
for node in nodes:
|
||||
if node.name == "Baked Image" or node.name == "TLM_Lightmap":
|
||||
|
||||
AOMult = nodes.new(type="ShaderNodeMixRGB")
|
||||
AOMult.name = "TLM_AOMult"
|
||||
AOMult.blend_type = 'MULTIPLY'
|
||||
AOMult.inputs[0].default_value = 1.0
|
||||
AOMult.location = -300, 300
|
||||
filepath = bpy.data.filepath
|
||||
dirpath = os.path.join(os.path.dirname(bpy.data.filepath), bpy.context.scene.TLM_EngineProperties.tlm_lightmap_savedir)
|
||||
|
||||
multyNode = nodes["Lightmap_Multiplication"]
|
||||
mainNode = nodes["Principled BSDF"]
|
||||
UVMapNode = nodes["Lightmap_UV"]
|
||||
LightmapPath = node.image.filepath_raw
|
||||
|
||||
node_tree.links.remove(multyNode.outputs[0].links[0])
|
||||
filebase = os.path.basename(LightmapPath)
|
||||
filename = os.path.splitext(filebase)[0]
|
||||
extension = os.path.splitext(filebase)[1]
|
||||
AOImagefile = filename[:-4] + "_ao"
|
||||
AOImagePath = os.path.join(dirpath, AOImagefile + extension)
|
||||
|
||||
node_tree.links.new(multyNode.outputs[0], AOMult.inputs[1])
|
||||
node_tree.links.new(AOMap.outputs[0], AOMult.inputs[2])
|
||||
node_tree.links.new(AOMult.outputs[0], mainNode.inputs[0])
|
||||
node_tree.links.new(UVMapNode.outputs[0], AOMap.inputs[0])
|
||||
AOMap = nodes.new('ShaderNodeTexImage')
|
||||
AOMap.name = "TLM_AOMap"
|
||||
AOImage = bpy.data.images.load(AOImagePath)
|
||||
AOMap.image = AOImage
|
||||
AOMap.location = -800, 0
|
||||
|
||||
AOMult = nodes.new(type="ShaderNodeMixRGB")
|
||||
AOMult.name = "TLM_AOMult"
|
||||
AOMult.blend_type = 'MULTIPLY'
|
||||
AOMult.inputs[0].default_value = 1.0
|
||||
AOMult.location = -300, 300
|
||||
|
||||
multyNode = nodes["Lightmap_Multiplication"]
|
||||
mainNode = nodes["Principled BSDF"]
|
||||
UVMapNode = nodes["Lightmap_UV"]
|
||||
|
||||
node_tree.links.remove(multyNode.outputs[0].links[0])
|
||||
|
||||
node_tree.links.new(multyNode.outputs[0], AOMult.inputs[1])
|
||||
node_tree.links.new(AOMap.outputs[0], AOMult.inputs[2])
|
||||
node_tree.links.new(AOMult.outputs[0], mainNode.inputs[0])
|
||||
node_tree.links.new(UVMapNode.outputs[0], AOMap.inputs[0])
|
||||
|
||||
def load_library(asset_name):
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import bpy, math
|
||||
import bpy, math, time
|
||||
|
||||
from . import cache
|
||||
from .. utility import *
|
||||
|
@ -23,6 +23,18 @@ def init(self, prev_container):
|
|||
|
||||
configure_meshes(self)
|
||||
|
||||
print("Config mesh catch omitted: REMEMBER TO SET IT BACK NAXELA")
|
||||
# try:
|
||||
# configure_meshes(self)
|
||||
# except Exception as e:
|
||||
|
||||
# print("An error occured during mesh configuration. See error below:")
|
||||
|
||||
# print(f"{type(e).__name__} at line {e.__traceback__.tb_lineno} of {__file__}: {e}")
|
||||
|
||||
# if not bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
# print("Turn on verbose mode to get more detail.")
|
||||
|
||||
def configure_world():
|
||||
pass
|
||||
|
||||
|
@ -32,13 +44,17 @@ def configure_lights():
|
|||
def configure_meshes(self):
|
||||
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
print("Configuring meshes")
|
||||
print("Configuring meshes: Start")
|
||||
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
print("Configuring meshes: Material restore")
|
||||
for obj in bpy.context.scene.objects:
|
||||
if obj.type == 'MESH' and obj.name in bpy.context.view_layer.objects:
|
||||
if obj.TLM_ObjectProperties.tlm_mesh_lightmap_use:
|
||||
cache.backup_material_restore(obj)
|
||||
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
print("Configuring meshes: Material rename check")
|
||||
for obj in bpy.context.scene.objects:
|
||||
if obj.type == 'MESH' and obj.name in bpy.context.view_layer.objects:
|
||||
if obj.TLM_ObjectProperties.tlm_mesh_lightmap_use:
|
||||
|
@ -62,9 +78,61 @@ def configure_meshes(self):
|
|||
|
||||
scene = bpy.context.scene
|
||||
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
print("Object: Setting UV, converting modifiers and prepare channels")
|
||||
|
||||
#OBJECT: Set UV, CONVERT AND PREPARE
|
||||
for obj in bpy.context.scene.objects:
|
||||
if obj.type == 'MESH' and obj.name in bpy.context.view_layer.objects:
|
||||
if obj.TLM_ObjectProperties.tlm_mesh_lightmap_use:
|
||||
|
||||
hidden = False
|
||||
|
||||
#We check if the object is hidden
|
||||
if obj.hide_get():
|
||||
hidden = True
|
||||
if obj.hide_viewport:
|
||||
hidden = True
|
||||
if obj.hide_render:
|
||||
hidden = True
|
||||
|
||||
#We check if the object's collection is hidden
|
||||
collections = obj.users_collection
|
||||
|
||||
for collection in collections:
|
||||
|
||||
if collection.hide_viewport:
|
||||
hidden = True
|
||||
if collection.hide_render:
|
||||
hidden = True
|
||||
|
||||
try:
|
||||
if collection.name in bpy.context.scene.view_layers[0].layer_collection.children:
|
||||
if bpy.context.scene.view_layers[0].layer_collection.children[collection.name].hide_viewport:
|
||||
hidden = True
|
||||
except:
|
||||
print("Error: Could not find collection: " + collection.name)
|
||||
|
||||
|
||||
#Additional check for zero poly meshes
|
||||
mesh = obj.data
|
||||
if (len(mesh.polygons)) < 1:
|
||||
print("Found an object with zero polygons. Skipping object: " + obj.name)
|
||||
obj.TLM_ObjectProperties.tlm_mesh_lightmap_use = False
|
||||
|
||||
if obj.TLM_ObjectProperties.tlm_mesh_lightmap_use and not hidden:
|
||||
|
||||
print("Preparing: UV initiation for object: " + obj.name)
|
||||
|
||||
if len(obj.data.vertex_colors) < 1:
|
||||
obj.data.vertex_colors.new(name="TLM")
|
||||
|
||||
if scene.TLM_SceneProperties.tlm_reset_uv:
|
||||
|
||||
uv_layers = obj.data.uv_layers
|
||||
uv_channel = "UVMap_Lightmap"
|
||||
for uvlayer in uv_layers:
|
||||
if uvlayer.name == uv_channel:
|
||||
uv_layers.remove(uvlayer)
|
||||
|
||||
if scene.TLM_SceneProperties.tlm_apply_on_unwrap:
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
|
@ -73,6 +141,17 @@ def configure_meshes(self):
|
|||
obj.select_set(True)
|
||||
bpy.ops.object.transform_apply(location=False, rotation=True, scale=True)
|
||||
|
||||
if scene.TLM_SceneProperties.tlm_apply_modifiers:
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
print("Applying modifiers to: " + obj.name)
|
||||
bpy.context.view_layer.objects.active = obj
|
||||
obj.select_set(True)
|
||||
bpy.ops.object.convert(target='MESH')
|
||||
|
||||
for slot in obj.material_slots:
|
||||
material = slot.material
|
||||
skipIncompatibleMaterials(material)
|
||||
|
||||
obj.hide_select = False #Remember to toggle this back
|
||||
for slot in obj.material_slots:
|
||||
if "." + slot.name + '_Original' in bpy.data.materials:
|
||||
|
@ -80,96 +159,204 @@ def configure_meshes(self):
|
|||
print("The material: " + slot.name + " shifted to " + "." + slot.name + '_Original')
|
||||
slot.material = bpy.data.materials["." + slot.name + '_Original']
|
||||
|
||||
|
||||
#ATLAS
|
||||
#ATLAS UV PROJECTING
|
||||
print("PREPARE: ATLAS")
|
||||
for atlasgroup in scene.TLM_AtlasList:
|
||||
|
||||
print("Adding UV Projection for Atlas group: " + atlasgroup.name)
|
||||
|
||||
atlas = atlasgroup.name
|
||||
atlas_items = []
|
||||
|
||||
bpy.ops.object.select_all(action='DESELECT')
|
||||
|
||||
|
||||
#Atlas: Set UV, CONVERT AND PREPARE
|
||||
for obj in bpy.context.scene.objects:
|
||||
|
||||
if obj.TLM_ObjectProperties.tlm_mesh_lightmap_unwrap_mode == "AtlasGroupA":
|
||||
if obj.TLM_ObjectProperties.tlm_atlas_pointer == atlasgroup.name:
|
||||
|
||||
uv_layers = obj.data.uv_layers
|
||||
hidden = False
|
||||
|
||||
if not obj.TLM_ObjectProperties.tlm_use_default_channel:
|
||||
uv_channel = obj.TLM_ObjectProperties.tlm_uv_channel
|
||||
else:
|
||||
uv_channel = "UVMap_Lightmap"
|
||||
#We check if the object is hidden
|
||||
if obj.hide_get():
|
||||
hidden = True
|
||||
if obj.hide_viewport:
|
||||
hidden = True
|
||||
if obj.hide_render:
|
||||
hidden = True
|
||||
|
||||
if not uv_channel in uv_layers:
|
||||
#We check if the object's collection is hidden
|
||||
collections = obj.users_collection
|
||||
|
||||
for collection in collections:
|
||||
|
||||
if collection.hide_viewport:
|
||||
hidden = True
|
||||
if collection.hide_render:
|
||||
hidden = True
|
||||
|
||||
try:
|
||||
if collection.name in bpy.context.scene.view_layers[0].layer_collection.children:
|
||||
if bpy.context.scene.view_layers[0].layer_collection.children[collection.name].hide_viewport:
|
||||
hidden = True
|
||||
except:
|
||||
print("Error: Could not find collection: " + collection.name)
|
||||
|
||||
if obj.TLM_ObjectProperties.tlm_mesh_lightmap_unwrap_mode == "AtlasGroupA" and not hidden:
|
||||
|
||||
uv_layers = obj.data.uv_layers
|
||||
|
||||
if not obj.TLM_ObjectProperties.tlm_use_default_channel:
|
||||
uv_channel = obj.TLM_ObjectProperties.tlm_uv_channel
|
||||
else:
|
||||
uv_channel = "UVMap_Lightmap"
|
||||
|
||||
if not uv_channel in uv_layers:
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
print("UV map created for object: " + obj.name)
|
||||
uvmap = uv_layers.new(name=uv_channel)
|
||||
uv_layers.active_index = len(uv_layers) - 1
|
||||
else:
|
||||
print("Existing UV map found for object: " + obj.name)
|
||||
for i in range(0, len(uv_layers)):
|
||||
if uv_layers[i].name == 'UVMap_Lightmap':
|
||||
uv_layers.active_index = i
|
||||
break
|
||||
|
||||
atlas_items.append(obj)
|
||||
obj.select_set(True)
|
||||
|
||||
if atlasgroup.tlm_atlas_lightmap_unwrap_mode == "SmartProject":
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
print("UV map created for object: " + obj.name)
|
||||
uvmap = uv_layers.new(name=uv_channel)
|
||||
uv_layers.active_index = len(uv_layers) - 1
|
||||
print("Atlasgroup Smart Project for: " + str(atlas_items))
|
||||
for obj in atlas_items:
|
||||
print("Applying Smart Project to: ")
|
||||
print(obj.name + ": Active UV: " + obj.data.uv_layers[obj.data.uv_layers.active_index].name)
|
||||
|
||||
|
||||
if len(atlas_items) > 0:
|
||||
bpy.context.view_layer.objects.active = atlas_items[0]
|
||||
|
||||
bpy.ops.object.mode_set(mode='EDIT')
|
||||
bpy.ops.mesh.select_all(action='SELECT')
|
||||
#API changes in 2.91 causes errors:
|
||||
if (2, 91, 0) > bpy.app.version:
|
||||
bpy.ops.uv.smart_project(angle_limit=45.0, island_margin=obj.TLM_ObjectProperties.tlm_mesh_unwrap_margin, user_area_weight=1.0, use_aspect=True, stretch_to_bounds=False)
|
||||
else:
|
||||
angle = math.radians(45.0)
|
||||
bpy.ops.uv.smart_project(angle_limit=angle, island_margin=obj.TLM_ObjectProperties.tlm_mesh_unwrap_margin, area_weight=1.0, correct_aspect=True, scale_to_bounds=False)
|
||||
bpy.ops.mesh.select_all(action='DESELECT')
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
print("Smart project done.")
|
||||
elif atlasgroup.tlm_atlas_lightmap_unwrap_mode == "Lightmap":
|
||||
|
||||
bpy.ops.object.mode_set(mode='EDIT')
|
||||
bpy.ops.uv.lightmap_pack('EXEC_SCREEN', PREF_CONTEXT='ALL_FACES', PREF_MARGIN_DIV=atlasgroup.tlm_atlas_unwrap_margin)
|
||||
bpy.ops.mesh.select_all(action='DESELECT')
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
|
||||
elif atlasgroup.tlm_atlas_lightmap_unwrap_mode == "Xatlas":
|
||||
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
print("Using Xatlas on Atlas Group: " + atlas)
|
||||
|
||||
for obj in atlas_items:
|
||||
obj.select_set(True)
|
||||
if len(atlas_items) > 0:
|
||||
bpy.context.view_layer.objects.active = atlas_items[0]
|
||||
|
||||
bpy.ops.object.mode_set(mode='EDIT')
|
||||
|
||||
Unwrap_Lightmap_Group_Xatlas_2_headless_call(obj)
|
||||
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
|
||||
else:
|
||||
print("Existing UV map found for object: " + obj.name)
|
||||
for i in range(0, len(uv_layers)):
|
||||
if uv_layers[i].name == 'UVMap_Lightmap':
|
||||
uv_layers.active_index = i
|
||||
break
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
print("Copied Existing UV Map for Atlas Group: " + atlas)
|
||||
|
||||
atlas_items.append(obj)
|
||||
obj.select_set(True)
|
||||
if atlasgroup.tlm_use_uv_packer:
|
||||
bpy.ops.object.select_all(action='DESELECT')
|
||||
for obj in atlas_items:
|
||||
obj.select_set(True)
|
||||
if len(atlas_items) > 0:
|
||||
bpy.context.view_layer.objects.active = atlas_items[0]
|
||||
bpy.ops.object.mode_set(mode='EDIT')
|
||||
bpy.ops.mesh.select_all(action='SELECT')
|
||||
|
||||
if atlasgroup.tlm_atlas_lightmap_unwrap_mode == "SmartProject":
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
print("Atlasgroup Smart Project for: " + str(atlas_items))
|
||||
for obj in atlas_items:
|
||||
print(obj.name + ": Active UV: " + obj.data.uv_layers[obj.data.uv_layers.active_index].name)
|
||||
bpy.context.scene.UVPackerProps.uvp_padding = atlasgroup.tlm_uv_packer_padding
|
||||
bpy.context.scene.UVPackerProps.uvp_engine = atlasgroup.tlm_uv_packer_packing_engine
|
||||
|
||||
if len(atlas_items) > 0:
|
||||
bpy.context.view_layer.objects.active = atlas_items[0]
|
||||
#print(x)
|
||||
|
||||
bpy.ops.object.mode_set(mode='EDIT')
|
||||
bpy.ops.mesh.select_all(action='SELECT')
|
||||
#API changes in 2.91 causes errors:
|
||||
if (2, 91, 0) > bpy.app.version:
|
||||
bpy.ops.uv.smart_project(angle_limit=45.0, island_margin=obj.TLM_ObjectProperties.tlm_mesh_unwrap_margin, user_area_weight=1.0, use_aspect=True, stretch_to_bounds=False)
|
||||
else:
|
||||
angle = math.radians(45.0)
|
||||
bpy.ops.uv.smart_project(angle_limit=angle, island_margin=obj.TLM_ObjectProperties.tlm_mesh_unwrap_margin, area_weight=1.0, correct_aspect=True, scale_to_bounds=False)
|
||||
bpy.ops.mesh.select_all(action='DESELECT')
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
elif atlasgroup.tlm_atlas_lightmap_unwrap_mode == "Lightmap":
|
||||
print("!!!!!!!!!!!!!!!!!!!!! Using UV Packer on: " + obj.name)
|
||||
|
||||
bpy.ops.object.mode_set(mode='EDIT')
|
||||
bpy.ops.uv.lightmap_pack('EXEC_SCREEN', PREF_CONTEXT='ALL_FACES', PREF_MARGIN_DIV=atlasgroup.tlm_atlas_unwrap_margin)
|
||||
bpy.ops.mesh.select_all(action='DESELECT')
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
if uv_layers.active == "UVMap_Lightmap":
|
||||
print("YES")
|
||||
else:
|
||||
print("NO")
|
||||
uv_layers.active_index = len(uv_layers) - 1
|
||||
|
||||
elif atlasgroup.tlm_atlas_lightmap_unwrap_mode == "Xatlas":
|
||||
if uv_layers.active == "UVMap_Lightmap":
|
||||
print("YES")
|
||||
else:
|
||||
print("NO")
|
||||
uv_layers.active_index = len(uv_layers) - 1
|
||||
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
print("Using Xatlas on Atlas Group: " + atlas)
|
||||
bpy.ops.uvpackeroperator.packbtn()
|
||||
|
||||
for obj in atlas_items:
|
||||
obj.select_set(True)
|
||||
if len(atlas_items) > 0:
|
||||
bpy.context.view_layer.objects.active = atlas_items[0]
|
||||
# if bpy.context.scene.UVPackerProps.uvp_engine == "OP0":
|
||||
# time.sleep(1)
|
||||
# else:
|
||||
# time.sleep(2)
|
||||
time.sleep(2)
|
||||
|
||||
bpy.ops.object.mode_set(mode='EDIT')
|
||||
#FIX THIS! MAKE A SEPARATE CALL. THIS IS A THREADED ASYNC
|
||||
|
||||
Unwrap_Lightmap_Group_Xatlas_2_headless_call(obj)
|
||||
bpy.ops.mesh.select_all(action='DESELECT')
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
|
||||
else:
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
print("Copied Existing UV Map for Atlas Group: " + atlas)
|
||||
#print(x)
|
||||
|
||||
for obj in bpy.context.scene.objects:
|
||||
if obj.type == 'MESH' and obj.name in bpy.context.view_layer.objects:
|
||||
if obj.TLM_ObjectProperties.tlm_mesh_lightmap_use:
|
||||
iterNum = iterNum + 1
|
||||
|
||||
#OBJECT UV PROJECTING
|
||||
print("PREPARE: OBJECTS")
|
||||
for obj in bpy.context.scene.objects:
|
||||
if obj.name in bpy.context.view_layer.objects: #Possible fix for view layer error
|
||||
if obj.type == 'MESH' and obj.name in bpy.context.view_layer.objects:
|
||||
if obj.TLM_ObjectProperties.tlm_mesh_lightmap_use:
|
||||
|
||||
hidden = False
|
||||
|
||||
#We check if the object is hidden
|
||||
if obj.hide_get():
|
||||
hidden = True
|
||||
if obj.hide_viewport:
|
||||
hidden = True
|
||||
if obj.hide_render:
|
||||
hidden = True
|
||||
|
||||
#We check if the object's collection is hidden
|
||||
collections = obj.users_collection
|
||||
|
||||
for collection in collections:
|
||||
|
||||
if collection.hide_viewport:
|
||||
hidden = True
|
||||
if collection.hide_render:
|
||||
hidden = True
|
||||
|
||||
try:
|
||||
if collection.name in bpy.context.scene.view_layers[0].layer_collection.children:
|
||||
if bpy.context.scene.view_layers[0].layer_collection.children[collection.name].hide_viewport:
|
||||
hidden = True
|
||||
except:
|
||||
print("Error: Could not find collection: " + collection.name)
|
||||
|
||||
if obj.TLM_ObjectProperties.tlm_mesh_lightmap_use and not hidden:
|
||||
|
||||
objWasHidden = False
|
||||
|
||||
|
@ -189,10 +376,14 @@ def configure_meshes(self):
|
|||
active = obs.active
|
||||
|
||||
#Provide material if none exists
|
||||
print("Preprocessing material for: " + obj.name)
|
||||
preprocess_material(obj, scene)
|
||||
|
||||
#UV Layer management here
|
||||
if not obj.TLM_ObjectProperties.tlm_mesh_lightmap_unwrap_mode == "AtlasGroupA":
|
||||
|
||||
print("Managing layer for Obj: " + obj.name)
|
||||
|
||||
uv_layers = obj.data.uv_layers
|
||||
|
||||
if not obj.TLM_ObjectProperties.tlm_use_default_channel:
|
||||
|
@ -225,6 +416,7 @@ def configure_meshes(self):
|
|||
else:
|
||||
angle = math.radians(45.0)
|
||||
bpy.ops.uv.smart_project(angle_limit=angle, island_margin=obj.TLM_ObjectProperties.tlm_mesh_unwrap_margin, area_weight=1.0, correct_aspect=True, scale_to_bounds=False)
|
||||
|
||||
bpy.ops.mesh.select_all(action='DESELECT')
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
|
||||
|
@ -242,6 +434,46 @@ def configure_meshes(self):
|
|||
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
print("Copied Existing UV Map for object: " + obj.name)
|
||||
|
||||
if obj.TLM_ObjectProperties.tlm_use_uv_packer:
|
||||
bpy.ops.object.select_all(action='DESELECT')
|
||||
obj.select_set(True)
|
||||
bpy.context.view_layer.objects.active = obj
|
||||
bpy.ops.object.mode_set(mode='EDIT')
|
||||
bpy.ops.mesh.select_all(action='SELECT')
|
||||
|
||||
bpy.context.scene.UVPackerProps.uvp_padding = obj.TLM_ObjectProperties.tlm_uv_packer_padding
|
||||
bpy.context.scene.UVPackerProps.uvp_engine = obj.TLM_ObjectProperties.tlm_uv_packer_packing_engine
|
||||
|
||||
#print(x)
|
||||
|
||||
print("!!!!!!!!!!!!!!!!!!!!! Using UV Packer on: " + obj.name)
|
||||
|
||||
if uv_layers.active == "UVMap_Lightmap":
|
||||
print("YES")
|
||||
else:
|
||||
print("NO")
|
||||
uv_layers.active_index = len(uv_layers) - 1
|
||||
|
||||
if uv_layers.active == "UVMap_Lightmap":
|
||||
print("YES")
|
||||
else:
|
||||
print("NO")
|
||||
uv_layers.active_index = len(uv_layers) - 1
|
||||
|
||||
bpy.ops.uvpackeroperator.packbtn()
|
||||
|
||||
if bpy.context.scene.UVPackerProps.uvp_engine == "OP0":
|
||||
time.sleep(1)
|
||||
else:
|
||||
time.sleep(2)
|
||||
|
||||
#FIX THIS! MAKE A SEPARATE CALL. THIS IS A THREADED ASYNC
|
||||
|
||||
bpy.ops.mesh.select_all(action='DESELECT')
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
|
||||
#print(x)
|
||||
|
||||
else:
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
print("Existing UV map found for obj: " + obj.name)
|
||||
|
@ -286,6 +518,13 @@ def configure_meshes(self):
|
|||
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
print("The material group is not supported!")
|
||||
|
||||
if (mainNode.type == "ShaderNodeMixRGB"):
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
print("Mix shader found")
|
||||
|
||||
#Skip for now
|
||||
slot.material.TLM_ignore = True
|
||||
|
||||
if (mainNode.type == "BSDF_PRINCIPLED"):
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
print("BSDF_Principled")
|
||||
|
@ -301,6 +540,7 @@ def configure_meshes(self):
|
|||
|
||||
#Clamp metallic
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_metallic_clamp == "limit":
|
||||
|
||||
MainMetNodeSocket = mainNode.inputs[4]
|
||||
if not len(MainMetNodeSocket.links) == 0:
|
||||
nodes = nodetree.nodes
|
||||
|
@ -308,14 +548,19 @@ def configure_meshes(self):
|
|||
MetClampNode.location = (-200,150)
|
||||
MetClampNode.inputs[2].default_value = 0.9
|
||||
minput = mainNode.inputs[4].links[0] #Metal input socket
|
||||
moutput = mainNode.inputs[4].links[0].from_node #Metal output node
|
||||
nodetree.links.remove(moutput.outputs[0].links[0]) #Works
|
||||
nodetree.links.new(moutput.outputs[0], MetClampNode.inputs[0]) #minput node to clamp node
|
||||
nodetree.links.new(MetClampNode.outputs[0],MainMetNodeSocket) #clamp node to metinput
|
||||
moutput = mainNode.inputs[4].links[0].from_socket #Output socket
|
||||
|
||||
nodetree.links.remove(minput)
|
||||
|
||||
nodetree.links.new(moutput, MetClampNode.inputs[0]) #minput node to clamp node
|
||||
nodetree.links.new(MetClampNode.outputs[0], MainMetNodeSocket) #clamp node to metinput
|
||||
|
||||
else:
|
||||
|
||||
if mainNode.inputs[4].default_value > 0.9:
|
||||
mainNode.inputs[4].default_value = 0.9
|
||||
elif bpy.context.scene.TLM_SceneProperties.tlm_metallic_clamp == "zero":
|
||||
|
||||
MainMetNodeSocket = mainNode.inputs[4]
|
||||
if not len(MainMetNodeSocket.links) == 0:
|
||||
nodes = nodetree.nodes
|
||||
|
@ -323,13 +568,18 @@ def configure_meshes(self):
|
|||
MetClampNode.location = (-200,150)
|
||||
MetClampNode.inputs[2].default_value = 0.0
|
||||
minput = mainNode.inputs[4].links[0] #Metal input socket
|
||||
moutput = mainNode.inputs[4].links[0].from_node #Metal output node
|
||||
nodetree.links.remove(moutput.outputs[0].links[0]) #Works
|
||||
nodetree.links.new(moutput.outputs[0], MetClampNode.inputs[0]) #minput node to clamp node
|
||||
nodetree.links.new(MetClampNode.outputs[0],MainMetNodeSocket) #clamp node to metinput
|
||||
moutput = mainNode.inputs[4].links[0].from_socket #Output socket
|
||||
|
||||
nodetree.links.remove(minput)
|
||||
|
||||
nodetree.links.new(moutput, MetClampNode.inputs[0]) #minput node to clamp node
|
||||
nodetree.links.new(MetClampNode.outputs[0], MainMetNodeSocket) #clamp node to metinput
|
||||
else:
|
||||
mainNode.inputs[4].default_value = 0.0
|
||||
|
||||
else: #Skip
|
||||
pass
|
||||
|
||||
if (mainNode.type == "BSDF_DIFFUSE"):
|
||||
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
print("BSDF_Diffuse")
|
||||
|
@ -526,13 +776,22 @@ def set_settings():
|
|||
sceneProperties = scene.TLM_SceneProperties
|
||||
engineProperties = scene.TLM_EngineProperties
|
||||
cycles.device = scene.TLM_EngineProperties.tlm_mode
|
||||
|
||||
if cycles.device == "GPU":
|
||||
scene.render.tile_x = 256
|
||||
scene.render.tile_y = 256
|
||||
else:
|
||||
scene.render.tile_x = 32
|
||||
scene.render.tile_y = 32
|
||||
|
||||
print(bpy.app.version)
|
||||
|
||||
if (3, 0, 0) >= bpy.app.version:
|
||||
|
||||
if cycles.device == "GPU":
|
||||
scene.cycles.tile_size = 256
|
||||
else:
|
||||
scene.cycles.tile_size = 32
|
||||
else:
|
||||
if cycles.device == "GPU":
|
||||
scene.render.tile_x = 256
|
||||
scene.render.tile_y = 256
|
||||
else:
|
||||
scene.render.tile_x = 32
|
||||
scene.render.tile_y = 32
|
||||
|
||||
if engineProperties.tlm_quality == "0":
|
||||
cycles.samples = 32
|
||||
|
@ -613,4 +872,45 @@ def store_existing(prev_container):
|
|||
bpy.context.view_layer.objects.active,
|
||||
selected,
|
||||
[scene.render.resolution_x, scene.render.resolution_y]
|
||||
]
|
||||
]
|
||||
|
||||
def skipIncompatibleMaterials(material):
|
||||
node_tree = material.node_tree
|
||||
nodes = material.node_tree.nodes
|
||||
|
||||
#ADD OR MIX SHADER? CUSTOM/GROUP?
|
||||
#IF Principled has emissive or transparency?
|
||||
|
||||
SkipMatList = ["EMISSION",
|
||||
"BSDF_TRANSPARENT",
|
||||
"BACKGROUND",
|
||||
"BSDF_HAIR",
|
||||
"BSDF_HAIR_PRINCIPLED",
|
||||
"HOLDOUT",
|
||||
"PRINCIPLED_VOLUME",
|
||||
"BSDF_REFRACTION",
|
||||
"EEVEE_SPECULAR",
|
||||
"BSDF_TRANSLUCENT",
|
||||
"VOLUME_ABSORPTION",
|
||||
"VOLUME_SCATTER"]
|
||||
|
||||
#Find output node
|
||||
outputNode = nodes[0]
|
||||
if(outputNode.type != "OUTPUT_MATERIAL"):
|
||||
for node in node_tree.nodes:
|
||||
if node.type == "OUTPUT_MATERIAL":
|
||||
outputNode = node
|
||||
break
|
||||
|
||||
#Find mainnode
|
||||
mainNode = outputNode.inputs[0].links[0].from_node
|
||||
|
||||
if mainNode.type in SkipMatList:
|
||||
material.TLM_ignore = True
|
||||
print("Ignored material: " + material.name)
|
||||
|
||||
def packUVPack():
|
||||
|
||||
|
||||
|
||||
pass
|
||||
|
|
|
@ -67,14 +67,14 @@ class TLM_Integrated_Denoise:
|
|||
filename, file_extension = os.path.splitext(image)
|
||||
filename = filename[:-6]
|
||||
|
||||
bpy.data.scenes["Scene"].render.filepath = self.image_output_destination + "/" + filename + "_denoised" + file_extension
|
||||
bpy.context.scene.render.filepath = self.image_output_destination + "/" + filename + "_denoised" + file_extension
|
||||
|
||||
denoised_image_path = self.image_output_destination
|
||||
bpy.data.scenes["Scene"].render.image_settings.file_format = "HDR"
|
||||
bpy.context.scene.render.image_settings.file_format = "HDR"
|
||||
|
||||
bpy.ops.render.render(write_still=True)
|
||||
|
||||
#Cleanup
|
||||
comp_nodes = [image_node, denoise_node, comp_node]
|
||||
for node in comp_nodes:
|
||||
tree.nodes.remove(node)
|
||||
tree.nodes.remove(node)
|
||||
|
|
|
@ -74,7 +74,7 @@ class TLM_OIDN_Denoise:
|
|||
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
|
||||
print("Loaded image: " + str(loaded_image))
|
||||
|
||||
verbose = bpy.context.scene.TLM_SceneProperties.tlm_verbose
|
||||
verbose = self.oidnProperties.tlm_oidn_verbose
|
||||
affinity = self.oidnProperties.tlm_oidn_affinity
|
||||
|
||||
if verbose:
|
||||
|
|
|
@ -1,10 +1,43 @@
|
|||
import bpy, math, os, gpu, bgl
|
||||
import bpy, math, os, gpu, bgl, importlib
|
||||
import numpy as np
|
||||
from . import utility
|
||||
from fractions import Fraction
|
||||
from gpu_extras.batch import batch_for_shader
|
||||
|
||||
def splitLogLuvAlphaAtlas(imageIn, outDir, quality):
|
||||
pass
|
||||
|
||||
def splitLogLuvAlpha(imageIn, outDir, quality):
|
||||
|
||||
bpy.app.driver_namespace["logman"].append("Starting LogLuv split for: " + str(imageIn))
|
||||
|
||||
cv2 = importlib.util.find_spec("cv2")
|
||||
|
||||
if cv2 is None:
|
||||
print("CV2 not found - Ignoring filtering")
|
||||
return 0
|
||||
else:
|
||||
cv2 = importlib.__import__("cv2")
|
||||
|
||||
print(imageIn)
|
||||
image = cv2.imread(imageIn, cv2.IMREAD_UNCHANGED)
|
||||
#cv2.imshow('image', image)
|
||||
split = cv2.split(image)
|
||||
merged = cv2.merge([split[0], split[1], split[2]])
|
||||
alpha = split[3]
|
||||
#b,g,r = cv2.split(image)
|
||||
#merged = cv2.merge([b, g, r])
|
||||
#alpha = cv2.merge([a,a,a])
|
||||
image_name = os.path.basename(imageIn)[:-4]
|
||||
#os.path.join(outDir, image_name+"_XYZ.png")
|
||||
|
||||
cv2.imwrite(os.path.join(outDir, image_name+"_XYZ.png"), merged)
|
||||
cv2.imwrite(os.path.join(outDir, image_name+"_W.png"), alpha)
|
||||
|
||||
def encodeLogLuvGPU(image, outDir, quality):
|
||||
|
||||
bpy.app.driver_namespace["logman"].append("Starting LogLuv encode for: " + str(image.name))
|
||||
|
||||
input_image = bpy.data.images[image.name]
|
||||
image_name = input_image.name
|
||||
|
||||
|
@ -139,9 +172,6 @@ def encodeLogLuvGPU(image, outDir, quality):
|
|||
bpy.context.scene.render.image_settings.quality = quality
|
||||
#input_image.save_render(filepath = input_image.filepath_raw, scene = bpy.context.scene)
|
||||
input_image.save()
|
||||
|
||||
#Todo - Find a way to save
|
||||
#bpy.ops.image.save_all_modified()
|
||||
|
||||
def encodeImageRGBDGPU(image, maxRange, outDir, quality):
|
||||
input_image = bpy.data.images[image.name]
|
||||
|
|
|
@ -7,7 +7,7 @@ class ViewportDraw:
|
|||
|
||||
bakefile = "TLM_Overlay.png"
|
||||
scriptDir = os.path.dirname(os.path.realpath(__file__))
|
||||
bakefile_path = os.path.abspath(os.path.join(scriptDir, '..', '..', 'assets/' + bakefile))
|
||||
bakefile_path = os.path.abspath(os.path.join(scriptDir, '..', '..', 'assets', bakefile))
|
||||
|
||||
image_name = "TLM_Overlay.png"
|
||||
|
||||
|
@ -15,7 +15,13 @@ class ViewportDraw:
|
|||
|
||||
print("Self path: " + bakefile_path)
|
||||
|
||||
image = bpy.data.images[image_name]
|
||||
for img in bpy.data.images:
|
||||
if img.filepath.endswith(image_name):
|
||||
image = img
|
||||
break
|
||||
|
||||
if not image:
|
||||
image = bpy.data.images[image_name]
|
||||
|
||||
x = 15
|
||||
y = 15
|
||||
|
@ -51,7 +57,11 @@ class ViewportDraw:
|
|||
if self.image:
|
||||
bgl.glEnable(bgl.GL_BLEND)
|
||||
bgl.glActiveTexture(bgl.GL_TEXTURE0)
|
||||
bgl.glBindTexture(bgl.GL_TEXTURE_2D, self.image.bindcode)
|
||||
|
||||
try:
|
||||
bgl.glBindTexture(bgl.GL_TEXTURE_2D, self.image.bindcode)
|
||||
except:
|
||||
bpy.types.SpaceView3D.draw_handler_remove(self.handle2, 'WINDOW')
|
||||
|
||||
self.shader.bind()
|
||||
self.shader.uniform_int("image", 0)
|
||||
|
@ -64,4 +74,4 @@ class ViewportDraw:
|
|||
|
||||
def remove_handle(self):
|
||||
#bpy.types.SpaceView3D.draw_handler_remove(self.handle, 'WINDOW')
|
||||
bpy.types.SpaceView3D.draw_handler_remove(self.handle2, 'WINDOW')
|
||||
bpy.types.SpaceView3D.draw_handler_remove(self.handle2, 'WINDOW')
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
import bpy
|
||||
import datetime
|
||||
|
||||
class TLM_Logman:
|
||||
|
||||
_log = []
|
||||
|
||||
def __init__(self):
|
||||
print("Logger started Init")
|
||||
self.append("Logger started.")
|
||||
|
||||
def append(self, appended):
|
||||
self._log.append(str(datetime.datetime.now()) + ": " + str(appended))
|
||||
|
||||
#TODO!
|
||||
def stats():
|
||||
pass
|
||||
|
||||
def dumpLog(self):
|
||||
for line in self._log:
|
||||
print(line)
|
|
@ -91,6 +91,8 @@ def postpack():
|
|||
|
||||
packer[atlas.name] = newPacker(PackingMode.Offline, PackingBin.BFF, rotation=False)
|
||||
|
||||
bpy.app.driver_namespace["logman"].append("Postpacking: " + str(atlas.name))
|
||||
|
||||
if scene.TLM_EngineProperties.tlm_setting_supersample == "2x":
|
||||
supersampling_scale = 2
|
||||
elif scene.TLM_EngineProperties.tlm_setting_supersample == "4x":
|
||||
|
@ -115,9 +117,13 @@ def postpack():
|
|||
|
||||
rect.append((res, res, obj.name))
|
||||
|
||||
#Add rect to bin
|
||||
for r in rect:
|
||||
packer[atlas.name].add_rect(*r)
|
||||
|
||||
print("Rects: " + str(rect))
|
||||
print("Bins:" + str(packer[atlas.name]))
|
||||
|
||||
packedAtlas[atlas.name] = np.zeros((atlas_resolution,atlas_resolution, 3), dtype="float32")
|
||||
|
||||
#Continue here...overwrite value if using 8-bit encoding
|
||||
|
@ -140,6 +146,8 @@ def postpack():
|
|||
|
||||
for idy, rect in enumerate(packer[atlas.name].rect_list()):
|
||||
|
||||
print("Packing atlas at: " + str(rect))
|
||||
|
||||
aob = rect[5]
|
||||
|
||||
src = cv2.imread(os.path.join(lightmap_directory, aob + end + formatEnc), image_channel_depth) #"_baked.hdr"
|
||||
|
@ -148,8 +156,11 @@ def postpack():
|
|||
|
||||
x,y,w,h = rect[1],rect[2],rect[3],rect[4]
|
||||
|
||||
print(src.shape)
|
||||
print(packedAtlas[atlas.name].shape)
|
||||
print("Obj Shape: " + str(src.shape))
|
||||
print("Atlas shape: " + str(packedAtlas[atlas.name].shape))
|
||||
|
||||
print("Bin Pos: ",x,y,w,h)
|
||||
|
||||
|
||||
packedAtlas[atlas.name][y:h+y, x:w+x] = src
|
||||
|
||||
|
@ -167,34 +178,64 @@ def postpack():
|
|||
|
||||
print("UVLayer set to: " + str(obj.data.uv_layers.active_index))
|
||||
|
||||
atlasRes = atlas_resolution
|
||||
texRes = rect[3] #Any dimension w/h (square)
|
||||
ratio = texRes/atlasRes
|
||||
scaleUV(obj.data.uv_layers.active, (ratio, ratio), (0,1))
|
||||
print(rect)
|
||||
|
||||
#Postpack error here...
|
||||
for uv_verts in obj.data.uv_layers.active.data:
|
||||
#For each vert
|
||||
|
||||
#NOTES! => X FUNKER
|
||||
#TODO => Y
|
||||
|
||||
#[0] = bin index
|
||||
#[1] = x
|
||||
#[2] = y (? + 1)
|
||||
#[3] = w
|
||||
#[4] = h
|
||||
|
||||
vertex_x = uv_verts.uv[0] + (rect[1]/atlasRes) #WORKING!
|
||||
vertex_y = uv_verts.uv[1] - (rect[2]/atlasRes) # + ((rect[2]-rect[4])/atlasRes) # # + (1-((rect[1]-rect[4])/atlasRes))
|
||||
#tr = "X: {0} + ({1}/{2})".format(uv_verts.uv[0],rect[1],atlasRes)
|
||||
#print(tr)
|
||||
#vertex_y = 1 - (uv_verts.uv[1]) uv_verts.uv[1] + (rect[1]/atlasRes)
|
||||
|
||||
#SET UV LAYER TO
|
||||
|
||||
atlasRes = atlas_resolution
|
||||
texRes = rect[3]
|
||||
x,y,w,z = x,y,texRes,texRes
|
||||
# atlasRes = atlas_resolution
|
||||
# texRes = rect[3] #Any dimension w/h (square)
|
||||
# print(texRes)
|
||||
# #texRes = 0.0,0.0
|
||||
# #x,y,w,z = x,y,texRes,texRes
|
||||
# x,y,w,z = x,y,0,0
|
||||
|
||||
ratio = atlasRes/texRes
|
||||
# ratio = atlasRes/texRes
|
||||
|
||||
if x == 0:
|
||||
x_offset = 0
|
||||
else:
|
||||
x_offset = 1/(atlasRes/x)
|
||||
# if x == 0:
|
||||
# x_offset = 0
|
||||
# else:
|
||||
# x_offset = 1/(atlasRes/x)
|
||||
|
||||
if y == 0:
|
||||
y_offset = 0
|
||||
else:
|
||||
y_offset = 1/(atlasRes/y)
|
||||
# if y == 0:
|
||||
# y_offset = 0
|
||||
# else:
|
||||
# y_offset = 1/(atlasRes/y)
|
||||
|
||||
vertex_x = (uv_verts.uv[0] * 1/(ratio)) + x_offset
|
||||
vertex_y = (1 - ((uv_verts.uv[1] * 1/(ratio)) + y_offset))
|
||||
# vertex_x = (uv_verts.uv[0] * 1/(ratio)) + x_offset
|
||||
# vertex_y = (1 - ((uv_verts.uv[1] * 1/(ratio)) + y_offset))
|
||||
|
||||
#TO FIX:
|
||||
#SELECT ALL
|
||||
#Scale Y => -1
|
||||
|
||||
uv_verts.uv[0] = vertex_x
|
||||
uv_verts.uv[1] = vertex_y
|
||||
|
||||
scaleUV(obj.data.uv_layers.active, (1, -1), getBoundsCenter(obj.data.uv_layers.active))
|
||||
print(getCenter(obj.data.uv_layers.active))
|
||||
#scaleUV(obj.data.uv_layers.active, (1, -1), getBoundsCenter(obj.data.uv_layers.active))
|
||||
#print(getCenter(obj.data.uv_layers.active))
|
||||
|
||||
cv2.imwrite(os.path.join(lightmap_directory, atlas.name + end + formatEnc), packedAtlas[atlas.name])
|
||||
print("Written: " + str(os.path.join(lightmap_directory, atlas.name + end + formatEnc)))
|
||||
|
@ -221,8 +262,12 @@ def postpack():
|
|||
|
||||
node.image = atlasImage
|
||||
|
||||
os.remove(os.path.join(lightmap_directory, obj.name + end + formatEnc))
|
||||
existing_image.user_clear()
|
||||
#print("Seeking for: " + atlasImage.filepath_raw)
|
||||
#print(x)
|
||||
|
||||
if(os.path.exists(os.path.join(lightmap_directory, obj.name + end + formatEnc))):
|
||||
os.remove(os.path.join(lightmap_directory, obj.name + end + formatEnc))
|
||||
existing_image.user_clear()
|
||||
|
||||
#Add dilation map here...
|
||||
for obj in bpy.context.scene.objects:
|
||||
|
|
|
@ -664,11 +664,14 @@ def Unwrap_Lightmap_Group_Xatlas_2_headless_call(obj):
|
|||
|
||||
def transfer_assets(copy, source, destination):
|
||||
for filename in glob.glob(os.path.join(source, '*.*')):
|
||||
shutil.copy(filename, destination)
|
||||
try:
|
||||
shutil.copy(filename, destination)
|
||||
except shutil.SameFileError:
|
||||
pass
|
||||
|
||||
def transfer_load():
|
||||
load_folder = bpy.path.abspath(os.path.join(os.path.dirname(bpy.data.filepath), bpy.context.scene.TLM_SceneProperties.tlm_load_folder))
|
||||
lightmap_folder = os.path.join(os.path.dirname(bpy.data.filepath), bpy.context.scene.TLM_EngineProperties.tlm_lightmap_savedir)
|
||||
print(load_folder)
|
||||
print(lightmap_folder)
|
||||
transfer_assets(True, load_folder, lightmap_folder)
|
||||
transfer_assets(True, load_folder, lightmap_folder)
|
||||
|
|
|
@ -85,9 +85,6 @@ class ARM_PT_ObjectPropsPanel(bpy.types.Panel):
|
|||
# Lightmapping props
|
||||
if obj.type == "MESH":
|
||||
row = layout.row(align=True)
|
||||
scene = bpy.context.scene
|
||||
if scene == None:
|
||||
return
|
||||
row.prop(obj.TLM_ObjectProperties, "tlm_mesh_lightmap_use")
|
||||
|
||||
if obj.TLM_ObjectProperties.tlm_mesh_lightmap_use:
|
||||
|
@ -122,6 +119,7 @@ class ARM_PT_ObjectPropsPanel(bpy.types.Panel):
|
|||
row.prop(obj.TLM_ObjectProperties, "tlm_postpack_object")
|
||||
row = layout.row()
|
||||
|
||||
|
||||
if obj.TLM_ObjectProperties.tlm_postpack_object and obj.TLM_ObjectProperties.tlm_mesh_lightmap_unwrap_mode != "AtlasGroupA":
|
||||
if scene.TLM_PostAtlasListItem >= 0 and len(scene.TLM_PostAtlasList) > 0:
|
||||
row = layout.row()
|
||||
|
@ -162,6 +160,15 @@ class ARM_PT_ObjectPropsPanel(bpy.types.Panel):
|
|||
row = layout.row(align=True)
|
||||
row.prop(obj.TLM_ObjectProperties, "tlm_mesh_filtering_iterations")
|
||||
|
||||
#If UV Packer installed
|
||||
if "UV-Packer" in bpy.context.preferences.addons.keys():
|
||||
row.prop(obj.TLM_ObjectProperties, "tlm_use_uv_packer")
|
||||
if obj.TLM_ObjectProperties.tlm_use_uv_packer:
|
||||
row = layout.row(align=True)
|
||||
row.prop(obj.TLM_ObjectProperties, "tlm_uv_packer_padding")
|
||||
row = layout.row(align=True)
|
||||
row.prop(obj.TLM_ObjectProperties, "tlm_uv_packer_packing_engine")
|
||||
|
||||
class ARM_PT_ModifiersPropsPanel(bpy.types.Panel):
|
||||
bl_label = "Armory Props"
|
||||
bl_space_type = "PROPERTIES"
|
||||
|
|
Loading…
Reference in New Issue