mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-05-22 05:14:46 -07:00
Support animated icons in asset packs
This commit is contained in:
@@ -2,10 +2,50 @@
|
|||||||
#include "assets_icons.h"
|
#include "assets_icons.h"
|
||||||
#include <core/dangerous_defines.h>
|
#include <core/dangerous_defines.h>
|
||||||
|
|
||||||
|
#define ICONS_FMT PACKS_DIR "/%s/Icons/%s"
|
||||||
|
|
||||||
XtremeAssets* xtreme_assets = NULL;
|
XtremeAssets* xtreme_assets = NULL;
|
||||||
|
|
||||||
|
void anim(const Icon** replace, const char* name, FuriString* path, File* file) {
|
||||||
|
do {
|
||||||
|
furi_string_printf(path, ICONS_FMT "/meta", XTREME_SETTINGS()->asset_pack, name);
|
||||||
|
if(!storage_file_open(file, furi_string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING))
|
||||||
|
break;
|
||||||
|
int32_t width, height, frame_rate, frame_count;
|
||||||
|
storage_file_read(file, &width, 4);
|
||||||
|
storage_file_read(file, &height, 4);
|
||||||
|
storage_file_read(file, &frame_rate, 4);
|
||||||
|
storage_file_read(file, &frame_count, 4);
|
||||||
|
storage_file_close(file);
|
||||||
|
|
||||||
|
Icon* icon = malloc(sizeof(Icon));
|
||||||
|
FURI_CONST_ASSIGN(icon->width, width);
|
||||||
|
FURI_CONST_ASSIGN(icon->height, height);
|
||||||
|
FURI_CONST_ASSIGN(icon->frame_rate, frame_rate);
|
||||||
|
FURI_CONST_ASSIGN(icon->frame_count, frame_count);
|
||||||
|
icon->frames = malloc(sizeof(const uint8_t*) * icon->frame_count);
|
||||||
|
const char* pack = XTREME_SETTINGS()->asset_pack;
|
||||||
|
|
||||||
|
bool ok = true;
|
||||||
|
for(int i = 0; ok && i < icon->frame_count; ++i) {
|
||||||
|
ok = false;
|
||||||
|
furi_string_printf(path, ICONS_FMT "/frame_%02d.bm", pack, name, i);
|
||||||
|
if(!storage_file_open(file, furi_string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING))
|
||||||
|
break;
|
||||||
|
|
||||||
|
uint64_t size = storage_file_size(file);
|
||||||
|
FURI_CONST_ASSIGN_PTR(icon->frames[i], malloc(size));
|
||||||
|
if(storage_file_read(file, (void*)icon->frames[i], size) == size) ok = true;
|
||||||
|
storage_file_close(file);
|
||||||
|
}
|
||||||
|
if(!ok) break;
|
||||||
|
|
||||||
|
*replace = icon;
|
||||||
|
} while(false);
|
||||||
|
}
|
||||||
|
|
||||||
void icon(const Icon** replace, const char* name, FuriString* path, File* file) {
|
void icon(const Icon** replace, const char* name, FuriString* path, File* file) {
|
||||||
furi_string_printf(path, PACKS_DIR "/%s/Icons/%s.bmx", XTREME_SETTINGS()->asset_pack, name);
|
furi_string_printf(path, ICONS_FMT ".bmx", XTREME_SETTINGS()->asset_pack, name);
|
||||||
if(storage_file_open(file, furi_string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) {
|
if(storage_file_open(file, furi_string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) {
|
||||||
uint64_t size = storage_file_size(file) - 8;
|
uint64_t size = storage_file_size(file) - 8;
|
||||||
int32_t width, height;
|
int32_t width, height;
|
||||||
@@ -27,6 +67,7 @@ void icon(const Icon** replace, const char* name, FuriString* path, File* file)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void swap(XtremeAssets* x, FuriString* p, File* f) {
|
void swap(XtremeAssets* x, FuriString* p, File* f) {
|
||||||
|
anim(&x->A_Levelup_128x64, "Animations/Levelup_128x64", p, f);
|
||||||
icon(&x->I_BLE_Pairing_128x64, "BLE/BLE_Pairing_128x64", p, f);
|
icon(&x->I_BLE_Pairing_128x64, "BLE/BLE_Pairing_128x64", p, f);
|
||||||
icon(&x->I_DolphinCommon_56x48, "Dolphin/DolphinCommon_56x48", p, f);
|
icon(&x->I_DolphinCommon_56x48, "Dolphin/DolphinCommon_56x48", p, f);
|
||||||
icon(&x->I_DolphinMafia_115x62, "iButton/DolphinMafia_115x62", p, f);
|
icon(&x->I_DolphinMafia_115x62, "iButton/DolphinMafia_115x62", p, f);
|
||||||
|
|||||||
@@ -32,4 +32,6 @@ typedef struct {
|
|||||||
const Icon* I_Error_62x31;
|
const Icon* I_Error_62x31;
|
||||||
} XtremeAssets;
|
} XtremeAssets;
|
||||||
|
|
||||||
|
void XTREME_ASSETS_LOAD();
|
||||||
|
|
||||||
XtremeAssets* XTREME_ASSETS();
|
XtremeAssets* XTREME_ASSETS();
|
||||||
|
|||||||
@@ -43,12 +43,51 @@ def convert_bmx(img: "Image.Image | pathlib.Path") -> bytes:
|
|||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
def pack_anim(src: pathlib.Path, dst: pathlib.Path):
|
||||||
|
if not (src / "meta.txt").is_file():
|
||||||
|
return
|
||||||
|
dst.mkdir(parents=True, exist_ok=True)
|
||||||
|
for frame in src.iterdir():
|
||||||
|
if not frame.is_file():
|
||||||
|
continue
|
||||||
|
if frame.name == "meta.txt":
|
||||||
|
shutil.copyfile(src / "meta.txt", dst / "meta.txt")
|
||||||
|
continue
|
||||||
|
elif frame.name.startswith("frame_"):
|
||||||
|
(dst / frame.with_suffix(".bm").name).write_bytes(convert_bm(frame))
|
||||||
|
|
||||||
|
|
||||||
|
def pack_icon_animated(src: pathlib.Path, dst: pathlib.Path):
|
||||||
|
if not (src / "frame_rate").is_file():
|
||||||
|
return
|
||||||
|
dst.mkdir(parents=True, exist_ok=True)
|
||||||
|
frame_count = 0
|
||||||
|
frame_rate = None
|
||||||
|
size = None
|
||||||
|
for frame in src.iterdir():
|
||||||
|
if not frame.is_file():
|
||||||
|
continue
|
||||||
|
if frame.name == "frame_rate":
|
||||||
|
frame_rate = int((src / "frame_rate").read_text())
|
||||||
|
continue
|
||||||
|
elif frame.name.startswith("frame_"):
|
||||||
|
frame_count += 1
|
||||||
|
if not size:
|
||||||
|
size = Image.open(frame).size
|
||||||
|
(dst / frame.with_suffix(".bm").name).write_bytes(convert_bm(frame))
|
||||||
|
(dst / "meta").write_bytes(struct.pack("<IIII", *size, frame_rate, frame_count))
|
||||||
|
|
||||||
|
|
||||||
|
def pack_icon_static(src: pathlib.Path, dst: pathlib.Path):
|
||||||
|
dst.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
dst.with_suffix(".bmx").write_bytes(convert_bmx(src))
|
||||||
|
|
||||||
|
|
||||||
def pack(
|
def pack(
|
||||||
input: "str | pathlib.Path", output: "str | pathlib.Path", logger: typing.Callable
|
input: "str | pathlib.Path", output: "str | pathlib.Path", logger: typing.Callable
|
||||||
):
|
):
|
||||||
input = pathlib.Path(input)
|
input = pathlib.Path(input)
|
||||||
output = pathlib.Path(output)
|
output = pathlib.Path(output)
|
||||||
output.mkdir(parents=True, exist_ok=True)
|
|
||||||
for source in input.iterdir():
|
for source in input.iterdir():
|
||||||
if source == output:
|
if source == output:
|
||||||
continue
|
continue
|
||||||
@@ -66,8 +105,6 @@ def pack(
|
|||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
packed.mkdir(parents=True, exist_ok=True)
|
|
||||||
|
|
||||||
if (source / "Anims/manifest.txt").exists():
|
if (source / "Anims/manifest.txt").exists():
|
||||||
(packed / "Anims").mkdir(parents=True, exist_ok=True)
|
(packed / "Anims").mkdir(parents=True, exist_ok=True)
|
||||||
shutil.copyfile(
|
shutil.copyfile(
|
||||||
@@ -76,30 +113,21 @@ def pack(
|
|||||||
for anim in (source / "Anims").iterdir():
|
for anim in (source / "Anims").iterdir():
|
||||||
if not anim.is_dir():
|
if not anim.is_dir():
|
||||||
continue
|
continue
|
||||||
(packed / "Anims" / anim.name).mkdir(parents=True, exist_ok=True)
|
pack_anim(anim, packed / "Anims" / anim.name)
|
||||||
for frame in anim.iterdir():
|
|
||||||
if not frame.is_file():
|
|
||||||
continue
|
|
||||||
if frame.name == "meta.txt":
|
|
||||||
shutil.copyfile(
|
|
||||||
frame, packed / "Anims" / anim.name / "meta.txt"
|
|
||||||
)
|
|
||||||
elif frame.name.startswith("frame_"):
|
|
||||||
(
|
|
||||||
packed / "Anims" / anim.name / frame.with_suffix(".bm").name
|
|
||||||
).write_bytes(convert_bm(frame))
|
|
||||||
|
|
||||||
if (source / "Icons").is_dir():
|
if (source / "Icons").is_dir():
|
||||||
for icons in (source / "Icons").iterdir():
|
for icons in (source / "Icons").iterdir():
|
||||||
if not icons.is_dir():
|
if not icons.is_dir():
|
||||||
continue
|
continue
|
||||||
(packed / "Icons" / icons.name).mkdir(parents=True, exist_ok=True)
|
|
||||||
for icon in icons.iterdir():
|
for icon in icons.iterdir():
|
||||||
if not icon.is_file():
|
if icon.is_dir():
|
||||||
continue
|
pack_icon_animated(
|
||||||
(
|
icon, packed / "Icons" / icons.name / icon.name
|
||||||
packed / "Icons" / icons.name / icon.with_suffix(".bmx").name
|
)
|
||||||
).write_bytes(convert_bmx(icon))
|
elif icon.is_file():
|
||||||
|
pack_icon_static(
|
||||||
|
icon, packed / "Icons" / icons.name / icon.name
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
Reference in New Issue
Block a user