public SharedVariablePresetListDrawer(SerializedObject serializedObject, SerializedProperty presetVariables, ISharedVariableHandler variableHandler, Func <int, Type> elementTypeGetter)
        {
            float lineHeight      = EditorGUIUtility.singleLineHeight;
            float lineHeightSpace = lineHeight + EditorGUIUtility.standardVerticalSpacing;

            presetVariableList = new ReorderableList(serializedObject, presetVariables, true, true, true, true)
            {
                drawElementCallback = (rect, index, isFocused, isActive) =>
                {
                    serializedObject.UpdateIfRequiredOrScript();
                    EditorGUI.BeginChangeCheck();
                    SerializedProperty variable = presetVariables.GetArrayElementAtIndex(index);
                    Type type = elementTypeGetter(index);
                    SerializedProperty    name      = variable.FindPropertyRelative("_name");
                    List <SharedVariable> variables = variableHandler.GetVariables(type);
                    EditorGUI.PropertyField(new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight), variable,
                                            new GUIContent(string.IsNullOrEmpty(name.stringValue) ? $"({type.Name})" : name.stringValue));
                    Rect valueRect = new Rect(rect.x, rect.y + lineHeightSpace, rect.width - 46, lineHeight);
                    if (variable.isExpanded)
                    {
                        //这里的isShared用来标识变量名的填写方式,不作正常用途
                        SerializedProperty isShared = variable.FindPropertyRelative("isShared");
                        int typeIndex = isShared.boolValue ? 1 : 0;
                        typeIndex = EditorGUI.Popup(new Rect(rect.x + rect.width - 44, rect.y + lineHeightSpace, 44, lineHeight), typeIndex, varType);
                        switch (typeIndex)
                        {
                        case 0:
                            isShared.boolValue = false;
                            break;

                        case 1:
                            isShared.boolValue = true;
                            break;
                        }
                        if (typeIndex == 1)
                        {
                            string[] varNames  = variables.Select(x => x.name).ToArray();
                            bool     noNames   = varNames.Length < 1;
                            int      nameIndex = Array.IndexOf(varNames, name.stringValue);
                            if (noNames)
                            {
                                varNames = varNames.Prepend("未选择").ToArray();
                            }
                            if (nameIndex < 0)
                            {
                                nameIndex = 0;
                            }
                            nameIndex = EditorGUI.Popup(valueRect, "关联变量名称", nameIndex, varNames);
                            string nameStr = name.stringValue;
                            if (!noNames && nameIndex >= 0 && nameIndex < variables.Count)
                            {
                                nameStr = varNames[nameIndex];
                            }
                            name.stringValue = nameStr;
                        }
                        else
                        {
                            EditorGUI.PropertyField(valueRect, name, new GUIContent("关联变量名称"));
                        }
                        SerializedProperty value = variable.FindPropertyRelative("value");
                        EditorGUI.PropertyField(new Rect(rect.x, rect.y + lineHeightSpace * 2, rect.width, EditorGUI.GetPropertyHeight(value, true) - lineHeight), value, new GUIContent("预设值"), true);
                    }
                    if (EditorGUI.EndChangeCheck())
                    {
                        serializedObject.ApplyModifiedProperties();
                    }
                },
                elementHeightCallback = (index) =>
                {
                    if (index >= presetVariables.arraySize)
                    {
                        return(0);
                    }
                    SerializedProperty variable = presetVariables.GetArrayElementAtIndex(index);
                    if (variable.isExpanded)
                    {
                        return(EditorGUI.GetPropertyHeight(presetVariables.GetArrayElementAtIndex(index), true));
                    }
                    else
                    {
                        return(lineHeightSpace);
                    }
                },
                onAddDropdownCallback = (rect, list) =>
                {
                    GenericMenu menu = new GenericMenu();
                    foreach (var type in TypeCache.GetTypesDerivedFrom <SharedVariable>())
                    {
                        if (!type.IsGenericType)
                        {
                            menu.AddItem(new GUIContent($"自定义/{type.Name}"), false, () => { InsertNewVariable(type, false); });
                        }
                    }
                    if (ZetanUtility.Editor.TryGetValue(presetVariables, out var value))
                    {
                        List <SharedVariable> variables = value as List <SharedVariable>;
                        foreach (var variable in variableHandler.Variables)
                        {
                            Type type = variable.GetType();
                            if (!variables.Exists(x => x.name == variable.name && x.GetType() == type))
                            {
                                menu.AddItem(new GUIContent(variable.name), false, () => { InsertNewVariable(type, true, variable.name); });
                            }
                        }
                    }
                    menu.DropDown(rect);
                },
                onRemoveCallback = (list) =>
                {
                    serializedObject.UpdateIfRequiredOrScript();
                    SerializedProperty _name = presetVariables.GetArrayElementAtIndex(list.index).FindPropertyRelative("_name");
                    if (EditorUtility.DisplayDialog("删除变量", $"确定要删除预设 {_name.stringValue} 吗?", "确定", "取消"))
                    {
                        list.serializedProperty.DeleteArrayElementAtIndex(list.index);
                        GUIUtility.ExitGUI();
                    }
                    serializedObject.ApplyModifiedProperties();
                },
                onCanRemoveCallback = (list) =>
                {
                    return(list.IsSelected(list.index));
                },
                drawHeaderCallback = (rect) =>
                {
                    EditorGUI.LabelField(rect, $"变量预设列表");
                },
                serializedProperty = presetVariables
            };

            void InsertNewVariable(Type type, bool select, string name = "")
            {
                if (ZetanUtility.Editor.TryGetValue(presetVariables, out var value) && value is List <SharedVariable> list)
                {
                    SharedVariable variable = (SharedVariable)Activator.CreateInstance(type);
                    variable.GetType().GetField("_name", ZetanUtility.CommonBindingFlags).SetValue(variable, name);
                    variable.isShared = select;
                    list.Add(variable);
                    presetVariableList.Select(presetVariables.arraySize);
                }
                else
                {
                    Debug.LogError("添加失败,请检查变量列表归属");
                }
            }
        }
Example #2
0
        void DrawRightPanel()
        {
            EditorGUIUtility.labelWidth = k_RightPanelLabelWidth;
            EditorGUILayout.BeginVertical();
            m_RightScrollPosition = EditorGUILayout.BeginScrollView(m_RightScrollPosition, GUILayout.ExpandHeight(true), GUILayout.ExpandWidth(true));

            using (new EditorGUILayout.HorizontalScope())
            {
                var titleRect = EditorGUILayout.GetControlRect(true, k_TitleTextHeight);
                EditorGUI.LabelField(titleRect, "Probe Volume Settings", m_SubtitleStyle);
                var debugButtonRect = EditorGUILayout.GetControlRect(true, k_TitleTextHeight, GUILayout.Width(k_TitleTextHeight));
                if (GUI.Button(debugButtonRect, Styles.debugButton))
                {
                    OpenProbeVolumeDebugPanel();
                }
            }

            EditorGUILayout.Space();
            SanitizeScenes();
            m_ScenesInSet.DoLayoutList();

            EditorGUILayout.Space();
            m_Scenarios.Select(GetCurrentBakingSet().lightingScenarios.IndexOf(ProbeReferenceVolume.instance.lightingScenario));
            m_Scenarios.DoLayoutList();

            var set       = GetCurrentBakingSet();
            var sceneGUID = sceneData.GetFirstProbeVolumeSceneGUID(set);

            if (sceneGUID != null)
            {
                EditorGUILayout.Space();

                // Show only the profile from the first scene of the set (they all should be the same)
                if (set.profile == null)
                {
                    EditorUtility.DisplayDialog("Missing Probe Volume Profile Asset!", $"We couldn't find the asset profile associated with the Baking Set '{set.name}'.\nDo you want to create a new one?", "Yes");
                    set.profile = ScriptableObject.CreateInstance <ProbeReferenceVolumeProfile>();

                    // Delay asset creation, workaround to avoid creating assets while importing another one (SRP can be called from asset import).
                    EditorApplication.update += DelayCreateAsset;
                    void DelayCreateAsset()
                    {
                        EditorApplication.update -= DelayCreateAsset;
                        ProjectWindowUtil.CreateAsset(set.profile, set.name + ".asset");
                    }
                }

                if (m_ProbeVolumeProfileEditor == null)
                {
                    m_ProbeVolumeProfileEditor = Editor.CreateEditor(set.profile);
                }
                if (m_ProbeVolumeProfileEditor.target != set.profile)
                {
                    Editor.CreateCachedEditor(set.profile, m_ProbeVolumeProfileEditor.GetType(), ref m_ProbeVolumeProfileEditor);
                }

                var serializedSets            = m_ProbeSceneData.FindPropertyRelative("serializedBakingSets");
                var serializedSet             = serializedSets.GetArrayElementAtIndex(m_BakingSets.index);
                var probeVolumeBakingSettings = serializedSet.FindPropertyRelative("settings");

                EditorGUILayout.LabelField("Probe Placement", EditorStyles.boldLabel);
                EditorGUI.indentLevel++;
                m_ProbeVolumeProfileEditor.OnInspectorGUI();
                EditorGUILayout.Space(3, true);
                EditorGUILayout.PropertyField(probeVolumeBakingSettings);
                EditorGUI.indentLevel--;

                // Clamp to make sure minimum we set for dilation distance is min probe distance
                set.settings.dilationSettings.dilationDistance = Mathf.Max(set.profile.minDistanceBetweenProbes, set.settings.dilationSettings.dilationDistance);

                EditorGUILayout.Space();
                EditorGUILayout.Space();
                EditorGUILayout.LabelField(Styles.stats, EditorStyles.boldLabel);
                {
                    EditorGUI.indentLevel++;
                    if (AllSetScenesAreLoaded())
                    {
                        long sharedCost = 0, scenarioCost = 0;
                        foreach (var data in ProbeReferenceVolume.instance.perSceneDataList)
                        {
                            if (!set.sceneGUIDs.Contains(sceneData.GetSceneGUID(data.gameObject.scene)))
                            {
                                continue;
                            }
                            scenarioCost += data.GetDiskSizeOfScenarioData(ProbeReferenceVolume.instance.lightingScenario);

                            sharedCost += data.GetDiskSizeOfSharedData();
                            foreach (var scenario in set.lightingScenarios)
                            {
                                sharedCost += data.GetDiskSizeOfScenarioData(scenario);
                            }
                        }

                        EditorGUILayout.LabelField(Styles.scenarioCostStat, EditorGUIUtility.TrTextContent((scenarioCost / (float)(1000 * 1000)).ToString("F1") + " MB"));
                        EditorGUILayout.LabelField(Styles.totalCostStat, EditorGUIUtility.TrTextContent((sharedCost / (float)(1000 * 1000)).ToString("F1") + " MB"));
                    }
                    else
                    {
                        EditorGUILayout.HelpBox("Somes scenes of the set are not currently loaded. Stats can't be displayed", MessageType.Info);
                    }
                    EditorGUI.indentLevel--;
                }
            }
            else
            {
                EditorGUILayout.HelpBox("You need to assign at least one scene with probe volumes to configure the baking settings", MessageType.Error, true);
            }

            EditorGUILayout.EndScrollView();

            EditorGUILayout.Space();
            DrawBakeButton();

            EditorGUILayout.EndVertical();
        }
        public SharedVariableListDrawer(SerializedObject serializedObject, SerializedProperty serializedVariables, bool isShared)
        {
            variableList = new ReorderableList(serializedObject, serializedVariables, true, true, true, true)
            {
                drawElementCallback = (rect, index, isFocused, isActive) =>
                {
                    if (serializedObject.targetObject)
                    {
                        serializedObject.UpdateIfRequiredOrScript();
                        EditorGUI.BeginChangeCheck();
                        SerializedProperty variable = serializedVariables.GetArrayElementAtIndex(index);
                        EditorGUI.PropertyField(new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight), variable, true);
                        if (EditorGUI.EndChangeCheck())
                        {
                            serializedObject.ApplyModifiedProperties();
                        }
                        if (ZetanUtility.Editor.TryGetValue(variable, out var value) && value is SharedVariable sv &&
                            sv.GetType().GetField("linkedVariables", ZetanUtility.CommonBindingFlags).GetValue(sv) is HashSet <SharedVariable> lvs)
                        {
                            foreach (var lv in lvs)
                            {
                                lv.GetType().GetField("_name", ZetanUtility.CommonBindingFlags).SetValue(lv, sv.name);
                            }
                        }
                    }
                },
                elementHeightCallback = (index) =>
                {
                    if (index >= serializedVariables.arraySize)
                    {
                        return(0);
                    }
                    return(EditorGUI.GetPropertyHeight(serializedVariables.GetArrayElementAtIndex(index), true));
                },
                onAddDropdownCallback = (rect, list) =>
                {
                    GenericMenu menu = new GenericMenu();
                    menu.AddItem(new GUIContent("新建类型"), false, CreateVariableScript);
                    menu.AddSeparator("");
                    foreach (var type in TypeCache.GetTypesDerivedFrom <SharedVariable>())
                    {
                        if (!type.IsGenericType)
                        {
                            menu.AddItem(new GUIContent(type.Name), false, () => { InsertNewVariable(type); });
                        }
                    }
                    menu.DropDown(rect);
                },
                onRemoveCallback = (list) =>
                {
                    serializedObject.UpdateIfRequiredOrScript();
                    SerializedProperty _name = serializedVariables.GetArrayElementAtIndex(list.index).FindPropertyRelative("_name");
                    if (EditorUtility.DisplayDialog("删除变量", $"确定要删除变量 {_name.stringValue} 吗?", "确定", "取消"))
                    {
                        if (ZetanUtility.Editor.TryGetValue(serializedVariables.GetArrayElementAtIndex(list.index), out var value) && value is SharedVariable sv &&
                            sv.GetType().GetField("linkedVariables", ZetanUtility.CommonBindingFlags).GetValue(sv) is HashSet <SharedVariable> lvs)
                        {
                            foreach (var lv in lvs)
                            {
                                lv.GetType().GetField("_name", ZetanUtility.CommonBindingFlags).SetValue(lv, string.Empty);
                                lv.GetType().GetField("linkedVariable", ZetanUtility.CommonBindingFlags).SetValue(lv, null);
                            }
                        }
                        list.serializedProperty.DeleteArrayElementAtIndex(list.index);
                    }
                    serializedObject.ApplyModifiedProperties();
                },
                onCanRemoveCallback = (list) =>
                {
                    return(list.IsSelected(list.index));
                },
                drawHeaderCallback = (rect) =>
                {
                    string typeMsg = EditorUtility.IsPersistent(serializedObject.targetObject) ? "(不可引用场景对象)" : "(可引用场景对象)";
                    EditorGUI.LabelField(rect, $"{(isShared ? "共享变量列表" : "全局变量列表")}{typeMsg}");
                },
                serializedProperty = serializedVariables
            };

            void InsertNewVariable(Type type)
            {
                if (ZetanUtility.Editor.TryGetValue(serializedVariables, out var value) && value is List <SharedVariable> list)
                {
                    SharedVariable variable = (SharedVariable)Activator.CreateInstance(type);
                    string         newName  = $"{char.ToLower(type.Name[0])}{type.Name.Substring(1)}_{serializedVariables.arraySize}";
                    variable.GetType().GetField("_name", ZetanUtility.CommonBindingFlags).SetValue(variable, newName);
                    variable.isShared = isShared;
                    variable.isGlobal = !isShared;
                    list.Add(variable);
                    variableList.Select(serializedVariables.arraySize);
                }
                else
                {
                    Debug.LogError("添加失败,请检查变量列表归属");
                }
            }
        }
 private void OnEnable()
 {
     if (ZetanUtility.TryGetMemberValue("attributeTypes", target, out var value, out _))
     {
         dict = value as Dictionary <string, RoleAttributeValueType>;
     }
     names = serializedObject.FindProperty("names");
     types = serializedObject.FindProperty("types");
     list  = new ReorderableList(serializedObject, names, false, true, true, true)
     {
         drawElementCallback = (rect, index, isActive, isFocused) =>
         {
             SerializedProperty name = names.GetArrayElementAtIndex(index);
             SerializedProperty type = types.GetArrayElementAtIndex(index);
             EditorGUI.LabelField(new Rect(rect.x, rect.y, 30, EditorGUIUtility.singleLineHeight), $"[{index}]");
             string nameBef = name.stringValue;
             EditorGUI.PropertyField(new Rect(rect.x + 30, rect.y, (rect.width - 30) / 2 - 2, EditorGUIUtility.singleLineHeight), name, new GUIContent(string.Empty));
             if (nameBef != name.stringValue && dict.ContainsKey(name.stringValue))
             {
                 if (EditorUtility.DisplayDialog("错误", $"已存在属性名 [{name.stringValue}]", "确定"))
                 {
                     name.stringValue = nameBef;
                 }
             }
             EditorGUI.PropertyField(new Rect(rect.x + +30 + (rect.width - 30) / 2, rect.y, (rect.width - 30) / 2 - 2, EditorGUIUtility.singleLineHeight), type, new GUIContent(string.Empty));
         },
         onAddCallback = (list) =>
         {
             string name = "属性0";
             int    i    = 1;
             while (dict.ContainsKey(name))
             {
                 name = $"属性{i}";
                 i++;
             }
             names.arraySize++;
             names.GetArrayElementAtIndex(names.arraySize - 1).stringValue = name;
             types.arraySize++;
             types.GetArrayElementAtIndex(types.arraySize - 1).enumValueIndex = (int)RoleAttributeValueType.Integer;
             list.Select(names.arraySize - 1);
         },
         onRemoveCallback = (list) =>
         {
             if (list.index >= 0 && list.index < names.arraySize)
             {
                 if (EditorUtility.DisplayDialog("警告", $"确定删除属性 [{names.GetArrayElementAtIndex(list.index).stringValue}] 吗?", "删除", "取消"))
                 {
                     names.DeleteArrayElementAtIndex(list.index);
                     types.DeleteArrayElementAtIndex(list.index);
                 }
             }
         },
         onCanRemoveCallback = (list) =>
         {
             return(list.selectedIndices.Contains(list.index));
         },
         elementHeightCallback = (index) =>
         {
             return(EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing);
         },
         drawHeaderCallback = (rect) =>
         {
             EditorGUI.LabelField(rect, "基础属性类型列表");
         }
     };
 }