IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

Recréer une GUI style Unity C++


Sujet :

C++

  1. #1
    Nouveau Candidat au Club
    Homme Profil pro
    Inscrit en
    Septembre 2013
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Septembre 2013
    Messages : 5
    Points : 1
    Points
    1
    Par défaut Recréer une GUI style Unity C++
    Salut tous !

    Je vous propose un petit défis de programmation, un problème qui ne nécessite pas de produire de code pour être résolu mais plutôt d'une idée de mécanisme...

    Contexte:
    Je cherchais à faire coder une outil simple et rapide d'utilisation pour réaliser des GUI en C++.

    Je me suis rappelé du mécanisme présent dans le moteur Unity3D. (Dans ce moteur, des scripts sont lu plusieurs fois par seconde pour rafraîchir le comportement du jeu dont la GUI.)

    Par exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     if (GUI.Button(new Rect(10, 70, 50, 30), "Click"))
                Debug.Log("Clicked the button with text");
    Ceci permet non seulement de créer un bouton, mais aussi d'y définir sa taille, position, son contenu (texte) et de savoir si on a cliqué dessus. Le tout en une ligne de code, ça c'est bien pratique !
    Pour faire cela, pas vraiment de mystère; le moteur Unity3D peut préparer l'image en fonction des paramètres et regarder l'actuelle position de la souris pour savoir si on clique dessus.


    Mais là où ça devient intéressant, c'est avec les fonctions de GUI "dynamique et flexible" qui vont automatiquement s'adapter au contenu d'une boite.

    Voyez plutôt:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    GUILayout.BeginHorizontal("box");
    if ( GUILayout.Button("I'm the first button") ) Debug.Log("Clicked");
    if ( GUILayout.Button("I'm to the right") ) Debug.Log("Clicked");
    GUILayout.EndHorizontal();
    Ce code déclare tout d'abord un nouveau champ horizontal puis y insère 2 boutons dont la taille devra automatiquement s'adapter suivant l'espace de la taille du champ actuel et de la taille des autres éléments (même ceux déclarés après !).

    La question est; comment le gestionnaire de GUI peut-il savoir si on a cliqué sur le bouton de la ligne 2 alors que celui-ci ne connaîtra sa taille réelle qu'en ligne 4, quand tout le contenu sera défini. Et par conséquent, comment peut il renvoyer sur la même instruction si oui ou non on a bien cliqué sur le bouton ?

    Ma piste;
    - Laisser passer une frame, et identifier les appels pour renvoyer la réponse à la prochaine frame. (mais comment les identifier sans instanciation !?)


    Une idée ?


    PS admin:
    ah je me suis peut être planté de sous forum, je viens de voir celui là;
    http://www.developpez.net/forums/f14...x-video/unity/
    Bien que le problème concerne le C++, les forumeur de unity comprendraient peut être mieux l'exemple fourni...

  2. #2
    Expert confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Points : 4 442
    Points
    4 442
    Par défaut
    Hello,

    Comme tu le dis, c'est un script qui est interprété. Les positions / dimensions de tous les widgets sont donc connus au chargement du script.

    (Suppositions, je connais pas Unity)
    1: chargement du script
    2: on en déduit les positions / dimensions des widgets
    3: on récupère le code à exécuter après un event (après un click par exemple)
    4: on crée la GUI et on bind les events à traiter (une machine virtuelle exécute le code du script, Debug.Log("Clicked"); par exemple
    5: en fonction de la position de la souris etc.. on lance les events correspondants

    Au final ça doit juste être la syntaxe de leurs scripts qui laisse croire qu'on peut tester si un bouton à été clické juste après sa création. (Enfin j'espère, car si c'est du code c++, niveau design ça vaut pas grand chose)

  3. #3
    Nouveau Candidat au Club
    Homme Profil pro
    Inscrit en
    Septembre 2013
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Septembre 2013
    Messages : 5
    Points : 1
    Points
    1
    Par défaut
    hey, merci pour ton idée !

    C'est vrai qu'on pourrais profiter de script pour simplifier les choses (de toutes façon, personnellement je voulais pas gérer la construction de la GUI dans des cpp mais plutôt dans des fichiers facilement éditable...)

    J'étais tout de même interloqué par ce mecanisme dans Unity3d; d'ailleurs je ne pense pas que ce dernier fonctionne comme ta méthode puisque on peut introduire, par exemple, des embranchements logiques.

    On pourrais donc avoir, dans le code, des comportements comme:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    GUIText( "Game over" );
    if ( life > 0 )
       if ( GUILayout.Button("Try again") ) Restart();
    if ( GUILayout.Button("Exit") ) Exit();
    life peut varier pendant l’exécution, proposant ou non l'option "Try again"

    Citation Envoyé par Iradrille Voir le message
    (Enfin j'espère, car si c'est du code c++, niveau design ça vaut pas grand chose)
    C'est à dire ? qu'est ce que tu entends par là ? de base, la construction d'une GUI ne devrait pas se trouvé dans du code C++ (pour des projets un peu important), ça je suis d'accord

    sinon pour infos les scripts Unity peuvent être en Javascript, Boo et surtout C# Mono.

  4. #4
    r0d
    r0d est déconnecté
    Expert éminent

    Homme Profil pro
    tech lead c++ linux
    Inscrit en
    Août 2004
    Messages
    4 262
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : tech lead c++ linux

    Informations forums :
    Inscription : Août 2004
    Messages : 4 262
    Points : 6 680
    Points
    6 680
    Billets dans le blog
    2
    Par défaut
    Ces histoires de définition dynamique d'IHM par script c'est une tendance lourde. J'avais un peu étudié WPF, mais c'est encore différent. Dans les WPF, le script (xaml) qui définit l'IHM est utilisé lors de la compilation.

    De toutes façons, il va te falloir un moteur assez puissant (en terme de complexité) pour pouvoir faire ce que tu veux; ce n'est pas simple.

    L'approche la plus simple consiste à enregistrer les coordonnées (rectangles englobants disons) de tes contrôles lors du parsing du script. Il faut ensuite passer par le contrôleur pour récupérer un événement "clic" avec les coordonnées du clic, et trouver dans ta liste de contrôle celui qui est concerné. C'est grosso-modo ce que propose Iradrille.

    Tu vas ensuite rencontrer de sérieux problèmes pour linker un bouton avec une action, le c++ n'est pas fait pur ce genre de chose. Ce n'est pas impossible (rien n'est impossible en c++), mais ça va vraiment pas être facile. Il va certainement falloir passer par une map de pointeur de fonction (par pointeur de fonction, je cause ici de tout ce qui peut être appelé: foncteur, std::function, etc.).
    « L'effort par lequel toute chose tend à persévérer dans son être n'est rien de plus que l'essence actuelle de cette chose. »
    Spinoza — Éthique III, Proposition VII

  5. #5
    Expert éminent sénior
    Avatar de Kannagi
    Homme Profil pro
    cyber-paléontologue
    Inscrit en
    Mai 2010
    Messages
    3 214
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : cyber-paléontologue

    Informations forums :
    Inscription : Mai 2010
    Messages : 3 214
    Points : 10 140
    Points
    10 140
    Par défaut
    J'imagine Yoher que tu n'es pas étudiant en info ou alors que tu n'as pas vue encore certaine matière , pour ma part a la fac j'avais étudié compilation et langage naturel , si c'est aussi ton cas relis tes cours

    Mais comme le dis Iradrille , c'est un langage interprété et rien n’empêche que il connais ce que fais la ligne 4 , vu que c'est très peu probable qu'il exécute le texte pas a pas directement , il doit probablement faire une analyse syntaxique avant , et donc

    Et par conséquent, comment peut il renvoyer sur la même instruction si oui ou non on a bien cliqué sur le bouton ?
    Parce que il a analysé le texte (et donc les instruction a faire ) avant de faire les instructions final (qu'il fera en C++).

    grosso modo quand t'as ça
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if ( GUILayout.Button("I'm the first button") ) Debug.Log("Clicked");
    il le fait pas directement le code en C++ , vu que il attend que tout ton script soit analysé avant.

  6. #6
    Nouveau Candidat au Club
    Homme Profil pro
    Inscrit en
    Septembre 2013
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Septembre 2013
    Messages : 5
    Points : 1
    Points
    1
    Par défaut
    Citation Envoyé par Kannagi Voir le message
    J'imagine Yoher que tu n'es pas étudiant en info ou alors que tu n'as pas vue encore certaine matière.
    (et nan, je suis encore lycéen :p)

    merci pour vos reponses !

    ben vous devez avoir raison, de toutes facon je vois pas comment ils pourraient faire autrement...

    mon autres pistes c'était qu'il pré-analyse le script aussi, mais juste pour identifié et marqué les instructions de GUI afin de donner retourner les bons resultats avec une frame de décalage (car la premiere frame servirait à structurer l'ensemble de la GUI).
    Ca éviterai notamment de devoir prendre en compte les instructions logique et leurs valeurs (qui changent) au moment de la pré-analyse (ce qui me semble très difficile).

    [pour ma part, je vais me contenter de la forme "if (GUI.Button(new Rect(10, 70, 50, 30), "Click"))". Au moins là il n'y aucune pré-analyse à faire, je pense que ce sera le plus rentable en terme de production/utilisation.]

  7. #7
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Bonjour,

    rien de défi ni vraiment difficile dans ce qui est fait.
    Le script n'est exécuté qu'une seule fois, il s'agit d'un script d'init, il crée un objet et y associe des callbacks sur évènement.
    La syntaxe proposée est une parmi plusieurs autres qu'ils ont choisi.
    Le langage de script est lui aussi à leur convenance. Pour ma part on utilise du Lua, sur un projet perso j'utilise du Python, Qt utilise une "surcharge" de javascript nommé Qml, ...

    Mais non, créer un objet et y associer des callbacks via scripting n'est rien d'extraordinaire en soit.

    Pour ma part j'accroche pas plus que ça à leur syntaxe, je préfère du code plus classique de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    button = CreateBUtton(size)
    button.OnClick(macallback)
    button.Hover(onhover)
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  8. #8
    Nouveau Candidat au Club
    Homme Profil pro
    Inscrit en
    Septembre 2013
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Septembre 2013
    Messages : 5
    Points : 1
    Points
    1
    Par défaut
    Le script n'est exécuté qu'une seule fois, il s'agit d'un script d'init, il crée un objet et y associe des callbacks sur évènement.
    Mmmh en l’occurrence ces scripts sont bien exécuté plusieurs par frames (autant que le Update des objets donc presque 60 fois par secondes) et heureusement puisque le code qu'il contient évolue. (il contient aussi de la "game logic")

    Là dessus, c'est sûr que j'aurais du m'adresser à des utilisateurs de Unity3D qui connaissent l'utilisation de ces scripts car il y a belle bien qu'elle que chose d'un peu "extraordinaire".

    Je te remercie tout de même pour ta réponse dont le mécanisme marcherait belle est bien pour un systeme de script d'init.

  9. #9
    Expert éminent sénior
    Avatar de Kannagi
    Homme Profil pro
    cyber-paléontologue
    Inscrit en
    Mai 2010
    Messages
    3 214
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : cyber-paléontologue

    Informations forums :
    Inscription : Mai 2010
    Messages : 3 214
    Points : 10 140
    Points
    10 140
    Par défaut
    Oui si c'est bel et bien quelque chose de static (html , xml) ou un script perso oui rien de spécial a faire , si c'est un langage (donc créer des variables , fonction , condition ect) , il faut justement créer son propre langage et donc passé par Analyse lexicale , Analyse syntaxique ect.
    il y a la page wiki pour t'aider http://fr.wikipedia.org/wiki/Analyse_lexicale.

    Mais je doute que le niveau lycéen est suffisant pour faire un interpréteur maison , sachant que c'est un gros morceau ce domaine.

    PS: pour les utilisateur Unity , oui ils verront de quoi tu parle exactement , apres te dire comment ça marche j'en doute , sachant que la création de langage soit on connait soit on connait pas =P
    Sur Unity il y a possibilité afficher un model 3D,animer , collision 3D pourtant sur unity tu peux faire tous cela sans avoir aucune idée de le faire en C++,ce n'est pas plus différents pour le script.

  10. #10
    Inactif  

    Homme Profil pro
    Ingénieur test de performance
    Inscrit en
    Décembre 2003
    Messages
    1 986
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur test de performance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 986
    Points : 2 605
    Points
    2 605
    Par défaut
    Bonjour.

    Citation Envoyé par Yoher Voir le message

    Je me suis rappelé du mécanisme présent dans le moteur Unity3D. (Dans ce moteur, des scripts sont lu plusieurs fois par seconde pour rafraîchir le comportement du jeu dont la GUI.)
    Comment sais-tu que les scripts concernant la GUI sont lus plusieurs fois par seconde, disons 30 (pour 30 fps).

    Je pense que les contrôles maintiennent leur position au sein de l'affichage. Si la position change, seule la variable contenant cette position est mise à jour.

    Ensuite lors d'un click, les contrôles sont questionnés pour savoir si leur position est à l'intérieur du click.

  11. #11
    Nouveau Candidat au Club
    Homme Profil pro
    Inscrit en
    Septembre 2013
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Septembre 2013
    Messages : 5
    Points : 1
    Points
    1
    Par défaut
    Citation Envoyé par moldavi Voir le message
    Comment sais-tu que les scripts concernant la GUI sont lus plusieurs fois par seconde, disons 30 (pour 30 fps).
    C'est parce que dans le même script, dans la même fonction, on peut afficher un Debug.Log qui s'affiche plusieurs fois par seconde -> on peut d'ailleurs y placer un compteur de FPS (ou même deplacer le joueurs en fonction des touches préssé).


    ou un script perso oui rien de spécial a faire , si c'est un langage (donc créer des variables , fonction , condition ect) , il faut justement créer son propre langage et donc passé par Analyse lexicale , Analyse syntaxique ect.
    C'est à dire que les scripts en question sont en C#, j'ose à peine imaginer le nombre de "spec" à prendre en compte pour analyser un tel language. Si d'après toi ce n'est rien de spécial, je suis étonné qu'il n'y est que le projet Mono pour lire du C# en script (avec JIT compiler).

    En tout cas c'est sûr que tout cela est loin de mon niveau, je suis juste un type curieux moi



    Note que, je crois que le projet C# Mono est open source, donc rien ne les empêcherais de modifier un peu l'analyser...
    Bien que je trouve vos solution un peu complexe.


    Finalement si je devais le faire moi, je m'y prendrais comme ceci:

    1) Au moment de chargé un script, je fais passer le script dans une fonction du moteur qui va remplacer les "GUILayout." par des "GUILayoutID(_FILE_,_LINE_)." à la manière d'une macro C++.
    2) Je passe ensuite le script à l’interpréteur C#/Mono qui va faire son job normal (puisqu'on aura justement prévu un foncteur de GUILayoutID qui prend 2 paramètres )

    3) Puis ensuite les cycles de jeu tournent
    frame 1:
    -> la GUI n'est pas construit, le bouton ne connais pas sa taille: cette frame la est tout simplement ignoré ! (1 seul avant des dizaines par seconde qui vont suivre....l'utilisateur n'aurait même pas le temps de cliquer de toutes façon !)
    frame 2:
    -> l'utilisateur clique et la GUI connait la forme qu'elle avait à la frame précedente; le même appel appel sur la même ligne se reconnait grâce au identifiant (_FILE_,_LINE_).

    Alors effectivement les événements de la GUI aurait un retard d'une frame et à raison de 60 frames par seconde sa fait un retard de 0.017 sec (pour simple GUI, on peut dire que c'est tout à fait passable ^^). L’intérêt est qu'on n'a ni analyseur syntaxique de C#, ni de wrap de block dans des callbacks, ni association evenement/action à faire. Juste une simple macro à placer.

  12. #12
    Expert confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Points : 4 442
    Points
    4 442
    Par défaut
    Citation Envoyé par Yoher Voir le message
    Alors effectivement les événements de la GUI aurait un retard d'une frame et à raison de 60 frames par seconde sa fait un retard de 0.017 sec (pour simple GUI, on peut dire que c'est tout à fait passable ^^). L’intérêt est qu'on n'a ni analyseur syntaxique de C#, ni de wrap de block dans des callbacks, ni association evenement/action à faire. Juste une simple macro à placer.
    Un retard de ~17ms dans un jeu c'est pas rien. Si c'est dans un menu, ça peut éventuellement être admissible, mais si le même système de GUI est utilisé en jeu (le 1er exemple qui me vient en tête c'est la barre de sorts dans un mmorpg), c'est tout simplement inadmissible (quand on sait que ça peut être évité).
    ~17ms auxquels on ajoute le lag.. ça peut très vite faire quelque chose d'injouable. (Bien que si quelqu'un clique sur les boutons et n'utilise pas de raccourcis clavier je dirai qu'il l'a bien cherché, mais c'est un autre sujet )

    Tu parles de GUI, mais il y à une énorme différence entre une GUI dans une appli 2D/3D (un jeu par exemple) et dans une appli "bureau".
    Généralement pour les applis 2D/3D (la GUI est donc dessinée avec openGL / directX), le fait qu'il faille la redessiner à chaque frame et que les boutons ne soient pas des "vrais" boutons, on en fait abstraction pour avoir quelques chose qui ressemble aux GUIs "bureau" :
    Un arbre de widgets, et des interactions via des events : avec un système permettant de s'abonner à un certain event (des callback)

    En fonction de ce que tu cherches réellement, la meilleure façon de comprendre comment ça marche (et pourquoi c'est fait comme ça) c'est de lire la doc.
    Donc Unity, CEGUI, etc.. si tu cherches à faire (ou à comprendre) les GUI dans les jeux,
    Qt et autres pour des applis "bureau".

    Mais schématiquement, ce qu'il doit se passer avec Unity doit ressembler à ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    GUI gui1("gui1"); // charger une GUI a partir d'un fichier script qui la définie
    GUI gui2("gui2"); // les events sont attachés au chargement
    GUI current = ...; // GUI actuellement affichée
    while(1) { // main loop
       KeyboardState ks = getKeyboardState(); // récup l'état du clavier
       MouseState ms = getMouseState(); // et de la souris
       processEvents(current, ks, ms); // lancer des events (onClick etc..) en fonction du clavier / souris -> les callback rattachés sont appelés
       current.show(); // afficher la GUI courante qui n'est peut être pas la même qu'avant, elle à peut être été modifiée en traitant un event
    }

Discussions similaires

  1. [Avis] Quel langage pour faire une GUI pour un pgm Fortran ?
    Par Radagast dans le forum Langages de programmation
    Réponses: 15
    Dernier message: 24/02/2011, 12h28
  2. Création d'une toolbar style "Google toolbar"
    Par zarbydigital dans le forum Général Conception Web
    Réponses: 3
    Dernier message: 18/09/2006, 13h47
  3. Création d'une GUI : gestion du drag & drop
    Par Eusebe dans le forum C++
    Réponses: 2
    Dernier message: 21/07/2006, 20h54
  4. Réponses: 2
    Dernier message: 28/11/2005, 13h20
  5. recréer une base mysql
    Par ryan dans le forum Administration
    Réponses: 2
    Dernier message: 27/06/2003, 23h04

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo