Asset Packer: Fix edge cases for animated icons

- FBT allows animated icons with any frame naming scheme
- Flipper needs precise naming
- This will ensure correct parsing and correct output
- If .bm and .png input for packer is mixed, could have issues due to inconsistent naming between input and output (duplicated frames)
This commit is contained in:
Willy-JL
2024-07-16 17:32:48 +01:00
parent e61e23a627
commit a953d0dfd4
3 changed files with 31 additions and 9 deletions
+1 -1
View File
@@ -116,7 +116,7 @@
- FBT: - FBT:
- Consistent version/branch info, fix gitorigin (by @Willy-JL) - Consistent version/branch info, fix gitorigin (by @Willy-JL)
- OFW: Fixed starting apps with spaces in path (by @hedger) - OFW: Fixed starting apps with spaces in path (by @hedger)
- AssetPacker: Pack pre-compiled icons and fonts too (by @Willy-JL) - AssetPacker: Pack pre-compiled icons and fonts too, fix animated icons edge cases (by @Willy-JL)
- GUI: Return user-provided index from `menu_set_selected_item()` like `submenu` equivalent (by @Willy-JL) - GUI: Return user-provided index from `menu_set_selected_item()` like `submenu` equivalent (by @Willy-JL)
- JS: - JS:
- Fix `subghz` RAW files, fix memory leaks, deinit correctly, better error handling (by @Willy-JL) - Fix `subghz` RAW files, fix memory leaks, deinit correctly, better error handling (by @Willy-JL)
+8 -6
View File
@@ -69,22 +69,24 @@ def pack_icon_animated(src: pathlib.Path, dst: pathlib.Path):
frame_count = 0 frame_count = 0
frame_rate = None frame_rate = None
size = None size = None
for frame in src.iterdir(): files = [file for file in src.iterdir() if file.is_file()]
for frame in sorted(files, key=lambda x: x.name):
if not frame.is_file(): if not frame.is_file():
continue continue
if frame.name == "frame_rate": if frame.name == "frame_rate":
frame_rate = int(frame.read_text()) frame_rate = int(frame.read_text().strip())
elif frame.name == "meta": elif frame.name == "meta":
shutil.copyfile(frame, dst / frame.name) shutil.copyfile(frame, dst / frame.name)
elif frame.name.startswith("frame_"): else:
dst_frame = dst / f"frame_{frame_count:02}.bm"
if frame.suffix == ".png": if frame.suffix == ".png":
if not size: if not size:
size = Image.open(frame).size size = Image.open(frame).size
(dst / frame.with_suffix(".bm").name).write_bytes(convert_bm(frame)) dst_frame.write_bytes(convert_bm(frame))
frame_count += 1 frame_count += 1
elif frame.suffix == ".bm": elif frame.suffix == ".bm":
if not (dst / frame.name).is_file(): if frame.with_suffix(".png") not in files:
shutil.copyfile(frame, dst / frame.name) shutil.copyfile(frame, dst_frame)
frame_count += 1 frame_count += 1
if size is not None and frame_rate is not None: if size is not None and frame_rate is not None:
(dst / "meta").write_bytes(struct.pack("<IIII", *size, frame_rate, frame_count)) (dst / "meta").write_bytes(struct.pack("<IIII", *size, frame_rate, frame_count))
+22 -2
View File
@@ -74,6 +74,7 @@ def _packs_emitter(target, source, env):
env.Replace(_PACKS_SRC_DIR=source_dir) env.Replace(_PACKS_SRC_DIR=source_dir)
target = set() target = set()
# Animations
target.update( target.update(
source_dir.rel_path(node) source_dir.rel_path(node)
for node in env.GlobRecursive("*/Anims/manifest.txt", source_dir.srcnode()) for node in env.GlobRecursive("*/Anims/manifest.txt", source_dir.srcnode())
@@ -86,14 +87,33 @@ def _packs_emitter(target, source, env):
source_dir.rel_path(node).removesuffix(".png") + ".bm" source_dir.rel_path(node).removesuffix(".png") + ".bm"
for node in env.GlobRecursive("*/Anims/**/*.png", source_dir.srcnode()) for node in env.GlobRecursive("*/Anims/**/*.png", source_dir.srcnode())
) )
# Animated icons
target.update( target.update(
source_dir.rel_path(node) source_dir.rel_path(node)
for node in env.GlobRecursive("*/Icons/**/*.bmx", source_dir.srcnode()) for node in env.GlobRecursive("*/Icons/*/*/meta", source_dir.srcnode())
)
target.update(
source_dir.rel_path(node).removesuffix("frame_rate") + "meta"
for node in env.GlobRecursive("*/Icons/*/*/frame_rate", source_dir.srcnode())
)
target.update(
source_dir.rel_path(node)
for node in env.GlobRecursive("*/Icons/*/*/*.bm", source_dir.srcnode())
)
target.update(
source_dir.rel_path(node).removesuffix(".png") + ".bm"
for node in env.GlobRecursive("*/Icons/*/*/*.png", source_dir.srcnode())
)
# Static icons
target.update(
source_dir.rel_path(node)
for node in env.GlobRecursive("*/Icons/*/*.bmx", source_dir.srcnode())
) )
target.update( target.update(
source_dir.rel_path(node).removesuffix(".png") + ".bmx" source_dir.rel_path(node).removesuffix(".png") + ".bmx"
for node in env.GlobRecursive("*/Icons/**/*.png", source_dir.srcnode()) for node in env.GlobRecursive("*/Icons/*/*.png", source_dir.srcnode())
) )
# Fonts
target.update( target.update(
source_dir.rel_path(node) source_dir.rel_path(node)
for node in env.GlobRecursive("*/Fonts/*.u8f", source_dir.srcnode()) for node in env.GlobRecursive("*/Fonts/*.u8f", source_dir.srcnode())