diff --git a/applications/settings/xtreme_settings/xtreme_assets.c b/applications/settings/xtreme_settings/xtreme_assets.c index 5ae22aab0..13014b8d1 100644 --- a/applications/settings/xtreme_settings/xtreme_assets.c +++ b/applications/settings/xtreme_settings/xtreme_assets.c @@ -2,10 +2,50 @@ #include "assets_icons.h" #include +#define ICONS_FMT PACKS_DIR "/%s/Icons/%s" + 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) { - 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)) { uint64_t size = storage_file_size(file) - 8; 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) { + 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_DolphinCommon_56x48, "Dolphin/DolphinCommon_56x48", p, f); icon(&x->I_DolphinMafia_115x62, "iButton/DolphinMafia_115x62", p, f); diff --git a/applications/settings/xtreme_settings/xtreme_assets.h b/applications/settings/xtreme_settings/xtreme_assets.h index 8fa5d1cde..038372a43 100644 --- a/applications/settings/xtreme_settings/xtreme_assets.h +++ b/applications/settings/xtreme_settings/xtreme_assets.h @@ -32,4 +32,6 @@ typedef struct { const Icon* I_Error_62x31; } XtremeAssets; +void XTREME_ASSETS_LOAD(); + XtremeAssets* XTREME_ASSETS(); diff --git a/scripts/asset_packer.py b/scripts/asset_packer.py index aea755811..02ed0b94e 100755 --- a/scripts/asset_packer.py +++ b/scripts/asset_packer.py @@ -43,12 +43,51 @@ def convert_bmx(img: "Image.Image | pathlib.Path") -> bytes: 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("