Ajouter un nouveau « design » de contrôleur/gamepad

Dans cet article, on va expliquer comment « bien » rajouter les images et les éléments pour pouvoir avoir un visuel spécifique et réaliste pour une manette. On expliquera aussi les parties QML à changer pour que cela puisse être intégrer dans la partie front end de Pegasus.

Dans cette article, on va voir avec le cas d’un manette de SNES (dans ce cas, on va prendre le visuelle de la Nintendo Switch Online SNES qui permet de couvrir le plus de cas de manettes SNES du marché parce qu’elle a un bouton L1/R1, mais aussi L2/R2). Bien sur, dans ce cas, on n’aura pas de stick analogique ni de L3/R3.

Choisir un image de « base » de qualité

Dans le cas de la SNES, j’ai pris cette du site de Nintendo switch online qui me semble vraiment belle, détaillé et sans ombre. On devra travailler avec des .png, les .svg n’apportent pas grand chose quand on utilise une source photo et non véctorielle.

Photo du site avec fond blanc (sans trop d’ombre et avec une vue sur chaque touche, même ceux de la tranche même si j’avoue que c’est limité et petit)

Préparer l’image de base à afficher

Dans mon cas, j’ouvre le fichier avec GIMP https://www.gimp.org/ puis avec l’outil de sélection contigu

je sélectionne le fond blanc :

Pour selectionné encore mieux vous pouvez aussi utiliser « l’outil de sélection par couleur » :

et en jouant sur le seuil

Puis j’ajoute un « canal alpha » au calque (en faisant bouton droit sur celui-ci):

Ainsi quand je supprime la zone sélectionnée, il me reste que la partie de la manette avec un fond transparent :

Astuce: il peut rester des petites parties que l’on ne peut pas enlever automatiquement,
il faudra donc les supprimer avec un outil de sélection par zone par exemple ou un outil de gomme de pixel

Ensuite je réduite le calque pour suivre les contours de la manette en allant dans « image/rogner selon le contenu » :

Maintenant le fichier de « base » est prêt, on va pouvoir l’exporter dans « fichier/exporter sous » et en sélectionnant le format .png (et pour les autres paramètres, on peut garder par défaut ceux de GIMP):

En terme de nommage, c’est bien de suivre la règle:

base_XXXXXX.png

XXXXX est le nom ou acronyme de la manette (s’assurer que c’est bien unique et pas déjà utilisé bien sur 😉

Dans notre cas, c’est « base_snes.png« 

Attention, dans certains, il faudra corrigé des imperfections dans le détourages en virant des pixels voir un ligne entière manuellement si besoin ou corriger un rognage mal placé, C’est pas magique même si 99% du boulot sera acceptable, on pourra peaufiner si besoin ! 😉

On peut aussi pour un rendu encore meilleur dans pixL, supprimer les boutons de façade et remplacer la zone par du noir (à ne pas faire pour les boutons de tranches et autres gachettes qui n’utilisent pas le même type d’animation au final)

Et donc utiliser une image ainsi:

Préparer les images de boutons/pads/sticks/gâchettes

Pour les boutons, le challenge va être de bien les détourer avec l’outil de sélection de couleur ou contigu et en jouant sur les seuils, le but va être de les isolés dans un .png dédié.

On aura 2 solutions de sélections pour le rendu final:

  1. on peut sélectionner en évitant de prendre les contour noir ou unie qui ne font pas parti du bouton.
  2. on peut sélectionner le contour noir si on pense pouvoir le réutiliser directement pour les animations.

On pourra aussi utiliser « l’outil de sélection elliptique »

Pour les boutons :

Puis on ira le « copier puis le coller dans un nouvelle image »…

Astuce: certaines fois les boutons ne seront pas rond ou ovale par exemple, dans ce cas un outils de sélection utilisant une suite de ligne ou à main levé sera nécessaire. Parfois on utilise aussi plusieurs formes elliptiques que l’on merge pour avoir le bouton en entier. (dans GIMP, on maintient la touche « shift » du clavier pour faire une sélection supplémentaire)

Qui nous donnera un nouvelle image avec un fond transparent:

Sans le tour noir (on devra prendre un outil de dessin et ajouter un cercle noir autour assez épais mais on devra avoir une image un peut plus grande peut être).
Avec le tour noir (on devra peut être reprendre l’image avec un outil de dessin et ajouter un cercle noir plus marqué si besoin)

Donc il faudra tester pour choisir le bon bouton finalement. Je conseil de tester un premier bouton dans le QML avant de continuer pour les autres boutons.

La convention de nommage sera la suivante :

{bouton}_XXXXXX.png

où:

{bouton} sera « a », »b », »x », »y », »l1″ etc…

et XXXXX est le nom ou acronyme de la manette (s’assurer que c’est bien unique et pas déjà utilisé bien sur 😉

Dans notre cas, on a fait le bouton x, donc le nom sera « x_snes.png« 

Rajouter des bords noir (si besoin… et que pour les boutons)

Pas applicable pour les gachettes/stick/dpad parce que l’on veut pas de bord noir dans ces cas

Le but est d’expliqué ici comment rajouter directement dans the gimp un tour noir plus prononcé pour accentuer l’appui sur la touche lors de l’animation

Attention, ce n’est pas forcément le mieux, il faut tester pour s’en assurer, cela peut faire moche finalement.

De plus, je me suis rendu compte que si la sélection du bouton est bien faite (en fesant attention de bien prendre la limite du bouton et le corps de la manette (souvent en étant sur la partie noir/grisatre entre les deux), ce n’est plus nécessaire.

On va d’abord resélectionné le bouton lui même avec l’outil de sélection elliptique

On prend bien soin d’entourer le bouton et toucher les bords du calque

Puis on va aller dans le menu « Sélection/Bordure »

On va juste prendre un bord de « 1 » pixel et en style de bordure « Adouci » et valider

Maintenant on va pouvoir remplir la zone autour du bouton avec du noir avec l’outil de remplissage (assuré vous que la couleur noire est bien sélectionné)

Pour avoir un beau cercle noir autour du bouton :

On pourra donc exporter de nouveau en png pour sauvegarder et écraser le fichier précédent si besoin :

Où mettre les nouvelles images préparées ?

Lien de l’ensemble des manettes faites par Aldébaran: https://drive.proton.me/urls/0ED4SCQFQ0#Xk3iNVodSq3K

on va rajouter les fichier de base (exemple: « base_snes.png ») & des touches (exemple: « x_snes.png ») dans le répertoire: src/frontend/assets/gamepad/{XXXXX} acronyme du pad et il faudra les rajouter aussi dans le projet pour être pris en compte dans le .qrc correspondant.

Remarque: pour bien prendre en compte les nouvelles ressources, il faudra « cleaner » et bien rebuilder le projet entièrement.

Attention: ne jamais modifier les fichiers ressources comme les .qrc directement « à la main » pour éviter des erreurs surtout si on doit changer plusieurs lignes, cela ne sera pas possible de valider/vérifier par la suite et cela sera source d’erreur/mismatch entre les ressources à utiliser et celle qui ont été importé. Si on doit un jour corriger une ressource « bugué » par exemple, on le fera sur peu de ligne et on en avertira les autres devs pour validation et éviter des erreurs potentielles.

Paramètres à gérer

Créer des nouvelles images et des QMLs ne sont pas suffisant.

Il faudra le lié à un groupe de controlleur dans le ListModel « myDeviceIcons » qui se trouve dans src/frontend/main.qml et en rajoutant la partie en rouge:

    //list model to manage icons of devices
    ListModel {
        id: myDeviceIcons

        //CONTROLLERS PART
...
        ListElement { icon: "\uf25e"; keywords: "snes,super nintendo"; type:"controller"; iconfont: "awesome"; layout: "snes"}
...
   }

Attention: les contrôleurs sans « layout » déclaré utiliseront le layout « default »

Gestion des icones au passage (si besoin/manquante)

Pour information, la valeur icon et iconfont sont là pour customiser l’icone qui s’affiche quand vous connectez la manette ou quand on l’affiche dans la liste des contrôleurs.

le « \u » est pour préciser que l’on charge une valeur hexadécimal qui est la référence du caractère dans la police correspondante, ex: « awesome » qui est déclaré comme « Font » disponible dans Pegasus-Frontend.

Si vous ne savez pas comment récupérer une valeur spécifique (en fait, il faut être capable d’ouvrir une des fontes disponibles dans les assets de Pegasus et voir quelle icone utiliser et son code correspondant, voir même en rajoutant si besoin mais c’est surement le sujet d’un autre article 😉

Exemple d’outil de consultation des fonts : FontForge (il y a peut être un outil mieux maintenant… il est vieillissant) https://sourceforge.net/projects/fontforge/files/fontforge-executables/

Si on veut rajouter des nouvelles icones dans une fonte, il faudra :

  1. Ouvrir la font en question « fontawesome_webfont.ttf » aller en position F0D1 ou plus vu que l’on a déjà mis d’autres icones de manette.
  2. Double-cliquer sur une case vide pour aller en mode Edition de la font
  3. Importer des .svg pas trop lourd ou via un copier/coller venant de l’outil « lnkscape » https://inkscape.org/
  4. Fermer la fenêtre d’édition
  5. Vérifier que l’on voit bien la nouvelle icone
  6. Générer la fonte (ne pas simplement l’enregistrer sinon le format sera corrompu)
Exemple d’utilisation avec l’outil « lnkscape » : https://inkscape.org/
Après copier/coller ou importation du fichier .svg de l’icone en question (bien resté dans le carré central, on aura peut être besoin de redimensionner)
Exemple d’icone déjà créé pour ce projet

Attention, par défaut le nom proposé du fichier à générer est « FontAwesome.ttf », et donc il faudra bien renommer en « fontawesome_webfront.ttf » qui est le nom dans le repo (me demandez pas pourquoi, c’est historique, il faudrait le changer un jour peut-être 😉

la font sera bien à « générer » avec le même nom attention pour écraser l’ancienne dans le repo de Pegasus-Frontend mais pas à « enregister »
C’est normal d’avoir cette alerte, on doit pouvoir générer (à tester dans tout les cas 😉

Si besoin de convertir de png/jpeg à svg, vous pouvez passer aussi par ce type d’outil par exemple : https://convertio.co/fr/png-svg/

Gestion du fichier qml à utiliser

Ensuite, Il faudra aussi mettre à jour le ListModel qui se trouve dans src/frontend/menu/settings/GamepadEditor.qml et dans un premier temps en rajoutant dans un ListElement le nom (exemple pour la SNES) et on utilisera toujours le même « Container » generique pour un nouveau layout (gamepad/preview/ContainerCustom.qml):

ListModel{
    id: myControllerLayout
        ListElement{name:"nes" ; qml:"gamepad/preview/ContainerCustom.qml"
...
}
        ListElement{name:"snes" ; qml:"gamepad/preview/ContainerCustom.qml"
}

}

Remarque: en annexe on explique comment rajouter un nouveau Container (en mode expert 😉 mais cela sera rarement voir jamais utile.

Il va falloir maintenant gérer les coordonnées et donc le placement des boutons/dpad/sticks sur la « base ».

Attention : on devra gérer un ratio parce que l’affichage du « layout » du contrôleur devra être adapté dans certains cas. comme ci-après par exemple :

Il va falloir déjà préciser les informations de la « base » :

ratio: 80/100 //at 80% of the size to enter in the existing container available
padVaseSoureceSizeWidth: 906
padBaseSourceSizeHeight: 398

Remarque: Le « ratio » est important parce que certaines fois, l’image devra être zoomé ou rétrécie pour optimiser au mieux l’affichage.

Il va falloir aussi rentrer les coordonnées à partir de l’image de base, voici dans le cas du « select »…

Pour cela nous allons utiliser Gimp aussi pour connaitre les informations à remplir :

  • Pour la taille de l’image on va aller dans « Image/Taille du Canevas »
On pourra récuper la largeur et la hauteur initial de l’image en question
        padSelectWidth : 69;
        padSelectHeight : 59;

Pour le positionnement du bouton, on va préciser les coordonnées de l’image dans l’image de base généralement en X/Y et en 2 infos: left X & top Y. voici pour l’info « top Y », on va se mettre en haut de l’image et lire la valeur en Y en bas à gauche (la seconde valeur) :

Dans ce cas, on est à « 205 » en Y
        padSelectTopY: 205;
        padSelectLeftX: 334;

Avec ceci, la taille de l’image en pixel + et les informations en X/Y, cela suffit à bien positionner le bouton dans l’image de base.

Attention, il faudra être rigoureux, RighX – LeftX = Width & BottomY – TopY = Height, c’est pour cela que l’on rentre les largeurs/hauteurs en plus des coordonnées pour être au plus juste. Un pixel peut faire la différence.

Donc en conclusion pour un pad comme celui de la SNES, voici les paramètre nécessaire que l’on va devoir mettre dans le ListElement correspondant pour la partie coordonnées:

                           //parameters for 'base'
                           ratio: 0.8; 
                           padBaseSourceSizeWidth : 906 ;
                           padBaseSourceSizeHeight : 398;
                          
                            //parameters for select
                            padSelectWidth : 69;
                            padSelectHeight : 59;
                            padSelectTopY: 205;
                            padSelectLeftX: 334;

                            //parameters for start
                            padStartWidth : 69;
                            padStartHeight : 59;
                            padStartTopY: 205;
                            padStartLeftX: 432;

                            //parameters for A/B/X/Y
                            padAWidth : 71;
                            padAHeight : 70;
                            padATopY: 170;
                            padALeftX: 763;

                            padBWidth : 71;
                            padBHeight : 71;
                            padBTopY: 237;
                            padBLeftX: 677;

                            padXWidth : 71;
                            padXHeight : 71;
                            padXTopY: 103;
                            padXLeftX: 677;

                            padYWidth : 73;
                            padYHeight : 72;
                            padYTopY: 170;
                            padYLeftX: 590;

                            //parameter for Dpad
                            dpadAreaTopY: 126;
                            dpadAreaBottomY: 285;
                            dpadAreaLeftX: 112;
                            dpadAreaRightX: 270;

                            //parameter for L1
                            padL1Width : 198;
                            padL1Height : 37;
                            padL1TopY: 0;
                            padL1LeftX: 97;

                            //parameter for R1
                            padR1Width : 198;
                            padR1Height : 36;
                            padR1TopY: 1;
                            padR1LeftX: 612;

                            //parameter for L2
                            padL2Width : 48;
                            padL2Height : 5;
                            padL2TopY: 4;
                            padL2LeftX: 350;

                            //parameter for R2
                            padR2Width : 54;
                            padR2Height : 6;
                            padR2TopY: 4;
                            padR2LeftX: 509;

De plus, on aura aussi le mapping des touches disponibles qui est décrit dans le ListElement pour nous permettre de savoir les touches disponibles et ne plus demander de configurer des touches non disponibles (pratique non ? ;-):

    //layout availability features list
    property var hasSelect : true
    property var hasStart : true
    property var hasDedicatedGuide : false
    property var hasDpad : true
    property var hasA : true
    property var hasB : true
    property var hasX : true
    property var hasY : true
    property var hasL1 : true
    property var hasR1 : true
    property var hasL2 : true
    property var hasR2 : true
    property var hasLeftStick : false
    property var hasRightStick : false
    property var hasScreenshotButton : false

Au final le nouveau ListElement complet ressemblera à cela :

            ListElement {   name: "snes"; qml: "gamepad/preview/ContainerCustom.qml";

                            hasDedicatedGuide: false;
                            hasSelect: true;
                            hasStart: true;

                            hasA: true;
                            hasB: true;
                            hasX: true;
                            hasY: true;
                            hasNintendoPad : true;

                            hasL1 : true; hasR1 : true;
                            hasL2 : true; hasR2 : true;

                            hasLeftStick : false; hasRightStick : false;
                            hasL3 : false; hasR3 : false;

                            hasScreenshotButton : false;

                            ratio: 0.8; padBaseSourceSizeWidth : 906 ; padBaseSourceSizeHeight : 398;
                            //parameters for select
                            padSelectWidth : 69;
                            padSelectHeight : 59;
                            padSelectTopY: 205;
                            padSelectLeftX: 334;

                            //parameters for start
                            padStartWidth : 69;
                            padStartHeight : 59;
                            padStartTopY: 205;
                            padStartLeftX: 432;

                            //parameters for A/B/X/Y
                            padAWidth : 71;
                            padAHeight : 70;
                            padATopY: 170;
                            padALeftX: 763;

                            padBWidth : 71;
                            padBHeight : 71;
                            padBTopY: 237;
                            padBLeftX: 677;

                            padXWidth : 71;
                            padXHeight : 71;
                            padXTopY: 103;
                            padXLeftX: 677;

                            padYWidth : 73;
                            padYHeight : 72;
                            padYTopY: 170;
                            padYLeftX: 590;

                            //parameter for Dpad
                            dpadAreaTopY: 126;
                            dpadAreaBottomY: 285;
                            dpadAreaLeftX: 112;
                            dpadAreaRightX: 270;

                            //parameter for L1
                            padL1Width : 198;
                            padL1Height : 37;
                            padL1TopY: 0;
                            padL1LeftX: 97;

                            //parameter for R1
                            padR1Width : 198;
                            padR1Height : 36;
                            padR1TopY: 1;
                            padR1LeftX: 612;

                            //parameter for L2
                            padL2Width : 48;
                            padL2Height : 5;
                            padL2TopY: 4;
                            padL2LeftX: 350;

                            //parameter for R2
                            padR2Width : 54;
                            padR2Height : 6;
                            padR2TopY: 4;
                            padR2LeftX: 509;

            } //As SNES pad (but with L2/R2 to be compatible with switch online ones)

Cela semble beaucoup de paramètre mais ne peut pas vraiment faire autrement… donc si on a bien mesuré/reporté les dimensions, on pourra afficher cela au final :

Pour ce visuel, on voit pas forcément très bien les touches de tranche.

ou même cela…

Pour ce visuel, la tranche est bien montré sans être obligé de la rajouter par nous même.

et la version avec sticks 😉

Pour ce visuel, nous avons du rajouter une tranche pour voir L1/R1 & L2/R2

Pour ce visuel, nous avons du gérer les D-pads utilisant des boutons.Nous avons du rajouter une tranche aussi.

Prenons justement le cas de la manette de xbox 360 pour décrire certains paramètres importants à connaitre plus en détails :

                            hasDedicatedGuide: true; 
                            hasSelect: true;
                            hasStart: true;

hasDedicatedGuide va nous permettre de préciser si on a le « select » qui fera office de hotkey/guide ou pas. Si à « true » cela veut dire que l’on a une touche dédié à la hotkey qui pourra être utilisé.

                            hasA: true;
                            hasB: true;
                            hasX: true;
                            hasY: true;
                            hasNintendoPad : false;

hasNintendoPad va nous permettre d’inverser x/y et a/b en fonction du mapping et l’aide contextuelle de la manette s’adaptera mais que dans le menu « gamepad Editor » pour le moment. Ceci pour éviter des incompréhensions d’usage des boutons A/B dans les menus par exemple

                        hasL1 : true; hasR1 : true;
                        hasL2 : true; hasR2 : true;

                        hasLeftStick : true; hasRightStick : true;
                        hasL3 : true; hasR3 : true;

hasLeftStick/hasRightStick va permettre de préciser que l’on utilise ou pas des sticks (juste L3/R3 utiliseront la même image que les sticks justement ex: lstick_xbox360 et rstick_xbox360)

                            //parameter for Dpad
                            dpadAreaTopY: 163;
                            dpadAreaBottomY: 289;
                            dpadAreaLeftX: 64;
                            dpadAreaRightX: 205;

Attention, pour le dpad, on utilise le coin supérieur gauche et le coin inférieur droit quand c’est une croix directionnelle (et pas la largeur/hauteur comme pour les boutons)

                            //parameter for Dpad with dedicated buttons and separated
                            dpadUpWidth : 69;
                            dpadUpHeight : 89;
                            dpadUpTopY: 189;
                            dpadUpLeftX: 213;

                            dpadDownWidth : 67;
                            dpadDownHeight : 89;
                            dpadDownTopY: 309;
                            dpadDownLeftX: 215;

                            dpadLeftWidth : 89;
                            dpadLeftHeight : 70;
                            dpadLeftTopY: 259;
                            dpadLeftLeftX: 145;

                            dpadRightWidth : 88;
                            dpadRightHeight : 70;
                            dpadRightTopY: 259;
                            dpadRightLeftX: 264;

Attention: Mais pour un Dpad comme celui du contrôleur de la PS4 avec des boutons indépendants, on aura plus de paramètres à saisir et cela sera géré comme des boutons. (voir ci-dessus, 4 paramètres par direction, up/down/left/right), les images des boutons seront du type: dpup_XXXX.png, dpdown_XXXX.png, dpright_XXXX.png et dpleft_XXXX.png

                            hasScreenshotButton : false;

hasScreenshotButton est pour voir par la suite si on pourra utiliser des boutons disctincts pour prendre des screenshots. Ce n’est pas encore supporté.

                            //to adapt contrast/brightness
                            contrast : 0.5
                            brightness: 0.5

contrast et brightness aident à distinguer quand on presse sur un bouton (à l’exception de A/B/X/Y qui reste à des valeurs moyennes (0.5)) mais pour les autres on peut les adapter en fonction de la couleur et du contrast du « layout » concerné. Les valeurs sont des « float » et doivent être plus grand que 0.0 et au maximum à 1.0

Par exemple, pour une manette plutôt noire comme celle de la PS4: c’est mieux d’augmenter « brightness » au dessus de 0.5 et baisser « contrast » en dessous de 0.5, mais cela reste à tester à chaque fois que l’on rajoute un layout.

Voilà, il reste les annexes si cela peut aider et voir comment on va pouvoir évoluer par la suite 😉

Enjoy !!!

ANNEXES

Liste des types de contrôleurs supportés à ce jour (dernière mise à jour: 06-03-2023)

(Attention, à ce jour Pegasus détecte par le nom et pas par le GUID. C’est pour que cela marche avec le plus de manette possible)

Pour rappel, le layout générique « default » est Container.qml

Type de manetteLayout utiliséMots clé recherché
dans le nom de la manette
Apparence
nesContainerCustom.qmlnes,nintendo entertainment system
snesContainerCustom.qmlsnes,super nintendo
xbox360ContainerCustom.qmlx360,xbox360,xbox 360,x-box 360
xboxoneContainerCustom.qmlxboxone,xbox one,x-box one
ps4ContainerCustom.qmlps4,playstation 4,dualshock 4,wireless controller
ps5ContainerCustom.qmlps5,playstation 5,dualsense,wireless controller
n64ContainerCustom.qmln64,nintendo 64,nintendo64,huijia
switchproContainerCustom.qmlpro controller
Attention, pour certains cas comme la ps4/ps5, le nom peut être identique dans ce cas, il faudra le fixer par GUID dans l’es_input.cfg maintenant (depuis le 06/03/2023) – expliqué dans un chapitre plus bas.

Exemple d’éléments graphiques d’une manette

Les noms de fichiers ne sont pas forcément les bons, on est au début où on doit décomposer les éléments et préparer la base.

Pour tester/introduire un nouveau type de « Container » dans le QML

On aura besoin rarement de faire cela mais cela peut être utile de savoir comment faire un nouveau qml « container » même si avec l’introduction du « ContainerCustom.qml » et la gestion de ces paramètres, on en a plus vraiment besoin de le faire.

Donc, si on en a vraiment besoin (j’insiste ;-), on va juste modifier le qml et ajouter des fichiers dans le projet de Pegasus pour tester. (il faudra être capable de compiler)

  1. on va se créer un qml spécifique pour la « snes » dans ce cas, ContainerSNES.qml dans le répertoire: src/frontend/menu/settings/gamepad/preview à partir d’un ContainerXXXXX.qml précédent.
  2. on va se créer aussi un qml spécifique pour les boutons « snes », PadButtonSNES.qml dans le répertoire: src/frontend/menu/settings/gamepad/preview à partir d’un PadButtonXXXXX.qml précédent.
  3. Dans ContainerSNES.qml, on va changer la source de l’image « padBase » par « qrc:/frontend/assets/gamepad/base_snes.png« 
  4. Pour l’instant dans PadButtonSNES.qml, on va changer la source de l’image « pieceImage » par « qrc:/frontend/assets/gamepad/ » + sortName + « _snes.png » en ligne 32.
  5. Pour tester le nouveau ContainerXXXXXXX.qml, on va juste l’intégrer dans la liste des « Layout » connu comme décrit dans le paragraphe ci-après.

Remarque: pour bien prendre en compte les nouvelles ressources, il faudra « cleaner » et bien rebuilder le projet entièrement.

Gérer un nouveau « layout »

En fait, on peut gérer des « layout » de style de manettes si besoin, par exemple, à ce jour on a le « layout » SNES qui sait géré des manettes avec 4 boutons + L1/R1 + L2/R2 (comme sur la switchj 😉 et un DPAD, mais sans sticks et seulement avec start/select et pas de touche dédié pour la hotkey.

Donc si on veut gérer un nouveau, il faudra mettre à jour le ListModel qui se trouve dans GamepadEditor.qml dans un premier temps en rajoutant un ListElement un nom et le chemin du fichier comme ci-après (exemple pour la SNES):

ListModel{
    id: myControllerLayout
        ListElement{name:"snes" ; qml:"gamepad/preview/ContainerSNES.qml"}
}

Puis il faudra le lié à un groupe de controlleur dans le ListModel qui se trouve dans main.qml et en rajoutant la partie en rouge:

    //list model to manage icons of devices
    ListModel {
        id: myDeviceIcons

        //CONTROLLERS PART
...
        ListElement { icon: "\uf25e"; keywords: "snes,super nintendo"; type:"controller"; iconfont: "awesome"; layout: "snes"}
...
   }

Remarque: si on ne défini pas de layout à ce niveau, on ira chercher un layout existant« 

Fixer le « device layout » du design par le GUID du contrôleur (mise à jour du 06/03/2023)

Suite à la constatation que dans certains cas, des manettes possèdent le même nom même si elles sont de générations différentes: c’est le cas par exemple de la manette de PS4 et PS5 qui ont toutes les 2 le même nom générique « wireless controller », il a fallut mettre en place la gestion d’un « device layout » qui fait référence au design voulu au niveau de l’es_input.cfg maintenant.

Bien sur, le « device layout » est un paramètre optionnel pour garder la possibilité de chercher par nom qui a aussi ses avantages, et donc sans celui-ci dans l’es_inpujt.cfg, on cherchera dans la liste que l’on a déjà fourni avec une recherche par nom pour sélectionner le design associé.

le nouvelle attribut devra être ainsi:

deviceLayout="ps4"
ou
deviceLayout="ps5"
deviceLayout="xxx"

Il faudra faire référence dans ce « layout » au design existant et déjà défini pour bien forcer l’utilisation d’un design ou d’un autre.

Exemple pour une manette de ps4 :

    <!-- Ps4 Wired -->
    <inputConfig deviceLayout="ps4" deviceName="Sony Computer Entertainment Wireless Controller" deviceGUID="030000004c050000c405000011810000" deviceNbButtons="13" type="joystick" deviceNbAxes="6" deviceNbHats="1">
        <input name="b" id="0" code="304" type="button" value="1"/>
        <input name="a" id="1" code="305" type="button" value="1"/>
        <input name="select" id="8" code="314" type="button" value="1"/>
        <input name="down" id="0" code="16" type="hat" value="4"/>
        <input name="left" id="0" code="16" type="hat" value="8"/>
        <input name="right" id="0" code="16" type="hat" value="2"/>
        <input name="up" id="0" code="16" type="hat" value="1"/>
        <input name="hotkey" id="10" code="316" type="button" value="1"/>
        <input name="l1" id="4" code="310" type="button" value="1"/>
        <input name="l3" id="11" code="317" type="button" value="1"/>
        <input name="l2" id="6" code="312" type="button" value="1"/>
        <input name="joystick1left" id="0" code="0" type="axis" value="-1"/>
        <input name="joystick1up" id="1" code="1" type="axis" value="-1"/>
        <input name="r1" id="5" code="311" type="button" value="1"/>
        <input name="r3" id="12" code="318" type="button" value="1"/>
        <input name="r2" id="7" code="313" type="button" value="1"/>
        <input name="joystick2left" id="3" code="3" type="axis" value="-1"/>
        <input name="joystick2up" id="4" code="4" type="axis" value="-1"/>
        <input name="start" id="9" code="315" type="button" value="1"/>
        <input name="y" id="3" code="308" type="button" value="1"/>
        <input name="x" id="2" code="307" type="button" value="1"/>
    </inputConfig>
    <!-- PS4 BT -->
    <inputConfig deviceLayout="ps4" deviceName="Wireless Controller" deviceGUID="050000004c050000c405000000810000" deviceNbButtons="13" type="joystick" deviceNbAxes="6" deviceNbHats="1">
        <input name="b" id="0" code="304" type="button" value="1"/>
        <input name="a" id="1" code="305" type="button" value="1"/>
        <input name="select" id="8" code="314" type="button" value="1"/>
        <input name="down" id="0" code="16" type="hat" value="4"/>
        <input name="left" id="0" code="16" type="hat" value="8"/>
        <input name="right" id="0" code="16" type="hat" value="2"/>
        <input name="up" id="0" code="16" type="hat" value="1"/>
        <input name="hotkey" id="10" code="316" type="button" value="1"/>
        <input name="l1" id="4" code="310" type="button" value="1"/>
        <input name="l3" id="11" code="317" type="button" value="1"/>
        <input name="l2" id="6" code="312" type="button" value="1"/>
        <input name="joystick1left" id="0" code="0" type="axis" value="-1"/>
        <input name="joystick1up" id="1" code="1" type="axis" value="-1"/>
        <input name="r1" id="5" code="311" type="button" value="1"/>
        <input name="r3" id="12" code="318" type="button" value="1"/>
        <input name="r2" id="7" code="313" type="button" value="1"/>
        <input name="joystick2left" id="3" code="3" type="axis" value="-1"/>
        <input name="joystick2up" id="4" code="4" type="axis" value="-1"/>
        <input name="start" id="9" code="315" type="button" value="1"/>
        <input name="y" id="3" code="308" type="button" value="1"/>
        <input name="x" id="2" code="307" type="button" value="1"/>
    </inputConfig>

Exemple pour une manette de ps5 :

    <!-- PS5 Official USB -->
    <inputConfig deviceLayout="ps5" deviceName="Sony Interactive Entertainment Wireless Controller" deviceGUID="030000004c050000e60c000011810000" deviceNbButtons="13" type="joystick" deviceNbAxes="6" deviceNbHats="1">
        <input name="b" id="0" code="304" type="button" value="1"/>
        <input name="a" id="1" code="305" type="button" value="1"/>
        <input name="select" id="8" code="314" type="button" value="1"/>
        <input name="down" id="0" code="16" type="hat" value="4"/>
        <input name="left" id="0" code="16" type="hat" value="8"/>
        <input name="right" id="0" code="16" type="hat" value="2"/>
        <input name="up" id="0" code="16" type="hat" value="1"/>
        <input name="hotkey" id="10" code="316" type="button" value="1"/>
        <input name="l1" id="4" code="310" type="button" value="1"/>
        <input name="l3" id="11" code="317" type="button" value="1"/>
        <input name="l2" id="2" code="2" type="axis" value="-1"/>
        <input name="joystick1left" id="0" code="0" type="axis" value="-1"/>
        <input name="joystick1up" id="1" code="1" type="axis" value="-1"/>
        <input name="r1" id="5" code="311" type="button" value="1"/>
        <input name="r3" id="12" code="318" type="button" value="1"/>
        <input name="r2" id="5" code="5" type="axis" value="-1"/>
        <input name="joystick2left" id="3" code="3" type="axis" value="-1"/>
        <input name="joystick2up" id="4" code="4" type="axis" value="-1"/>
        <input name="start" id="9" code="315" type="button" value="1"/>
        <input name="y" id="3" code="308" type="button" value="1"/>
        <input name="x" id="2" code="307" type="button" value="1"/>
    </inputConfig>
    <!-- PS5 Official Weifang Goertek Electronics Co.Ltd wireless -->
    <inputConfig deviceLayout="ps5" deviceName="Wireless Controller" deviceGUID="050000004c050000e60c000000810000" deviceNbButtons="13" type="joystick" deviceNbAxes="6" deviceNbHats="1">
        <input name="b" id="0" code="304" type="button" value="1"/>
        <input name="a" id="1" code="305" type="button" value="1"/>
        <input name="select" id="8" code="314" type="button" value="1"/>
        <input name="down" id="0" code="16" type="hat" value="4"/>
        <input name="left" id="0" code="16" type="hat" value="8"/>
        <input name="right" id="0" code="16" type="hat" value="2"/>
        <input name="up" id="0" code="16" type="hat" value="1"/>
        <input name="hotkey" id="10" code="316" type="button" value="1"/>
        <input name="l1" id="4" code="310" type="button" value="1"/>
        <input name="l3" id="11" code="317" type="button" value="1"/>
        <input name="l2" id="2" code="2" type="axis" value="-1"/>
        <input name="joystick1left" id="0" code="0" type="axis" value="-1"/>
        <input name="joystick1up" id="1" code="1" type="axis" value="-1"/>
        <input name="r1" id="5" code="311" type="button" value="1"/>
        <input name="r3" id="12" code="318" type="button" value="1"/>
        <input name="r2" id="5" code="5" type="axis" value="-1"/>
        <input name="joystick2left" id="3" code="3" type="axis" value="-1"/>
        <input name="joystick2up" id="4" code="4" type="axis" value="-1"/>
        <input name="start" id="9" code="315" type="button" value="1"/>
        <input name="y" id="3" code="308" type="button" value="1"/>
        <input name="x" id="2" code="307" type="button" value="1"/>
    </inputConfig>

Pour simuler un visuel d’une manette donnée

Pendant la mise au point d’un nouveau visuel, si vous voulez intégrer sans avoir le contrôleur en question, vous pouvez donc « bricoler » le deviceLayout d’un de vos contrôleurs.

Il faudra aller modifier sur votre version de pixL, le fichier « input.cfg » qui est ici dans votre share:

Attention: Sur un PC de dev où on va vouloir tester à partir de QT Creator, vu que l’on va chercher dans le « user » de pixL habituellement pour cette partie de code, il faudra se mettre aussi un répertoire « .pegasus-frontend » dans votre « /home/{user} » avec une copie de l’input.cfg et c’est celui ci qu’il faudra modifier.

Et modifier le deviceLayout d’une de vos manettes (il faudra le faire avant de la connecter bien sur ;-), comme ici, où on utilise le layout « ps4 » sur une manette de xbox series :

Et voilà ce que l’on arrive à simuler :

Alternative à font forge (depuis le 7/10/2024)

Vu que FontForge est vraiment un outil vieillissant j’ai finalement trouvé une alternative opensource pour windows, linux et macos pour au moins consulter (j’ai pas encore essayé d’éditer) : https://birdfont.org/purchase.php

C’est gratuit

Après installation il faudra sélectionner la licence « non commercial » et ouvrir le fichier « font » en question puis si on veut voir les icones actuelles il faudra sélectionner « All Glyphs » :

On pourra double cliquer sur une icone pour voir plus précisément:

Laisser un commentaire