Toggle et GameObject dans l'Inspector

Questions à propos du scripting. Hors Shader, GUI, Audio et Mobile.
EmileF
Messages : 676
Inscription : 18 Mars 2017 19:39

Toggle et GameObject dans l'Inspector

Message par EmileF » 03 Mars 2020 13:32

Bonjour,

Oui, je m'explique:

Dans l'inspector, je voudrais afficher une liste d'objets avec une case à cocher pour chacun sur la même ligne, pour éclaicir et rendre plus compact cette liste d'objets.

Actuellement il me faut 3 lignes pour afficher un objet, j'ai dans certains cas une trentaine, voire plus d'objets, ce qui me fait des liste interminables et pas pratique à gérer.

Les tutos ou exemples que j'ai réussi à trouver sur le net utilisent la case à cocher pour afficher ou cacher une partie de l'inspector.

Si quelqu'un pouvait m'aider, ce serait super.
La différence entre l'intelligence et la stupidité est que l'intelligence est limitée.

EmileF
Messages : 676
Inscription : 18 Mars 2017 19:39

Re: Toggle et GameObject dans l'Inspector

Message par EmileF » 03 Mars 2020 16:10

Après maints essais, voilà ce que j'ai obtenu:

Image

J'arrive grâce à ces scripts à mettre sur une même ligne l'objet et la case à cocher.

Code : Tout sélectionner

public class ToggleAttribute : PropertyAttribute
{
}

public class Block : MonoBehaviour
{

    [Toggle()]
    public GameObject Objet;

    [Toggle()]
    public GameObject[] Objets;
}

Code : Tout sélectionner


[CustomPropertyDrawer(typeof(ToggleAttribute))]
public class ToggleDrawer : PropertyDrawer
{
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        GameObject objet = (GameObject)property.objectReferenceValue;
        bool actif = false;
        if (objet)
        {
            actif = objet.activeSelf;
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.PropertyField(property, GUIContent.none);
            actif = EditorGUILayout.Toggle(actif);
            EditorGUILayout.EndHorizontal();
            objet.SetActive(actif);
        }
    }
}
Mais comme on peut le voir,
la ligne contenant l'objet avec sa case à cocher, ne remplit pas l'espace

Quand j'ai une liste d'objets, j'ai plusieurs lignes vides qui s'insèrent.

Est-ce que quelqu'un peut m'aider à corriger cela ?
La différence entre l'intelligence et la stupidité est que l'intelligence est limitée.

EmileF
Messages : 676
Inscription : 18 Mars 2017 19:39

Re: Toggle et GameObject dans l'Inspector

Message par EmileF » 05 Mars 2020 10:48

Voilà, j'ai avancé un peu,
mais il me reste un soucis que je n'arrive pas à régler.

J'utilise, en fin de compte, EditorWindow, pour gérer mes objets.

Dans mon EditorWindow, si je sélectionne un objet avec le tag "Block", il s'exécute.

D'abord, il charge les objets enfants de l'objet sélectionné
Ensuite, il les affiche en ajoutant l'option de les activer ou de les désactiver.

Pour ce faire j'ai un ToggleLeft suivi du nom de l'objet pour l'activation.
Ce toggle me permet s'il est actif d'afficher ses enfants.
Tout va bien jusque là.

Sur la même ligne de chaque objet j'ai un 2ème Toggle qui est sensé me permettre de ne pas afficher ma liste pour gagner de la place.
Pas moyen de faire fonctionner ce 2ème Toggle.
J'ai essayé de le faire fonctionner tout seul, pas moyen non plus.

Il doit y avoir un petit truc qui coince, mais je n'arrive pas à trouver quoi.

Si quelqu'un avait la gentillesse de regarder mon script, ce serait super.

Code : Tout sélectionner

public class BlockWindow : EditorWindow
{
    public class ObjetData
    {
        internal GameObject Objet;
        internal List<ObjetData> Objets;
        internal bool expand = true;

        //initialise l'ObjetData
        public ObjetData(GameObject objet)
        {
            Objet = objet;
            //Récupère les objets enfants
            Objets = new List<ObjetData>();
            foreach (Transform item in Objet.transform)
            {
                Objets.Add(new ObjetData(item.gameObject));
            }
        }
    }


    [MenuItem("Perso/Block")]
    public static void ShowWindow()
    {
        GetWindow<BlockWindow>("Block");
    }

    GameObject Select;

    private void OnGUI()
    {
        GUILayout.Label("Block Window", EditorStyles.boldLabel);
        Repaint();

        Select = Selection.activeGameObject;
        if (Select == null || Select.tag != "Block")
        {
            EditorGUILayout.TextField("Selection", "");
        }
        else
        {
            EditorGUILayout.TextField("Selection", Select.name);
            foreach (Transform item in Select.transform)
            {
                ObjetData objet = new ObjetData(item.gameObject);
                ShowObjetData(objet);
            }
        }
    }

    private void ShowObjetData(ObjetData objet)
    {
        string name = objet.Objet.name;

        GUILayout.BeginHorizontal();
        //Toggle pour activer ou désactiver l'objet
        objet.Objet.SetActive(EditorGUILayout.ToggleLeft(new GUIContent(name), objet.Objet.activeSelf));
        //pour dérouler ou enrouler la liste de cet objet
        //l'objet.expand reste en permanence à true ou à false selon comme je le mets dans le script
        objet.expand = EditorGUILayout.ToggleLeft(GUIContent.none, objet.expand);
        GUILayout.EndHorizontal();

        //Si objet actif
        if (objet.Objet.activeSelf && objet.expand)
        {
            EditorGUI.indentLevel += 1;
            foreach (ObjetData item in objet.Objets)
            {
                ShowObjetData(item);
            }
            EditorGUI.indentLevel -= 1;
        }
    }
}

La différence entre l'intelligence et la stupidité est que l'intelligence est limitée.

EmileF
Messages : 676
Inscription : 18 Mars 2017 19:39

Re: Toggle et GameObject dans l'Inspector

Message par EmileF » 05 Mars 2020 12:59

J'ai enfin trouvé après une semaine de recherche

Mon 2ème toggle ne fonctionnait pas parce qu'il était réinitialisé en permanence.

J'ai initialisé les listes des objets dans la fonction OnSelectionChange() afin qu'ils ne soient initialisés qu'une fois, à la sélection.

J'ai pu donc adapter l'affichage au nombre d'objet.

voici mon script si ça intéresse quelqu'un:

Code : Tout sélectionner

public class BlockWindow : EditorWindow
{
    public class ObjetData
    {
        internal GameObject Objet;
        internal List<ObjetData> Objets;
        internal bool expand;

        //initialise l'ObjetData
        public ObjetData(GameObject objet)
        {
            Objet = objet;
            expand = false;
            //Récupère les objets enfants
            Objets = new List<ObjetData>();
            foreach (Transform item in Objet.transform)
            {
                Objets.Add(new ObjetData(item.gameObject));
                expand = true;
            }
        }
    }


    [MenuItem("Perso/Block")]
    public static void ShowWindow()
    {
        GetWindow<BlockWindow>("Block");
    }

    List<ObjetData> Objets;
    GameObject Select;
    private void OnSelectionChange()
    {

        Select = Selection.activeGameObject;
        Objets = new List<ObjetData>();
        if (Select != null && Select.tag == "Block")
        {
            foreach (Transform item in Select.transform)
            {
                ObjetData objet = new ObjetData(item.gameObject);
                Objets.Add(objet);
            }
        }
    }

    private void OnGUI()
    {
        GUILayout.Label("Block Window", EditorStyles.boldLabel);
        Repaint();
        if (Select == null || Select.tag != "Block")
        {
            EditorGUILayout.TextField("Selection", "");
        }
        else if (Objets != null && Objets.Count > 0)
        {

            EditorGUILayout.TextField("Selection", Select.name);
            foreach (ObjetData item in Objets)
            {
                ShowObjetData(item);
            }
        }
    }

    private void ShowObjetData(ObjetData objet)
    {
        string name = objet.Objet.name;

        GUILayout.BeginHorizontal();
        //Toggle pour activer ou désactiver l'objet
        bool actif = objet.Objet.activeSelf;
        objet.Objet.SetActive(EditorGUILayout.ToggleLeft(new GUIContent(name), objet.Objet.activeSelf));
        
        //Si l'activation de l'objet change, adapte l'affichage de la liste
        if (actif != objet.Objet.activeSelf)
            objet.expand = objet.Objet.activeSelf;
        actif = objet.Objet.activeSelf;
        
        //pour dérouler ou enrouler la liste de cet objet
        //s'il y a des objets enfants
        if (objet.Objets.Count > 0)
            objet.expand = EditorGUILayout.ToggleLeft(GUIContent.none, objet.expand);

        //si l'objet est désactive ou pas de liste enfant, pas d'affichage
        if (!actif || objet.Objets.Count == 0)
            objet.expand = false;

        GUILayout.EndHorizontal();

        //Si l'expansion est activée
        if (objet.expand)
        {
            EditorGUI.indentLevel += 1;
            foreach (ObjetData item in objet.Objets)
            {
                ShowObjetData(item);
            }
            EditorGUI.indentLevel -= 1;
        }
    }
}

La différence entre l'intelligence et la stupidité est que l'intelligence est limitée.

Avatar de l’utilisateur
boubouk50
ModoGenereux
ModoGenereux
Messages : 6220
Inscription : 28 Avr 2014 11:57
Localisation : Saint-Didier-en-Bresse (71)

Re: Toggle et GameObject dans l'Inspector

Message par boubouk50 » 05 Mars 2020 13:55

Un grand merci à toi mon pauvre Emile qui se répond souvent tout seul mais qui nous fait partager ses découvertes/solutions.

Désolé, je ne peux pas toujours aider, je suis plutôt utile côté algorithme et utilisation d'Unity. Je n'y connais strictement rien en EditorWindow.
"Ce n'est pas en améliorant la bougie, que l'on a inventé l'ampoule, c'est en marchant longtemps."
Nétiquette du forum
Savoir faire une recherche
Apprendre la programmation

EmileF
Messages : 676
Inscription : 18 Mars 2017 19:39

Re: Toggle et GameObject dans l'Inspector

Message par EmileF » 05 Mars 2020 17:07

Pas de soucis et merci

A la prochaine
La différence entre l'intelligence et la stupidité est que l'intelligence est limitée.

Répondre

Revenir vers « Scripting »