繁体   English   中英

如何自动使编辑器窗口内容在窗口大小中?

[英]How can I make automatic the editor window content to be in the window size?

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

public class ConversationsEditorWindow : EditorWindow
{
    public SerializedObject conversation = null;

    private ConversationTrigger _conversationTrigger;

    [SerializeField] private ReorderableList conversationsList;

    private SerializedProperty _conversations;

    private int _currentlySelectedConversationIndex = -1;
    private int newSize = 0;
    private Vector2 scrollPos;

    private readonly Dictionary<string, ReorderableList> _dialoguesListDict = new Dictionary<string, ReorderableList>();
    private readonly Dictionary<string, ReorderableList> _sentencesListDict = new Dictionary<string, ReorderableList>();

    private SerializedObject itemcopy;

    public void Init(SerializedObject _item)
    {
        // Copy the Item targetObject to not lose reference when you
        // click another element on the project window.
        itemcopy = new SerializedObject(_item.targetObject);
        conversation = itemcopy;

        // Other things to initialize the window

        const int width = 1500;
        const int height = 900;

        var x = (Screen.currentResolution.width - width) / 2;
        var y = (Screen.currentResolution.height - height) / 2;

        var window = GetWindow<ConversationsEditorWindow>();
        window.position = new Rect(x, y, width, height);

        _conversationTrigger = (ConversationTrigger)_item.targetObject;
        _conversations = itemcopy.FindProperty("conversations");

        conversationsList = new ReorderableList(itemcopy, _conversations)
        {
            displayAdd = true,
            displayRemove = true,
            draggable = true,

            drawHeaderCallback = DrawConversationsHeader,

            drawElementCallback = DrawConversationsElement,

            onAddCallback = (list) =>
            {
                SerializedProperty addedElement;
                // if something is selected add after that element otherwise on the end
                if (_currentlySelectedConversationIndex >= 0)
                {
                    list.serializedProperty.InsertArrayElementAtIndex(_currentlySelectedConversationIndex + 1);
                    addedElement = list.serializedProperty.GetArrayElementAtIndex(_currentlySelectedConversationIndex + 1);
                }
                else
                {
                    list.serializedProperty.arraySize++;
                    addedElement = list.serializedProperty.GetArrayElementAtIndex(list.serializedProperty.arraySize - 1);
                }

                var name = addedElement.FindPropertyRelative("Name");
                var foldout = addedElement.FindPropertyRelative("Foldout");
                var dialogues = addedElement.FindPropertyRelative("Dialogues");

                name.stringValue = "";
                foldout.boolValue = false;
                dialogues.arraySize = 0;
            },

            elementHeightCallback = (index) =>
            {
                return GetConversationHeight(_conversations.GetArrayElementAtIndex(index));
            }
        };
    }

    private void OnGUI()
    {
        itemcopy.Update();

        // if there are no elements reset _currentlySelectedConversationIndex
        if (conversationsList.serializedProperty.arraySize - 1 < _currentlySelectedConversationIndex) _currentlySelectedConversationIndex = -1;

        EditorGUILayout.LabelField("Conversations", EditorStyles.boldLabel);
        EditorGUI.BeginChangeCheck();
        {
            newSize = EditorGUILayout.IntField(_conversations.arraySize);
        }
        if (EditorGUI.EndChangeCheck())
        {
            if (newSize > _conversations.arraySize)
            {
                // elements have to be added -> how many?
                var toAdd = newSize - _conversations.arraySize - 1;
                // why -1 ? -> We add the first element and set its values to default
                // now if we simply increase the arraySize for the rest of the elements
                // they will be all a copy of the first -> all defaults ;)

                // first add one element
                _conversations.arraySize++;
                // then get that element
                var newIndex = _conversations.arraySize - 1;
                var newElement = _conversations.GetArrayElementAtIndex(newIndex);

                // now reset all properties like
                var name = newElement.FindPropertyRelative("Name");
                name.stringValue = "";

                // now for the rest simply increase arraySize
                _conversations.arraySize += toAdd;
            }
            else
            {
                // for removing just make sure the arraySize is not under 0
                _conversations.arraySize = Mathf.Max(newSize, 0);
            }

            EditorGUI.FocusTextInControl(null);
        }

        scrollPos = EditorGUILayout.BeginScrollView(scrollPos, GUILayout.Height(250));

        GUILayout.Space(10);
        conversationsList.DoLayoutList();

        EditorGUILayout.EndScrollView();

        if (GUILayout.Button("Save Conversations"))
        {
            _conversationTrigger.SaveConversations();
        }

        if (GUILayout.Button("Load Conversations"))
        {
            Undo.RecordObject(_conversationTrigger, "Loaded conversations from JSON");
            _conversationTrigger.LoadConversations();
        }

        itemcopy.ApplyModifiedProperties();
    }

    private void DrawConversationsHeader(Rect rect)
    {
        //EditorGUI.LabelField(rect, "Conversations");
    }

    private void DrawDialoguesHeader(Rect rect)
    {
        EditorGUI.LabelField(rect, "Dialogues");
    }

    private void DrawSentencesHeader(Rect rect)
    {
        EditorGUI.LabelField(rect, "Sentences");
    }


    private void DrawConversationsElement(Rect rect, int index, bool isActive, bool isFocused)
    {
        if (isActive) _currentlySelectedConversationIndex = index;

        var conversation = _conversations.GetArrayElementAtIndex(index);

        var position = new Rect(rect);

        var name = conversation.FindPropertyRelative("Name");
        var foldout = conversation.FindPropertyRelative("Foldout");
        var dialogues = conversation.FindPropertyRelative("Dialogues");
        var conversationindex = conversation.FindPropertyRelative("ConversationIndex");
        string dialoguesListKey = conversation.propertyPath;

        EditorGUI.indentLevel++;
        {
            // make the label be a foldout
            foldout.boolValue = EditorGUI.Foldout(new Rect(position.x, position.y, 10, EditorGUIUtility.singleLineHeight), foldout.boolValue, "Conversation Name " + (index + 1).ToString(), true);
            name.stringValue = EditorGUI.TextField(new Rect(position.x + 145, position.y, 244, EditorGUIUtility.singleLineHeight), name.stringValue);

            if (foldout.boolValue)
            {
                // draw the name field
                //name.stringValue = EditorGUI.TextField(new Rect(position.x, position.y, position.width, EditorGUIUtility.singleLineHeight), name.stringValue);
                position.y += EditorGUIUtility.singleLineHeight;

                if (!_dialoguesListDict.ContainsKey(dialoguesListKey))
                {
                    // create reorderabl list and store it in dict
                    var dialoguesList = new ReorderableList(conversation.serializedObject, dialogues)
                    {
                        displayAdd = true,
                        displayRemove = true,
                        draggable = true,

                        drawHeaderCallback = DrawDialoguesHeader,

                        drawElementCallback = (convRect, convIndex, convActive, convFocused) => { DrawDialoguesElement(_dialoguesListDict[dialoguesListKey], convRect, convIndex, convActive, convFocused); },

                        elementHeightCallback = (dialogIndex) =>
                        {
                            return GetDialogueHeight(_dialoguesListDict[dialoguesListKey].serializedProperty.GetArrayElementAtIndex(dialogIndex));
                        },

                        onAddCallback = (list) =>
                        {
                            list.serializedProperty.arraySize++;
                            var addedElement = list.serializedProperty.GetArrayElementAtIndex(list.serializedProperty.arraySize - 1);

                            var newDialoguesName = addedElement.FindPropertyRelative("Name");
                            var newDialoguesFoldout = addedElement.FindPropertyRelative("Foldout");
                            var sentences = addedElement.FindPropertyRelative("Sentences");

                            newDialoguesName.stringValue = "";
                            newDialoguesFoldout.boolValue = true;
                            sentences.arraySize = 0;
                        }
                    };
                    _dialoguesListDict[dialoguesListKey] = dialoguesList;
                }

                _dialoguesListDict[dialoguesListKey].DoList(new Rect(position.x, position.y, position.width, position.height - EditorGUIUtility.singleLineHeight));
            }

        }
        EditorGUI.indentLevel--;
    }

    private void DrawDialoguesElement(ReorderableList list, Rect rect, int index, bool isActive, bool isFocused)
    {
        if (list == null) return;

        var dialog = list.serializedProperty.GetArrayElementAtIndex(index);

        var position = new Rect(rect);

        var foldout = dialog.FindPropertyRelative("Foldout");
        var name = dialog.FindPropertyRelative("Name");

        {
            // make the label be a foldout
            foldout.boolValue = EditorGUI.Foldout(new Rect(position.x, position.y, 10, EditorGUIUtility.singleLineHeight), foldout.boolValue, "Character Name ", true);
            name.stringValue = EditorGUI.TextField(new Rect(position.x + 120, position.y, 244, EditorGUIUtility.singleLineHeight), name.stringValue);

            var sentencesListKey = dialog.propertyPath;
            var sentences = dialog.FindPropertyRelative("Sentences");

            if (foldout.boolValue)
            {
                position.y += EditorGUIUtility.singleLineHeight;

                if (!_sentencesListDict.ContainsKey(sentencesListKey))
                {
                    // create reorderabl list and store it in dict
                    var sentencesList = new ReorderableList(sentences.serializedObject, sentences)
                    {
                        displayAdd = true,
                        displayRemove = true,
                        draggable = true,

                        // header for the dialog list
                        drawHeaderCallback = DrawSentencesHeader,

                        // how a sentence is displayed
                        drawElementCallback = (sentenceRect, sentenceIndex, sentenceIsActive, sentenceIsFocused) =>
                        {
                            var sentence = sentences.GetArrayElementAtIndex(sentenceIndex);

                            // draw simple textArea for sentence
                            sentence.stringValue = EditorGUI.TextArea(sentenceRect, sentence.stringValue);
                        },

                        // Sentences have simply a fixed height of 2 lines
                        elementHeight = EditorGUIUtility.singleLineHeight * 2,

                        // when a sentence is added
                        onAddCallback = (sentList) =>
                        {
                            sentList.serializedProperty.arraySize++;
                            var addedElement = sentList.serializedProperty.GetArrayElementAtIndex(sentList.serializedProperty.arraySize - 1);

                            addedElement.stringValue = "";
                        }
                    };

                    // store the created ReorderableList
                    _sentencesListDict[sentencesListKey] = sentencesList;
                }

                // Draw the list
                _sentencesListDict[sentencesListKey].DoList(new Rect(position.x, position.y, position.width, position.height - EditorGUIUtility.singleLineHeight));
            }
        }
    }


    /// <summary>
    /// Returns the height of given Conversation property
    /// </summary>
    /// <param name="conversation"></param>
    /// <returns>height of given Conversation property</returns>
    private float GetConversationHeight(SerializedProperty conversation)
    {
        var foldout = conversation.FindPropertyRelative("Foldout");

        // if not foldout the height is simply 1 line
        var height = EditorGUIUtility.singleLineHeight;

        // otherwise we sum up every controls and child heights
        if (foldout.boolValue)
        {
            // we need some more lines:
            //  for the Name field,
            // the list header,
            // the list buttons and a bit buffer
            height += EditorGUIUtility.singleLineHeight * 5;


            var dialogues = conversation.FindPropertyRelative("Dialogues");

            for (var d = 0; d < dialogues.arraySize; d++)
            {
                var dialog = dialogues.GetArrayElementAtIndex(d);
                height += GetDialogueHeight(dialog);
            }
        }

        return height;
    }

    /// <summary>
    /// Returns the height of given Dialogue property
    /// </summary>
    /// <param name="dialog"></param>
    /// <returns>height of given Dialogue property</returns>
    private float GetDialogueHeight(SerializedProperty dialog)
    {
        var foldout = dialog.FindPropertyRelative("Foldout");

        // same game for the dialog if not foldout it is only a single line
        var height = EditorGUIUtility.singleLineHeight;

        // otherwise sum up controls and child heights
        if (foldout.boolValue)
        {
            // we need some more lines:
            //  for the Name field,
            // the list header,
            // the list buttons and a bit buffer
            height += EditorGUIUtility.singleLineHeight * 4;

            var sentences = dialog.FindPropertyRelative("Sentences");

            // the sentences are easier since they always have the same height
            // in this example 2 lines so simply do
            // at least have space for 1 sentences even if there is none
            height += EditorGUIUtility.singleLineHeight * Mathf.Max(1, sentences.arraySize) * 2;
        }

        return height;
    }

视窗大小为1500x900

这是我通过带有按钮的编辑器脚本打开编辑器窗口的方式:

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

[CustomEditor(typeof(ConversationTrigger))]
public class ConversationTriggerEditor : Editor
{
        if (GUILayout.Button("Configure Item"))
        {
            ConversationsEditorWindow myWindow = CreateInstance<ConversationsEditorWindow>();

            myWindow.minSize = new Vector2(1500, 900);
            myWindow.maxSize = new Vector2(1500, 900);
            myWindow.Init(serializedObject);

        }
}

结果是:

编辑器窗口

保存和加载这两个按钮应该在窗口的底部,整个内容应该散布在所有窗口上,甚至按按钮,文本和所有内容的大小,甚至所有内容都应该更大。

但是主要的问题是窗口的一半以上是空的。 我希望它的尺寸​​为1500x900

你明确地说

scrollPos = EditorGUILayout.BeginScrollView(scrollPos, GUILayout.Height(250));

并将固定高度设置为250

您应该使用GUILayout.ExpandHeight

scrollPos = EditorGUILayout.BeginScrollView(scrollPos, GUILayout.ExpandHeight(true));

通常,为了将按钮移至底部,还可以使用GUILayout.FlexibleSpace(); 就像填充元素一样,将其后的所有内容推到窗口/矩形的末端。

多个FlexibleSpaces在rect上均匀分布,因此您也可以使用其中两个,以便始终将某个元素放置在rect的中心。


出于可用性的原因,我实际上将避免为EditorWindow强制使用固定大小...如果用户的显示较小,该怎么办? 即使所有显示器的尺寸相同,有时也无法调整窗口大小确实很烦人。

通过在GUILayout.Button()方法的options参数中传递ExpandHeight布局选项,可以使rect占用所有已用空间。

float sizeY = this.position.size.y;
GUILayout.Button("One", GUILayout.ExpandHeight(true));
GUILayout.Button("Two", GUILayout.ExpandHeight(true));

覆盖整个屏幕的按钮。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM