OldBlueWater/BlueWater/Assets/Doozy/Editor/UIManager/Nodes/UINodeEditor.cs

460 lines
18 KiB
C#

// Copyright (c) 2015 - 2023 Doozy Entertainment. All Rights Reserved.
// This code can only be used under the standard Unity Asset Store End User License Agreement
// A Copy of the EULA APPENDIX 1 is available at http://unity3d.com/company/legal/as_terms
using System.Collections.Generic;
using Doozy.Editor.EditorUI;
using Doozy.Editor.EditorUI.Components;
using Doozy.Editor.EditorUI.Components.Internal;
using Doozy.Editor.EditorUI.ScriptableObjects.Colors;
using Doozy.Editor.EditorUI.Utils;
using Doozy.Editor.Nody.Nodes.Internal;
using Doozy.Editor.UIElements;
using Doozy.Editor.UIManager.Nodes.PortData;
using Doozy.Runtime.Colors;
using Doozy.Runtime.Common.Extensions;
using Doozy.Runtime.UIElements.Extensions;
using Doozy.Runtime.UIManager.Nodes;
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UIElements;
namespace Doozy.Editor.UIManager.Nodes
{
[CustomEditor(typeof(UINode))]
public class UINodeEditor : FlowNodeEditor
{
public override IEnumerable<Texture2D> nodeIconTextures => EditorSpriteSheets.Nody.Icons.UINode;
private FluidComponentHeader enterNodeHeader { get; set; }
private FluidComponentHeader exitNodeHeader { get; set; }
private FluidToggleSwitch onEnterHideAllViewsSwitch { get; set; }
private FluidToggleSwitch onExitHideAllViewsSwitch { get; set; }
private SerializedProperty propertyOnEnterShowViews { get; set; }
private SerializedProperty propertyOnEnterHideViews { get; set; }
private SerializedProperty propertyOnExitShowViews { get; set; }
private SerializedProperty propertyOnExitHideViews { get; set; }
private SerializedProperty propertyOnEnterHideAllViews { get; set; }
private SerializedProperty propertyOnExitHideAllViews { get; set; }
protected override void OnDestroy()
{
base.OnDestroy();
enterNodeHeader?.Recycle();
exitNodeHeader?.Recycle();
onEnterHideAllViewsSwitch?.Recycle();
onExitHideAllViewsSwitch?.Recycle();
}
protected override void FindProperties()
{
base.FindProperties();
propertyOnEnterShowViews = serializedObject.FindProperty("OnEnterShowViews");
propertyOnEnterHideViews = serializedObject.FindProperty("OnEnterHideViews");
propertyOnExitShowViews = serializedObject.FindProperty("OnExitShowViews");
propertyOnExitHideViews = serializedObject.FindProperty("OnExitHideViews");
propertyOnEnterHideAllViews = serializedObject.FindProperty("OnEnterHideAllViews");
propertyOnExitHideAllViews = serializedObject.FindProperty("OnExitHideAllViews");
}
protected override void InitializeEditor()
{
base.InitializeEditor();
componentHeader
.SetComponentNameText(ObjectNames.NicifyVariableName(nameof(UINode)))
.AddManualButton()
.AddApiButton("https://api.doozyui.com/api/Doozy.Runtime.UIManager.Nodes.UINode.html")
.AddYouTubeButton();
enterNodeHeader =
GetHeader()
.SetComponentNameText("On Enter Node")
.SetIcon(EditorSpriteSheets.Nody.Icons.EnterNode)
.SetAccentColor(EditorColors.Nody.Input);
onEnterHideAllViewsSwitch =
FluidToggleSwitch.Get()
.SetToggleAccentColor(EditorSelectableColors.Nody.Input)
.SetLabelText("Hide All Views")
.BindToProperty(propertyOnEnterHideAllViews);
exitNodeHeader =
GetHeader()
.SetComponentNameText("On Exit Node")
.SetIcon(EditorSpriteSheets.Nody.Icons.ExitNode)
.SetAccentColor(EditorColors.Nody.Output);
onExitHideAllViewsSwitch =
FluidToggleSwitch.Get()
.SetToggleAccentColor(EditorSelectableColors.Nody.Output)
.SetLabelText("Hide All Views")
.BindToProperty(propertyOnExitHideAllViews);
RefreshNodeEditor();
}
public override void RefreshNodeEditor()
{
base.RefreshNodeEditor();
flowNode.outputPorts.ForEach(p => portsContainer.AddChild(new UIOutputPortDataEditor(p, nodeView)));
}
protected override void Compose()
{
base.Compose();
root
.AddSpaceBlock(2)
.AddChild(portsContainer)
.AddSpaceBlock(3)
.AddChild(enterNodeHeader)
.AddSpaceBlock()
.AddChild
(
showHideContainer
.SetStyleBorderColor(EditorColors.Nody.Input.WithAlpha(0.4f))
.AddChild(onEnterHideAllViewsSwitch)
.AddSpaceBlock(2)
.AddChild
(
new IdsPropertyList(propertyOnEnterShowViews)
.SetListTitle("Show Views")
.SetListDescription("Views that will be shown when the node is activated")
.SetListTitleColor(EditorColors.Nody.Input)
)
.AddSpaceBlock(2)
.AddChild
(
new IdsPropertyList(propertyOnEnterHideViews)
.SetListTitle("Hide Views")
.SetListDescription("Views that will be hidden when the node is activated")
.SetListTitleColor(EditorColors.Nody.Input)
)
)
.AddSpaceBlock(4)
.AddChild(exitNodeHeader)
.AddSpaceBlock()
.AddChild
(
showHideContainer
.SetStyleBorderColor(EditorColors.Nody.Output.WithAlpha(0.4f))
.AddChild(onExitHideAllViewsSwitch)
.AddSpaceBlock(2)
.AddChild
(
new IdsPropertyList(propertyOnExitShowViews)
.SetListTitle("Show Views")
.SetListDescription("Views that will be shown when the node is deactivated")
.SetListTitleColor(EditorColors.Nody.Output)
)
.AddSpaceBlock(2)
.AddChild
(
new IdsPropertyList(propertyOnExitHideViews)
.SetListTitle("Hide Views")
.SetListDescription("Views that will be hidden when the node is deactivated")
.SetListTitleColor(EditorColors.Nody.Output)
)
)
.AddSpaceBlock(2)
;
}
private static VisualElement showHideContainer =>
DesignUtils.column
.SetStyleBorderRadius(6)
.SetStyleBorderWidth(1)
.SetStylePadding(DesignUtils.k_Spacing2X);
private static FluidComponentHeader GetHeader() => FluidComponentHeader.Get().SetElementSize(ElementSize.Small);
private class IdsPropertyList : VisualElement
{
private SerializedProperty property { get; }
//REFERENCES
private VisualElement layoutContainer { get; }
private Label titleLabel { get; }
private Label descriptionLabel { get; }
private VisualElement toolbarContainer { get; }
private VisualElement listContainer { get; }
private VisualElement addItemButtonContainer { get; }
//ACTIONS
public UnityAction AddNewItemButtonCallback;
//SELECTABLE COLORS
private static EditorSelectableColorInfo actionSelectableColor => EditorSelectableColors.Default.Action;
private static EditorSelectableColorInfo addSelectableColor => EditorSelectableColors.Default.Add;
private static EditorSelectableColorInfo removeSelectableColor => EditorSelectableColors.Default.Remove;
//COLORS
private static Color listNameTextColor => EditorColors.Default.TextTitle;
private static Color listDescriptionTextColor => EditorColors.Default.TextDescription;
private static Color backgroundColor => EditorColors.Default.Background;
//FONTS
private static Font listNameFont => EditorFonts.Ubuntu.Light;
private static Font listDescriptionFont => EditorFonts.Inter.Light;
private List<PropertyRow> rows { get; }
public IdsPropertyList(SerializedProperty property)
{
if (property == null) return;
if (!property.isArray) return;
this.property = property;
layoutContainer =
new VisualElement()
.SetStyleBackgroundColor(backgroundColor)
.SetStylePadding(DesignUtils.k_Spacing)
.SetStyleBorderRadius(DesignUtils.k_Spacing2X);
titleLabel =
new Label()
.SetStyleColor(listNameTextColor)
.SetStyleUnityFont(listNameFont)
.SetStylePadding(DesignUtils.k_Spacing)
.SetStyleDisplay(DisplayStyle.None)
.SetStyleFontSize(14);
descriptionLabel =
new Label()
.SetStyleColor(listDescriptionTextColor)
.SetStyleUnityFont(listDescriptionFont)
.SetStyleDisplay(DisplayStyle.None)
.SetStyleFontSize(10)
.SetStylePaddingLeft(DesignUtils.k_Spacing)
.SetWhiteSpace(WhiteSpace.Normal);
toolbarContainer =
new VisualElement()
.SetStyleFlexDirection(FlexDirection.Row)
.SetStyleFlexGrow(1);
addItemButtonContainer =
new VisualElement()
.SetStyleFlexDirection(FlexDirection.Row)
.SetStyleFlexGrow(0)
.SetStyleFlexShrink(0)
.SetStylePaddingLeft(DesignUtils.k_Spacing)
.SetStylePaddingRight(DesignUtils.k_Spacing2X)
.AddChild
(
DesignUtils.row
.AddChild(DesignUtils.dividerVertical)
.AddSpaceBlock()
.AddChild(Buttons.addButton.SetOnClick(AddNewItem).SetStyleAlignSelf(Align.FlexEnd))
);
listContainer
= new VisualElement()
.SetStyleBackgroundColor(backgroundColor);
this
.AddChild
(
layoutContainer
.AddChild(titleLabel)
.AddChild(descriptionLabel)
.AddSpaceBlock()
.AddChild
(
DesignUtils.row
.AddChild(toolbarContainer)
.AddChild(addItemButtonContainer)
)
.AddSpaceBlock()
.AddChild(listContainer)
);
const int rowsCapacity = 5;
rows = new List<PropertyRow>(rowsCapacity);
RefreshRows();
//every 50ms check if the array size has changed
//this is needed to for Undo/Redo operations
schedule.Execute
(
() =>
{
if (property.arraySize != rows.Count)
RefreshRows();
}
)
.Every(30);
}
public IdsPropertyList SetListTitle(string listTitle)
{
titleLabel.SetStyleDisplay(listTitle.IsNullOrEmpty() ? DisplayStyle.None : DisplayStyle.Flex);
titleLabel.text = listTitle;
return this;
}
public IdsPropertyList SetListDescription(string listDescription)
{
descriptionLabel.SetStyleDisplay(listDescription.IsNullOrEmpty() ? DisplayStyle.None : DisplayStyle.Flex);
descriptionLabel.text = listDescription;
return this;
}
public IdsPropertyList SetListTitleColor(Color color)
{
titleLabel.SetStyleColor(color);
return this;
}
public IdsPropertyList SetListDescriptionColor(Color color)
{
descriptionLabel.SetStyleColor(color);
return this;
}
private void RefreshRows()
{
property.serializedObject.UpdateIfRequiredOrScript();
// make sure the row capacity is enough (in case the array size was increased to a crazy number)
if (rows.Capacity < property.arraySize)
rows.Capacity = property.arraySize;
for (int i = rows.Count - 1; i >= 0; i--)
{
VisualElement row = rows[i];
if (row == null) continue;
rows[i].Recycle();
rows.RemoveAt(i);
}
if (rows.Count > 0)
rows.Clear();
listContainer
.RecycleAndClear();
for (int i = 0; i < property.arraySize; i++)
{
PropertyRow row = GetRow(i);
rows.Add(row);
listContainer.AddChild(row);
}
listContainer.Bind(property.serializedObject);
}
private PropertyRow GetRow(int elementIndex) =>
PropertyRow.Get()
.SetProperty(property.GetArrayElementAtIndex(elementIndex))
.SetRemoveAction(() => RemoveItem(elementIndex));
private void RemoveItem(int elementIndex)
{
//check if the index is valid
if (elementIndex < 0 || elementIndex >= property.arraySize)
return;
//remove the property
property.DeleteArrayElementAtIndex(elementIndex);
property.serializedObject.ApplyModifiedProperties();
//refresh the rows
RefreshRows();
}
private void AddNewItem()
{
//add a new element to the array
property.InsertArrayElementAtIndex(property.arraySize);
property.serializedObject.ApplyModifiedProperties();
//refresh the rows
RefreshRows();
}
public class PropertyRow : PoolableElement<PropertyRow>
{
private SerializedProperty property { get; set; }
private PropertyField propertyField { get; }
private FluidButton removeButton { get; }
public override void Reset()
{
propertyField.Unbind();
property = null;
propertyField.SetBindingPath(null);
removeButton.ClearOnClick();
removeButton.SetSelectionState(SelectionState.Normal);
}
public PropertyRow()
{
propertyField =
new PropertyField()
.ResetLayout()
.SetStyleFlexGrow(1);
removeButton =
Buttons.removeButton;
this
.SetStyleAlignItems(Align.Center)
.SetStyleBorderRadius(DesignUtils.k_FieldBorderRadius)
.SetStylePadding(DesignUtils.k_Spacing)
.SetStyleMargins(DesignUtils.k_Spacing)
.SetStyleBackgroundColor(EditorColors.Default.FieldBackground)
.SetStyleFlexDirection(FlexDirection.Row);
this
.AddChild(propertyField)
.AddSpaceBlock()
.AddChild(DesignUtils.dividerVertical)
.AddSpaceBlock()
.AddChild(removeButton);
}
public PropertyRow SetProperty(SerializedProperty newProperty)
{
property = newProperty;
propertyField.SetBindingPath(property.propertyPath);
return this;
}
public PropertyRow SetRemoveAction(UnityAction action)
{
removeButton.SetOnClick(action);
return this;
}
}
private static class Buttons
{
private const ElementSize k_Size = ElementSize.Small;
private const ButtonStyle k_ButtonStyle = ButtonStyle.Clear;
private static EditorSelectableColorInfo accentColor => actionSelectableColor;
// ReSharper disable once MemberCanBePrivate.Local
public static FluidButton GetNewToolbarButton(IEnumerable<Texture2D> textures, string tooltip = "") =>
FluidButton.Get()
.SetIcon(textures)
.SetElementSize(k_Size)
.SetButtonStyle(k_ButtonStyle)
.SetAccentColor(accentColor)
.SetTooltip(tooltip);
public static FluidButton addButton => GetNewToolbarButton(EditorSpriteSheets.EditorUI.Icons.Plus, "Add Item").SetAccentColor(addSelectableColor);
public static FluidButton removeButton => GetNewToolbarButton(EditorSpriteSheets.EditorUI.Icons.Minus, "Remove Item").SetAccentColor(removeSelectableColor);
}
}
}
}