diff --git a/README.md b/README.md index f767781..3108eb9 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,9 @@ # Cyberpunk-Helper-Scripts -scripts to help automate troubleshooting and other tasks for modding cyberpunk 2077. + +scripts to help automate troubleshooting and other tasks for modding cyberpunk 2077. FindAllErrors.bat - updated or version 2.12a -USAGE: -Simply place the file in your install directory or drag and drop your Cyberpunk 2077 folder on top of the .bat wherever it may be. The script will dig through the folder +USAGE: +Simply place the file in your install directory or drag and drop your Cyberpunk 2077 folder on top of the .bat wherever +it may be. The script will dig through the folder for logs, extract any error messages and print them to a new file called FilteredLogs.txt for easy troubleshooting. diff --git a/export_phys.py b/export_phys.py index 465cf00..110125a 100644 --- a/export_phys.py +++ b/export_phys.py @@ -1,30 +1,32 @@ - # by The Magnificent Doctor Presto August 4 2023 - # /$$ https://github.com/DoctorPresto/Cyberpunk-Helper-Scripts /$$ /$$$$$$ - # | $$ | $$ /$$__ $$ - # /$$$$$$| $$$$$$$ /$$ /$$ /$$$$$$$ /$$$$$$ /$$ /$$ /$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ | $$ \__/$$$$$$ /$$$$$$ - # /$$__ $| $$__ $| $$ | $$/$$_____/ /$$__ $| $$ /$$//$$__ $$/$$__ $$/$$__ $|_ $$_/ | $$$$ /$$__ $$/$$__ $$ -# | $$ \ $| $$ \ $| $$ | $| $$$$$$ | $$$$$$$$\ $$$$/| $$ \ $| $$ \ $| $$ \__/ | $$ | $$_/ | $$ \ $| $$ \__/ -# | $$ | $| $$ | $| $$ | $$\____ $$ | $$_____/ >$$ $$| $$ | $| $$ | $| $$ | $$ /$$ | $$ | $$ | $| $$ -# | $$$$$$$| $$ | $| $$$$$$$/$$$$$$$/ | $$$$$$$/$$/\ $| $$$$$$$| $$$$$$| $$ | $$$$/ | $$ | $$$$$$| $$ -# | $$____/|__/ |__/\____ $|_______/ \_______|__/ \__| $$____/ \______/|__/ \___/ |__/ \______/|__/ -# | $$ /$$ | $$ /$$$$$$$ /$$ | $$ /$$ -# | $$ | $$$$$$/ | $$__ $| $$ | $$ | $$ -# |__/ \______/ | $$ \ $| $$ /$$$$$$ /$$$$$$$ /$$$$$$$ /$$$$$$ /$$$$$$ - # | $$$$$$$| $$/$$__ $| $$__ $$/$$__ $$/$$__ $$/$$__ $$ - # | $$__ $| $| $$$$$$$| $$ \ $| $$ | $| $$$$$$$| $$ \__/ - # | $$ \ $| $| $$_____| $$ | $| $$ | $| $$_____| $$ - # | $$$$$$$| $| $$$$$$| $$ | $| $$$$$$| $$$$$$| $$ - # |_______/|__/\_______|__/ |__/\_______/\_______|__/ import json -import bpy import os -import bmesh + +import bpy import mathutils -### Just enter the path tio your original .json file here and the script will export the changes you've made in blender to a copy of the original json in -### that will be saved into same directory as the original with a new_ prefix. All you need to do is right click on this file in wolvenkit and convert from json back to .phys +# by The Magnificent Doctor Presto August 4 2023 +# /$$ https://github.com/DoctorPresto/Cyberpunk-Helper-Scripts /$$ /$$$$$$ +# | $$ | $$ /$$__ $$ +# /$$$$$$| $$$$$$$ /$$ /$$ /$$$$$$$ /$$$$$$ /$$ /$$ /$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ | $$ \__/$$$$$$ /$$$$$$ +# /$$__ $| $$__ $| $$ | $$/$$_____/ /$$__ $| $$ /$$//$$__ $$/$$__ $$/$$__ $|_ $$_/ | $$$$ /$$__ $$/$$__ $$ +# | $$ \ $| $$ \ $| $$ | $| $$$$$$ | $$$$$$$$\ $$$$/| $$ \ $| $$ \ $| $$ \__/ | $$ | $$_/ | $$ \ $| $$ \__/ +# | $$ | $| $$ | $| $$ | $$\____ $$ | $$_____/ >$$ $$| $$ | $| $$ | $| $$ | $$ /$$ | $$ | $$ | $| $$ +# | $$$$$$$| $$ | $| $$$$$$$/$$$$$$$/ | $$$$$$$/$$/\ $| $$$$$$$| $$$$$$| $$ | $$$$/ | $$ | $$$$$$| $$ +# | $$____/|__/ |__/\____ $|_______/ \_______|__/ \__| $$____/ \______/|__/ \___/ |__/ \______/|__/ +# | $$ /$$ | $$ /$$$$$$$ /$$ | $$ /$$ +# | $$ | $$$$$$/ | $$__ $| $$ | $$ | $$ +# |__/ \______/ | $$ \ $| $$ /$$$$$$ /$$$$$$$ /$$$$$$$ /$$$$$$ /$$$$$$ +# | $$$$$$$| $$/$$__ $| $$__ $$/$$__ $$/$$__ $$/$$__ $$ +# | $$__ $| $| $$$$$$$| $$ \ $| $$ | $| $$$$$$$| $$ \__/ +# | $$ \ $| $| $$_____| $$ | $| $$ | $| $$_____| $$ +# | $$$$$$$| $| $$$$$$| $$ | $| $$$$$$| $$$$$$| $$ +# |_______/|__/\_______|__/ |__/\_______/\_______|__/ + + +### Just enter the path tio your original .json file here and the script will export the changes you've made in blender to a copy of the original json in +### that will be saved into same directory as the original with a new_ prefix. All you need to do is right click on this file in wolvenkit and convert from json back to .phys -physJsonPath = "the\\full\\path\\to\\original\\json" # make sure to use \\ in your path +physJsonPath = 'the\\full\\path\\to\\original\\json' # make sure to use \\ in your path phys = open(physJsonPath) data = json.load(phys) @@ -50,7 +52,10 @@ i['Data']['localToBody']['orientation']['k'] = obj.rotation_quaternion.y i['Data']['localToBody']['orientation']['r'] = obj.rotation_quaternion.w - if colliderType == "physicsColliderConvex" or colliderType == "physicsColliderConcave": + if ( + colliderType == 'physicsColliderConvex' + or colliderType == 'physicsColliderConcave' + ): mesh = obj.data if 'vertices' in i['Data']: for j, vert in enumerate(mesh.vertices): @@ -58,9 +63,11 @@ i['Data']['vertices'][j]['Y'] = vert.co.y i['Data']['vertices'][j]['Z'] = vert.co.z - elif colliderType == "physicsColliderBox": + elif colliderType == 'physicsColliderBox': # Calculate world-space bounding box vertices - world_bounds = [obj.matrix_world @ mathutils.Vector(coord) for coord in obj.bound_box] + world_bounds = [ + obj.matrix_world @ mathutils.Vector(coord) for coord in obj.bound_box + ] # Get center of the box in world space center = sum(world_bounds, mathutils.Vector()) / 8 @@ -74,9 +81,11 @@ i['Data']['halfExtents']['Y'] = obj.dimensions.y / 2 i['Data']['halfExtents']['Z'] = obj.dimensions.z / 2 - elif colliderType == "physicsColliderCapsule": - i['Data']['radius'] = obj.dimensions.x / 2 # Divided by 2 because blender dimensions are diameter - i['Data']['height'] = obj.dimensions.z + elif colliderType == 'physicsColliderCapsule': + i['Data']['radius'] = ( + obj.dimensions.x / 2 + ) # Divided by 2 because blender dimensions are diameter + i['Data']['height'] = obj.dimensions.z with open(output, 'w') as f: json.dump(data, f, indent=2) diff --git a/filter_anims.py b/filter_anims.py index b35b37d..03bc678 100644 --- a/filter_anims.py +++ b/filter_anims.py @@ -1,59 +1,64 @@ -import bpy import os import json +import bpy + ########################## You need to fill these out ###################################################### # you need to edit this so that it points to the json you want to filter, paths need two slashes \\ not \ -file_to_search = "path\\to\\your\\anims.json" +file_to_search = 'path\\to\\your\\anims.json' ## set this to True if you have imported the anims file to blender and also want it to delete all the extra nla strips -delete_anims = False +delete_anims = False # List of anims to search for, seperated by a comma, individual lines is optional but easier to read names_to_search = [ -"anim__1", -"anim__2", - + 'anim__1', + 'anim__2', ] ######################### you don't need to touch any of this ######################################################## -# we're going to use the path of the original json to set the output path, this gets the path to the directory -# we're going to make the new file in +# we're going to use the path of the original json to set the output path, this gets the path to the directory +# we're going to make the new file in dir_path, file_name = os.path.split(file_to_search) # lelts get the name of the anims.json file_name_without_extension, file_extension = os.path.splitext(file_name) -# set the new filename to match the original but with filtered_ in front -new_file_name = "filtered_" + file_name_without_extension + file_extension +# set the new filename to match the original but with filtered_ in front +new_file_name = 'filtered_' + file_name_without_extension + file_extension -# tell the script to make the new file in the directory of the original +# tell the script to make the new file in the directory of the original output_path = os.path.join(dir_path, new_file_name) -with open(file_to_search, "r") as json_file: +with open(file_to_search, 'r') as json_file: data = json.load(json_file) # Create a copy of the original JSON data output_data = data.copy() # Create a new animations array that only contains the animations we're searching for -output_data["Data"]["RootChunk"]["animations"] = [ - animation for animation in data["Data"]["RootChunk"]["animations"] if - animation["Data"]["animation"]["Data"]["name"]["$value"] in names_to_search +output_data['Data']['RootChunk']['animations'] = [ + animation + for animation in data['Data']['RootChunk']['animations'] + if animation['Data']['animation']['Data']['name']['$value'] in names_to_search ] # Write the modified JSON data to the output file -with open(output_path, "w") as output_file: +with open(output_path, 'w') as output_file: json.dump(output_data, output_file, indent=4) - + # If the delete_anims bool is set to True, delete any NLA strips which have matching names to the ones we searched if delete_anims: for obj in bpy.context.scene.objects: - if obj.type == 'ARMATURE' and obj.animation_data and obj.animation_data.nla_tracks: + if ( + obj.type == 'ARMATURE' + and obj.animation_data + and obj.animation_data.nla_tracks + ): for strip in obj.animation_data.nla_tracks: if strip.name not in names_to_search: obj.animation_data.nla_tracks.remove(strip) -print("your new anims.json has been saved to:" + output_path) +print('your new anims.json has been saved to:' + output_path) diff --git a/generate_inkatlas.py b/generate_inkatlas.py index d9b9c7e..8e73237 100644 --- a/generate_inkatlas.py +++ b/generate_inkatlas.py @@ -1,46 +1,75 @@ -# ▓█████▄ ██▀███ ██▓███ ██▀███ ▓█████ ██████ ▄▄▄█████▓ ▒█████ ██████ -# ▒██▀ ██▌▓██ ▒ ██▒ ▓██░ ██▒▓██ ▒ ██▒▓█ ▀ ▒██ ▒ ▓ ██▒ ▓▒▒██▒ ██▒▒██ ▒ -# ░██ █▌▓██ ░▄█ ▒ ▓██░ ██▓▒▓██ ░▄█ ▒▒███ ░ ▓██▄ ▒ ▓██░ ▒░▒██░ ██▒░ ▓██▄ +import os +import sys +import re +import json + +try: + from PIL import Image +except ImportError: + print('') + print('INKATLAS GENERATOR ERROR: PILLOW NOT INSTALLED ') + print( + '-----------------------------------------------------------------------------------------------' + ) + print('') + print( + 'you need to install PILLOW (Python Imaging Library) by copy pasting the following into the command line:' + ) + print('') + print('pip install pillow') + print('') + print('for more help check the wiki: ') + print( + 'https://wiki.redmodding.org/cyberpunk-2077-modding/for-mod-creators/modding-guides/everything-else/running-python-scripts' + ) + print( + '-----------------------------------------------------------------------------------------------' + ) + sys.exit(1) + +# ▓█████▄ ██▀███ ██▓███ ██▀███ ▓█████ ██████ ▄▄▄█████▓ ▒█████ ██████ +# ▒██▀ ██▌▓██ ▒ ██▒ ▓██░ ██▒▓██ ▒ ██▒▓█ ▀ ▒██ ▒ ▓ ██▒ ▓▒▒██▒ ██▒▒██ ▒ +# ░██ █▌▓██ ░▄█ ▒ ▓██░ ██▓▒▓██ ░▄█ ▒▒███ ░ ▓██▄ ▒ ▓██░ ▒░▒██░ ██▒░ ▓██▄ # ░▓█▄ ▌▒██▀▀█▄ ▒██▄█▓▒ ▒▒██▀▀█▄ ▒▓█ ▄ ▒ ██▒░ ▓██▓ ░ ▒██ ██░ ▒ ██▒ # ░▒████▓ ░██▓ ▒██▒ ▒██▒ ░ ░░██▓ ▒██▒░▒████▒▒██████▒▒ ▒██▒ ░ ░ ████▓▒░▒██████▒▒ # ▒▒▓ ▒ ░ ▒▓ ░▒▓░ ▒▓▒░ ░ ░░ ▒▓ ░▒▓░░░ ▒░ ░▒ ▒▓▒ ▒ ░ ▒ ░░ ░ ▒░▒░▒░ ▒ ▒▓▒ ▒ ░ # ░ ▒ ▒ ░▒ ░ ▒░ ░▒ ░ ░▒ ░ ▒░ ░ ░ ░░ ░▒ ░ ░ ░ ░ ▒ ▒░ ░ ░▒ ░ ░ -# ░ ░ ░ ░░ ░ ░░ ░░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ▒ ░ ░ ░ -# ░ ░ ░ ░ ░ ░ ░ ░ ░ +# ░ ░ ░ ░░ ░ ░░ ░░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ▒ ░ ░ ░ +# ░ ░ ░ ░ ░ ░ ░ ░ ░ # ███▄ ▄███▓ ▄▄▄ ▄████ ███▄ █ ██▓ █████▒██▓ ▄████▄ ▓█████ ███▄ █ ▄▄▄█████▓ # ▓██▒▀█▀ ██▒▒████▄ ██▒ ▀█▒ ██ ▀█ █ ▓██▒▓██ ▒▓██▒▒██▀ ▀█ ▓█ ▀ ██ ▀█ █ ▓ ██▒ ▓▒ # ▓██ ▓██░▒██ ▀█▄ ▒██░▄▄▄░▓██ ▀█ ██▒▒██▒▒████ ░▒██▒▒▓█ ▄ ▒███ ▓██ ▀█ ██▒▒ ▓██░ ▒░ -# ▒██ ▒██ ░██▄▄▄▄██ ░▓█ ██▓▓██▒ ▐▌██▒░██░░▓█▒ ░░██░▒▓▓▄ ▄██▒▒▓█ ▄ ▓██▒ ▐▌██▒░ ▓██▓ ░ -# ▒██▒ ░██▒ ▓█ ▓██▒░▒▓███▀▒▒██░ ▓██░░██░░▒█░ ░██░▒ ▓███▀ ░░▒████▒▒██░ ▓██░ ▒██▒ ░ -# ░ ▒░ ░ ░ ▒▒ ▓▒█░ ░▒ ▒ ░ ▒░ ▒ ▒ ░▓ ▒ ░ ░▓ ░ ░▒ ▒ ░░░ ▒░ ░░ ▒░ ▒ ▒ ▒ ░░ -# ░ ░ ░ ▒ ▒▒ ░ ░ ░ ░ ░░ ░ ▒░ ▒ ░ ░ ▒ ░ ░ ▒ ░ ░ ░░ ░░ ░ ▒░ ░ -# ░ ░ ░ ▒ ░ ░ ░ ░ ░ ░ ▒ ░ ░ ░ ▒ ░░ ░ ░ ░ ░ ░ -# ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ # -# ██▓ ███▄ █ ██ ▄█▀▄▄▄ ▄▄▄█████▓ ██▓ ▄▄▄ ██████ -# ▓██▒ ██ ▀█ █ ██▄█▒▒████▄ ▓ ██▒ ▓▒▓██▒ ▒████▄ ▒██ ▒ -# ▒██▒▓██ ▀█ ██▒▓███▄░▒██ ▀█▄ ▒ ▓██░ ▒░▒██░ ▒██ ▀█▄ ░ ▓██▄ -# ░██░▓██▒ ▐▌██▒▓██ █▄░██▄▄▄▄██░ ▓██▓ ░ ▒██░ ░██▄▄▄▄██ ▒ ██▒ -# ░██░▒██░ ▓██░▒██▒ █▄▓█ ▓██▒ ▒██▒ ░ ░██████▒▓█ ▓██▒▒██████▒▒ -# ░▓ ░ ▒░ ▒ ▒ ▒ ▒▒ ▓▒▒▒ ▓▒█░ ▒ ░░ ░ ▒░▓ ░▒▒ ▓▒█░▒ ▒▓▒ ▒ ░ -# ▒ ░░ ░░ ░ ▒░░ ░▒ ▒░ ▒ ▒▒ ░ ░ ░ ░ ▒ ░ ▒ ▒▒ ░░ ░▒ ░ ░ -# ▒ ░ ░ ░ ░ ░ ░░ ░ ░ ▒ ░ ░ ░ ░ ▒ ░ ░ ░ -# ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ -# ▄████ ▓█████ ███▄ █ ▓█████ ██▀███ ▄▄▄ ▄▄▄█████▓ ▒█████ ██▀███ +# ▒██ ▒██ ░██▄▄▄▄██ ░▓█ ██▓▓██▒ ▐▌██▒░██░░▓█▒ ░░██░▒▓▓▄ ▄██▒▒▓█ ▄ ▓██▒ ▐▌██▒░ ▓██▓ ░ +# ▒██▒ ░██▒ ▓█ ▓██▒░▒▓███▀▒▒██░ ▓██░░██░░▒█░ ░██░▒ ▓███▀ ░░▒████▒▒██░ ▓██░ ▒██▒ ░ +# ░ ▒░ ░ ░ ▒▒ ▓▒█░ ░▒ ▒ ░ ▒░ ▒ ▒ ░▓ ▒ ░ ░▓ ░ ░▒ ▒ ░░░ ▒░ ░░ ▒░ ▒ ▒ ▒ ░░ +# ░ ░ ░ ▒ ▒▒ ░ ░ ░ ░ ░░ ░ ▒░ ▒ ░ ░ ▒ ░ ░ ▒ ░ ░ ░░ ░░ ░ ▒░ ░ +# ░ ░ ░ ▒ ░ ░ ░ ░ ░ ░ ▒ ░ ░ ░ ▒ ░░ ░ ░ ░ ░ ░ +# ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ # +# ██▓ ███▄ █ ██ ▄█▀▄▄▄ ▄▄▄█████▓ ██▓ ▄▄▄ ██████ +# ▓██▒ ██ ▀█ █ ██▄█▒▒████▄ ▓ ██▒ ▓▒▓██▒ ▒████▄ ▒██ ▒ +# ▒██▒▓██ ▀█ ██▒▓███▄░▒██ ▀█▄ ▒ ▓██░ ▒░▒██░ ▒██ ▀█▄ ░ ▓██▄ +# ░██░▓██▒ ▐▌██▒▓██ █▄░██▄▄▄▄██░ ▓██▓ ░ ▒██░ ░██▄▄▄▄██ ▒ ██▒ +# ░██░▒██░ ▓██░▒██▒ █▄▓█ ▓██▒ ▒██▒ ░ ░██████▒▓█ ▓██▒▒██████▒▒ +# ░▓ ░ ▒░ ▒ ▒ ▒ ▒▒ ▓▒▒▒ ▓▒█░ ▒ ░░ ░ ▒░▓ ░▒▒ ▓▒█░▒ ▒▓▒ ▒ ░ +# ▒ ░░ ░░ ░ ▒░░ ░▒ ▒░ ▒ ▒▒ ░ ░ ░ ░ ▒ ░ ▒ ▒▒ ░░ ░▒ ░ ░ +# ▒ ░ ░ ░ ░ ░ ░░ ░ ░ ▒ ░ ░ ░ ░ ▒ ░ ░ ░ +# ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ +# ▄████ ▓█████ ███▄ █ ▓█████ ██▀███ ▄▄▄ ▄▄▄█████▓ ▒█████ ██▀███ # ██▒ ▀█▒▓█ ▀ ██ ▀█ █ ▓█ ▀ ▓██ ▒ ██▒▒████▄ ▓ ██▒ ▓▒▒██▒ ██▒▓██ ▒ ██▒ # ▒██░▄▄▄░▒███ ▓██ ▀█ ██▒▒███ ▓██ ░▄█ ▒▒██ ▀█▄ ▒ ▓██░ ▒░▒██░ ██▒▓██ ░▄█ ▒ -# ░▓█ ██▓▒▓█ ▄ ▓██▒ ▐▌██▒▒▓█ ▄ ▒██▀▀█▄ ░██▄▄▄▄██░ ▓██▓ ░ ▒██ ██░▒██▀▀█▄ +# ░▓█ ██▓▒▓█ ▄ ▓██▒ ▐▌██▒▒▓█ ▄ ▒██▀▀█▄ ░██▄▄▄▄██░ ▓██▓ ░ ▒██ ██░▒██▀▀█▄ # ░▒▓███▀▒░▒████▒▒██░ ▓██░░▒████▒░██▓ ▒██▒ ▓█ ▓██▒ ▒██▒ ░ ░ ████▓▒░░██▓ ▒██▒ # ░▒ ▒ ░░ ▒░ ░░ ▒░ ▒ ▒ ░░ ▒░ ░░ ▒▓ ░▒▓░ ▒▒ ▓▒█░ ▒ ░░ ░ ▒░▒░▒░ ░ ▒▓ ░▒▓░ # ░ ░ ░ ░ ░░ ░░ ░ ▒░ ░ ░ ░ ░▒ ░ ▒░ ▒ ▒▒ ░ ░ ░ ▒ ▒░ ░▒ ░ ▒░ -# ░ ░ ░ ░ ░ ░ ░ ░ ░░ ░ ░ ▒ ░ ░ ░ ░ ▒ ░░ ░ -# ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ -######################################################################################################## +# ░ ░ ░ ░ ░ ░ ░ ░ ░░ ░ ░ ▒ ░ ░ ░ ░ ▒ ░░ ░ +# ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ +######################################################################################################## # ENV_VARS to skip providing input every time: # INKATLAS_OUTPUT_DIR: path to the output folder # INKATLAS_OUTPUT_NAME: name for the inkatlas file # INKATLAS_SOURCE: path to the source folder -# STOP! +# STOP! # YOU DO NOT NEED TO EDIT THE SCRIPT BELOW IN ORDER TO USE IT @@ -48,42 +77,23 @@ # SIMPLY TYPE CMD IN THE ADDRESS BAR OF THE FOLDER THIS SCRIPT IS LOCATED IN AND THEN PASTE -# python generate_inkatlas.py +# python generate_inkatlas.py # INTO THE COMMAND LINE -# DO NOT COPY THE '#' +# DO NOT COPY THE '#' # FOR MORE HELP: https://wiki.redmodding.org/cyberpunk-2077-modding/for-mod-creators/modding-guides/everything-else/running-python-scripts -######################################################################################################## -import os -import sys -import re -import json -try: - from PIL import Image -except ImportError: - print('') - print('INKATLAS GENERATOR ERROR: PILLOW NOT INSTALLED ') - print('-----------------------------------------------------------------------------------------------') - print('') - print('you need to install PILLOW (Python Imaging Library) by copy pasting the following into the command line:') - print('') - print('pip install pillow') - print('') - print("for more help check the wiki: ") - print("https://wiki.redmodding.org/cyberpunk-2077-modding/for-mod-creators/modding-guides/everything-else/running-python-scripts") - print('-----------------------------------------------------------------------------------------------') - sys.exit(1) - - +######################################################################################################## def main(): icon_folder, png_files = get_source_dir_and_pngs() - output_folder = get_output_dir() - atlas_name = os.getenv('INKATLAS_OUTPUT_NAME') or input(" Enter the name for your new inkatlas file (without extension): ") + output_folder = get_output_dir() + atlas_name = os.getenv('INKATLAS_OUTPUT_NAME') or input( + ' Enter the name for your new inkatlas file (without extension): ' + ) # Load each image to get its dimensions images = [] @@ -91,14 +101,24 @@ def main(): image_path = os.path.join(icon_folder, png_file) try: img = Image.open(image_path) - images.append({"path": image_path, "image": img, "name": os.path.splitext(png_file)[0]}) + images.append( + { + 'path': image_path, + 'image': img, + 'name': os.path.splitext(png_file)[0], + } + ) except Exception as e: - print("INKATLAS GENERATOR ERROR: ") - print('-----------------------------------------------------------------------------------------------') + print('INKATLAS GENERATOR ERROR: ') + print( + '-----------------------------------------------------------------------------------------------' + ) print('') - print(f" Error opening image {png_file}: {e}") + print(f' Error opening image {png_file}: {e}') print('') - print('-----------------------------------------------------------------------------------------------') + print( + '-----------------------------------------------------------------------------------------------' + ) print('') # Calculate the maximum width of the combined image @@ -112,7 +132,7 @@ def main(): # Iterate through each image for image_data in images: - img = image_data["image"] + img = image_data['image'] width = img.width height = img.height @@ -134,15 +154,21 @@ def main(): grid.append(current_row) # Calculate the total height of the combined image - total_height = sum(max(image_data["image"].height for image_data in row) for row in grid) + total_height = sum( + max(image_data['image'].height for image_data in row) for row in grid + ) # Ensure total height is an even number total_height += total_height % 2 total_width = 0 for row in grid: - row_width = sum(image_data["image"].width for image_data in row) # Calculate the total width of images in the current row - total_width = max(total_width, row_width) # Update the total width if the current row width is greater + row_width = sum( + image_data['image'].width for image_data in row + ) # Calculate the total width of images in the current row + total_width = max( + total_width, row_width + ) # Update the total width if the current row width is greater # Ensure total width does not exceed the maximum width total_width = min(total_width, max_width) @@ -151,93 +177,103 @@ def main(): total_width += total_width % 2 # Create a blank canvas to paste images onto - combined_image = Image.new("RGBA", (total_width, total_height), (0, 0, 0, 0)) - raw_index = re.sub(r".*?" + re.escape("raw"), "", output_folder, 1) + combined_image = Image.new('RGBA', (total_width, total_height), (0, 0, 0, 0)) + raw_index = re.sub(r'.*?' + re.escape('raw'), '', output_folder, 1) if raw_index is not None: - atlas_xbm = os.path.join(raw_index, atlas_name + ".xbm") - atlas_xbm_1080 = atlas_xbm.replace(".xbm", "_1080.xbm") + atlas_xbm = os.path.join(raw_index, atlas_name + '.xbm') + atlas_xbm_1080 = atlas_xbm.replace('.xbm', '_1080.xbm') # JSON data data = { - "Header": { - "WolvenKitVersion": "8.13.0-nightly.2024-03-17", - "WKitJsonVersion": "0.0.8", - "GameVersion": 2120, - "ExportedDateTime": "2024-03-18T04:38:07.1672443Z", - "DataType": "CR2W", - "ArchiveFileName": "" + 'Header': { + 'WolvenKitVersion': '8.13.0-nightly.2024-03-17', + 'WKitJsonVersion': '0.0.8', + 'GameVersion': 2120, + 'ExportedDateTime': '2024-03-18T04:38:07.1672443Z', + 'DataType': 'CR2W', + 'ArchiveFileName': '', }, - "Data": { - "Version": 195, - "BuildVersion": 0, - "RootChunk": { - "$type": "inkTextureAtlas", - "activeTexture": "StaticTexture", - "cookingPlatform": "PLATFORM_None", - "dynamicTexture": { - "DepotPath": {"$type": "ResourcePath", "$storage": "uint64", "$value": "0"}, - "Flags": "Default" + 'Data': { + 'Version': 195, + 'BuildVersion': 0, + 'RootChunk': { + '$type': 'inkTextureAtlas', + 'activeTexture': 'StaticTexture', + 'cookingPlatform': 'PLATFORM_None', + 'dynamicTexture': { + 'DepotPath': { + '$type': 'ResourcePath', + '$storage': 'uint64', + '$value': '0', + }, + 'Flags': 'Default', }, - "dynamicTextureSlot": { - "$type": "inkDynamicTextureSlot", - "parts": [], - "texture": {"DepotPath": {"$type": "ResourcePath", "$storage": "uint64", "$value": "0"}, - "Flags": "Default"} + 'dynamicTextureSlot': { + '$type': 'inkDynamicTextureSlot', + 'parts': [], + 'texture': { + 'DepotPath': { + '$type': 'ResourcePath', + '$storage': 'uint64', + '$value': '0', + }, + 'Flags': 'Default', + }, }, - "isSingleTextureMode": 1, - "parts": [], - "slices": [], - "slots": { - "Elements": [ + 'isSingleTextureMode': 1, + 'parts': [], + 'slices': [], + 'slots': { + 'Elements': [ { - "$type": "inkTextureSlot", - "parts": [], - "slices": [], - "texture": { - "DepotPath": { - "$type": "ResourcePath", - "$storage": "string", - "$value": (f"{atlas_xbm}") + '$type': 'inkTextureSlot', + 'parts': [], + 'slices': [], + 'texture': { + 'DepotPath': { + '$type': 'ResourcePath', + '$storage': 'string', + '$value': (f'{atlas_xbm}'), }, - "Flags": "Soft" - } + 'Flags': 'Soft', + }, }, { - "$type": "inkTextureSlot", - "parts": [], - "slices": [], - "texture": { - "DepotPath": { - "$type": "ResourcePath", - "$storage": "string", - "$value": (f"{atlas_xbm_1080}") + '$type': 'inkTextureSlot', + 'parts': [], + 'slices': [], + 'texture': { + 'DepotPath': { + '$type': 'ResourcePath', + '$storage': 'string', + '$value': (f'{atlas_xbm_1080}'), }, - "Flags": "Soft" - } - } + 'Flags': 'Soft', + }, + }, ] }, - "texture": { - "DepotPath": { - "$type": "ResourcePath", - "$storage": "string", - "$value": "" + 'texture': { + 'DepotPath': { + '$type': 'ResourcePath', + '$storage': 'string', + '$value': '', }, - "Flags": "Default" + 'Flags': 'Default', }, - "textureResolution": "UltraHD_3840_2160" + 'textureResolution': 'UltraHD_3840_2160', }, - "EmbeddedFiles": [] - } + 'EmbeddedFiles': [], + }, } # Paste each image onto the canvas and add its data to the JSON current_y = 0 for row in grid: - max_height_in_row = max(image_data["image"].height for image_data in row) + max_height_in_row = max(image_data['image'].height for image_data in row) current_x = 0 for image_data in row: - img = image_data["image"] - name = image_data["name"] + img = image_data['image'] + name = image_data['name'] width = img.width height = img.height @@ -250,68 +286,72 @@ def main(): # Add image data to JSON part_data = { - "$type": "inkTextureAtlasMapper", - "clippingRectInPixels": { - "$type": "Rect", - "bottom": top_pixel + height, - "left": left_pixel, - "right": left_pixel + width, - "top": top_pixel + '$type': 'inkTextureAtlasMapper', + 'clippingRectInPixels': { + '$type': 'Rect', + 'bottom': top_pixel + height, + 'left': left_pixel, + 'right': left_pixel + width, + 'top': top_pixel, }, - "clippingRectInUVCoords": { - "$type": "RectF", - "Bottom": (top_pixel + height) / total_height, - "Left": left_pixel / total_width, - "Right": (left_pixel + width) / total_width, - "Top": top_pixel / total_height + 'clippingRectInUVCoords': { + '$type': 'RectF', + 'Bottom': (top_pixel + height) / total_height, + 'Left': left_pixel / total_width, + 'Right': (left_pixel + width) / total_width, + 'Top': top_pixel / total_height, }, - "partName": { - "$type": "CName", - "$storage": "string", - "$value": name - } + 'partName': {'$type': 'CName', '$storage': 'string', '$value': name}, } - # Append part data to parts array - data["Data"]["RootChunk"]["slots"]["Elements"][0]["parts"].append(part_data) - data["Data"]["RootChunk"]["slots"]["Elements"][1]["parts"].append(part_data) + # Append part data to parts array + data['Data']['RootChunk']['slots']['Elements'][0]['parts'].append(part_data) + data['Data']['RootChunk']['slots']['Elements'][1]['parts'].append(part_data) current_y += max_height_in_row - - # Create the output folder if it does not exist + + # Create the output folder if it does not exist if not os.path.exists(output_folder): os.makedirs(output_folder) # Set the output file name - output_file = os.path.join(output_folder, atlas_name + ".inkatlas.json") + output_file = os.path.join(output_folder, atlas_name + '.inkatlas.json') # Write everything to the .inkatlas.json - with open(output_file, "w") as json_file: + with open(output_file, 'w') as json_file: json.dump(data, json_file, indent=2) - print(f"Data has been saved to {output_file}") + print(f'Data has been saved to {output_file}') # Save the combined image - combined_image_path = os.path.join(output_folder, atlas_name + ".png") + combined_image_path = os.path.join(output_folder, atlas_name + '.png') combined_image.save(combined_image_path) - print(f"Combined image has been saved to {combined_image_path}") + print(f'Combined image has been saved to {combined_image_path}') # Save the resized image with "_1080" suffix - resized_image = combined_image.resize((total_width // 2, total_height // 2),resample=None, box=None, reducing_gap=None) - combined_image_path_1080 = combined_image_path.replace(".png", "_1080.png") - resized_image.save(combined_image_path_1080) - print(f"Combined image has been saved to {combined_image_path_1080}") + resized_image = combined_image.resize( + (total_width // 2, total_height // 2), + resample=None, + box=None, + reducing_gap=None, + ) + combined_image_path_1080 = combined_image_path.replace('.png', '_1080.png') + resized_image.save(combined_image_path_1080) + print(f'Combined image has been saved to {combined_image_path_1080}') def get_source_dir_and_pngs(): icon_folder = os.getenv('INKATLAS_SOURCE') png_files = [] print('') - print("INKATLAS GENERATOR INPUT: ") + print('INKATLAS GENERATOR INPUT: ') while True: - icon_folder = icon_folder or input(" Enter the path to the folder containing the PNG files you want to combine into an inkatlas: ") + icon_folder = icon_folder or input( + ' Enter the path to the folder containing the PNG files you want to combine into an inkatlas: ' + ) # Check for quotes which will break the input path if (icon_folder.startswith('"') or icon_folder.startswith("'")) and ( - icon_folder.endswith('"') or icon_folder.endswith("'")): + icon_folder.endswith('"') or icon_folder.endswith("'") + ): # Remove the quotes icon_folder = icon_folder[1:-1] if icon_folder.endswith('\\'): @@ -320,14 +360,20 @@ def get_source_dir_and_pngs(): if not os.path.exists(icon_folder): print('') print('INKATLAS GENERATOR ERROR:') - print('-----------------------------------------------------------------------------------------------') + print( + '-----------------------------------------------------------------------------------------------' + ) print('') print(' The entered path does not exist.') print('') - print('-----------------------------------------------------------------------------------------------') + print( + '-----------------------------------------------------------------------------------------------' + ) print('') - print("INKATLAS GENERATOR INPUT: ") - icon_folder = None # Reset the input in case env var leads to an invalid path + print('INKATLAS GENERATOR INPUT: ') + icon_folder = ( + None # Reset the input in case env var leads to an invalid path + ) continue files_in_folder = os.listdir(icon_folder) @@ -336,14 +382,20 @@ def get_source_dir_and_pngs(): if not png_files: print('') print('INKATLAS GENERATOR ERROR:') - print('-----------------------------------------------------------------------------------------------') + print( + '-----------------------------------------------------------------------------------------------' + ) print('') print(' The entered folder does not contain any PNG files.') print('') - print('-----------------------------------------------------------------------------------------------') + print( + '-----------------------------------------------------------------------------------------------' + ) print('') - print("INKATLAS GENERATOR INPUT: ") - icon_folder = None # Reset the input in case env var leads to an invalid path + print('INKATLAS GENERATOR INPUT: ') + icon_folder = ( + None # Reset the input in case env var leads to an invalid path + ) continue break # Exit the loop if the folder contains at least one .png file @@ -353,40 +405,47 @@ def get_source_dir_and_pngs(): def get_output_dir(): output_folder = os.getenv('INKATLAS_OUTPUT_DIR') while True: - output_folder = output_folder or input(" Enter the path to output the raw inkatlas files for you to import in Wolvenkit: ") + output_folder = output_folder or input( + ' Enter the path to output the raw inkatlas files for you to import in Wolvenkit: ' + ) # Check for quotes which will break the input path if (output_folder.startswith('"') or output_folder.startswith("'")) and ( - output_folder.endswith('"') or output_folder.endswith("'") or output_folder.endswith("\\")): + output_folder.endswith('"') + or output_folder.endswith("'") + or output_folder.endswith('\\') + ): # Remove the quotes output_folder = output_folder[1:-1] - if output_folder.endswith("source"): - output_folder = os.path.join(output_folder, "raw") - elif "\\archive" in output_folder: - output_folder = output_folder.replace("\\archive", "\\raw") + if output_folder.endswith('source'): + output_folder = os.path.join(output_folder, 'raw') + elif '\\archive' in output_folder: + output_folder = output_folder.replace('\\archive', '\\raw') - if "raw" in output_folder: + if 'raw' in output_folder: break # Exit the loop if "raw" is in the output folder path else: print('') print('INKATLAS GENERATOR ERROR: ') - print('-----------------------------------------------------------------------------------------------') + print( + '-----------------------------------------------------------------------------------------------' + ) print('') - print(f' Entered path {output_folder} does not seem to be within a Wolvenkit project.') + print( + f' Entered path {output_folder} does not seem to be within a Wolvenkit project.' + ) print('') - print('-----------------------------------------------------------------------------------------------') + print( + '-----------------------------------------------------------------------------------------------' + ) print('') - print("INKATLAS GENERATOR INPUT: ") - output_folder = None # Reset the input in case env var leads to an invalid path + print('INKATLAS GENERATOR INPUT: ') + output_folder = ( + None # Reset the input in case env var leads to an invalid path + ) return output_folder - - -if __name__ == "__main__": +if __name__ == '__main__': main() - - - - diff --git a/import_.phys.py b/import_.phys.py index 128dd66..4068fb0 100644 --- a/import_.phys.py +++ b/import_.phys.py @@ -1,32 +1,33 @@ - # by The Magnificent Doctor Presto August 4 2023 - # https://github.com/DoctorPresto/Cyberpunk-Helper-Scripts - # /$$ /$$ /$$ /$$$$$$ - # | $$ |__/ | $$ /$$__ $$ - # /$$$$$$| $$$$$$$ /$$ /$$ /$$$$$$$ /$$/$$$$$$/$$$$ /$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ | $$ \__/$$$$$$ /$$$$$$ - # /$$__ $| $$__ $| $$ | $$/$$_____/ | $| $$_ $$_ $$/$$__ $$/$$__ $$/$$__ $|_ $$_/ | $$$$ /$$__ $$/$$__ $$ -# | $$ \ $| $$ \ $| $$ | $| $$$$$$ | $| $$ \ $$ \ $| $$ \ $| $$ \ $| $$ \__/ | $$ | $$_/ | $$ \ $| $$ \__/ -# | $$ | $| $$ | $| $$ | $$\____ $$ | $| $$ | $$ | $| $$ | $| $$ | $| $$ | $$ /$$ | $$ | $$ | $| $$ -# | $$$$$$$| $$ | $| $$$$$$$/$$$$$$$/ | $| $$ | $$ | $| $$$$$$$| $$$$$$| $$ | $$$$/ | $$ | $$$$$$| $$ -# | $$____/|__/ |__/\____ $|_______/ |__|__/ |__/ |__| $$____/ \______/|__/ \___/ |__/ \______/|__/ -# | $$ /$$ | $$ /$$$$$$$ /$$ | $$ /$$ -# | $$ | $$$$$$/ | $$__ $| $$ | $$ | $$ -# |__/ \______/ | $$ \ $| $$ /$$$$$$ /$$$$$$$ /$$$$$$$ /$$$$$$ /$$$$$$ - # | $$$$$$$| $$/$$__ $| $$__ $$/$$__ $$/$$__ $$/$$__ $$ - # | $$__ $| $| $$$$$$$| $$ \ $| $$ | $| $$$$$$$| $$ \__/ - # | $$ \ $| $| $$_____| $$ | $| $$ | $| $$_____| $$ - # | $$$$$$$| $| $$$$$$| $$ | $| $$$$$$| $$$$$$| $$ - # |_______/|__/\_______|__/ |__/\_______/\_______|__/ import json -import bpy import os + +import bpy import bmesh -import mathutils + +# by The Magnificent Doctor Presto August 4 2023 +# https://github.com/DoctorPresto/Cyberpunk-Helper-Scripts +# /$$ /$$ /$$ /$$$$$$ +# | $$ |__/ | $$ /$$__ $$ +# /$$$$$$| $$$$$$$ /$$ /$$ /$$$$$$$ /$$/$$$$$$/$$$$ /$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ | $$ \__/$$$$$$ /$$$$$$ +# /$$__ $| $$__ $| $$ | $$/$$_____/ | $| $$_ $$_ $$/$$__ $$/$$__ $$/$$__ $|_ $$_/ | $$$$ /$$__ $$/$$__ $$ +# | $$ \ $| $$ \ $| $$ | $| $$$$$$ | $| $$ \ $$ \ $| $$ \ $| $$ \ $| $$ \__/ | $$ | $$_/ | $$ \ $| $$ \__/ +# | $$ | $| $$ | $| $$ | $$\____ $$ | $| $$ | $$ | $| $$ | $| $$ | $| $$ | $$ /$$ | $$ | $$ | $| $$ +# | $$$$$$$| $$ | $| $$$$$$$/$$$$$$$/ | $| $$ | $$ | $| $$$$$$$| $$$$$$| $$ | $$$$/ | $$ | $$$$$$| $$ +# | $$____/|__/ |__/\____ $|_______/ |__|__/ |__/ |__| $$____/ \______/|__/ \___/ |__/ \______/|__/ +# | $$ /$$ | $$ /$$$$$$$ /$$ | $$ /$$ +# | $$ | $$$$$$/ | $$__ $| $$ | $$ | $$ +# |__/ \______/ | $$ \ $| $$ /$$$$$$ /$$$$$$$ /$$$$$$$ /$$$$$$ /$$$$$$ +# | $$$$$$$| $$/$$__ $| $$__ $$/$$__ $$/$$__ $$/$$__ $$ +# | $$__ $| $| $$$$$$$| $$ \ $| $$ | $| $$$$$$$| $$ \__/ +# | $$ \ $| $| $$_____| $$ | $| $$ | $| $$_____| $$ +# | $$$$$$$| $| $$$$$$| $$ | $| $$$$$$| $$$$$$| $$ +# |_______/|__/\_______|__/ |__/\_______/\_______|__/ ## Just convert the .phys file to .json with wolvenkit and put the full path here, make sure to use \\ -## if you're trying to match the location of a vehicle ent imported with the cp77 blender plugin, just check the ent file for the vehicleChassisComponent and +## if you're trying to match the location of a vehicle ent imported with the cp77 blender plugin, just check the ent file for the vehicleChassisComponent and ## raise the verts by the Z value in localTransform - remember to undo this before export as well -physJsonPath = "the\\full\\path\\to\\original\\json" # make sure to use \\ in your path +physJsonPath = 'the\\full\\path\\to\\original\\json' # make sure to use \\ in your path phys = open(physJsonPath) data = json.load(phys) @@ -36,33 +37,48 @@ new_collection = bpy.data.collections.new(collection_name) bpy.context.scene.collection.children.link(new_collection) + # create the new objects def create_new_object(name, transform): mesh = bpy.data.meshes.new(name) obj = bpy.data.objects.new(name, mesh) - new_collection.objects.link(obj) + new_collection.objects.link(obj) bpy.context.view_layer.objects.active = obj obj.select_set(True) - # create dicts for position/orientation - position = (transform['position']['X'], transform['position']['Y'], transform['position']['Z']) - orientation = (transform['orientation']['r'], transform['orientation']['j'], transform['orientation']['k'], transform['orientation']['i']) + # create dicts for position/orientation + position = ( + transform['position']['X'], + transform['position']['Y'], + transform['position']['Z'], + ) + orientation = ( + transform['orientation']['r'], + transform['orientation']['j'], + transform['orientation']['k'], + transform['orientation']['i'], + ) obj.location = position obj.rotation_mode = 'QUATERNION' obj.rotation_quaternion = orientation return obj -# Iterate through the collisionShapes array, creatting submeshes in the collector named after the collider types -for index, i in enumerate(data['Data']['RootChunk']['bodies'][0]['Data']['collisionShapes']): -# create dicts for later +# Iterate through the collisionShapes array, creatting submeshes in the collector named after the collider types +for index, i in enumerate( + data['Data']['RootChunk']['bodies'][0]['Data']['collisionShapes'] +): + # create dicts for later colliderType = i['Data']['$type'] submeshName = str(index) + '_' + colliderType transform = i['Data']['localToBody'] -# If the type is "physicsColliderConvex", or "physicsColliderConcave" create meshes with vertices everywhere specified in the vertices array - if colliderType == "physicsColliderConvex" or colliderType == "physicsColliderConcave": + # If the type is "physicsColliderConvex", or "physicsColliderConcave" create meshes with vertices everywhere specified in the vertices array + if ( + colliderType == 'physicsColliderConvex' + or colliderType == 'physicsColliderConcave' + ): obj = create_new_object(submeshName, transform) if 'vertices' in i['Data']: verts = [(j['X'], j['Y'], j['Z']) for j in i['Data']['vertices']] @@ -72,33 +88,57 @@ def create_new_object(name, transform): bm.to_mesh(obj.data) bm.free() -# If the type is "physicsColliderBox", create a box centered at the object's location - elif colliderType == "physicsColliderBox": + # If the type is "physicsColliderBox", create a box centered at the object's location + elif colliderType == 'physicsColliderBox': half_extents = i['Data']['halfExtents'] - dimensions = (2 * half_extents['X'], 2 * half_extents['Y'], 2 * half_extents['Z']) + dimensions = ( + 2 * half_extents['X'], + 2 * half_extents['Y'], + 2 * half_extents['Z'], + ) bpy.ops.mesh.primitive_cube_add(size=1, location=(0, 0, 0)) box = bpy.context.object box.scale = dimensions box.name = submeshName - box.location = transform['position']['X'], transform['position']['Y'], transform['position']['Z'] + box.location = ( + transform['position']['X'], + transform['position']['Y'], + transform['position']['Z'], + ) box.rotation_mode = 'QUATERNION' # Set the rotation mode to QUATERNION first - box.rotation_quaternion = transform['orientation']['r'], transform['orientation']['j'], transform['orientation']['k'], transform['orientation']['i'] + box.rotation_quaternion = ( + transform['orientation']['r'], + transform['orientation']['j'], + transform['orientation']['k'], + transform['orientation']['i'], + ) new_collection.objects.link(box) - bpy.context.collection.objects.unlink(box) # Unlink from the current collection + bpy.context.collection.objects.unlink(box) # Unlink from the current collection - # handle physicsColliderCapsule - elif colliderType == "physicsColliderCapsule": + # handle physicsColliderCapsule + elif colliderType == 'physicsColliderCapsule': radius = i['Data']['radius'] height = i['Data']['height'] - bpy.ops.mesh.primitive_cylinder_add(radius=radius, depth=height, location=(0, 0, 0)) + bpy.ops.mesh.primitive_cylinder_add( + radius=radius, depth=height, location=(0, 0, 0) + ) capsule = bpy.context.object capsule.name = submeshName capsule.rotation_mode = 'QUATERNION' - capsule.location = transform['position']['X'], transform['position']['Y'], transform['position']['Z'] - capsule.rotation_quaternion = transform['orientation']['r'], transform['orientation']['j'], transform['orientation']['k'], transform['orientation']['i'] + capsule.location = ( + transform['position']['X'], + transform['position']['Y'], + transform['position']['Z'], + ) + capsule.rotation_quaternion = ( + transform['orientation']['r'], + transform['orientation']['j'], + transform['orientation']['k'], + transform['orientation']['i'], + ) new_collection.objects.link(capsule) - bpy.context.collection.objects.unlink(capsule) + bpy.context.collection.objects.unlink(capsule) -print('Finished') \ No newline at end of file +print('Finished') diff --git a/metadata.py b/metadata.py index 578cc17..b500b16 100644 --- a/metadata.py +++ b/metadata.py @@ -1,16 +1,18 @@ -# Run this script from the commandline - all necessary inputs will be prompted for there. -# Don't use quoations or double slashes in paths +import json +# Run this script from the commandline - all necessary inputs will be prompted for there. +# Don't use quoations or double slashes in paths -############################################################# -import json +############################################################# -searchPhrase = input( "Enter the string to search for in class names: ") +searchPhrase = input('Enter the string to search for in class names: ') -metadata_json = input( "Enter the path to your metadata.json file: " ) -output_json = input( "Enter the absolute path for the output file including file name and .json: ") +metadata_json = input('Enter the path to your metadata.json file: ') +output_json = input( + 'Enter the absolute path for the output file including file name and .json: ' +) def search_and_output(json_data, output_file_path): @@ -18,11 +20,13 @@ def search_and_output(json_data, output_file_path): def find_metadata(classes): for entry in classes: - if "name" in entry and searchPhrase in entry["name"]:#.startswith(searchPhrase): + if ( + 'name' in entry and searchPhrase in entry['name'] + ): # .startswith(searchPhrase): matching_entries.append(entry) - if "classes" in json_data: - find_metadata(json_data["classes"]) + if 'classes' in json_data: + find_metadata(json_data['classes']) # Write the output JSON file with open(output_file_path, 'w') as output_file: @@ -30,9 +34,10 @@ def find_metadata(classes): print('classes exported to:', output_json) # Read the metadata JSON file + + with open(metadata_json, 'r') as file: input_data = json.load(file) # Call the search_and_output function search_and_output(input_data, output_json) - \ No newline at end of file diff --git a/swizzle.py b/swizzle.py index 2023db1..c99b7b4 100644 --- a/swizzle.py +++ b/swizzle.py @@ -1,30 +1,29 @@ +import os +from PIL import Image +import numpy as np -# just paste this into blender's script editor and then fill this in with the path to your opengl(blue coloured) normnal, and press run, the cyberpunk swizzled +# just paste this into blender's script editor and then fill this in with the path to your opengl(blue coloured) normnal, and press run, the cyberpunk swizzled # normal will be in the same folder as the opengl normal with _swizzled added to the filename -from PIL import Image -import numpy as np -import bpy -import os - -# just fill this in with the path to your opengl(blue coloured) normnal, and press run, the cyberpunk swizzled +# just fill this in with the path to your opengl(blue coloured) normnal, and press run, the cyberpunk swizzled # normal will be in the same folder as the opengl normal with _swizzled added to the filename # use double slashes in between folder names in your path C:\\folder1\\folder2\\my_example_normal.png -inpath = "s:\\KB3D_HEM_MetalFrame_normal.png" # replace this with the path to your normal image to convert -swizzle_or_unswizzle = True # set to True to swizzle, False to unswizzle -#(the blue looking one not used in game needs to be swizzled, the ones from the game, unswizzled) +inpath = 's:\\KB3D_HEM_MetalFrame_normal.png' # replace this with the path to your normal image to convert +swizzle_or_unswizzle = True # set to True to swizzle, False to unswizzle +# (the blue looking one not used in game needs to be swizzled, the ones from the game, unswizzled) def load_img(img_path): if img_path is not None: - print(f"loading: {img_path} ") + print(f'loading: {img_path} ') img = Image.open(img_path) return img + def swizzle_normal(oglnorm): dxnorm = np.array(oglnorm).astype(np.float32) dxnorm = dxnorm / 255.0 * 2.0 - 1.0 @@ -32,26 +31,30 @@ def swizzle_normal(oglnorm): dxnorm[..., 2] = -1.0 dxnorm = ((dxnorm + 1.0) / 2.0 * 255.0).astype(np.uint8) return Image.fromarray(dxnorm) - + + def unswizzle_normal(dxnorm): oglnorm = np.array(dxnorm).astype(np.float32) oglnorm = oglnorm / 255.0 * 2.0 - 1.0 oglnorm[..., 1] = -oglnorm[..., 1] - oglnorm[..., 2] = np.sqrt(np.clip(1.0 - oglnorm[..., 0]**2 - oglnorm[..., 1]**2, 0, 1)) + oglnorm[..., 2] = np.sqrt( + np.clip(1.0 - oglnorm[..., 0] ** 2 - oglnorm[..., 1] ** 2, 0, 1) + ) oglnorm = ((oglnorm + 1.0) / 2.0 * 255.0).astype(np.uint8) return Image.fromarray(oglnorm) - + + if swizzle_or_unswizzle == True: oglnrm = load_img(inpath) - print("preparing to swizzle your image") + print('preparing to swizzle your image') outpath = os.path.splitext(inpath)[0] + '_swizzled.png' dxnrm = swizzle_normal(oglnrm) dxnrm.save(outpath) else: dxnrm = load_img(inpath) - print("preparing to unswizzle your image") + print('preparing to unswizzle your image') outpath = os.path.splitext(inpath)[0] + '_unswizzled.png' oglnrm = unswizzle_normal(dxnrm) oglnrm.save(outpath) -print(f"successfully converted image saved to: {outpath}") +print(f'successfully converted image saved to: {outpath}')