Compare commits

..

4 Commits

Author SHA1 Message Date
6d564c26bc 1.8.4 Hotfix 2026-01-11 14:51:13 +01:00
d02e72dd80 Blender Addon 1.8.4
Compatible with Enfusion Tools 2025.09
2026-01-11 01:00:55 +01:00
Killergnom
1d23946c1d Added new Tool to convert OpenGL to DirectX 2025-10-13 21:58:44 +02:00
cde365759a 1960Tools_1_8_3 hot fix
Script error with Merge Materials to Mask function
2025-10-04 20:14:27 +02:00
34 changed files with 42455 additions and 1 deletions

Binary file not shown.

View File

@@ -151,7 +151,7 @@ class MESH_OT_merge_materials_to_mask(bpy.types.Operator):
bpy.ops.object.material_slot_remove() bpy.ops.object.material_slot_remove()
# Put UV first # Put UV first
self.put_UV_first(obj, selected_uv) self.put_UV_first(obj, int(selected_uv))
# Change UV names like in Reforger Tools # Change UV names like in Reforger Tools
mesh = obj.data mesh = obj.data
@@ -197,6 +197,8 @@ class MESH_OT_merge_materials_to_mask(bpy.types.Operator):
# Order: target_index -> first # Order: target_index -> first
indices = list(range(len(uv_layers))) indices = list(range(len(uv_layers)))
new_order = [target_index] + [i for i in indices if i != target_index] new_order = [target_index] + [i for i in indices if i != target_index]
print(new_order)
# Delete all UV-layers # Delete all UV-layers
while len(uv_layers) > 0: while len(uv_layers) > 0:

View File

@@ -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 0255 Werte umwandeln
# rgb_255 = [round(c * 255) for c in pixel][:3]
# colors.append({
# "face": poly.index,
# "rgb": rgb_255
# })
# # print(colors[-1]) # -> [{'face': <BMFace(0x000002B417086A30), index=0, totverts=4>, '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

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

View File

@@ -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"}

View File

@@ -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"}

View File

@@ -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"}

View File

@@ -0,0 +1,244 @@
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="MASK UV Map", description="Select Mask 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
ts = scene.tool_settings
arr_obj = context.selected_objects
activeObj = context.active_object
# Get all inputs from user
selected_uv = context.scene.settings_uv_enum_props.uv_enum
ignore_custom = context.scene.settings_multi_ignor
mat_nameing = context.scene.settings_mat_nameing
island_margin_custom = context.scene.settings_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():
IGNORE.extend(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]
# 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)
# Deactivate uv Select Sync in UV Editor. Makes Problems
old_ts_state = ts.use_uv_select_sync
ts.use_uv_select_sync = False
skip = 0
idx_multi = None
idx_multi_name = 1
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 = str(mat_nameing).replace("$MeshName", obj.name.replace("L1960_", "").replace("KB3D_AMC_", "")) + "_" + str(idx_multi_name)
idx_multi_name += 1
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}"
# Activate Select Sync in UV Editor
ts.use_uv_select_sync = old_ts_state
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):
target_index = int(target_index)
mesh = obj.data
uv_layers = mesh.uv_layers
if target_index < 0 or target_index >= len(uv_layers):
return
if len(uv_layers) <= 1:
return
# Sicherstellen, dass wir im Object Mode sind
if obj.mode != 'OBJECT':
bpy.ops.object.mode_set(mode='OBJECT')
# Backup aller UV-Layer
uv_backup = []
for layer in uv_layers:
uv_backup.append({
"name": layer.name,
"data": [loop.uv.copy() for loop in layer.data]
})
# Neue Reihenfolge: target_index zuerst
new_order = [target_index] + [
i for i in range(len(uv_layers)) 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 & render setzen
uv_layers.active_index = 0
uv_layers[0].active_render = True

View File

@@ -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"}

View File

@@ -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])

View File

@@ -0,0 +1,222 @@
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.settings_uv_enum_props
row.prop(props, "uv_enum", text="UV Mask")
box.prop(context.scene, "settings_multi_ignor", text="Ignore")
box.prop(context.scene, "settings_mat_nameing", text="Naming")
box.prop(context.scene, "settings_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_mat_nameing = bpy.props.StringProperty(name="Naming", default="Multi_$MeshName", description="Naming for new multi materials, use $MeshName as placeholder")
bpy.types.Scene.settings_multi_ignor = bpy.props.StringProperty(name="Ignore", default="", description="Ignore material when string is in name (split by comma) | Default: grass, glass, atlas")
bpy.types.Scene.settings_uv_enum_props = bpy.props.PointerProperty(type=UVEnumProperties)
bpy.types.Scene.settings_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_mat_nameing
del bpy.types.Scene.settings_multi_ignor
del bpy.types.Scene.settings_uv_enum_props
del bpy.types.Scene.settings_uv_island_margin_slider
if __name__== "__main__":
register()

View File

@@ -0,0 +1 @@
python3 -m PyInstaller -F --icon=./convertogldx.ico -c ./convertogldx.py

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,320 @@
('E:\\Arma Reforger '
'Work\\1960-utils\\Texturing\\ConvertOGLDX\\dist\\convertogldx.exe',
True,
False,
False,
['E:\\Arma Reforger '
'Work\\1960-utils\\Texturing\\ConvertOGLDX\\convertogldx.ico'],
None,
False,
False,
b'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n<assembly xmlns='
b'"urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">\n <trustInfo x'
b'mlns="urn:schemas-microsoft-com:asm.v3">\n <security>\n <requested'
b'Privileges>\n <requestedExecutionLevel level="asInvoker" uiAccess='
b'"false"/>\n </requestedPrivileges>\n </security>\n </trustInfo>\n '
b'<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">\n <'
b'application>\n <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f'
b'0}"/>\n <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>\n '
b' <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>\n <s'
b'upportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>\n <supporte'
b'dOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>\n </application>\n <'
b'/compatibility>\n <application xmlns="urn:schemas-microsoft-com:asm.v3">'
b'\n <windowsSettings>\n <longPathAware xmlns="http://schemas.micros'
b'oft.com/SMI/2016/WindowsSettings">true</longPathAware>\n </windowsSett'
b'ings>\n </application>\n <dependency>\n <dependentAssembly>\n <ass'
b'emblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version='
b'"6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" langua'
b'ge="*"/>\n </dependentAssembly>\n </dependency>\n</assembly>',
True,
False,
None,
None,
None,
'E:\\Arma Reforger '
'Work\\1960-utils\\Texturing\\ConvertOGLDX\\build\\convertogldx\\convertogldx.pkg',
[('pyi-contents-directory _internal', '', 'OPTION'),
('PYZ-00.pyz',
'E:\\Arma Reforger '
'Work\\1960-utils\\Texturing\\ConvertOGLDX\\build\\convertogldx\\PYZ-00.pyz',
'PYZ'),
('struct',
'E:\\Arma Reforger '
'Work\\1960-utils\\Texturing\\ConvertOGLDX\\build\\convertogldx\\localpycs\\struct.pyc',
'PYMODULE'),
('pyimod01_archive',
'E:\\Arma Reforger '
'Work\\1960-utils\\Texturing\\ConvertOGLDX\\build\\convertogldx\\localpycs\\pyimod01_archive.pyc',
'PYMODULE'),
('pyimod02_importers',
'E:\\Arma Reforger '
'Work\\1960-utils\\Texturing\\ConvertOGLDX\\build\\convertogldx\\localpycs\\pyimod02_importers.pyc',
'PYMODULE'),
('pyimod03_ctypes',
'E:\\Arma Reforger '
'Work\\1960-utils\\Texturing\\ConvertOGLDX\\build\\convertogldx\\localpycs\\pyimod03_ctypes.pyc',
'PYMODULE'),
('pyimod04_pywin32',
'E:\\Arma Reforger '
'Work\\1960-utils\\Texturing\\ConvertOGLDX\\build\\convertogldx\\localpycs\\pyimod04_pywin32.pyc',
'PYMODULE'),
('pyiboot01_bootstrap',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\PyInstaller\\loader\\pyiboot01_bootstrap.py',
'PYSOURCE'),
('pyi_rth_inspect',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\PyInstaller\\hooks\\rthooks\\pyi_rth_inspect.py',
'PYSOURCE'),
('pyi_rth_pkgutil',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\PyInstaller\\hooks\\rthooks\\pyi_rth_pkgutil.py',
'PYSOURCE'),
('pyi_rth_multiprocessing',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\PyInstaller\\hooks\\rthooks\\pyi_rth_multiprocessing.py',
'PYSOURCE'),
('pyi_rth_pkgres',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\PyInstaller\\hooks\\rthooks\\pyi_rth_pkgres.py',
'PYSOURCE'),
('pyi_rth_pywintypes',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\_pyinstaller_hooks_contrib\\hooks\\rthooks\\pyi_rth_pywintypes.py',
'PYSOURCE'),
('pyi_rth_pythoncom',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\_pyinstaller_hooks_contrib\\hooks\\rthooks\\pyi_rth_pythoncom.py',
'PYSOURCE'),
('pyi_rth_setuptools',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\PyInstaller\\hooks\\rthooks\\pyi_rth_setuptools.py',
'PYSOURCE'),
('convertogldx',
'E:\\Arma Reforger '
'Work\\1960-utils\\Texturing\\ConvertOGLDX\\convertogldx.py',
'PYSOURCE'),
('python310.dll',
'C:\\Program '
'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\\python310.dll',
'BINARY'),
('libopenblas64__v0.3.21-gcc_10_3_0.dll',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\numpy\\.libs\\libopenblas64__v0.3.21-gcc_10_3_0.dll',
'BINARY'),
('pywin32_system32\\pywintypes310.dll',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\pywin32_system32\\pywintypes310.dll',
'BINARY'),
('pywin32_system32\\pythoncom310.dll',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\pywin32_system32\\pythoncom310.dll',
'BINARY'),
('_decimal.pyd',
'C:\\Program '
'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\\DLLs\\_decimal.pyd',
'EXTENSION'),
('_lzma.pyd',
'C:\\Program '
'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\\DLLs\\_lzma.pyd',
'EXTENSION'),
('_bz2.pyd',
'C:\\Program '
'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\\DLLs\\_bz2.pyd',
'EXTENSION'),
('_hashlib.pyd',
'C:\\Program '
'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\\DLLs\\_hashlib.pyd',
'EXTENSION'),
('unicodedata.pyd',
'C:\\Program '
'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\\DLLs\\unicodedata.pyd',
'EXTENSION'),
('select.pyd',
'C:\\Program '
'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\\DLLs\\select.pyd',
'EXTENSION'),
('_socket.pyd',
'C:\\Program '
'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\\DLLs\\_socket.pyd',
'EXTENSION'),
('win32\\win32api.pyd',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\win32\\win32api.pyd',
'EXTENSION'),
('_ssl.pyd',
'C:\\Program '
'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\\DLLs\\_ssl.pyd',
'EXTENSION'),
('_ctypes.pyd',
'C:\\Program '
'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\\DLLs\\_ctypes.pyd',
'EXTENSION'),
('win32\\win32evtlog.pyd',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\win32\\win32evtlog.pyd',
'EXTENSION'),
('_queue.pyd',
'C:\\Program '
'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\\DLLs\\_queue.pyd',
'EXTENSION'),
('_multiprocessing.pyd',
'C:\\Program '
'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\\DLLs\\_multiprocessing.pyd',
'EXTENSION'),
('pyexpat.pyd',
'C:\\Program '
'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\\DLLs\\pyexpat.pyd',
'EXTENSION'),
('_overlapped.pyd',
'C:\\Program '
'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\\DLLs\\_overlapped.pyd',
'EXTENSION'),
('_asyncio.pyd',
'C:\\Program '
'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\\DLLs\\_asyncio.pyd',
'EXTENSION'),
('markupsafe\\_speedups.cp310-win_amd64.pyd',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\markupsafe\\_speedups.cp310-win_amd64.pyd',
'EXTENSION'),
('win32com\\shell\\shell.pyd',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\win32comext\\shell\\shell.pyd',
'EXTENSION'),
('win32\\win32trace.pyd',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\win32\\win32trace.pyd',
'EXTENSION'),
('Pythonwin\\win32ui.pyd',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\Pythonwin\\win32ui.pyd',
'EXTENSION'),
('win32\\_win32sysloader.pyd',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\win32\\_win32sysloader.pyd',
'EXTENSION'),
('numpy\\core\\_multiarray_tests.cp310-win_amd64.pyd',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\numpy\\core\\_multiarray_tests.cp310-win_amd64.pyd',
'EXTENSION'),
('psutil\\_psutil_windows.pyd',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\psutil\\_psutil_windows.pyd',
'EXTENSION'),
('numpy\\core\\_multiarray_umath.cp310-win_amd64.pyd',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\numpy\\core\\_multiarray_umath.cp310-win_amd64.pyd',
'EXTENSION'),
('win32\\win32pdh.pyd',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\win32\\win32pdh.pyd',
'EXTENSION'),
('numpy\\linalg\\lapack_lite.cp310-win_amd64.pyd',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\numpy\\linalg\\lapack_lite.cp310-win_amd64.pyd',
'EXTENSION'),
('numpy\\random\\mtrand.cp310-win_amd64.pyd',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\numpy\\random\\mtrand.cp310-win_amd64.pyd',
'EXTENSION'),
('numpy\\random\\_sfc64.cp310-win_amd64.pyd',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\numpy\\random\\_sfc64.cp310-win_amd64.pyd',
'EXTENSION'),
('numpy\\random\\_philox.cp310-win_amd64.pyd',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\numpy\\random\\_philox.cp310-win_amd64.pyd',
'EXTENSION'),
('numpy\\random\\_pcg64.cp310-win_amd64.pyd',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\numpy\\random\\_pcg64.cp310-win_amd64.pyd',
'EXTENSION'),
('numpy\\random\\_mt19937.cp310-win_amd64.pyd',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\numpy\\random\\_mt19937.cp310-win_amd64.pyd',
'EXTENSION'),
('numpy\\random\\bit_generator.cp310-win_amd64.pyd',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\numpy\\random\\bit_generator.cp310-win_amd64.pyd',
'EXTENSION'),
('numpy\\random\\_generator.cp310-win_amd64.pyd',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\numpy\\random\\_generator.cp310-win_amd64.pyd',
'EXTENSION'),
('numpy\\random\\_bounded_integers.cp310-win_amd64.pyd',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\numpy\\random\\_bounded_integers.cp310-win_amd64.pyd',
'EXTENSION'),
('numpy\\random\\_common.cp310-win_amd64.pyd',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\numpy\\random\\_common.cp310-win_amd64.pyd',
'EXTENSION'),
('numpy\\fft\\_pocketfft_internal.cp310-win_amd64.pyd',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\numpy\\fft\\_pocketfft_internal.cp310-win_amd64.pyd',
'EXTENSION'),
('numpy\\linalg\\_umath_linalg.cp310-win_amd64.pyd',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\numpy\\linalg\\_umath_linalg.cp310-win_amd64.pyd',
'EXTENSION'),
('PIL\\_webp.cp310-win_amd64.pyd',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\PIL\\_webp.cp310-win_amd64.pyd',
'EXTENSION'),
('PIL\\_imagingtk.cp310-win_amd64.pyd',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\PIL\\_imagingtk.cp310-win_amd64.pyd',
'EXTENSION'),
('PIL\\_imagingcms.cp310-win_amd64.pyd',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\PIL\\_imagingcms.cp310-win_amd64.pyd',
'EXTENSION'),
('_cffi_backend.cp310-win_amd64.pyd',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\_cffi_backend.cp310-win_amd64.pyd',
'EXTENSION'),
('PIL\\_imaging.cp310-win_amd64.pyd',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\PIL\\_imaging.cp310-win_amd64.pyd',
'EXTENSION'),
('_elementtree.pyd',
'C:\\Program '
'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\\DLLs\\_elementtree.pyd',
'EXTENSION'),
('VCRUNTIME140.dll',
'C:\\Program '
'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\\VCRUNTIME140.dll',
'BINARY'),
('VCRUNTIME140_1.dll',
'C:\\Program '
'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\\VCRUNTIME140_1.dll',
'BINARY'),
('libcrypto-1_1.dll',
'C:\\Program '
'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\\DLLs\\libcrypto-1_1.dll',
'BINARY'),
('libssl-1_1.dll',
'C:\\Program '
'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\\DLLs\\libssl-1_1.dll',
'BINARY'),
('libffi-7.dll',
'C:\\Program '
'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\\DLLs\\libffi-7.dll',
'BINARY'),
('Pythonwin\\mfc140u.dll',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\Pythonwin\\mfc140u.dll',
'BINARY'),
('python3.dll',
'C:\\Program '
'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\\python3.dll',
'BINARY'),
('numpy\\.libs\\libopenblas64__v0.3.21-gcc_10_3_0.dll',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\numpy\\.libs\\libopenblas64__v0.3.21-gcc_10_3_0.dll',
'BINARY'),
('base_library.zip',
'E:\\Arma Reforger '
'Work\\1960-utils\\Texturing\\ConvertOGLDX\\build\\convertogldx\\base_library.zip',
'DATA'),
('setuptools-65.5.0.dist-info\\METADATA',
'C:\\Program '
'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\\lib\\site-packages\\setuptools-65.5.0.dist-info\\METADATA',
'DATA'),
('setuptools-65.5.0.dist-info\\top_level.txt',
'C:\\Program '
'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\\lib\\site-packages\\setuptools-65.5.0.dist-info\\top_level.txt',
'DATA'),
('setuptools-65.5.0.dist-info\\REQUESTED',
'C:\\Program '
'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\\lib\\site-packages\\setuptools-65.5.0.dist-info\\REQUESTED',
'DATA'),
('setuptools-65.5.0.dist-info\\INSTALLER',
'C:\\Program '
'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\\lib\\site-packages\\setuptools-65.5.0.dist-info\\INSTALLER',
'DATA'),
('setuptools-65.5.0.dist-info\\WHEEL',
'C:\\Program '
'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\\lib\\site-packages\\setuptools-65.5.0.dist-info\\WHEEL',
'DATA'),
('setuptools-65.5.0.dist-info\\entry_points.txt',
'C:\\Program '
'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\\lib\\site-packages\\setuptools-65.5.0.dist-info\\entry_points.txt',
'DATA'),
('setuptools-65.5.0.dist-info\\LICENSE',
'C:\\Program '
'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\\lib\\site-packages\\setuptools-65.5.0.dist-info\\LICENSE',
'DATA'),
('setuptools-65.5.0.dist-info\\RECORD',
'C:\\Program '
'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\\lib\\site-packages\\setuptools-65.5.0.dist-info\\RECORD',
'DATA')],
[],
False,
False,
1760384735,
[('run.exe',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\PyInstaller\\bootloader\\Windows-64bit-intel\\run.exe',
'EXECUTABLE')],
'C:\\Program '
'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\\python310.dll')

View File

@@ -0,0 +1,295 @@
('E:\\Arma Reforger '
'Work\\1960-utils\\Texturing\\ConvertOGLDX\\build\\convertogldx\\convertogldx.pkg',
{'BINARY': True,
'DATA': True,
'EXECUTABLE': True,
'EXTENSION': True,
'PYMODULE': True,
'PYSOURCE': True,
'PYZ': False,
'SPLASH': True,
'SYMLINK': False},
[('pyi-contents-directory _internal', '', 'OPTION'),
('PYZ-00.pyz',
'E:\\Arma Reforger '
'Work\\1960-utils\\Texturing\\ConvertOGLDX\\build\\convertogldx\\PYZ-00.pyz',
'PYZ'),
('struct',
'E:\\Arma Reforger '
'Work\\1960-utils\\Texturing\\ConvertOGLDX\\build\\convertogldx\\localpycs\\struct.pyc',
'PYMODULE'),
('pyimod01_archive',
'E:\\Arma Reforger '
'Work\\1960-utils\\Texturing\\ConvertOGLDX\\build\\convertogldx\\localpycs\\pyimod01_archive.pyc',
'PYMODULE'),
('pyimod02_importers',
'E:\\Arma Reforger '
'Work\\1960-utils\\Texturing\\ConvertOGLDX\\build\\convertogldx\\localpycs\\pyimod02_importers.pyc',
'PYMODULE'),
('pyimod03_ctypes',
'E:\\Arma Reforger '
'Work\\1960-utils\\Texturing\\ConvertOGLDX\\build\\convertogldx\\localpycs\\pyimod03_ctypes.pyc',
'PYMODULE'),
('pyimod04_pywin32',
'E:\\Arma Reforger '
'Work\\1960-utils\\Texturing\\ConvertOGLDX\\build\\convertogldx\\localpycs\\pyimod04_pywin32.pyc',
'PYMODULE'),
('pyiboot01_bootstrap',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\PyInstaller\\loader\\pyiboot01_bootstrap.py',
'PYSOURCE'),
('pyi_rth_inspect',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\PyInstaller\\hooks\\rthooks\\pyi_rth_inspect.py',
'PYSOURCE'),
('pyi_rth_pkgutil',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\PyInstaller\\hooks\\rthooks\\pyi_rth_pkgutil.py',
'PYSOURCE'),
('pyi_rth_multiprocessing',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\PyInstaller\\hooks\\rthooks\\pyi_rth_multiprocessing.py',
'PYSOURCE'),
('pyi_rth_pkgres',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\PyInstaller\\hooks\\rthooks\\pyi_rth_pkgres.py',
'PYSOURCE'),
('pyi_rth_pywintypes',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\_pyinstaller_hooks_contrib\\hooks\\rthooks\\pyi_rth_pywintypes.py',
'PYSOURCE'),
('pyi_rth_pythoncom',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\_pyinstaller_hooks_contrib\\hooks\\rthooks\\pyi_rth_pythoncom.py',
'PYSOURCE'),
('pyi_rth_setuptools',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\PyInstaller\\hooks\\rthooks\\pyi_rth_setuptools.py',
'PYSOURCE'),
('convertogldx',
'E:\\Arma Reforger '
'Work\\1960-utils\\Texturing\\ConvertOGLDX\\convertogldx.py',
'PYSOURCE'),
('python310.dll',
'C:\\Program '
'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\\python310.dll',
'BINARY'),
('libopenblas64__v0.3.21-gcc_10_3_0.dll',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\numpy\\.libs\\libopenblas64__v0.3.21-gcc_10_3_0.dll',
'BINARY'),
('pywin32_system32\\pywintypes310.dll',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\pywin32_system32\\pywintypes310.dll',
'BINARY'),
('pywin32_system32\\pythoncom310.dll',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\pywin32_system32\\pythoncom310.dll',
'BINARY'),
('_decimal.pyd',
'C:\\Program '
'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\\DLLs\\_decimal.pyd',
'EXTENSION'),
('_lzma.pyd',
'C:\\Program '
'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\\DLLs\\_lzma.pyd',
'EXTENSION'),
('_bz2.pyd',
'C:\\Program '
'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\\DLLs\\_bz2.pyd',
'EXTENSION'),
('_hashlib.pyd',
'C:\\Program '
'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\\DLLs\\_hashlib.pyd',
'EXTENSION'),
('unicodedata.pyd',
'C:\\Program '
'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\\DLLs\\unicodedata.pyd',
'EXTENSION'),
('select.pyd',
'C:\\Program '
'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\\DLLs\\select.pyd',
'EXTENSION'),
('_socket.pyd',
'C:\\Program '
'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\\DLLs\\_socket.pyd',
'EXTENSION'),
('win32\\win32api.pyd',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\win32\\win32api.pyd',
'EXTENSION'),
('_ssl.pyd',
'C:\\Program '
'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\\DLLs\\_ssl.pyd',
'EXTENSION'),
('_ctypes.pyd',
'C:\\Program '
'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\\DLLs\\_ctypes.pyd',
'EXTENSION'),
('win32\\win32evtlog.pyd',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\win32\\win32evtlog.pyd',
'EXTENSION'),
('_queue.pyd',
'C:\\Program '
'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\\DLLs\\_queue.pyd',
'EXTENSION'),
('_multiprocessing.pyd',
'C:\\Program '
'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\\DLLs\\_multiprocessing.pyd',
'EXTENSION'),
('pyexpat.pyd',
'C:\\Program '
'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\\DLLs\\pyexpat.pyd',
'EXTENSION'),
('_overlapped.pyd',
'C:\\Program '
'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\\DLLs\\_overlapped.pyd',
'EXTENSION'),
('_asyncio.pyd',
'C:\\Program '
'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\\DLLs\\_asyncio.pyd',
'EXTENSION'),
('markupsafe\\_speedups.cp310-win_amd64.pyd',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\markupsafe\\_speedups.cp310-win_amd64.pyd',
'EXTENSION'),
('win32com\\shell\\shell.pyd',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\win32comext\\shell\\shell.pyd',
'EXTENSION'),
('win32\\win32trace.pyd',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\win32\\win32trace.pyd',
'EXTENSION'),
('Pythonwin\\win32ui.pyd',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\Pythonwin\\win32ui.pyd',
'EXTENSION'),
('win32\\_win32sysloader.pyd',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\win32\\_win32sysloader.pyd',
'EXTENSION'),
('numpy\\core\\_multiarray_tests.cp310-win_amd64.pyd',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\numpy\\core\\_multiarray_tests.cp310-win_amd64.pyd',
'EXTENSION'),
('psutil\\_psutil_windows.pyd',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\psutil\\_psutil_windows.pyd',
'EXTENSION'),
('numpy\\core\\_multiarray_umath.cp310-win_amd64.pyd',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\numpy\\core\\_multiarray_umath.cp310-win_amd64.pyd',
'EXTENSION'),
('win32\\win32pdh.pyd',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\win32\\win32pdh.pyd',
'EXTENSION'),
('numpy\\linalg\\lapack_lite.cp310-win_amd64.pyd',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\numpy\\linalg\\lapack_lite.cp310-win_amd64.pyd',
'EXTENSION'),
('numpy\\random\\mtrand.cp310-win_amd64.pyd',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\numpy\\random\\mtrand.cp310-win_amd64.pyd',
'EXTENSION'),
('numpy\\random\\_sfc64.cp310-win_amd64.pyd',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\numpy\\random\\_sfc64.cp310-win_amd64.pyd',
'EXTENSION'),
('numpy\\random\\_philox.cp310-win_amd64.pyd',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\numpy\\random\\_philox.cp310-win_amd64.pyd',
'EXTENSION'),
('numpy\\random\\_pcg64.cp310-win_amd64.pyd',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\numpy\\random\\_pcg64.cp310-win_amd64.pyd',
'EXTENSION'),
('numpy\\random\\_mt19937.cp310-win_amd64.pyd',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\numpy\\random\\_mt19937.cp310-win_amd64.pyd',
'EXTENSION'),
('numpy\\random\\bit_generator.cp310-win_amd64.pyd',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\numpy\\random\\bit_generator.cp310-win_amd64.pyd',
'EXTENSION'),
('numpy\\random\\_generator.cp310-win_amd64.pyd',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\numpy\\random\\_generator.cp310-win_amd64.pyd',
'EXTENSION'),
('numpy\\random\\_bounded_integers.cp310-win_amd64.pyd',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\numpy\\random\\_bounded_integers.cp310-win_amd64.pyd',
'EXTENSION'),
('numpy\\random\\_common.cp310-win_amd64.pyd',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\numpy\\random\\_common.cp310-win_amd64.pyd',
'EXTENSION'),
('numpy\\fft\\_pocketfft_internal.cp310-win_amd64.pyd',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\numpy\\fft\\_pocketfft_internal.cp310-win_amd64.pyd',
'EXTENSION'),
('numpy\\linalg\\_umath_linalg.cp310-win_amd64.pyd',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\numpy\\linalg\\_umath_linalg.cp310-win_amd64.pyd',
'EXTENSION'),
('PIL\\_webp.cp310-win_amd64.pyd',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\PIL\\_webp.cp310-win_amd64.pyd',
'EXTENSION'),
('PIL\\_imagingtk.cp310-win_amd64.pyd',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\PIL\\_imagingtk.cp310-win_amd64.pyd',
'EXTENSION'),
('PIL\\_imagingcms.cp310-win_amd64.pyd',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\PIL\\_imagingcms.cp310-win_amd64.pyd',
'EXTENSION'),
('_cffi_backend.cp310-win_amd64.pyd',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\_cffi_backend.cp310-win_amd64.pyd',
'EXTENSION'),
('PIL\\_imaging.cp310-win_amd64.pyd',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\PIL\\_imaging.cp310-win_amd64.pyd',
'EXTENSION'),
('_elementtree.pyd',
'C:\\Program '
'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\\DLLs\\_elementtree.pyd',
'EXTENSION'),
('VCRUNTIME140.dll',
'C:\\Program '
'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\\VCRUNTIME140.dll',
'BINARY'),
('VCRUNTIME140_1.dll',
'C:\\Program '
'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\\VCRUNTIME140_1.dll',
'BINARY'),
('libcrypto-1_1.dll',
'C:\\Program '
'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\\DLLs\\libcrypto-1_1.dll',
'BINARY'),
('libssl-1_1.dll',
'C:\\Program '
'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\\DLLs\\libssl-1_1.dll',
'BINARY'),
('libffi-7.dll',
'C:\\Program '
'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\\DLLs\\libffi-7.dll',
'BINARY'),
('Pythonwin\\mfc140u.dll',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\Pythonwin\\mfc140u.dll',
'BINARY'),
('python3.dll',
'C:\\Program '
'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\\python3.dll',
'BINARY'),
('numpy\\.libs\\libopenblas64__v0.3.21-gcc_10_3_0.dll',
'C:\\Users\\Niklas\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python310\\site-packages\\numpy\\.libs\\libopenblas64__v0.3.21-gcc_10_3_0.dll',
'BINARY'),
('base_library.zip',
'E:\\Arma Reforger '
'Work\\1960-utils\\Texturing\\ConvertOGLDX\\build\\convertogldx\\base_library.zip',
'DATA'),
('setuptools-65.5.0.dist-info\\METADATA',
'C:\\Program '
'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\\lib\\site-packages\\setuptools-65.5.0.dist-info\\METADATA',
'DATA'),
('setuptools-65.5.0.dist-info\\top_level.txt',
'C:\\Program '
'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\\lib\\site-packages\\setuptools-65.5.0.dist-info\\top_level.txt',
'DATA'),
('setuptools-65.5.0.dist-info\\REQUESTED',
'C:\\Program '
'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\\lib\\site-packages\\setuptools-65.5.0.dist-info\\REQUESTED',
'DATA'),
('setuptools-65.5.0.dist-info\\INSTALLER',
'C:\\Program '
'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\\lib\\site-packages\\setuptools-65.5.0.dist-info\\INSTALLER',
'DATA'),
('setuptools-65.5.0.dist-info\\WHEEL',
'C:\\Program '
'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\\lib\\site-packages\\setuptools-65.5.0.dist-info\\WHEEL',
'DATA'),
('setuptools-65.5.0.dist-info\\entry_points.txt',
'C:\\Program '
'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\\lib\\site-packages\\setuptools-65.5.0.dist-info\\entry_points.txt',
'DATA'),
('setuptools-65.5.0.dist-info\\LICENSE',
'C:\\Program '
'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\\lib\\site-packages\\setuptools-65.5.0.dist-info\\LICENSE',
'DATA'),
('setuptools-65.5.0.dist-info\\RECORD',
'C:\\Program '
'Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\\lib\\site-packages\\setuptools-65.5.0.dist-info\\RECORD',
'DATA')],
'python310.dll',
False,
False,
False,
[],
None,
None,
None)

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,192 @@
This file lists modules PyInstaller was not able to find. This does not
necessarily mean this module is required for running your program. Python and
Python 3rd-party packages include a lot of conditional or optional modules. For
example the module 'ntpath' only exists on Windows, whereas the module
'posixpath' only exists on Posix systems.
Types if import:
* top-level: imported at the top-level - look at these first
* conditional: imported within an if-statement
* delayed: imported within a function
* optional: imported within a try-except-statement
IMPORTANT: Do NOT post this list to the issue-tracker. Use it as a basis for
tracking down the missing module yourself. Thanks!
missing module named pep517 - imported by importlib.metadata (delayed)
missing module named 'org.python' - imported by copy (optional), xml.sax (delayed, conditional)
missing module named pwd - imported by posixpath (delayed, conditional), subprocess (delayed, conditional, optional), shutil (delayed, optional), tarfile (optional), pathlib (delayed, optional), netrc (delayed, conditional), getpass (delayed), http.server (delayed, optional), webbrowser (delayed), distutils.util (delayed, conditional, optional), distutils.archive_util (optional), psutil (optional), setuptools._distutils.archive_util (optional), setuptools._distutils.util (delayed, conditional, optional)
missing module named grp - imported by subprocess (delayed, conditional, optional), shutil (delayed, optional), tarfile (optional), pathlib (delayed, optional), distutils.archive_util (optional), setuptools._distutils.archive_util (optional)
missing module named org - imported by pickle (optional)
missing module named posix - imported by os (conditional, optional), shutil (conditional), importlib._bootstrap_external (conditional)
missing module named resource - imported by posix (top-level)
missing module named _frozen_importlib_external - imported by importlib._bootstrap (delayed), importlib (optional), importlib.abc (optional), zipimport (top-level)
excluded module named _frozen_importlib - imported by importlib (optional), importlib.abc (optional), zipimport (top-level)
missing module named _posixsubprocess - imported by subprocess (optional), multiprocessing.util (delayed)
missing module named fcntl - imported by subprocess (optional), xmlrpc.server (optional), psutil._compat (delayed, optional)
missing module named vms_lib - imported by platform (delayed, optional)
missing module named 'java.lang' - imported by platform (delayed, optional)
missing module named _winreg - imported by platform (delayed, optional), pkg_resources._vendor.appdirs (delayed, conditional)
missing module named _scproxy - imported by urllib.request (conditional)
missing module named termios - imported by getpass (optional), tty (top-level), psutil._compat (delayed, optional)
missing module named usercustomize - imported by site (delayed, optional)
missing module named sitecustomize - imported by site (delayed, optional)
missing module named startup - imported by pyreadline3.keysyms.common (conditional), pyreadline3.keysyms.keysyms (conditional)
missing module named sets - imported by pyreadline3.keysyms.common (optional)
missing module named System - imported by pyreadline3.clipboard.ironpython_clipboard (top-level), pyreadline3.keysyms.ironpython_keysyms (top-level), pyreadline3.console.ironpython_console (top-level), pyreadline3.rlmain (conditional)
missing module named console - imported by pyreadline3.console.ansi (conditional)
missing module named clr - imported by pyreadline3.clipboard.ironpython_clipboard (top-level), pyreadline3.console.ironpython_console (top-level)
missing module named IronPythonConsole - imported by pyreadline3.console.ironpython_console (top-level)
missing module named _posixshmem - imported by multiprocessing.resource_tracker (conditional), multiprocessing.shared_memory (conditional)
missing module named multiprocessing.set_start_method - imported by multiprocessing (top-level), multiprocessing.spawn (top-level)
missing module named multiprocessing.get_start_method - imported by multiprocessing (top-level), multiprocessing.spawn (top-level)
missing module named multiprocessing.get_context - imported by multiprocessing (top-level), multiprocessing.pool (top-level), multiprocessing.managers (top-level), multiprocessing.sharedctypes (top-level)
missing module named multiprocessing.TimeoutError - imported by multiprocessing (top-level), multiprocessing.pool (top-level)
missing module named java - imported by xml.sax._exceptions (conditional)
missing module named multiprocessing.BufferTooShort - imported by multiprocessing (top-level), multiprocessing.connection (top-level)
missing module named multiprocessing.AuthenticationError - imported by multiprocessing (top-level), multiprocessing.connection (top-level)
missing module named asyncio.DefaultEventLoopPolicy - imported by asyncio (delayed, conditional), asyncio.events (delayed, conditional)
missing module named pyparsing.Word - imported by pyparsing (delayed), pyparsing.unicode (delayed)
missing module named railroad - imported by pkg_resources._vendor.pyparsing.diagram (top-level), pyparsing.diagram (top-level), setuptools._vendor.pyparsing.diagram (top-level)
missing module named 'setuptools.extern.pyparsing' - imported by setuptools._vendor.packaging.requirements (top-level), setuptools._vendor.packaging.markers (top-level)
missing module named _manylinux - imported by packaging._manylinux (delayed, optional), setuptools._vendor.packaging._manylinux (delayed, optional), pkg_resources._vendor.packaging._manylinux (delayed, optional)
missing module named 'setuptools.extern.jaraco' - imported by setuptools._reqs (top-level), setuptools._entry_points (top-level), setuptools.command.egg_info (top-level), setuptools._vendor.jaraco.text (top-level)
missing module named setuptools.extern.importlib_resources - imported by setuptools.extern (conditional), setuptools._importlib (conditional), setuptools._vendor.jaraco.text (optional)
missing module named setuptools.extern.tomli - imported by setuptools.extern (delayed), setuptools.config.pyprojecttoml (delayed)
missing module named setuptools.extern.importlib_metadata - imported by setuptools.extern (conditional), setuptools._importlib (conditional)
missing module named setuptools.extern.ordered_set - imported by setuptools.extern (top-level), setuptools.dist (top-level)
missing module named setuptools.extern.packaging - imported by setuptools.extern (top-level), setuptools.dist (top-level), setuptools.command.egg_info (top-level), setuptools.depends (top-level)
missing module named 'typing.io' - imported by importlib.resources (top-level)
missing module named 'setuptools.extern.more_itertools' - imported by setuptools.dist (top-level), setuptools.config.expand (delayed), setuptools._itertools (top-level), setuptools._entry_points (top-level), setuptools.msvc (top-level), setuptools._vendor.jaraco.functools (top-level)
missing module named 'setuptools.extern.packaging.version' - imported by setuptools.config.setupcfg (top-level), setuptools.msvc (top-level)
missing module named 'setuptools.extern.packaging.utils' - imported by setuptools.wheel (top-level)
missing module named 'setuptools.extern.packaging.tags' - imported by setuptools.wheel (top-level)
missing module named 'pkg_resources.extern.pyparsing' - imported by pkg_resources._vendor.packaging.markers (top-level), pkg_resources._vendor.packaging.requirements (top-level)
missing module named 'pkg_resources.extern.importlib_resources' - imported by pkg_resources._vendor.jaraco.text (optional)
missing module named 'pkg_resources.extern.more_itertools' - imported by pkg_resources._vendor.jaraco.functools (top-level)
missing module named 'com.sun' - imported by pkg_resources._vendor.appdirs (delayed, conditional, optional)
missing module named com - imported by pkg_resources._vendor.appdirs (delayed)
missing module named 'win32com.gen_py' - imported by win32com (conditional, optional)
missing module named pkg_resources.extern.packaging - imported by pkg_resources.extern (top-level), pkg_resources (top-level)
missing module named pkg_resources.extern.appdirs - imported by pkg_resources.extern (top-level), pkg_resources (top-level)
missing module named 'pkg_resources.extern.jaraco' - imported by pkg_resources (top-level), pkg_resources._vendor.jaraco.text (top-level)
missing module named trove_classifiers - imported by setuptools.config._validate_pyproject.formats (optional)
missing module named 'setuptools.extern.packaging.specifiers' - imported by setuptools.config.setupcfg (top-level), setuptools.config._apply_pyprojecttoml (delayed)
missing module named 'setuptools.extern.packaging.requirements' - imported by setuptools.config.setupcfg (top-level)
missing module named importlib_metadata - imported by setuptools._importlib (delayed, optional)
missing module named pyimod02_importers - imported by C:\Users\Niklas\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\PyInstaller\hooks\rthooks\pyi_rth_pkgutil.py (delayed), C:\Users\Niklas\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\PyInstaller\hooks\rthooks\pyi_rth_pkgres.py (delayed)
missing module named dummy_threading - imported by psutil._compat (optional)
missing module named _dummy_thread - imported by cffi.lock (conditional, optional), numpy.core.arrayprint (optional)
missing module named numpy.core.result_type - imported by numpy.core (delayed), numpy.testing._private.utils (delayed)
missing module named numpy.core.float_ - imported by numpy.core (delayed), numpy.testing._private.utils (delayed)
missing module named numpy.core.number - imported by numpy.core (delayed), numpy.testing._private.utils (delayed)
missing module named numpy.core.object_ - imported by numpy.core (top-level), numpy.linalg.linalg (top-level), numpy.testing._private.utils (delayed)
missing module named numpy.core.all - imported by numpy.core (top-level), numpy.linalg.linalg (top-level), numpy.testing._private.utils (delayed)
missing module named numpy.core.bool_ - imported by numpy.core (delayed), numpy.testing._private.utils (delayed)
missing module named numpy.core.inf - imported by numpy.core (delayed), numpy.testing._private.utils (delayed)
missing module named numpy.core.array2string - imported by numpy.core (delayed), numpy.testing._private.utils (delayed)
missing module named numpy.lib.imag - imported by numpy.lib (delayed), numpy.testing._private.utils (delayed)
missing module named numpy.lib.real - imported by numpy.lib (delayed), numpy.testing._private.utils (delayed)
missing module named numpy.lib.iscomplexobj - imported by numpy.lib (delayed), numpy.testing._private.utils (delayed)
missing module named numpy.core.signbit - imported by numpy.core (delayed), numpy.testing._private.utils (delayed)
missing module named numpy.core.isscalar - imported by numpy.core (delayed), numpy.testing._private.utils (delayed), numpy.lib.polynomial (top-level)
missing module named numpy.core.isinf - imported by numpy.core (delayed), numpy.testing._private.utils (delayed)
missing module named numpy.core.errstate - imported by numpy.core (top-level), numpy.linalg.linalg (top-level), numpy.testing._private.utils (delayed)
missing module named numpy.core.isfinite - imported by numpy.core (top-level), numpy.linalg.linalg (top-level), numpy.testing._private.utils (delayed)
missing module named numpy.core.isnan - imported by numpy.core (top-level), numpy.linalg.linalg (top-level), numpy.testing._private.utils (delayed)
missing module named numpy.core.array - imported by numpy.core (top-level), numpy.linalg.linalg (top-level), numpy.testing._private.utils (top-level), numpy.lib.polynomial (top-level)
missing module named numpy.core.isnat - imported by numpy.core (top-level), numpy.testing._private.utils (top-level)
missing module named numpy.core.ndarray - imported by numpy.core (top-level), numpy.testing._private.utils (top-level), numpy.lib.utils (top-level)
missing module named numpy.core.array_repr - imported by numpy.core (top-level), numpy.testing._private.utils (top-level)
missing module named numpy.core.arange - imported by numpy.core (top-level), numpy.testing._private.utils (top-level), numpy.fft.helper (top-level)
missing module named numpy.core.empty - imported by numpy.core (top-level), numpy.linalg.linalg (top-level), numpy.testing._private.utils (top-level), numpy.fft.helper (top-level)
missing module named numpy.core.float32 - imported by numpy.core (top-level), numpy.testing._private.utils (top-level)
missing module named numpy.core.intp - imported by numpy.core (top-level), numpy.linalg.linalg (top-level), numpy.testing._private.utils (top-level)
missing module named numpy.core.linspace - imported by numpy.core (top-level), numpy.lib.index_tricks (top-level)
missing module named numpy.core.iinfo - imported by numpy.core (top-level), numpy.lib.twodim_base (top-level)
missing module named numpy.core.transpose - imported by numpy.core (top-level), numpy.lib.function_base (top-level)
missing module named numpy.core.asarray - imported by numpy.core (top-level), numpy.linalg.linalg (top-level), numpy.lib.utils (top-level), numpy.fft._pocketfft (top-level), numpy.fft.helper (top-level)
missing module named numpy.core.integer - imported by numpy.core (top-level), numpy.fft.helper (top-level)
missing module named numpy.core.sqrt - imported by numpy.core (top-level), numpy.linalg.linalg (top-level), numpy.fft._pocketfft (top-level)
missing module named numpy.core.conjugate - imported by numpy.core (top-level), numpy.fft._pocketfft (top-level)
missing module named numpy.core.swapaxes - imported by numpy.core (top-level), numpy.linalg.linalg (top-level), numpy.fft._pocketfft (top-level)
missing module named numpy.core.zeros - imported by numpy.core (top-level), numpy.linalg.linalg (top-level), numpy.fft._pocketfft (top-level)
missing module named numpy.core.reciprocal - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
missing module named numpy.core.sort - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
missing module named numpy.core.argsort - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
missing module named numpy.core.sign - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
missing module named numpy.core.count_nonzero - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
missing module named numpy.core.divide - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
missing module named numpy.core.matmul - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
missing module named numpy.core.asanyarray - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
missing module named numpy.core.atleast_2d - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
missing module named numpy.core.product - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
missing module named numpy.core.amax - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
missing module named numpy.core.amin - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
missing module named numpy.core.moveaxis - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
missing module named numpy.core.geterrobj - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
missing module named numpy.core.finfo - imported by numpy.core (top-level), numpy.linalg.linalg (top-level), numpy.lib.polynomial (top-level)
missing module named numpy.core.sum - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
missing module named numpy.core.multiply - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
missing module named numpy.core.add - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
missing module named numpy.core.dot - imported by numpy.core (top-level), numpy.linalg.linalg (top-level), numpy.lib.polynomial (top-level)
missing module named numpy.core.Inf - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
missing module named numpy.core.newaxis - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
missing module named numpy.core.complexfloating - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
missing module named numpy.core.inexact - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
missing module named numpy.core.cdouble - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
missing module named numpy.core.csingle - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
missing module named numpy.core.double - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
missing module named numpy.core.single - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
missing module named numpy.core.intc - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
missing module named numpy.core.empty_like - imported by numpy.core (top-level), numpy.linalg.linalg (top-level)
missing module named numpy.core.ufunc - imported by numpy.core (top-level), numpy.lib.utils (top-level)
missing module named numpy.core.ones - imported by numpy.core (top-level), numpy.lib.polynomial (top-level)
missing module named numpy.core.hstack - imported by numpy.core (top-level), numpy.lib.polynomial (top-level)
missing module named numpy.core.atleast_1d - imported by numpy.core (top-level), numpy.lib.polynomial (top-level)
missing module named numpy.core.atleast_3d - imported by numpy.core (top-level), numpy.lib.shape_base (top-level)
missing module named numpy.core.vstack - imported by numpy.core (top-level), numpy.lib.shape_base (top-level)
missing module named pickle5 - imported by numpy.compat.py3k (optional)
missing module named numpy.eye - imported by numpy (delayed), numpy.core.numeric (delayed)
missing module named numpy.recarray - imported by numpy (top-level), numpy.ma.mrecords (top-level)
missing module named numpy.expand_dims - imported by numpy (top-level), numpy.ma.core (top-level)
missing module named numpy.array - imported by numpy (top-level), numpy.ma.core (top-level), numpy.ma.extras (top-level), numpy.ma.mrecords (top-level)
missing module named numpy.iscomplexobj - imported by numpy (top-level), numpy.ma.core (top-level)
missing module named numpy.amin - imported by numpy (top-level), numpy.ma.core (top-level)
missing module named numpy.amax - imported by numpy (top-level), numpy.ma.core (top-level)
missing module named numpy.float64 - imported by numpy (top-level), numpy.array_api._typing (top-level)
missing module named numpy.float32 - imported by numpy (top-level), numpy.array_api._typing (top-level)
missing module named numpy.uint64 - imported by numpy (top-level), numpy.array_api._typing (top-level)
missing module named numpy.uint32 - imported by numpy (top-level), numpy.array_api._typing (top-level)
missing module named numpy.uint16 - imported by numpy (top-level), numpy.array_api._typing (top-level)
missing module named numpy.uint8 - imported by numpy (top-level), numpy.array_api._typing (top-level)
missing module named numpy.int64 - imported by numpy (top-level), numpy.array_api._typing (top-level)
missing module named numpy.int32 - imported by numpy (top-level), numpy.array_api._typing (top-level)
missing module named numpy.int16 - imported by numpy (top-level), numpy.array_api._typing (top-level)
missing module named numpy.int8 - imported by numpy (top-level), numpy.array_api._typing (top-level)
missing module named numpy._typing._ufunc - imported by numpy._typing (conditional)
missing module named numpy.bytes_ - imported by numpy (top-level), numpy._typing._array_like (top-level)
missing module named numpy.str_ - imported by numpy (top-level), numpy._typing._array_like (top-level)
missing module named numpy.void - imported by numpy (top-level), numpy._typing._array_like (top-level)
missing module named numpy.object_ - imported by numpy (top-level), numpy._typing._array_like (top-level)
missing module named numpy.datetime64 - imported by numpy (top-level), numpy._typing._array_like (top-level)
missing module named numpy.timedelta64 - imported by numpy (top-level), numpy._typing._array_like (top-level)
missing module named numpy.number - imported by numpy (top-level), numpy._typing._array_like (top-level)
missing module named numpy.complexfloating - imported by numpy (top-level), numpy._typing._array_like (top-level)
missing module named numpy.floating - imported by numpy (top-level), numpy._typing._array_like (top-level)
missing module named numpy.integer - imported by numpy (top-level), numpy._typing._array_like (top-level), numpy.ctypeslib (top-level)
missing module named numpy.unsignedinteger - imported by numpy (top-level), numpy._typing._array_like (top-level)
missing module named numpy.bool_ - imported by numpy (top-level), numpy._typing._array_like (top-level), numpy.ma.core (top-level), numpy.ma.mrecords (top-level)
missing module named numpy.generic - imported by numpy (top-level), numpy._typing._array_like (top-level)
missing module named numpy.dtype - imported by numpy (top-level), numpy._typing._array_like (top-level), numpy.array_api._typing (top-level), numpy.ma.mrecords (top-level), numpy.ctypeslib (top-level)
missing module named numpy.ndarray - imported by numpy (top-level), numpy._typing._array_like (top-level), numpy.ma.core (top-level), numpy.ma.extras (top-level), numpy.ma.mrecords (top-level), numpy.ctypeslib (top-level)
missing module named numpy.ufunc - imported by numpy (top-level), numpy._typing (top-level)
missing module named numpy.histogramdd - imported by numpy (delayed), numpy.lib.twodim_base (delayed)
missing module named olefile - imported by PIL.FpxImagePlugin (top-level), PIL.MicImagePlugin (top-level)
missing module named dummy_thread - imported by cffi.lock (conditional, optional)
missing module named thread - imported by cffi.lock (conditional, optional), cffi.cparser (conditional, optional)
missing module named cStringIO - imported by cffi.ffiplatform (optional)
missing module named cPickle - imported by pycparser.ply.yacc (delayed, optional)
missing module named cffi._pycparser - imported by cffi (optional), cffi.cparser (optional)
missing module named xmlrpclib - imported by defusedxml.xmlrpc (conditional)

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

View File

@@ -0,0 +1,165 @@
# normalmap_to_directx_filtered.py
# Drag & drop image files or folders onto the EXE.
# Default: FORCE convert to DirectX (Y) by flipping green.
# Suffix filter: only process files whose *basename* ends with one of: _n, _nrm, _normal (case-insensitive).
# Flags:
# --detect -> flip only if image looks OpenGL (+Y)
# --all -> ignore suffix filter; process all supported images
# --suffixes "a,b,c" -> comma-separated list of suffixes (without extensions)
import sys, os
from PIL import Image
import numpy as np
SUPPORTED_EXTS = {".png", ".tga", ".jpg", ".jpeg", ".tif", ".tiff", ".bmp"}
OUT_SUBFOLDER = "DirectX_Converted"
DEFAULT_SUFFIXES = ["_n", "_nrm", "_normal"] # case-insensitive
def is_image(p):
return os.path.splitext(p)[1].lower() in SUPPORTED_EXTS
def iter_inputs(paths):
for p in paths:
if os.path.isdir(p):
for root, _, files in os.walk(p):
for f in files:
fp = os.path.join(root, f)
if is_image(fp):
yield fp
else:
if is_image(p):
yield p
def has_normal_suffix(path, suffixes):
stem = os.path.splitext(os.path.basename(path))[0].lower()
return any(stem.endswith(suf.lower()) for suf in suffixes)
def flip_green(img_rgba):
r, g, b, a = img_rgba.split()
g = g.point(lambda i: 255 - i)
return Image.merge("RGBA", (r, g, b, a))
def analyze_mean_y(img_rgba):
_, g, b, _ = img_rgba.split()
g_np = np.array(g, dtype=np.float32)
b_np = np.array(b, dtype=np.float32)
y = (g_np / 255.0) * 2.0 - 1.0
flat_mask = b_np > 240
y_use = y[~flat_mask] if (~flat_mask).any() else y
return float(y_use.mean())
def ensure_directx(img_rgba, detect_mode: bool):
if not detect_mode:
return flip_green(img_rgba), True, None # forced
mean_y = analyze_mean_y(img_rgba)
if mean_y >= 0.0:
return flip_green(img_rgba), True, mean_y
else:
return img_rgba, False, mean_y
def output_path(src_path):
folder, base = os.path.split(src_path)
out_dir = os.path.join(folder, OUT_SUBFOLDER)
os.makedirs(out_dir, exist_ok=True)
return os.path.join(out_dir, base)
def save_preserving_format(out_img_rgba, src_path, had_alpha):
_, ext = os.path.splitext(src_path)
ext = ext.lower()
if not had_alpha or ext in {".jpg", ".jpeg", ".bmp"}:
out_img = out_img_rgba.convert("RGB")
else:
out_img = out_img_rgba
dst = output_path(src_path)
save_kwargs, fmt = {}, None
if ext in {".jpg", ".jpeg"}:
save_kwargs["quality"] = 95
fmt = "JPEG"
elif ext == ".png":
fmt = "PNG"
elif ext == ".tga":
fmt = "TGA"
elif ext in {".tif", ".tiff"}:
fmt = "TIFF"
elif ext == ".bmp":
fmt = "BMP"
else:
dst = os.path.splitext(dst)[0] + ".png"
fmt = "PNG"
out_img.save(dst, format=fmt, **save_kwargs)
return dst
def process_one(path, detect_mode: bool):
try:
src = Image.open(path)
had_alpha = src.mode in ("LA", "RGBA", "PA")
img = src.convert("RGBA")
out_img, flipped, mean_y = ensure_directx(img, detect_mode)
dst = save_preserving_format(out_img, path, had_alpha)
if detect_mode:
status = "flipped to DirectX (Y)" if flipped else "already DirectX (Y)"
extra = f" meanY={mean_y:+.4f}"
else:
status = "FORCED flip -> DirectX (Y)"
extra = ""
print(f"[OK] {path}\n {status}{extra}\n -> {dst}")
except Exception as e:
print(f"[ERR] {path} :: {e}")
def parse_args(argv):
detect_mode = False
process_all = False
suffixes = DEFAULT_SUFFIXES[:]
paths = []
it = iter(argv)
for a in it:
if a == "--detect":
detect_mode = True
elif a == "--all":
process_all = True
elif a == "--suffixes":
try:
raw = next(it)
suffixes = [s.strip() for s in raw.split(",") if s.strip()]
except StopIteration:
print("[WARN] --suffixes expects a quoted comma-separated list; using defaults.")
else:
paths.append(a)
return detect_mode, process_all, suffixes, paths
def main():
detect_mode, process_all, suffixes, args = parse_args(sys.argv[1:])
if not args:
print("Drag and drop image files or folders onto this EXE.")
print("Options: --detect --all --suffixes \"_n,_nrm,_normal\"")
return # auto-exit
files = list(iter_inputs(args))
if not files:
print("No supported images found.")
return
mode_desc = "DETECT mode (flip only if +Y detected)" if detect_mode else "FORCE mode (flip everything)"
filt_desc = "NO suffix filter (--all)" if process_all else f"Suffix filter: {', '.join(suffixes)}"
print(f"{mode_desc}\n{filt_desc}\nFound {len(files)} file(s) before filtering.\n")
count_total = 0
count_skipped = 0
for p in files:
if not process_all and not has_normal_suffix(p, suffixes):
print(f"[SKIP] {p} (name lacks normal-map suffix)")
count_skipped += 1
continue
count_total += 1
process_one(p, detect_mode)
print(f"\nProcessed: {count_total}, Skipped: {count_skipped}")
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,38 @@
# -*- mode: python ; coding: utf-8 -*-
a = Analysis(
['convertogldx.py'],
pathex=[],
binaries=[],
datas=[],
hiddenimports=[],
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=[],
noarchive=False,
)
pyz = PYZ(a.pure)
exe = EXE(
pyz,
a.scripts,
a.binaries,
a.datas,
[],
name='convertogldx',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=True,
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
icon=['convertogldx.ico'],
)

Binary file not shown.