Пример #1
0
        /// <summary>
        /// When the window is first shown, create and organize all the top-level UI elements.
        /// </summary>
        private void InitializeUI()
        {
            var root = rootVisualElement;

            messageField = new Label();

            headerContainer = new Box();
            headerContainer.AddToClassList(headersClassName);
            headerContainer.AddToClassList("top-headers");
            headerContainer.AddToClassList(rowClassName);

            valueScrollView = new ScrollView();
            valueScrollView.AddToClassList("value-container");

            buttonContainer = new Box();
            buttonContainer.AddToClassList("button-container");
            buttonContainer.AddToClassList(rowClassName);

            // In Windows & Mac editor, providing a callback on Button creation works a expected.
            uploadButton = new Button(() => SyncDataManager.UpdateRemoteConfigAsync(
                                          RemoteConfigData.CreateUploadData()))
            {
                text = "Upload to Remote Config"
            };

            downloadButton = new Button(() => SyncDataManager.GetRemoteConfigDataAsync())
            {
                text = "Sync from Remote Config"
            };

            resetChangesButton = new Button(ResetLocalChanges)
            {
                text = "Reset All"
            };

            // Register callbacks on MouseDownEvent for Linux editor.
#if UNITY_EDITOR && !UNITY_EDITOR_WIN && !UNITY_EDITOR_OSX
            downloadButton.RegisterCallback <MouseDownEvent>(
                evt => SyncDataManager.GetRemoteConfigDataAsync());
            uploadButton.RegisterCallback <MouseDownEvent>(evt => SyncDataManager
                                                           .UpdateRemoteConfigAsync(RemoteConfigData.CreateUploadData()));
            resetChangesButton.RegisterCallback <MouseDownEvent>(evt => ResetLocalChanges());
#endif

            // Until first Remote Config data sync, only show Sync From button.
            buttonContainer.Add(downloadButton);

            root.Add(headerContainer);
            root.Add(valueScrollView);
            root.Add(buttonContainer);
            // Add target style to root element.
            root.styleSheets.Add(AssetDatabase.LoadAssetAtPath <StyleSheet>(stylePath));
        }
Пример #2
0
        /// <summary>
        /// Used for the top-level SyncTargetContainer which contains all discovered SyncTargets.
        /// Creates a header box with "Sync Targets" and uses this element as the top level UI
        /// element for all created children.
        /// </summary>
        /// <returns>This VisualElement, to contain all created UI child elements.</returns>
        private VisualElement CreateTopLevelGroupElement()
        {
            var box = new Box();

            box.AddToClassList("headers");
            box.AddToClassList("row");
            var header = new Label("Sync Targets");

            box.Add(header);
            this.Add(box);
            return(this);
        }
Пример #3
0
        private TextField AddTextField(string text, VisualElement container, EventCallback <ChangeEvent <string> > e,
                                       int lines = 1)
        {
            var row = new Box();

            row.AddToClassList("properties-item");

            var label = new Label(text);

            var field = new TextField();

            if (lines > 1)
            {
                field.multiline = true;
                field.AddToClassList("multiline");
            }

            field.RegisterCallback(e);

            row.Add(label);
            row.Add(field);

            container.Add(row);

            return(field);
        }
Пример #4
0
        void PopulatePackageList(string search = null)
        {
            ListView packageListView = rootVisualElement.Q <ListView>("listView");

            packageListView.Clear();

            for (int i = 0; i < packageList.Count; i++)
            {
                int elementID = i;

                if (search != null)
                {
                    if (!packageList[i].name.ToLower().StartsWith(search))
                    {
                        continue;
                    }
                }

                Box listContainer = new Box();
                listContainer.name         = "listItem";
                listContainer.style.height = 30;
                listContainer.AddManipulator(new Clickable(() =>
                {
                    SelectPackage(elementID);
                    PopulatePackageList();
                    UpdateRightPanel();
                }));

                Label listLabel = new Label(packageList[i].name);
                listLabel.style.unityTextAlign = TextAnchor.LowerLeft;
                listLabel.style.marginLeft     = 3;
                listLabel.style.height         = 23;

                Box separator = new Box();
                separator.style.width     = new StyleLength(StyleKeyword.Auto);
                separator.style.height    = 2;
                separator.style.bottom    = 0;
                separator.style.marginTop = new StyleLength(StyleKeyword.Auto);
                separator.AddToClassList("separator");

                listContainer.Add(listLabel);
                listContainer.Add(separator);

                packageListView.Insert(packageListView.childCount, listContainer);

                if (elementID == selectedPackage)
                {
                    listContainer.style.backgroundColor = new StyleColor(new Color32(48, 48, 48, 255));
                }
            }
        }
        public override VisualElement CreateInspectorGUI()
        {
            var root = new VisualElement {
                name = "HierarchyHeaderRoot"
            };

            scrollView = new ScrollView();

#if UNITY_2020_2_OR_NEWER
            var boxContainer = new Box();
            boxContainer.AddToClassList("mainBoxContainer");
            boxContainer.Add(scrollView);
#endif
            serializedObject.Update();
            var property = serializedObject.GetIterator();
            if (property.NextVisible(true))
            {
                do
                {
                    var propPath      = property.propertyPath;
                    var propertyField = new PropertyField(property)
                    {
                        name = "PropertyField:" + propPath
                    };
                    switch (propPath)
                    {
                    case "m_Script" when serializedObject.targetObject != null:
                        propertyField.visible = true;
                        propertyField.SetEnabled(true);
                        break;

                    default:
                        if (property.IsReallyArray() && serializedObject.targetObject != null)
                        {
                            var copiedProperty = property.Copy();     // @formatter:off
#if UNITY_2020_2_OR_NEWER
                            var imDefaultProperty = new IMGUIContainer(() =>
                            {
                                DoDrawDefaultIMGUIProperty(serializedObject, copiedProperty);
                            })
                            {
                                name = propPath
                            };
#else
                            reorderableList = new ReorderableList(serializedObject, copiedProperty)
                            {
                                drawHeaderCallback    = DrawHeaderCallback,
                                drawElementCallback   = DrawElementCallback,
                                elementHeightCallback = ElementHeightCallback,
                                onAddCallback         = OnAddCallback
                            };     // @formatter:on

                            reorderableList.elementHeightCallback = ElementHeightCallback;

                            var imDefaultProperty = new IMGUIContainer(() =>
                            {
                                serializedObject.Update();
                                reorderableList.DoLayoutList();
                                serializedObject.ApplyModifiedProperties();
                            })
                            {
                                name = propPath
                            };
#endif
                            imDefaultProperty.RegisterCallback <ChangeEvent <bool> >(evt => RecomputeSize(imDefaultProperty));
                            scrollView.Add(imDefaultProperty);
                        }

                        break;     // @formatter:on
                    }
                } while (property.NextVisible(false));
            }

            foreach (var foldoutList in scrollView.Query <Foldout>().ToList())
            {
                foldoutList.RegisterValueChangedCallback(e =>
                {
                    if (!(e.target is Foldout fd))
                    {
                        return;
                    }
                    var path      = fd.bindingPath;
                    var container = scrollView.Q <IMGUIContainer>(path);
                    RecomputeSize(container);
                });
            }

            serializedObject.ApplyModifiedProperties();

#if UNITY_2020_2_OR_NEWER
            root.Add(boxContainer);
#else
            root.Add(scrollView);
#endif
            return(root);
        }
        public override VisualElement CreateInspectorGUI()
        {
            if (Selection.activeObject is null || Selection.objects.Length == 0)
            {
                return(base.CreateInspectorGUI());
            }
            if (!GetType().IsSubclassOf(typeof(ScriptableObject)) || categoryList is null || categoryList.Count == 0)
            {
                return(base.CreateInspectorGUI());
            }
            if (!idConfig.AAIConfiguration().enableCustomEditors)
            {
                return(base.CreateInspectorGUI());
            }

            var baseStyleSheet = idConfig.GetStyleSheet("AAIDefaultEditorBase");

            if (defaultStyleSheet is null)
            {
                defaultStyleSheet = idConfig.GetStyleSheet("AAIDefaultEditorStyle");
            }
            if (defaultStyleSheet is null)
            {
                Debug.Log("Could not locate AAIDefaultEditorStyle");
            }

            serializedObject.Update();

            defaultRoot = new VisualElement();

            defaultRoot.styleSheets.Add(baseStyleSheet);
            defaultRoot.styleSheets.Add(defaultStyleSheet);
            defaultRoot.AddToClassList("rootContainer");

            var boxContainer = new Box();

            boxContainer.AddToClassList("mainBoxContainer");

            if (beforeDefaultElements == null)
            {
                beforeDefaultElements = new VisualElement();
            }
            beforeDefaultElements.name = "beforeDefaultElements";
            beforeDefaultElements.AddToClassList("beforeDefaultElements");
            defaultRoot.Add(beforeDefaultElements);

            categoryList.ForEach(x =>
            {
                if (x is null)
                {
                    return;
                }
                x.AddToClassList("categoryFoldout");
                boxContainer.Add(x);
            });

            m_ScrollView = new ScrollView();
            boxContainer.Add(m_ScrollView);

            keyData = classDataDictionary.Keys.ToList();

            #region Property Iteration

            var property = serializedObject.GetIterator();
            if (property.NextVisible(true))
            {
                do
                {
                    // -- Shortening name for ease of typing -------------
                    var propPath = property.propertyPath;

                    // -- Skip over excluded fields ----------------------
                    if (excludedFields.Contains(propPath) && serializedObject.targetObject != null)
                    {
                        continue;
                    }

                    // -- Property row VisualElement ---------------------
                    var propertyRow    = new VisualElement();
                    var propertyColumn = new VisualElement();
                    propertyRow.AddToClassList("propertyRow");
                    propertyColumn.AddToClassList("propertyColumn");

                    // -- Property fallback field ------------------------
                    var propertyField = new PropertyField(property)
                    {
                        name = "PropertyField:" + propPath
                    };

                    // -- Determine if current property is field data ----
                    if (!classDataDictionary[Enumerable.First(keyData)].fieldDatas.Keys.Contains(propPath))
                    {
                        switch (propPath)
                        {
                        case "m_Script" when serializedObject.targetObject != null:
                            propertyField.visible = false;     // @formatter:off
                            propertyField.SetEnabled(false);
                            break;

                        default:
                            if (property.IsReallyArray() && serializedObject.targetObject != null)
                            {
                                var copiedProperty    = property.Copy();
                                var imDefaultProperty = new IMGUIContainer(() =>
                                {
                                    DoDrawDefaultIMGUIProperty(serializedObject, copiedProperty);
                                })
                                {
                                    name = propPath
                                };
                                m_ScrollView.Add(imDefaultProperty);
                            }
                            break;     // @formatter:on
                        }
                    }
                    else
                    {
                        var propertyData = classDataDictionary[Enumerable.First(keyData)].fieldDatas[propPath];
                        switch (propertyData.fieldInfo)
                        {
                        // -- String/TextField Elements --------------
                        case FieldInfo a when a.FieldType == typeof(string):
                        case FieldInfo b when b.FieldType == typeof(PropertyName):
                            if (defaultEditorDebug)
                            {
                                Debug.Log($"String: {propPath}");
                            }

                            var propertyTextLabel = new Label(property.displayName);
                            propertyTextLabel.name = $"{propPath}Label";
                            var propertyTextField = new TextField
                            {
                                bindingPath = propPath,
                                name        = $"{propPath}Text"
                            };

                            if (propertyData.categoryAttr.toolTip != "")
                            {
                                propertyTextLabel.tooltip = propertyData.categoryAttr.toolTip;
                                propertyTextField.tooltip = propertyData.categoryAttr.toolTip;
                            }

                            propertyTextLabel.AddToClassList("propertyTextLabel");
                            propertyTextField.AddToClassList("propertyTextField");
                            propertyRow.Add(propertyTextLabel);
                            propertyRow.Add(propertyTextField);
                            boxContainer.Q(propertyData.categoryAttr.category).Add(propertyRow);
                            break;

                        // -- Integer Elements -----------------------
                        case FieldInfo a when a.FieldType == typeof(int):
                            if (defaultEditorDebug)
                            {
                                Debug.Log($"Integer: {propPath}");
                            }
                            var propertyIntegerLabel = new Label(property.displayName);
                            propertyIntegerLabel.name = $"{propPath}Label";
                            var propertyIntegerField = new IntegerField
                            {
                                bindingPath = propPath,
                                name        = $"{propPath}Integer"
                            };

                            if (propertyData.categoryAttr.toolTip != "")
                            {
                                propertyIntegerLabel.tooltip = propertyData.categoryAttr.toolTip;
                                propertyIntegerField.tooltip = propertyData.categoryAttr.toolTip;
                            }

                            propertyIntegerLabel.AddToClassList("propertyIntegerLabel");
                            propertyIntegerField.AddToClassList("propertyIntegerField");
                            propertyRow.Add(propertyIntegerLabel);
                            propertyRow.Add(propertyIntegerField);
                            boxContainer.Q(propertyData.categoryAttr.category).Add(propertyRow);
                            break;

                        // -- Float Elements -------------------------
                        case FieldInfo a when a.FieldType == typeof(float):
                            if (defaultEditorDebug)
                            {
                                Debug.Log($"Float: {propPath}");
                            }

                            var propertyFloatLabel = new Label(property.displayName);
                            propertyFloatLabel.name = $"{propPath}Label";
                            var propertyFloatField = new FloatField
                            {
                                bindingPath = propPath,
                                name        = $"{propPath}Float"
                            };

                            if (propertyData.categoryAttr.toolTip != "")
                            {
                                propertyFloatLabel.tooltip = propertyData.categoryAttr.toolTip;
                                propertyFloatField.tooltip = propertyData.categoryAttr.toolTip;
                            }

                            propertyFloatLabel.AddToClassList("propertyFloatLabel");
                            propertyFloatField.AddToClassList("propertyFloatField");
                            propertyRow.Add(propertyFloatLabel);
                            propertyRow.Add(propertyFloatField);
                            boxContainer.Q(propertyData.categoryAttr.category).Add(propertyRow);
                            break;

                        // -- Bool/Toggle Elements -------------------
                        case FieldInfo a when a.FieldType == typeof(bool):
                        case FieldInfo b when b.FieldType == typeof(Toggle):
                            if (defaultEditorDebug)
                            {
                                Debug.Log($"Toggle: {propPath}");
                            }

                            var propertyToggleLabel = new Label(property.displayName);
                            propertyToggleLabel.name = $"{propPath}ToggleLabel";
                            var propertyToggleSpacer = new VisualElement();
                            var propertyToggleField  = new Toggle
                            {
                                bindingPath = propPath,
                                name        = $"{propPath}ToggleField"
                            };

                            if (propertyData.categoryAttr.toolTip != "")
                            {
                                propertyToggleLabel.tooltip = propertyData.categoryAttr.toolTip;
                                propertyToggleField.tooltip = propertyData.categoryAttr.toolTip;
                            }


                            propertyToggleLabel.AddToClassList("propertyToggleLabel");
                            propertyToggleLabel.AddToClassList("propertyToggleSpacer");
                            propertyToggleField.AddToClassList("propertyToggleField");
                            propertyRow.Add(propertyToggleLabel);
                            propertyRow.Add(propertyToggleField);
                            propertyRow.Add(propertyToggleSpacer);
                            propertyRow.RemoveFromClassList("propertyRow");
                            propertyRow.AddToClassList("propertyToggleRow");
                            boxContainer.Q(propertyData.categoryAttr.category).Add(propertyRow);
                            break;

                        // -- Dictionary Elements --------------------
                        case FieldInfo a when typeof(IDictionary).IsAssignableFrom(a.FieldType):
                        case FieldInfo b when typeof(IDictionary).IsSubclassOf(b.FieldType):
                            var dictionaryFoldout = new Foldout {
                                text = property.displayName
                            };
                            dictionaryFoldout.AddToClassList("arrayFoldout");
                            dictionaryFoldout.value = false;

                            if (propertyData.categoryAttr.toolTip != "")
                            {
                                dictionaryFoldout.tooltip = propertyData.categoryAttr.toolTip;
                                propertyColumn.tooltip    = propertyData.categoryAttr.toolTip;
                            }

                            dictionaryFoldout.Add(propertyField);
                            propertyColumn.Add(dictionaryFoldout);
                            boxContainer.Q(propertyData.categoryAttr.category).Add(propertyColumn);
                            break;

                        // -- List/Set Elements ----------------------
                        case FieldInfo a when typeof(IList).IsAssignableFrom(a.FieldType):
                        case FieldInfo b when typeof(IList).IsSubclassOf(b.FieldType):
                        case FieldInfo c when typeof(ISet <>).IsAssignableFrom(c.FieldType):
                        case FieldInfo d when typeof(ISet <>).IsSubclassOf(d.FieldType):
                            var arrayElementBuilder = new ArrayElementBuilder(property, propertyData);

                            if (propertyData.categoryAttr.toolTip != "")
                            {
                                propertyRow.tooltip = propertyData.categoryAttr.toolTip;
                            }

                            propertyRow.Add(arrayElementBuilder);
                            boxContainer.Q(propertyData.categoryAttr.category).Add(propertyRow);
                            break;

                        // -- Object Elements ----------------------
                        case FieldInfo a when a.FieldType == typeof(Object):
                        case FieldInfo b when typeof(Object).IsSubclassOf(b.FieldType):
                        case FieldInfo c when typeof(Object).IsAssignableFrom(c.FieldType):
                            var propertyObjectLabel = new Label(property.displayName);
                            propertyObjectLabel.name = $"{propPath}ObjectLabel";
                            var propertyObjectField = new ObjectField
                            {
                                objectType  = propertyData.fieldType,
                                bindingPath = propPath,
                                name        = $"{propPath}ObjectField"
                            };

                            if (propertyData.categoryAttr.toolTip != "")
                            {
                                propertyObjectLabel.tooltip = propertyData.categoryAttr.toolTip;
                                propertyObjectField.tooltip = propertyData.categoryAttr.toolTip;
                            }

                            propertyObjectLabel.AddToClassList("propertyObjectLabel");
                            propertyObjectField.AddToClassList("propertyObjectField");
                            propertyRow.Add(propertyObjectLabel);
                            propertyRow.Add(propertyObjectField);
                            boxContainer.Q(propertyData.categoryAttr.category).Add(propertyRow);
                            if (defaultEditorDebug)
                            {
                                Debug.Log($"Fallback Test: Name: {propPath} Type: {property.type} Array: {property.isArray} : {property.propertyType}");
                            }
                            break;

                        default:
                            if (property.IsReallyArray())
                            {
                                propertyColumn.Add(propertyField);
                                boxContainer.Q(propertyData.categoryAttr.category).Add(propertyColumn);
                            }

                            // else propertyColumn.Add(propertyField);
                            //
                            if (propertyData.categoryAttr.toolTip != "")
                            {
                                propertyColumn.tooltip = propertyData.categoryAttr.toolTip;
                            }

                            //
                            // boxContainer.Q(propertyData.categoryAttr.category).Add(propertyColumn);
                            break;
                        }
                    }
                } while (property.NextVisible(false));
            }

            #endregion

            foreach (var foldoutList in m_ScrollView.Query <Foldout>().ToList())
            {
                foldoutList.RegisterValueChangedCallback(e =>
                {
                    // TODO Remove this:
                    if (!(e.target is Foldout fd))
                    {
                        return;
                    }
                    Debug.Log($" {fd.name}");
                    var path      = fd.bindingPath;
                    var container = m_ScrollView.Q <IMGUIContainer>(path);
                    RecomputeSize(container);
                });
            }

            foreach (var foldoutList in m_ScrollView.Query <AnimatedFoldout>().ToList())
            {
                foldoutList.RegisterValueChangedCallback(e =>
                {
                    // TODO Remove this:
                    if (!(e.target is Foldout fd))
                    {
                        return;
                    }
                    Debug.Log($" {fd.name}");
                    var path      = fd.bindingPath;
                    var container = m_ScrollView.Q <IMGUIContainer>(path);
                    RecomputeSize(container);
                });
            }

            VisualElement defaultCategory = null;
            for (var i = 0; i < categoryList.Count; i++)
            {
                VisualElement x;
                if (isAnimated)
                {
                    x = categoryList[i].Q <AnimatedFoldout>();
                }
                else
                {
                    x = categoryList[i].Q <Foldout>();
                }
                if (x.name != "Default")
                {
                    continue;
                }
                defaultCategory = x;
                break;
            }

            if (defaultCategory.childCount == 0)
            {
                defaultCategory.style.display = DisplayStyle.None;
            }

            if (isAnimated)
            {
                var listItems = boxContainer.Query <AnimatedFoldout>().ToList();
                listItems.ForEach(x => foldout.Add((AnimatedFoldout)x));
            }
            else
            {
                var listItems = boxContainer.Query <Foldout>().ToList();
                listItems.ForEach(x => foldout.Add((Foldout)x));
            }

            foldout.ForEach(x =>
            {
                Toggle toggleItem;
                if (isAnimated)
                {
                    var item        = (AnimatedFoldout)x;
                    var contentItem = item.Q(null, AnimatedFoldout.expanderUssClassName);
                    contentItem.ToggleInClassList("categoryFoldoutClosed");
                    item.Q(null, "unity-toggle__checkmark").AddToClassList("toggleCheckmark");
                    item.RegisterCallback((ChangeEvent <bool> evt) =>
                    {
                        var targetElement = evt.target as VisualElement;

                        if (targetElement == item)
                        {
                            item.value = evt.newValue;
                        }

                        if (targetElement.parent == item || targetElement == item || targetElement.contentContainer == item)
                        {
                            item.value = evt.newValue;
                            // if (evt.newValue) item.contentContainer.style.display = DisplayStyle.Flex;

                            // if (!evt.newValue) // @formatter:off
                            // {
                            //     item.schedule.Execute(() =>
                            //     {
                            //         item.contentContainer.style.display = DisplayStyle.None;
                            //     }).StartingIn(500);
                            //     item.schedule.Execute(() =>
                            //     {
                            //         contentItem.style.display = DisplayStyle.None;
                            //     }).StartingIn(600); // @formatter:on
                            // }
                        }
                        else
                        {
                            item.expander.TriggerExpanderResize(true);
                        }
                    }); // @formatter:on
                }
                else
                {
                    var item   = (Foldout)x;
                    toggleItem = item.Q <Toggle>();
                    toggleItem.ToggleInClassList("categoryFoldoutClosed");
                    item.Q(null, "unity-toggle__checkmark").AddToClassList("toggleCheckmark");
                }
            });

            serializedObject.ApplyModifiedProperties();

            if (afterDefaultElements == null)
            {
                afterDefaultElements = new VisualElement();
            }
            afterDefaultElements.name = "afterDefaultElements";
            afterDefaultElements.AddToClassList("afterDefaultElements");

            boxContainer.Add(afterDefaultElements);
            defaultRoot.Add(boxContainer);

            defaultRoot.RegisterCallback <GeometryChangedEvent>(ExecutePostBuildTask);
            defaultRoot.schedule.Execute(ExecuteLocalDeferredTask).StartingIn(0);

            return(defaultRoot);
        }
Пример #7
0
    private void Init()
    {
        var uiAsset = AssetDatabase.LoadAssetAtPath <VisualTreeAsset>("Assets/Scripts/USS attempt/Editor/MyWindow.uxml");

        Layout = uiAsset.CloneTree();

        var myStyle = AssetDatabase.LoadAssetAtPath <StyleSheet>("Assets/Scripts/USS attempt/Editor/MyStylesheet.uss");

        var myBox = new Box {
            name = "myBox"
        };

        myBox.AddToClassList("My_Fancy_box");

        input = new TextField("New Name");

        myBox.Add(input);

        var row = new VisualElement {
            name = "row"
        };

        row.Add(new Label("Position"));

        var x = new FloatField("x");
        var y = new FloatField("y");
        var z = new FloatField("z");

        x.RegisterCallback <ChangeEvent <float> >(l => pos.x = x.value);
        y.RegisterCallback <ChangeEvent <float> >(l => pos.y = y.value);
        z.RegisterCallback <ChangeEvent <float> >(l => pos.z = z.value);

        row.Add(x);
        row.Add(y);
        row.Add(z);

        myBox.Add(row);

        myBox.Q <TextField>().RegisterCallback <ChangeEvent <string> >(l => newName = (l.target as TextField).value);

        doTheThing = new Button();

        doTheThing.AddToClassList("Fancy__button");

        doTheThing.text = "Do the thing...";

        ///Button Click methods????\\\

        //doTheThing.clickable = new Clickable(delegate () { DoTheThing(); });


        //doTheThing.clickable = new Clickable(l => DoTheThing());


        //doTheThing.clickable = new Clickable(delegate () { DoTheThing(); }, 1, 1);


        //doTheThing.clickable.clicked += DoTheThing;


        //////Finally something worked
        doTheThing.clickable.clickedWithEventInfo += GoDoThatThing();


        ///Button Click methods????\\\

        myBox.Add(doTheThing);

        Layout.Add(myBox);

        rootVisualElement.styleSheets.Add(myStyle);

        rootVisualElement.Add(Layout);
    }
Пример #8
0
        /// <summary>
        /// Once RemoteConfigData and SyncTargets are retrieved, render them in the ScrollView.
        /// First show unmapped parameters in a list, ending in a TextField+Button to add a new
        /// unmapped parameter.
        /// Then show all the discovered SyncTargets in hierarchy view, and highlight which ones
        /// are not synced with RemoteConfig.
        /// </summary>
        public void RenderParameters()
        {
            InitHeaders();
            var offset = valueScrollView.scrollOffset;

            valueScrollView.Clear();
            topLevelElement = new TemplateContainer();
            valueScrollView.Add(topLevelElement);

            // Render unmapped targets, if any.
            var unmappedParamsSection = new TemplateContainer();

            // Create Unmapped Parameters header section.
            var unmappedParamsHeader = new Box();

            unmappedParamsHeader.AddToClassList(headersClassName);
            var unmappedLabel = new Label("Unmapped Parameters");

            unmappedParamsHeader.Add(unmappedLabel);
            unmappedParamsSection.Add(unmappedParamsHeader);
            foreach (var param in unmappedParams.OrderBy(p => p.Key))
            {
                var unmappedTarget = new UnmappedSyncElement(param);
                unmappedParamsSection.Add(unmappedTarget);
            }

            // Add a section with TextField and Button to create a new unmapped Parameter.
            var newKeyContainer = new TemplateContainer();

            newKeyContainer.AddToClassList(columnClassName);
            newKeyContainer.AddToClassList(rowClassName);
            var newUnmappedParamText = "New Unmapped Param";
            var newKeyField          = new TextField {
                value = newUnmappedParamText
            };

            newKeyContainer.Add(newKeyField);

            var newUnmappedButton = new Button(() => {
                if (string.IsNullOrWhiteSpace(newKeyField.value))
                {
                    Debug.LogWarning("Cannot create parameter with null/whitespace key.");
                    return;
                }
                if (RemoteConfigData.parameters.ContainsKey(newKeyField.value))
                {
                    Debug.LogWarning($"A parameter with key {newKeyField.value} already exists.");
                    return;
                }
                var newParam          = RemoteConfigData.GetOrCreateParameter(newKeyField.value);
                var newUnmappedTarget = new UnmappedSyncElement(newParam);
                // Insert the new unmapped key at the end of the unmapped keys list.
                var index = unmappedParamsSection.IndexOf(newKeyContainer);
                unmappedParamsSection.Insert(index, newUnmappedTarget);
                newKeyField.value = newUnmappedParamText;
                // Apply column sizing to newly created SyncTargetElement.
                newUnmappedTarget
                .Query(null, columnClassName)
                .ForEach(col => col.style.minWidth = col.style.maxWidth = columnSize);
            });

            newUnmappedButton.text = "+";
            newUnmappedButton.AddToClassList("flex-0");
            newKeyContainer.Add(newUnmappedButton);
            unmappedParamsSection.Add(newKeyContainer);
            topLevelElement.Add(unmappedParamsSection);

            // Create a SyncGroupElement for the top-level SyncTargetContainer. SyncGroupElement and
            // the various SyncTypeElement classes handle the logic for creating the hierarchy UI.
            topLevelSyncTarget = new SyncGroupElement(SyncTargets);
            topLevelElement.Add(topLevelSyncTarget);

            // Below the ScrollView area, show a set of buttons to sync to/from RC and reset local changes.
            buttonContainer.Clear();
            buttonContainer.Add(uploadButton);
            buttonContainer.Add(downloadButton);
            buttonContainer.Add(resetChangesButton);

            // Reset UI by scrolling to previous scroll position and sizing the newly created columns.
            valueScrollView.scrollOffset = offset;
            lastTabWidth = position.width;
            ResizeColumns();
        }
Пример #9
0
        private void OnMaterialsDropped(Material[] droppedMaterials)
        {
            remappingRoot.Clear();

            DisposeOfSerializedObjects();

            //Construct a dictionary between shaders and their materials
            shadersToMaterials = new Dictionary <Shader, List <SerializedObject> >();
            foreach (Material material in droppedMaterials)
            {
                if (!shadersToMaterials.TryGetValue(material.shader, out var list))
                {
                    list = new List <SerializedObject>();
                    shadersToMaterials.Add(material.shader, list);
                }

                list.Add(new SerializedObject(material));
            }

            foreach (var pair in shadersToMaterials)
            {
                Box shaderRoot = new Box();
                shaderRoot.AddToClassList("innerPadding");
                remappingRoot.Add(shaderRoot);

                Shader      shader      = pair.Key;
                ObjectField shaderField = new ObjectField {
                    objectType = typeof(Shader), value = shader
                };
                shaderField.SetEnabled(false);
                shaderRoot.Add(shaderField);

                //RemapType, to a set of keys referring to values that could be remapped.
                var remapsFrom = new Dictionary <RemapType, HashSet <string> >();
                var remapsTo   = new Dictionary <RemapType, HashSet <string> >();

                List <SerializedObject> materials = pair.Value;
                foreach (SerializedObject materialSO in materials)
                {
                    SerializedProperty savedProperties = materialSO.FindProperty("m_SavedProperties");

                    //Textures -------------------------------------------------------------------------
                    SerializedProperty texEnvsArray = savedProperties.FindPropertyRelative("m_TexEnvs");
                    var textureKeys = new HashSet <string>();
                    remapsTo.Add(RemapType.Texture, textureKeys);
                    var textureKeysFrom = new HashSet <string>();
                    remapsFrom.Add(RemapType.Texture, textureKeysFrom);
                    for (int i = 0; i < texEnvsArray.arraySize; i++)
                    {
                        SerializedProperty texEnv  = texEnvsArray.GetArrayElementAtIndex(i);
                        SerializedProperty key     = texEnv.FindPropertyRelative("first");
                        SerializedProperty texture = texEnv.FindPropertyRelative("second.m_Texture");

                        textureKeys.Add(key.stringValue);
                        //Only add to the "from", if there is a key with a meaningful value in it.
                        if (texture.objectReferenceValue != null)
                        {
                            textureKeysFrom.Add(key.stringValue);
                        }
                    }
                    //-----------------------------------------------------------------------------------

                    //Floats ----------------------------------------------------------------------------
                    SerializedProperty floatsArray = savedProperties.FindPropertyRelative("m_Floats");
                    //floats have no way of telling if they're not set, so they can use the same set
                    var floatKeys = new HashSet <string>();
                    remapsTo.Add(RemapType.Float, floatKeys);
                    remapsFrom.Add(RemapType.Float, floatKeys);
                    for (int i = 0; i < floatsArray.arraySize; i++)
                    {
                        SerializedProperty @float = floatsArray.GetArrayElementAtIndex(i);
                        SerializedProperty key    = @float.FindPropertyRelative("first");
                        floatKeys.Add(key.stringValue);
                    }
                    //-----------------------------------------------------------------------------------

                    //Vectors and Colors ----------------------------------------------------------------
                    SerializedProperty colorsArray = savedProperties.FindPropertyRelative("m_Colors");
                    //colors have no way of telling if they're not set, so they can use the same set
                    var vectorKeys = new HashSet <string>();
                    remapsTo.Add(RemapType.VectorOrColor, vectorKeys);
                    remapsFrom.Add(RemapType.VectorOrColor, vectorKeys);
                    for (int i = 0; i < colorsArray.arraySize; i++)
                    {
                        SerializedProperty vector = colorsArray.GetArrayElementAtIndex(i);
                        SerializedProperty key    = vector.FindPropertyRelative("first");
                        vectorKeys.Add(key.stringValue);
                    }

                    //-----------------------------------------------------------------------------------
                }

                //CONTROLS
                var remapTypeField = new EnumField("Remap Type", RemapType.None)
                {
                    name = remapTypeName
                };
                remapTypeField.RegisterCallback <ChangeEvent <Enum> >(SelectedRemapType);
                shaderRoot.Add(remapTypeField);

                PopupField <string> popupFromField = new PopupField <string>(fromKeyLabel, noneList, 0)
                {
                    name = fromKeyPopupName
                };
                popupFromField.SetEnabled(false);
                shaderRoot.Add(popupFromField);

                PopupField <string> popupToField = new PopupField <string>(toKeyLabel, noneList, 0)
                {
                    name = toKeyPopupName
                };
                popupToField.SetEnabled(false);
                shaderRoot.Add(popupToField);

                Button remapButton = new Button {
                    text = "Remap", name = remapButtonName
                };
                remapButton.SetEnabled(false);
                shaderRoot.Add(remapButton);


                void SelectedRemapType(ChangeEvent <Enum> remapEvt)
                {
                    if (remapEvt == null)
                    {
                        throw new ArgumentNullException(nameof(remapEvt));
                    }

                    RemapType value = (RemapType)remapEvt.newValue;

                    if (value == RemapType.None)
                    {
                        GetButton().SetEnabled(false);
                        GetRemapTo().SetEnabled(false);
                        GetRemapFrom().SetEnabled(false);
                        return;
                    }

                    PopupField <string> child = GetRemapFrom();
                    int index = shaderRoot.IndexOf(child);

                    child.RemoveFromHierarchy();

                    List <string> choicesFrom = remapsFrom[value].ToList();

                    choicesFrom.Insert(0, none);
                    popupFromField = new PopupField <string>(fromKeyLabel, choicesFrom, none)
                    {
                        name = fromKeyPopupName
                    };
                    shaderRoot.Insert(index, popupFromField);
                    popupFromField.RegisterCallback <ChangeEvent <string> >(SelectedRemapFrom);
                }

                void SelectedRemapFrom(ChangeEvent <string> popupFromEvt)
                {
                    string remapFromKey = popupFromEvt.newValue;

                    if (remapFromKey == none)
                    {
                        GetButton().SetEnabled(false);
                        GetRemapTo().SetEnabled(false);
                        return;
                    }

                    PopupField <string> child = GetRemapTo();
                    int index = shaderRoot.IndexOf(child);

                    child.RemoveFromHierarchy();

                    List <string> choicesTo = remapsTo[(RemapType)remapTypeField.value].ToList();

                    choicesTo.Insert(0, none);
                    popupToField = new PopupField <string>(toKeyLabel, choicesTo, none)
                    {
                        name = toKeyPopupName
                    };
                    shaderRoot.Insert(index, popupToField);
                    popupToField.RegisterCallback <ChangeEvent <string>, (PopupField <string>, string)>(SelectedRemapTo, (popupToField, remapFromKey));
                }

                void SelectedRemapTo(ChangeEvent <string> popupToEvt, (PopupField <string> popupToField, string remapFromKey) args)
                {
                    string        remapToKey = popupToEvt.newValue;
                    VisualElement background = args.popupToField.Q(null, PopupField <string> .inputUssClassName);

                    if (remapToKey == none)
                    {
                        GetButton().SetEnabled(false);
                        background.style.unityBackgroundImageTintColor = default;
                        return;
                    }

                    if (remapToKey == args.remapFromKey)
                    {
                        background.style.unityBackgroundImageTintColor = new Color(1f, 0.46f, 0.51f);
                        return;
                    }

                    background.style.unityBackgroundImageTintColor = default;

                    var button = GetButton();

                    button.SetEnabled(true);
                    button.RemoveManipulator(button.clickable);
                    button.clickable = new Clickable(() => PerformRemap(shader, (RemapType)GetRemapType().value, args.remapFromKey, remapToKey));
                    button.AddManipulator(button.clickable);
                }

                Button GetButton() => shaderRoot.Q <Button>(remapButtonName);
                EnumField GetRemapType() => shaderRoot.Q <EnumField>(remapTypeName);
                PopupField <string> GetRemapFrom() => shaderRoot.Q <PopupField <string> >(fromKeyPopupName);
                PopupField <string> GetRemapTo() => shaderRoot.Q <PopupField <string> >(toKeyPopupName);
            }
        }