-1

enter image description hereI want to access each key as gameobject. I loop first over the dictionary but what next? should I add another inner loop over the keys?

or maybe to loop like this:

for(int i = 0; i < dictio.Keys.Count; i++)

and then how to get each key?

instead looping over the selected objects I want to loop over the dictionary and get each key and value and display each key and value and on the left near each key a number for example:

1 mygameobject(key) myscript(value)

here is a screenshot of the keys on the left and the values this is what I want to display in the editor window and to add on the left a number for each object:

example

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;

public class RenameSelected : EditorWindow
{
    private static readonly Vector2Int size = new Vector2Int(500, 500);
    private string childrenPrefix;
    private int startIndex;
    private bool showPosition = false;
    private bool includeChildren = false;
    private GameObject[] objects;
    private Vector2 scrollPos;
    static Dictionary<GameObject, string> dictio = new Dictionary<GameObject, string>();

    [MenuItem("GameObject/Rename Selected")]
    public static void Init()
    {
        EditorWindow window = GetWindow<RenameSelected>();
        window.minSize = size;
        window.maxSize = size;

        MonoBehaviour[] scripts = UnityEngine.Object.FindObjectsOfType<MonoBehaviour>();
        foreach (MonoBehaviour script in scripts)
        {
            Type scriptType = script.GetType();
            var scope = scriptType.Namespace;
            if (scope == null || !scope.StartsWith("Unity"))
            {
                if (!dictio.Keys.Contains(script.gameObject))
                {
                    dictio.Add(script.gameObject, scriptType.Name);
                }
            }
        }
    }

    private void OnSelectionChange()
    {
        objects = Selection.gameObjects;
    }

    private void OnEnable()
    {
        objects = Selection.gameObjects;
    }

    public void OnGUI()
    {
        GUILayout.Space(10);
        childrenPrefix = EditorGUILayout.TextField("Rename prefix", childrenPrefix);
        startIndex = EditorGUILayout.IntField("Start index", startIndex);
        includeChildren = EditorGUILayout.Toggle("Include Children", includeChildren);
        // When checkbox true include children then to loop
        // and add children if there is any of the selected object and make if needed
        // folded nested tree of the children of the object.
        // to add also checkbox to each selected gameobject so you can select individual
        // if to include children for only specific objects and which not !!!!!

        if (objects.Length == 0)
        {
            showPosition = false;
        }
        GUILayout.Space(20);
        EditorGUI.BeginChangeCheck();
        EditorGUILayout.GetControlRect(true, 16f, EditorStyles.foldout);
        Rect foldRect = GUILayoutUtility.GetLastRect();
        if (Event.current.type == EventType.MouseUp && foldRect.Contains(Event.current.mousePosition))
        {
            showPosition = !showPosition;
            GUI.changed = true;
            Event.current.Use();
        }

        showPosition = EditorGUI.Foldout(foldRect, showPosition, "Objects");
        GUILayout.Space(2);

        if (showPosition)
        {
            EditorGUI.indentLevel++;

            scrollPos =
            EditorGUILayout.BeginScrollView(scrollPos);
            for(int i = 0; i < dictio.Keys.Count; i++)
            //for (int i = 0; i < objects.Length; i++) // To loop and add children if there are
                // so each selected gameobject will have nested foldout for children like a 
                // tree. to think how to do it first.
                // the global bool variable includeChildren is for the renaming.
                // if true to rename also children if false only parents(the selected objects 
                // without the children).
            {
                EditorGUIUtility.labelWidth = 50;

                EditorGUILayout.BeginHorizontal();
                {
                    GUILayoutOption[] options = { GUILayout.MaxWidth(300.0f), GUILayout.MinWidth(300.0f) };
                    //objects[i] = (GameObject)EditorGUILayout.ObjectField(i.ToString(), objects[i], typeof(GameObject), true, options);
                    dictio.Keys
                    EditorGUIUtility.labelWidth = 112;
                }
                EditorGUILayout.EndHorizontal();
            }
            EditorGUILayout.EndScrollView();

            EditorGUI.indentLevel--;
        }

        GUILayout.FlexibleSpace();
        if (GUILayout.Button("Rename Objects"))
        {
            
        }

        Repaint();
    }
}

result:

counter

  • 1
    What is `GameObject` and why are you using it as a dictionary key type? (`GameObject` sounds like a mutable `class` type, but dictionary keys should either be immutable, non-nullable class types or `struct` value types. – Dai May 05 '23 at 01:19
  • 2
    `foreach( GameObject go in dictio.Keys ) { String value = dictio[go]; Console.WriteLine( "{0} -> {1}", go, value ); }` – Dai May 05 '23 at 01:21
  • 1
    You had the answer in your question all along: *"access EACH key"*. If you want to do something FOR EACH item in a list then a `foreach` loop should be your first choice. Only use a `for` loop if you can't use a `foreach` loop for some reason, e.g. you need to access corresponding items from two lists. – jmcilhinney May 05 '23 at 01:35
  • @jmcilhinney if I'm looping like this foreach (KeyValuePair pair in dictio) then access each key like pair.Key how do I replace then this line including numbering each line in the window? objects[i] = (GameObject)EditorGUILayout.ObjectField(i.ToString(), objects[i], typeof(GameObject), true, options); – Sheron Blumental May 05 '23 at 01:38
  • 1
    `int i = 0;` then `i++;` at the end of the loop (**do not** use the `ElementAt` answer in the duplicate) – Ry- May 05 '23 at 01:56
  • @Ry- because I'm using foreach how do i replace the 'i' variable at this line? before I used for(int...... but I was looping over selection objects array now I'm looping over dictionary so I'm using foreach var go = pair.Key; go = (GameObject)EditorGUILayout.ObjectField(i.ToString(), go, typeof(GameObject), true, options); the part: i.ToString() – Sheron Blumental May 05 '23 at 02:05
  • @SheronBlumental: That’s exactly what I was describing. Declare `int i = 0;` before the `foreach` loop and do `i++;` at the end of the `foreach` loop. See also [How do you get the index of the current iteration of a foreach loop?](https://stackoverflow.com/questions/43021/how-do-you-get-the-index-of-the-current-iteration-of-a-foreach-loop) – Ry- May 05 '23 at 02:12
  • @Ry- this is what I did before. I declared int variable I called it counter then used it in the foreach loop on this line to number it: go = (GameObject)EditorGUILayout.ObjectField(counter.ToString(),go, typeof(GameObject), true, options); then after the loop or at the bottom of the loop I did counter++; the problem is that OnGUI is called each frame so the numbers get increasing nonstop. and all the objects have the same number each time. it's not 1,2,3,4,5,6,7 but all the objects are 1 then next iterate all the objects are number with 2 then 3 4 5 – Sheron Blumental May 05 '23 at 02:41
  • @Ry- I edited my question and added at the bottom a screenshot of the window when numbering the lines. you can see all the lines have the same number 816 and it keep increasing the numbers nonstop. – Sheron Blumental May 05 '23 at 02:43
  • The items in a `Dictionary` are not guaranteed to be in any particular order and you should not rely on them being so. Trying to use an index into a `Dictionary` and some other list of corresponding items is inherently wrong. The point of a `Dictionary` is accessing values based on keys. If you have other values that also relate to those keys then you should have another `Dictionary` or the values in your original `Dictionary` should be a different type that incorporates the other data too. – jmcilhinney May 05 '23 at 02:55
  • 1
    @SheronBlumental: The counter should be declared immediately before the loop and incremented *inside* the loop. – Ry- May 05 '23 at 03:32
  • @SheronBlumental [SerializableDictionary](https://assetstore.unity.com/packages/tools/integration/serializabledictionary-90477) already exists ... why re-implement it? – derHugo May 05 '23 at 08:16
  • @derHugo didn't know about that package. I edited my qyestion with a screenshot at the top as i success to get what I wanted and that's why I used dictionary. – Sheron Blumental May 05 '23 at 13:28
  • @Ry- i added a screenshot to my question at the top showing what I wanted to do and that now it's working. but if not using dictionary then how can I get that result in editor window in another way ? – Sheron Blumental May 05 '23 at 13:29
  • @SheronBlumental indices have no meaning for a Dictionary though .. so I don't understand why you think they are relevant or even reliable .. the order of `FindObjectsOfType` is based on internal instance IDs - it doesn't tell you much though – derHugo May 05 '23 at 13:38

1 Answers1

1
foreach (var pair in dictio )
{
    pair.key
}
CorrieJanse
  • 2,374
  • 1
  • 6
  • 23