2025-12-01

This commit is contained in:
2026-03-17 14:58:51 -06:00
parent 183e865f8b
commit 4b82b57113
6846 changed files with 954887 additions and 162606 deletions
@@ -0,0 +1,13 @@
def Diff(li1, li2):
return (list(set(li1) - set(li2)))
def Intersection(li1, li2):
set1 = set(li1)
set2 = set(li2)
return list(set.intersection(set1,set2))
def flatten(t):
return [item for sublist in t for item in sublist]
def remove_duplicate(l):
return list(dict.fromkeys(l))
@@ -0,0 +1,39 @@
import os
import bpy
class Node_Types:
image_texture = 'TEX_IMAGE'
pbr_node = 'BSDF_PRINCIPLED'
mapping = 'MAPPING'
normal_map = 'NORMAL_MAP'
bump_map = 'BUMP'
material_output = 'OUTPUT_MATERIAL'
class Shader_Node_Types:
emission = "ShaderNodeEmission"
image_texture = "ShaderNodeTexImage"
mapping = "ShaderNodeMapping"
normal = "ShaderNodeNormalMap"
ao = "ShaderNodeAmbientOcclusion"
uv = "ShaderNodeUVMap"
comp_image_node = 'CompositorNodeImage'
mix ="ShaderNodeMixRGB"
class Bake_Passes:
pbr = ["EMISSION"]
lightmap = ["NOISY", "NRM", "COLOR"]
ao = ["AO","COLOR"]
class Material_Suffix:
bake_type_mat_suffix = {
"pbr" : "_Bake",
"ao" : "_AO",
"lightmap" : "_AO"
}
class Path_List:
def get_project_dir():
return os.path.dirname(bpy.data.filepath)
def get_textures_dir():
return os.path.join(os.path.dirname(bpy.data.filepath),'textures','GLBTexTool')
@@ -0,0 +1,91 @@
import bpy
from bpy.app.handlers import persistent
def update_pbr_button(self,context):
self["lightmap_bake"] = False
self["ao_bake"] = False
def update_lightmap_button(self,context):
self["pbr_bake"] = False
self["ao_bake"] = False
update_active_element_in_bake_list()
def update_ao_button(self,context):
self["lightmap_bake"] = False
self["pbr_bake"] = False
update_active_element_in_bake_list()
# ----------------------- UPDATE BAKE IMAGE NAME / ENUM--------------------#
last_selection = []
@persistent
def update_on_selection(scene):
C = bpy.context
global last_selection
object = getattr(C,"object",None)
if object is None:
return
if C.selected_objects != last_selection:
last_selection = C.selected_objects
update_active_element_in_bake_list()
def update_bake_list(bake_settings,context):
bake_textures_set = set()
for obj in bpy.data.objects:
if bake_settings.lightmap_bake:
if obj.get("lightmap_name"):
bake_textures_set.add((obj.lightmap_name, obj.lightmap_name, "Baked Texture Name"))
if bake_settings.ao_bake:
if obj.get("ao_map_name"):
bake_textures_set.add((obj.ao_map_name, obj.ao_map_name, "Baked Texture Name"))
if len(bake_textures_set) == 0:
bake_textures_set.add(("-- Baking Groups --","-- Baking Groups --","No Lightmap baked yet"))
return list(bake_textures_set)
def update_active_element_in_bake_list():
C = bpy.context
active_object = C.active_object
bake_settings = C.scene.bake_settings
new_bake_image_name = ""
if bake_settings.lightmap_bake:
new_bake_image_name = active_object.get("lightmap_name")
if new_bake_image_name is None:
new_bake_image_name = "Lightmap " + active_object.name
if bake_settings.ao_bake:
new_bake_image_name = active_object.get("ao_map_name")
if new_bake_image_name is None:
new_bake_image_name = "AO " + active_object.name
enum_items = bake_settings.get_baked_lightmaps()
keys = [key[0] for key in enum_items]
if new_bake_image_name in keys:
bake_settings.bake_image_name = new_bake_image_name
bake_settings.baking_groups = new_bake_image_name
else:
if active_object.type == "MESH":
bake_settings.bake_image_name = new_bake_image_name
def headline(layout,*valueList):
box = layout.box()
row = box.row()
split = row.split()
for pair in valueList:
split = split.split(factor=pair[0])
split.label(text=pair[1])
@persistent
def init_values(self,context):
bpy.context.scene.world.light_settings.distance = 1
@@ -0,0 +1,107 @@
import bpy
import os
from . import node_functions
from . import constants
from bpy.app.handlers import persistent
@persistent
def save_images(self,context):
images = bpy.data.images
for img in images:
if img.is_dirty:
print(img.name)
save_image(img) # img.save()
def get_all_images_in_ui_list():
images_in_scene = bpy.data.images
image_name_list = bpy.types.GTT_TEX_UL_List.image_name_list
images_found = []
if len(image_name_list) > 0:
images_found = [img for img in images_in_scene for name_list_entry in image_name_list if img.name == name_list_entry]
return images_found
def save_image(image,save_internally=False):
if save_internally:
image.pack()
else:
filePath = bpy.data.filepath
path = os.path.dirname(filePath)
if not os.path.exists(path + "/textures"):
os.mkdir(path + "/textures")
if not os.path.exists(path + "/textures/GLBTexTool"):
os.mkdir(path + "/textures/GLBTexTool")
if not os.path.exists(path + "/textures/GLBTexTool/" + str(image.size[0])):
os.mkdir(path + "/textures/GLBTexTool/" + str(image.size[0]))
# file format
image.file_format = bpy.context.scene.img_file_format
# change path
savepath = path + "\\textures\\GLBTexTool\\" + str(image.size[0]) + "\\" + image.name + "." + image.file_format
# image.use_fake_user = True
image.filepath_raw = savepath
image.save()
def create_image(image_name, image_size):
D = bpy.data
# find image
image = D.images.get(image_name)
if image:
old_size = list(image.size)
new_size = list(image_size)
if old_size != new_size:
D.images.remove(image)
image = None
# image = D.images.get(image_name)
if image is None:
image = D.images.new(
image_name, width=image_size[0], height=image_size[1])
image.name = image_name
return image
def get_file_size(filepath):
size = "Unpack Files"
try:
path = bpy.path.abspath(filepath)
size = os.path.getsize(path)
size /= 1024
except:
return ("Unpack")
# print("error getting file path for " + filepath)
return (size)
def scale_image(image, new_size):
if (image.org_filepath != ''):
image.filepath = image.org_filepath
image.org_filepath = image.filepath
if new_size[0] > image.size[0] or new_size[1] > image.size[1]:
new_size[0] = image.size[0]
new_size[1] = image.size[1]
# set image back to original if size is 0, else scale it
if new_size[0] == 0:
image.filepath_raw = image.org_filepath
else:
image.scale(new_size[0], new_size[1])
save_image(image)
@@ -0,0 +1,40 @@
import bpy
def get_all_visible_materials():
objects=[ob for ob in bpy.context.view_layer.objects if ob.visible_get()]
slot_array = [object.material_slots for object in objects]
vis_mat = set()
for slots in slot_array:
for slot in slots:
vis_mat.add(slot.material)
# to remove None values in list
vis_mat = list(filter(None, vis_mat))
return vis_mat
def get_selected_materials(selected_objects):
selected_materials = set()
slots_array = [obj.material_slots for obj in selected_objects]
for slots in slots_array:
for slot in slots:
selected_materials.add(slot.material)
return selected_materials
def clean_empty_materials():
for obj in bpy.data.objects:
for slot in obj.material_slots:
mat = slot.material
if mat is None:
print("Removed Empty Materials from " + obj.name)
bpy.ops.object.select_all(action='DESELECT')
obj.select_set(True)
bpy.ops.object.material_slot_remove()
def clean_no_user_materials():
for material in bpy.data.materials:
if not material.users:
bpy.data.materials.remove(material)
def use_nodes():
for material in bpy.data.materials:
if not material.use_nodes:
material.use_nodes = True
@@ -0,0 +1,390 @@
import bpy.ops as O
import bpy
import os
from .. Functions import constants
import mathutils
# -----------------------COMPOSITING--------------------#
def blur_bake_image(noisy_image,color_image):
# switch on nodes and get reference
if not bpy.context.scene.use_nodes:
bpy.context.scene.use_nodes = True
tree = bpy.context.scene.node_tree
# add cam if not in scene
cam = bpy.context.scene.camera
if not cam:
bpy.ops.object.camera_add()
# bake image
image_node = tree.nodes.new(type='CompositorNodeImage')
image_node.image = noisy_image
image_node.location = 0, 0
# color image
color_image_node = tree.nodes.new(type='CompositorNodeImage')
color_image_node.image = color_image
color_image_node.location = 0, 300
# create blur node
blur_node = tree.nodes.new(type='CompositorNodeBilateralblur')
blur_node.location = 300, 0
# create output node
comp_node = tree.nodes.new('CompositorNodeComposite')
comp_node.location = 600, 0
# link nodes
links = tree.links
links.new(image_node.outputs[0], blur_node.inputs[0])
links.new(color_image_node.outputs[0], blur_node.inputs[1])
links.new(blur_node.outputs[0], comp_node.inputs[0])
# set output resolution to image res
bpy.context.scene.render.resolution_x = noisy_image.size[0]
bpy.context.scene.render.resolution_y = noisy_image.size[1]
# set output path
scene = bpy.context.scene
outputImagePath = constants.Path_List.get_textures_dir()
# set image format and quality
scene.render.image_settings.file_format = bpy.context.scene.img_file_format
scene.render.image_settings.quality = 100
scene.render.filepath = os.path.join(outputImagePath,noisy_image.name + "_Denoise_AO")
bpy.ops.render.render(write_still=True)
if bpy.context.scene.img_file_format == 'JPEG':
file_extention = '.jpg'
elif bpy.context.scene.img_file_format == 'PNG':
file_extention = '.png'
elif bpy.context.scene.img_file_format == 'HDR':
file_extention = '.hdr'
# cleanup
comp_nodes = [image_node,color_image_node,blur_node,comp_node]
for node in comp_nodes:
tree.nodes.remove(node)
return scene.render.filepath + file_extention
def comp_ai_denoise(noisy_image, nrm_image, color_image):
# switch on nodes and get reference
if not bpy.context.scene.use_nodes:
bpy.context.scene.use_nodes = True
tree = bpy.context.scene.node_tree
# add cam if not in scene
cam = bpy.context.scene.camera
if not cam:
bpy.ops.object.camera_add()
# bake image
image_node = tree.nodes.new(type='CompositorNodeImage')
image_node.image = noisy_image
image_node.location = 0, 0
# nrm image
nrm_image_node = tree.nodes.new(type='CompositorNodeImage')
nrm_image_node.image = nrm_image
nrm_image_node.location = 0, 300
# color image
color_image_node = tree.nodes.new(type='CompositorNodeImage')
color_image_node.image = color_image
color_image_node.location = 0, 600
# create denoise node
denoise_node = tree.nodes.new(type='CompositorNodeDenoise')
denoise_node.location = 300, 0
# create output node
comp_node = tree.nodes.new('CompositorNodeComposite')
comp_node.location = 600, 0
# link nodes
links = tree.links
links.new(image_node.outputs[0], denoise_node.inputs[0])
links.new(nrm_image_node.outputs[0], denoise_node.inputs[1])
links.new(color_image_node.outputs[0], denoise_node.inputs[2])
links.new(denoise_node.outputs[0], comp_node.inputs[0])
# set output resolution to image res
bpy.context.scene.render.resolution_x = noisy_image.size[0]
bpy.context.scene.render.resolution_y = noisy_image.size[1]
# set output path
scene = bpy.context.scene
outputImagePath = constants.Path_List.get_textures_dir()
# set image format and quality
scene.render.image_settings.file_format = bpy.context.scene.img_file_format
scene.render.image_settings.quality = 100
scene.render.filepath = os.path.join(outputImagePath,noisy_image.name + "_Denoise_LM")
print("Starting Denoise")
bpy.ops.render.render(write_still=True)
if bpy.context.scene.img_file_format == 'JPEG':
file_extention = '.jpg'
elif bpy.context.scene.img_file_format == 'PNG':
file_extention = '.png'
elif bpy.context.scene.img_file_format == 'HDR':
file_extention = '.hdr'
# cleanup
comp_nodes = [image_node, nrm_image_node,color_image_node, denoise_node, comp_node]
for node in comp_nodes:
tree.nodes.remove(node)
return scene.render.filepath + file_extention
# -----------------------CHECKING --------------------#
def check_pbr(self, material):
check_ok = True
if material is None:
return False
if material.node_tree is None:
return False
if material.node_tree.nodes is None:
return False
# get pbr shader
nodes = material.node_tree.nodes
pbr_node_type = constants.Node_Types.pbr_node
pbr_nodes = get_nodes_by_type(nodes, pbr_node_type)
# check only one pbr node
if len(pbr_nodes) == 0:
self.report({'INFO'}, 'No PBR Shader Found')
check_ok = False
if len(pbr_nodes) > 1:
self.report(
{'INFO'}, 'More than one PBR Node found ! Clean before Baking.')
check_ok = False
return check_ok
def check_is_org_material(self, material):
check_ok = True
if "_Bake" in material.name:
self.report({'INFO'}, 'Change back to org. Material')
check_ok = False
return check_ok
# -----------------------NODES --------------------#
def get_pbr_inputs(pbr_node):
base_color_input = pbr_node.inputs["Base Color"]
metallic_input = pbr_node.inputs["Metallic"]
specular_input = pbr_node.inputs["Specular Tint"]
roughness_input = pbr_node.inputs["Roughness"]
normal_input = pbr_node.inputs["Normal"]
emission_input = pbr_node.inputs["Emission Color"]
alpha_input = pbr_node.inputs["Alpha"]
pbr_inputs = {"base_color_input": base_color_input, "metallic_input": metallic_input,
"specular_input": specular_input, "roughness_input": roughness_input,
"normal_input": normal_input, "emission_input": emission_input,"alpha_input":alpha_input}
return pbr_inputs
def get_nodes_by_type(nodes, node_type):
nodes_found = [n for n in nodes if n.type == node_type]
return nodes_found
def get_node_by_type_recusivly(material, note_to_start, node_type, del_nodes_inbetween=False):
nodes = material.node_tree.nodes
if note_to_start.type == node_type:
return note_to_start
for input in note_to_start.inputs:
for link in input.links:
current_node = link.from_node
if (del_nodes_inbetween and note_to_start.type != constants.Node_Types.normal_map and note_to_start.type != constants.Node_Types.bump_map):
nodes.remove(note_to_start)
return get_node_by_type_recusivly(material, current_node, node_type, del_nodes_inbetween)
def get_node_by_name_recusivly(node, idname):
if node.bl_idname == idname:
return node
for input in node.inputs:
for link in input.links:
current_node = link.from_node
return get_node_by_name_recusivly(current_node, idname)
def get_pbr_node(material):
nodes = material.node_tree.nodes
pbr_node = get_nodes_by_type(nodes, constants.Node_Types.pbr_node)
if len(pbr_node) > 0:
return pbr_node[0]
def make_link(material, socket1, socket2):
links = material.node_tree.links
links.new(socket1, socket2)
def remove_link(material, socket1, socket2):
node_tree = material.node_tree
links = node_tree.links
for l in socket1.links:
if l.to_socket == socket2:
links.remove(l)
def add_in_gamme_node(material, pbrInput):
nodeToPrincipledOutput = pbrInput.links[0].from_socket
gammaNode = material.node_tree.nodes.new("ShaderNodeGamma")
gammaNode.inputs[1].default_value = 2.2
gammaNode.name = "Gamma Bake"
# link in gamma
make_link(material, nodeToPrincipledOutput, gammaNode.inputs["Color"])
make_link(material, gammaNode.outputs["Color"], pbrInput)
def remove_gamma_node(material, pbrInput):
nodes = material.node_tree.nodes
gammaNode = nodes.get("Gamma Bake")
nodeToPrincipledOutput = gammaNode.inputs[0].links[0].from_socket
make_link(material, nodeToPrincipledOutput, pbrInput)
material.node_tree.nodes.remove(gammaNode)
def emission_setup(material, node_output):
nodes = material.node_tree.nodes
emission_node = add_node(
material, constants.Shader_Node_Types.emission, "Emission Bake")
# link emission to whatever goes into current pbrInput
emission_input = emission_node.inputs[0]
make_link(material, node_output, emission_input)
# link emission to materialOutput
surface_input = get_nodes_by_type(nodes,constants.Node_Types.material_output)[0].inputs[0]
emission_output = emission_node.outputs[0]
make_link(material, emission_output, surface_input)
def link_pbr_to_output(material, pbr_node):
nodes = material.node_tree.nodes
surface_input = get_nodes_by_type(nodes,constants.Node_Types.material_output)[0].inputs[0]
make_link(material, pbr_node.outputs[0], surface_input)
def reconnect_PBR(material, pbrNode):
nodes = material.node_tree.nodes
pbr_output = pbrNode.outputs[0]
surface_input = get_nodes_by_type(
nodes, constants.Node_Types.material_output)[0].inputs[0]
make_link(material, pbr_output, surface_input)
def mute_all_texture_mappings(material, do_mute):
nodes = material.node_tree.nodes
for node in nodes:
if node.bl_idname == "ShaderNodeMapping":
node.mute = do_mute
def add_node(material, shader_node_type, node_name):
nodes = material.node_tree.nodes
new_node = nodes.get(node_name)
if new_node is None:
new_node = nodes.new(shader_node_type)
new_node.name = node_name
new_node.label = node_name
return new_node
def remove_node(material, node_name):
nodes = material.node_tree.nodes
node = nodes.get(node_name)
if node is not None:
nodes.remove(node)
def remove_reconnect_node(material, node_name):
nodes = material.node_tree.nodes
node = nodes.get(node_name)
input_node = node.inputs["Color1"].links[0].from_node
output_node = node.outputs["Color"].links[0].to_node
if node is not None:
make_link(material,input_node.outputs["Color"],output_node.inputs["Base Color"])
nodes.remove(node)
def remove_unused_nodes(material):
nodes = material.node_tree.nodes
all_nodes = set(nodes)
connected_nodes = set()
material_output = nodes.get("Material Output")
get_all_connected_nodes(material_output, connected_nodes)
unconnected_nodes = all_nodes - connected_nodes
for node in unconnected_nodes:
nodes.remove(node)
def remove_double_linking(material,texture_node):
color_output = texture_node.outputs["Color"]
links_count = len(color_output.links)
org_vector_input = texture_node.inputs["Vector"]
position_y = texture_node.location.y
if links_count > 1:
for link in color_output.links:
new_texture_node = add_node(material,constants.Shader_Node_Types.image_texture,texture_node.name + "_Copy" + str(link))
new_texture_node.image = texture_node.image
new_texture_node.location = texture_node.location
position_y -= 250
new_texture_node.location.y = position_y
# relink tex node output
make_link(material,new_texture_node.outputs["Color"],link.to_socket)
# remap texture mapping
if len(org_vector_input.links) != 0:
new_vector_input = new_texture_node.inputs["Vector"]
tex_transform_socket = org_vector_input.links[0].from_socket
make_link(material,tex_transform_socket,new_vector_input)
def get_all_connected_nodes(node, connected_nodes):
connected_nodes.add(node)
for input in node.inputs:
for link in input.links:
current_node = link.from_node
get_all_connected_nodes(current_node, connected_nodes)
@@ -0,0 +1,36 @@
import bpy
from .. Functions import node_functions
def apply_transform_on_linked():
bpy.ops.object.select_linked(type='OBDATA')
bpy.ops.object.make_single_user(type='SELECTED_OBJECTS', object=True, obdata=True, material=False, animation=False)
bpy.ops.object.transform_apply(location=False, rotation=False, scale=True)
bpy.ops.object.make_links_data(type='OBDATA')
def select_object(self, obj):
C = bpy.context
O = bpy.ops
try:
O.object.select_all(action='DESELECT')
C.view_layer.objects.active = obj
obj.select_set(True)
except:
self.report({'INFO'}, "Object not in View Layer")
def select_obj_by_mat(mat,self=None):
D = bpy.data
result = []
for obj in D.objects:
if obj.type == "MESH":
object_materials = [slot.material for slot in obj.material_slots]
if mat in object_materials:
result.append(obj)
if (self):
select_object(self, obj)
return result
# TODO - save objects in array, unlink objects, apply scale and link them back
def apply_scale_on_multiuser():
O = bpy.ops
O.object.transform_apply(location=False, rotation=False, scale=True)
@@ -0,0 +1,200 @@
import bpy
from bpy import context
from . import node_functions
from . import material_functions
from . import object_functions
from . import constants
from . import basic_functions
import mathutils
def update_selected_image(self, context):
sel_texture = bpy.data.images[self.texture_index]
show_image_in_image_editor(sel_texture)
def show_image_in_image_editor(image):
for area in bpy.context.screen.areas:
if area.type == 'IMAGE_EDITOR':
area.spaces.active.image = image
def switch_baked_material(show_bake_material,affect):
current_bake_type = bpy.context.scene.bake_settings.get_current_bake_type()
material_name_suffix = constants.Material_Suffix.bake_type_mat_suffix[current_bake_type]
# on what object to work
if affect == 'active':
objects = [bpy.context.active_object]
elif affect == 'selected':
objects = bpy.context.selected_editable_objects
elif affect == 'visible':
objects = [ob for ob in bpy.context.view_layer.objects if ob.visible_get()]
elif affect == 'scene':
objects = bpy.context.scene.objects
elif affect == 'linked':
objects = []
selected_objects = bpy.context.selected_editable_objects
selected_materials = material_functions.get_selected_materials(selected_objects)
for material in selected_materials:
objs = object_functions.select_obj_by_mat(material)
objects.append(objs)
objects = basic_functions.flatten(objects)
objects = basic_functions.remove_duplicate(objects)
all_mats = bpy.data.materials
baked_mats = [mat for mat in all_mats if material_name_suffix in mat.name]
for obj in objects:
# if current_bake_type != "pbr":
# baked_ao_flag = getattr(obj,"ao_map_name") != '' or getattr(obj,"lightmap_name") != ''
# if not baked_ao_flag:
# continue
for slot in obj.material_slots:
if show_bake_material:
for baked_mat in baked_mats:
try:
if baked_mat.name == slot.material.name + material_name_suffix + obj.bake_version:
slot.material = baked_mat
except:
pass
else:
if (material_name_suffix in slot.material.name):
bake_material = slot.material
index = bake_material.name.find(material_name_suffix)
org_mat = all_mats.get(bake_material.name[0:index])
if org_mat is not None:
slot.material = org_mat
def preview_bake_texture(self,context):
context = bpy.context
bake_settings = context.scene.bake_settings
preview_bake_texture = context.scene.texture_settings.preview_bake_texture
vis_mats = material_functions.get_all_visible_materials()
for mat in vis_mats:
if not mat.node_tree:
continue
nodes = mat.node_tree.nodes
bake_texture_node = None
if bake_settings.lightmap_bake:
bake_texture_node = nodes.get(bake_settings.texture_node_lightmap)
elif bake_settings.ao_bake:
bake_texture_node = nodes.get(bake_settings.texture_node_ao)
if bake_texture_node is not None:
if preview_bake_texture:
node_functions.emission_setup(mat, bake_texture_node.outputs["Color"])
else:
pbr_node = node_functions.get_nodes_by_type(nodes, constants.Node_Types.pbr_node)
if len(pbr_node) == 0:
return
pbr_node = pbr_node[0]
node_functions.remove_node(mat, "Emission Bake")
node_functions.reconnect_PBR(mat, pbr_node)
def preview_lightmap(self, context):
preview_lightmap = context.scene.texture_settings.preview_lightmap
vis_mats = material_functions.get_all_visible_materials()
for material in vis_mats:
if not material.node_tree:
continue
nodes = material.node_tree.nodes
lightmap_node = nodes.get("Lightmap")
if lightmap_node is None:
continue
pbr_node = node_functions.get_pbr_node(material)
if pbr_node is None:
print("\n " + material.name + " has no PBR Node \n")
continue
base_color_input = node_functions.get_pbr_inputs(pbr_node)["base_color_input"]
emission_input = node_functions.get_pbr_inputs(pbr_node)["emission_input"]
lightmap_output = lightmap_node.outputs["Color"]
if preview_lightmap:
# add mix node
mix_node_name = "Mulitply Lightmap"
mix_node = node_functions.add_node(material,constants.Shader_Node_Types.mix, mix_node_name)
mix_node.blend_type = 'MULTIPLY'
mix_node.inputs[0].default_value = 1 # set factor to 1
pos_offset = mathutils.Vector((-200, 200))
mix_node.location = pbr_node.location + pos_offset
mix_node_input1 = mix_node.inputs["Color1"]
mix_node_input2 = mix_node.inputs["Color2"]
mix_node_output = mix_node.outputs["Color"]
# image texture in base color
if base_color_input.is_linked:
node_before_base_color = base_color_input.links[0].from_node
if not node_before_base_color.name == mix_node_name:
node_functions.make_link(material, node_before_base_color.outputs["Color"], mix_node_input1)
node_functions.make_link(material, lightmap_output, mix_node_input2)
node_functions.make_link(material, mix_node_output, base_color_input)
else :
mix_node_input1.default_value = base_color_input.default_value
node_functions.make_link(material, lightmap_output, mix_node_input2)
node_functions.make_link(material, mix_node_output, base_color_input)
node_functions.remove_link(material,lightmap_output,emission_input)
if not preview_lightmap:
# remove mix and reconnect base color
mix_node = nodes.get("Mulitply Lightmap")
if mix_node is not None:
color_input_connections = len(mix_node.inputs["Color1"].links)
if (color_input_connections == 0):
node_functions.remove_node(material,mix_node.name)
else:
node_functions.remove_reconnect_node(material,mix_node.name)
node_functions.link_pbr_to_output(material,pbr_node)
def lightmap_to_emission(self, context, connect):
vis_mats = material_functions.get_all_visible_materials()
for material in vis_mats:
if not material.node_tree:
continue
nodes = material.node_tree.nodes
pbr_node = node_functions.get_pbr_node(material)
lightmap_node = nodes.get("Lightmap")
if lightmap_node is None:
continue
emission_input = node_functions.get_pbr_inputs(pbr_node)["emission_input"]
lightmap_output = lightmap_node.outputs["Color"]
if connect:
node_functions.make_link(material, lightmap_output, emission_input)
else:
node_functions.remove_link(material,lightmap_output,emission_input)