1732 lines
		
	
	
		
			66 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
		
		
			
		
	
	
			1732 lines
		
	
	
		
			66 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
|  | import bpy, os, time, blf, webbrowser, platform, numpy, bmesh | ||
|  | import math, subprocess, multiprocessing | ||
|  | from .. utility import utility | ||
|  | from .. utility import build | ||
|  | from .. utility.cycles import cache | ||
|  | from .. network import server | ||
|  | 
 | ||
|  | def setObjectLightmapByWeight(minimumRes, maximumRes, objWeight): | ||
|  |          | ||
|  |         availableResolutions = [32,64,128,256,512,1024,2048,4096,8192] | ||
|  |          | ||
|  |         minRes = minimumRes | ||
|  |         minResIdx = availableResolutions.index(minRes) | ||
|  |         maxRes = maximumRes | ||
|  |         maxResIdx = availableResolutions.index(maxRes) | ||
|  |          | ||
|  |         exampleWeight = objWeight | ||
|  |          | ||
|  |         if minResIdx == maxResIdx: | ||
|  |             pass | ||
|  |         else: | ||
|  |          | ||
|  |             increment = 1.0/(maxResIdx-minResIdx) | ||
|  |              | ||
|  |             assortedRange = [] | ||
|  |              | ||
|  |             for a in numpy.arange(0.0, 1.0, increment): | ||
|  |                 assortedRange.append(round(a, 2)) | ||
|  |                  | ||
|  |             assortedRange.append(1.0) | ||
|  |             nearestWeight = min(assortedRange, key=lambda x:abs(x - exampleWeight)) | ||
|  |             return (availableResolutions[assortedRange.index(nearestWeight) + minResIdx]) | ||
|  | 
 | ||
|  | class TLM_BuildLightmaps(bpy.types.Operator): | ||
|  |     bl_idname = "tlm.build_lightmaps" | ||
|  |     bl_label = "Build Lightmaps" | ||
|  |     bl_description = "Build Lightmaps" | ||
|  |     bl_options = {'REGISTER', 'UNDO'} | ||
|  | 
 | ||
|  |     def modal(self, context, event): | ||
|  | 
 | ||
|  |         #Add progress bar from 0.15 | ||
|  | 
 | ||
|  |         print("MODAL") | ||
|  | 
 | ||
|  |         return {'PASS_THROUGH'} | ||
|  | 
 | ||
|  |     def invoke(self, context, event): | ||
|  | 
 | ||
|  |         if not bpy.app.background: | ||
|  | 
 | ||
|  |             build.prepare_build(self, False) | ||
|  | 
 | ||
|  |         else: | ||
|  | 
 | ||
|  |             print("Running in background mode. Contextual operator not available. Use command 'thelightmapper.addon.build.prepare_build()'") | ||
|  | 
 | ||
|  |         return {'RUNNING_MODAL'} | ||
|  | 
 | ||
|  |     def cancel(self, context): | ||
|  |         pass | ||
|  | 
 | ||
|  |     def draw_callback_px(self, context, event): | ||
|  |         pass | ||
|  | 
 | ||
|  | class TLM_CleanLightmaps(bpy.types.Operator): | ||
|  |     bl_idname = "tlm.clean_lightmaps" | ||
|  |     bl_label = "Clean Lightmaps" | ||
|  |     bl_description = "Clean Lightmaps" | ||
|  |     bl_options = {'REGISTER', 'UNDO'} | ||
|  | 
 | ||
|  |     def execute(self, context): | ||
|  | 
 | ||
|  |         scene = context.scene | ||
|  | 
 | ||
|  |         filepath = bpy.data.filepath | ||
|  |         dirpath = os.path.join(os.path.dirname(bpy.data.filepath), scene.TLM_EngineProperties.tlm_lightmap_savedir) | ||
|  | 
 | ||
|  |         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: | ||
|  |                 if obj.TLM_ObjectProperties.tlm_mesh_lightmap_use: | ||
|  |                     cache.backup_material_restore(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: | ||
|  |                     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) | ||
|  | 
 | ||
|  |         for mat in bpy.data.materials: | ||
|  |             if mat.name.startswith("."): | ||
|  |                 if "_Original" in mat.name: | ||
|  |                     bpy.data.materials.remove(mat) | ||
|  | 
 | ||
|  |         for image in bpy.data.images: | ||
|  |             if image.name.endswith("_baked"): | ||
|  |                 bpy.data.images.remove(image, do_unlink=True) | ||
|  | 
 | ||
|  |         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: | ||
|  |                     if obj.TLM_ObjectProperties.tlm_postpack_object: | ||
|  | 
 | ||
|  |                         atlas = obj.TLM_ObjectProperties.tlm_postatlas_pointer | ||
|  |                         atlas_resize = False | ||
|  | 
 | ||
|  |                         for atlasgroup in scene.TLM_PostAtlasList: | ||
|  |                             if atlasgroup.name == atlas: | ||
|  |                                 atlas_resize = True | ||
|  | 
 | ||
|  |                         if atlas_resize: | ||
|  | 
 | ||
|  |                             bpy.ops.object.select_all(action='DESELECT') | ||
|  |                             obj.select_set(True) | ||
|  |                             bpy.context.view_layer.objects.active = obj | ||
|  | 
 | ||
|  |                             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" | ||
|  |                              | ||
|  |                             for i in range(0, len(uv_layers)): | ||
|  |                                 if uv_layers[i].name == uv_channel: | ||
|  |                                     uv_layers.active_index = i | ||
|  |                                     break | ||
|  | 
 | ||
|  |                             bpy.ops.object.mode_set(mode='EDIT') | ||
|  |                             bpy.ops.mesh.select_all(action='SELECT') | ||
|  |                             bpy.ops.uv.select_all(action='SELECT') | ||
|  |                             bpy.ops.uv.pack_islands(rotate=False, margin=0.001) | ||
|  |                             bpy.ops.uv.select_all(action='DESELECT') | ||
|  |                             bpy.ops.mesh.select_all(action='DESELECT') | ||
|  |                             bpy.ops.object.mode_set(mode='OBJECT') | ||
|  | 
 | ||
|  |                             if bpy.context.scene.TLM_SceneProperties.tlm_verbose: | ||
|  |                                 print("Resized for obj: " + obj.name) | ||
|  | 
 | ||
|  |                     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): | ||
|  |     bl_idname = "tlm.explore_lightmaps" | ||
|  |     bl_label = "Explore Lightmaps" | ||
|  |     bl_description = "Explore Lightmaps" | ||
|  |     bl_options = {'REGISTER', 'UNDO'} | ||
|  | 
 | ||
|  |     def execute(self, context): | ||
|  | 
 | ||
|  |         scene = context.scene | ||
|  |         cycles = scene.cycles | ||
|  | 
 | ||
|  |         if not bpy.data.is_saved: | ||
|  |             self.report({'INFO'}, "Please save your file first") | ||
|  |             return {"CANCELLED"} | ||
|  | 
 | ||
|  |         filepath = bpy.data.filepath | ||
|  |         dirpath = os.path.join(os.path.dirname(bpy.data.filepath), scene.TLM_EngineProperties.tlm_lightmap_savedir) | ||
|  |          | ||
|  |         if platform.system() != "Linux": | ||
|  | 
 | ||
|  |             if os.path.isdir(dirpath): | ||
|  |                 webbrowser.open('file://' + dirpath) | ||
|  |             else: | ||
|  |                 os.mkdir(dirpath) | ||
|  |                 webbrowser.open('file://' + dirpath) | ||
|  |         else: | ||
|  | 
 | ||
|  |             if os.path.isdir(dirpath): | ||
|  |                 os.system('xdg-open "%s"' % dirpath) | ||
|  |                 #webbrowser.open('file://' + dirpath) | ||
|  |             else: | ||
|  |                 os.mkdir(dirpath) | ||
|  |                 os.system('xdg-open "%s"' % dirpath) | ||
|  |                 #webbrowser.open('file://' + dirpath) | ||
|  | 
 | ||
|  |         return {'FINISHED'} | ||
|  | 
 | ||
|  | class TLM_EnableSet(bpy.types.Operator): | ||
|  |     """Enable for set""" | ||
|  |     bl_idname = "tlm.enable_set" | ||
|  |     bl_label = "Enable for set" | ||
|  |     bl_description = "Enable for set" | ||
|  |     bl_options = {'REGISTER', 'UNDO'} | ||
|  | 
 | ||
|  |     def execute(self, context): | ||
|  | 
 | ||
|  |         scene = context.scene | ||
|  | 
 | ||
|  |         weightList = {} #ObjName : [Dimension,Weight] | ||
|  |         max = 0 | ||
|  | 
 | ||
|  |         if bpy.context.scene.TLM_SceneProperties.tlm_utility_set == "Scene": | ||
|  |             for obj in bpy.context.scene.objects: | ||
|  |                 if obj.type == "MESH": | ||
|  | 
 | ||
|  |                     print("Enabling for scene: " + obj.name) | ||
|  |                      | ||
|  |                     bpy.context.view_layer.objects.active = obj | ||
|  |                     obj.select_set(True) | ||
|  |                     bpy.ops.object.transform_apply(location=False, rotation=True, scale=True) | ||
|  |                      | ||
|  |                     obj.TLM_ObjectProperties.tlm_mesh_lightmap_use = True | ||
|  |                      | ||
|  |                     obj.TLM_ObjectProperties.tlm_mesh_lightmap_unwrap_mode = bpy.context.scene.TLM_SceneProperties.tlm_mesh_lightmap_unwrap_mode | ||
|  |                     obj.TLM_ObjectProperties.tlm_mesh_unwrap_margin = bpy.context.scene.TLM_SceneProperties.tlm_mesh_unwrap_margin | ||
|  |                     obj.TLM_ObjectProperties.tlm_postpack_object = bpy.context.scene.TLM_SceneProperties.tlm_postpack_object | ||
|  | 
 | ||
|  |                     if obj.TLM_ObjectProperties.tlm_mesh_lightmap_unwrap_mode == "AtlasGroupA": | ||
|  |                         obj.TLM_ObjectProperties.tlm_atlas_pointer = bpy.context.scene.TLM_SceneProperties.tlm_atlas_pointer | ||
|  | 
 | ||
|  |                     obj.TLM_ObjectProperties.tlm_postatlas_pointer = bpy.context.scene.TLM_SceneProperties.tlm_postatlas_pointer | ||
|  |                      | ||
|  |                     if bpy.context.scene.TLM_SceneProperties.tlm_resolution_weight == "Single": | ||
|  |                         obj.TLM_ObjectProperties.tlm_mesh_lightmap_resolution = scene.TLM_SceneProperties.tlm_mesh_lightmap_resolution | ||
|  |                     elif bpy.context.scene.TLM_SceneProperties.tlm_resolution_weight == "Dimension": | ||
|  |                         obj_dimensions = obj.dimensions.x * obj.dimensions.y * obj.dimensions.z | ||
|  |                         weightList[obj.name] = [obj_dimensions, 0] | ||
|  |                         if obj_dimensions > max: | ||
|  |                             max = obj_dimensions | ||
|  |                     elif bpy.context.scene.TLM_SceneProperties.tlm_resolution_weight == "Surface": | ||
|  |                         bm = bmesh.new() | ||
|  |                         bm.from_mesh(obj.data) | ||
|  |                         area = sum(f.calc_area() for f in bm.faces) | ||
|  |                         weightList[obj.name] = [area, 0] | ||
|  |                         if area > max: | ||
|  |                             max = area | ||
|  |                     elif bpy.context.scene.TLM_SceneProperties.tlm_resolution_weight == "Volume": | ||
|  |                         bm = bmesh.new() | ||
|  |                         bm.from_mesh(obj.data) | ||
|  |                         volume = float( bm.calc_volume()) | ||
|  |                         weightList[obj.name] = [volume, 0] | ||
|  |                         if volume > max: | ||
|  |                             max = volume | ||
|  |          | ||
|  |         elif bpy.context.scene.TLM_SceneProperties.tlm_utility_set == "Selection": | ||
|  |             for obj in bpy.context.selected_objects: | ||
|  |                 if obj.type == "MESH": | ||
|  |                      | ||
|  |                     print("Enabling for selection: " + obj.name) | ||
|  |                      | ||
|  |                     bpy.context.view_layer.objects.active = obj | ||
|  |                     obj.select_set(True) | ||
|  |                     bpy.ops.object.transform_apply(location=False, rotation=True, scale=True) | ||
|  |                      | ||
|  |                     obj.TLM_ObjectProperties.tlm_mesh_lightmap_use = True | ||
|  |                      | ||
|  |                     obj.TLM_ObjectProperties.tlm_mesh_lightmap_unwrap_mode = bpy.context.scene.TLM_SceneProperties.tlm_mesh_lightmap_unwrap_mode | ||
|  |                     obj.TLM_ObjectProperties.tlm_mesh_unwrap_margin = bpy.context.scene.TLM_SceneProperties.tlm_mesh_unwrap_margin | ||
|  |                     obj.TLM_ObjectProperties.tlm_postpack_object = bpy.context.scene.TLM_SceneProperties.tlm_postpack_object | ||
|  | 
 | ||
|  |                     if obj.TLM_ObjectProperties.tlm_mesh_lightmap_unwrap_mode == "AtlasGroupA": | ||
|  |                         obj.TLM_ObjectProperties.tlm_atlas_pointer = bpy.context.scene.TLM_SceneProperties.tlm_atlas_pointer | ||
|  | 
 | ||
|  |                     obj.TLM_ObjectProperties.tlm_postatlas_pointer = bpy.context.scene.TLM_SceneProperties.tlm_postatlas_pointer | ||
|  |                      | ||
|  |                     if bpy.context.scene.TLM_SceneProperties.tlm_resolution_weight == "Single": | ||
|  |                         obj.TLM_ObjectProperties.tlm_mesh_lightmap_resolution = scene.TLM_SceneProperties.tlm_mesh_lightmap_resolution | ||
|  |                     elif bpy.context.scene.TLM_SceneProperties.tlm_resolution_weight == "Dimension": | ||
|  |                         obj_dimensions = obj.dimensions.x * obj.dimensions.y * obj.dimensions.z | ||
|  |                         weightList[obj.name] = [obj_dimensions, 0] | ||
|  |                         if obj_dimensions > max: | ||
|  |                             max = obj_dimensions | ||
|  |                     elif bpy.context.scene.TLM_SceneProperties.tlm_resolution_weight == "Surface": | ||
|  |                         bm = bmesh.new() | ||
|  |                         bm.from_mesh(obj.data) | ||
|  |                         area = sum(f.calc_area() for f in bm.faces) | ||
|  |                         weightList[obj.name] = [area, 0] | ||
|  |                         if area > max: | ||
|  |                             max = area | ||
|  |                     elif bpy.context.scene.TLM_SceneProperties.tlm_resolution_weight == "Volume": | ||
|  |                         bm = bmesh.new() | ||
|  |                         bm.from_mesh(obj.data) | ||
|  |                         volume = float( bm.calc_volume()) | ||
|  |                         weightList[obj.name] = [volume, 0] | ||
|  |                         if volume > max: | ||
|  |                             max = volume | ||
|  |          | ||
|  |         else: #Enabled | ||
|  |             for obj in bpy.context.scene.objects: | ||
|  |                 if obj.type == "MESH": | ||
|  |                     if obj.TLM_ObjectProperties.tlm_mesh_lightmap_use: | ||
|  | 
 | ||
|  |                         print("Enabling for designated: " + obj.name) | ||
|  |                          | ||
|  |                         bpy.context.view_layer.objects.active = obj | ||
|  |                         obj.select_set(True) | ||
|  |                         bpy.ops.object.transform_apply(location=False, rotation=True, scale=True) | ||
|  |                          | ||
|  |                         obj.TLM_ObjectProperties.tlm_mesh_lightmap_use = True | ||
|  |                          | ||
|  |                         obj.TLM_ObjectProperties.tlm_mesh_lightmap_unwrap_mode = bpy.context.scene.TLM_SceneProperties.tlm_mesh_lightmap_unwrap_mode | ||
|  |                         obj.TLM_ObjectProperties.tlm_mesh_unwrap_margin = bpy.context.scene.TLM_SceneProperties.tlm_mesh_unwrap_margin | ||
|  |                         obj.TLM_ObjectProperties.tlm_postpack_object = bpy.context.scene.TLM_SceneProperties.tlm_postpack_object | ||
|  | 
 | ||
|  |                         if obj.TLM_ObjectProperties.tlm_mesh_lightmap_unwrap_mode == "AtlasGroupA": | ||
|  |                             obj.TLM_ObjectProperties.tlm_atlas_pointer = bpy.context.scene.TLM_SceneProperties.tlm_atlas_pointer | ||
|  | 
 | ||
|  |                         obj.TLM_ObjectProperties.tlm_postatlas_pointer = bpy.context.scene.TLM_SceneProperties.tlm_postatlas_pointer | ||
|  |                          | ||
|  |                         if bpy.context.scene.TLM_SceneProperties.tlm_resolution_weight == "Single": | ||
|  |                             obj.TLM_ObjectProperties.tlm_mesh_lightmap_resolution = scene.TLM_SceneProperties.tlm_mesh_lightmap_resolution | ||
|  |                         elif bpy.context.scene.TLM_SceneProperties.tlm_resolution_weight == "Dimension": | ||
|  |                             obj_dimensions = obj.dimensions.x * obj.dimensions.y * obj.dimensions.z | ||
|  |                             weightList[obj.name] = [obj_dimensions, 0] | ||
|  |                             if obj_dimensions > max: | ||
|  |                                 max = obj_dimensions | ||
|  |                         elif bpy.context.scene.TLM_SceneProperties.tlm_resolution_weight == "Surface": | ||
|  |                             bm = bmesh.new() | ||
|  |                             bm.from_mesh(obj.data) | ||
|  |                             area = sum(f.calc_area() for f in bm.faces) | ||
|  |                             weightList[obj.name] = [area, 0] | ||
|  |                             if area > max: | ||
|  |                                 max = area | ||
|  |                         elif bpy.context.scene.TLM_SceneProperties.tlm_resolution_weight == "Volume": | ||
|  |                             bm = bmesh.new() | ||
|  |                             bm.from_mesh(obj.data) | ||
|  |                             volume = float( bm.calc_volume()) | ||
|  |                             weightList[obj.name] = [volume, 0] | ||
|  |                             if volume > max: | ||
|  |                                 max = volume | ||
|  | 
 | ||
|  |         if bpy.context.scene.TLM_SceneProperties.tlm_utility_set == "Scene": | ||
|  |             for obj in bpy.context.scene.objects: | ||
|  |                 if obj.type == "MESH": | ||
|  |          | ||
|  |                     if bpy.context.scene.TLM_SceneProperties.tlm_resolution_weight != "Single": | ||
|  |                         for key in weightList: | ||
|  |                             weightList[obj.name][1] = weightList[obj.name][0] / max | ||
|  |                         a = setObjectLightmapByWeight(int(bpy.context.scene.TLM_SceneProperties.tlm_resolution_min), int(bpy.context.scene.TLM_SceneProperties.tlm_resolution_max), weightList[obj.name][1]) | ||
|  |                         print(str(a) + "/" + str(weightList[obj.name][1])) | ||
|  |                         print("Scale: " + str(weightList[obj.name][0])) | ||
|  |                         print("Obj: " + obj.name) | ||
|  |                         obj.TLM_ObjectProperties.tlm_mesh_lightmap_resolution = str(a) | ||
|  | 
 | ||
|  |         elif bpy.context.scene.TLM_SceneProperties.tlm_utility_set == "Selection": | ||
|  |             for obj in bpy.context.selected_objects: | ||
|  |                 if obj.type == "MESH": | ||
|  | 
 | ||
|  |                     if bpy.context.scene.TLM_SceneProperties.tlm_resolution_weight != "Single": | ||
|  |                         for key in weightList: | ||
|  |                             weightList[obj.name][1] = weightList[obj.name][0] / max | ||
|  |                         a = setObjectLightmapByWeight(int(bpy.context.scene.TLM_SceneProperties.tlm_resolution_min), int(bpy.context.scene.TLM_SceneProperties.tlm_resolution_max), weightList[obj.name][1]) | ||
|  |                         print(str(a) + "/" + str(weightList[obj.name][1])) | ||
|  |                         print("Scale: " + str(weightList[obj.name][0])) | ||
|  |                         print("Obj: " + obj.name) | ||
|  |                         obj.TLM_ObjectProperties.tlm_mesh_lightmap_resolution = str(a) | ||
|  | 
 | ||
|  | 
 | ||
|  |         else: #Enabled | ||
|  |             for obj in bpy.context.scene.objects: | ||
|  |                 if obj.type == "MESH": | ||
|  |                     if obj.TLM_ObjectProperties.tlm_mesh_lightmap_use: | ||
|  | 
 | ||
|  |                         if bpy.context.scene.TLM_SceneProperties.tlm_resolution_weight != "Single": | ||
|  |                             for key in weightList: | ||
|  |                                 weightList[obj.name][1] = weightList[obj.name][0] / max | ||
|  |                             a = setObjectLightmapByWeight(int(bpy.context.scene.TLM_SceneProperties.tlm_resolution_min), int(bpy.context.scene.TLM_SceneProperties.tlm_resolution_max), weightList[obj.name][1]) | ||
|  |                             print(str(a) + "/" + str(weightList[obj.name][1])) | ||
|  |                             print("Scale: " + str(weightList[obj.name][0])) | ||
|  |                             print("Obj: " + obj.name) | ||
|  |                             print("") | ||
|  |                             obj.TLM_ObjectProperties.tlm_mesh_lightmap_resolution = str(a) | ||
|  |          | ||
|  |         return{'FINISHED'} | ||
|  | 
 | ||
|  | class TLM_DisableSelection(bpy.types.Operator): | ||
|  |     """Disable for set""" | ||
|  |     bl_idname = "tlm.disable_selection" | ||
|  |     bl_label = "Disable for set" | ||
|  |     bl_description = "Disable for selection" | ||
|  |     bl_options = {'REGISTER', 'UNDO'} | ||
|  | 
 | ||
|  |     def execute(self, context): | ||
|  | 
 | ||
|  |         scene = context.scene | ||
|  | 
 | ||
|  |         weightList = {} #ObjName : [Dimension,Weight] | ||
|  |         max = 0 | ||
|  | 
 | ||
|  |         if bpy.context.scene.TLM_SceneProperties.tlm_utility_set == "Scene": | ||
|  |             for obj in bpy.context.scene.objects: | ||
|  |                 if obj.type == "MESH": | ||
|  | 
 | ||
|  |                     obj.TLM_ObjectProperties.tlm_mesh_lightmap_use = False | ||
|  | 
 | ||
|  |         elif bpy.context.scene.TLM_SceneProperties.tlm_utility_set == "Selection": | ||
|  |             for obj in bpy.context.selected_objects: | ||
|  |                 if obj.type == "MESH": | ||
|  | 
 | ||
|  |                     obj.TLM_ObjectProperties.tlm_mesh_lightmap_use = False | ||
|  | 
 | ||
|  | 
 | ||
|  |         else: #Enabled | ||
|  |             for obj in bpy.context.scene.objects: | ||
|  |                 if obj.type == "MESH": | ||
|  |                     if obj.TLM_ObjectProperties.tlm_mesh_lightmap_use: | ||
|  | 
 | ||
|  |                         obj.TLM_ObjectProperties.tlm_mesh_lightmap_use = False | ||
|  | 
 | ||
|  | 
 | ||
|  |         return{'FINISHED'} | ||
|  | 
 | ||
|  | class TLM_RemoveLightmapUV(bpy.types.Operator): | ||
|  |     """Remove Lightmap UV for set""" | ||
|  |     bl_idname = "tlm.remove_uv_selection" | ||
|  |     bl_label = "Remove Lightmap UV" | ||
|  |     bl_description = "Remove Lightmap UV for 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": | ||
|  | 
 | ||
|  |                     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" | ||
|  | 
 | ||
|  |                     for uvlayer in uv_layers: | ||
|  |                         if uvlayer.name == uv_channel: | ||
|  |                             uv_layers.remove(uvlayer) | ||
|  | 
 | ||
|  |         elif bpy.context.scene.TLM_SceneProperties.tlm_utility_set == "Selection": | ||
|  |             for obj in bpy.context.selected_objects: | ||
|  |                 if obj.type == "MESH": | ||
|  | 
 | ||
|  |                     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" | ||
|  | 
 | ||
|  |                     for uvlayer in uv_layers: | ||
|  |                         if uvlayer.name == uv_channel: | ||
|  |                             uv_layers.remove(uvlayer) | ||
|  | 
 | ||
|  |         else: #Enabled | ||
|  |             for obj in bpy.context.scene.objects: | ||
|  |                 if obj.type == "MESH": | ||
|  |                     if obj.TLM_ObjectProperties.tlm_mesh_lightmap_use: | ||
|  | 
 | ||
|  |                         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" | ||
|  | 
 | ||
|  |                         for uvlayer in uv_layers: | ||
|  |                             if uvlayer.name == uv_channel: | ||
|  |                                 uv_layers.remove(uvlayer) | ||
|  | 
 | ||
|  |         return{'FINISHED'} | ||
|  | 
 | ||
|  | class TLM_SelectLightmapped(bpy.types.Operator): | ||
|  |     """Select all objects for lightmapping""" | ||
|  |     bl_idname = "tlm.select_lightmapped_objects" | ||
|  |     bl_label = "Select lightmap objects" | ||
|  |     bl_description = "Remove Lightmap UV for selection" | ||
|  |     bl_options = {'REGISTER', 'UNDO'} | ||
|  | 
 | ||
|  |     def execute(self, context): | ||
|  | 
 | ||
|  |         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: | ||
|  | 
 | ||
|  |                     obj.select_set(True) | ||
|  | 
 | ||
|  |         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" | ||
|  |     bl_label = "Add a new item" | ||
|  |     bl_description = "Create a new AtlasGroup" | ||
|  | 
 | ||
|  |     def execute(self, context): | ||
|  |         scene = context.scene | ||
|  |         scene.TLM_AtlasList.add() | ||
|  |         scene.TLM_AtlasListItem = len(scene.TLM_AtlasList) - 1 | ||
|  | 
 | ||
|  |         scene.TLM_AtlasList[len(scene.TLM_AtlasList) - 1].name = "AtlasGroup" | ||
|  | 
 | ||
|  |         return{'FINISHED'} | ||
|  | 
 | ||
|  | class TLM_PostAtlasListNewItem(bpy.types.Operator): | ||
|  |     # Add a new item to the list | ||
|  |     bl_idname = "tlm_postatlaslist.new_item" | ||
|  |     bl_label = "Add a new item" | ||
|  |     bl_description = "Create a new AtlasGroup" | ||
|  |     bl_description = "" | ||
|  | 
 | ||
|  |     def execute(self, context): | ||
|  |         scene = context.scene | ||
|  |         scene.TLM_PostAtlasList.add() | ||
|  |         scene.TLM_PostAtlasListItem = len(scene.TLM_PostAtlasList) - 1 | ||
|  | 
 | ||
|  |         scene.TLM_PostAtlasList[len(scene.TLM_PostAtlasList) - 1].name = "AtlasGroup" | ||
|  | 
 | ||
|  |         return{'FINISHED'} | ||
|  | 
 | ||
|  | class TLM_AtlastListDeleteItem(bpy.types.Operator): | ||
|  |     # Delete the selected item from the list | ||
|  |     bl_idname = "tlm_atlaslist.delete_item" | ||
|  |     bl_label = "Deletes an item" | ||
|  |     bl_description = "Delete an AtlasGroup" | ||
|  | 
 | ||
|  |     @classmethod | ||
|  |     def poll(self, context): | ||
|  |         """ Enable if there's something in the list """ | ||
|  |         scene = context.scene | ||
|  |         return len(scene.TLM_AtlasList) > 0 | ||
|  | 
 | ||
|  |     def execute(self, context): | ||
|  |         scene = context.scene | ||
|  |         list = scene.TLM_AtlasList | ||
|  |         index = scene.TLM_AtlasListItem | ||
|  | 
 | ||
|  |         for obj in bpy.context.scene.objects: | ||
|  | 
 | ||
|  |             atlasName = scene.TLM_AtlasList[index].name | ||
|  | 
 | ||
|  |             if obj.TLM_ObjectProperties.tlm_atlas_pointer == atlasName: | ||
|  |                 obj.TLM_ObjectProperties.tlm_mesh_lightmap_unwrap_mode = "SmartProject" | ||
|  | 
 | ||
|  |         list.remove(index) | ||
|  | 
 | ||
|  |         if index > 0: | ||
|  |             index = index - 1 | ||
|  | 
 | ||
|  |         scene.TLM_AtlasListItem = index | ||
|  |         return{'FINISHED'} | ||
|  | 
 | ||
|  | class TLM_PostAtlastListDeleteItem(bpy.types.Operator): | ||
|  |     # Delete the selected item from the list | ||
|  |     bl_idname = "tlm_postatlaslist.delete_item" | ||
|  |     bl_label = "Deletes an item" | ||
|  |     bl_description = "Delete an AtlasGroup" | ||
|  | 
 | ||
|  |     @classmethod | ||
|  |     def poll(self, context): | ||
|  |         """ Enable if there's something in the list """ | ||
|  |         scene = context.scene | ||
|  |         return len(scene.TLM_PostAtlasList) > 0 | ||
|  | 
 | ||
|  |     def execute(self, context): | ||
|  |         scene = context.scene | ||
|  |         list = scene.TLM_PostAtlasList | ||
|  |         index = scene.TLM_PostAtlasListItem | ||
|  | 
 | ||
|  |         for obj in bpy.context.scene.objects: | ||
|  | 
 | ||
|  |             atlasName = scene.TLM_PostAtlasList[index].name | ||
|  | 
 | ||
|  |             if obj.TLM_ObjectProperties.tlm_atlas_pointer == atlasName: | ||
|  |                 obj.TLM_ObjectProperties.tlm_mesh_lightmap_unwrap_mode = "SmartProject" | ||
|  | 
 | ||
|  |         list.remove(index) | ||
|  | 
 | ||
|  |         if index > 0: | ||
|  |             index = index - 1 | ||
|  | 
 | ||
|  |         scene.TLM_PostAtlasListItem = index | ||
|  |         return{'FINISHED'} | ||
|  | 
 | ||
|  | class TLM_AtlasListMoveItem(bpy.types.Operator): | ||
|  |     # Move an item in the list | ||
|  |     bl_idname = "tlm_atlaslist.move_item" | ||
|  |     bl_label = "Move an item in the list" | ||
|  |     bl_description = "Move an item in the list" | ||
|  |     direction: bpy.props.EnumProperty( | ||
|  |                 items=( | ||
|  |                     ('UP', 'Up', ""), | ||
|  |                     ('DOWN', 'Down', ""),)) | ||
|  | 
 | ||
|  |     def move_index(self): | ||
|  |         # Move index of an item render queue while clamping it | ||
|  |         scene = context.scene | ||
|  |         index = scene.TLM_AtlasListItem | ||
|  |         list_length = len(scene.TLM_AtlasList) - 1 | ||
|  |         new_index = 0 | ||
|  | 
 | ||
|  |         if self.direction == 'UP': | ||
|  |             new_index = index - 1 | ||
|  |         elif self.direction == 'DOWN': | ||
|  |             new_index = index + 1 | ||
|  | 
 | ||
|  |         new_index = max(0, min(new_index, list_length)) | ||
|  |         scene.TLM_AtlasList.move(index, new_index) | ||
|  |         scene.TLM_AtlasListItem = new_index | ||
|  | 
 | ||
|  |     def execute(self, context): | ||
|  |         scene = context.scene | ||
|  |         list = scene.TLM_AtlasList | ||
|  |         index = scene.TLM_AtlasListItem | ||
|  | 
 | ||
|  |         if self.direction == 'DOWN': | ||
|  |             neighbor = index + 1 | ||
|  |             self.move_index() | ||
|  | 
 | ||
|  |         elif self.direction == 'UP': | ||
|  |             neighbor = index - 1 | ||
|  |             self.move_index() | ||
|  |         else: | ||
|  |             return{'CANCELLED'} | ||
|  |         return{'FINISHED'} | ||
|  | 
 | ||
|  | class TLM_PostAtlasListMoveItem(bpy.types.Operator): | ||
|  |     # Move an item in the list | ||
|  |     bl_idname = "tlm_postatlaslist.move_item" | ||
|  |     bl_label = "Move an item in the list" | ||
|  |     bl_description = "Move an item in the list" | ||
|  |     direction: bpy.props.EnumProperty( | ||
|  |                 items=( | ||
|  |                     ('UP', 'Up', ""), | ||
|  |                     ('DOWN', 'Down', ""),)) | ||
|  | 
 | ||
|  |     def move_index(self): | ||
|  |         # Move index of an item render queue while clamping it | ||
|  |         scene = context.scene | ||
|  |         index = scene.TLM_PostAtlasListItem | ||
|  |         list_length = len(scene.TLM_PostAtlasList) - 1 | ||
|  |         new_index = 0 | ||
|  | 
 | ||
|  |         if self.direction == 'UP': | ||
|  |             new_index = index - 1 | ||
|  |         elif self.direction == 'DOWN': | ||
|  |             new_index = index + 1 | ||
|  | 
 | ||
|  |         new_index = max(0, min(new_index, list_length)) | ||
|  |         scene.TLM_PostAtlasList.move(index, new_index) | ||
|  |         scene.TLM_PostAtlasListItem = new_index | ||
|  | 
 | ||
|  |     def execute(self, context): | ||
|  |         scene = context.scene | ||
|  |         list = scene.TLM_PostAtlasList | ||
|  |         index = scene.TLM_PostAtlasListItem | ||
|  | 
 | ||
|  |         if self.direction == 'DOWN': | ||
|  |             neighbor = index + 1 | ||
|  |             self.move_index() | ||
|  | 
 | ||
|  |         elif self.direction == 'UP': | ||
|  |             neighbor = index - 1 | ||
|  |             self.move_index() | ||
|  |         else: | ||
|  |             return{'CANCELLED'} | ||
|  |         return{'FINISHED'} | ||
|  | 
 | ||
|  | class TLM_StartServer(bpy.types.Operator): | ||
|  |     bl_idname = "tlm.start_server" | ||
|  |     bl_label = "Start Network Server" | ||
|  |     bl_description = "Start Network Server" | ||
|  |     bl_options = {'REGISTER', 'UNDO'} | ||
|  | 
 | ||
|  |     def modal(self, context, event): | ||
|  | 
 | ||
|  |         #Add progress bar from 0.15 | ||
|  | 
 | ||
|  |         print("MODAL") | ||
|  | 
 | ||
|  |         return {'PASS_THROUGH'} | ||
|  | 
 | ||
|  |     def invoke(self, context, event): | ||
|  | 
 | ||
|  |         server.startServer() | ||
|  | 
 | ||
|  |         return {'RUNNING_MODAL'} | ||
|  | 
 | ||
|  | class TLM_BuildEnvironmentProbes(bpy.types.Operator): | ||
|  |     bl_idname = "tlm.build_environmentprobe" | ||
|  |     bl_label = "Build Environment Probes" | ||
|  |     bl_description = "Build all environment probes from reflection cubemaps" | ||
|  |     bl_options = {'REGISTER', 'UNDO'} | ||
|  | 
 | ||
|  |     def invoke(self, context, event): | ||
|  | 
 | ||
|  |         for obj in bpy.context.scene.objects: | ||
|  | 
 | ||
|  |             if obj.type == "LIGHT_PROBE": | ||
|  |                 if obj.data.type == "CUBEMAP": | ||
|  | 
 | ||
|  |                     cam_name = "EnvPCam_" + obj.name | ||
|  |                     camera = bpy.data.cameras.new(cam_name) | ||
|  |                     camobj_name = "EnvPCamera_" + obj.name | ||
|  |                     cam_obj = bpy.data.objects.new(camobj_name, camera) | ||
|  |                     bpy.context.collection.objects.link(cam_obj) | ||
|  |                     cam_obj.location = obj.location | ||
|  |                     camera.angle = math.radians(90) | ||
|  | 
 | ||
|  |                     prevResx = bpy.context.scene.render.resolution_x | ||
|  |                     prevResy = bpy.context.scene.render.resolution_y | ||
|  |                     prevCam = bpy.context.scene.camera | ||
|  |                     prevEngine = bpy.context.scene.render.engine | ||
|  |                     bpy.context.scene.camera = cam_obj | ||
|  | 
 | ||
|  |                     bpy.context.scene.render.engine = bpy.context.scene.TLM_SceneProperties.tlm_environment_probe_engine | ||
|  |                     bpy.context.scene.render.resolution_x = int(bpy.context.scene.TLM_SceneProperties.tlm_environment_probe_resolution) | ||
|  |                     bpy.context.scene.render.resolution_y = int(bpy.context.scene.TLM_SceneProperties.tlm_environment_probe_resolution) | ||
|  | 
 | ||
|  |                     savedir = os.path.dirname(bpy.data.filepath) | ||
|  |                     directory = os.path.join(savedir, "Probes") | ||
|  | 
 | ||
|  |                     t = 90 | ||
|  | 
 | ||
|  |                     inverted = bpy.context.scene.TLM_SceneProperties.tlm_invert_direction | ||
|  | 
 | ||
|  |                     if inverted: | ||
|  | 
 | ||
|  |                         positions = { | ||
|  |                                 "xp" : (math.radians(t), 0, math.radians(0)), | ||
|  |                                 "zp" : (math.radians(t), 0, math.radians(t)), | ||
|  |                                 "xm" : (math.radians(t), 0, math.radians(t*2)), | ||
|  |                                 "zm" : (math.radians(t), 0, math.radians(-t)), | ||
|  |                                 "yp" : (math.radians(t*2), 0, math.radians(t)), | ||
|  |                                 "ym" : (0, 0, math.radians(t)) | ||
|  |                         } | ||
|  | 
 | ||
|  |                     else: | ||
|  | 
 | ||
|  |                         positions = { | ||
|  |                                 "xp" : (math.radians(t), 0, math.radians(t*2)), | ||
|  |                                 "zp" : (math.radians(t), 0, math.radians(-t)), | ||
|  |                                 "xm" : (math.radians(t), 0, math.radians(0)), | ||
|  |                                 "zm" : (math.radians(t), 0, math.radians(t)), | ||
|  |                                 "yp" : (math.radians(t*2), 0, math.radians(-t)), | ||
|  |                                 "ym" : (0, 0, math.radians(-t)) | ||
|  |                         } | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  |                     cam = cam_obj | ||
|  |                     image_settings = bpy.context.scene.render.image_settings | ||
|  |                     image_settings.file_format = "HDR" | ||
|  |                     image_settings.color_depth = '32' | ||
|  | 
 | ||
|  |                     for val in positions: | ||
|  |                         cam.rotation_euler = positions[val] | ||
|  |                          | ||
|  |                         filename = os.path.join(directory, val) + "_" + camobj_name + ".hdr" | ||
|  |                         bpy.context.scene.render.filepath = filename | ||
|  |                         print("Writing out: " + val) | ||
|  |                         bpy.ops.render.render(write_still=True) | ||
|  | 
 | ||
|  |                     cmft_path = bpy.path.abspath(os.path.join(os.path.dirname(bpy.data.filepath), bpy.context.scene.TLM_SceneProperties.tlm_cmft_path)) | ||
|  | 
 | ||
|  |                     output_file_irr = camobj_name + ".hdr" | ||
|  | 
 | ||
|  |                     posx = directory + "/" + "xp_" + camobj_name + ".hdr" | ||
|  |                     negx = directory + "/" + "xm_" + camobj_name + ".hdr" | ||
|  |                     posy = directory + "/" + "yp_" + camobj_name + ".hdr" | ||
|  |                     negy = directory + "/" + "ym_" + camobj_name + ".hdr" | ||
|  |                     posz = directory + "/" + "zp_" + camobj_name + ".hdr" | ||
|  |                     negz = directory + "/" + "zm_" + camobj_name + ".hdr" | ||
|  |                     output = directory + "/" + camobj_name | ||
|  | 
 | ||
|  |                     if platform.system() == 'Windows': | ||
|  |                         envpipe = [cmft_path,  | ||
|  |                         '--inputFacePosX', posx,  | ||
|  |                         '--inputFaceNegX', negx,  | ||
|  |                         '--inputFacePosY', posy,  | ||
|  |                         '--inputFaceNegY', negy,  | ||
|  |                         '--inputFacePosZ', posz,  | ||
|  |                         '--inputFaceNegZ', negz,  | ||
|  |                         '--output0', output,  | ||
|  |                         '--output0params',  | ||
|  |                         'hdr,rgbe,latlong'] | ||
|  |                          | ||
|  |                     else: | ||
|  |                         envpipe = [cmft_path + '--inputFacePosX' + posx  | ||
|  |                         + '--inputFaceNegX' + negx  | ||
|  |                         + '--inputFacePosY' + posy  | ||
|  |                         + '--inputFaceNegY' + negy  | ||
|  |                         + '--inputFacePosZ' + posz  | ||
|  |                         + '--inputFaceNegZ' + negz  | ||
|  |                         + '--output0' + output  | ||
|  |                         + '--output0params' + 'hdr,rgbe,latlong'] | ||
|  | 
 | ||
|  |                     if bpy.context.scene.TLM_SceneProperties.tlm_verbose: | ||
|  |                         print("Calling CMFT with:" + str(envpipe)) | ||
|  | 
 | ||
|  |                     if bpy.context.scene.TLM_SceneProperties.tlm_create_spherical: | ||
|  |                         subprocess.call(envpipe, shell=True) | ||
|  | 
 | ||
|  |                     input2 = output + ".hdr" | ||
|  |                     output2 = directory + "/" + camobj_name | ||
|  | 
 | ||
|  |                     if platform.system() == 'Windows': | ||
|  |                         envpipe2 = [cmft_path,  | ||
|  |                         '--input', input2,  | ||
|  |                         '--filter', 'shcoeffs',  | ||
|  |                         '--outputNum', '1',  | ||
|  |                         '--output0', output2] | ||
|  |                          | ||
|  |                     else: | ||
|  |                         envpipe2 = [cmft_path +  | ||
|  |                         '--input' + input2 | ||
|  |                         + '-filter' + 'shcoeffs' | ||
|  |                         + '--outputNum' + '1' | ||
|  |                         + '--output0' + output2] | ||
|  |                          | ||
|  |                     if bpy.context.scene.TLM_SceneProperties.tlm_write_sh: | ||
|  |                         subprocess.call(envpipe2, shell=True) | ||
|  | 
 | ||
|  |                     if bpy.context.scene.TLM_SceneProperties.tlm_write_radiance: | ||
|  | 
 | ||
|  |                         use_opencl = 'false' | ||
|  |                         cpu_count = 2 | ||
|  | 
 | ||
|  |                         # 4096 = 256 face | ||
|  |                         # 2048 = 128 face | ||
|  |                         # 1024 = 64 face | ||
|  |                         target_w = int(512) | ||
|  |                         face_size = target_w / 8 | ||
|  |                         if target_w == 2048: | ||
|  |                             mip_count = 9 | ||
|  |                         elif target_w == 1024: | ||
|  |                             mip_count = 8 | ||
|  |                         else: | ||
|  |                             mip_count = 7 | ||
|  | 
 | ||
|  |                         output_file_rad = directory + "/" + camobj_name + "_rad.hdr" | ||
|  |                          | ||
|  |                         if platform.system() == 'Windows': | ||
|  | 
 | ||
|  |                             envpipe3 = [ | ||
|  |                                 cmft_path, | ||
|  |                                 '--input', input2, | ||
|  |                                 '--filter', 'radiance', | ||
|  |                                 '--dstFaceSize', str(face_size), | ||
|  |                                 '--srcFaceSize', str(face_size), | ||
|  |                                 '--excludeBase', 'false', | ||
|  |                                 # '--mipCount', str(mip_count), | ||
|  |                                 '--glossScale', '8', | ||
|  |                                 '--glossBias', '3', | ||
|  |                                 '--lightingModel', 'blinnbrdf', | ||
|  |                                 '--edgeFixup', 'none', | ||
|  |                                 '--numCpuProcessingThreads', str(cpu_count), | ||
|  |                                 '--useOpenCL', use_opencl, | ||
|  |                                 '--clVendor', 'anyGpuVendor', | ||
|  |                                 '--deviceType', 'gpu', | ||
|  |                                 '--deviceIndex', '0', | ||
|  |                                 '--generateMipChain', 'true', | ||
|  |                                 '--inputGammaNumerator', '1.0', | ||
|  |                                 '--inputGammaDenominator', '1.0', | ||
|  |                                 '--outputGammaNumerator', '1.0', | ||
|  |                                 '--outputGammaDenominator', '1.0', | ||
|  |                                 '--outputNum', '1', | ||
|  |                                 '--output0', output_file_rad, | ||
|  |                                 '--output0params', 'hdr,rgbe,latlong' | ||
|  |                             ] | ||
|  | 
 | ||
|  |                             subprocess.call(envpipe3) | ||
|  | 
 | ||
|  |                         else: | ||
|  | 
 | ||
|  |                             envpipe3 = cmft_path + \ | ||
|  |                                 ' --input "' + input2 + '"' + \ | ||
|  |                                 ' --filter radiance' + \ | ||
|  |                                 ' --dstFaceSize ' + str(face_size) + \ | ||
|  |                                 ' --srcFaceSize ' + str(face_size) + \ | ||
|  |                                 ' --excludeBase false' + \ | ||
|  |                                 ' --glossScale 8' + \ | ||
|  |                                 ' --glossBias 3' + \ | ||
|  |                                 ' --lightingModel blinnbrdf' + \ | ||
|  |                                 ' --edgeFixup none' + \ | ||
|  |                                 ' --numCpuProcessingThreads ' + str(cpu_count) + \ | ||
|  |                                 ' --useOpenCL ' + use_opencl + \ | ||
|  |                                 ' --clVendor anyGpuVendor' + \ | ||
|  |                                 ' --deviceType gpu' + \ | ||
|  |                                 ' --deviceIndex 0' + \ | ||
|  |                                 ' --generateMipChain true' + \ | ||
|  |                                 ' --inputGammaNumerator ' + '1.0' + \ | ||
|  |                                 ' --inputGammaDenominator 1.0' + \ | ||
|  |                                 ' --outputGammaNumerator 1.0' + \ | ||
|  |                                 ' --outputGammaDenominator 1.0' + \ | ||
|  |                                 ' --outputNum 1' + \ | ||
|  |                                 ' --output0 "' + output_file_rad + '"' + \ | ||
|  |                                 ' --output0params hdr,rgbe,latlong' | ||
|  | 
 | ||
|  |                             subprocess.call([envpipe3], shell=True) | ||
|  | 
 | ||
|  |                     for obj in bpy.context.scene.objects: | ||
|  |                         obj.select_set(False) | ||
|  | 
 | ||
|  |                     cam_obj.select_set(True) | ||
|  |                     bpy.ops.object.delete() | ||
|  |                     bpy.context.scene.render.resolution_x = prevResx | ||
|  |                     bpy.context.scene.render.resolution_y = prevResy | ||
|  |                     bpy.context.scene.camera = prevCam | ||
|  |                     bpy.context.scene.render.engine = prevEngine | ||
|  | 
 | ||
|  |                     print("Finished building environment probes") | ||
|  | 
 | ||
|  | 
 | ||
|  |         return {'RUNNING_MODAL'} | ||
|  | 
 | ||
|  | class TLM_CleanBuildEnvironmentProbes(bpy.types.Operator):  | ||
|  |     bl_idname = "tlm.clean_environmentprobe" | ||
|  |     bl_label = "Clean Environment Probes" | ||
|  |     bl_description = "Clean Environment Probes" | ||
|  |     bl_options = {'REGISTER', 'UNDO'} | ||
|  | 
 | ||
|  |     def execute(self, context): | ||
|  | 
 | ||
|  |         scene = context.scene | ||
|  | 
 | ||
|  |         savedir = os.path.dirname(bpy.data.filepath) | ||
|  |         dirpath = os.path.join(savedir, "Probes") | ||
|  | 
 | ||
|  |         if os.path.isdir(dirpath): | ||
|  |             for file in os.listdir(dirpath): | ||
|  |                 os.remove(os.path.join(dirpath + "/" + file)) | ||
|  | 
 | ||
|  |         return {'FINISHED'} | ||
|  | 
 | ||
|  | class TLM_MergeAdjacentActors(bpy.types.Operator):  | ||
|  |     bl_idname = "tlm.merge_adjacent_actors" | ||
|  |     bl_label = "Merge adjacent actors" | ||
|  |     bl_description = "Merges the adjacent faces/vertices of selected objects" | ||
|  |     bl_options = {'REGISTER', 'UNDO'} | ||
|  | 
 | ||
|  |     def execute(self, context): | ||
|  | 
 | ||
|  |         scene = context.scene | ||
|  | 
 | ||
|  |         return {'FINISHED'} | ||
|  | 
 | ||
|  | class TLM_PrepareUVMaps(bpy.types.Operator):  | ||
|  |     bl_idname = "tlm.prepare_uvmaps" | ||
|  |     bl_label = "Prepare UV maps" | ||
|  |     bl_description = "Prepare UV lightmaps for selected objects" | ||
|  |     bl_options = {'REGISTER', 'UNDO'} | ||
|  | 
 | ||
|  |     def execute(self, context): | ||
|  | 
 | ||
|  |         scene = context.scene | ||
|  | 
 | ||
|  |         return {'FINISHED'} | ||
|  | 
 | ||
|  | class TLM_LoadLightmaps(bpy.types.Operator):  | ||
|  |     bl_idname = "tlm.load_lightmaps" | ||
|  |     bl_label = "Load Lightmaps" | ||
|  |     bl_description = "Load lightmaps from selected folder" | ||
|  |     bl_options = {'REGISTER', 'UNDO'} | ||
|  | 
 | ||
|  |     def execute(self, context): | ||
|  | 
 | ||
|  |         scene = context.scene | ||
|  | 
 | ||
|  |         utility.transfer_load() | ||
|  | 
 | ||
|  |         print("Transfer finished") | ||
|  | 
 | ||
|  |         build.finish_assemble(self, 1, 1) | ||
|  | 
 | ||
|  |         return {'FINISHED'} | ||
|  | 
 | ||
|  | class TLM_ToggleTexelDensity(bpy.types.Operator):  | ||
|  |     bl_idname = "tlm.toggle_texel_density" | ||
|  |     bl_label = "Toggle Texel Density" | ||
|  |     bl_description = "Toggle visualize lightmap texel density for selected objects" | ||
|  |     bl_options = {'REGISTER', 'UNDO'} | ||
|  | 
 | ||
|  |     def execute(self, context): | ||
|  | 
 | ||
|  |         scene = context.scene | ||
|  | 
 | ||
|  |         for obj in bpy.context.selected_objects: | ||
|  |             if obj.type == "MESH": | ||
|  |                 uv_layers = obj.data.uv_layers | ||
|  | 
 | ||
|  |                 #if the object has a td_vis in the uv maps, toggle off | ||
|  |                 #else toggle on | ||
|  | 
 | ||
|  |                 if obj.TLM_ObjectProperties.tlm_use_default_channel: | ||
|  | 
 | ||
|  |                     for i in range(0, len(uv_layers)): | ||
|  |                         if uv_layers[i].name == 'UVMap_Lightmap': | ||
|  |                             uv_layers.active_index = i | ||
|  |                             break | ||
|  |                 else: | ||
|  | 
 | ||
|  |                     for i in range(0, len(uv_layers)): | ||
|  |                         if uv_layers[i].name == obj.TLM_ObjectProperties.tlm_uv_channel: | ||
|  |                             uv_layers.active_index = i | ||
|  |                             break | ||
|  | 
 | ||
|  |                 #filepath = r"C:\path\to\image.png" | ||
|  | 
 | ||
|  |                 #img = bpy.data.images.load(filepath) | ||
|  | 
 | ||
|  |                 for area in bpy.context.screen.areas: | ||
|  |                     if area.type == 'VIEW_3D': | ||
|  |                         space_data = area.spaces.active | ||
|  |                         bpy.ops.screen.area_dupli('INVOKE_DEFAULT') | ||
|  |                         new_window = context.window_manager.windows[-1] | ||
|  | 
 | ||
|  |                         area = new_window.screen.areas[-1] | ||
|  |                         area.type = 'VIEW_3D' | ||
|  |                         #bg = space_data.background_images.new() | ||
|  |                         print(bpy.context.object) | ||
|  |                         bpy.ops.object.bake_td_uv_to_vc() | ||
|  | 
 | ||
|  |                         #bg.image = img | ||
|  |                         break | ||
|  | 
 | ||
|  |                  | ||
|  |                 #set active uv_layer to  | ||
|  |                  | ||
|  | 
 | ||
|  |         print("TLM_Viz_Toggle") | ||
|  | 
 | ||
|  |         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 | ||
|  | 
 | ||
|  | def TLM_HalfResolution(): | ||
|  |     pass | ||
|  | 
 | ||
|  | def TLM_DivideLMGroups(): | ||
|  |     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'} |