GIF handling: skip GIFs in HTTPImageFetcher, filter GIF screenshots, fallback portrait URLs
All checks were successful
Build plugin / build (push) Successful in 1m11s
All checks were successful
Build plugin / build (push) Successful in 1m11s
- HTTPImageFetcher: skip GIF requests early (Godot can't decode), add webp support, try fallback formats - Art provider: filter GIF screenshots from banners, prefer non-GIF cover URLs via _best_portrait_url - Fix variable ordering bug (meta used before definition)
This commit is contained in:
parent
8a5dc41064
commit
d06cba872c
2 changed files with 54 additions and 13 deletions
|
|
@ -52,14 +52,10 @@ func get_boxart(item: LibraryItem, kind: LAYOUT) -> Texture2D:
|
|||
|
||||
var game_id := int(game.get("id", 0))
|
||||
var title: String = game.get("title", "")
|
||||
var cover_url := _cover_url(game)
|
||||
logger.info("get_boxart: title=%s id=%d cover_url=%s layout=%s" % [title, game_id, cover_url, str(kind)])
|
||||
logger.info("get_boxart: title=%s id=%d layout=%s" % [title, game_id, str(kind)])
|
||||
if title.is_empty():
|
||||
logger.warn("Game title is empty for id %d" % game_id)
|
||||
return null
|
||||
if cover_url.is_empty():
|
||||
logger.warn("No cover URL for: %s (id=%d)" % [title, game_id])
|
||||
return null
|
||||
|
||||
# Enrich on first access: scrape the itch.io page for screenshots.
|
||||
var meta: Dictionary = _enriched.get(game_id, {})
|
||||
|
|
@ -77,15 +73,28 @@ func get_boxart(item: LibraryItem, kind: LAYOUT) -> Texture2D:
|
|||
logger.warn("No URL in game dict for: %s" % title)
|
||||
|
||||
var screenshots: Array = meta.get("screenshots", [])
|
||||
# Filter out GIF screenshots — Godot can't decode them.
|
||||
var non_gif_screenshots: Array = screenshots.filter(
|
||||
func(url): return not url.to_lower().ends_with(".gif")
|
||||
)
|
||||
if screenshots.size() != non_gif_screenshots.size():
|
||||
logger.info("Filtered %d GIF screenshots for: %s" % [screenshots.size() - non_gif_screenshots.size(), title])
|
||||
|
||||
var cover_url := _best_portrait_url(game, non_gif_screenshots)
|
||||
if cover_url.is_empty():
|
||||
logger.warn("No cover URL for: %s (id=%d)" % [title, game_id])
|
||||
return null
|
||||
logger.info("cover_url=%s" % cover_url.left(80))
|
||||
|
||||
var cache_flags := Cache.FLAGS.NONE
|
||||
if use_caching:
|
||||
cache_flags = Cache.FLAGS.LOAD | Cache.FLAGS.SAVE
|
||||
|
||||
# Banner: combine two screenshots side-by-side when available.
|
||||
if kind == LAYOUT.BANNER and screenshots.size() >= 2:
|
||||
if kind == LAYOUT.BANNER and non_gif_screenshots.size() >= 2:
|
||||
logger.info("Fetching itch.io banner (2 screenshots) for: " + item.name)
|
||||
var tex_a := await http_image.fetch(screenshots[0], cache_flags)
|
||||
var tex_b := await http_image.fetch(screenshots[1], cache_flags)
|
||||
var tex_a := await http_image.fetch(non_gif_screenshots[0], cache_flags)
|
||||
var tex_b := await http_image.fetch(non_gif_screenshots[1], cache_flags)
|
||||
if tex_a != null and tex_b != null:
|
||||
return _combine_side_by_side(tex_a, tex_b)
|
||||
# Fall through to single-image path if either failed.
|
||||
|
|
@ -95,7 +104,7 @@ func get_boxart(item: LibraryItem, kind: LAYOUT) -> Texture2D:
|
|||
if tex_b != null:
|
||||
return tex_b
|
||||
|
||||
var url := _url_for_layout(kind, cover_url, screenshots)
|
||||
var url := _url_for_layout(kind, cover_url, non_gif_screenshots)
|
||||
if url.is_empty():
|
||||
logger.warn("URL for layout %s is empty (cover=%s)" % [str(kind), cover_url])
|
||||
return null
|
||||
|
|
@ -130,20 +139,52 @@ func _url_for_layout(kind: LAYOUT, cover_url: String, screenshots: Array) -> Str
|
|||
LAYOUT.GRID_PORTRAIT, LAYOUT.LOGO:
|
||||
return cover_url
|
||||
LAYOUT.GRID_LANDSCAPE:
|
||||
return screenshots[0] if not screenshots.is_empty() else cover_url
|
||||
# Prefer a non-GIF screenshot
|
||||
for url in screenshots:
|
||||
if not url.to_lower().ends_with(".gif"):
|
||||
return url
|
||||
return cover_url
|
||||
LAYOUT.BANNER:
|
||||
# Single screenshot fallback (two-screenshot case handled in get_boxart).
|
||||
return screenshots[0] if not screenshots.is_empty() else cover_url
|
||||
# Prefer a non-GIF screenshot.
|
||||
for url in screenshots:
|
||||
if not url.to_lower().ends_with(".gif"):
|
||||
return url
|
||||
return cover_url
|
||||
return ""
|
||||
|
||||
|
||||
func _cover_url(game: Dictionary) -> String:
|
||||
var still: String = game.get("stillCoverUrl", "")
|
||||
if not still.is_empty():
|
||||
if not still.is_empty() and not still.to_lower().ends_with(".gif"):
|
||||
return still
|
||||
# stillCoverUrl is empty or is a GIF — prefer it if non-GIF alternatives
|
||||
# aren't available, but log a warning.
|
||||
if not still.is_empty():
|
||||
logger.debug("stillCoverUrl is a GIF, will try alternatives: " + still)
|
||||
return game.get("coverUrl", "")
|
||||
|
||||
|
||||
## Returns a non-GIF URL suitable for portrait/logo from the game data.
|
||||
## Falls back through: stillCoverUrl → coverUrl (non-GIF) → first non-GIF
|
||||
## screenshot.
|
||||
func _best_portrait_url(game: Dictionary, screenshots: Array) -> String:
|
||||
# Prefer stillCoverUrl if it's not a GIF
|
||||
var still: String = game.get("stillCoverUrl", "")
|
||||
if not still.is_empty() and not still.to_lower().ends_with(".gif"):
|
||||
return still
|
||||
# Try coverUrl if it's not a GIF
|
||||
var cover: String = game.get("coverUrl", "")
|
||||
if not cover.is_empty() and not cover.to_lower().ends_with(".gif"):
|
||||
return cover
|
||||
# Try the first non-GIF screenshot
|
||||
for url in screenshots:
|
||||
if not url.to_lower().ends_with(".gif"):
|
||||
return url
|
||||
# Last resort: use whatever we have (GIF)
|
||||
return still if not still.is_empty() else cover
|
||||
|
||||
|
||||
## Combines two textures side-by-side into a single banner image.
|
||||
## Both images are scaled to the same height, then placed left and right.
|
||||
func _combine_side_by_side(a: Texture2D, b: Texture2D) -> Texture2D:
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"plugin.id": "itch-artprovider",
|
||||
"plugin.name": "itch.io Art Provider",
|
||||
"plugin.version": "0.1.3",
|
||||
"plugin.version": "0.1.4",
|
||||
"plugin.min-api-version": "1.1.0",
|
||||
"plugin.link": "https://forge.thergic.ar/jose/itchio-opengamepadui-artprovider-plugin",
|
||||
"plugin.source": "https://forge.thergic.ar/jose/itchio-opengamepadui-artprovider-plugin",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue