diff --git a/backend/config/config_manager.py b/backend/config/config_manager.py index 4d7f0217e..a5974fc3c 100644 --- a/backend/config/config_manager.py +++ b/backend/config/config_manager.py @@ -66,7 +66,6 @@ class Config: SCAN_ARTWORK_PRIORITY: list[str] SCAN_REGION_PRIORITY: list[str] SCAN_LANGUAGE_PRIORITY: list[str] - SCAN_ARTWORK_COVER_STYLE: str def __init__(self, **entries): self.__dict__.update(entries) @@ -243,11 +242,6 @@ class ConfigManager: "scan.priority.language", ["en", "fr"], ), - SCAN_ARTWORK_COVER_STYLE=pydash.get( - self._raw_config, - "scan.artwork.cover_style", - "box2d", - ).lower(), ) def _get_ejs_controls(self) -> dict[str, EjsControls]: @@ -426,12 +420,6 @@ class ConfigManager: log.critical("Invalid config.yml: scan.priority.language must be a list") sys.exit(3) - if not isinstance(self.config.SCAN_ARTWORK_COVER_STYLE, str): - log.critical( - "Invalid config.yml: scan.artwork.cover_style must be a string" - ) - sys.exit(3) - def get_config(self) -> Config: try: with open(self.config_file, "r") as config_file: @@ -487,9 +475,6 @@ class ConfigManager: "region": self.config.SCAN_REGION_PRIORITY, "language": self.config.SCAN_LANGUAGE_PRIORITY, }, - "artwork": { - "cover_style": self.config.SCAN_ARTWORK_COVER_STYLE, - }, }, } diff --git a/backend/endpoints/configs.py b/backend/endpoints/configs.py index c57ee40b7..8fc4f1bde 100644 --- a/backend/endpoints/configs.py +++ b/backend/endpoints/configs.py @@ -42,7 +42,6 @@ def get_config() -> ConfigResponse: SCAN_ARTWORK_PRIORITY=cfg.SCAN_ARTWORK_PRIORITY, SCAN_REGION_PRIORITY=cfg.SCAN_REGION_PRIORITY, SCAN_LANGUAGE_PRIORITY=cfg.SCAN_LANGUAGE_PRIORITY, - SCAN_ARTWORK_COVER_STYLE=cfg.SCAN_ARTWORK_COVER_STYLE, ) diff --git a/backend/endpoints/responses/config.py b/backend/endpoints/responses/config.py index cbc526446..a972b9508 100644 --- a/backend/endpoints/responses/config.py +++ b/backend/endpoints/responses/config.py @@ -22,4 +22,3 @@ class ConfigResponse(TypedDict): SCAN_ARTWORK_PRIORITY: list[str] SCAN_REGION_PRIORITY: list[str] SCAN_LANGUAGE_PRIORITY: list[str] - SCAN_ARTWORK_COVER_STYLE: str diff --git a/backend/handler/metadata/gamelist_handler.py b/backend/handler/metadata/gamelist_handler.py index ccd24e96c..9a7e74fa2 100644 --- a/backend/handler/metadata/gamelist_handler.py +++ b/backend/handler/metadata/gamelist_handler.py @@ -7,7 +7,6 @@ from xml.etree.ElementTree import Element # trunk-ignore(bandit/B405) import pydash from defusedxml import ElementTree as ET -from config.config_manager import config_manager as cm from handler.filesystem import fs_platform_handler from logger.logger import log from models.platform import Platform @@ -50,12 +49,6 @@ class GamelistRom(BaseRom): gamelist_metadata: NotRequired[GamelistMetadata] -def get_cover_style() -> str: - """Get cover art style from config""" - config = cm.get_config() - return config.SCAN_ARTWORK_COVER_STYLE - - def extract_media_from_gamelist_rom(game: Element) -> GamelistMetadataMedia: image_elem = game.find("image") video_elem = game.find("video") @@ -273,7 +266,7 @@ class GamelistHandler(MetadataHandler): ) # Choose which cover style to use - cover_path = rom_media.get(get_cover_style()) or rom_media["box2d"] + cover_path = rom_media["box2d"] if cover_path: cover_path_path = fs_platform_handler.validate_path( f"{platform_dir}/{cover_path}" @@ -299,7 +292,7 @@ class GamelistHandler(MetadataHandler): f"{platform_dir}/{rom_media['title_screen']}" ) url_screenshots.append(f"file://{str(title_screen_path)}") - if rom_media["miximage"] and get_cover_style() != "miximage": + if rom_media["miximage"]: miximage_path = fs_platform_handler.validate_path( f"{platform_dir}/{rom_media['miximage']}" ) diff --git a/backend/handler/metadata/ss_handler.py b/backend/handler/metadata/ss_handler.py index 4f18ba012..ef3c6b23a 100644 --- a/backend/handler/metadata/ss_handler.py +++ b/backend/handler/metadata/ss_handler.py @@ -41,12 +41,6 @@ def get_preferred_languages() -> list[str]: return list(dict.fromkeys(config.SCAN_LANGUAGE_PRIORITY + ["en", "fr"])) -def get_cover_style() -> str: - """Get cover art style from config""" - config = cm.get_config() - return config.SCAN_ARTWORK_COVER_STYLE - - PS1_SS_ID: Final = 57 PS2_SS_ID: Final = 58 PSP_SS_ID: Final = 61 @@ -349,13 +343,13 @@ def build_ss_rom(game: SSGame) -> SSRom: if res_summary: break - url_cover = ss_media.get(get_cover_style()) or ss_media["box2d"] + url_cover = ss_media["box2d"] url_manual = ss_media["manual"] url_screenshots = pydash.compact( [ ss_media["screenshot"], ss_media["title_screen"], - ss_media["miximage"] if get_cover_style() != "miximage" else None, + ss_media["miximage"], ] ) diff --git a/backend/tests/config/fixtures/config/config.yml b/backend/tests/config/fixtures/config/config.yml index 994c57020..c2cea669e 100644 --- a/backend/tests/config/fixtures/config/config.yml +++ b/backend/tests/config/fixtures/config/config.yml @@ -45,8 +45,6 @@ scan: language: - jp - es - artwork: - cover_style: box2d emulatorjs: debug: true diff --git a/examples/config.example.yml b/examples/config.example.yml index 20006c100..921bf70d6 100644 --- a/examples/config.example.yml +++ b/examples/config.example.yml @@ -80,8 +80,6 @@ filesystem: {} # { roms_folder: 'roms' } For example if your folder structure is # language: # Cover art and game title (only used by Screenscraper) # - "en" # - "fr" -# artwork: # Only used by Screenscraper and ES-DE -# cover_style: box2d (Options: box2d, box3d, physical, miximage, fanart) # EmulatorJS per-core options # emulatorjs: diff --git a/frontend/src/__generated__/models/ConfigResponse.ts b/frontend/src/__generated__/models/ConfigResponse.ts index 48fe88ed5..92015583a 100644 --- a/frontend/src/__generated__/models/ConfigResponse.ts +++ b/frontend/src/__generated__/models/ConfigResponse.ts @@ -22,6 +22,5 @@ export type ConfigResponse = { SCAN_ARTWORK_PRIORITY: Array; SCAN_REGION_PRIORITY: Array; SCAN_LANGUAGE_PRIORITY: Array; - SCAN_ARTWORK_COVER_STYLE: string; }; diff --git a/frontend/src/components/Details/Info/GameInfo.vue b/frontend/src/components/Details/Info/GameInfo.vue index a5e7ebb0b..3513eeb0c 100644 --- a/frontend/src/components/Details/Info/GameInfo.vue +++ b/frontend/src/components/Details/Info/GameInfo.vue @@ -90,7 +90,11 @@ const coverImageSource = computed(() => { const hostname = new URL(props.rom.url_cover).hostname; if (hostname === "images.igdb.com") return "IGDB"; - if (hostname === "screenscraper.fr") return "ScreenScraper"; + if ( + hostname === "screenscraper.fr" || + hostname === "neoclone.screenscraper.fr" + ) + return "ScreenScraper"; if (hostname === "cdn.mobygames.com" || hostname === "cdn2.mobygames.com") return "MobyGames"; if ( diff --git a/frontend/src/components/Settings/UserInterface/Interface.vue b/frontend/src/components/Settings/UserInterface/Interface.vue index 425d00541..8fb9a214b 100644 --- a/frontend/src/components/Settings/UserInterface/Interface.vue +++ b/frontend/src/components/Settings/UserInterface/Interface.vue @@ -51,6 +51,9 @@ const enableExperimentalCacheRef = useLocalStorage( false, ); +// Boxart +const boxartStyleRef = useLocalStorage("settings.boxartStyle", "box2d"); + const homeOptions = computed(() => [ { title: t("settings.show-stats"), @@ -181,6 +184,14 @@ const galleryOptions = computed(() => [ }, ]); +const boxartStyleOptions = computed(() => [ + { title: t("settings.boxart-box2d"), value: "box2d" }, + { title: t("settings.boxart-box3d"), value: "box3d" }, + { title: t("settings.boxart-physical"), value: "physical" }, + { title: t("settings.boxart-miximage"), value: "miximage" }, + { title: t("settings.boxart-fanart"), value: "fanart" }, +]); + const setPlatformDrawerGroupBy = (value: string) => { platformsGroupByRef.value = value; }; @@ -200,19 +211,18 @@ const setVirtualCollectionType = async (value: string) => { virtualCollectionTypeRef.value = value; collectionsStore.fetchVirtualCollections(value); }; - +const setBoxartStyle = (value: string) => { + boxartStyleRef.value = value; +}; const toggleShowStats = (value: boolean) => { showStatsRef.value = value; }; - const toggleShowRecentRoms = (value: boolean) => { showRecentRomsRef.value = value; }; - const toggleGroupRoms = (value: boolean) => { groupRomsRef.value = value; }; - const toggleSiblings = (value: boolean) => { siblingsRef.value = value; }; @@ -220,15 +230,12 @@ const toggleSiblings = (value: boolean) => { const toggleRegions = (value: boolean) => { regionsRef.value = value; }; - const toggleLanguages = (value: boolean) => { languagesRef.value = value; }; - const toggleStatus = (value: boolean) => { statusRef.value = value; }; - const toggleActionBar = (value: boolean) => { actionBarRef.value = value; }; @@ -271,6 +278,17 @@ const toggleExperimentalCache = (value: boolean) => { @update:model-value="option.modelTrigger" /> + + + ("settings.boxartStyle", "box2d"); const hasNotes = computed(() => { if (!romsStore.isSimpleRom(props.rom)) return false; @@ -146,9 +149,23 @@ const isWebpEnabled = computed( () => heartbeatStore.value.TASKS?.ENABLE_SCHEDULED_CONVERT_IMAGES_TO_WEBP, ); +// User selected alternative cover image +const boxartStyleCover = computed(() => { + if ( + props.coverSrc || + !romsStore.isSimpleRom(props.rom) || + boxartStyle.value === "box2d" + ) + return null; + const ssMedia = props.rom.ss_metadata?.[boxartStyle.value]; + const gamelistMedia = props.rom.gamelist_metadata?.[boxartStyle.value]; + return ssMedia || gamelistMedia; +}); + const largeCover = computed(() => { if (props.coverSrc) return props.coverSrc; - if (!romsStore.isSimpleRom(props.rom)) + if (boxartStyleCover.value) return boxartStyleCover.value; + if (!romsStore.isSimpleRom(props.rom)) { return ( props.rom.igdb_url_cover || props.rom.moby_url_cover || @@ -156,6 +173,7 @@ const largeCover = computed(() => { props.rom.launchbox_url_cover || props.rom.flashpoint_url_cover ); + } const pathCoverLarge = isWebpEnabled.value ? props.rom.path_cover_large?.replace(EXTENSION_REGEX, ".webp") : props.rom.path_cover_large; @@ -164,6 +182,7 @@ const largeCover = computed(() => { const smallCover = computed(() => { if (props.coverSrc) return props.coverSrc; + if (boxartStyleCover.value) return boxartStyleCover.value; if (!romsStore.isSimpleRom(props.rom)) return ""; const pathCoverSmall = isWebpEnabled.value ? props.rom.path_cover_small?.replace(EXTENSION_REGEX, ".webp") @@ -171,14 +190,6 @@ const smallCover = computed(() => { return pathCoverSmall || ""; }); -const is3DCover = computed(() => { - if (!romsStore.isSimpleRom(props.rom)) return false; - return ( - props.rom.url_cover?.includes("box-3D") || - props.rom.url_cover?.includes("3dboxes") - ); -}); - const showNoteDialog = (event: MouseEvent | KeyboardEvent) => { event.preventDefault(); if (romsStore.isSimpleRom(props.rom)) { @@ -232,7 +243,9 @@ onBeforeUnmount(() => { 'border-selected': withBorderPrimary, 'transform-scale': transformScale && !enable3DTilt, }" - :elevation="isOuterHovering && transformScale ? 20 : 3" + :elevation=" + isOuterHovering && transformScale ? 20 : boxartStyleCover ? 0 : 3 + " :aria-label="`${rom.name} game card`" @mouseenter=" () => { @@ -255,8 +268,8 @@ onBeforeUnmount(() => { { /> -
+
{