From d02e72dd809747a3072f94a0efa77444ada63b93 Mon Sep 17 00:00:00 2001 From: Prodeath21 Date: Sun, 11 Jan 2026 01:00:55 +0100 Subject: [PATCH] Blender Addon 1.8.4 Compatible with Enfusion Tools 2025.09 --- .../_Release/L1960_Tools_1_8_4.zip | Bin 0 -> 44186 bytes .../L1960_Tools_1_8_4/AutoColorPalette.py | 333 ++++++ .../L1960_Tools_1_8_4/ColorPalette_01.csv | 1025 +++++++++++++++++ .../L1960_Tools_1_8_4/ColorPalette_01.png | Bin 0 -> 9972 bytes .../L1960_Tools_1_8_4/ColorPalette_02.csv | 1025 +++++++++++++++++ .../L1960_Tools_1_8_4/ColorPalette_02.png | Bin 0 -> 9295 bytes .../L1960_Tools_1_8_4/CubeProjection.py | 94 ++ .../_Source/L1960_Tools_1_8_4/Dekogon.py | 187 +++ .../_Source/L1960_Tools_1_8_4/Helper.py | 139 +++ .../L1960_Tools_1_8_4/MaterialToMask.py | 227 ++++ .../_Source/L1960_Tools_1_8_4/PrepareLods.py | 42 + .../_CreateColorPaletteMatrix.py | 30 + .../_Source/L1960_Tools_1_8_4/__init__.py | 219 ++++ 13 files changed, 3321 insertions(+) create mode 100644 Blender/L1960_Tools/_Release/L1960_Tools_1_8_4.zip create mode 100644 Blender/L1960_Tools/_Source/L1960_Tools_1_8_4/AutoColorPalette.py create mode 100644 Blender/L1960_Tools/_Source/L1960_Tools_1_8_4/ColorPalette_01.csv create mode 100644 Blender/L1960_Tools/_Source/L1960_Tools_1_8_4/ColorPalette_01.png create mode 100644 Blender/L1960_Tools/_Source/L1960_Tools_1_8_4/ColorPalette_02.csv create mode 100644 Blender/L1960_Tools/_Source/L1960_Tools_1_8_4/ColorPalette_02.png create mode 100644 Blender/L1960_Tools/_Source/L1960_Tools_1_8_4/CubeProjection.py create mode 100644 Blender/L1960_Tools/_Source/L1960_Tools_1_8_4/Dekogon.py create mode 100644 Blender/L1960_Tools/_Source/L1960_Tools_1_8_4/Helper.py create mode 100644 Blender/L1960_Tools/_Source/L1960_Tools_1_8_4/MaterialToMask.py create mode 100644 Blender/L1960_Tools/_Source/L1960_Tools_1_8_4/PrepareLods.py create mode 100644 Blender/L1960_Tools/_Source/L1960_Tools_1_8_4/_CreateColorPaletteMatrix.py create mode 100644 Blender/L1960_Tools/_Source/L1960_Tools_1_8_4/__init__.py diff --git a/Blender/L1960_Tools/_Release/L1960_Tools_1_8_4.zip b/Blender/L1960_Tools/_Release/L1960_Tools_1_8_4.zip new file mode 100644 index 0000000000000000000000000000000000000000..b08197245171db461b6f7d747934c8a6a10fde9a GIT binary patch literal 44186 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 NbN59NW)!}D`d>I3ZutNJ literal 0 HcmV?d00001 diff --git a/Blender/L1960_Tools/_Source/L1960_Tools_1_8_4/AutoColorPalette.py b/Blender/L1960_Tools/_Source/L1960_Tools_1_8_4/AutoColorPalette.py new file mode 100644 index 0000000..e9199f4 --- /dev/null +++ b/Blender/L1960_Tools/_Source/L1960_Tools_1_8_4/AutoColorPalette.py @@ -0,0 +1,333 @@ +import bpy +import math +import csv +import os +import json +from mathutils import Vector + +### GENRATE MLOD ### + +plugin_dir = bpy.utils.user_resource('SCRIPTS') +plugin_path = "addons\L1960Tools" +L1960_path = os.path.join(plugin_dir, plugin_path) + +colorpalettes = [ + json.dumps(["ColorPalette_01.png", "BF1BC94A0DE4398F"]), + json.dumps(["ColorPalette_02.png", "A95B2794A0EE8340"]) +] + +enum_palettes = [] +for palettes in colorpalettes: + file = json.loads(palettes)[0] + enum_palettes.append((palettes, file[:-4], "Select " + file[:-4] + " for MLOD")) + +class EnumColorPalettes(bpy.types.PropertyGroup): + mlod_enum_selection: bpy.props.EnumProperty(name="Color Palettes for MLOD", items = enum_palettes, description = "Choose a palette", default = 0) + +class MESH_OT_set_up_mlod(bpy.types.Operator): + """Set´s up a material to be used for MLOD´s""" + + bl_idname = "mesh.set_up_mlod" + bl_label = "Set´s up a material to be used for MLOD´s" + bl_options = {"REGISTER", "UNDO"} + + def execute(self, context): + + #Load Color Palettes + self.import_palettes_textures() + + #Selected Mesh + obj = bpy.context.active_object + + if obj not in bpy.context.selected_objects or obj.type != "MESH": + self.report({'WARNING'}, 'Select a Mesh to continue') + return {"CANCELLED"} + + arr_layers = obj.data.uv_layers + if not arr_layers.get("MLOD") or len(arr_layers) > 1: + for uv_layer in reversed(arr_layers): + arr_layers.remove(uv_layer) + arr_layers.new(name = 'MLOD') + + if not len(obj.data.materials) == 0: + obj.data.materials.clear() + + palette_enum_selection = json.loads(context.scene.color_palettes.mlod_enum_selection) + mlod_material_name = "MLOD_" + palette_enum_selection[0][:-4] + "_" + palette_enum_selection[1] + + if not bpy.data.materials.get(mlod_material_name): + material = bpy.data.materials.new(name=mlod_material_name) + material.use_nodes = True + bsdf_node = material.node_tree.nodes["Principled BSDF"] + texImage = material.node_tree.nodes.new('ShaderNodeTexImage') + texImage.image = bpy.data.images.get(palette_enum_selection[0]) + + material.node_tree.links.new(bsdf_node.inputs['Base Color'], texImage.outputs['Color']) + + obj.data.materials.append(bpy.data.materials.get(mlod_material_name)) + + self.report({'INFO'}, 'Mesh configured like MLOD') + return {"FINISHED"} + + def import_palettes_textures(self): + for image_name in colorpalettes: + image_name = json.loads(image_name)[0] + texture_name = image_name.split(".")[0] + if texture_name not in bpy.data.textures: + texture = bpy.data.textures.new(name=texture_name, type='IMAGE') + else: + texture = bpy.data.textures.get(texture_name) + if image_name not in bpy.data.images: + image = bpy.data.images.load(os.path.join(L1960_path, image_name)) + else: + image = bpy.data.images.get(image_name) + texture.image = image + +# texture_filepath = os.path.join(L1960_path, colorpalettes[1]) + +### Palette MLOD ### +# class MESH_OT_bake_basic_mlod(bpy.types.Operator): +# """Set´s up a basic MLOD via Bake""" + +# bl_idname = "mesh.bake_basic_mlod" +# bl_label = "Set´s up a basic MLOD via Bake" +# bl_options = {"REGISTER", "UNDO"} + +# def execute(self, context): +# obj = context.active_object + +# #Palette selection +# palette_enum_selection = json.loads(context.scene.color_palettes.mlod_enum_selection) + +# if obj not in bpy.context.selected_objects or obj.type != "MESH": +# self.report({'WARNING'}, 'Select a Mesh to continue') +# return {"CANCELLED"} + +# faces_with_color = self.get_faces_with_color(obj) + +# grouped_colors = self.groupe_colors(faces_with_color, threshold=50) + +# matched_colors = self.find_matching_color(grouped_colors, palette_enum_selection[0][:-4]) + +# self.adjust_UV(obj, matched_colors) + +# #Entfernen des referenz Bake Image +# #bpy.data.images.remove(bpy.data.images["MLOD_Temp"]) + +# # Entfernen aller Meterials +# if not len(obj.data.materials) == 0: +# obj.data.materials.clear() + +# # Create new Material with selected Palette +# mlod_material_name = "MLOD_" + palette_enum_selection[0][:-4] + palette_enum_selection[1] + +# texture_filepath = os.path.join(L1960_path, palette_enum_selection[0]) +# image = bpy.data.images.load(texture_filepath) + +# if not bpy.data.materials.get(mlod_material_name): +# material = bpy.data.materials.new(name=mlod_material_name) +# material.use_nodes = True +# bsdf_node = material.node_tree.nodes["Principled BSDF"] +# texImage = material.node_tree.nodes.new('ShaderNodeTexImage') +# texImage.image = image +# material.node_tree.links.new(bsdf_node.inputs['Base Color'], texImage.outputs['Color']) +# obj.data.materials.append(bpy.data.materials.get(mlod_material_name)) + +# self.report({'INFO'}, f'MLOD sucessfully created with {palette_enum_selection[0][:-4]}.') +# return {"FINISHED"} + +# def get_faces_with_color(self, obj): + +# #Bake Image +# image = self.bake_diffuse(obj) + +# mesh = obj.data +# uv_layer = mesh.uv_layers.active.data # direct UV access + +# colors = [] + +# for poly in mesh.polygons: # same as "face" in BMesh +# # Durchschnittliche UV-Koordinaten berechnen +# uv = Vector((0.0, 0.0)) +# for loop_index in poly.loop_indices: +# uv += uv_layer[loop_index].uv +# uv /= len(poly.loop_indices) + +# # UV → Pixel-Koordinaten (Bildgröße) +# x = int(uv.x * (image.size[0] - 1)) +# y = int(uv.y * (image.size[1] - 1)) + +# # RGBA Pixel holen +# index = (y * image.size[0] + x) * 4 +# pixel = image.pixels[index:index+4] + +# # In 0–255 Werte umwandeln +# rgb_255 = [round(c * 255) for c in pixel][:3] + +# colors.append({ +# "face": poly.index, +# "rgb": rgb_255 +# }) + +# # print(colors[-1]) # -> [{'face': , 'rgb': [0, 0, 0]}] + +# return colors + +# def groupe_colors(self, color_list, threshold = 10): +# groups = [] + +# for color in color_list: +# found_group = False +# for group in groups: +# # Compute average color of the group +# avg_color = [sum(c["rgb"][i] for c in group)/len(group) for i in range(3)] +# if self.color_distance(color["rgb"], avg_color) <= threshold: +# group.append(color) +# found_group = True +# break +# if not found_group: +# groups.append([color]) + +# # Compute the average color for each group +# grouped_colors = [{ +# "face": [c["face"] for c in group], +# "rgb": [round(sum(c["rgb"][i] for c in group) / len(group)) for i in range(3)] +# } +# for group in groups +# ] + +# return grouped_colors + +# def color_distance(self, c1, c2): +# return math.sqrt( +# (c1[0]-c2[0])**2 + +# (c1[1]-c2[1])**2 + +# (c1[2]-c2[2])**2 +# ) + +# def read_color_csv(self, palette): +# colors = [] +# try: +# with open(f"{palette}.csv", newline="") as datei: +# reader = csv.DictReader(datei) +# for row in reader: +# colors.append({ +# "rgb": [int(row["r"]), int(row["g"]), int(row["b"])], +# "norm_x": float(row["norm_x"]), +# "norm_y": float(row["norm_y"]) +# }) +# return colors +# except: +# return [] + +# def find_matching_color(self, colors, palette): +# match = [] +# for color in colors: +# best = None +# min_dist = float("inf") + +# for target in self.read_color_csv(palette): +# dist = self.color_distance(target["rgb"], color["rgb"]) +# if dist < min_dist: +# min_dist = dist +# best = { +# "face": color["face"], +# "rgb": color["rgb"], +# "norm_x": target["norm_x"], +# "norm_y": target["norm_y"] +# } +# match.append(best) +# return match + +# def adjust_UV(self, obj, new_face_coords): +# scale = 0.001 # Skalierung + +# mesh = obj.data + +# arr_layers = obj.data.uv_layers +# if not arr_layers.get("MLOD") or len(arr_layers) > 1: +# for uv_layer in reversed(arr_layers): +# arr_layers.remove(uv_layer) +# arr_layers.new(name = 'MLOD') +# uv_layer = arr_layers.get("MLOD") +# mesh.uv_layers.active = uv_layer + +# for poly in mesh.polygons: +# for coords in new_face_coords: +# if poly.index in coords["face"]: + +# # Mittelpunkt der UVs dieses Polygons berechnen +# uvs = [uv_layer.data[i].uv.copy() for i in poly.loop_indices] +# center = sum(uvs, Vector((0.0, 0.0))) / len(uvs) + +# # Skalieren + Verschieben +# for i in poly.loop_indices: +# uv = uv_layer.data[i].uv +# uv -= center +# uv *= scale +# uv += Vector((float(coords["norm_x"]), float(coords["norm_y"]))) + +# # Mesh updaten +# mesh.update() + +# def bake_diffuse(self, selected_obj, res = 1024): + +# source_obj = None +# for obj in bpy.data.objects: +# if obj.type == 'MESH' and obj.name.endswith("_LOD0"): +# print(obj.name) +# source_obj = obj.copy() +# source_obj.data = obj.data.copy() +# bpy.context.collection.objects.link(source_obj) +# break + +# if source_obj is None: +# source_obj = selected_obj.copy() +# source_obj.data = selected_obj.data.copy() +# bpy.context.collection.objects.link(source_obj) + +# # Material erstellen +# if "MLOD_Temp" in bpy.data.materials: +# mat = bpy.data.materials.remove["MLOD_Temp"] +# mat = bpy.data.materials.new(name="MLOD_Temp") +# source_obj.data.materials.clear() +# source_obj.data.materials.append(mat) + +# # WICHTIG: Material als aktives Material setzen +# mat.use_nodes = True +# source_obj.active_material = mat + +# # Ziel Image Node konfigurieren +# nodes = mat.node_tree.nodes +# links = mat.node_tree.links +# nodes.clear() +# tex_node = nodes.new(type="ShaderNodeTexImage") +# bsdf = nodes.new(type="ShaderNodeBsdfPrincipled") +# output = nodes.new(type="ShaderNodeOutputMaterial") +# links.new(bsdf.outputs["BSDF"], output.inputs["Surface"]) +# links.new(tex_node.outputs["Color"], bsdf.inputs["Base Color"]) +# nodes.active = tex_node + +# # Erstellen des Images +# if "MLOD_Temp" in bpy.data.images: +# bpy.data.images.remove(bpy.data.images["MLOD_Temp"]) +# image = bpy.data.images.new("MLOD_Temp", res, res) +# tex_node.image = image + +# # Selected Object = Quelle +# bpy.context.view_layer.objects.active = source_obj +# # Active Object = Ziel +# selected_obj.select_set(True) + +# # Bake +# bpy.context.scene.render.engine = 'CYCLES' +# bpy.ops.object.bake(type='COMBINED', width=512, height=512, cage_extrusion=0.5, pass_filter={'COLOR'}, margin=16, use_selected_to_active=True) + +# # Temporäre Helfer entfernen +# bpy.data.objects.remove(source_obj, do_unlink=True) +# if "MLOD_Temp" in bpy.data.materials: +# bpy.data.materials.remove(mat) + +# bpy.context.view_layer.objects.active = selected_obj + +# return image \ No newline at end of file diff --git a/Blender/L1960_Tools/_Source/L1960_Tools_1_8_4/ColorPalette_01.csv b/Blender/L1960_Tools/_Source/L1960_Tools_1_8_4/ColorPalette_01.csv new file mode 100644 index 0000000..853a0f3 --- /dev/null +++ b/Blender/L1960_Tools/_Source/L1960_Tools_1_8_4/ColorPalette_01.csv @@ -0,0 +1,1025 @@ +norm_x,norm_y,r,g,b +0.015625,0.984375,255,196,181 +0.046875,0.984375,255,234,176 +0.078125,0.984375,255,253,190 +0.109375,0.984375,237,255,190 +0.140625,0.984375,207,255,186 +0.171875,0.984375,188,255,192 +0.203125,0.984375,188,255,217 +0.234375,0.984375,190,255,245 +0.265625,0.984375,190,245,255 +0.296875,0.984375,188,217,255 +0.328125,0.984375,188,192,253 +0.359375,0.984375,207,187,255 +0.390625,0.984375,238,190,255 +0.421875,0.984375,255,190,253 +0.453125,0.984375,255,190,225 +0.484375,0.984375,254,193,201 +0.515625,0.984375,238,212,207 +0.546875,0.984375,238,224,204 +0.578125,0.984375,238,237,206 +0.609375,0.984375,229,238,206 +0.640625,0.984375,212,237,203 +0.671875,0.984375,204,238,207 +0.703125,0.984375,204,238,218 +0.734375,0.984375,206,238,233 +0.765625,0.984375,206,233,238 +0.796875,0.984375,204,218,238 +0.828125,0.984375,204,206,237 +0.859375,0.984375,213,204,238 +0.890625,0.984375,229,206,238 +0.921875,0.984375,238,206,237 +0.953125,0.984375,238,206,223 +0.984375,0.984375,239,207,212 +0.015625,0.953125,254,181,167 +0.046875,0.953125,255,217,163 +0.078125,0.953125,255,252,164 +0.109375,0.953125,230,255,163 +0.140625,0.953125,188,254,158 +0.171875,0.953125,160,255,167 +0.203125,0.953125,160,255,203 +0.234375,0.953125,163,255,241 +0.265625,0.953125,164,241,255 +0.296875,0.953125,160,200,254 +0.328125,0.953125,160,166,254 +0.359375,0.953125,188,159,255 +0.390625,0.953125,232,163,255 +0.421875,0.953125,255,163,249 +0.453125,0.953125,255,163,215 +0.484375,0.953125,254,167,181 +0.515625,0.953125,232,195,188 +0.546875,0.953125,232,212,186 +0.578125,0.953125,232,230,187 +0.609375,0.953125,218,232,186 +0.640625,0.953125,197,230,182 +0.671875,0.953125,184,231,187 +0.703125,0.953125,184,231,204 +0.734375,0.953125,186,232,225 +0.765625,0.953125,187,225,232 +0.796875,0.953125,184,203,230 +0.828125,0.953125,182,186,230 +0.859375,0.953125,197,182,231 +0.890625,0.953125,219,186,232 +0.921875,0.953125,232,186,229 +0.953125,0.953125,232,186,212 +0.984375,0.953125,232,190,195 +0.015625,0.921875,254,159,141 +0.046875,0.921875,255,206,136 +0.078125,0.921875,255,250,135 +0.109375,0.921875,221,255,135 +0.140625,0.921875,167,254,131 +0.171875,0.921875,132,254,140 +0.203125,0.921875,134,255,188 +0.234375,0.921875,135,255,239 +0.265625,0.921875,135,238,255 +0.296875,0.921875,134,185,254 +0.328125,0.921875,133,139,254 +0.359375,0.921875,169,131,254 +0.390625,0.921875,224,136,255 +0.421875,0.921875,255,136,248 +0.453125,0.921875,255,136,204 +0.484375,0.921875,254,141,158 +0.515625,0.921875,226,178,170 +0.546875,0.921875,225,201,166 +0.578125,0.921875,225,223,165 +0.609375,0.921875,207,225,165 +0.640625,0.921875,180,223,162 +0.671875,0.921875,162,223,166 +0.703125,0.921875,164,224,190 +0.734375,0.921875,165,225,217 +0.765625,0.921875,165,216,225 +0.796875,0.921875,164,188,224 +0.828125,0.921875,163,166,223 +0.859375,0.921875,181,162,223 +0.890625,0.921875,210,166,225 +0.921875,0.921875,225,166,222 +0.953125,0.921875,225,166,200 +0.984375,0.921875,226,170,178 +0.015625,0.890625,255,137,116 +0.046875,0.890625,255,193,109 +0.078125,0.890625,255,249,109 +0.109375,0.890625,213,255,110 +0.140625,0.890625,146,255,102 +0.171875,0.890625,105,254,115 +0.203125,0.890625,106,255,172 +0.234375,0.890625,109,255,236 +0.265625,0.890625,108,234,255 +0.296875,0.890625,106,170,255 +0.328125,0.890625,107,114,255 +0.359375,0.890625,150,103,254 +0.390625,0.890625,217,108,255 +0.421875,0.890625,255,109,248 +0.453125,0.890625,255,109,192 +0.484375,0.890625,254,116,134 +0.515625,0.890625,219,160,150 +0.546875,0.890625,217,187,145 +0.578125,0.890625,217,215,145 +0.609375,0.890625,197,217,146 +0.640625,0.890625,162,216,140 +0.671875,0.890625,141,216,146 +0.703125,0.890625,143,217,176 +0.734375,0.890625,145,217,207 +0.765625,0.890625,145,207,217 +0.796875,0.890625,143,175,217 +0.828125,0.890625,144,146,217 +0.859375,0.890625,164,141,216 +0.890625,0.890625,198,145,217 +0.921875,0.890625,217,145,215 +0.953125,0.890625,217,145,186 +0.984375,0.890625,218,150,159 +0.015625,0.859375,255,115,91 +0.046875,0.859375,255,182,83 +0.078125,0.859375,255,248,83 +0.109375,0.859375,207,255,83 +0.140625,0.859375,128,255,75 +0.171875,0.859375,78,254,90 +0.203125,0.859375,78,255,157 +0.234375,0.859375,82,255,231 +0.265625,0.859375,82,230,255 +0.296875,0.859375,78,153,255 +0.328125,0.859375,80,88,254 +0.359375,0.859375,131,76,254 +0.390625,0.859375,210,82,255 +0.421875,0.859375,255,82,247 +0.453125,0.859375,255,82,181 +0.484375,0.859375,255,91,114 +0.515625,0.859375,212,144,132 +0.546875,0.859375,212,176,126 +0.578125,0.859375,212,208,126 +0.609375,0.859375,188,212,126 +0.640625,0.859375,146,210,120 +0.671875,0.859375,122,210,128 +0.703125,0.859375,122,210,160 +0.734375,0.859375,125,211,198 +0.765625,0.859375,125,198,211 +0.796875,0.859375,122,159,210 +0.828125,0.859375,123,127,210 +0.859375,0.859375,146,120,208 +0.890625,0.859375,188,125,211 +0.921875,0.859375,211,125,207 +0.953125,0.859375,211,125,174 +0.984375,0.859375,212,132,143 +0.015625,0.828125,254,94,65 +0.046875,0.828125,255,172,56 +0.078125,0.828125,255,247,55 +0.109375,0.828125,198,255,55 +0.140625,0.828125,108,254,47 +0.171875,0.828125,50,254,64 +0.203125,0.828125,51,255,141 +0.234375,0.828125,54,255,227 +0.265625,0.828125,56,226,255 +0.296875,0.828125,51,137,255 +0.328125,0.828125,51,62,253 +0.359375,0.828125,111,47,254 +0.390625,0.828125,203,55,255 +0.421875,0.828125,255,55,246 +0.453125,0.828125,255,55,169 +0.484375,0.828125,255,65,91 +0.515625,0.828125,207,127,113 +0.546875,0.828125,204,164,106 +0.578125,0.828125,204,201,105 +0.609375,0.828125,177,204,105 +0.640625,0.828125,129,201,99 +0.671875,0.828125,101,203,108 +0.703125,0.828125,102,204,146 +0.734375,0.828125,104,204,190 +0.765625,0.828125,106,190,204 +0.796875,0.828125,102,145,204 +0.828125,0.828125,101,107,201 +0.859375,0.828125,131,99,201 +0.890625,0.828125,179,105,204 +0.921875,0.828125,204,105,200 +0.953125,0.828125,204,105,162 +0.984375,0.828125,207,113,125 +0.015625,0.796875,255,70,39 +0.046875,0.796875,255,160,25 +0.078125,0.796875,255,248,26 +0.109375,0.796875,192,255,26 +0.140625,0.796875,87,255,15 +0.171875,0.796875,19,255,35 +0.203125,0.796875,20,255,126 +0.234375,0.796875,26,255,227 +0.265625,0.796875,27,223,255 +0.296875,0.796875,20,121,255 +0.328125,0.796875,20,34,255 +0.359375,0.796875,91,15,255 +0.390625,0.796875,197,26,255 +0.421875,0.796875,255,26,246 +0.453125,0.796875,255,26,157 +0.484375,0.796875,255,38,67 +0.515625,0.796875,201,108,93 +0.546875,0.796875,197,150,82 +0.578125,0.796875,197,193,83 +0.609375,0.796875,165,197,83 +0.640625,0.796875,111,195,75 +0.671875,0.796875,78,195,86 +0.703125,0.796875,79,195,132 +0.734375,0.796875,83,197,182 +0.765625,0.796875,84,182,198 +0.796875,0.796875,79,129,195 +0.828125,0.796875,79,86,195 +0.859375,0.796875,113,75,195 +0.890625,0.796875,167,83,197 +0.921875,0.796875,197,83,193 +0.953125,0.796875,197,83,148 +0.984375,0.796875,200,92,107 +0.015625,0.765625,255,50,15 +0.046875,0.765625,255,149,1 +0.078125,0.765625,255,247,2 +0.109375,0.765625,184,255,2 +0.140625,0.765625,67,254,0 +0.171875,0.765625,0,255,13 +0.203125,0.765625,0,255,110 +0.234375,0.765625,2,255,223 +0.265625,0.765625,1,217,255 +0.296875,0.765625,0,106,255 +0.328125,0.765625,0,8,255 +0.359375,0.765625,72,0,254 +0.390625,0.765625,188,1,255 +0.421875,0.765625,255,1,245 +0.453125,0.765625,255,1,145 +0.484375,0.765625,255,14,46 +0.515625,0.765625,193,92,75 +0.546875,0.765625,190,138,64 +0.578125,0.765625,190,187,65 +0.609375,0.765625,155,190,65 +0.640625,0.765625,96,190,63 +0.671875,0.765625,64,190,70 +0.703125,0.765625,64,190,119 +0.734375,0.765625,65,190,175 +0.765625,0.765625,64,172,190 +0.796875,0.765625,64,117,190 +0.828125,0.765625,64,68,190 +0.859375,0.765625,99,63,190 +0.890625,0.765625,158,64,190 +0.921875,0.765625,190,64,186 +0.953125,0.765625,190,64,136 +0.984375,0.765625,193,74,90 +0.015625,0.734375,234,43,13 +0.046875,0.734375,239,135,0 +0.078125,0.734375,238,226,0 +0.109375,0.734375,167,242,0 +0.140625,0.734375,59,232,0 +0.171875,0.734375,0,233,7 +0.203125,0.734375,0,235,99 +0.234375,0.734375,0,246,203 +0.265625,0.734375,0,198,245 +0.296875,0.734375,0,94,234 +0.328125,0.734375,0,5,233 +0.359375,0.734375,63,0,234 +0.390625,0.734375,171,0,244 +0.421875,0.734375,239,0,223 +0.453125,0.734375,239,0,130 +0.484375,0.734375,235,13,41 +0.515625,0.734375,178,83,68 +0.546875,0.734375,179,127,60 +0.578125,0.734375,178,171,59 +0.609375,0.734375,144,182,61 +0.640625,0.734375,87,174,58 +0.671875,0.734375,58,174,62 +0.703125,0.734375,59,176,108 +0.734375,0.734375,61,184,162 +0.765625,0.734375,61,160,182 +0.796875,0.734375,58,105,175 +0.828125,0.734375,58,60,174 +0.859375,0.734375,90,58,175 +0.890625,0.734375,146,61,182 +0.921875,0.734375,180,60,171 +0.953125,0.734375,179,60,125 +0.984375,0.734375,179,68,82 +0.015625,0.703125,207,41,13 +0.046875,0.703125,207,118,1 +0.078125,0.703125,208,197,0 +0.109375,0.703125,148,212,0 +0.140625,0.703125,52,204,0 +0.171875,0.703125,0,204,8 +0.203125,0.703125,0,204,87 +0.234375,0.703125,0,213,176 +0.265625,0.703125,0,174,215 +0.296875,0.703125,0,83,204 +0.328125,0.703125,0,7,203 +0.359375,0.703125,56,0,204 +0.390625,0.703125,150,0,213 +0.421875,0.703125,208,0,195 +0.453125,0.703125,208,0,115 +0.484375,0.703125,207,13,40 +0.515625,0.703125,158,75,61 +0.546875,0.703125,156,111,53 +0.578125,0.703125,156,149,52 +0.609375,0.703125,127,159,53 +0.640625,0.703125,77,153,51 +0.671875,0.703125,51,153,55 +0.703125,0.703125,51,153,94 +0.734375,0.703125,53,160,141 +0.765625,0.703125,54,140,160 +0.796875,0.703125,51,92,153 +0.828125,0.703125,51,55,152 +0.859375,0.703125,79,51,153 +0.890625,0.703125,128,53,160 +0.921875,0.703125,156,52,149 +0.953125,0.703125,156,52,109 +0.984375,0.703125,158,61,75 +0.015625,0.671875,181,37,13 +0.046875,0.671875,181,102,1 +0.078125,0.671875,181,170,1 +0.109375,0.671875,127,182,1 +0.140625,0.671875,46,177,0 +0.171875,0.671875,0,176,7 +0.203125,0.671875,0,178,76 +0.234375,0.671875,0,186,152 +0.265625,0.671875,1,150,185 +0.296875,0.671875,0,71,178 +0.328125,0.671875,0,6,176 +0.359375,0.671875,49,0,176 +0.390625,0.671875,129,0,184 +0.421875,0.671875,181,0,170 +0.453125,0.671875,181,0,100 +0.484375,0.671875,181,13,35 +0.515625,0.671875,138,66,55 +0.546875,0.671875,136,96,46 +0.578125,0.671875,136,130,46 +0.609375,0.671875,109,137,46 +0.640625,0.671875,67,132,44 +0.671875,0.671875,44,132,47 +0.703125,0.671875,44,133,82 +0.734375,0.671875,46,139,122 +0.765625,0.671875,47,121,139 +0.796875,0.671875,44,79,133 +0.828125,0.671875,44,47,132 +0.859375,0.671875,68,44,132 +0.890625,0.671875,110,46,138 +0.921875,0.671875,135,45,129 +0.953125,0.671875,135,45,95 +0.984375,0.671875,138,55,65 +0.015625,0.640625,155,33,13 +0.046875,0.640625,152,88,0 +0.078125,0.640625,153,144,1 +0.109375,0.640625,108,155,0 +0.140625,0.640625,39,149,0 +0.171875,0.640625,0,149,6 +0.203125,0.640625,0,150,64 +0.234375,0.640625,0,157,129 +0.265625,0.640625,1,127,156 +0.296875,0.640625,0,61,150 +0.328125,0.640625,0,5,150 +0.359375,0.640625,41,0,148 +0.390625,0.640625,110,0,155 +0.421875,0.640625,153,0,143 +0.453125,0.640625,153,0,85 +0.484375,0.640625,155,13,31 +0.515625,0.640625,119,59,48 +0.546875,0.640625,114,82,38 +0.578125,0.640625,115,110,39 +0.609375,0.640625,93,116,39 +0.640625,0.640625,56,111,37 +0.671875,0.640625,37,111,40 +0.703125,0.640625,38,113,70 +0.734375,0.640625,39,117,103 +0.765625,0.640625,40,102,117 +0.796875,0.640625,38,68,113 +0.828125,0.640625,37,40,112 +0.859375,0.640625,58,37,111 +0.890625,0.640625,93,39,116 +0.921875,0.640625,114,38,109 +0.953125,0.640625,114,38,80 +0.984375,0.640625,119,48,57 +0.015625,0.609375,129,29,14 +0.046875,0.609375,125,72,0 +0.078125,0.609375,127,118,1 +0.109375,0.609375,88,127,0 +0.140625,0.609375,30,122,0 +0.171875,0.609375,0,122,5 +0.203125,0.609375,0,123,51 +0.234375,0.609375,1,129,106 +0.265625,0.609375,0,104,129 +0.296875,0.609375,0,50,122 +0.328125,0.609375,0,3,123 +0.359375,0.609375,32,0,122 +0.390625,0.609375,90,0,128 +0.421875,0.609375,127,0,119 +0.453125,0.609375,125,0,69 +0.484375,0.609375,130,13,27 +0.515625,0.609375,99,50,42 +0.546875,0.609375,93,67,31 +0.578125,0.609375,95,90,32 +0.609375,0.609375,76,95,32 +0.640625,0.609375,45,91,30 +0.671875,0.609375,30,91,32 +0.703125,0.609375,31,92,56 +0.734375,0.609375,33,97,85 +0.765625,0.609375,32,83,96 +0.796875,0.609375,30,55,91 +0.828125,0.609375,31,32,92 +0.859375,0.609375,46,30,91 +0.890625,0.609375,77,32,96 +0.921875,0.609375,95,32,91 +0.953125,0.609375,93,31,65 +0.984375,0.609375,100,42,49 +0.015625,0.578125,103,26,13 +0.046875,0.578125,98,55,0 +0.078125,0.578125,99,93,0 +0.109375,0.578125,68,100,0 +0.140625,0.578125,24,96,0 +0.171875,0.578125,0,95,4 +0.203125,0.578125,0,95,40 +0.234375,0.578125,1,100,83 +0.265625,0.578125,0,82,101 +0.296875,0.578125,0,38,96 +0.328125,0.578125,0,3,96 +0.359375,0.578125,26,0,97 +0.390625,0.578125,70,0,101 +0.421875,0.578125,99,0,92 +0.453125,0.578125,98,0,54 +0.484375,0.578125,103,13,24 +0.515625,0.578125,80,42,36 +0.546875,0.578125,73,51,24 +0.578125,0.578125,74,71,25 +0.609375,0.578125,59,75,25 +0.640625,0.578125,36,72,24 +0.671875,0.578125,24,71,26 +0.703125,0.578125,24,71,44 +0.734375,0.578125,26,75,66 +0.765625,0.578125,25,65,75 +0.796875,0.578125,24,43,72 +0.828125,0.578125,24,25,72 +0.859375,0.578125,37,24,72 +0.890625,0.578125,60,25,75 +0.921875,0.578125,74,25,70 +0.953125,0.578125,73,24,51 +0.984375,0.578125,80,36,41 +0.015625,0.546875,78,22,13 +0.046875,0.546875,69,40,0 +0.078125,0.546875,69,67,1 +0.109375,0.546875,49,72,1 +0.140625,0.546875,18,69,0 +0.171875,0.546875,0,69,3 +0.203125,0.546875,0,69,29 +0.234375,0.546875,1,72,60 +0.265625,0.546875,1,59,73 +0.296875,0.546875,0,28,70 +0.328125,0.546875,0,2,68 +0.359375,0.546875,18,0,70 +0.390625,0.546875,50,0,72 +0.421875,0.546875,71,0,65 +0.453125,0.546875,70,0,38 +0.484375,0.546875,78,13,22 +0.515625,0.546875,61,34,29 +0.546875,0.546875,51,37,17 +0.578125,0.546875,52,51,18 +0.609375,0.546875,43,54,19 +0.640625,0.546875,26,51,17 +0.671875,0.546875,17,51,18 +0.703125,0.546875,17,51,31 +0.734375,0.546875,19,54,48 +0.765625,0.546875,19,48,55 +0.796875,0.546875,17,31,52 +0.828125,0.546875,17,18,51 +0.859375,0.546875,26,17,52 +0.890625,0.546875,43,18,54 +0.921875,0.546875,53,18,50 +0.953125,0.546875,52,17,36 +0.984375,0.546875,61,29,34 +0.015625,0.515625,41,5,0 +0.046875,0.515625,41,24,0 +0.078125,0.515625,41,40,1 +0.109375,0.515625,29,44,0 +0.140625,0.515625,10,41,0 +0.171875,0.515625,0,41,2 +0.203125,0.515625,0,41,17 +0.234375,0.515625,1,42,36 +0.265625,0.515625,0,35,43 +0.296875,0.515625,0,17,41 +0.328125,0.515625,0,2,41 +0.359375,0.515625,10,0,41 +0.390625,0.515625,30,0,42 +0.421875,0.515625,42,0,39 +0.453125,0.515625,41,0,23 +0.484375,0.515625,41,0,5 +0.515625,0.515625,30,12,10 +0.546875,0.515625,30,22,10 +0.578125,0.515625,31,30,11 +0.609375,0.515625,25,33,11 +0.640625,0.515625,15,30,10 +0.671875,0.515625,10,30,11 +0.703125,0.515625,10,30,18 +0.734375,0.515625,11,31,28 +0.765625,0.515625,11,28,32 +0.796875,0.515625,10,18,30 +0.828125,0.515625,10,11,30 +0.859375,0.515625,15,10,30 +0.890625,0.515625,25,10,31 +0.921875,0.515625,31,10,29 +0.953125,0.515625,30,10,21 +0.984375,0.515625,30,10,12 +0.015625,0.484375,221,204,201 +0.046875,0.484375,232,224,212 +0.078125,0.484375,232,231,212 +0.109375,0.484375,226,232,212 +0.140625,0.484375,216,231,210 +0.171875,0.484375,211,231,212 +0.203125,0.484375,212,232,221 +0.234375,0.484375,212,232,229 +0.265625,0.484375,212,229,232 +0.296875,0.484375,212,219,232 +0.328125,0.484375,211,212,230 +0.359375,0.484375,217,211,231 +0.390625,0.484375,227,212,232 +0.421875,0.484375,232,212,231 +0.453125,0.484375,232,212,223 +0.484375,0.484375,221,203,204 +0.515625,0.484375,215,208,207 +0.546875,0.484375,225,222,217 +0.578125,0.484375,226,226,218 +0.609375,0.484375,224,226,218 +0.640625,0.484375,218,224,217 +0.671875,0.484375,217,225,217 +0.703125,0.484375,217,225,221 +0.734375,0.484375,218,226,225 +0.765625,0.484375,218,225,226 +0.796875,0.484375,217,221,225 +0.828125,0.484375,217,217,224 +0.859375,0.484375,218,217,224 +0.890625,0.484375,224,218,226 +0.921875,0.484375,226,218,226 +0.953125,0.484375,226,218,223 +0.984375,0.484375,215,208,210 +0.015625,0.453125,224,201,197 +0.046875,0.453125,223,211,195 +0.078125,0.453125,223,222,195 +0.109375,0.453125,215,223,195 +0.140625,0.453125,200,219,190 +0.171875,0.453125,193,222,195 +0.203125,0.453125,193,222,206 +0.234375,0.453125,195,223,218 +0.265625,0.453125,195,218,223 +0.296875,0.453125,193,204,221 +0.328125,0.453125,193,195,221 +0.359375,0.453125,201,192,221 +0.390625,0.453125,216,195,223 +0.421875,0.453125,223,195,221 +0.453125,0.453125,223,195,211 +0.484375,0.453125,224,198,201 +0.515625,0.453125,213,207,206 +0.546875,0.453125,212,208,204 +0.578125,0.453125,213,213,204 +0.609375,0.453125,211,212,204 +0.640625,0.453125,204,211,201 +0.671875,0.453125,201,212,203 +0.703125,0.453125,203,212,207 +0.734375,0.453125,204,212,212 +0.765625,0.453125,204,212,213 +0.796875,0.453125,203,207,212 +0.828125,0.453125,201,203,212 +0.859375,0.453125,204,201,212 +0.890625,0.453125,211,204,212 +0.921875,0.453125,212,204,212 +0.953125,0.453125,212,204,208 +0.984375,0.453125,215,207,207 +0.015625,0.421875,213,186,181 +0.046875,0.421875,212,198,177 +0.078125,0.421875,212,212,177 +0.109375,0.421875,203,212,177 +0.140625,0.421875,185,211,174 +0.171875,0.421875,174,211,176 +0.203125,0.421875,176,212,192 +0.234375,0.421875,177,212,207 +0.265625,0.421875,177,207,212 +0.296875,0.421875,176,190,212 +0.328125,0.421875,175,177,211 +0.359375,0.421875,185,174,211 +0.390625,0.421875,204,177,212 +0.421875,0.421875,212,177,211 +0.453125,0.421875,212,177,198 +0.484375,0.421875,213,181,186 +0.515625,0.421875,204,193,192 +0.546875,0.421875,201,195,188 +0.578125,0.421875,201,201,188 +0.609375,0.421875,198,201,188 +0.640625,0.421875,190,198,186 +0.671875,0.421875,187,198,188 +0.703125,0.421875,188,200,193 +0.734375,0.421875,188,201,198 +0.765625,0.421875,188,198,201 +0.796875,0.421875,188,193,200 +0.828125,0.421875,187,188,198 +0.859375,0.421875,190,186,198 +0.890625,0.421875,198,188,201 +0.921875,0.421875,201,188,200 +0.953125,0.421875,201,188,195 +0.984375,0.421875,204,192,193 +0.015625,0.390625,207,171,165 +0.046875,0.390625,204,185,160 +0.078125,0.390625,204,201,160 +0.109375,0.390625,190,204,160 +0.140625,0.390625,167,201,155 +0.171875,0.390625,157,201,160 +0.203125,0.390625,158,203,178 +0.234375,0.390625,160,204,198 +0.265625,0.390625,159,197,203 +0.296875,0.390625,158,177,203 +0.328125,0.390625,158,160,203 +0.359375,0.390625,170,156,201 +0.390625,0.390625,192,159,203 +0.421875,0.390625,204,160,201 +0.453125,0.390625,204,160,185 +0.484375,0.390625,206,164,170 +0.515625,0.390625,192,180,178 +0.546875,0.390625,188,182,174 +0.578125,0.390625,188,188,174 +0.609375,0.390625,186,190,175 +0.640625,0.390625,175,186,170 +0.671875,0.390625,172,187,173 +0.703125,0.390625,173,188,180 +0.734375,0.390625,174,188,187 +0.765625,0.390625,174,187,188 +0.796875,0.390625,173,179,188 +0.828125,0.390625,173,174,188 +0.859375,0.390625,176,171,186 +0.890625,0.390625,185,174,188 +0.921875,0.390625,188,174,188 +0.953125,0.390625,188,174,182 +0.984375,0.390625,192,178,180 +0.015625,0.359375,197,155,148 +0.046875,0.359375,195,173,143 +0.078125,0.359375,195,193,143 +0.109375,0.359375,180,195,143 +0.140625,0.359375,153,192,138 +0.171875,0.359375,139,192,143 +0.203125,0.359375,140,193,164 +0.234375,0.359375,141,193,187 +0.265625,0.359375,141,186,193 +0.296875,0.359375,140,163,193 +0.328125,0.359375,141,143,193 +0.359375,0.359375,155,138,192 +0.390625,0.359375,180,141,193 +0.421875,0.359375,193,141,192 +0.453125,0.359375,193,141,172 +0.484375,0.359375,197,148,153 +0.515625,0.359375,181,167,164 +0.546875,0.359375,177,170,160 +0.578125,0.359375,177,176,160 +0.609375,0.359375,172,177,160 +0.640625,0.359375,160,174,156 +0.671875,0.359375,157,175,158 +0.703125,0.359375,157,175,165 +0.734375,0.359375,159,177,174 +0.765625,0.359375,159,174,177 +0.796875,0.359375,157,165,175 +0.828125,0.359375,158,159,176 +0.859375,0.359375,162,156,174 +0.890625,0.359375,172,159,177 +0.921875,0.359375,177,159,176 +0.953125,0.359375,177,159,169 +0.984375,0.359375,181,164,166 +0.015625,0.328125,188,139,131 +0.046875,0.328125,185,160,125 +0.078125,0.328125,185,182,125 +0.109375,0.328125,167,185,125 +0.140625,0.328125,137,181,119 +0.171875,0.328125,121,182,125 +0.203125,0.328125,122,182,149 +0.234375,0.328125,124,184,175 +0.265625,0.328125,125,176,185 +0.296875,0.328125,122,148,182 +0.328125,0.328125,121,124,182 +0.359375,0.328125,138,119,181 +0.390625,0.328125,169,125,185 +0.421875,0.328125,185,125,182 +0.453125,0.328125,185,125,159 +0.484375,0.328125,188,132,139 +0.515625,0.328125,169,153,150 +0.546875,0.328125,165,157,145 +0.578125,0.328125,165,164,145 +0.609375,0.328125,159,165,145 +0.640625,0.328125,146,160,140 +0.671875,0.328125,141,162,141 +0.703125,0.328125,141,163,150 +0.734375,0.328125,144,164,160 +0.765625,0.328125,145,162,165 +0.796875,0.328125,141,150,163 +0.828125,0.328125,141,141,162 +0.859375,0.328125,146,140,160 +0.890625,0.328125,160,145,165 +0.921875,0.328125,165,145,164 +0.953125,0.328125,165,145,156 +0.984375,0.328125,170,150,153 +0.015625,0.296875,179,123,114 +0.046875,0.296875,174,146,105 +0.078125,0.296875,175,173,106 +0.109375,0.296875,156,175,106 +0.140625,0.296875,121,171,99 +0.171875,0.296875,101,172,106 +0.203125,0.296875,102,173,134 +0.234375,0.296875,106,175,166 +0.265625,0.296875,106,165,175 +0.296875,0.296875,102,133,173 +0.328125,0.296875,102,106,173 +0.359375,0.296875,122,99,171 +0.390625,0.296875,157,106,175 +0.421875,0.296875,175,106,172 +0.453125,0.296875,175,106,145 +0.484375,0.296875,179,114,122 +0.515625,0.296875,157,138,135 +0.546875,0.296875,150,141,128 +0.578125,0.296875,152,150,129 +0.609375,0.296875,146,152,129 +0.640625,0.296875,130,146,123 +0.671875,0.296875,125,149,127 +0.703125,0.296875,125,149,136 +0.734375,0.296875,129,152,149 +0.765625,0.296875,129,149,152 +0.796875,0.296875,125,135,149 +0.828125,0.296875,125,126,149 +0.859375,0.296875,131,123,146 +0.890625,0.296875,146,129,152 +0.921875,0.296875,152,129,150 +0.953125,0.296875,152,129,141 +0.984375,0.296875,157,135,138 +0.015625,0.265625,171,109,98 +0.046875,0.265625,166,134,90 +0.078125,0.265625,166,164,90 +0.109375,0.265625,144,166,90 +0.140625,0.265625,109,165,89 +0.171875,0.265625,89,166,93 +0.203125,0.265625,89,166,122 +0.234375,0.265625,90,166,156 +0.265625,0.265625,90,155,166 +0.296875,0.265625,89,121,166 +0.328125,0.265625,89,91,166 +0.359375,0.265625,110,89,165 +0.390625,0.265625,146,90,166 +0.421875,0.265625,166,90,163 +0.453125,0.265625,166,90,133 +0.484375,0.265625,171,98,108 +0.515625,0.265625,146,126,122 +0.546875,0.265625,141,130,115 +0.578125,0.265625,141,140,115 +0.609375,0.265625,134,141,115 +0.640625,0.265625,121,140,114 +0.671875,0.265625,114,140,115 +0.703125,0.265625,114,140,125 +0.734375,0.265625,115,141,138 +0.765625,0.265625,115,137,141 +0.796875,0.265625,114,125,140 +0.828125,0.265625,114,115,140 +0.859375,0.265625,121,114,140 +0.890625,0.265625,134,115,141 +0.921875,0.265625,141,115,140 +0.953125,0.265625,141,115,130 +0.984375,0.265625,146,122,125 +0.015625,0.234375,156,99,90 +0.046875,0.234375,155,123,83 +0.078125,0.234375,155,150,83 +0.109375,0.234375,135,158,85 +0.140625,0.234375,99,150,81 +0.171875,0.234375,81,150,83 +0.203125,0.234375,82,153,112 +0.234375,0.234375,86,160,146 +0.265625,0.234375,85,145,159 +0.296875,0.234375,82,110,152 +0.328125,0.234375,81,82,150 +0.359375,0.234375,101,82,152 +0.390625,0.234375,136,85,158 +0.421875,0.234375,156,84,150 +0.453125,0.234375,155,83,122 +0.484375,0.234375,157,91,99 +0.515625,0.234375,134,115,112 +0.546875,0.234375,131,120,107 +0.578125,0.234375,131,130,107 +0.609375,0.234375,126,134,109 +0.640625,0.234375,110,128,104 +0.671875,0.234375,104,128,105 +0.703125,0.234375,105,129,115 +0.734375,0.234375,110,135,131 +0.765625,0.234375,110,130,135 +0.796875,0.234375,105,115,129 +0.828125,0.234375,104,104,128 +0.859375,0.234375,111,105,129 +0.890625,0.234375,126,109,134 +0.921875,0.234375,132,108,130 +0.953125,0.234375,131,107,120 +0.984375,0.234375,135,113,115 +0.015625,0.203125,138,89,80 +0.046875,0.203125,135,108,73 +0.078125,0.203125,136,132,73 +0.109375,0.203125,118,138,74 +0.140625,0.203125,86,132,71 +0.171875,0.203125,71,132,73 +0.203125,0.203125,71,133,97 +0.234375,0.203125,75,139,127 +0.265625,0.203125,75,127,140 +0.296875,0.203125,71,96,133 +0.328125,0.203125,71,73,132 +0.359375,0.203125,88,71,132 +0.390625,0.203125,120,75,139 +0.421875,0.203125,136,73,132 +0.453125,0.203125,136,73,107 +0.484375,0.203125,138,80,88 +0.515625,0.203125,119,102,99 +0.546875,0.203125,115,106,94 +0.578125,0.203125,115,114,94 +0.609375,0.203125,110,117,95 +0.640625,0.203125,96,112,91 +0.671875,0.203125,91,112,92 +0.703125,0.203125,92,113,101 +0.734375,0.203125,96,118,114 +0.765625,0.203125,96,114,118 +0.796875,0.203125,92,100,113 +0.828125,0.203125,91,92,112 +0.859375,0.203125,97,91,112 +0.890625,0.203125,111,96,118 +0.921875,0.203125,115,94,114 +0.953125,0.203125,115,94,105 +0.984375,0.203125,119,99,102 +0.015625,0.171875,122,78,72 +0.046875,0.171875,118,94,64 +0.078125,0.171875,118,114,64 +0.109375,0.171875,102,119,64 +0.140625,0.171875,76,115,62 +0.171875,0.171875,61,114,63 +0.203125,0.171875,62,116,85 +0.234375,0.171875,65,121,110 +0.265625,0.171875,65,109,120 +0.296875,0.171875,62,84,116 +0.328125,0.171875,61,63,114 +0.359375,0.171875,76,61,114 +0.390625,0.171875,102,64,119 +0.421875,0.171875,117,63,114 +0.453125,0.171875,117,63,93 +0.484375,0.171875,122,72,78 +0.515625,0.171875,105,91,88 +0.546875,0.171875,100,92,82 +0.578125,0.171875,100,99,82 +0.609375,0.171875,95,101,83 +0.640625,0.171875,84,97,79 +0.671875,0.171875,79,97,80 +0.703125,0.171875,80,98,88 +0.734375,0.171875,83,102,98 +0.765625,0.171875,83,98,102 +0.796875,0.171875,80,87,98 +0.828125,0.171875,79,80,97 +0.859375,0.171875,84,79,97 +0.890625,0.171875,95,82,101 +0.921875,0.171875,99,81,98 +0.953125,0.171875,99,81,91 +0.984375,0.171875,105,88,90 +0.015625,0.140625,105,68,62 +0.046875,0.140625,99,80,53 +0.078125,0.140625,100,97,54 +0.109375,0.140625,87,101,54 +0.140625,0.140625,64,97,52 +0.171875,0.140625,52,97,54 +0.203125,0.140625,53,98,72 +0.234375,0.140625,55,102,94 +0.265625,0.140625,55,93,102 +0.296875,0.140625,53,71,98 +0.328125,0.140625,52,54,97 +0.359375,0.140625,63,51,96 +0.390625,0.140625,87,54,101 +0.421875,0.140625,99,53,96 +0.453125,0.140625,99,53,79 +0.484375,0.140625,105,62,68 +0.515625,0.140625,91,78,77 +0.546875,0.140625,83,77,68 +0.578125,0.140625,84,83,69 +0.609375,0.140625,80,85,69 +0.640625,0.140625,71,82,67 +0.671875,0.140625,67,82,68 +0.703125,0.140625,68,83,74 +0.734375,0.140625,70,86,83 +0.765625,0.140625,70,83,86 +0.796875,0.140625,68,74,83 +0.828125,0.140625,67,68,82 +0.859375,0.140625,70,66,81 +0.890625,0.140625,80,69,85 +0.921875,0.140625,84,68,83 +0.953125,0.140625,84,68,77 +0.984375,0.140625,91,77,78 +0.015625,0.109375,88,59,54 +0.046875,0.109375,81,65,43 +0.078125,0.109375,83,80,45 +0.109375,0.109375,70,82,44 +0.140625,0.109375,51,79,42 +0.171875,0.109375,42,79,43 +0.203125,0.109375,43,80,58 +0.234375,0.109375,46,84,77 +0.265625,0.109375,45,76,84 +0.296875,0.109375,42,57,79 +0.328125,0.109375,43,44,80 +0.359375,0.109375,52,42,79 +0.390625,0.109375,72,45,83 +0.421875,0.109375,82,44,79 +0.453125,0.109375,81,43,64 +0.484375,0.109375,89,54,58 +0.515625,0.109375,77,67,65 +0.546875,0.109375,69,63,56 +0.578125,0.109375,70,69,57 +0.609375,0.109375,66,70,57 +0.640625,0.109375,58,67,55 +0.671875,0.109375,55,67,55 +0.703125,0.109375,55,67,60 +0.734375,0.109375,58,71,69 +0.765625,0.109375,58,68,71 +0.796875,0.109375,55,60,67 +0.828125,0.109375,55,55,67 +0.859375,0.109375,58,55,67 +0.890625,0.109375,66,57,70 +0.921875,0.109375,70,57,69 +0.953125,0.109375,69,56,63 +0.984375,0.109375,77,65,66 +0.015625,0.078125,72,48,44 +0.046875,0.078125,63,50,34 +0.078125,0.078125,64,62,34 +0.109375,0.078125,55,65,35 +0.140625,0.078125,40,62,33 +0.171875,0.078125,33,62,34 +0.203125,0.078125,33,62,45 +0.234375,0.078125,35,65,60 +0.265625,0.078125,35,59,65 +0.296875,0.078125,33,44,62 +0.328125,0.078125,33,34,62 +0.359375,0.078125,42,34,63 +0.390625,0.078125,56,35,65 +0.421875,0.078125,64,34,62 +0.453125,0.078125,63,34,50 +0.484375,0.078125,72,44,48 +0.515625,0.078125,62,54,53 +0.546875,0.078125,54,50,44 +0.578125,0.078125,54,53,44 +0.609375,0.078125,52,55,45 +0.640625,0.078125,45,53,43 +0.671875,0.078125,42,52,42 +0.703125,0.078125,42,52,46 +0.734375,0.078125,45,55,53 +0.765625,0.078125,45,53,55 +0.796875,0.078125,43,47,53 +0.828125,0.078125,43,43,53 +0.859375,0.078125,46,43,53 +0.890625,0.078125,52,45,55 +0.921875,0.078125,54,44,53 +0.953125,0.078125,54,44,50 +0.984375,0.078125,62,53,54 +0.015625,0.046875,56,39,36 +0.046875,0.046875,45,36,24 +0.078125,0.046875,45,44,25 +0.109375,0.046875,40,47,26 +0.140625,0.046875,29,45,24 +0.171875,0.046875,24,45,25 +0.203125,0.046875,24,45,33 +0.234375,0.046875,26,47,43 +0.265625,0.046875,26,44,48 +0.296875,0.046875,24,32,45 +0.328125,0.046875,24,25,44 +0.359375,0.046875,29,24,45 +0.390625,0.046875,40,25,47 +0.421875,0.046875,46,25,44 +0.453125,0.046875,45,24,35 +0.484375,0.046875,55,36,39 +0.515625,0.046875,49,43,42 +0.546875,0.046875,38,35,31 +0.578125,0.046875,38,38,31 +0.609375,0.046875,38,40,33 +0.640625,0.046875,33,38,31 +0.671875,0.046875,31,38,31 +0.703125,0.046875,31,38,34 +0.734375,0.046875,33,40,39 +0.765625,0.046875,33,39,40 +0.796875,0.046875,31,34,38 +0.828125,0.046875,30,30,37 +0.859375,0.046875,33,31,38 +0.890625,0.046875,37,32,39 +0.921875,0.046875,39,32,38 +0.953125,0.046875,38,31,35 +0.984375,0.046875,48,41,42 +0.015625,0.015625,0,0,0 +0.046875,0.015625,4,4,4 +0.078125,0.015625,9,9,9 +0.109375,0.015625,15,15,15 +0.140625,0.015625,21,21,21 +0.171875,0.015625,28,28,28 +0.203125,0.015625,36,36,36 +0.234375,0.015625,44,44,44 +0.265625,0.015625,52,52,52 +0.296875,0.015625,60,60,60 +0.328125,0.015625,69,69,69 +0.359375,0.015625,79,79,79 +0.390625,0.015625,88,88,88 +0.421875,0.015625,98,98,98 +0.453125,0.015625,108,108,108 +0.484375,0.015625,118,118,118 +0.515625,0.015625,128,128,128 +0.546875,0.015625,137,137,137 +0.578125,0.015625,146,146,146 +0.609375,0.015625,157,157,157 +0.640625,0.015625,167,167,167 +0.671875,0.015625,176,176,176 +0.703125,0.015625,186,186,186 +0.734375,0.015625,195,195,195 +0.765625,0.015625,203,203,203 +0.796875,0.015625,211,211,211 +0.828125,0.015625,218,218,218 +0.859375,0.015625,227,227,227 +0.890625,0.015625,234,234,234 +0.921875,0.015625,239,239,239 +0.953125,0.015625,246,246,246 +0.984375,0.015625,250,250,250 diff --git a/Blender/L1960_Tools/_Source/L1960_Tools_1_8_4/ColorPalette_01.png b/Blender/L1960_Tools/_Source/L1960_Tools_1_8_4/ColorPalette_01.png new file mode 100644 index 0000000000000000000000000000000000000000..a1bae62ae6e5dfc873380cc8becf0e2e9115a014 GIT binary patch literal 9972 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 literal 0 HcmV?d00001 diff --git a/Blender/L1960_Tools/_Source/L1960_Tools_1_8_4/CubeProjection.py b/Blender/L1960_Tools/_Source/L1960_Tools_1_8_4/CubeProjection.py new file mode 100644 index 0000000..5e6ca15 --- /dev/null +++ b/Blender/L1960_Tools/_Source/L1960_Tools_1_8_4/CubeProjection.py @@ -0,0 +1,94 @@ +import bpy +from math import pi + +L1960_Arr_PlainData = [ + ["Proj_Empty_01", (0, 0, 2), (0, 0, 0)], + ["Proj_Empty_02", (2, 0, 0), ((pi * 90 / 180), 0, (pi * 90 / 180))], + ["Proj_Empty_03", (0, 2, 0), ((pi * 90 / 180), 0, (pi * 180 / 180))], + ["Proj_Empty_04", (0, 0, -2), ((pi * 180 / 180), 0, 0)], + ["Proj_Empty_05", (-2, 0, 0), ((pi * 90 / 180), 0, (pi * -90 / 180))], + ["Proj_Empty_06", (0, -2, 0), ((pi * 90 / 180), 0, 0)] +] + +class MESH_OT_add_auto_cube_projection(bpy.types.Operator): + """Check Empty´s for projecting, if not existing create new one´s""" + + bl_idname = "mesh.add_auto_cube_projection" + bl_label = "Add Plain_Axes to scene" + bl_options = {"REGISTER", "UNDO"} + + def execute(self, context): + + scene = context.scene + oldSelection = context.selected_objects + oldActive = context.active_object + + for EmptyData in L1960_Arr_PlainData: + + EmptyName = EmptyData[0] + EmptyLocation = EmptyData[1] + EmptyRotation = EmptyData[2] + + if not scene.objects.get(EmptyName): + bpy.ops.object.empty_add(type='PLAIN_AXES', align='WORLD', location=EmptyLocation, scale=(1, 1, 1), rotation=EmptyRotation) + empty = context.active_object + empty.name = EmptyName + empty.hide_select = True + empty.hide_set(True) + + #Change back to old selection and select old active + for obj in oldSelection: + obj.select_set(True) + context.view_layer.objects.active = oldActive + + self.report({'INFO'}, 'Added/Fixed Emptys for Projection to Scene') + return {"FINISHED"} + +class MESH_OT_add_modifier_to_mesh(bpy.types.Operator): + """Add Modifier to selected Mesh´s and prepare UV-Maps""" + + bl_idname = "mesh.add_modifier_to_mesh" + bl_label = "Add Modifier to selected Mesh" + bl_options = {"REGISTER", "UNDO"} + + def execute(self, context): + + newModifierName = "CubeTexModifier" + arr_obj = context.selected_objects + if not arr_obj: + self.report({'WARNING'}, 'Select a mesh to add the UVProject-Modifier') + return {"CANCELLED"} + + empty_objs = [emp_obj for emp_obj in context.scene.objects if emp_obj.name.startswith("Proj_Empty")] + if len(empty_objs) < 6: + self.report({'WARNING'}, 'Create/Recreate projectors, they need to be set up first!') + return {"CANCELLED"}; + + for obj in arr_obj: + + if obj.data.uv_layers.get("UVMap"): + obj.data.uv_layers['UVMap'].name = 'UVMap0' + + if not obj.data.uv_layers.get("UVMap0"): + obj.data.uv_layers.new(name = 'UVMap0') + + if not obj.data.uv_layers.get("UVMap1"): + obj.data.uv_layers.new(name = 'UVMap1') + + + if obj.type == "MESH" and newModifierName not in obj.modifiers: + obj.modifiers.new(type='UV_PROJECT', name=newModifierName) + mod = obj.modifiers[newModifierName] + mod.uv_layer = "UVMap1" + mod.projector_count = 6 + + i = 0 + for p in mod.projectors: + p.object = bpy.data.objects[L1960_Arr_PlainData[i][0]] + i = i+1 + else: + self.report({'INFO'}, 'UVProject-Modifier allready set') + return {"FINISHED"} + + self.report({'INFO'}, 'Added UVProject-Modifier to mesh') + return {"FINISHED"} diff --git a/Blender/L1960_Tools/_Source/L1960_Tools_1_8_4/Dekogon.py b/Blender/L1960_Tools/_Source/L1960_Tools_1_8_4/Dekogon.py new file mode 100644 index 0000000..92688b1 --- /dev/null +++ b/Blender/L1960_Tools/_Source/L1960_Tools_1_8_4/Dekogon.py @@ -0,0 +1,187 @@ +import bpy +import re +import os + +### GROUP OBJECTS TO COLLECTIONS ### + +class MESH_OT_group_objects_in_collections(bpy.types.Operator): + """Groups objects by name into seperate collections, usefull for Unreal Decogon import""" + + bl_idname = "mesh.group_objects_in_collections" + bl_label = "Groups objects by name into seperate collections, usefull for Unreal Decogon import" + bl_options = {"REGISTER", "UNDO"} + + def execute(self, context): + # Erstellen einer leeren Dictionary zur Speicherung der Collections nach Basisnamen + collection_dict = {} + + # Durchlaufen aller Objekte in der Szene + for obj in context.scene.objects: + # Überprüfen, ob das Objekt ein leeres Elternobjekt ist + if obj.type == 'EMPTY': + # Anwenden der Regex auf den Objektnamen + match = re.match(r'^(.*?)_(.*?)_(\d+)([a-zA-Z]+)$', obj.name) + if match: + prefix = match.group(1) + name = match.group(2) + number = match.group(3) + letter = match.group(4) + + # Extrahieren des Basisnamens für die Collection + base_name = f"L1960_{name}" + + # Hinzufügen des Objekts zur entsprechenden Liste in der Dictionary + if base_name not in collection_dict: + collection_dict[base_name] = {} + if number not in collection_dict[base_name]: + collection_dict[base_name][number] = {} + if letter not in collection_dict[base_name][number]: + collection_dict[base_name][number][letter] = {'empty': obj, 'children': []} + + # Durchlaufen der Dictionary und Erstellen der Collections + for base_name, number_dict in collection_dict.items(): + # Erstellen einer neuen Collection für den Basisnamen + base_collection = bpy.data.collections.new(base_name) + bpy.context.scene.collection.children.link(base_collection) + + # Durchlaufen der sortierten Liste der Objekte und Verschieben in die Collections + for number, letter_dict in number_dict.items(): + # Erstellen einer Collection für die Nummer und Verschieben des leeren Elternobjekts dorthin + number_collection = bpy.data.collections.new(f"{base_name}_{number}") + base_collection.children.link(number_collection) + + # Durchlaufen der Buchstaben und Erstellen der Buchstaben-Collection unter der Nummer + for letter, obj_data in letter_dict.items(): + empty = obj_data['empty'] + children = empty.children + + letter_collection = bpy.data.collections.new(f"{base_name}_{number}{letter}") + number_collection.children.link(letter_collection) + + # Verschieben des leeren Elternobjekts in die entsprechende Collection + letter_collection.objects.link(empty) + + # Verschieben der Kinder des leeren Elternobjekts in die entsprechende Collection + for child in children: + letter_collection.objects.link(child) + + # Entfernen des leeren Elternobjekts und seiner Kinder aus der Szene + bpy.context.collection.objects.unlink(empty) + for child in children: + bpy.context.collection.objects.unlink(child) + + # ------------------------------------------------------------------------------------------- + # Regular expression pattern to match any _LOD1, _LOD2, etc., but not _LOD0 + pattern = re.compile(r"_LOD[1-9]\d*$") + + # Loop through all objects in the scene + for obj in bpy.context.scene.objects: + # If the object name matches the pattern, hide it + if pattern.search(obj.name): + obj.hide_set(True) # This hides the object in the viewport + else: + obj.hide_set(False) # Ensure _LOD0 objects remain visible + + # Update the view layer to reflect changes + bpy.context.view_layer.update() + + self.report({'INFO'}, 'All objects sorted') + return {"FINISHED"} + + +### ASSIGN TEXTURES ### + +class MESH_OT_assign_textures(bpy.types.Operator): + """Assign Textures to Mesh´s, usefull for Unreal Decogon import""" + + bl_idname = "mesh.assign_textures" + bl_label = "Assign Textures to Mesh´s, usefull for Unreal Decogon import" + bl_options = {"REGISTER", "UNDO"} + + def execute(self, context): + + # Define the path to the folder containing your textures + texture_folder_path = context.scene.dekogon_file_path + + texture_prefix = context.scene.dekogon_settings_prefix + if texture_prefix != "": + if texture_prefix[-1] != "_": + texture_prefix = texture_prefix + "_" + + texture_suffix = context.scene.dekogon_settings_suffix + if texture_suffix != "": + if texture_suffix[0] != "_": + texture_suffix = "_" + texture_suffix + + texture_filetype = context.scene.dekogon_settings_filetype + + if not os.path.exists(texture_folder_path): + self.report({'ERROR'}, f"The texture folder path '{texture_folder_path}' does not exist.") + return {"FINISHED"} + else: + self.report({'INFO'}, f"Texture folder path: {texture_folder_path}") + # List all files in the texture folder for debugging purposes + #texture_files = os.listdir(texture_folder_path) + #self.report({'INFO'}, "Files in texture folder:") + #for f in texture_files: + # print(f" - {f}") + + # Iterate over all materials in the Blender file + for material in bpy.data.materials: + self.report({'INFO'}, f"Processing material: {material.name}") + # Ensure the material uses nodes + if not material.use_nodes: + material.use_nodes = True + self.report({'INFO'}, f"Enabled nodes for material: {material.name}") + + # Get the node tree of the material + if material.node_tree is None: + self.report({'WARNING'}, f"Material {material.name} has no node tree.") + continue + + nodes = material.node_tree.nodes + + # Find or create an Image Texture node + image_texture_node = None + for node in nodes: + if node.type == 'TEX_IMAGE': + image_texture_node = node + break + if image_texture_node is None: + image_texture_node = nodes.new(type='ShaderNodeTexImage') + self.report({'INFO'}, f"Created new Image Texture node for material: {material.name}") + else: + self.report({'INFO'}, f"Found existing Image Texture node for material: {material.name}") + + # Construct the expected texture filename based on the material name + texture_filename = f"{texture_prefix}{material.name}{texture_suffix}.{texture_filetype}" + texture_filepath = os.path.join(texture_folder_path, texture_filename) + self.report({'INFO'}, f"Looking for texture: {texture_filepath}") + + # Check if the texture file exists + if os.path.exists(texture_filepath): + try: + # Load the image and assign it to the Image Texture node + image = bpy.data.images.load(texture_filepath) + image_texture_node.image = image + self.report({'INFO'}, f"Loaded texture: {texture_filename} for material: {material.name}") + + # Link the Image Texture node to the Base Color of the Principled BSDF shader + principled_node = None + for node in nodes: + if node.type == 'BSDF_PRINCIPLED': + principled_node = node + break + if principled_node is not None: + links = material.node_tree.links + links.new(image_texture_node.outputs['Color'], principled_node.inputs['Base Color']) + self.report({'INFO'}, f"Linked texture to Principled BSDF for material: {material.name}") + else: + self.report({'WARNING'}, f"No Principled BSDF node found for material: {material.name}") + except RuntimeError as e: + self.report({'ERROR'}, f"Failed to load image {texture_filename}: {e}") + else: + self.report({'WARNING'}, "Texture file not found for material {material.name}: {texture_filename}") + + self.report({'INFO'}, 'Texture assignment complete.') + return {"FINISHED"} \ No newline at end of file diff --git a/Blender/L1960_Tools/_Source/L1960_Tools_1_8_4/Helper.py b/Blender/L1960_Tools/_Source/L1960_Tools_1_8_4/Helper.py new file mode 100644 index 0000000..388226a --- /dev/null +++ b/Blender/L1960_Tools/_Source/L1960_Tools_1_8_4/Helper.py @@ -0,0 +1,139 @@ +import bpy +import bmesh + +### FIX MATERIALS ### + +class MESH_OT_fix_material_names(bpy.types.Operator): + """Fixes the material naming, if duplicated are present e.g. Material.001, Material.002 ...""" + + bl_idname = "mesh.fix_material_names" + bl_label = "Fixes the material naming, if duplicated are present" + bl_options = {"REGISTER", "UNDO"} + + def execute(self, context): + #Remove all duplicated materials + self.merge_duplicated_materials() + + #Merge material slots for every mesh in the scene + for obj in bpy.context.scene.objects: + if obj.type == "MESH": + self.merge_material_slots(obj) + + + self.report({'INFO'}, 'All duplicated Materials fixed') + return {"FINISHED"} + + def merge_duplicated_materials(self): + for material in bpy.data.materials: + #Remove MI for Dekogon material names + if material.name.split('_')[0] == 'MI': + material.name = material.name[3:] + #Check for .001 at end and remove + if material.name[-3:].isnumeric(): + opti_matName = material.name[:-4] + if bpy.data.materials.get(opti_matName): #check if og_mat exists + material.user_remap(bpy.data.materials.get(opti_matName)) + print("Removed Material: " + material.name) + bpy.data.materials.remove(material) + else: + material.name = opti_matName + + def merge_material_slots(self, obj): + duplicated_material_list = [] + + #create list with indexes of material slots with the same name and merge them + for og_slot in obj.material_slots: + for slot in obj.material_slots: + if slot.name == og_slot.name: + if slot.slot_index == og_slot.slot_index: + continue + if og_slot.slot_index in duplicated_material_list: + continue + duplicated_material_list.append(int(slot.slot_index)) + + #delete all material slots within list + for slot_index in sorted(duplicated_material_list, reverse=True): + obj.data.materials.pop(index = slot_index) + + +### FIX NAMING CONVENTIONS ### + +class MESH_OT_fix_naming_conventions(bpy.types.Operator): + """Changes . to _ to solve naming issues with workbench""" + + bl_idname = "mesh.fix_naming_convention" + bl_label = "Changes . to _ to solve naming issues with workbench" + bl_options = {"REGISTER", "UNDO"} + + def execute(self, context): + for obj in bpy.data.objects: + obj.name = obj.name.replace(".","_") + + self.report({'INFO'}, 'Fixed Naming') + return {"FINISHED"} + +class MESH_OT_generate_empty_for_mesh(bpy.types.Operator): + """Generates a Empty with the objects name at it´s position""" + + bl_idname = "mesh.generate_empty_for_mesh" + bl_label = "Generates a Empty with the objects name at it´s position" + bl_options = {"REGISTER", "UNDO"} + + def execute(self, context): + scene = bpy.context.scene + Selection = bpy.context.selected_objects + FilteredSelection = [obj for obj in Selection if obj.type != 'EMPTY'] + ActiveObj = bpy.context.active_object + + for obj in FilteredSelection: + oldEmpty = scene.objects.get("Socket_" + obj.name) + if oldEmpty: + oldEmpty.location = obj.location + oldEmpty.rotation_euler = obj.rotation_euler + else: + obj.select_set(True) + bpy.ops.object.empty_add(type='PLAIN_AXES', align='WORLD', location=obj.location, scale=(1, 1, 1), rotation=obj.rotation_euler) + empty = bpy.context.active_object + empty.name = "Socket_" + obj.name + + #Change back to selection and select old active + bpy.ops.object.select_all(action='DESELECT') + + self.report({'INFO'}, 'Generated Emptys for selectes Meshes in Scene') + return {"FINISHED"} + +class MESH_OT_select_face_id(bpy.types.Operator): + """Highlights Face with given ID""" + + bl_idname = "mesh.select_face_id" + bl_label = "Highlight/Select Face with given Index" + bl_options = {"REGISTER", "UNDO"} + + def execute(self, context): + EditObj = bpy.context.active_object + + face_Index = int(context.scene.face_id_field) + + if EditObj != None: + bpy.ops.object.mode_set(mode='EDIT') + bpy.ops.mesh.select_all(action='DESELECT') + bm = bmesh.from_edit_mesh(EditObj.data) + bm.faces.ensure_lookup_table() + + for area in bpy.context.screen.areas: + if area.type == 'VIEW_3D': + for space in area.spaces: + if space.type == 'VIEW_3D': + space.shading.type = 'WIREFRAME' + try: + bm.faces[face_Index].select = True + bmesh.update_edit_mesh(EditObj.data) + + self.report({'INFO'}, f'Highlighted Face with Index: {face_Index}') + return {"FINISHED"} + except IndexError: + self.report({'INFO'}, f'Index: {face_Index} out of range!') + return {"FINISHED"} + else: + self.report({'INFO'}, 'Please select a Mesh first.') + return {"FINISHED"} \ No newline at end of file diff --git a/Blender/L1960_Tools/_Source/L1960_Tools_1_8_4/MaterialToMask.py b/Blender/L1960_Tools/_Source/L1960_Tools_1_8_4/MaterialToMask.py new file mode 100644 index 0000000..7bddb6c --- /dev/null +++ b/Blender/L1960_Tools/_Source/L1960_Tools_1_8_4/MaterialToMask.py @@ -0,0 +1,227 @@ +import bpy +import bmesh + +# Callback for Enum Items +def get_uv_layers(self, context): + items = [] + obj = context.object + + if obj and obj.type == 'MESH' and obj.data.uv_layers: + for i, uv in enumerate(obj.data.uv_layers): + items.append((str(i), uv.name, f"UV Layer {i}")) + else: + items.append(("NONE", "No UVs", "No UV available within Mesh")) + + return items + +class UVEnumProperties(bpy.types.PropertyGroup): + uv_enum: bpy.props.EnumProperty(name="UV Map", description="Select UV-Layer", items=get_uv_layers, default=0) + +class MESH_OT_merge_materials_to_mask(bpy.types.Operator): + """Merges 4 Materials into one Material (Mask)""" + + bl_idname = "mesh.merge_materials_to_mask" + bl_label = "Merges 4 Materials into one Material (Mask)" + bl_options = {"REGISTER", "UNDO"} + + def execute(self, context): + scene = context.scene + arr_obj = context.selected_objects + activeObj = context.active_object + + ignore_custom = context.scene.settings_multi_ignor + island_margin_custom = context.scene.uv_island_margin_slider + + # Scale and offset for UV allignment + SCALE = 0.5 + OFFSETS = [ + (0.0, 0.5), + (0.5, 0.5), + (0.0, 0.0), + (0.5, 0.0) + ] + IGNORE = ["glass", "glas", "grass", "gras", "atlas"] + if ignore_custom.strip(): + CUSTOM_IGNORE = ignore_custom.split(",") + IGNORE.extend(CUSTOM_IGNORE) + + # No Mesh selected + if not arr_obj: + self.report({'WARNING'}, 'Select one mesh') + return {"CANCELLED"} + + # Only one Mesh selected? + if len(arr_obj) > 1: + self.report({'WARNING'}, 'Only one Mesh can be selected') + return {"CANCELLED"} + + obj = arr_obj[0] + selected_uv = context.scene.uv_enum_props.uv_enum + + # UV Maps present? + if not obj.data.uv_layers or not selected_uv: + self.report({'WARNING'}, 'No UV-Map selected') + return {"CANCELLED"} + + obj.data.uv_layers.active_index = int(selected_uv) + + skip = 0 + idx_multi = None + delete = [] + + # Loop through all Materials + for i, slot in enumerate(obj.material_slots): + + # Skip Materials in static ignore list or user ignore list + if any(str(name).lower() in slot.material.name.lower() for name in IGNORE): + self.report({'INFO'}, f'Material "{slot.material.name}" skipped.') + skip += 1 + continue + + # Switch to edit mode + bpy.ops.object.mode_set(mode='EDIT') + + # Create bmesh to work with + bm = bmesh.from_edit_mesh(obj.data) + uv_layer = bm.loops.layers.uv.active + + # Deselect all + bpy.ops.mesh.select_all(action='DESELECT') + + if slot.material: + # Select Mat slot + obj.active_material_index = i + + # Select all Faces of Mat + bpy.ops.object.material_slot_select() + + # If UV has assigned faces + if any(f.select for f in bm.faces): + # Repack UV Islands + bpy.ops.uv.select_all(action='SELECT') + bpy.ops.uv.pack_islands(margin=island_margin_custom) + + # Select Offset + group = (i - skip) % len(OFFSETS) + offset = OFFSETS[group] + + # Scale and offset UV + for f in bm.faces: + if f.select: + for loop in f.loops: + uv = loop[uv_layer].uv + uv[0] = offset[0] + uv[0] * SCALE + uv[1] = offset[1] + uv[1] * SCALE + + # Apply Changes + bmesh.update_edit_mesh(obj.data) + + # Create Texture Attributes with previous material names + match group: + case 0: + mat = bpy.data.materials.get(obj.material_slots[i].name) + mat["1. Black "] = mat.name + + # Change name and use as base to merge + mat.name = "Multi_" + mat.name + idx_multi = i + self.report({'INFO'}, f'Material "{mat.name}" created.') + continue + case 1: + mat = bpy.data.materials.get(obj.material_slots[idx_multi].name) + mat["2. Red "] = slot.material.name + case 2: + mat = bpy.data.materials.get(obj.material_slots[idx_multi].name) + mat["3. Green "] = slot.material.name + case 3: + mat = bpy.data.materials.get(obj.material_slots[idx_multi].name) + mat["4. Blue "] = slot.material.name + case _: + pass + + # Merge Material A -> B + self.merge_mat_A_to_B(obj, i, idx_multi) + + # Add Material B to delete list + delete.insert(0, i) + + # Switch to object mode + bpy.ops.object.mode_set(mode='OBJECT') + + # Delete not used materials from list + for mat in delete: + obj.active_material_index = mat + bpy.ops.object.material_slot_remove() + + # Put UV first + self.put_UV_first(obj, selected_uv) + + # Change UV names like in Reforger Tools + mesh = obj.data + uv_layers = mesh.uv_layers + for i, layer in enumerate(uv_layers): + layer.name = f"UVMap{i + 1}" + + self.report({'INFO'}, 'Merged Materials to Multitextures.') + return {"FINISHED"} + + def merge_mat_A_to_B(self, obj, mat_A, mat_B): + # check if Mat Name is index or string and convert + if type(mat_A) is str: + mat_A = bpy.data.materials.get(mat_A) + mat_A = obj.material_slots.find(mat_A) + if type(mat_B) is str: + mat_B = bpy.data.materials.get(mat_B) + mat_B = obj.material_slots.find(mat_B) + + # Change to Edit Mode + bpy.ops.object.mode_set(mode='EDIT') + bpy.ops.mesh.select_all(action='DESELECT') + + # Select all Faces from Mat B + obj.active_material_index = mat_A + bpy.ops.object.material_slot_select() + + # Select Mat A and assign Faces from Mat B + obj.active_material_index = mat_B + bpy.ops.object.material_slot_assign() # Faces from B → A + + # Switch to object mode + bpy.ops.object.mode_set(mode='OBJECT') + + def put_UV_first(self, obj, target_index): + mesh = obj.data + uv_layers = mesh.uv_layers + + if len(uv_layers) <= 1: + return + + # Sicherstellen, dass wir im Object Mode sind + if obj.mode != 'OBJECT': + bpy.ops.object.mode_set(mode='OBJECT') + + # UV-Daten + Namen sichern + uv_backup = [] + for layer in uv_layers: + uv_backup.append({ + "name": layer.name, + "data": [loop.uv.copy() for loop in layer.data] + }) + + # Neue Reihenfolge + indices = list(range(len(uv_layers))) + new_order = [i for i in indices if i != target_index] + + # Alle UV-Layer löschen (rückwärts!) + for i in range(len(uv_layers) - 1, -1, -1): + uv_layers.remove(uv_layers[i]) + + # UV-Layer neu erstellen + for idx in new_order: + info = uv_backup[idx] + new_layer = uv_layers.new(name=info["name"]) + for i, uv in enumerate(info["data"]): + new_layer.data[i].uv = uv + + # Ersten UV-Layer aktiv setzen + uv_layers.active_index = 0 \ No newline at end of file diff --git a/Blender/L1960_Tools/_Source/L1960_Tools_1_8_4/PrepareLods.py b/Blender/L1960_Tools/_Source/L1960_Tools_1_8_4/PrepareLods.py new file mode 100644 index 0000000..928f456 --- /dev/null +++ b/Blender/L1960_Tools/_Source/L1960_Tools_1_8_4/PrepareLods.py @@ -0,0 +1,42 @@ +import bpy + +### PREPARE LODS ### + +class MESH_OT_prepare_lods_decimate(bpy.types.Operator): + """Copy current Mesh and apply decimate Modifier""" + + bl_idname = "mesh.prepare_lods_decimate" + bl_label = "Copy current Mesh and apply decimate Modifier" + bl_options = {"REGISTER", "UNDO"} + + def execute(self, context): + + #Selected Mesh + obj = bpy.context.active_object + + if obj not in bpy.context.selected_objects or obj.type != "MESH": + self.report({'WARNING'}, 'Select a Mesh to continue') + return {"CANCELLED"} + + if not obj.name[:-1].endswith('LOD'): + obj.name = obj.name + '_LOD0' + + LODnumber = context.scene.lod_slider #Get from Slider + startLODcount = int(obj.name[-1]) + endLODcount = startLODcount + LODnumber + + for i in range (startLODcount + 1, endLODcount): + new_obj = obj.copy() + new_obj.data = obj.data.copy() + new_obj.name = obj.name[:-1] + str(i) + bpy.context.collection.objects.link(new_obj) + + for t in range (startLODcount, i): + newModifierName = 'LOD_Decimate_' + str(t) + new_obj.modifiers.new(type='DECIMATE', name=newModifierName) + mod = new_obj.modifiers[newModifierName] + mod.ratio = 0.49 + mod.use_collapse_triangulate = True + + self.report({'INFO'}, 'LOD´s created') + return {"FINISHED"} \ No newline at end of file diff --git a/Blender/L1960_Tools/_Source/L1960_Tools_1_8_4/_CreateColorPaletteMatrix.py b/Blender/L1960_Tools/_Source/L1960_Tools_1_8_4/_CreateColorPaletteMatrix.py new file mode 100644 index 0000000..0d4debc --- /dev/null +++ b/Blender/L1960_Tools/_Source/L1960_Tools_1_8_4/_CreateColorPaletteMatrix.py @@ -0,0 +1,30 @@ +from PIL import Image +import csv + +palettes = ["ColorPalette_01", "ColorPalette_02"] + +for palette in palettes: + # Bild öffnen (Pfad anpassen) + bild = Image.open(f"{palette}.png").convert("RGB") + + breite, hoehe = bild.size + tiles_x, tiles_y = 32, 32 + + # Auf 32x32 verkleinern (nimmt repräsentative Pixel pro Kachel) + klein = bild.resize((32, 32), Image.NEAREST) + + # CSV-Datei schreiben + with open(f"{palette}.csv", mode="w", newline="") as datei: + writer = csv.writer(datei) + writer.writerow(["norm_x", "norm_y", "r", "g", "b"]) + + for py in range(tiles_y): + for px in range(tiles_x): + # Farbe an diesem Pixel holen + r, g, b = bild.getpixel((int(px), int(py))) + + # Normalisierung [0,1] + norm_x = (px / (breite)) + 1/64 + norm_y = 1.0 - ((py / (hoehe))) - 1/64 + + writer.writerow([f"{norm_x:.6f}", f"{norm_y:.6f}", r, g, b]) diff --git a/Blender/L1960_Tools/_Source/L1960_Tools_1_8_4/__init__.py b/Blender/L1960_Tools/_Source/L1960_Tools_1_8_4/__init__.py new file mode 100644 index 0000000..e6f6bc3 --- /dev/null +++ b/Blender/L1960_Tools/_Source/L1960_Tools_1_8_4/__init__.py @@ -0,0 +1,219 @@ +bl_info = { + "name": "L1960 Tools", + "author": "Prodeath21", + "version": (1, 8, 4), + "blender": (4, 2, 0), + "location": "3D Viewport > Sidebar > 1960Life category", + "description": "Set´s up the Projection-Modifier automatically and add´s in the Emptys if not allready created.", + "category": "Object", +} + +# ---------------------------------------------- +# Import modules +# ---------------------------------------------- +if "bpy" in locals(): + import imp + imp.reload(Dekogon) + imp.reload(CubeProjection) + imp.reload(Helper) + imp.reload(PrepareLods) + imp.reload(AutoColorPalette) + imp.reload(MaterialToMask) + print("L1960 Tools: Reloaded multifiles") +else: + from . import Dekogon + from . import CubeProjection + from . import Helper + from . import PrepareLods + from . import AutoColorPalette + from . import MaterialToMask + +import bpy + +from . Dekogon import MESH_OT_group_objects_in_collections, MESH_OT_assign_textures +from . CubeProjection import MESH_OT_add_auto_cube_projection, MESH_OT_add_modifier_to_mesh +from . Helper import MESH_OT_fix_material_names, MESH_OT_fix_naming_conventions, MESH_OT_generate_empty_for_mesh, MESH_OT_select_face_id +from . PrepareLods import MESH_OT_prepare_lods_decimate +from . AutoColorPalette import MESH_OT_set_up_mlod, EnumColorPalettes +from . MaterialToMask import UVEnumProperties, MESH_OT_merge_materials_to_mask + +class L1960_PT_dekogon(bpy.types.Panel): + #where to add the panel + bl_space_type = "VIEW_3D" + bl_region_type = "UI" + + #add labels + bl_label = "1960-Life Import" + bl_category = "1960-Life" + bl_options = {'DEFAULT_CLOSED'} + + def draw(self, context): + box = self.layout.box() + # Dekogon-Import + box.label(text="Dekogon-Import") + row = box.row() + row.enabled = context.mode == 'OBJECT' + row.operator("mesh.group_objects_in_collections", text="Group to Collections") + row = box.row() + split = row.split(factor=0.5) + split.enabled = context.mode == 'OBJECT' + split.operator("mesh.assign_textures", text="Assign Textures") + split.prop(context.scene, "dekogon_file_path", text="") + row = box.row() + row.prop(context.scene, "section1", + text="Settings", + icon="TRIA_DOWN" if context.scene.section1 else "TRIA_RIGHT", + emboss=False) + if context.scene.section1: + box.prop(context.scene, "dekogon_settings_prefix", text="Prefix") + box.prop(context.scene, "dekogon_settings_suffix", text="Suffix") + box.prop(context.scene, "dekogon_settings_filetype", text="File Type") + self.layout.separator() + + box = self.layout.box() + # Americano-Import + box.label(text="Materials-to-Multi") + row = box.row() + row.enabled = context.mode == 'OBJECT' + row.operator("mesh.merge_materials_to_mask", text="Merge Materials to Mask") + row = box.row() + row.prop(context.scene, "section2", + text="Settings", + icon="TRIA_DOWN" if context.scene.section2 else "TRIA_RIGHT", + emboss=False) + if context.scene.section2: + row = box.row() + props = context.scene.uv_enum_props + row.prop(props, "uv_enum", text="Use UV") + box.prop(context.scene, "settings_multi_ignor", text="Ignore") + box.prop(context.scene, "uv_island_margin_slider", text="Island Margin") + +class L1960_PT_tools(bpy.types.Panel): + #where to add the panel + bl_space_type = "VIEW_3D" + bl_region_type = "UI" + + #add labels + bl_label = "1960-Life Tools" + bl_category = "1960-Life" + + def draw(self, context): + """define the layout of the panel""" + box = self.layout.box() + # UV-Project helper + box.label(text="UV-Projection") + row = box.row() + row.enabled = context.mode == 'OBJECT' + row.operator("mesh.add_auto_cube_projection", text="Set up Projectors") + row = box.row() + row.operator("mesh.add_modifier_to_mesh", text="Add Modifier to Mesh") + self.layout.separator() + # Helpers + box = self.layout.box() + box.label(text="Various Helper") + row = box.row() + row.enabled = context.mode == 'OBJECT' + row.operator("mesh.fix_material_names", text="Fix Material Name´s") + row = box.row() + row.operator("mesh.fix_naming_convention", text="Fix Naming Convention") + row = box.row() + row.enabled = context.mode == 'OBJECT' + row.operator("mesh.generate_empty_for_mesh", text="Generate Empty") + row = box.row() + split = row.split(factor=0.7) + split.operator("mesh.select_face_id", text="Show Face Index") + split.prop(context.scene, "face_id_field", text="") + self.layout.separator() + # Generate LODs + box = self.layout.box() + box.label(text="LOD´s") + row = box.row() + row.operator("mesh.prepare_lods_decimate", text="Create LOD´s") + box.prop(context.scene, "lod_slider", text="Amount") + box = self.layout.box() + box.prop(context.scene.color_palettes, "mlod_enum_selection", expand=True) + row = box.row() + row.enabled = context.mode == 'OBJECT' + # row.operator("mesh.set_up_mlod", text="Set up MLOD") + row.operator("mesh.set_up_mlod", text="Set up MLOD (Palette)") + self.layout.separator() + ############################### + # Enfusion Blender Tools Linked + box = self.layout.box() + box.label(text="EBT Linked") + row = box.row() + row.operator("ebt.sort_collections", text="Sort Objects") + # colliders setup is allowed in both OBJECT and EDIT mode + row = box.row() + row.operator("ebt.collider_cache_reload", icon="FILE_REFRESH", text="") + row.operator("ebt.collider_setup", text=" Colliders Setup") + # Light Setup + row = box.row() + row.operator("ebt.setup_light", text=" Light Setup") + # Update Materials + row = box.row() + col = row.column(align=True) + col.operator( + "ebt.update_enf_materials", + ) + row = box.row() + col = row.column(align=True) + col.operator("ebt.open_in_workbench") + row.prop(context.scene, "ebt_xob_path") + row = box.row() + col = row.column(align=True) + +#register the panel with blender +modules = [ L1960_PT_dekogon, + L1960_PT_tools, + MESH_OT_add_auto_cube_projection, + MESH_OT_add_modifier_to_mesh, + MESH_OT_merge_materials_to_mask, + MESH_OT_fix_material_names, + MESH_OT_group_objects_in_collections, + MESH_OT_assign_textures, + MESH_OT_fix_naming_conventions, + MESH_OT_generate_empty_for_mesh, + MESH_OT_prepare_lods_decimate, + MESH_OT_set_up_mlod, + EnumColorPalettes, + MESH_OT_select_face_id, + UVEnumProperties +] + +def register(): + for mod in modules: + bpy.utils.register_class(mod) + + bpy.types.Scene.lod_slider = bpy.props.IntProperty(name="LOD Number", default=3, min=0, max=10) + bpy.types.Scene.color_palettes = bpy.props.PointerProperty(type=EnumColorPalettes) + bpy.types.Scene.face_id_field = bpy.props.IntProperty(name="Face ID", default=0, min=0) + bpy.types.Scene.section1 = bpy.props.BoolProperty(name="Expand Section", default=False) + bpy.types.Scene.section2 = bpy.props.BoolProperty(name="Expand Section", default=False) + bpy.types.Scene.dekogon_file_path = bpy.props.StringProperty(name="Textures", description="Path to the texture folder, textures to be applied from", subtype="DIR_PATH", default="") + bpy.types.Scene.dekogon_settings_prefix = bpy.props.StringProperty(name="Prefix", default="TX") + bpy.types.Scene.dekogon_settings_suffix = bpy.props.StringProperty(name="Suffix", default="ALB") + bpy.types.Scene.dekogon_settings_filetype = bpy.props.StringProperty(name="File Type", default="tga") + bpy.types.Scene.settings_multi_ignor = bpy.props.StringProperty(name="Ignore", default="", description="Ignore material when string is in name (split by comma)") + bpy.types.Scene.uv_enum_props = bpy.props.PointerProperty(type=UVEnumProperties) + bpy.types.Scene.uv_island_margin_slider = bpy.props.FloatProperty(name="Island Margin", default=0.02, min=0.01, max=0.1) + +def unregister(): + for mod in modules: + bpy.utils.unregister_class(mod) + + del bpy.types.Scene.lod_slider + del bpy.types.Scene.color_palettes + del bpy.types.Scene.face_id_field + del bpy.types.Scene.section1 + del bpy.types.Scene.section2 + del bpy.types.Scene.dekogon_file_path + del bpy.types.Scene.dekogon_settings_prefix + del bpy.types.Scene.dekogon_settings_suffix + del bpy.types.Scene.dekogon_settings_filetype + del bpy.types.Scene.settings_multi_ignor + del bpy.types.Scene.uv_enum_props + del bpy.types.Scene.uv_island_margin_slider + +if __name__== "__main__": + register() \ No newline at end of file