mirror of
https://github.com/lutris/lutris
synced 2024-11-05 18:10:49 +00:00
Process EGS media
This commit is contained in:
parent
44fae7b2dc
commit
cadac7d3de
4 changed files with 99 additions and 4 deletions
|
@ -129,7 +129,6 @@ def get_pixbuf_for_game(image_abspath, size, is_installed=True):
|
|||
|
||||
def convert_to_background(background_path, target_size=(320, 1080)):
|
||||
"""Converts a image to a pane background"""
|
||||
|
||||
coverart = Image.open(background_path)
|
||||
coverart = coverart.convert("RGBA")
|
||||
|
||||
|
@ -159,6 +158,43 @@ def convert_to_background(background_path, target_size=(320, 1080)):
|
|||
return background
|
||||
|
||||
|
||||
def thumbnail_image(base_image, target_size):
|
||||
base_width, base_height = base_image.size
|
||||
base_ratio = base_width / base_height
|
||||
target_width, target_height = target_size
|
||||
target_ratio = target_width / target_height
|
||||
|
||||
# Resize and crop coverart
|
||||
if base_ratio >= target_ratio:
|
||||
width = int(base_width * (target_height / base_height))
|
||||
height = target_height
|
||||
else:
|
||||
width = target_width
|
||||
height = int(base_height * (target_width / base_width))
|
||||
x_offset = int((width - target_width) / 2)
|
||||
y_offset = int((height - target_height) / 2)
|
||||
base_image = base_image.resize((width, height), resample=Image.BICUBIC)
|
||||
base_image = base_image.crop((x_offset, y_offset, width - x_offset, height - y_offset))
|
||||
return base_image
|
||||
|
||||
|
||||
def paste_overlay(base_image, overlay_image, position=0.7):
|
||||
base_width, base_height = base_image.size
|
||||
overlay_width, overlay_height = overlay_image.size
|
||||
offset_x = int((base_width - overlay_width) / 2)
|
||||
offset_y = int((base_height - overlay_height) / 2)
|
||||
base_image.paste(
|
||||
overlay_image, (
|
||||
offset_x,
|
||||
offset_y,
|
||||
overlay_width + offset_x,
|
||||
overlay_height + offset_y
|
||||
),
|
||||
mask=overlay_image
|
||||
)
|
||||
return base_image
|
||||
|
||||
|
||||
def image2pixbuf(image):
|
||||
"""Converts a PIL Image to a GDK Pixbuf"""
|
||||
image_array = array.array('B', image.tobytes())
|
||||
|
|
|
@ -55,6 +55,7 @@ class BaseService(GObject.Object):
|
|||
local = False
|
||||
drm_free = False # DRM free games can be added to Lutris from an existing install
|
||||
medias = {}
|
||||
extra_medias = {}
|
||||
default_format = "icon"
|
||||
|
||||
__gsignals__ = {
|
||||
|
@ -84,10 +85,19 @@ class BaseService(GObject.Object):
|
|||
|
||||
def load_icons(self):
|
||||
"""Download all game media from the service"""
|
||||
for icon_type in self.medias:
|
||||
service_media = self.medias[icon_type]()
|
||||
all_medias = self.medias.copy()
|
||||
all_medias.update(self.extra_medias)
|
||||
# Download icons
|
||||
for icon_type in all_medias:
|
||||
service_media = all_medias[icon_type]()
|
||||
media_urls = service_media.get_media_urls()
|
||||
download_icons(media_urls, service_media)
|
||||
|
||||
# Process icons
|
||||
for icon_type in all_medias:
|
||||
service_media = all_medias[icon_type]()
|
||||
service_media.render()
|
||||
|
||||
if self.id != "lutris":
|
||||
for service_media_class in (LutrisIcon, LutrisBanner):
|
||||
service_media = service_media_class()
|
||||
|
|
|
@ -9,6 +9,7 @@ from lutris import settings
|
|||
from lutris.config import LutrisConfig, write_game_config
|
||||
from lutris.database.games import add_game, get_game_by_field
|
||||
from lutris.database.services import ServiceGameCollection
|
||||
from lutris.gui.widgets.utils import Image, paste_overlay, thumbnail_image
|
||||
from lutris.services.base import OnlineService
|
||||
from lutris.services.service_game import ServiceGame
|
||||
from lutris.services.service_media import ServiceMedia
|
||||
|
@ -17,10 +18,42 @@ from lutris.util.egs.egs_launcher import EGSLauncher
|
|||
from lutris.util.log import logger
|
||||
from lutris.util.strings import slugify
|
||||
|
||||
EGS_GAME_ART_PATH = os.path.expanduser("~/.cache/lutris/egs/game_box")
|
||||
EGS_GAME_BOX_PATH = os.path.expanduser("~/.cache/lutris/egs/game_box_tall")
|
||||
EGS_LOGO_PATH = os.path.expanduser("~/.cache/lutris/egs/game_logo")
|
||||
EGS_BANNERS_PATH = os.path.expanduser("~/.cache/lutris/egs/banners")
|
||||
EGS_BOX_ART_PATH = os.path.expanduser("~/.cache/lutris/egs/boxart")
|
||||
BANNER_SIZE = (316, 178)
|
||||
BOX_ART_SIZE = (200, 267)
|
||||
|
||||
|
||||
class DieselGameMedia(ServiceMedia):
|
||||
service = "egs"
|
||||
file_pattern = "%s.jpg"
|
||||
min_logo_x = 300
|
||||
min_logo_y = 150
|
||||
|
||||
def _render_filename(self, filename):
|
||||
game_box_path = os.path.join(self.dest_path, filename)
|
||||
logo_path = os.path.join(EGS_LOGO_PATH, filename.replace(".jpg", ".png"))
|
||||
has_logo = os.path.exists(logo_path)
|
||||
thumb_image = Image.open(game_box_path)
|
||||
thumb_image = thumb_image.convert("RGBA")
|
||||
thumb_image = thumbnail_image(thumb_image, self.size)
|
||||
if has_logo:
|
||||
logo_image = Image.open(logo_path)
|
||||
logo_image = logo_image.convert("RGBA")
|
||||
logo_width, logo_height = logo_image.size
|
||||
if logo_width > self.min_logo_x:
|
||||
logo_image = logo_image.resize((self.min_logo_x, int(
|
||||
logo_height * (self.min_logo_x / logo_width))), resample=Image.BICUBIC)
|
||||
elif logo_height > self.min_logo_y:
|
||||
logo_image = logo_image.resize(
|
||||
(int(logo_width * (self.min_logo_y / logo_height)), self.min_logo_y), resample=Image.BICUBIC)
|
||||
thumb_image = paste_overlay(thumb_image, logo_image)
|
||||
thumb_path = os.path.join(self.dest_path, filename)
|
||||
thumb_image = thumb_image.convert("RGB")
|
||||
thumb_image.save(thumb_path)
|
||||
|
||||
def get_media_url(self, detail):
|
||||
for image in detail.get("keyImages", []):
|
||||
|
@ -31,13 +64,21 @@ class DieselGameMedia(ServiceMedia):
|
|||
class DieselGameBoxTall(DieselGameMedia):
|
||||
"""EGS tall game box"""
|
||||
size = (200, 267)
|
||||
min_logo_x = 100
|
||||
min_logo_y = 100
|
||||
dest_path = os.path.join(settings.CACHE_DIR, "egs/game_box_tall")
|
||||
api_field = "DieselGameBoxTall"
|
||||
|
||||
def render(self):
|
||||
for filename in os.listdir(self.dest_path):
|
||||
self._render_filename(filename)
|
||||
|
||||
class DieselGameBox(DieselGameMedia):
|
||||
|
||||
class DieselGameBox(DieselGameBoxTall):
|
||||
"""EGS game box"""
|
||||
size = (316, 178)
|
||||
min_logo_x = 300
|
||||
min_logo_y = 150
|
||||
dest_path = os.path.join(settings.CACHE_DIR, "egs/game_box")
|
||||
api_field = "DieselGameBox"
|
||||
|
||||
|
@ -45,6 +86,8 @@ class DieselGameBox(DieselGameMedia):
|
|||
class DieselGameBoxLogo(DieselGameMedia):
|
||||
"""EGS game box"""
|
||||
size = (200, 100)
|
||||
file_pattern = "%s.png"
|
||||
visible = False
|
||||
dest_path = os.path.join(settings.CACHE_DIR, "egs/game_logo")
|
||||
api_field = "DieselGameBoxLogo"
|
||||
|
||||
|
@ -74,6 +117,8 @@ class EpicGamesStoreService(OnlineService):
|
|||
medias = {
|
||||
"game_box": DieselGameBox,
|
||||
"box_tall": DieselGameBoxTall,
|
||||
}
|
||||
extra_medias = {
|
||||
"logo": DieselGameBoxLogo,
|
||||
}
|
||||
default_format = "box_tall"
|
||||
|
|
|
@ -18,6 +18,7 @@ class ServiceMedia:
|
|||
service = NotImplemented
|
||||
size = NotImplemented
|
||||
source = "remote" # set to local if the files don't need to be downloaded
|
||||
visible = True # This media should be displayed as an option in the UI
|
||||
small_size = None
|
||||
dest_path = None
|
||||
file_pattern = NotImplemented
|
||||
|
@ -88,3 +89,6 @@ class ServiceMedia:
|
|||
logger.error(ex.code)
|
||||
return None
|
||||
return cache_path
|
||||
|
||||
def render(self):
|
||||
"""Used if the media requires extra processing"""
|
||||
|
|
Loading…
Reference in a new issue