This commit is contained in:
2025-01-17 13:10:42 +01:00
commit 4536213c91
15115 changed files with 1442174 additions and 0 deletions

View File

@@ -0,0 +1,8 @@
namespace Unity.VisualScripting
{
[Descriptor(typeof(AnyState))]
public class AnyStateDescriptor : StateDescriptor<AnyState>
{
public AnyStateDescriptor(AnyState state) : base(state) { }
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0ae8021e59c334368b5ae08b2adfcfaf
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,18 @@
namespace Unity.VisualScripting
{
[Widget(typeof(AnyState))]
public class AnyStateWidget : StateWidget<AnyState>
{
public AnyStateWidget(StateCanvas canvas, AnyState state) : base(canvas, state) { }
protected override NodeColorMix color => NodeColorMix.TealReadable;
protected override string summary => null;
public override bool canToggleStart => false;
public override bool canForceEnter => false;
public override bool canForceExit => false;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e7f4def392c07401096915e803a01ebf
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
namespace Unity.VisualScripting
{
[Descriptor(typeof(FlowState))]
public class FlowStateDescriptor : NesterStateDescriptor<FlowState>
{
public FlowStateDescriptor(FlowState state) : base(state) { }
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f66f8803a57c44b2eb4880f870823740
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
namespace Unity.VisualScripting
{
[Editor(typeof(FlowState))]
public sealed class FlowStateEditor : NesterStateEditor
{
public FlowStateEditor(Metadata metadata) : base(metadata) { }
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5290affe00001419e8971554534f83f5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,231 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
namespace Unity.VisualScripting
{
[Widget(typeof(FlowState))]
public sealed class FlowStateWidget : NesterStateWidget<FlowState>, IDragAndDropHandler
{
public FlowStateWidget(StateCanvas canvas, FlowState state) : base(canvas, state)
{
state.nest.beforeGraphChange += BeforeGraphChange;
state.nest.afterGraphChange += AfterGraphChange;
if (state.nest.graph != null)
{
state.nest.graph.elements.CollectionChanged += CacheEventLinesOnUnityThread;
}
}
public override void Dispose()
{
base.Dispose();
state.nest.beforeGraphChange -= BeforeGraphChange;
state.nest.afterGraphChange -= AfterGraphChange;
}
private void BeforeGraphChange()
{
if (state.nest.graph != null)
{
state.nest.graph.elements.CollectionChanged -= CacheEventLinesOnUnityThread;
}
}
private void AfterGraphChange()
{
CacheEventLinesOnUnityThread();
if (state.nest.graph != null)
{
state.nest.graph.elements.CollectionChanged += CacheEventLinesOnUnityThread;
}
}
#region Model
private List<EventLine> eventLines { get; } = new List<EventLine>();
private void CacheEventLinesOnUnityThread()
{
UnityAPI.Async(CacheEventLines);
}
private void CacheEventLines()
{
eventLines.Clear();
if (state.nest.graph != null)
{
eventLines.AddRange(state.nest.graph.units
.OfType<IEventUnit>()
.Select(e => e.GetType())
.Distinct()
.Select(eventType => new EventLine(eventType))
.OrderBy(eventLine => eventLine.content.text));
}
Reposition();
}
protected override void CacheItemFirstTime()
{
base.CacheItemFirstTime();
CacheEventLines();
}
#endregion
#region Positioning
public Dictionary<EventLine, Rect> eventLinesPositions { get; } = new Dictionary<EventLine, Rect>();
public override void CachePosition()
{
base.CachePosition();
eventLinesPositions.Clear();
var y = contentInnerPosition.y;
foreach (var eventLine in eventLines)
{
var eventLinePosition = new Rect
(
contentInnerPosition.x,
y,
contentInnerPosition.width,
eventLine.GetHeight(contentInnerPosition.width)
);
eventLinesPositions.Add(eventLine, eventLinePosition);
y += eventLinePosition.height;
}
}
protected override float GetContentHeight(float width)
{
var eventLinesHeight = 0f;
foreach (var eventLine in eventLines)
{
eventLinesHeight += eventLine.GetHeight(width);
}
return eventLinesHeight;
}
#endregion
#region Drawing
protected override bool showContent => eventLines.Count > 0;
protected override void DrawContent()
{
foreach (var eventLine in eventLines)
{
eventLine.Draw(eventLinesPositions[eventLine]);
}
}
#endregion
#region Drag & Drop
public DragAndDropVisualMode dragAndDropVisualMode => DragAndDropVisualMode.Generic;
public bool AcceptsDragAndDrop()
{
return DragAndDropUtility.Is<ScriptGraphAsset>();
}
public void PerformDragAndDrop()
{
UndoUtility.RecordEditedObject("Drag & Drop Macro");
state.nest.source = GraphSource.Macro;
state.nest.macro = DragAndDropUtility.Get<ScriptGraphAsset>();
state.nest.embed = null;
GUI.changed = true;
}
public void UpdateDragAndDrop() { }
public void DrawDragAndDropPreview()
{
GraphGUI.DrawDragAndDropPreviewLabel(new Vector2(edgePosition.x, outerPosition.yMax), "Replace with: " + DragAndDropUtility.Get<ScriptGraphAsset>().name, typeof(ScriptGraphAsset).Icon());
}
public void ExitDragAndDrop() { }
#endregion
public new static class Styles
{
static Styles()
{
eventLine = new GUIStyle(EditorStyles.label);
eventLine.wordWrap = true;
eventLine.imagePosition = ImagePosition.TextOnly; // The icon is drawn manually
eventLine.padding = new RectOffset(0, 0, 3, 3);
}
public static readonly GUIStyle eventLine;
public static readonly float spaceAroundLineIcon = 5;
}
public class EventLine
{
public EventLine(Type eventType)
{
content = new GUIContent(BoltFlowNameUtility.UnitTitle(eventType, false, true), eventType.Icon()?[IconSize.Small]);
}
public GUIContent content { get; }
public float GetHeight(float width)
{
var labelWidth = width - Styles.spaceAroundLineIcon - IconSize.Small - Styles.spaceAroundLineIcon;
return Styles.eventLine.CalcHeight(content, labelWidth);
}
public void Draw(Rect position)
{
var iconPosition = new Rect
(
position.x + Styles.spaceAroundLineIcon,
position.y + Styles.eventLine.padding.top - 1,
IconSize.Small,
IconSize.Small
);
var labelPosition = new Rect
(
iconPosition.xMax + Styles.spaceAroundLineIcon,
position.y,
position.width - Styles.spaceAroundLineIcon - iconPosition.width - Styles.spaceAroundLineIcon,
position.height
);
if (content.image != null)
{
GUI.DrawTexture(iconPosition, content.image);
}
GUI.Label(labelPosition, content, Styles.eventLine);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d891a8dfd0a4d464897c1598d1a0f5a0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,7 @@
namespace Unity.VisualScripting
{
public interface IStateWidget : IGraphElementWidget
{
IState state { get; }
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a560e5c5437a44f2db6a4291e7ea9182
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,29 @@
using System.Collections.Generic;
namespace Unity.VisualScripting
{
[Analyser(typeof(INesterState))]
public class NesterStateAnalyser<TNesterState> : StateAnalyser<TNesterState>
where TNesterState : class, INesterState
{
public NesterStateAnalyser(GraphReference reference, TNesterState state) : base(reference, state) { }
protected override IEnumerable<Warning> Warnings()
{
foreach (var baseWarning in base.Warnings())
{
yield return baseWarning;
}
if (state.childGraph == null)
{
yield return Warning.Caution("Missing nested graph.");
}
if (state.nest.hasBackgroundEmbed)
{
yield return Warning.Caution("Background embed graph detected.");
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2bca8b8e70d8942bc9e0bed5eddf855d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,21 @@
namespace Unity.VisualScripting
{
[Descriptor(typeof(INesterState))]
public class NesterStateDescriptor<TNesterState> : StateDescriptor<TNesterState>
where TNesterState : class, INesterState
{
public NesterStateDescriptor(TNesterState state) : base(state) { }
[RequiresUnityAPI]
public override string Title()
{
return GraphNesterDescriptor.Title(state);
}
[RequiresUnityAPI]
public override string Summary()
{
return GraphNesterDescriptor.Summary(state);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e5353b3c45ba346d2ae924e8c15518cd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,30 @@
using UnityEngine;
namespace Unity.VisualScripting
{
[Editor(typeof(INesterState))]
public class NesterStateEditor : StateEditor
{
public NesterStateEditor(Metadata metadata) : base(metadata) { }
private Metadata nestMetadata => metadata[nameof(INesterState.nest)];
private Metadata graphMetadata => nestMetadata[nameof(IGraphNest.graph)];
protected override GraphReference headerReference => reference.ChildReference((INesterState)metadata.value, false);
protected override Metadata headerTitleMetadata => graphMetadata[nameof(IGraph.title)];
protected override Metadata headerSummaryMetadata => graphMetadata[nameof(IGraph.summary)];
protected override float GetInspectorHeight(float width)
{
return LudiqGUI.GetEditorHeight(this, nestMetadata, width);
}
protected override void OnInspectorGUI(Rect position)
{
LudiqGUI.Editor(nestMetadata, position);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 26fe4d37196fc4b978c8d67f2bf58df3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,56 @@
using System;
using System.Collections.Generic;
namespace Unity.VisualScripting
{
public abstract class NesterStateWidget<TNesterState> : StateWidget<TNesterState>
where TNesterState : class, INesterState
{
protected NesterStateWidget(StateCanvas canvas, TNesterState state) : base(canvas, state) { }
protected override IEnumerable<DropdownOption> contextOptions
{
get
{
var childReference = reference.ChildReference(state, false);
if (state.childGraph != null)
{
yield return new DropdownOption((Action)(() => window.reference = childReference), "Open");
yield return new DropdownOption((Action)(() => GraphWindow.OpenTab(childReference)), "Open in new window");
}
foreach (var baseOption in base.contextOptions)
{
yield return baseOption;
}
}
}
protected override void OnDoubleClick()
{
if (state.graph.zoom == 1)
{
var childReference = reference.ChildReference(state, false);
if (childReference != null)
{
if (e.ctrlOrCmd)
{
GraphWindow.OpenTab(childReference);
}
else
{
window.reference = childReference;
}
}
e.Use();
}
else
{
base.OnDoubleClick();
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8143bcca23d9e4377b5974c05f42e6dc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,57 @@
using System.Collections.Generic;
namespace Unity.VisualScripting
{
[Analyser(typeof(IState))]
public class StateAnalyser<TState> : Analyser<TState, StateAnalysis>
where TState : class, IState
{
public StateAnalyser(GraphReference reference, TState target) : base(reference, target) { }
public TState state => target;
[Assigns]
protected virtual bool IsEntered()
{
using (var recursion = Recursion.New(1))
{
return IsEntered(state, recursion);
}
}
[Assigns]
protected virtual IEnumerable<Warning> Warnings()
{
if (!IsEntered())
{
yield return Warning.Info("State is never entered.");
}
}
private bool IsEntered(IState state, Recursion recursion)
{
if (state.isStart)
{
return true;
}
if (!recursion?.TryEnter(state) ?? false)
{
return false;
}
foreach (var incomingTransition in state.incomingTransitions)
{
if (IsEntered(incomingTransition.source, recursion) && incomingTransition.Analysis<StateTransitionAnalysis>(context).isTraversed)
{
recursion?.Exit(state);
return true;
}
}
recursion?.Exit(state);
return false;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: eb1a4bbdbfdb14545866ce6d30badb33
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,7 @@
namespace Unity.VisualScripting
{
public sealed class StateAnalysis : GraphElementAnalysis
{
public bool isEntered { get; set; }
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 90539a84ee39e4c2493af60a32b9adb4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,6 @@
namespace Unity.VisualScripting
{
public sealed class StateDescription : GraphElementDescription
{
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e2102ddc23fbd412ca4aaec620483938
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,30 @@
namespace Unity.VisualScripting
{
[Descriptor(typeof(IState))]
public class StateDescriptor<TState> : Descriptor<TState, StateDescription>
where TState : class, IState
{
public StateDescriptor(TState target) : base(target) { }
public TState state => target;
[Assigns]
public override string Title()
{
return state.GetType().HumanName();
}
[Assigns]
public override string Summary()
{
return state.GetType().Summary();
}
[Assigns]
[RequiresUnityAPI]
public override EditorTexture Icon()
{
return state.GetType().Icon();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c2ac946d6d90843948d6f9062367a87e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,12 @@
namespace Unity.VisualScripting
{
[Editor(typeof(IState))]
public class StateEditor : GraphElementEditor<StateGraphContext>
{
public StateEditor(Metadata metadata) : base(metadata) { }
protected IState state => (IState)element;
protected new StateDescription description => (StateDescription)base.description;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: af7367866b51441ce9687566c007cb62
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,7 @@
namespace Unity.VisualScripting
{
public sealed class StateTransitionAnalysis : GraphElementAnalysis
{
public bool isTraversed { get; set; }
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 920ab3a8f1eff44d99181bd337fb849a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 03a1be6398ca64d4fa9e4810eb77c472
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
namespace Unity.VisualScripting
{
[Descriptor(typeof(SuperState))]
public class SuperStateDescriptor : NesterStateDescriptor<SuperState>
{
public SuperStateDescriptor(SuperState state) : base(state) { }
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7079eea8915904f1aa73089daa0789e4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
namespace Unity.VisualScripting
{
[Editor(typeof(SuperState))]
public sealed class SuperStateEditor : NesterStateEditor
{
public SuperStateEditor(Metadata metadata) : base(metadata) { }
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 14623fc883ca546f2af2de01ae7a8590
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,44 @@
using UnityEditor;
using UnityEngine;
namespace Unity.VisualScripting
{
[Widget(typeof(SuperState))]
public sealed class SuperStateWidget : NesterStateWidget<SuperState>, IDragAndDropHandler
{
public SuperStateWidget(StateCanvas canvas, SuperState state) : base(canvas, state) { }
#region Drag & Drop
public DragAndDropVisualMode dragAndDropVisualMode => DragAndDropVisualMode.Generic;
public bool AcceptsDragAndDrop()
{
return DragAndDropUtility.Is<StateGraphAsset>();
}
public void PerformDragAndDrop()
{
UndoUtility.RecordEditedObject("Drag & Drop Macro");
state.nest.source = GraphSource.Macro;
state.nest.macro = DragAndDropUtility.Get<StateGraphAsset>();
state.nest.embed = null;
GUI.changed = true;
}
public void UpdateDragAndDrop()
{
}
public void DrawDragAndDropPreview()
{
GraphGUI.DrawDragAndDropPreviewLabel(new Vector2(edgePosition.x, outerPosition.yMax), "Replace with: " + DragAndDropUtility.Get<StateGraphAsset>().name, typeof(StateGraphAsset).Icon());
}
public void ExitDragAndDrop()
{
}
#endregion
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 99e3f3703a7fd4b78928d46762518767
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: