diff --git a/titles/chuni/frontend.py b/titles/chuni/frontend.py index e860400..aef8c1a 100644 --- a/titles/chuni/frontend.py +++ b/titles/chuni/frontend.py @@ -13,6 +13,7 @@ from core.config import CoreConfig from .database import ChuniData from .config import ChuniConfig from .const import ChuniConstants, AvatarCategory, ItemKind +from .read import ChuniReader def pairwise(iterable): @@ -91,6 +92,9 @@ class ChuniFrontend(FE_Base): self.data = ChuniData(cfg, self.game_cfg) self.nav_name = "Chunithm" + # Convert any old assets created with a previous version of the importer + ChuniReader.ConvertOldAssets(self.logger) + def get_routes(self) -> List[Route]: return [ Route("/", self.render_GET, methods=['GET']), @@ -252,12 +256,12 @@ class ChuniFrontend(FE_Base): artist=music_chart.artist title=music_chart.title (jacket, ext) = path.splitext(music_chart.jacketPath) - jacket += ".png" + jacket += ".webp" else: difficultyNum=0 artist="unknown" title="musicid: " + str(record.musicId) - jacket = "unknown.png" + jacket = "unknown.webp" # Check if this song is a favorite so we can populate the add/remove button is_favorite = await self.data.item.is_favorite(user_id, version, record.musicId) @@ -313,12 +317,12 @@ class ChuniFrontend(FE_Base): title=song.title genre=song.genre (jacket, ext) = path.splitext(song.jacketPath) - jacket += ".png" + jacket += ".webp" else: artist="unknown" title="musicid: " + str(favorite.favId) genre="unknown" - jacket = "unknown.png" + jacket = "unknown.webp" # add a new collection for the genre if this is our first time seeing it if genre not in favorites_by_genre: @@ -370,7 +374,7 @@ class ChuniFrontend(FE_Base): item = dict() item["id"] = row["mapIconId"] item["name"] = row["name"] - item["iconPath"] = path.splitext(row["iconPath"])[0] + ".png" + item["iconPath"] = path.splitext(row["iconPath"])[0] + ".webp" items[row["mapIconId"]] = item return (items, len(rows)) @@ -395,7 +399,7 @@ class ChuniFrontend(FE_Base): item = dict() item["id"] = row["voiceId"] item["name"] = row["name"] - item["imagePath"] = path.splitext(row["imagePath"])[0] + ".png" + item["imagePath"] = path.splitext(row["imagePath"])[0] + ".webp" items[row["voiceId"]] = item return (items, len(rows)) @@ -418,7 +422,7 @@ class ChuniFrontend(FE_Base): item = dict() item["id"] = row["nameplateId"] item["name"] = row["name"] - item["texturePath"] = path.splitext(row["texturePath"])[0] + ".png" + item["texturePath"] = path.splitext(row["texturePath"])[0] + ".webp" items[row["nameplateId"]] = item return (items, len(rows)) @@ -464,7 +468,7 @@ class ChuniFrontend(FE_Base): item = dict() item["id"] = row["characterId"] item["name"] = row["name"] - item["iconPath"] = path.splitext(row["imagePath3"])[0] + ".png" + item["iconPath"] = path.splitext(row["imagePath3"])[0] + ".webp" items[row["characterId"]] = item return (items, len(rows)) @@ -482,8 +486,8 @@ class ChuniFrontend(FE_Base): item = dict() item["id"] = row["avatarAccessoryId"] item["name"] = row["name"] - item["iconPath"] = path.splitext(row["iconPath"])[0] + ".png" - item["texturePath"] = path.splitext(row["texturePath"])[0] + ".png" + item["iconPath"] = path.splitext(row["iconPath"])[0] + ".webp" + item["texturePath"] = path.splitext(row["texturePath"])[0] + ".webp" items[row["avatarAccessoryId"]] = item return (items, len(rows)) diff --git a/titles/chuni/img/avatar-common.png b/titles/chuni/img/avatar-common.png deleted file mode 100644 index 030b55e..0000000 Binary files a/titles/chuni/img/avatar-common.png and /dev/null differ diff --git a/titles/chuni/img/avatar-common.webp b/titles/chuni/img/avatar-common.webp new file mode 100644 index 0000000..1e2033f Binary files /dev/null and b/titles/chuni/img/avatar-common.webp differ diff --git a/titles/chuni/img/avatar-platform.png b/titles/chuni/img/avatar-platform.png deleted file mode 100644 index e981414..0000000 Binary files a/titles/chuni/img/avatar-platform.png and /dev/null differ diff --git a/titles/chuni/img/avatar-platform.webp b/titles/chuni/img/avatar-platform.webp new file mode 100644 index 0000000..1271b56 Binary files /dev/null and b/titles/chuni/img/avatar-platform.webp differ diff --git a/titles/chuni/img/character-bg.png b/titles/chuni/img/character-bg.png deleted file mode 100644 index d345ef7..0000000 Binary files a/titles/chuni/img/character-bg.png and /dev/null differ diff --git a/titles/chuni/img/character-bg.webp b/titles/chuni/img/character-bg.webp new file mode 100644 index 0000000..52fc41e Binary files /dev/null and b/titles/chuni/img/character-bg.webp differ diff --git a/titles/chuni/img/jacket/.gitignore b/titles/chuni/img/jacket/.gitignore index 99b4674..a5a9242 100644 --- a/titles/chuni/img/jacket/.gitignore +++ b/titles/chuni/img/jacket/.gitignore @@ -2,4 +2,4 @@ * # Except this file and default unknown !.gitignore -!unknown.png \ No newline at end of file +!unknown.webp \ No newline at end of file diff --git a/titles/chuni/img/jacket/unknown.png b/titles/chuni/img/jacket/unknown.png deleted file mode 100644 index 92a72d6..0000000 Binary files a/titles/chuni/img/jacket/unknown.png and /dev/null differ diff --git a/titles/chuni/img/jacket/unknown.webp b/titles/chuni/img/jacket/unknown.webp new file mode 100644 index 0000000..ebfaba4 Binary files /dev/null and b/titles/chuni/img/jacket/unknown.webp differ diff --git a/titles/chuni/img/rank/rank0.png b/titles/chuni/img/rank/rank0.png deleted file mode 100644 index ba152db..0000000 Binary files a/titles/chuni/img/rank/rank0.png and /dev/null differ diff --git a/titles/chuni/img/rank/rank0.webp b/titles/chuni/img/rank/rank0.webp new file mode 100644 index 0000000..4ae41bd Binary files /dev/null and b/titles/chuni/img/rank/rank0.webp differ diff --git a/titles/chuni/img/rank/rank1.png b/titles/chuni/img/rank/rank1.png deleted file mode 100644 index 552b12c..0000000 Binary files a/titles/chuni/img/rank/rank1.png and /dev/null differ diff --git a/titles/chuni/img/rank/rank1.webp b/titles/chuni/img/rank/rank1.webp new file mode 100644 index 0000000..1bda4dd Binary files /dev/null and b/titles/chuni/img/rank/rank1.webp differ diff --git a/titles/chuni/img/rank/rank10.png b/titles/chuni/img/rank/rank10.png deleted file mode 100644 index 14d976c..0000000 Binary files a/titles/chuni/img/rank/rank10.png and /dev/null differ diff --git a/titles/chuni/img/rank/rank10.webp b/titles/chuni/img/rank/rank10.webp new file mode 100644 index 0000000..e1c36b8 Binary files /dev/null and b/titles/chuni/img/rank/rank10.webp differ diff --git a/titles/chuni/img/rank/rank11.png b/titles/chuni/img/rank/rank11.png deleted file mode 100644 index 4e31d19..0000000 Binary files a/titles/chuni/img/rank/rank11.png and /dev/null differ diff --git a/titles/chuni/img/rank/rank11.webp b/titles/chuni/img/rank/rank11.webp new file mode 100644 index 0000000..124f47e Binary files /dev/null and b/titles/chuni/img/rank/rank11.webp differ diff --git a/titles/chuni/img/rank/rank2.png b/titles/chuni/img/rank/rank2.png deleted file mode 100644 index 0c78938..0000000 Binary files a/titles/chuni/img/rank/rank2.png and /dev/null differ diff --git a/titles/chuni/img/rank/rank2.webp b/titles/chuni/img/rank/rank2.webp new file mode 100644 index 0000000..df6dcca Binary files /dev/null and b/titles/chuni/img/rank/rank2.webp differ diff --git a/titles/chuni/img/rank/rank3.png b/titles/chuni/img/rank/rank3.png deleted file mode 100644 index 5d55b3d..0000000 Binary files a/titles/chuni/img/rank/rank3.png and /dev/null differ diff --git a/titles/chuni/img/rank/rank3.webp b/titles/chuni/img/rank/rank3.webp new file mode 100644 index 0000000..3491a22 Binary files /dev/null and b/titles/chuni/img/rank/rank3.webp differ diff --git a/titles/chuni/img/rank/rank4.png b/titles/chuni/img/rank/rank4.png deleted file mode 100644 index 5d55b3d..0000000 Binary files a/titles/chuni/img/rank/rank4.png and /dev/null differ diff --git a/titles/chuni/img/rank/rank4.webp b/titles/chuni/img/rank/rank4.webp new file mode 100644 index 0000000..3491a22 Binary files /dev/null and b/titles/chuni/img/rank/rank4.webp differ diff --git a/titles/chuni/img/rank/rank5.png b/titles/chuni/img/rank/rank5.png deleted file mode 100644 index af519b6..0000000 Binary files a/titles/chuni/img/rank/rank5.png and /dev/null differ diff --git a/titles/chuni/img/rank/rank5.webp b/titles/chuni/img/rank/rank5.webp new file mode 100644 index 0000000..8a04d1c Binary files /dev/null and b/titles/chuni/img/rank/rank5.webp differ diff --git a/titles/chuni/img/rank/rank6.png b/titles/chuni/img/rank/rank6.png deleted file mode 100644 index af519b6..0000000 Binary files a/titles/chuni/img/rank/rank6.png and /dev/null differ diff --git a/titles/chuni/img/rank/rank6.webp b/titles/chuni/img/rank/rank6.webp new file mode 100644 index 0000000..8a04d1c Binary files /dev/null and b/titles/chuni/img/rank/rank6.webp differ diff --git a/titles/chuni/img/rank/rank7.png b/titles/chuni/img/rank/rank7.png deleted file mode 100644 index db7ae79..0000000 Binary files a/titles/chuni/img/rank/rank7.png and /dev/null differ diff --git a/titles/chuni/img/rank/rank7.webp b/titles/chuni/img/rank/rank7.webp new file mode 100644 index 0000000..723a10d Binary files /dev/null and b/titles/chuni/img/rank/rank7.webp differ diff --git a/titles/chuni/img/rank/rank8.png b/titles/chuni/img/rank/rank8.png deleted file mode 100644 index db7ae79..0000000 Binary files a/titles/chuni/img/rank/rank8.png and /dev/null differ diff --git a/titles/chuni/img/rank/rank8.webp b/titles/chuni/img/rank/rank8.webp new file mode 100644 index 0000000..723a10d Binary files /dev/null and b/titles/chuni/img/rank/rank8.webp differ diff --git a/titles/chuni/img/rank/rank9.png b/titles/chuni/img/rank/rank9.png deleted file mode 100644 index 145096d..0000000 Binary files a/titles/chuni/img/rank/rank9.png and /dev/null differ diff --git a/titles/chuni/img/rank/rank9.webp b/titles/chuni/img/rank/rank9.webp new file mode 100644 index 0000000..35ee986 Binary files /dev/null and b/titles/chuni/img/rank/rank9.webp differ diff --git a/titles/chuni/img/rank/rating0.png b/titles/chuni/img/rank/rating0.png deleted file mode 100644 index 66813b8..0000000 Binary files a/titles/chuni/img/rank/rating0.png and /dev/null differ diff --git a/titles/chuni/img/rank/rating0.webp b/titles/chuni/img/rank/rating0.webp new file mode 100644 index 0000000..d75d5eb Binary files /dev/null and b/titles/chuni/img/rank/rating0.webp differ diff --git a/titles/chuni/img/rank/team3.png b/titles/chuni/img/rank/team3.png deleted file mode 100644 index 9ac4724..0000000 Binary files a/titles/chuni/img/rank/team3.png and /dev/null differ diff --git a/titles/chuni/img/rank/team3.webp b/titles/chuni/img/rank/team3.webp new file mode 100644 index 0000000..4521bbb Binary files /dev/null and b/titles/chuni/img/rank/team3.webp differ diff --git a/titles/chuni/read.py b/titles/chuni/read.py index 47c1939..0b96b7b 100644 --- a/titles/chuni/read.py +++ b/titles/chuni/read.py @@ -1,9 +1,11 @@ +from logging import Logger from typing import Optional -from os import walk, path +from os import walk, path, remove import xml.etree.ElementTree as ET from read import BaseReader from PIL import Image import configparser +import glob from core.config import CoreConfig from titles.chuni.database import ChuniData @@ -43,6 +45,9 @@ class ChuniReader(BaseReader): if self.version >= ChuniConstants.VER_CHUNITHM_NEW: we_diff = "5" + # Convert any old assets created with a previous version of the importer + ChuniReader.ConvertOldAssets(self.logger) + # character images could be stored anywhere across all the data dirs. Map them first self.logger.info(f"Mapping DDS image files...") dds_images = dict() @@ -533,17 +538,40 @@ class ChuniReader(BaseReader): self.logger.warning(f"Failed to unlock challenge {id}") def copy_image(self, filename: str, src_dir: str, dst_dir: str) -> None: - # Convert the image to png so we can easily display it in the frontend + # Convert the image to webp so we can easily display it in the frontend file_src = path.join(src_dir, filename) (basename, ext) = path.splitext(filename) - file_dst = path.join(dst_dir, basename) + ".png" + file_dst = path.join(dst_dir, basename) + ".webp" if path.exists(file_src) and not path.exists(file_dst): try: im = Image.open(file_src) im.save(file_dst) except Exception: - self.logger.warning(f"Failed to convert {filename} to png") + self.logger.warning(f"Failed to convert {filename} to webp") + + def ConvertOldAssets(logger: Logger): + """ + Converts any previously-imported png files to webp. + In the initial version of the userbox/avatar frontend support, png images were used, scraped via read.py. + The amount of data pushed once a lot of stuff was unlocked was noticeable so the frontend now uses webp format + for these assets. If any png files are present, convert them to webp now. + """ + # Find all pngs under the /img directory + png_files = glob.glob(f'titles/chuni/img/**/*.png', recursive=True) + if len(png_files) > 0: + logger.info(f'Found {len(png_files)} old assets. Converting to webp... (may take a few minutes)') + for img_png in png_files: + img_webp = path.splitext(img_png)[0] + '.webp' + try: + # convert to webp + im = Image.open(img_png) + im.save(img_webp) + # delete the original file + remove(img_png) + except Exception as e: + logger.warning(f'Failed to convert {img_png} to webp') + logger.info(f'Conversion complete') def map_dds_images(self, image_dict: dict, dds_dir: str) -> None: for root, dirs, files in walk(dds_dir): diff --git a/titles/chuni/templates/chuni_avatar.jinja b/titles/chuni/templates/chuni_avatar.jinja index 30fecf1..4fa4a45 100644 --- a/titles/chuni/templates/chuni_avatar.jinja +++ b/titles/chuni/templates/chuni_avatar.jinja @@ -14,13 +14,13 @@ - diff --git a/titles/chuni/templates/chuni_userbox.jinja b/titles/chuni/templates/chuni_userbox.jinja index 3bca2fd..192d96e 100644 --- a/titles/chuni/templates/chuni_userbox.jinja +++ b/titles/chuni/templates/chuni_userbox.jinja @@ -18,7 +18,7 @@ - +
{{team_name}}
@@ -26,7 +26,7 @@
- +
Lv. {{ profile.level }}   {{ profile.userName }} @@ -37,7 +37,7 @@
- + @@ -50,7 +50,7 @@ {% endfor %} - + {% if cur_version >= 17 %} - + {% endif %} +
AVATAR
- + - + @@ -36,7 +36,7 @@
Front:
Back:
+
    
Trophy Sub 1:
Character:
@@ -180,10 +181,10 @@ function changeItem(type, id, name, img) { function getRankImage(selected_rank) { for (const x of Array(12).keys()) { if (selected_rank.classList.contains("trophy-rank" + x.toString())) { - return "rank" + x.toString() + ".png"; + return "rank" + x.toString() + ".webp"; } } - return "rank0.png"; // shouldnt ever happen + return "rank0.webp"; // shouldnt ever happen } function changeTrophy() {