mntm-asset-packer 1.1.1__py3-none-any.whl → 1.1.2__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.2
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=xR-9IpKDWbgfTVBrvDBve_jEhIfy8zT0Od-gau48XzQ,26765
2
+ mntm_asset_packer-1.1.2.dist-info/METADATA,sha256=Q6x7aVPiOPYROpKYnmJoR6wBKsuVQlw3YQGI1mel1Es,3621
3
+ mntm_asset_packer-1.1.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
4
+ mntm_asset_packer-1.1.2.dist-info/entry_points.txt,sha256=CF05qVMVPPNhTroKeH_kkKqVgG-mJ-Q0mSAZHpfxkr0,61
5
+ mntm_asset_packer-1.1.2.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
175
  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")
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,38 @@ 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
+ code = src.read_bytes().split(b' U8G2_FONT_SECTION("')[1].split(b'") =')[1].strip()
327
334
  font = b""
328
335
  for line in code.splitlines():
329
336
  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
- )
337
+ font += line[line.find(b'"') + 1 : line.rfind(b'"')].decode("unicode_escape").encode("latin_1")
335
338
  font += b"\0"
336
339
  dst.with_suffix(".u8f").write_bytes(font)
337
340
  elif src.suffix == ".u8f":
@@ -342,27 +345,25 @@ def pack_font(src: pathlib.Path, dst: pathlib.Path):
342
345
  # recover font is not implemented
343
346
 
344
347
 
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)"""
348
+ def convert_and_rename_frames(directory: "str | pathlib.Path", logger: typing.Callable) -> None:
349
+ """Converts all frames to png and renames them "frame_N.png".
350
+
351
+ (requires the image name to contain the frame number)
352
+ """
348
353
  already_formatted = True
349
354
  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
355
+ if file.is_file() and file.suffix in (".jpg", ".jpeg", ".png") and not re.match(r"frame_\d+.png", file.name):
356
+ already_formatted = False
357
+ break
354
358
  if already_formatted:
355
- logger(f"\"{directory.name}\" anim is formatted")
359
+ logger(f'"{directory.name}" anim is formatted')
356
360
  return
357
361
 
358
362
  try:
359
363
  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"
364
+ 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
365
  )
366
+ input("Press [Enter] if you wish to continue or [Ctrl+C] to cancel")
366
367
  except KeyboardInterrupt:
367
368
  sys.exit(0)
368
369
  print()
@@ -382,16 +383,26 @@ def convert_and_rename_frames(directory: "str | pathlib.Path", logger: typing.Ca
382
383
  file.unlink()
383
384
 
384
385
 
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)"""
386
+ def convert_and_rename_frames_for_all_anims(
387
+ directory_for_anims: "str | pathlib.Path",
388
+ logger: typing.Callable,
389
+ ) -> None:
390
+ """Formats all anim frames correctly.
391
+
392
+ Converts all frames to png and renames them "frame_N.png for all anims in the given anim folder.
393
+ (requires the image name to contain the frame number)
394
+ """
388
395
  for anim in directory_for_anims.iterdir():
389
396
  if anim.is_dir():
390
397
  convert_and_rename_frames(anim, logger)
391
398
 
392
399
 
393
- def pack_specific(asset_pack_path: "str | pathlib.Path", output_directory: "str | pathlib.Path", logger: typing.Callable):
394
- """Packs a specific asset pack"""
400
+ def pack_specific(
401
+ asset_pack_path: "str | pathlib.Path",
402
+ output_directory: "str | pathlib.Path",
403
+ logger: typing.Callable,
404
+ ) -> None:
405
+ """Packs a specific asset pack."""
395
406
  asset_pack_path = pathlib.Path(asset_pack_path)
396
407
  output_directory = pathlib.Path(output_directory)
397
408
  logger(f"Packing '\033[3m{asset_pack_path.name}\033[0m'")
@@ -413,22 +424,23 @@ def pack_specific(asset_pack_path: "str | pathlib.Path", output_directory: "str
413
424
 
414
425
  # packing anims
415
426
  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")
427
+ (packed / "Anims").mkdir(
428
+ parents=True,
429
+ exist_ok=True,
430
+ ) # ensure that the "Anims" directory exists
431
+ copy_file_as_lf(
432
+ asset_pack_path / "Anims/manifest.txt",
433
+ packed / "Anims/manifest.txt",
434
+ )
418
435
  manifest = (asset_pack_path / "Anims/manifest.txt").read_bytes()
419
436
 
420
437
  # Find all the anims in the manifest
421
438
  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()
439
+ anim_name = anim.group(1).decode().replace("\\", "/").replace("/", os.sep).replace("\r", "\n").strip()
440
+ logger(
441
+ f"Compiling anim '\033[3m{anim_name}\033[0m' for '\033[3m{asset_pack_path.name}\033[0m'",
429
442
  )
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)
443
+ pack_anim(asset_pack_path / "Anims" / anim_name, packed / "Anims" / anim_name)
432
444
 
433
445
  # packing icons
434
446
  if (asset_pack_path / "Icons").is_dir():
@@ -439,20 +451,20 @@ def pack_specific(asset_pack_path: "str | pathlib.Path", output_directory: "str
439
451
  if icon.name.startswith("."):
440
452
  continue
441
453
  if icon.is_dir():
442
- logger(f"Compiling icon for pack '{asset_pack_path.name}': {icons.name}/{icon.name}")
454
+ logger(
455
+ f"Compiling icon for pack '{asset_pack_path.name}': {icons.name}/{icon.name}",
456
+ )
443
457
  pack_animated_icon(icon, packed / "Icons" / icons.name / icon.name)
444
458
  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}")
459
+ logger(
460
+ f"Compiling icon for pack '{asset_pack_path.name}': {icons.name}/{icon.name}",
461
+ )
446
462
  pack_static_icon(icon, packed / "Icons" / icons.name / icon.name)
447
463
 
448
464
  # packing fonts
449
465
  if (asset_pack_path / "Fonts").is_dir():
450
466
  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
- ):
467
+ if not font.is_file() or font.name.startswith(".") or font.suffix not in (".c", ".u8f"):
456
468
  continue
457
469
  logger(f"Compiling font for pack '{asset_pack_path.name}': {font.name}")
458
470
  pack_font(font, packed / "Fonts" / font.name)
@@ -461,8 +473,12 @@ def pack_specific(asset_pack_path: "str | pathlib.Path", output_directory: "str
461
473
  logger(f"Saved to: '\033[33m{packed}\033[0m'")
462
474
 
463
475
 
464
- def recover_specific(asset_pack_path: "str | pathlib.Path", output_directory: "str | pathlib.Path", logger: typing.Callable):
465
- """Recovers a specific asset pack"""
476
+ def recover_specific(
477
+ asset_pack_path: "str | pathlib.Path",
478
+ output_directory: "str | pathlib.Path",
479
+ logger: typing.Callable,
480
+ ) -> None:
481
+ """Recovers a specific asset pack."""
466
482
  asset_pack_path = pathlib.Path(asset_pack_path)
467
483
  output_directory = pathlib.Path(output_directory)
468
484
  logger(f"Recovering '\033[3m{asset_pack_path.name}\033[0m'")
@@ -484,11 +500,17 @@ def recover_specific(asset_pack_path: "str | pathlib.Path", output_directory: "s
484
500
 
485
501
  # recovering anims
486
502
  if (asset_pack_path / "Anims").is_dir():
487
- (recovered / "Anims").mkdir(parents=True, exist_ok=True) # ensure that the "Anims" directory exists
503
+ (recovered / "Anims").mkdir(
504
+ parents=True,
505
+ exist_ok=True,
506
+ ) # ensure that the "Anims" directory exists
488
507
 
489
508
  # copy the manifest if it exists
490
509
  if (asset_pack_path / "Anims/manifest.txt").exists():
491
- shutil.copyfile(asset_pack_path / "Anims/manifest.txt", recovered / "Anims/manifest.txt")
510
+ shutil.copyfile(
511
+ asset_pack_path / "Anims/manifest.txt",
512
+ recovered / "Anims/manifest.txt",
513
+ )
492
514
 
493
515
  # recover all the anims in the Anims directory
494
516
  for anim in (asset_pack_path / "Anims").iterdir():
@@ -514,31 +536,24 @@ def recover_specific(asset_pack_path: "str | pathlib.Path", output_directory: "s
514
536
 
515
537
  # recovering fonts
516
538
  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
539
+ logger("Fonts recovery not implemented yet")
527
540
 
528
541
  logger(f"\033[32mFinished recovering '\033[3m{asset_pack_path.name}\033[23m'\033[0m")
529
542
  logger(f"Saved to: '\033[33m{recovered}\033[0m'")
530
543
 
531
544
 
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"""
545
+ def pack_all_asset_packs(
546
+ source_directory: "str | pathlib.Path",
547
+ output_directory: "str | pathlib.Path",
548
+ logger: typing.Callable,
549
+ ) -> None:
550
+ """Packs all asset packs in the source directory."""
534
551
  try:
535
552
  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"
553
+ "This will pack all asset packs in the current directory."
554
+ "The resulting asset packs will be saved to './asset_packs'\n",
541
555
  )
556
+ input("Press [Enter] if you wish to continue or [Ctrl+C] to cancel")
542
557
  except KeyboardInterrupt:
543
558
  sys.exit(0)
544
559
  print()
@@ -550,22 +565,24 @@ def pack_all_asset_packs(source_directory: "str | pathlib.Path", output_director
550
565
  # Skip folders that are definitely not meant to be packed
551
566
  if source == output_directory:
552
567
  continue
553
- if not source.is_dir() or source.name.startswith(".") or source.name in ("venv", "recovered") :
568
+ if not source.is_dir() or source.name.startswith(".") or source.name in ("venv", "recovered"):
554
569
  continue
555
570
 
556
571
  pack_specific(source, output_directory, logger)
557
572
 
558
573
 
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"""
574
+ def recover_all_asset_packs(
575
+ source_directory: "str | pathlib.Path",
576
+ output_directory: "str | pathlib.Path",
577
+ logger: typing.Callable,
578
+ ) -> None:
579
+ """Recovers all asset packs in the source directory."""
561
580
  try:
562
581
  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"
582
+ "This will recover all asset packs in the current directory."
583
+ "The resulting asset packs will be saved to './recovered'\n",
568
584
  )
585
+ input("Press [Enter] if you wish to continue or [Ctrl+C] to cancel")
569
586
  except KeyboardInterrupt:
570
587
  sys.exit(0)
571
588
  print()
@@ -577,15 +594,18 @@ def recover_all_asset_packs(source_directory: "str | pathlib.Path", output_direc
577
594
  # Skip folders that are definitely not meant to be recovered
578
595
  if source == output_directory:
579
596
  continue
580
- if not source.is_dir() or source.name.startswith(".") or source.name in ("venv", "recovered") :
597
+ if not source.is_dir() or source.name.startswith(".") or source.name in ("venv", "recovered"):
581
598
  continue
582
599
 
583
600
  recover_specific(source, output_directory, logger)
584
601
 
585
602
 
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
-
603
+ def create_asset_pack(
604
+ asset_pack_name: str,
605
+ output_directory: "str | pathlib.Path",
606
+ logger: typing.Callable,
607
+ ) -> None:
608
+ """Creates the file structure for an asset pack."""
589
609
  if not isinstance(output_directory, pathlib.Path):
590
610
  output_directory = pathlib.Path(output_directory)
591
611
 
@@ -607,74 +627,106 @@ def create_asset_pack(asset_pack_name: str, output_directory: "str | pathlib.Pat
607
627
  # creating "manifest.txt" file
608
628
  if generate_example_files:
609
629
  (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:
630
+ with Path.open(
631
+ output_directory / asset_pack_name / "Anims" / "manifest.txt",
632
+ "w",
633
+ encoding="utf-8",
634
+ ) as f:
611
635
  f.write(EXAMPLE_MANIFEST)
612
- (output_directory / asset_pack_name / "Anims" / "example_anim").mkdir(parents=True)
636
+ (output_directory / asset_pack_name / "Anims" / "example_anim").mkdir(
637
+ parents=True,
638
+ )
613
639
  (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:
640
+ with Path.open(
641
+ output_directory / asset_pack_name / "Anims" / "example_anim" / "meta.txt",
642
+ "w",
643
+ encoding="utf-8",
644
+ ) as f:
615
645
  f.write(EXAMPLE_META)
616
646
 
617
647
  logger(f"Created asset pack '{asset_pack_name}' in '{output_directory}'")
618
648
 
619
649
 
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)
650
+ def main() -> None:
651
+ """Main function."""
652
+ if len(sys.argv) <= 1:
653
+ # If no arguments are provided, pack all
654
+ here = pathlib.Path(__file__).absolute().parent
655
+ start = time.perf_counter()
656
+ pack_all_asset_packs(here, here / "asset_packs", logger=print)
657
+ end = time.perf_counter()
658
+ print(f"\nFinished in {round(end - start, 2)}s\n")
659
+ return
634
660
 
635
- case "pack":
636
- if len(sys.argv) == 3:
637
- here = pathlib.Path(__file__).absolute().parent
638
- start = time.perf_counter()
661
+ match sys.argv[1]:
662
+ case "--version" | "-v":
663
+ print(f"mntm-asset-packer {VERSION}")
639
664
 
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)
665
+ case "help" | "-h" | "--help":
666
+ print(HELP_MESSAGE)
667
+ return
644
668
 
645
- end = time.perf_counter()
646
- print(f"\nFinished in {round(end - start, 2)}s\n")
669
+ case "create":
670
+ if len(sys.argv) >= 3:
671
+ asset_pack_name = " ".join(sys.argv[2:])
672
+ create_asset_pack(asset_pack_name, pathlib.Path.cwd(), logger=print)
673
+ return
674
+ print(HELP_MESSAGE)
675
+
676
+ case "pack":
677
+ if len(sys.argv) == 3:
678
+ here = pathlib.Path(__file__).absolute().parent
679
+ start = time.perf_counter()
680
+
681
+ if sys.argv[2] == "all":
682
+ pack_all_asset_packs(
683
+ here,
684
+ here / "asset_packs",
685
+ logger=print,
686
+ )
647
687
  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)
688
+ pack_specific(
689
+ sys.argv[2],
690
+ pathlib.Path.cwd() / "asset_packs",
691
+ logger=print,
692
+ )
693
+
694
+ end = time.perf_counter()
695
+ print(f"\nFinished in {round(end - start, 2)}s\n")
696
+ return
697
+ print(HELP_MESSAGE)
698
+
699
+ case "recover":
700
+ if len(sys.argv) == 3:
701
+ here = pathlib.Path(__file__).absolute().parent
702
+ start = time.perf_counter()
703
+
704
+ if sys.argv[2] == "all":
705
+ recover_all_asset_packs(
706
+ here / "asset_packs",
707
+ here / "recovered",
708
+ logger=print,
709
+ )
667
710
  else:
668
- print(HELP_MESSAGE)
711
+ recover_specific(
712
+ sys.argv[2],
713
+ pathlib.Path.cwd() / "recovered",
714
+ logger=print,
715
+ )
716
+
717
+ end = time.perf_counter()
718
+ print(f"Finished in {round(end - start, 2)}s")
719
+ return
720
+ print(HELP_MESSAGE)
669
721
 
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")
722
+ case "convert":
723
+ if len(sys.argv) == 3:
724
+ convert_and_rename_frames_for_all_anims(pathlib.Path(sys.argv[2]) / "Anims", logger=print)
725
+ return
726
+ print(HELP_MESSAGE)
727
+
728
+ case _:
729
+ print(HELP_MESSAGE)
678
730
 
679
731
 
680
732
  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,,