diff --git a/README.md b/README.md index 4a719d4..2e54dcf 100644 --- a/README.md +++ b/README.md @@ -138,6 +138,10 @@ themes/mon-theme/ Les chemins doivent rester dans le dossier du thème (`..` et chemins absolus refusés) et les valeurs des variables ne peuvent pas contenir `url(`, `;` ou `{}` : un thème téléchargé ne peut ni lire vos fichiers ni casser l'interface. Les erreurs de thème sont écrites dans les logs. Les sons d'Orbe sont générés par `node tools/gen-sounds.mjs`. +## Skin Steam + +Pour garder Steam avec le style Orbe : skin CSS Loader pour Big Picture et le mode jeu SteamOS, plus une vidéo de démarrage pour Steam Deck. Voir [`skins/steam`](skins/steam/README.md). + ## Mode kiosque *Paramètres*, *Mode kiosque* : le launcher reste en plein écran et ne se ferme plus au clavier (Alt+F4 ne suffit pas) ; on le quitte par le menu système. diff --git a/skins/steam/Orbe/background.css b/skins/steam/Orbe/background.css new file mode 100644 index 0000000..da11fe8 --- /dev/null +++ b/skins/steam/Orbe/background.css @@ -0,0 +1,5 @@ +/* Orbe de particules (image fixe, rendue par tools/art.html) derrière l'accueil et la bibliothèque */ +.gamepadui_BasicHome.gamepadui_OpaqueBackground, +.gamepadlibrary_GamepadLibrary { + background: url(/themes_custom/Orbe/orb.webp) right -10vw center / auto 110% no-repeat, radial-gradient(ellipse at 74% 50%, #151b09 0%, #0d0f0a 35%, #0a0a0a 70%) !important; +} diff --git a/skins/steam/Orbe/fonts.css b/skins/steam/Orbe/fonts.css new file mode 100644 index 0000000..256cafd --- /dev/null +++ b/skins/steam/Orbe/fonts.css @@ -0,0 +1,9 @@ +/* Archivo à la place de Motiva Sans : on redéclare la famille utilisée par Steam (les dernières déclarations l'emportent), sans toucher aux sélecteurs. */ +@font-face { font-family: "Motiva Sans"; src: url(/themes_custom/Orbe/fonts/Archivo.woff2) format("woff2"); font-weight: 100; } +@font-face { font-family: "Motiva Sans"; src: url(/themes_custom/Orbe/fonts/Archivo.woff2) format("woff2"); font-weight: 300; } +@font-face { font-family: "Motiva Sans"; src: url(/themes_custom/Orbe/fonts/Archivo.woff2) format("woff2"); font-weight: 400; } +@font-face { font-family: "Motiva Sans"; src: url(/themes_custom/Orbe/fonts/Archivo.woff2) format("woff2"); font-weight: 500; } +@font-face { font-family: "Motiva Sans"; src: url(/themes_custom/Orbe/fonts/Archivo.woff2) format("woff2"); font-weight: 700; } +@font-face { font-family: "Motiva Sans"; src: url(/themes_custom/Orbe/fonts/Archivo.woff2) format("woff2"); font-weight: 400; font-style: italic; } +@font-face { font-family: "Motiva Sans"; src: url(/themes_custom/Orbe/fonts/Archivo.woff2) format("woff2"); font-weight: 300; font-style: italic; } +@font-face { font-family: "Motiva Sans"; src: url(/themes_custom/Orbe/fonts/Archivo.woff2) format("woff2"); font-weight: 700; font-style: italic; } diff --git a/skins/steam/Orbe/fonts/Archivo.woff2 b/skins/steam/Orbe/fonts/Archivo.woff2 new file mode 100644 index 0000000..e2448d0 Binary files /dev/null and b/skins/steam/Orbe/fonts/Archivo.woff2 differ diff --git a/skins/steam/Orbe/fonts/OFL-Archivo.txt b/skins/steam/Orbe/fonts/OFL-Archivo.txt new file mode 100644 index 0000000..8597481 --- /dev/null +++ b/skins/steam/Orbe/fonts/OFL-Archivo.txt @@ -0,0 +1,93 @@ +Copyright 2020 The Archivo Project Authors (https://github.com/Omnibus-Type/Archivo) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/skins/steam/Orbe/orb.webp b/skins/steam/Orbe/orb.webp new file mode 100644 index 0000000..6bb81a6 Binary files /dev/null and b/skins/steam/Orbe/orb.webp differ diff --git a/skins/steam/Orbe/shared.css b/skins/steam/Orbe/shared.css new file mode 100644 index 0000000..21e3adb --- /dev/null +++ b/skins/steam/Orbe/shared.css @@ -0,0 +1,61 @@ +/* Orbe pour Steam (Big Picture, mode jeu SteamOS) via CSS Loader. + Les classes sont écrites sous leur nom lisible : CSS Loader les traduit vers les noms de la version de Steam installée + (tools/check.py vérifie qu'elles existent toutes). */ +:root { + --orbe-bg: #0a0a0a; + --orbe-surface: #121212; + --orbe-line: #262624; + --orbe-text: #f5f5f0; + --orbe-muted: #8f8f8a; + --orbe-accent: #d3fd50; +} + +::selection { background: var(--orbe-accent); color: var(--orbe-bg); } + +/* Fonds : noir profond à la place du bleu nuit */ +.gamepadui_BasicHome.gamepadui_OpaqueBackground, +.gamepadlibrary_GamepadLibrary { background: var(--orbe-bg) !important; } +.gamepadpagedsettings_PagedSettingsDialog, +.mainmenu_Menu { background: var(--orbe-bg) !important; } + +/* Jaquettes : contour citron au focus */ +.appportrait_LibraryItemBox.gpfocus { + outline: 3px solid var(--orbe-accent) !important; + outline-offset: 3px; + box-shadow: 0 0 34px rgba(211, 253, 80, .28) !important; +} + +/* Boutons : accent plein au focus */ +button.DialogButton.gpfocus, +button.DialogButton:enabled.gpfocus, +button.gamepaddialog_Button.DialogButton.gpfocus, +button.gamepaddialog_Button.DialogButton:enabled.gpfocus { + background: var(--orbe-accent) !important; + color: var(--orbe-bg) !important; +} + +/* Onglets du haut */ +.gamepadtabbedpage_Tab.gamepadtabbedpage_Selected, +.gamepadtabbedpage_Tab.gamepadtabbedpage_Selected:hover { + background-color: var(--orbe-accent) !important; + color: var(--orbe-bg) !important; +} + +/* Menu principal : entrée active en citron */ +.mainmenu_Item.mainmenu_Active, +.mainmenu_Item.mainmenu_Active .mainmenu_ItemIcon { color: var(--orbe-accent) !important; } + +/* Menus contextuels */ +.gamepadcontextmenu_contextMenuItem.gamepadcontextmenu_Focused { + background: var(--orbe-accent) !important; + color: var(--orbe-bg) !important; +} + +/* Lignes de réglage : léger voile citron au focus */ +.gamepaddialog_Field.gpfocus, +.gamepaddialog_Field.gpfocuswithin { background: rgba(211, 253, 80, .08) !important; } + +/* Interrupteurs et curseurs */ +.gamepaddialog_ToggleRail::before { background: var(--orbe-accent) !important; } +.gamepaddialog_Toggle.gamepaddialog_On .gamepaddialog_ToggleSwitch { background: var(--orbe-bg) !important; } +.gamepadslider_SliderTrack { --left-track-color: var(--orbe-accent) !important; } diff --git a/skins/steam/Orbe/theme.json b/skins/steam/Orbe/theme.json new file mode 100644 index 0000000..5cdb299 --- /dev/null +++ b/skins/steam/Orbe/theme.json @@ -0,0 +1,29 @@ +{ + "name": "Orbe", + "author": "yasder5", + "version": "v1.0.0", + "description": "Le style d'Orbe Launcher dans Steam (Big Picture et mode jeu SteamOS) : noir profond, accent citron, police Archivo, orbe de particules en fond.", + "target": "System-Wide", + "manifest_version": 8, + "inject": { + "shared.css": ["SP", "bigpicture", "QuickAccess", "MainMenu"] + }, + "patches": { + "Police Archivo": { + "default": "Yes", + "type": "checkbox", + "values": { + "Yes": { "fonts.css": ["SP", "bigpicture", "QuickAccess", "MainMenu"] }, + "No": {} + } + }, + "Fond orbe": { + "default": "Yes", + "type": "checkbox", + "values": { + "Yes": { "background.css": ["SP", "bigpicture"] }, + "No": {} + } + } + } +} diff --git a/skins/steam/README.md b/skins/steam/README.md new file mode 100644 index 0000000..f64cfd6 --- /dev/null +++ b/skins/steam/README.md @@ -0,0 +1,26 @@ +# Skin Steam Orbe + +Le style d'Orbe Launcher pour l'interface manette de Steam (Big Picture sous Windows, mode jeu SteamOS / Steam Deck), via [CSS Loader](https://github.com/DeckThemes/SDH-CssLoader). Rien n'est modifié dans les fichiers de Steam. + +- `Orbe/` : le thème CSS Loader (couleurs dans `shared.css`, options « Police Archivo » et « Fond orbe »). +- `deck_startup.webm` : vidéo de démarrage 1280×800 pour Steam Deck / SteamOS. +- `tools/check.py` : vérifie que chaque classe utilisée existe dans la version actuelle de Steam. +- `tools/art.html` + `tools/render.py` : rendent `Orbe/orb.webp` et les images de la vidéo. + +## Installer + +**Steam Deck / SteamOS** : Decky Loader, puis CSS Loader depuis sa boutique ; copier `Orbe/` dans `~/homebrew/themes/` et l'activer dans CSS Loader. + +**Windows (Big Picture)** : [CSSLoader Desktop](https://github.com/beebls/CSSLoader-Desktop/releases) ; activer le mode développeur de Windows et redémarrer le backend une fois (police et fond) ; copier `Orbe/` dans `%USERPROFILE%\homebrew\themes\`. + +**Vidéo de démarrage** : copier `deck_startup.webm` dans `~/.steam/root/config/uioverrides/movies/`, puis Paramètres, Personnalisation, Vidéo de démarrage. + +## Classes Steam + +Les sélecteurs utilisent les noms lisibles (`gamepaddialog_ToggleRail`) : CSS Loader les traduit vers les noms obfusqués de la version de Steam installée. Après une mise à jour de Steam : + +```sh +curl -so map.json https://api.deckthemes.com/stable.json +# sp.css : dans le paquet steamui_websrc_all du client (liste : client-update.steamstatic.com/steam_client_ubuntu12) +python3 tools/check.py map.json sp.css +``` diff --git a/skins/steam/deck_startup.webm b/skins/steam/deck_startup.webm new file mode 100644 index 0000000..d8783b3 Binary files /dev/null and b/skins/steam/deck_startup.webm differ diff --git a/skins/steam/tools/art.html b/skins/steam/tools/art.html new file mode 100644 index 0000000..557c27c --- /dev/null +++ b/skins/steam/tools/art.html @@ -0,0 +1,60 @@ + + + + +Orbe Steam art + + + + +
orbe.
+ + + diff --git a/skins/steam/tools/check.py b/skins/steam/tools/check.py new file mode 100644 index 0000000..b51785e --- /dev/null +++ b/skins/steam/tools/check.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python3 +"""Vérifie que chaque classe lisible du skin (module_Nom) est connue de CSS Loader et existe dans l'interface Steam actuelle. +Usage : check.py """ +import json, re, sys +from pathlib import Path + +mapping, sp = json.load(open(sys.argv[1])), open(sys.argv[2]).read() +alias = {a: v[-1] for v in mapping.values() for a in v} +bad = 0 +for f in sorted((Path(__file__).parent.parent / "Orbe").glob("*.css")): + for name in sorted(set(re.findall(r"\.([a-z]+_[A-Za-z]+)\b", f.read_text()))): + cur = alias.get(name) + ok = cur is not None and re.search(r"\." + re.escape(cur) + r"(?![\w-])", sp) + bad += not ok + print("%-4s %-12s %-45s %s" % ("ok" if ok else "ABS", f.name, name, cur or "-")) +sys.exit(1 if bad else 0) diff --git a/skins/steam/tools/render.py b/skins/steam/tools/render.py new file mode 100644 index 0000000..3144619 --- /dev/null +++ b/skins/steam/tools/render.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +"""Rend tools/art.html dans un Chromium headless (protocole CDP) : fond orbe (PNG transparent) et vidéo de démarrage (images PNG). +Usage : render.py """ +import base64, json, os, sys, time, urllib.request +import websocket + +url, cdp, out = sys.argv[1:4] +os.makedirs(out + "/frames", exist_ok=True) +t = json.load(urllib.request.urlopen(urllib.request.Request(cdp + "/json/new?about:blank", method="PUT"))) +ws, n = websocket.create_connection(t["webSocketDebuggerUrl"], timeout=60), 0 + + +def cmd(method, **params): + global n + n += 1 + ws.send(json.dumps({"id": n, "method": method, "params": params})) + while True: + m = json.loads(ws.recv()) + if m.get("id") == n: + return m.get("result", {}) + + +def shot(path, w, h): + png = cmd("Page.captureScreenshot", format="png", clip={"x": 0, "y": 0, "width": w, "height": h, "scale": 1})["data"] + open(path, "wb").write(base64.b64decode(png)) + + +def load(mode, w, h): + cmd("Emulation.setDeviceMetricsOverride", width=w, height=h, deviceScaleFactor=1, mobile=False) + cmd("Emulation.setDefaultBackgroundColorOverride", color={"r": 0, "g": 0, "b": 0, "a": 0}) + cmd("Page.navigate", url=url + "?mode=" + mode) + time.sleep(1.5) + cmd("Runtime.evaluate", expression="document.fonts.ready", awaitPromise=True) + + +cmd("Page.enable") +load("bg", 1920, 1080) +cmd("Runtime.evaluate", expression="render(2)") +shot(out + "/orb.png", 1920, 1080) + +load("boot", 1280, 800) +for i in range(120): # 4 s à 30 i/s + cmd("Runtime.evaluate", expression="render(%f)" % (i / 30)) + shot("%s/frames/%03d.png" % (out, i), 1280, 800) +cmd("Page.close")