From c68d02dc50db7751e3f9598c15b58cb9d5beb93d Mon Sep 17 00:00:00 2001 From: Prodeath21 Date: Fri, 3 Oct 2025 11:44:58 +0200 Subject: [PATCH] 1.8.3 L1960-Tools Release New: - Enhanced texture import for Dekogon Assets - Merge 4 Materials in Multi-Mats by one click Other fixes and tweaks --- Blender/AR_WorkbenchCustomScripts.zip | Bin 6889 -> 0 bytes .../_Release/L1960_Tools_1_8_3.zip | Bin 0 -> 71058 bytes .../L1960_Tools_1_8_3/AutoColorPalette.py | 333 ++++++ .../L1960_Tools_1_8_3/ColorPalette_01.csv | 1025 +++++++++++++++++ .../L1960_Tools_1_8_3/ColorPalette_01.png | Bin 0 -> 9972 bytes .../L1960_Tools_1_8_3/ColorPalette_02.csv | 1025 +++++++++++++++++ .../L1960_Tools_1_8_3/ColorPalette_02.png | Bin 0 -> 9295 bytes .../L1960_Tools_1_8_3/CubeProjection.py | 94 ++ .../_Source/L1960_Tools_1_8_3/Dekogon.py | 187 +++ .../_Source/L1960_Tools_1_8_3/Helper.py | 139 +++ .../L1960_Tools_1_8_3/MaterialToMask.py | 215 ++++ .../_Source/L1960_Tools_1_8_3/PrepareLods.py | 42 + .../_CreateColorPaletteMatrix.py | 30 + .../_Source/L1960_Tools_1_8_3/__init__.py | 207 ++++ 14 files changed, 3297 insertions(+) delete mode 100644 Blender/AR_WorkbenchCustomScripts.zip create mode 100644 Blender/L1960_Tools/_Release/L1960_Tools_1_8_3.zip create mode 100644 Blender/L1960_Tools/_Source/L1960_Tools_1_8_3/AutoColorPalette.py create mode 100644 Blender/L1960_Tools/_Source/L1960_Tools_1_8_3/ColorPalette_01.csv create mode 100644 Blender/L1960_Tools/_Source/L1960_Tools_1_8_3/ColorPalette_01.png create mode 100644 Blender/L1960_Tools/_Source/L1960_Tools_1_8_3/ColorPalette_02.csv create mode 100644 Blender/L1960_Tools/_Source/L1960_Tools_1_8_3/ColorPalette_02.png create mode 100644 Blender/L1960_Tools/_Source/L1960_Tools_1_8_3/CubeProjection.py create mode 100644 Blender/L1960_Tools/_Source/L1960_Tools_1_8_3/Dekogon.py create mode 100644 Blender/L1960_Tools/_Source/L1960_Tools_1_8_3/Helper.py create mode 100644 Blender/L1960_Tools/_Source/L1960_Tools_1_8_3/MaterialToMask.py create mode 100644 Blender/L1960_Tools/_Source/L1960_Tools_1_8_3/PrepareLods.py create mode 100644 Blender/L1960_Tools/_Source/L1960_Tools_1_8_3/_CreateColorPaletteMatrix.py create mode 100644 Blender/L1960_Tools/_Source/L1960_Tools_1_8_3/__init__.py diff --git a/Blender/AR_WorkbenchCustomScripts.zip b/Blender/AR_WorkbenchCustomScripts.zip deleted file mode 100644 index 87f121b944aa5b30571e652eec1a7c33ac6f2173..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6889 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 diff --git a/Blender/L1960_Tools/_Release/L1960_Tools_1_8_3.zip b/Blender/L1960_Tools/_Release/L1960_Tools_1_8_3.zip new file mode 100644 index 0000000000000000000000000000000000000000..8434b71c3e7dcd9df374cde9598b08873198042c GIT binary patch literal 71058 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≪mV<_-OQcr``5VL`lPq_1 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 D#^#&@ literal 0 HcmV?d00001 diff --git a/Blender/L1960_Tools/_Source/L1960_Tools_1_8_3/AutoColorPalette.py b/Blender/L1960_Tools/_Source/L1960_Tools_1_8_3/AutoColorPalette.py new file mode 100644 index 0000000..e9199f4 --- /dev/null +++ b/Blender/L1960_Tools/_Source/L1960_Tools_1_8_3/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_3/ColorPalette_01.csv b/Blender/L1960_Tools/_Source/L1960_Tools_1_8_3/ColorPalette_01.csv new file mode 100644 index 0000000..853a0f3 --- /dev/null +++ b/Blender/L1960_Tools/_Source/L1960_Tools_1_8_3/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_3/ColorPalette_01.png b/Blender/L1960_Tools/_Source/L1960_Tools_1_8_3/ColorPalette_01.png new file mode 100644 index 0000000000000000000000000000000000000000..a1bae62ae6e5dfc873380cc8becf0e2e9115a014 GIT binary patch literal 9972 zcmeHrc|4Ts|FPiE;%fmN-Qj^CD_e>MIsoA1<4GWT-~p6NUU&dLkVv4T3mh#< zxAU1s@M`UQ#~>N158a-+2+I=a{YFKm4^T?Klmw*|TgB*y-tgk)=5E@{3l`auyN0P= zNKVak=;Kx`Ejo@8Sy=nAzPpr1nOrvg?aK50Ho<^N=R=3Je{^n5W~x$yg|;R+T7pq| zi*g);+uNA$JKBbM8($J4&MC%>Ciz#Nq~dV?Y2np=5D}MZHr0g zlKRHU*Lzg5>b_~jB53L&CtCOLn(&khqj}pbhN{`TTo`ssI?ob1aaATSCoyqyW`4J% zx}czzxQsRf6&yOFwV^e)&%jS)x`#m|9dso=og!}VanyI>* z8<+dasGUZ~RPYu#s_IuGd{n(BJ|1uK^OMQQ>!_^OYOL(M-?6~PH>8l)?!Gh2=p~f* zeRW)7Ep-b%V$+#GQK z!=+0mT)EGc)4qS}*_&sg-aFP3yb$nU_&lote2m8@hzjNTM!jX#%=RN_@B5JlM-Ca= z*+fHml_n%2xA&#gThw$-pg$hN=6ZHy)M6THt51rk)4jU_&D*ookes;H#jci95tZIS zNAG$3cowHrCnp>>H{@vXT?JI>t6%!5<&F?ZtfKUOCxrTzJAp33EdOk zg=q4$xsDKNo$V?i6TT+%un)e=epYrJJ7aBgfwb{e(Q1@9*4Mn)G`7T2mNRF9@?VuI z$@Sk+bQ7`N-`rt*_noEID`_BlMgSInd$l$^Ejt~|SoJZPnZb&hSp6Sg! zevh5QV<3EFRfF@;+s*d){f@o}esj^S;7_v#J52Q}rb)h`OWaAjO5`?8QYqJ~*kOkV zgN37|kFlkd9|Go|uBO*kZe$DU0L74qI%4bW8@+aQZ#R)~xA8+}m$$CIchh%1@t$RK z<7TSKa#+i`(?(bGiJrmQ z6En=h#7skw95JthU(-&dSBpns`}mIX)cy2YvJrjNA~OEM7|n6#`{`{(HHgf$v!N{Q@Cg9--{2JyGRHS zkNQSUy?d2z3M*+Ero;{zB95;5h48%RcaW&vem$3GJHo8UlP8)|i^(X0zb|J<^mlAi z{u;G8uDHi?n$%TaviJ<~##2(iH|lK?fX;FxW@_pRIO`Qrp%Y^JLdCg2+12`~!hoOc6gC#_ps#yJCnDn#yVg3?antreH{nIq= zC~*!Urj&I~S$pn$zjmeqjwRiTGrWv*qDrr%Hm8r#8vosf) zoiiUa1ED7sbr$-ZISxtk4+>jatFS!gedj?J35qbg&%P0Tm~^IruDwYsaaPB!EHpYL zjw>amax?U^#6Vc5AnOzBSkO)XuzETw91bt6?+(vDt^M$>O=-C##dsrmP{2QdPn<3M z^_;NXXUQ0aL+D3|oX%Ubhqak>5;9^(zvOb8sb3cTxS);Zui}f#3)gfF6tZ*zt9IHUYAayZp{j|vLs6JIeiZ=_jtESih@=-r|w~8^C z{)JoO16)JCN=Bo`NVdKiuB7$RbQygu4rx=s=6FKOr!pD7(|gxn$^P~6BO)^WzS%|^ z&M=N(SB}SGQ;n2M($M0GZo0!6a{68N(XxsngR>S#GlU1uxz;pSobC%9)A(&iIXP@2 z5lPXCWPS&Hes^=Ka*ktE*Jos>NLJc5#-(`hT>X%Fw^&z(#?dbycUF>n#@I>&cEsrh zu z6`FCy7p>=D%Y#P}z}i({cO}(lpbhM&r)(#vxD4qqey1QL|wO;sj19((xinbx-mUIAX)zOswZ{gu+{r< z5lwypQO|WI3nR@Jj4_ekAz#d<)DTtaw*=5reNor7o$iSQNDW`jWEB@wwvCaH?P=uc zWndHZFW+@iQQk4)<4r;pUNLmw8a#Vg)o?+qZx-^V-kqEzKBGSS?%Y>c%$4*}%_~l~ zZOW&8+pZl$Yo-(?`Nvvu1!L*ES*H!=KPHBFSf1A(KMrE+MIeMA^L_!^#v)l{^a?Jb zIbB`d=iJW69>!Da?7Sa7N;8_-WW+UnWYHDXj{!eCJ;J_Z7~K^@027c_0S4BMirb>~ zRzfXFL7fgw>5d8J&#sMp5uNW?XM=}sXxih86HX~g)WKNLwVB^kG*~Z>&{=mxR%*Z4 za-R%UGh(4Pf^;ye-4nE#H}JCR8NF$DIxjY2B2kA)gW{HA*oe^s*hO>==g1Vlmw^yj z5dKV|pTx!uNtsTFN+~sA2ZJm{9WgxpTh)%!>P9S1aGYb!%R!zT?j9>bYk+rKcJ!W`(Mk(NPJ5Z?ah%NJb}>Zruec z%JVsrIyOEjl^kA6$Q8**X9!&|4=!Z zV;;u(zFi8kuy}*)Sa{bwtXl!b+cn38boGypGJ2rVE0Y&;LZw$86nXgx^u`+>0_XNE ztH#GiJ|Y5PO!@i=8tYOCFYvS1L0kCDrj<{81qEVN^x4FE2PDJEy6b}STlsOgw;Wco z9-IT~wy3WXGFxc>GDU?H!`@_iTJF zE)NlQ!!Ml_v3e|wYw}T!h2GuNuJf#5_}L+z3C%1&MYl4$6z1G70yZdT;h{aGvklWf9ps@VDzv80>{FsjeHvDT{s*r0RH_O5=e!PA?dl zvSj5p)RwuheQ$ZTf|LV#EjSYDGorN}NJf}8tE3oPHq7~qi@ahINilmtbRE)ekitVw$IgUI zpEu}nt)Xy4b(1T9w2HZ&4=B5}jT}g}p6TJKE7J#FNQ=CzmQbcMwAOb?+thF^(ES2e zXmEaVUGXUTx5d>=YxPnAPmhq-OZ7V{Xb-O4s8EZ<(7SknQ zX?f&LMkYvstMTV>fItRkT>RYF`BbP%fQ4-u+lR~*skFP)#0=-Va22MO*8Mk6#cqdM zoD;iI{9_QGXA$vsAvUcZHY>0wP>*#?})La`)_3D$upr@w!FHWu_vAHC?=?OvI4S{d`aRkcil8$&K#nLb>$%(2Q{L*nTT!R|*0dbwbZsj1Juyx+UP3%Eob@Cu#r%2%>(^6Kr!6SLYbyz; zAL5NTpVaoQ>JVuwy?BxD+}HYtWQIbz}M8t=*lRkcKs_4G_WacnVy>yD=YFnAXtSp~S<+y(>?aVo&`Fk`T>mnPnos2Ajew+u3| z!UnlxkvO30IdWhc!uw)niN<*PQB;6HT0h{A@sYfYjsJuv z`~J=XjSsm%w3nQ`ELe_2lKZQNFGbs*2J-uW{zngAE81HdISah6r=JfNukDW~Q^fuX zfy4gk@8##?@iQG9Ru1ohC(%rOX;J0>7E)K=*z8Y_0}5P-B(I-dG_wC@Ng)#cL)PEM zcF^-Poxcu*=Kd${->m=0{iiX_%GemC<%#t>7@oeC3h*F43g?L>;!r`OtDvG@Zh8n`TxhJ&L$zJQSkJP3oq zz(7z8ULJ%{M96~_72s$^ECC6IW59obF!dqQREhTZ>!=Q(a5N}+CZ84v7Il zVGs-mqW}ei5O|mZm_UHy;ox6TI4nxX(}#qnm6J$9yWr)#$Syx)91xCDH`7-ELS%oL z{%kSxKvM`b2ihDUl5w5^zW*_{B9icy6!Za~@`^CHA`~VsuPBd@hd?3!F|xt?_|mj^ zfGQ7`RrrN`P#6>~9U8Uh1Etac{>T%h>4Qg8JbkP@Jv~%_2SWfHc>WYPK>1f$^oYJR zi%SQZ|6TQ#c<*0Vzb1hP@n;tR@Kd-bH1<~zU$j3S_cIX9?^hSr6-{=*(`NYZlKP{a z_&<~j3CGGq(MUK5gCsyeP&5P$LSxYiAOaXdOB(^hW6-}U{wKPxCxH@x_Q9*W&@!cE zLzB?YYygtKlPUH0(FC~S510Z&pdhdU2m-Z&D4-xP6j&Z8_uo$s2PeqWl#2zykZ_uW zpacvE4ad^-jZsv zJRAfCqmdvq5-ksc!{l)UydoBjfe`*)jsN57(b7YLz_j!bC@2giulPrL%5n#HcRA2X@!$OXK8yaFApn4XgZv|Y|E23+y8aOZ z|H$}Xb^S}%KVsk?8UL%U|7Ucu|7Wv`C)1u^187@OL+*EE+BTLMW2mb|w}0@x(^_(i z*23ncXXi`X`#wE5=wEo=!_gX9DEh|QEc0yiJfI`O3Cc7(7O=jSx|QAwn3Nzix*L^ucvcPXrzZwgmy6Mz-aQY7`||lgcmMrqeD; zb;Xz0Qln(z_;s)IOV zJ=^AIEb!E*oJy$l`57@KKOM4OO@foXv=Q%8?&RYd;S*<+5sz0GZ{}*9-kN*3SHmMP zaZE2DHu&E6K;97*O_gQGk72j+My{STT5>IKJG7O{8T%-#{=LhHf3JVT$hQpZ6M}XM z#1NO=DamiE%(e~J3|mw4fNzG3ocqpy)w)(97zDl4L7wrcQj|?bd#6RErMcW@OFHU= z-&2YO!vPV9CoX$=O4OrtGA);p%bCG#K3$(Ly_*s+?T~ZgM#>T;TUN>VMpyBt(@jy- z%?=dW=gF&u3(}khbw>q0W$dDN#V7e%f>k07?QBd&*v0&S?J`B{ox+*&nn9 z$H9yUl|%bo)z`Dwo{W|FEl^tTGK)91?4GKxTk(^ai6 zKaak$!OkduPh)TG+8?_L6b^Z!u@#XPP=40!$fcrPCGHbk%|g|OlP1gCUiuH|UDqEw z-#7@-O|GyL9(5u`s7vfnIT^1cy-!j&Ntk;%qwR!p0NRMP_-uC^5-S|LHYD#ut*$CM z)!lXX)dk_&-ZN1Z5mE4puV7^THq|J@D0k)u?%N?wJJ+^vuO8-{VA(L)&0x}zn8X^r z6;(WWYRF2=gmNS}O@0vO@TkJJvfUwEzTv5=OE=?AZw1!WGsG^_bCYXGFIA}djq=0u zk!p{>Qjt2XdLp*Iare3kKcOwleUmkByM-}JSPM7=|3<}>>OLN=nCZPZDRx~KqyHrO z!-`O|JoC#v#1zl-p1G0OoZ_l`ZDVyK7B?1k%JJmnTcD1v}C$DfA|( z8ti^$i;nEGkBT~G9ZQ|4#M^4HyQ#pkK+zD}noRH1AyK*!2hbnu`Kn3kU#zOzJtr}^~ zctxT%s#0X63p;cD*-q&O7t`tB`Lxrz{I$0%PxdJwxx1AL8kG6`Gc8;*BiS#z#;6vH zst7I0yu{RXvBg$Zqd9ImmQ`F{kgN*tdGuIp`^J%oaT%bQcFLlM0=(u^{5wol1bo|D z$s^8ak$*h?%AL>fNpf9djn3GYc=CghMX-bQCVoRg9B}DEKLrR3FBaW?lv8JagzcPF z4n)Bm#LN+sXHaj%^xF?9!h#^kbFze!fq`fWG!N` zClh23E?b*me^v~e^c*W~Mr5cMK2VZ|++Q9}K)H+=$Hwh5K_!Y<-RLTn zHFq43&6zF3Q(LVOV=|8?6KvtyF13yCgpPdcV^JD~NQ{KL6|8mFj07h6+Vvy_5XF1O z&M>xbYrXNo@gA;0C1m8Jeg0lW-hFI{4yd`7;A~xzo!=M1rOEu}X-qZ6LUAA|K+sxZ z$iDZ95`U?Ezd>hvX_-y_v(I}~BJLvy38bC7F>AV8QF#58{?pcv^3%Vb-zdrXQvF#C zHfT?u?e?s&*li^H2ETc4xufCPkgap!uc5|op`4+2+6+tYZ zG-(1#7ZntcFX*Yy_x?He-uM1G$+MHa*P3(8HO882ugsl98!HoT4lxb@0Kjc#YG_OU z2JRhf4D`=!k);B9yGaPvk!Fhv1o}}aWDjo=kQVGm0+NC}$N)glaM5KasvMffa5p#! zt-z3az=qe|n_<4}?Q-ad-5*NBKt+Vf9#n`UZ9mjkC;qCc_=32$-VE1`@l4Xq7;-|ehz{m2a$ zz~5P_Tz%;6+<3rCY0$eo4x37esI+-)gaGv(|0=S0NI0Uwr=J$s@TBjle?_qHy4I&h z@0P8lP$o@Zew4jyl2M1tUxQ%LZB+67Yjc^eXoA~cb`~yu6e~StoBdiQwL2{^F=Jcj z2%m30BT^x}U3>oNcQxIlHyHjDUTkFfxAf4j)=<^)%pUV7Oul$1qBPR_v9O*qm$cnA z&*7^kN$m~JF!e)K2IPhos?w{tdj*bAg;hH|vw?Q3kexaDBG%4AJ6^*73Hp+n?V^0v zytztKmaTXFA!l>7xB{ueLfjxA%Q7uZxFBX?7;aHf5NI2HY7? zT)lF-_=?+=fcm$WZq-bjzv$o;aQAh?J6(@Q*UyZThQ`k5=q@n@PMIm@Q9pW=L^v$j z4Mv3R>b>4B@jRniB>pt;b))l>Apuv~1uUF{tRAA`ie&)!l)tqLODTR*Mz)4G%ZTbJ zy!H-0mcsFH33PDx*daHH(Xpo83g4>kypQBvulG6T8}S#n0>{D~?#hc^ZNO6wsFYdX z*y4$P?(L{>+48Vsdv_B{RLQlJ=4$~kw@ma;xFoMeyMLlSoKYz zZKafX-wmrXmwM?cs{^AXo9J*9xFk=Ng3_EpvKo{6UUx8vS7|Sdot_`_Hlsq zOr9)()tC9ci$8!cn?E|*EO|?I}A+{^T8rrTc9k4aWV!Cw_Qb;~76PUs@hJZy3d9Yy%*qig=x zbic)N^qOUA^oh?Ot5WkDJT8`bxB%~R>Z7dWklWGW?5nJ$O!tQX=Uvi2*M4X=RRvqG z_^D03TH?Js-TF~p_s;R)QGuk$32~v)aoUVl(VTfHF!9yek;ndm;_~9BdB5EFUbvCj zr4^R8s6URCeh%Q=E~!77^jzxjiO7Qq*`aIU(baW1b4MV7$a!yFha&~-ZULak@A@V$ zW;WvukCw9~he(8WJH{*Au4A%za)G}@uf;!-mJ91oob1NL7YMARCQpB3BF5-?$p%?n zXnq1yf4-h`FaC&#vQA`y-9>(tR8e%SU2Yd=i*#?Q(QRdmo;G#&PGobhfP3)qTZTOf zlzd#SmXB_{1?pz#S*AW4CP5vmTQ&PZ=}z}<>d2Az)pgZXEX{d0XY^09goRHui)?uE zc$y;vuZ>Qo%j`2byaez)rv~I!6buD8U=@X&iKm&YP`uskcF{_i6)NXHh_J61eT8Ll zJ(Sz@e&S*ESwil7z5n86)tXF>gzLJF7d(ven(pS&)>DrW6hGdI>|#@TW0fbnv<;XX zfiMXe$_{t%l_+GIeIG4Sd1*pC^zz=F`NCAOsQBRtrgx>YvXZ5cGw)Yj<@o`Hil6zN zS<}*)3hp$OBaYi04T=eKGGZ5NP$KanI-!@PB^CBhSO_EqbusZYq^o1>-qBs6pGmo*e`L|yL^7hr)qN{E(wx2Bbi=lKEGHPexBNE15SC}F%mkx z@kNvGZHyQ=%G>PWYQ{F&QPP^zeEk%wnfQ`Hf#CN}o;rr~C{`1`!}ZeFcl=|Hj?1cv zAr6fJptd6_abhM{!1!CMu1yp>PS1nj)%{|!W{m>}Q;e1qNI6(gn?rtoLcV*COD59)A(vZcl?voc=k5ig>DnCkV zUggUn4}&Qk@gg>^JickC6f-j7uj+hyUXfSB*>-N^&4t+_tu8Aw5Btk%HyvLp+H+mC ztC?hJ$yR>T>RZz&zt5^R4QZb>tlEG~WwIC(KNr8mRwP%V1hCT7(a!=7gjn8mQp{?} ztx}(hwNm1f4i2Ab>Y=uYv1NZ?rgm3pV#wX~F8A_zu(qB6%LYla{-e#;Bp$ph!Jp&d z(~TD31{B#}T0gz7r&x8nPp~u6VzR#c9@Fb4k$OXDa60<~n}|4Ozq8!d4UQ=y2ZhSJ z<#Q&uxzspNgAEfg^L708QHujwM&A@a$OTwD#51yV+C5pGT_k$w7{|FzFfSJEQ)g3t z0=?lQ$S-d2j5=j|q7DJQM9fMh1Td*M5NvHOkm8QsHD$-%eX~&>jp{A1wcGy@fSdt{ zauw`22(2$q)Ktsq4LtUIU{vQ-QToP@+%(8_`{rVWkhEi*gtmT9UQ@7|Usrm-3R}TM zh(ntjH-~q>cr0)9?KW4z5FpCtiOl)o>Ic}Wh>n5^Q>#&5%7DE$*U9qyR(^trB?d*# z4l`;mxWQbTu!-Xd-PFyH&NUDoo6l`(deMmi-#qx9iOr+GltI2I_9~8fzSZHa>HdL< zWc4z0g(<&hjO%A(zZn#RW>aib8H$ApRT$m3!<&q;%aY;UmU?OD%k{*orwC^jqBdT? zSbLT*Mg$ISaqQ1!tX;cOi)HFE=RYXMQN>`gol7E=L2ktX z1;azh^M-?-rN{T~ilpD(f#M)#|?r z%@ATz7qo84YE{oJ%s?HIh%X30v7PXJX{Ig9>OWb;Tb*+HumsbG0bT0#qa=4BkgO;* zN9_Fkg+zrZV5Vw;iZwW*qn*MYOm z`&*|s?H5b~g&%(F5QplwmaB~7U8FC5>%onFmSP#weKZy5`rufi=%7zUf10gwJ1*FY)5%rYcS5p+Y`d$A`Y>*mam*7~_&eg<(DLCcs+uF@qBIm?ZB8Ga;wo77(Ma`A>l zN-~Hx3>)1lz`(W>Szk@2``NwgURXN#AZ0ox~eYl#VQk@&{BW-TQdMDLw}B!n3#$8_(H?Hh&?v zk+bf+V|~9+NyS+=MZ8wEItCvd_v##fEl)=NopV$jm{PGsE#lKd$K(-}7n^R?Cda@cl@g2J&TJBAY` zUWb_^G+cIVGFo-|=XGSt3cS20r_U)TV^mkGGOV6`Jg&kQpBP`*bxWILYW$*6`}g?H zOIPkoL0LnqCF6fgV_heU8Z{oZnt!KN#ATF9smfZWRWpgd^e<1#z6dJq#J>);3m4Mm zNvwbB#C_#V^*k-s08(>xNA^-01K9|Z-S=qOM0hT@dVEJkkpCEK=z@D8)0ToL;jubvY@eAuHL}*o zFdIT+Ux>SNu-J9uB;qYgvuS2lCIGN6*2BQS#>~Lr_mYZUNaciO95U^)5sKR_PU2PJ zIKy|k$L6{--^D4VV`|Z{FYMi4cgz%n-Cv{^HljGHm|3NgkFg$bb2)f|S#NdUlsZbe z*)(xZAyybF**JQBH+Oe#+<#yGQC#_31bgXKQsER7dhPiBv#tZIQgM97SbTA=DVRLr zbaLaBMZkecr}40e!N?0p(FwuCxy!ze-QwK?mKJlZ))GW{GwH*MJmNIHDU+(F>g}i1 zF>0&5H!{qg39=?Wz_UI**lQkVu4N!$i%tC$Tlth@4%Fva^w4=@2Fx{c_oBv-N2+w1 zyj*$=nToaLcv7@IpQUz<8Cbi8Q-an{z#Jb5WO62(t zene_ow_p8v<;d5KS|6k}U>ELJba&@93uMbIr0rI0T4aaM#8mUG$7k=q=Yf1Gw1}HA z4R_Yh2ejr5Am2w$9={Rs?E3Kqi4tDjIP%?4MhOW9L8B+G8$p4TxzQg>9?w=-dyS}1 z{g%1P0RWys4|!xJbblfR$AI+ zfF49`83%+V#L~}zV_=V{8qLe}kZ3Y0J3N zXnq(lI503!JrJ%=p}K*gXfzrOfq`K#5ZwagAM8uR1%Z71W%nR{VHlG92~-b1ng_)f zxQB_uQvzt(GBWgj;P2z}@w2r21K!vFHx=l5fP-*;V5m9-?BfIetA{_$=nNg?w*mb} z4}UEEQ32SN0_n_mT(L_y{CIJOPk>OB~1`b64p%HLR5Ly#QMr$CDnh+HHFA&yL4|-PO zy#G3?Jt!g_3Q5+4Ls1Yi2o5L1K^iCo9aIAW0YPvm1c`tqkznv&P(%X8m_qfz(WleH z2j@lt`}w;4jIk#;M$g7fTLz{M`Lo5w8%HD49q4Po!)}JPqv7`Sgd!1| zNDTy31ByVvVG!h>M)oACKRp-sP@xcY_%GzWiNVn6(51!gWhx!urw5%4#(+w~(I`|b zh2pI(vo|QU@AS05dw1mDb5#rczq0w4!C!9S^jZJaM&BCfI}P}ct>(9M*joVq#n*4E z=)V|&4*hSCf28lfa{VjUKT_Zy8ULGI|H}1`6!=HR|7O?!Gr2haELKUr^xv<6^iuSZ zg*u8}#|70Cqo9Cx3eF+qHM>dqgQE(i>T6W|l^*AK3Ttfs{2< zW4P&#!e)kgSkp(A*&}H)5BUwPg_EDn_AaK`!dmJ-!?xb%1YdbWA*EScJ4oHARSc_QFGE`l5yV6JY;`gKjD(;P&?<02WH_}+rR(U*ct2+3DRdx}V5{2txl`z@HJp4h;z!0@r{JA5Hr}kO@Yeegz{$y`oC7}|oa~;u zm-1dwauUGZ%2<%V<2orDb0KFvCvP*6cU93fENI72iOJ-6>BR9*hZImMipIplFrH zKA7Ks!g`$}y_+mldi1$y%MIpau7^%@2ZYsEJ72d~p61nM;dN7@rPcCD)b=)V4mrp$ zw!&OXjzu#?X#+AiQ)Oz7d(|o^P)jI0lfPOraJUVnl%Y#Awb-)rLb|4sqeG z{DvoLF2tU5cMwUkH%*xhaj~lW?1x`10UfPf*@v-k<-4(=xcjO^b4^>B>+wo5Zs-r)&v*_oC#RqF2B z_oV6HP^&~-;a2Dr&fGs!!yzD0&c>IbMBI0*CD+~?ziy$&~!~MJ4tdjo7g4xJmhRU;Lt*$nG1kVVYV^#774n`j+7Q!+E3NIz+kJEu=Ux1o*H%`|jiwdd#@VTsZ zLu|b!p9}8b`{UR=)Y<|1AzIt7?S$gGaqN+x#ZxUxnjSDgGY++iFD!CZKeV0+=f`m{ z$kB*=1yF;xC;1!*^{N_Ngu0%`DqUmmgg2V6=(Rkn(mMxv%Jl;SmUnk3KjfVFVv_6% z7gB+Ur^LDz73Xcww(g%%QMK9%Gfb#KtIF$k)x&VJH;vy}CaXC4puQf#*7>zGsJW3- z@VG3MheaIrqAU+@MXCsNk6D%#r3RhSCr3Tlcv^1m9e9js6&aYL2f+8$4=ahj^jx#Y zw;aPx_#Woh3o11e=M>e{)TwOfY$6F|D4GtaMM5HP)j%z33@x@k+`iT^(UWcjE98)Q zTXz)5zun4Qe%$!MWBE)wSc?IRVb7?&&%h^8n1OpqMU7PaOs_zb%yPtqlX$r?{>9}@ zlO7h8?jwZ^Z!RqFYos)>_V^KQp{9Io9#fzmZk_jQ7r>Qx)k4>#A4=kCG5W`(*T~n&Nt{%~)^NSg$k(;CwT7~KpN%h; nFYow_Xjr-oS-uQf+2vg~gFj1*P^Rx00Dzg1m0^|ssp$U!d!}EZ literal 0 HcmV?d00001 diff --git a/Blender/L1960_Tools/_Source/L1960_Tools_1_8_3/CubeProjection.py b/Blender/L1960_Tools/_Source/L1960_Tools_1_8_3/CubeProjection.py new file mode 100644 index 0000000..5e6ca15 --- /dev/null +++ b/Blender/L1960_Tools/_Source/L1960_Tools_1_8_3/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_3/Dekogon.py b/Blender/L1960_Tools/_Source/L1960_Tools_1_8_3/Dekogon.py new file mode 100644 index 0000000..92688b1 --- /dev/null +++ b/Blender/L1960_Tools/_Source/L1960_Tools_1_8_3/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_3/Helper.py b/Blender/L1960_Tools/_Source/L1960_Tools_1_8_3/Helper.py new file mode 100644 index 0000000..388226a --- /dev/null +++ b/Blender/L1960_Tools/_Source/L1960_Tools_1_8_3/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_3/MaterialToMask.py b/Blender/L1960_Tools/_Source/L1960_Tools_1_8_3/MaterialToMask.py new file mode 100644 index 0000000..d5e614f --- /dev/null +++ b/Blender/L1960_Tools/_Source/L1960_Tools_1_8_3/MaterialToMask.py @@ -0,0 +1,215 @@ +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"] + ignore_custom.split(",") + + # 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(name 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["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["Red "] = slot.material.name + case 2: + mat = bpy.data.materials.get(obj.material_slots[idx_multi].name) + mat["Green "] = slot.material.name + case 3: + mat = bpy.data.materials.get(obj.material_slots[idx_multi].name) + mat["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: + # Transform UV-Layers to dict + uv_data_dict = {i: [loop_uv.uv.copy() for loop_uv in layer.data] for i, layer in enumerate(uv_layers)} + + # Order: target_index -> first + indices = list(range(len(uv_layers))) + new_order = [target_index] + [i for i in indices if i != target_index] + + # Delete all UV-layers + while len(uv_layers) > 0: + uv_layers.remove(uv_layers[0]) + + # write new order of UV´s + new_layers = [] + for old_idx in new_order: + new_layer = uv_layers.new(name=f"Temp_{old_idx}") # temp Name + old_data = uv_data_dict[old_idx] + for j, loop_uv in enumerate(old_data): + new_layer.data[j].uv = loop_uv + new_layers.append(new_layer) + + # Set active UV + uv_layers.active_index = 0 \ No newline at end of file diff --git a/Blender/L1960_Tools/_Source/L1960_Tools_1_8_3/PrepareLods.py b/Blender/L1960_Tools/_Source/L1960_Tools_1_8_3/PrepareLods.py new file mode 100644 index 0000000..928f456 --- /dev/null +++ b/Blender/L1960_Tools/_Source/L1960_Tools_1_8_3/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_3/_CreateColorPaletteMatrix.py b/Blender/L1960_Tools/_Source/L1960_Tools_1_8_3/_CreateColorPaletteMatrix.py new file mode 100644 index 0000000..0d4debc --- /dev/null +++ b/Blender/L1960_Tools/_Source/L1960_Tools_1_8_3/_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_3/__init__.py b/Blender/L1960_Tools/_Source/L1960_Tools_1_8_3/__init__.py new file mode 100644 index 0000000..57a5b6b --- /dev/null +++ b/Blender/L1960_Tools/_Source/L1960_Tools_1_8_3/__init__.py @@ -0,0 +1,207 @@ +bl_info = { + "name": "L1960 Tools", + "author": "Prodeath21", + "version": (1, 8, 3), + "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 # MESH_OT_bake_basic_mlod, +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.operator("mesh.group_objects_in_collections", text="Group to Collections") + row = box.row() + split = row.split(factor=0.5) + 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.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.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.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.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.operator("mesh.set_up_mlod", text="Set up MLOD") + row = box.row() + row.operator("mesh.set_up_mlod", text="Generate MLOD (Palette)") + self.layout.separator() + ############################### + # Enfusion Blender Tools Linked + box = self.layout.box() + box.label(text="EBT Linked") + row = box.row() + row.operator("view3d.ebt_sort", text="Sort Objects") + # colliders setup is allowed in both OBJECT and EDIT mode + row = box.row() + row.operator("view3d.ebt_colliders_setup", text=" Colliders Setup") + row = box.row() + # Light Setup + row.operator("view3d.ebt_setup_light", text=" Light Setup") + row = box.row() + col = row.column(align=True) + # Update Materials + col.operator("scene.ebt_update_enf_materials",) + 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_bake_basic_mlod, + 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