private void AddEntries(ArrayElementBuilder elementBuilder, int count) => elementBuilder.schedule.Execute(() => elementBuilder.value += count);
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); }