mntm-asset-packer 1.1.1__py3-none-any.whl → 1.1.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,8 +1,8 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mntm-asset-packer
3
- Version: 1.1.1
3
+ Version: 1.1.3
4
4
  Summary: An improved asset packer script to make the process of creating and packing asset packs for the Momentum firmware easier.
5
- Author-email: notnotnescap <97590612+nescapp@users.noreply.github.com>
5
+ Author-email: notnotnescap <nescap@tuta.io>
6
6
  Requires-Python: >=3.11
7
7
  Requires-Dist: heatshrink2>=0.13.0
8
8
  Requires-Dist: pillow>=11.2.1
@@ -0,0 +1,5 @@
1
+ mntm_asset_packer.py,sha256=0wSoBAX9JRgwnWrEiMls6_YMpoJv1v-LPF4YPNXlIdg,26940
2
+ mntm_asset_packer-1.1.3.dist-info/METADATA,sha256=OZTt7_-bEkH9Pd17zQqRV6SnjbX80MzMaEQaPzyjT6E,3621
3
+ mntm_asset_packer-1.1.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
4
+ mntm_asset_packer-1.1.3.dist-info/entry_points.txt,sha256=CF05qVMVPPNhTroKeH_kkKqVgG-mJ-Q0mSAZHpfxkr0,61
5
+ mntm_asset_packer-1.1.3.dist-info/RECORD,,
mntm_asset_packer.py CHANGED
@@ -1,31 +1,36 @@
1
1
  #!/usr/bin/env python3
2
- """
3
- An improved asset packer for the Momentum firmware.
2
+ """Script to pack and recover asset packs for Momentum.
3
+
4
+ I recommend installing the mntm-asset-packer package from PyPI instead of using this script directly.
5
+ more info here: https://github.com/notnotnescap/mntm-asset-packer
4
6
  This is a modification of the original asset_packer script by @Willy-JL
5
7
  """
6
8
 
9
+ import importlib.metadata
10
+ import io
11
+ import os
7
12
  import pathlib
13
+ import re
8
14
  import shutil
9
15
  import struct
10
- import typing
11
- import time
12
- import re
13
- import io
14
- import os
15
16
  import sys
16
- from PIL import Image, ImageOps
17
+ import time
18
+ import typing
19
+ from pathlib import Path
20
+
17
21
  import heatshrink2
22
+ from PIL import Image, ImageOps
18
23
 
19
- HELP_MESSAGE = """The asset packer converts animations with a specific structure to be efficient and compatible
20
- with the asset pack system used in Momentum. More info: https://github.com/Kuronons/FZ_graphics
24
+ HELP_MESSAGE = """The asset packer converts animations with a specific structure to be \
25
+ efficient and compatible with the asset pack system used in Momentum.
26
+ More info: https://github.com/Kuronons/FZ_graphics
21
27
 
22
28
  Usage :
23
29
  \033[32mmntm-asset-packer \033[0;33;1mhelp\033[0m
24
30
  \033[3mDisplays this message
25
31
  \033[0m
26
32
  \033[32mmntm-asset-packer \033[0;33;1mcreate <Asset Pack Name>\033[0m
27
- \033[3mCreates a directory with the correct file structure that can be used
28
- to prepare for the packing process.
33
+ \033[3mCreates a directory with the correct file structure that can be used to prepare for the packing process.
29
34
  \033[0m
30
35
  \033[32mmntm-asset-packer \033[0;33;1mpack <./path/to/AssetPack>\033[0m
31
36
  \033[3mPacks the specified asset pack into './asset_packs/AssetPack'
@@ -37,15 +42,13 @@ Usage :
37
42
  \033[3mSame as 'mntm-asset-packer pack all'
38
43
  \033[0m
39
44
  \033[32mmntm-asset-packer \033[0;33;1mrecover <./asset_packs/AssetPack>\033[0m
40
- \033[3mRecovers the png frame(s) from a compiled assets for the specified asset pack
41
- The recovered asset pack is saved in './recovered/AssetPack'
45
+ \033[3mRecovers the png frame(s) from a compiled assets for the specified asset pack. The recovered asset pack is saved in './recovered/AssetPack'
42
46
  \033[0m
43
47
  \033[32mmntm-asset-packer \033[0;33;1mrecover all\033[0m
44
48
  \033[3mRecovers all asset packs in './asset_packs/' into './recovered/'
45
49
  \033[0m
46
50
  \033[32mmntm-asset-packer \033[0;33;1mconvert <./path/to/AssetPack>\033[0m
47
- \033[3mConverts all anim frames to .png files and renames them to the correct format.
48
- (requires numbers in filenames)
51
+ \033[3mConverts all anim frames to .png files and renames them to the correct format. (requires numbers in filenames)
49
52
  \033[0m
50
53
  """
51
54
 
@@ -78,9 +81,11 @@ Active cooldown: 0
78
81
  Bubble slots: 0
79
82
  """
80
83
 
84
+ VERSION = importlib.metadata.version("mntm-asset-packer")
85
+
81
86
 
82
87
  def convert_to_bm(img: "Image.Image | pathlib.Path") -> bytes:
83
- """Converts an image to a bitmap"""
88
+ """Converts an image to a bitmap."""
84
89
  if not isinstance(img, Image.Image):
85
90
  img = Image.open(img)
86
91
 
@@ -107,7 +112,7 @@ def convert_to_bm(img: "Image.Image | pathlib.Path") -> bytes:
107
112
 
108
113
 
109
114
  def convert_to_bmx(img: "Image.Image | pathlib.Path") -> bytes:
110
- """Converts an image to a bmx that contains image size info"""
115
+ """Converts an image to a bmx that contains image size info."""
111
116
  if not isinstance(img, Image.Image):
112
117
  img = Image.open(img)
113
118
 
@@ -117,15 +122,15 @@ def convert_to_bmx(img: "Image.Image | pathlib.Path") -> bytes:
117
122
 
118
123
 
119
124
  def recover_from_bm(bm: "bytes | pathlib.Path", width: int, height: int) -> Image.Image:
120
- """Converts a bitmap back to a png (same as convert_to_bm but in reverse) The resulting png
121
- will not always be the same as the original image as some information is lost during the
122
- conversion"""
125
+ """Converts a bitmap back to a png (same as convert_to_bm but in reverse).
126
+
127
+ The resulting png will not always be the same as the original image as some
128
+ information is lost during the conversion.
129
+ """
123
130
  if not isinstance(bm, bytes):
124
131
  bm = bm.read_bytes()
125
132
 
126
- # expected_length = (width * height + 7) // 8
127
-
128
- if bm.startswith(b'\x01\x00'):
133
+ if bm.startswith(b"\x01\x00"):
129
134
  data_dec = heatshrink2.decompress(bm[4:], window_sz2=8, lookahead_sz2=4)
130
135
  else:
131
136
  data_dec = bm[1:]
@@ -139,7 +144,7 @@ def recover_from_bm(bm: "bytes | pathlib.Path", width: int, height: int) -> Imag
139
144
  if len(pixels) < num_target_pixels:
140
145
  pixels.append(1 - ((byte_val >> i) & 1))
141
146
  else:
142
- break
147
+ break
143
148
  if len(pixels) >= num_target_pixels:
144
149
  break
145
150
 
@@ -149,7 +154,7 @@ def recover_from_bm(bm: "bytes | pathlib.Path", width: int, height: int) -> Imag
149
154
 
150
155
 
151
156
  def recover_from_bmx(bmx: "bytes | pathlib.Path") -> Image.Image:
152
- """Converts a bmx back to a png (same as convert_to_bmx but in reverse)"""
157
+ """Converts a bmx back to a png (same as convert_to_bmx but in reverse)."""
153
158
  if not isinstance(bmx, bytes):
154
159
  bmx = bmx.read_bytes()
155
160
 
@@ -157,21 +162,23 @@ def recover_from_bmx(bmx: "bytes | pathlib.Path") -> Image.Image:
157
162
  return recover_from_bm(bmx[8:], width, height)
158
163
 
159
164
 
160
- def copy_file_as_lf(src: "pathlib.Path", dst: "pathlib.Path"):
161
- """Copy file but replace Windows Line Endings with Unix Line Endings"""
165
+ def copy_file_as_lf(src: "pathlib.Path", dst: "pathlib.Path") -> None:
166
+ """Copy file but replace Windows Line Endings with Unix Line Endings."""
162
167
  dst.write_bytes(src.read_bytes().replace(b"\r\n", b"\n"))
163
168
 
164
169
 
165
- def pack_anim(src: pathlib.Path, dst: pathlib.Path):
166
- """Packs an anim"""
170
+ def pack_anim(src: pathlib.Path, dst: pathlib.Path) -> None:
171
+ """Packs an anim."""
167
172
  if not (src / "meta.txt").is_file():
168
- print(f"\033[31mNo meta.txt found in \"{src.name}\" anim.\033[0m")
173
+ print(f'\033[31mNo meta.txt found in "{src.name}" anim.\033[0m')
169
174
  return
170
- if not any(re.match(r"frame_\d+.(png|bm)", file.name) for file in src.iterdir()):
171
- print(f"\033[31mNo frames with the required format found in \"{src.name}\" anim.\033[0m")
175
+ if not any(re.match(r"frame_\d+\.(png|bm)", file.name) for file in src.iterdir()):
176
+ print(
177
+ f'\033[31mNo frames with the required format found in "{src.name}" anim.\033[0m',
178
+ )
172
179
  try:
173
180
  input(
174
- "Press [Enter] to convert and rename the frames or [Ctrl+C] to cancel\033[0m"
181
+ "Press [Enter] to convert and rename the frames or [Ctrl+C] to cancel\033[0m",
175
182
  )
176
183
  except KeyboardInterrupt:
177
184
  sys.exit(0)
@@ -187,18 +194,19 @@ def pack_anim(src: pathlib.Path, dst: pathlib.Path):
187
194
  elif frame.name.startswith("frame_"):
188
195
  if frame.suffix == ".png":
189
196
  (dst / frame.with_suffix(".bm").name).write_bytes(convert_to_bm(frame))
190
- elif frame.suffix == ".bm":
191
- if not (dst / frame.name).is_file():
192
- shutil.copyfile(frame, dst / frame.name)
197
+ elif frame.suffix == ".bm" and not (dst / frame.name).is_file():
198
+ shutil.copyfile(frame, dst / frame.name)
193
199
 
194
200
 
195
- def recover_anim(src: pathlib.Path, dst: pathlib.Path):
196
- """Converts a bitmap to a png"""
197
- if not os.path.exists(src):
198
- print(f"\033[31mError: \"{src}\" not found\033[0m")
201
+ def recover_anim(src: pathlib.Path, dst: pathlib.Path) -> None:
202
+ """Converts a bitmap to a png."""
203
+ if not Path.exists(src):
204
+ print(f'\033[31mError: "{src}" not found\033[0m')
199
205
  return
200
206
  if not any(re.match(r"frame_\d+.bm", file.name) for file in src.iterdir()):
201
- print(f"\033[31mNo frames with the required format found in \"{src.name}\" anim.\033[0m")
207
+ print(
208
+ f'\033[31mNo frames with the required format found in "{src.name}" anim.\033[0m',
209
+ )
202
210
  return
203
211
 
204
212
  dst.mkdir(parents=True, exist_ok=True)
@@ -206,9 +214,9 @@ def recover_anim(src: pathlib.Path, dst: pathlib.Path):
206
214
  width = 128
207
215
  height = 64
208
216
  meta = src / "meta.txt"
209
- if os.path.exists(meta):
217
+ if Path.exists(meta):
210
218
  shutil.copyfile(meta, dst / meta.name)
211
- with open(meta, "r", encoding="utf-8") as f:
219
+ with Path.open(meta, encoding="utf-8") as f:
212
220
  for line in f:
213
221
  if line.startswith("Width:"):
214
222
  width = int(line.split(":")[1].strip())
@@ -223,8 +231,8 @@ def recover_anim(src: pathlib.Path, dst: pathlib.Path):
223
231
  img.save(dst / file.with_suffix(".png").name)
224
232
 
225
233
 
226
- def pack_animated_icon(src: pathlib.Path, dst: pathlib.Path):
227
- """Packs an animated icon"""
234
+ def pack_animated_icon(src: pathlib.Path, dst: pathlib.Path) -> None:
235
+ """Packs an animated ico."""
228
236
  if not (src / "frame_rate").is_file() and not (src / "meta").is_file():
229
237
  return
230
238
  dst.mkdir(parents=True, exist_ok=True)
@@ -254,8 +262,8 @@ def pack_animated_icon(src: pathlib.Path, dst: pathlib.Path):
254
262
  (dst / "meta").write_bytes(struct.pack("<IIII", *size, frame_rate, frame_count))
255
263
 
256
264
 
257
- def recover_animated_icon(src: pathlib.Path, dst: pathlib.Path):
258
- """Recovers an animated icon"""
265
+ def recover_animated_icon(src: pathlib.Path, dst: pathlib.Path) -> None:
266
+ """Recovers an animated icon."""
259
267
  meta_file_path = src / "meta"
260
268
 
261
269
  if not meta_file_path.is_file():
@@ -263,7 +271,7 @@ def recover_animated_icon(src: pathlib.Path, dst: pathlib.Path):
263
271
 
264
272
  unpacked_meta_data = None
265
273
  try:
266
- with open(meta_file_path, "rb") as f:
274
+ with Path.open(meta_file_path, "rb") as f:
267
275
  expected_bytes_count = struct.calcsize("<IIII")
268
276
  data_bytes = f.read(expected_bytes_count)
269
277
  if len(data_bytes) < expected_bytes_count:
@@ -271,9 +279,11 @@ def recover_animated_icon(src: pathlib.Path, dst: pathlib.Path):
271
279
  return
272
280
  unpacked_meta_data = struct.unpack("<IIII", data_bytes)
273
281
  except struct.error:
274
- print(f"Error: Failed to unpack meta file '{meta_file_path}'. It might be corrupted.")
282
+ print(
283
+ f"Error: Failed to unpack meta file '{meta_file_path}'. It might be corrupted.",
284
+ )
275
285
  return
276
- except Exception as e: # Catch other potential IO errors
286
+ except OSError as e: # Catch file-related IO errors
277
287
  print(f"Error reading meta file '{meta_file_path}': {e}")
278
288
  return
279
289
 
@@ -293,45 +303,42 @@ def recover_animated_icon(src: pathlib.Path, dst: pathlib.Path):
293
303
  try:
294
304
  frame = recover_from_bm(frame_bm_file_path, image_width, image_height)
295
305
  frame.save(dst / f"frame_{i:02}.png")
296
- except Exception as e:
306
+ except (OSError, ValueError) as e:
297
307
  print(f"Error recovering or saving frame '{frame_bm_file_path}': {e}")
298
- continue # skip to the next frame if an error occurs
308
+ continue # skip to the next frame if an error occurs
299
309
 
300
310
  (dst / "frame_rate").write_text(str(frame_rate_value))
301
311
 
302
312
 
303
- def pack_static_icon(src: pathlib.Path, dst: pathlib.Path):
304
- """Packs a static icon"""
313
+ def pack_static_icon(src: pathlib.Path, dst: pathlib.Path) -> None:
314
+ """Packs a static icon."""
305
315
  dst.parent.mkdir(parents=True, exist_ok=True)
306
316
  if src.suffix == ".png":
307
317
  dst.with_suffix(".bmx").write_bytes(convert_to_bmx(src))
308
- elif src.suffix == ".bmx":
309
- if not dst.is_file():
310
- shutil.copyfile(src, dst)
318
+ elif src.suffix == ".bmx" and not dst.is_file():
319
+ shutil.copyfile(src, dst)
311
320
 
312
321
 
313
- def recover_static_icon(src: pathlib.Path, dst: pathlib.Path):
314
- """Recovers a static icon"""
322
+ def recover_static_icon(src: pathlib.Path, dst: pathlib.Path) -> None:
323
+ """Recovers a static icon."""
315
324
  dst.parent.mkdir(parents=True, exist_ok=True)
316
325
  if src.suffix == ".bmx":
317
326
  recover_from_bmx(src).save(dst.with_suffix(".png"))
318
327
 
319
328
 
320
- def pack_font(src: pathlib.Path, dst: pathlib.Path):
321
- """Packs a font"""
329
+ def pack_font(src: pathlib.Path, dst: pathlib.Path) -> None:
330
+ """Packs a font."""
322
331
  dst.parent.mkdir(parents=True, exist_ok=True)
323
332
  if src.suffix == ".c":
324
- code = (
325
- src.read_bytes().split(b' U8G2_FONT_SECTION("')[1].split(b'") =')[1].strip()
326
- )
333
+ try:
334
+ code = src.read_bytes().split(b' U8G2_FONT_SECTION("')[1].split(b'") =')[1].strip()
335
+ except IndexError:
336
+ print(f'\033[31mError: "{src.name}" is not a valid font file.\033[0m')
337
+ return
327
338
  font = b""
328
339
  for line in code.splitlines():
329
340
  if line.count(b'"') == 2:
330
- font += (
331
- line[line.find(b'"') + 1 : line.rfind(b'"')]
332
- .decode("unicode_escape")
333
- .encode("latin_1")
334
- )
341
+ font += line[line.find(b'"') + 1 : line.rfind(b'"')].decode("unicode_escape").encode("latin_1")
335
342
  font += b"\0"
336
343
  dst.with_suffix(".u8f").write_bytes(font)
337
344
  elif src.suffix == ".u8f":
@@ -342,27 +349,25 @@ def pack_font(src: pathlib.Path, dst: pathlib.Path):
342
349
  # recover font is not implemented
343
350
 
344
351
 
345
- def convert_and_rename_frames(directory: "str | pathlib.Path", logger: typing.Callable):
346
- """Converts all frames to png and renames them "frame_N.png"
347
- (requires the image name to contain the frame number)"""
352
+ def convert_and_rename_frames(directory: "str | pathlib.Path", logger: typing.Callable) -> None:
353
+ """Converts all frames to png and renames them "frame_N.png".
354
+
355
+ (requires the image name to contain the frame number)
356
+ """
348
357
  already_formatted = True
349
358
  for file in directory.iterdir():
350
- if file.is_file() and file.suffix in (".jpg", ".jpeg", ".png"):
351
- if not re.match(r"frame_\d+.png", file.name):
352
- already_formatted = False
353
- break
359
+ if file.is_file() and file.suffix in (".jpg", ".jpeg", ".png") and not re.match(r"frame_\d+.png", file.name):
360
+ already_formatted = False
361
+ break
354
362
  if already_formatted:
355
- logger(f"\"{directory.name}\" anim is formatted")
363
+ logger(f'"{directory.name}" anim is formatted')
356
364
  return
357
365
 
358
366
  try:
359
367
  print(
360
- f"\033[31mThis will convert all frames for the \"{directory.name}\" anim to png and rename them.\n"
361
- "This action is irreversible, make sure to back up your files if needed.\n\033[0m"
362
- )
363
- input(
364
- "Press [Enter] if you wish to continue or [Ctrl+C] to cancel"
368
+ f'\033[31mThis will convert all frames for the "{directory.name}" anim to png and rename them.\nThis action is irreversible, make sure to back up your files if needed.\n\033[0m',
365
369
  )
370
+ input("Press [Enter] if you wish to continue or [Ctrl+C] to cancel")
366
371
  except KeyboardInterrupt:
367
372
  sys.exit(0)
368
373
  print()
@@ -382,16 +387,26 @@ def convert_and_rename_frames(directory: "str | pathlib.Path", logger: typing.Ca
382
387
  file.unlink()
383
388
 
384
389
 
385
- def convert_and_rename_frames_for_all_anims(directory_for_anims: "str | pathlib.Path", logger: typing.Callable):
386
- """Converts all frames to png and renames them "frame_N.png for all anims in the given anim folder.
387
- (requires the image name to contain the frame number)"""
390
+ def convert_and_rename_frames_for_all_anims(
391
+ directory_for_anims: "str | pathlib.Path",
392
+ logger: typing.Callable,
393
+ ) -> None:
394
+ """Formats all anim frames correctly.
395
+
396
+ Converts all frames to png and renames them "frame_N.png for all anims in the given anim folder.
397
+ (requires the image name to contain the frame number)
398
+ """
388
399
  for anim in directory_for_anims.iterdir():
389
400
  if anim.is_dir():
390
401
  convert_and_rename_frames(anim, logger)
391
402
 
392
403
 
393
- def pack_specific(asset_pack_path: "str | pathlib.Path", output_directory: "str | pathlib.Path", logger: typing.Callable):
394
- """Packs a specific asset pack"""
404
+ def pack_specific(
405
+ asset_pack_path: "str | pathlib.Path",
406
+ output_directory: "str | pathlib.Path",
407
+ logger: typing.Callable,
408
+ ) -> None:
409
+ """Packs a specific asset pack."""
395
410
  asset_pack_path = pathlib.Path(asset_pack_path)
396
411
  output_directory = pathlib.Path(output_directory)
397
412
  logger(f"Packing '\033[3m{asset_pack_path.name}\033[0m'")
@@ -404,7 +419,7 @@ def pack_specific(asset_pack_path: "str | pathlib.Path", output_directory: "str
404
419
 
405
420
  if packed.exists():
406
421
  try:
407
- if packed.is_dir():
422
+ if packed.is_dir() and not packed.is_symlink():
408
423
  shutil.rmtree(packed, ignore_errors=True)
409
424
  else:
410
425
  packed.unlink()
@@ -413,22 +428,23 @@ def pack_specific(asset_pack_path: "str | pathlib.Path", output_directory: "str
413
428
 
414
429
  # packing anims
415
430
  if (asset_pack_path / "Anims/manifest.txt").exists():
416
- (packed / "Anims").mkdir(parents=True, exist_ok=True) # ensure that the "Anims" directory exists
417
- copy_file_as_lf(asset_pack_path / "Anims/manifest.txt", packed / "Anims/manifest.txt")
431
+ (packed / "Anims").mkdir(
432
+ parents=True,
433
+ exist_ok=True,
434
+ ) # ensure that the "Anims" directory exists
435
+ copy_file_as_lf(
436
+ asset_pack_path / "Anims/manifest.txt",
437
+ packed / "Anims/manifest.txt",
438
+ )
418
439
  manifest = (asset_pack_path / "Anims/manifest.txt").read_bytes()
419
440
 
420
441
  # Find all the anims in the manifest
421
442
  for anim in re.finditer(rb"Name: (.*)", manifest):
422
- anim = (
423
- anim.group(1)
424
- .decode()
425
- .replace("\\", "/")
426
- .replace("/", os.sep)
427
- .replace("\r", "\n")
428
- .strip()
443
+ anim_name = anim.group(1).decode().replace("\\", "/").replace("/", os.sep).replace("\r", "\n").strip()
444
+ logger(
445
+ f"Compiling anim '\033[3m{anim_name}\033[0m' for '\033[3m{asset_pack_path.name}\033[0m'",
429
446
  )
430
- logger(f"Compiling anim '\033[3m{anim}\033[0m' for '\033[3m{asset_pack_path.name}\033[0m'")
431
- pack_anim(asset_pack_path / "Anims" / anim, packed / "Anims" / anim)
447
+ pack_anim(asset_pack_path / "Anims" / anim_name, packed / "Anims" / anim_name)
432
448
 
433
449
  # packing icons
434
450
  if (asset_pack_path / "Icons").is_dir():
@@ -439,20 +455,20 @@ def pack_specific(asset_pack_path: "str | pathlib.Path", output_directory: "str
439
455
  if icon.name.startswith("."):
440
456
  continue
441
457
  if icon.is_dir():
442
- logger(f"Compiling icon for pack '{asset_pack_path.name}': {icons.name}/{icon.name}")
458
+ logger(
459
+ f"Compiling icon for pack '{asset_pack_path.name}': {icons.name}/{icon.name}",
460
+ )
443
461
  pack_animated_icon(icon, packed / "Icons" / icons.name / icon.name)
444
462
  elif icon.is_file() and icon.suffix in (".png", ".bmx"):
445
- logger(f"Compiling icon for pack '{asset_pack_path.name}': {icons.name}/{icon.name}")
463
+ logger(
464
+ f"Compiling icon for pack '{asset_pack_path.name}': {icons.name}/{icon.name}",
465
+ )
446
466
  pack_static_icon(icon, packed / "Icons" / icons.name / icon.name)
447
467
 
448
468
  # packing fonts
449
469
  if (asset_pack_path / "Fonts").is_dir():
450
470
  for font in (asset_pack_path / "Fonts").iterdir():
451
- if (
452
- not font.is_file()
453
- or font.name.startswith(".")
454
- or font.suffix not in (".c", ".u8f")
455
- ):
471
+ if not font.is_file() or font.name.startswith(".") or font.suffix not in (".c", ".u8f"):
456
472
  continue
457
473
  logger(f"Compiling font for pack '{asset_pack_path.name}': {font.name}")
458
474
  pack_font(font, packed / "Fonts" / font.name)
@@ -461,8 +477,12 @@ def pack_specific(asset_pack_path: "str | pathlib.Path", output_directory: "str
461
477
  logger(f"Saved to: '\033[33m{packed}\033[0m'")
462
478
 
463
479
 
464
- def recover_specific(asset_pack_path: "str | pathlib.Path", output_directory: "str | pathlib.Path", logger: typing.Callable):
465
- """Recovers a specific asset pack"""
480
+ def recover_specific(
481
+ asset_pack_path: "str | pathlib.Path",
482
+ output_directory: "str | pathlib.Path",
483
+ logger: typing.Callable,
484
+ ) -> None:
485
+ """Recovers a specific asset pack."""
466
486
  asset_pack_path = pathlib.Path(asset_pack_path)
467
487
  output_directory = pathlib.Path(output_directory)
468
488
  logger(f"Recovering '\033[3m{asset_pack_path.name}\033[0m'")
@@ -484,11 +504,17 @@ def recover_specific(asset_pack_path: "str | pathlib.Path", output_directory: "s
484
504
 
485
505
  # recovering anims
486
506
  if (asset_pack_path / "Anims").is_dir():
487
- (recovered / "Anims").mkdir(parents=True, exist_ok=True) # ensure that the "Anims" directory exists
507
+ (recovered / "Anims").mkdir(
508
+ parents=True,
509
+ exist_ok=True,
510
+ ) # ensure that the "Anims" directory exists
488
511
 
489
512
  # copy the manifest if it exists
490
513
  if (asset_pack_path / "Anims/manifest.txt").exists():
491
- shutil.copyfile(asset_pack_path / "Anims/manifest.txt", recovered / "Anims/manifest.txt")
514
+ shutil.copyfile(
515
+ asset_pack_path / "Anims/manifest.txt",
516
+ recovered / "Anims/manifest.txt",
517
+ )
492
518
 
493
519
  # recover all the anims in the Anims directory
494
520
  for anim in (asset_pack_path / "Anims").iterdir():
@@ -514,31 +540,24 @@ def recover_specific(asset_pack_path: "str | pathlib.Path", output_directory: "s
514
540
 
515
541
  # recovering fonts
516
542
  if (asset_pack_path / "Fonts").is_dir():
517
- # for font in (asset_pack_path / "Fonts").iterdir():
518
- # if (
519
- # not font.is_file()
520
- # or font.name.startswith(".")
521
- # or font.suffix not in (".c", ".u8f")
522
- # ):
523
- # continue
524
- # logger(f"Compiling font for pack '{asset_pack_path.name}': {font.name}")
525
- # pack_font(font, recovered / "Fonts" / font.name)
526
- logger("Fonts recovery not implemented yet") #TODO: implement
543
+ logger("Fonts recovery not implemented yet")
527
544
 
528
545
  logger(f"\033[32mFinished recovering '\033[3m{asset_pack_path.name}\033[23m'\033[0m")
529
546
  logger(f"Saved to: '\033[33m{recovered}\033[0m'")
530
547
 
531
548
 
532
- def pack_all_asset_packs(source_directory: "str | pathlib.Path", output_directory: "str | pathlib.Path", logger: typing.Callable):
533
- """Packs all asset packs in the source directory"""
549
+ def pack_all_asset_packs(
550
+ source_directory: "str | pathlib.Path",
551
+ output_directory: "str | pathlib.Path",
552
+ logger: typing.Callable,
553
+ ) -> None:
554
+ """Packs all asset packs in the source directory."""
534
555
  try:
535
556
  print(
536
- "This will pack all asset packs in the current directory.\n"
537
- "The resulting asset packs will be saved to './asset_packs'\n"
538
- )
539
- input(
540
- "Press [Enter] if you wish to continue or [Ctrl+C] to cancel"
557
+ "This will pack all asset packs in the current directory."
558
+ "The resulting asset packs will be saved to './asset_packs'\n",
541
559
  )
560
+ input("Press [Enter] if you wish to continue or [Ctrl+C] to cancel")
542
561
  except KeyboardInterrupt:
543
562
  sys.exit(0)
544
563
  print()
@@ -550,22 +569,24 @@ def pack_all_asset_packs(source_directory: "str | pathlib.Path", output_director
550
569
  # Skip folders that are definitely not meant to be packed
551
570
  if source == output_directory:
552
571
  continue
553
- if not source.is_dir() or source.name.startswith(".") or source.name in ("venv", "recovered") :
572
+ if not source.is_dir() or source.name.startswith(".") or source.name in ("venv", "recovered"):
554
573
  continue
555
574
 
556
575
  pack_specific(source, output_directory, logger)
557
576
 
558
577
 
559
- def recover_all_asset_packs(source_directory: "str | pathlib.Path", output_directory: "str | pathlib.Path", logger: typing.Callable):
560
- """Recovers all asset packs in the source directory"""
578
+ def recover_all_asset_packs(
579
+ source_directory: "str | pathlib.Path",
580
+ output_directory: "str | pathlib.Path",
581
+ logger: typing.Callable,
582
+ ) -> None:
583
+ """Recovers all asset packs in the source directory."""
561
584
  try:
562
585
  print(
563
- "This will recover all asset packs in the current directory.\n"
564
- "The resulting asset packs will be saved to './recovered'\n"
565
- )
566
- input(
567
- "Press [Enter] if you wish to continue or [Ctrl+C] to cancel"
586
+ "This will recover all asset packs in the current directory."
587
+ "The resulting asset packs will be saved to './recovered'\n",
568
588
  )
589
+ input("Press [Enter] if you wish to continue or [Ctrl+C] to cancel")
569
590
  except KeyboardInterrupt:
570
591
  sys.exit(0)
571
592
  print()
@@ -577,15 +598,18 @@ def recover_all_asset_packs(source_directory: "str | pathlib.Path", output_direc
577
598
  # Skip folders that are definitely not meant to be recovered
578
599
  if source == output_directory:
579
600
  continue
580
- if not source.is_dir() or source.name.startswith(".") or source.name in ("venv", "recovered") :
601
+ if not source.is_dir() or source.name.startswith(".") or source.name in ("venv", "recovered"):
581
602
  continue
582
603
 
583
604
  recover_specific(source, output_directory, logger)
584
605
 
585
606
 
586
- def create_asset_pack(asset_pack_name: str, output_directory: "str | pathlib.Path", logger: typing.Callable):
587
- """Creates the file structure for an asset pack"""
588
-
607
+ def create_asset_pack(
608
+ asset_pack_name: str,
609
+ output_directory: "str | pathlib.Path",
610
+ logger: typing.Callable,
611
+ ) -> None:
612
+ """Creates the file structure for an asset pack."""
589
613
  if not isinstance(output_directory, pathlib.Path):
590
614
  output_directory = pathlib.Path(output_directory)
591
615
 
@@ -607,74 +631,106 @@ def create_asset_pack(asset_pack_name: str, output_directory: "str | pathlib.Pat
607
631
  # creating "manifest.txt" file
608
632
  if generate_example_files:
609
633
  (output_directory / asset_pack_name / "Anims" / "manifest.txt").touch()
610
- with open(output_directory / asset_pack_name / "Anims" / "manifest.txt", "w", encoding="utf-8") as f:
634
+ with Path.open(
635
+ output_directory / asset_pack_name / "Anims" / "manifest.txt",
636
+ "w",
637
+ encoding="utf-8",
638
+ ) as f:
611
639
  f.write(EXAMPLE_MANIFEST)
612
- (output_directory / asset_pack_name / "Anims" / "example_anim").mkdir(parents=True)
640
+ (output_directory / asset_pack_name / "Anims" / "example_anim").mkdir(
641
+ parents=True,
642
+ )
613
643
  (output_directory / asset_pack_name / "Anims" / "example_anim" / "meta.txt").touch()
614
- with open(output_directory / asset_pack_name / "Anims" / "example_anim" / "meta.txt", "w", encoding="utf-8") as f:
644
+ with Path.open(
645
+ output_directory / asset_pack_name / "Anims" / "example_anim" / "meta.txt",
646
+ "w",
647
+ encoding="utf-8",
648
+ ) as f:
615
649
  f.write(EXAMPLE_META)
616
650
 
617
651
  logger(f"Created asset pack '{asset_pack_name}' in '{output_directory}'")
618
652
 
619
653
 
620
- def main():
621
- """Main function"""
622
- if len(sys.argv) > 1:
623
- match sys.argv[1]:
624
- case "help" | "-h" | "--help":
625
- print(HELP_MESSAGE)
626
-
627
- case "create":
628
- if len(sys.argv) >= 3:
629
- NAME = " ".join(sys.argv[2:])
630
- create_asset_pack(NAME, pathlib.Path.cwd(), logger=print)
631
-
632
- else:
633
- print(HELP_MESSAGE)
654
+ def main() -> None:
655
+ """Main function."""
656
+ if len(sys.argv) <= 1:
657
+ # If no arguments are provided, pack all
658
+ here = pathlib.Path(__file__).absolute().parent
659
+ start = time.perf_counter()
660
+ pack_all_asset_packs(here, here / "asset_packs", logger=print)
661
+ end = time.perf_counter()
662
+ print(f"\nFinished in {round(end - start, 2)}s\n")
663
+ return
634
664
 
635
- case "pack":
636
- if len(sys.argv) == 3:
637
- here = pathlib.Path(__file__).absolute().parent
638
- start = time.perf_counter()
665
+ match sys.argv[1]:
666
+ case "--version" | "-v":
667
+ print(f"mntm-asset-packer {VERSION}")
639
668
 
640
- if sys.argv[2] == "all":
641
- pack_all_asset_packs(here, here / "asset_packs", logger=print)
642
- else:
643
- pack_specific(sys.argv[2], pathlib.Path.cwd() / "asset_packs", logger=print)
669
+ case "help" | "-h" | "--help":
670
+ print(HELP_MESSAGE)
671
+ return
644
672
 
645
- end = time.perf_counter()
646
- print(f"\nFinished in {round(end - start, 2)}s\n")
673
+ case "create":
674
+ if len(sys.argv) >= 3:
675
+ asset_pack_name = " ".join(sys.argv[2:])
676
+ create_asset_pack(asset_pack_name, pathlib.Path.cwd(), logger=print)
677
+ return
678
+ print(HELP_MESSAGE)
679
+
680
+ case "pack":
681
+ if len(sys.argv) == 3:
682
+ here = pathlib.Path(__file__).absolute().parent
683
+ start = time.perf_counter()
684
+
685
+ if sys.argv[2] == "all":
686
+ pack_all_asset_packs(
687
+ here,
688
+ here / "asset_packs",
689
+ logger=print,
690
+ )
647
691
  else:
648
- print(HELP_MESSAGE)
649
-
650
- case "recover":
651
- if len(sys.argv) == 3:
652
- here = pathlib.Path(__file__).absolute().parent
653
- start = time.perf_counter()
654
-
655
- if sys.argv[2] == "all":
656
- recover_all_asset_packs(here / "asset_packs", here / "recovered", logger=print)
657
- else:
658
- recover_specific(sys.argv[2], pathlib.Path.cwd() / "recovered", logger=print)
659
-
660
- # recover_anim(pathlib.Path(sys.argv[2]), pathlib.Path.cwd() / "recovered")
661
- end = time.perf_counter()
662
- print(f"Finished in {round(end - start, 2)}s")
663
-
664
- case "convert":
665
- if len(sys.argv) == 3:
666
- convert_and_rename_frames_for_all_anims(pathlib.Path(sys.argv[2]) / "Anims", logger=print)
692
+ pack_specific(
693
+ sys.argv[2],
694
+ pathlib.Path.cwd() / "asset_packs",
695
+ logger=print,
696
+ )
697
+
698
+ end = time.perf_counter()
699
+ print(f"\nFinished in {round(end - start, 2)}s\n")
700
+ return
701
+ print(HELP_MESSAGE)
702
+
703
+ case "recover":
704
+ if len(sys.argv) == 3:
705
+ here = pathlib.Path(__file__).absolute().parent
706
+ start = time.perf_counter()
707
+
708
+ if sys.argv[2] == "all":
709
+ recover_all_asset_packs(
710
+ here / "asset_packs",
711
+ here / "recovered",
712
+ logger=print,
713
+ )
667
714
  else:
668
- print(HELP_MESSAGE)
715
+ recover_specific(
716
+ sys.argv[2],
717
+ pathlib.Path.cwd() / "recovered",
718
+ logger=print,
719
+ )
720
+
721
+ end = time.perf_counter()
722
+ print(f"Finished in {round(end - start, 2)}s")
723
+ return
724
+ print(HELP_MESSAGE)
669
725
 
670
- case _:
671
- print(HELP_MESSAGE)
672
- else:
673
- here = pathlib.Path(__file__).absolute().parent
674
- start = time.perf_counter()
675
- pack_all_asset_packs(here, here / "asset_packs", logger=print)
676
- end = time.perf_counter()
677
- print(f"\nFinished in {round(end - start, 2)}s\n")
726
+ case "convert":
727
+ if len(sys.argv) == 3:
728
+ convert_and_rename_frames_for_all_anims(pathlib.Path(sys.argv[2]) / "Anims", logger=print)
729
+ return
730
+ print(HELP_MESSAGE)
731
+
732
+ case _:
733
+ print(HELP_MESSAGE)
678
734
 
679
735
 
680
736
  if __name__ == "__main__":
@@ -1,5 +0,0 @@
1
- mntm_asset_packer.py,sha256=1oRpiZI7-miamOx0POado6LBBjYo6mIEdfdBVpjltrg,26260
2
- mntm_asset_packer-1.1.1.dist-info/METADATA,sha256=AlqTF_5auhg9yNE9XHPH6LjFpR4WFpgbwK-mLb4GjAc,3648
3
- mntm_asset_packer-1.1.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
4
- mntm_asset_packer-1.1.1.dist-info/entry_points.txt,sha256=CF05qVMVPPNhTroKeH_kkKqVgG-mJ-Q0mSAZHpfxkr0,61
5
- mntm_asset_packer-1.1.1.dist-info/RECORD,,