diff --git a/README.md b/README.md index 4198f0f..1a4f323 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,15 @@ # Blender-BakeLab2 ![Thumbnail](bakelab_thumbnail_text_logo_small.jpg) BakeLab - A blender addon for baking images.
-Compatible with Blender 2.81 or higher.
-For blender version 2.79 go to [here](https://github.com/Shahzod114/Bakelab-Blender-addon) +Compatible with Blender 4.0.0/5.0.0 or higher.
+For Blender version 2.79, go to [here](https://github.com/Shahzod114/Bakelab-Blender-addon) Main Features: -* Automatically create images, setup materials, bake objects and save/pack images in one click; +* Automatically create images, setup materials, bake objects, and save/pack images in one click; * Automatically generating materials; * Anti-Aliased baking; * Baking cycles displacement to real geometry; -* Bake any PBR attributes of your material by its name (Metallic, Roughness, Specular and etc); +* Bake any PBR attributes of your material by its name (Metallic, Roughness, Specular etc.); * Adaptive image size by object's surface size; * Unwrap and Bake Multiple Objects into one image; diff --git a/__init__.py b/__init__.py index 3b8ceab..89d343a 100644 --- a/__init__.py +++ b/__init__.py @@ -1,22 +1,9 @@ -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTIBILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - bl_info = { "name" : "BakeLab", "author" : "Shahzod Boyxonov (specoolar@gmail.com)", "description" : "Bake textures easily", - "blender" : (2, 81, 0), - "version" : (2, 0, 1), + "blender" : (4, 0, 0), + "version" : (2, 0, 2), "location" : "View3D > Properties > BakeLab", "category" : "Baking" } @@ -40,8 +27,8 @@ import bpy from bpy.types import ( - Operator, - PropertyGroup, + Operator, + PropertyGroup, Panel ) from bpy.props import ( @@ -61,10 +48,6 @@ def updateAdaptiveImageMinSize(self, context): def updateAdaptiveImageMaxSize(self, context): self.image_max_size = max(self.image_min_size, self.image_max_size) -def updateSavePath(self, context): - if bpy.data.is_saved: - self.save_path = bpy.path.abspath(self.save_path) - class BakeLabProperties(PropertyGroup): bake_state: EnumProperty( items = ( @@ -122,7 +105,7 @@ class BakeLabProperties(PropertyGroup): update=updateAdaptiveImageMinSize ) round_adaptive_image : BoolProperty( - name = 'Round to power of two', + name = 'Round to power of two', default = True ) anti_alias : IntProperty( @@ -162,7 +145,7 @@ class BakeLabProperties(PropertyGroup): name="Create folder", description="Automatically creates a folder named after the object(s)", default = True - ) + ) folder_name : StringProperty( name = 'Folder name', description = 'Name of the folder', @@ -172,12 +155,11 @@ class BakeLabProperties(PropertyGroup): default=expanduser("~"), name="Folder", subtype="DIR_PATH", - update=updateSavePath ) show_bake_settings : BoolProperty(name = '', default = False) show_map_settings : BoolProperty(name = '', default = False) show_file_settings : BoolProperty(name = '', default = False) - + apply_only_selected : BoolProperty( name = 'Apply only to Selected', description = 'Apply only to selected objects', @@ -188,7 +170,6 @@ class BakeLabProperties(PropertyGroup): description = 'Make data single user', default = True ) - # Display baking_obj_count : IntProperty( name = 'Baking object count', default = 0 @@ -224,7 +205,7 @@ class BakeLabProperties(PropertyGroup): classes = ( BakeLabProperties, - + bakelab_bake.Baker, bakelab_uv.Unwrapper, bakelab_uv.ClearUV, @@ -246,7 +227,7 @@ class BakeLabProperties(PropertyGroup): def register(): for cls in classes: bpy.utils.register_class(cls) - + bpy.types.Scene.BakeLabProps = PointerProperty(type = BakeLabProperties) bpy.types.Scene.BakeLabMaps = CollectionProperty(type = bakelab_map.BakeLabMap) bpy.types.Scene.BakeLab_Data = CollectionProperty(type = bakelab_baked_data.BakeLab_BakedData) @@ -255,11 +236,11 @@ def register(): def unregister(): for cls in classes: bpy.utils.unregister_class(cls) - + del bpy.types.Scene.BakeLabProps del bpy.types.Scene.BakeLabMaps del bpy.types.Scene.BakeLab_Data del bpy.types.Scene.BakeLabMapIndex if __name__ == "__main__": - register() + register() \ No newline at end of file diff --git a/bakelab_bake.py b/bakelab_bake.py index 88cd478..96c5eea 100644 --- a/bakelab_bake.py +++ b/bakelab_bake.py @@ -211,7 +211,94 @@ def copy_node(self, dst_nodes, node): if dst_input is not None: if hasattr(src_input, 'default_value') and \ hasattr(dst_input, 'default_value'): - dst_input.default_value = src_input.default_value + + try: + src_val = src_input.default_value + dst_val = dst_input.default_value + + print( + "COPY:", + node.name, + src_input.name, + src_val, + "->", + dst_input.name, + dst_val + ) + + if "Vector" in dst_input.bl_idname: + try: + value = tuple(src_val[:3]) + print("ASSIGN:", dst_input.name, dst_input.bl_idname, value) + dst_input.default_value = value + except Exception as e: + print("FAILED:", dst_input.name, dst_input.bl_idname, value, e) + raise + else: + try: + if hasattr(dst_input.default_value, "__len__"): + dst_len = len(dst_input.default_value) + + if hasattr(src_val, "__len__"): + if len(src_val) > dst_len: + try: + value = src_val[:dst_len] + print("ASSIGN:", dst_input.name, dst_input.bl_idname, value) + dst_input.default_value = value + except Exception as e: + print("FAILED:", dst_input.name, dst_input.bl_idname, value, e) + raise + elif len(src_val) < dst_len: + try: + value = tuple(src_val) + tuple([0.0] * (dst_len - len(src_val))) + print("ASSIGN:", dst_input.name, dst_input.bl_idname, value) + dst_input.default_value = value + except Exception as e: + print("FAILED:", dst_input.name, dst_input.bl_idname, value, e) + raise + print( + "DEBUG:", + dst_input.name, + dst_input.bl_idname, + src_val + ) + else: + try: + value = src_val + print("ASSIGN:", dst_input.name, dst_input.bl_idname, value) + dst_input.default_value = value + except Exception as e: + print("FAILED:", dst_input.name, dst_input.bl_idname, value, e) + raise + else: + try: + value = src_val + print("ASSIGN:", dst_input.name, dst_input.bl_idname, value) + dst_input.default_value = value + except Exception as e: + print("FAILED:", dst_input.name, dst_input.bl_idname, value, e) + raise + else: + try: + value = src_val + print("ASSIGN:", dst_input.name, dst_input.bl_idname, value) + dst_input.default_value = value + except Exception as e: + print("FAILED:", dst_input.name, dst_input.bl_idname, value, e) + raise + except: + pass + + except Exception as e: + print( + "FAILED:", + node.name, + src_input.name, + src_val, + "->", + dst_input.name, + e + ) return new_node def find_node(self, nodes, type): @@ -251,18 +338,233 @@ def extract_nodes_rc( from_node = link.from_node if from_node == gr_in: - ng_input = self.get_socket(n_group.inputs, link.from_socket.identifier) + ng_input = self.get_socket( + n_group.inputs, + link.from_socket.identifier + ) + if ng_input is None: continue - dst_input.default_value = ng_input.default_value - for ng_link in ng_input.links: - links.new(ng_link.from_socket, dst_input) + + src_val = ng_input.default_value + + try: + dst_val = dst_input.default_value + + if hasattr(dst_val, "__len__") and not isinstance(dst_val, str): + try: + dst_len = len(dst_val) + except: + dst_len = 1 + + if "Vector" in dst_input.bl_idname: + dst_len = 3 + + elif "Color" in dst_input.bl_idname: + dst_len = 4 + + print( + "SRC:", src_input.name, + "DST:", dst_input.name, + "SRC_LEN:", len(src_val) if hasattr(src_val, "__len__") else 1, + "DST_LEN:", dst_len, + "DST_SOCKET:", dst_input.bl_idname + ) + + if hasattr(src_val, "__len__"): + src_len = len(src_val) + + if "Vector" in dst_input.bl_idname: + tmp = list(src_val[:3]) + while len(tmp) < 3: + tmp.append(0.0) + print( + "SOCKET:", + dst_input.name, + dst_input.bl_idname, + "LEN:", + len(tmp) if 'tmp' in locals() else 'scalar' + ) + try: + value = tuple(tmp[:dst_len]) + print("ASSIGN:", dst_input.name, dst_input.bl_idname, value) + dst_input.default_value = value + except Exception as e: + print("FAILED:", dst_input.name, dst_input.bl_idname, value, e) + raise + + elif "Color" in dst_input.bl_idname: + tmp = list(src_val[:4]) + + while len(tmp) < 4: + tmp.append(1.0) + + print( + "SOCKET:", + dst_input.name, + "TYPE:", + dst_input.bl_idname, + "DST_LEN:", + dst_len, + "VALUE_LEN:", + len(tmp) + ) + + try: + value = tuple(tmp[:4]) + print("ASSIGN:", dst_input.name, dst_input.bl_idname, value) + dst_input.default_value = value + except Exception as e: + print("FAILED:", dst_input.name, dst_input.bl_idname, value, e) + raise + elif src_len > dst_len: + if "Vector" in dst_input.bl_idname: + try: + value = tuple(src_val[:3]) + print("ASSIGN:", dst_input.name, dst_input.bl_idname, value) + dst_input.default_value = value + except Exception as e: + print("FAILED:", dst_input.name, dst_input.bl_idname, value, e) + raise + elif dst_input.bl_idname == "NodeSocketColor": + tmp = list(src_val[:4]) + while len(tmp) < 4: + tmp.append(1.0) + try: + value = tuple(tmp[:4]) + print("ASSIGN:", dst_input.name, dst_input.bl_idname, value) + dst_input.default_value = value + except Exception as e: + print("FAILED:", dst_input.name, dst_input.bl_idname, value, e) + raise + else: + try: + value = tuple(src_val[:dst_len]) + print("ASSIGN:", dst_input.name, dst_input.bl_idname, value) + dst_input.default_value = value + except Exception as e: + print("FAILED:", dst_input.name, dst_input.bl_idname, value, e) + raise + + elif src_len < dst_len: + tmp = list(src_val) + tmp.extend([src_val[-1]] * (dst_len - src_len)) + print( + "SOCKET:", + dst_input.name, + dst_input.bl_idname, + "LEN:", + len(tmp) if 'tmp' in locals() else 'scalar' + ) + try: + value = tuple(tmp[:dst_len]) + print("ASSIGN:", dst_input.name, dst_input.bl_idname, value) + dst_input.default_value = value + except Exception as e: + print("FAILED:", dst_input.name, dst_input.bl_idname, value, e) + raise + + else: + if "Vector" in dst_input.bl_idname: + try: + value = tuple(src_val[:3]) + print("ASSIGN:", dst_input.name, dst_input.bl_idname, value) + dst_input.default_value = value + except Exception as e: + print("FAILED:", dst_input.name, dst_input.bl_idname, value, e) + raise + + elif dst_input.bl_idname == "NodeSocketColor": + tmp = list(src_val[:4]) + while len(tmp) < 4: + tmp.append(1.0) + print( + "SOCKET:", + dst_input.name, + dst_input.bl_idname, + "LEN:", + len(tmp) if 'tmp' in locals() else 'scalar' + ) + try: + value = tuple(tmp[:dst_len]) + print("ASSIGN:", dst_input.name, dst_input.bl_idname, value) + dst_input.default_value = value + except Exception as e: + print("FAILED:", dst_input.name, dst_input.bl_idname, value, e) + raise + + else: + if "Vector" in dst_input.bl_idname: + try: + value = tuple(src_val[:3]) + print("ASSIGN:", dst_input.name, dst_input.bl_idname, value) + dst_input.default_value = value + except Exception as e: + print("FAILED:", dst_input.name, dst_input.bl_idname, value, e) + raise + elif dst_input.bl_idname == "NodeSocketColor": + tmp = list(src_val[:4]) + while len(tmp) < 4: + tmp.append(1.0) + try: + value = tuple(tmp[:4]) + print("ASSIGN:", dst_input.name, dst_input.bl_idname, value) + dst_input.default_value = value + except Exception as e: + print("FAILED:", dst_input.name, dst_input.bl_idname, value, e) + raise + else: + try: + value = tuple(src_val[:dst_len]) + print("ASSIGN:", dst_input.name, dst_input.bl_idname, value) + dst_input.default_value = value + except Exception as e: + print("FAILED:", dst_input.name, dst_input.bl_idname, value, e) + raise + else: + try: + value = tuple([src_val] * dst_len) + print("ASSIGN:", dst_input.name, dst_input.bl_idname, value) + dst_input.default_value = value + except Exception as e: + print("FAILED:", dst_input.name, dst_input.bl_idname, value, e) + raise + else: + if hasattr(src_val, "__len__"): + try: + value = float(src_val[0]) + print("ASSIGN:", dst_input.name, dst_input.bl_idname, value) + dst_input.default_value = value + except Exception as e: + print("FAILED:", dst_input.name, dst_input.bl_idname, value, e) + raise + else: + try: + value = float(src_val) + print("ASSIGN:", dst_input.name, dst_input.bl_idname, value) + dst_input.default_value = value + except Exception as e: + print("FAILED:", dst_input.name, dst_input.bl_idname, value, e) + raise + + except Exception as e: + print("ERROR SOCKET:", dst_input.name) + print("ERROR TYPE:", dst_input.bl_idname) + print("ERROR VALUE:", src_val) + print("ERROR:", e) + + raise + else: link_node = self.extract_nodes_rc( from_node, gr_in, gr_out, nodes, links, n_group, node_dict) + if link_node is not None: - link_output = self.get_socket(link_node.outputs, link.from_socket.identifier) + link_output = self.get_socket( + link_node.outputs, + link.from_socket.identifier) + if link_output is not None: links.new(link_output, dst_input) ### } diff --git a/bakelab_baked_data.py b/bakelab_baked_data.py index 78b8473..c10d8a5 100644 --- a/bakelab_baked_data.py +++ b/bakelab_baked_data.py @@ -20,9 +20,10 @@ class BakeObjData(PropertyGroup): type=bpy.types.Object ) class BakeMapData(PropertyGroup): - bake_map : PointerProperty( - type=bakelab_map.BakeLabMap - ) + map_type : StringProperty() + pass_name : StringProperty() + normal_space : StringProperty() + image : PointerProperty( type=bpy.types.Image ) @@ -42,8 +43,7 @@ def AddObj(self, obj): def AddMap(self, bake_map, image): item = self.map_list.add() - item.bake_map.type = bake_map.type - item.bake_map.pass_name = bake_map.pass_name - item.bake_map.normal_space = bake_map.normal_space - + item.map_type = bake_map.type + item.pass_name = bake_map.pass_name + item.normal_space = bake_map.normal_space item.image = image