diff --git a/.gitattributes b/.gitattributes index 00f1252..29489e1 100644 --- a/.gitattributes +++ b/.gitattributes @@ -2,6 +2,5 @@ *.png binary # our generated mesh should be save as binary *.bin binary -# json is data and not good for human reading(althought I edit it on my own hand.) -# so set it as binary -bbp_ng/json/*.json binary \ No newline at end of file +# the compressed json data should be binary +bbp_ng/raw_jsons/*.json binary diff --git a/.gitignore b/.gitignore index d9056db..b4b6e27 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,8 @@ bbp_ng/PyBMap/*.pdb bbp_ng/icons/* !bbp_ng/icons/.gitkeep +bbp_ng/jsons/* +!bbp_ng/jsons/.gitkeep # Byte-compiled / optimized / DLL files __pycache__/ diff --git a/bbp_ng/json/trafos.json b/bbp_ng/json/trafos.json deleted file mode 100644 index 9719112..0000000 --- a/bbp_ng/json/trafos.json +++ /dev/null @@ -1,312 +0,0 @@ -[ - { - "identifier": "raw_trafo", - "showcase": null, - "params": [ - { - "field": "trafo_texture", - "data": "\"BallWood\"" - }, - { - "field": "height", - "data": "5.0" - }, - { - "field": "face", - "data": "(True, False, True, True, True, True)" - } - ], - "vars": [ - { - "field": "uv_height", - "data": "height / 5.0" - } - ], - "vertices": [ - { - "skip": "False", - "data": "(0, 0, 0)" - }, - { - "skip": "False", - "data": "(5, 0, 0)" - }, - { - "skip": "False", - "data": "(5, 5, 0)" - }, - { - "skip": "False", - "data": "(0, 5, 0)" - }, - { - "skip": "False", - "data": "(0, 0, -height)" - }, - { - "skip": "False", - "data": "(5, 0, -height)" - }, - { - "skip": "False", - "data": "(5, 5, -height)" - }, - { - "skip": "False", - "data": "(0, 5, -height)" - } - ], - "faces": [ - { - "skip": "not face[0]", - "texture": "trafo_texture", - "indices": [0, 1, 2, 3], - "uvs": [ - "(0, 0)", - "(1, 0)", - "(1, 1)", - "(0, 1)" - ], - "normals": [ - "(0, 0, 1)", - "(0, 0, 1)", - "(0, 0, 1)", - "(0, 0, 1)" - ] - }, - { - "skip": "not face[1]", - "texture": "trafo_texture", - "indices": [5, 4, 7, 6], - "uvs": [ - "(0, 0)", - "(1, 0)", - "(1, 1)", - "(0, 1)" - ], - "normals": [ - "(0, 0, -1)", - "(0, 0, -1)", - "(0, 0, -1)", - "(0, 0, -1)" - ] - }, - { - "skip": "not face[2]", - "texture": "trafo_texture", - "indices": [3, 7, 4, 0], - "uvs": [ - "(0, 0)", - "(1, 0)", - "(1, uv_height)", - "(0, uv_height)" - ], - "normals": [ - "(-1, 0, 0)", - "(-1, 0, 0)", - "(-1, 0, 0)", - "(-1, 0, 0)" - ] - }, - { - "skip": "not face[3]", - "texture": "trafo_texture", - "indices": [1, 5, 6, 2], - "uvs": [ - "(0, 0)", - "(1, 0)", - "(1, uv_height)", - "(0, uv_height)" - ], - "normals": [ - "(1, 0, 0)", - "(1, 0, 0)", - "(1, 0, 0)", - "(1, 0, 0)" - ] - }, - { - "skip": "not face[4]", - "texture": "trafo_texture", - "indices": [0, 4, 5, 1], - "uvs": [ - "(0, 0)", - "(1, 0)", - "(1, uv_height)", - "(0, uv_height)" - ], - "normals": [ - "(0, -1, 0)", - "(0, -1, 0)", - "(0, -1, 0)", - "(0, -1, 0)" - ] - }, - { - "skip": "not face[5]", - "texture": "trafo_texture", - "indices": [2, 6, 7, 3], - "uvs": [ - "(0, 0)", - "(1, 0)", - "(1, uv_height)", - "(0, uv_height)" - ], - "normals": [ - "(1, 0, 0)", - "(1, 0, 0)", - "(1, 0, 0)", - "(1, 0, 0)" - ] - } - ], - "instances": [] - }, - { - "identifier": "wood_trafo", - "showcase": { - "title": "Wood Trafo", - "icon": "WoodTrafo", - "type": "floor", - "cfgs": [ - { - "field": "height_", - "type": "float", - "title": "Height", - "desc": "The height of block.", - "default": "5.0" - }, - { - "field": "face_", - "type": "face", - "title": "Face", - "desc": "Whether has some faces.", - "default": "(True, False, True, True, True, True)" - } - ] - }, - "params": [ - { - "field": "height", - "data": "height_" - }, - { - "field": "face", - "data": "face_" - } - ], - "vars": [], - "vertices": [], - "faces": [], - "instances": [ - { - "identifier": "raw_trafo", - "skip": "False", - "params": { - "trafo_texture": "\"BallWood\"", - "height": "height", - "face": "face" - }, - "transform": "ident()" - } - ] - }, - { - "identifier": "stone_trafo", - "showcase": { - "title": "Stone Trafo", - "icon": "StoneTrafo", - "type": "floor", - "cfgs": [ - { - "field": "height_", - "type": "float", - "title": "Height", - "desc": "The height of block.", - "default": "5.0" - }, - { - "field": "face_", - "type": "face", - "title": "Face", - "desc": "Whether has some faces.", - "default": "(True, False, True, True, True, True)" - } - ] - }, - "params": [ - { - "field": "height", - "data": "height_" - }, - { - "field": "face", - "data": "face_" - } - ], - "vars": [], - "vertices": [], - "faces": [], - "instances": [ - { - "identifier": "raw_trafo", - "skip": "False", - "params": { - "trafo_texture": "\"BallStone\"", - "height": "height", - "face": "face" - }, - "transform": "ident()" - } - ] - }, - { - "identifier": "paper_trafo", - "showcase": { - "title": "Paper Trafo", - "icon": "PaperTrafo", - "type": "floor", - "cfgs": [ - { - "field": "height_", - "type": "float", - "title": "Height", - "desc": "The height of block.", - "default": "5.0" - }, - { - "field": "face_", - "type": "face", - "title": "Face", - "desc": "Whether has some faces.", - "default": "(True, False, True, True, True, True)" - } - ] - }, - "params": [ - { - "field": "height", - "data": "height_" - }, - { - "field": "face", - "data": "face_" - } - ], - "vars": [], - "vertices": [], - "faces": [], - "instances": [ - { - "identifier": "raw_trafo", - "skip": "False", - "params": { - "trafo_texture": "\"BallPaper\"", - "height": "height", - "face": "face" - }, - "transform": "ident()" - } - ] - } -] \ No newline at end of file diff --git a/bbp_ng/jsons/.gitkeep b/bbp_ng/jsons/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/bbp_ng/raw_jsons/trafos.json b/bbp_ng/raw_jsons/trafos.json new file mode 100644 index 0000000..6ef2a7f Binary files /dev/null and b/bbp_ng/raw_jsons/trafos.json differ diff --git a/bbp_ng/tools/build_icons.py b/bbp_ng/tools/build_icons.py index fe8f9e2..37e7751 100644 --- a/bbp_ng/tools/build_icons.py +++ b/bbp_ng/tools/build_icons.py @@ -1,4 +1,5 @@ import os +import common import PIL, PIL.Image # the config for thumbnail @@ -12,29 +13,29 @@ def resize_image(src_file: str, dst_file: str) -> None: # save to new file src_image.save(dst_file) -def relative_to_folder(abs_path: str, src_parent: str, dst_parent: str) -> str: - return os.path.join(dst_parent, os.path.relpath(abs_path, src_parent)) - def create_thumbnails() -> None: # get folder path root_folder: str = os.path.dirname(os.path.dirname(__file__)) - raw_icons_folder: str = os.path.join(root_folder, 'raw_icons') - icons_folder: str = os.path.join(root_folder, 'icons') - # iterate raw icons folder - for root, dirs, files in os.walk(raw_icons_folder, topdown = True): - # iterate folder and create it in dest folder - for name in dirs: - src_folder: str = os.path.join(root, name) - dst_folder: str = relative_to_folder(src_folder, raw_icons_folder, icons_folder) - print(f'Creating Folder: {src_folder} -> {dst_folder}') - os.makedirs(dst_folder, exist_ok = True) - for name in files: - if not name.endswith('.png'): continue # skip non-image - src_file: str = os.path.join(root, name) - dst_file: str = relative_to_folder(src_file, raw_icons_folder, icons_folder) - print(f'Processing Thumbnail: {src_file} -> {dst_file}') - resize_image(src_file, dst_file) + # prepare handler + def folder_handler(src_folder: str, dst_folder: str) -> None: + # just create folder + print(f'Creating Folder: {src_folder} -> {dst_folder}') + os.makedirs(dst_folder, exist_ok = True) + def file_handler(src_file: str, dst_file: str) -> None: + # skip non-image + if not src_file.endswith('.png'): return + # call thumbnail func + print(f'Processing Thumbnail: {src_file} -> {dst_file}') + resize_image(src_file, dst_file) + + # call common processor + common.common_file_migrator( + os.path.join(root_folder, 'raw_icons'), + os.path.join(root_folder, 'icons'), + folder_handler, + file_handler + ) print('Done.') diff --git a/bbp_ng/tools/build_jsons.py b/bbp_ng/tools/build_jsons.py new file mode 100644 index 0000000..72e2af1 --- /dev/null +++ b/bbp_ng/tools/build_jsons.py @@ -0,0 +1,43 @@ +import os, json +import common + +def compress_json(src_file: str, dst_file: str) -> None: + with open(src_file, 'r', encoding = 'utf-8') as fr: + with open(dst_file, 'w', encoding = 'utf-8') as fw: + json.dump( + json.load(fr), # load from src file + fw, + indent = None, # no indent. the most narrow style. + separators = (',', ':'), # also for narrow style. + sort_keys = False, # do not sort key + ) + +def create_compressed_jsons() -> None: + # get folder path + root_folder: str = os.path.dirname(os.path.dirname(__file__)) + + # prepare handler + def folder_handler(src_folder: str, dst_folder: str) -> None: + # just create folder + print(f'Creating Folder: {src_folder} -> {dst_folder}') + os.makedirs(dst_folder, exist_ok = True) + def file_handler(src_file: str, dst_file: str) -> None: + # skip non-json + if not src_file.endswith('.json'): return + # call compress func + print(f'Processing Json: {src_file} -> {dst_file}') + compress_json(src_file, dst_file) + + # call common processor + common.common_file_migrator( + os.path.join(root_folder, 'raw_jsons'), + os.path.join(root_folder, 'jsons'), + folder_handler, + file_handler + ) + + print('Done.') + +if __name__ == '__main__': + create_compressed_jsons() + diff --git a/bbp_ng/tools/common.py b/bbp_ng/tools/common.py new file mode 100644 index 0000000..bb4da68 --- /dev/null +++ b/bbp_ng/tools/common.py @@ -0,0 +1,57 @@ +import os, typing + +def relative_to_folder(abs_path: str, src_parent: str, dst_parent: str) -> str: + """ + Rebase one path to another path. + + Give a absolute file path and folder path, and compute the relative path of given file to given folder. + Then applied the computed relative path to another given folder path. + Thus it seems like the file was rebased to from a folder to another folder with keeping the folder hierarchy. + + For example, given `/path/to/file` and `/path`, it will compute relative path `to/file`. + Then it was applied to another folder path `/new` and got `/new/to/file`. + + @param abs_path[in] The absolute path to a folder or file. + @param src_parent[in] The absolute path to folder which the `abs_path` will have relative path to. + @param dst_parent[in] The absolute path to folder which the relative path will be applied to. + """ + return os.path.join(dst_parent, os.path.relpath(abs_path, src_parent)) + +def common_file_migrator( + from_folder: str, to_folder: str, + fct_proc_folder: typing.Callable[[str, str], None], + fct_proc_file: typing.Callable[[str, str], None]) -> None: + """ + Common file migrator used by some build script. + + This function receive 2 absolute folder path. `from_folder` indicate the file migrated out, + and `to_folder` indicate the file migrated in. + `fct_proc_folder` is a function pointer from caller which handle folder migration in detail. + `fct_proc_file` is same but handle file migration. + + `fct_proc_folder` will receive 2 args. First is the source folder. Second is expected dest folder. + `fct_proc_file` is same, but receive the file path instead. + Both of these function pointer should do the migration in detail. This function will only just iterate + folder and give essential args and will not do any migration operations such as copying or moving. + + @param from_folder[in] The folder need to be migrated. + @param to_folder[in] The folder will be migrated to. + @param fct_proc_folder[in] Folder migration detail handler. + @param fct_proc_file[in] File migration detail handler. + """ + # iterate from_folder folder + for root, dirs, files in os.walk(from_folder, topdown = True): + # iterate folders + for name in dirs: + # prepare handler args + src_folder: str = os.path.join(root, name) + dst_folder: str = relative_to_folder(src_folder, from_folder, to_folder) + # call handler + fct_proc_folder(src_folder, dst_folder) + # iterate files + for name in files: + # prepare handler args + src_file: str = os.path.join(root, name) + dst_file: str = relative_to_folder(src_file, from_folder, to_folder) + # call handler + fct_proc_file(src_file, dst_file)