Files
.vs
Assets
Library
APIUpdater
Artifacts
Bee
BuildPlayerData
PackageCache
com.unity.collab-proxy@2.5.2
com.unity.editorcoroutines@1.0.0
com.unity.ext.nunit@1.0.6
com.unity.feature.development@1.0.1
com.unity.ide.rider@3.0.31
com.unity.ide.visualstudio@2.0.22
com.unity.ide.vscode@1.2.5
com.unity.modules.ai@1.0.0
com.unity.modules.androidjni@1.0.0
com.unity.modules.animation@1.0.0
com.unity.modules.assetbundle@1.0.0
com.unity.modules.audio@1.0.0
com.unity.modules.cloth@1.0.0
com.unity.modules.director@1.0.0
com.unity.modules.imageconversion@1.0.0
com.unity.modules.imgui@1.0.0
com.unity.modules.jsonserialize@1.0.0
com.unity.modules.particlesystem@1.0.0
com.unity.modules.physics2d@1.0.0
com.unity.modules.physics@1.0.0
com.unity.modules.screencapture@1.0.0
com.unity.modules.subsystems@1.0.0
com.unity.modules.terrain@1.0.0
com.unity.modules.terrainphysics@1.0.0
com.unity.modules.tilemap@1.0.0
com.unity.modules.ui@1.0.0
com.unity.modules.uielements@1.0.0
com.unity.modules.umbra@1.0.0
com.unity.modules.unityanalytics@1.0.0
com.unity.modules.unitywebrequest@1.0.0
com.unity.modules.unitywebrequestassetbundle@1.0.0
com.unity.modules.unitywebrequestaudio@1.0.0
com.unity.modules.unitywebrequesttexture@1.0.0
com.unity.modules.unitywebrequestwww@1.0.0
com.unity.modules.vehicles@1.0.0
com.unity.modules.video@1.0.0
com.unity.modules.vr@1.0.0
com.unity.modules.wind@1.0.0
com.unity.modules.xr@1.0.0
com.unity.performance.profile-analyzer@1.2.2
com.unity.settings-manager@2.0.1
com.unity.test-framework@1.1.33
com.unity.testtools.codecoverage@1.2.6
com.unity.textmeshpro@3.0.6
com.unity.timeline@1.7.6
com.unity.ugui@1.0.0
com.unity.visualscripting@1.9.4
Documentation~
Editor
Graphics
Runtime
VisualScripting.Core
VisualScripting.Flow
Connections
Dependencies
EditorBinding
Framework
Ports
Properties
Antlr3.Runtime.defines
Antlr3.Runtime.defines.meta
Connections.meta
Dependencies.meta
EditorBinding.meta
Flow.cs
Flow.cs.meta
FlowGraph.cs
FlowGraph.cs.meta
FlowGraphData.cs
FlowGraphData.cs.meta
Framework.meta
IDefaultValue.cs
IDefaultValue.cs.meta
INesterUnit.cs
INesterUnit.cs.meta
IUnit.cs
IUnit.cs.meta
IUnitDebugData.cs
IUnitDebugData.cs.meta
MultiInputUnit.cs
MultiInputUnit.cs.meta
NesterUnit.cs
NesterUnit.cs.meta
Ports.meta
Properties.meta
ScriptGraphAsset.cs
ScriptGraphAsset.cs.meta
ScriptMachine.cs
ScriptMachine.cs.meta
SubgraphUnit.cs
SubgraphUnit.cs.meta
Unit.cs
Unit.cs.meta
UnitCategory.cs
UnitCategory.cs.meta
UnitCategoryConverter.cs
UnitCategoryConverter.cs.meta
UnitPortDefinitionCollection.cs
UnitPortDefinitionCollection.cs.meta
UnitPreservation.cs
UnitPreservation.cs.meta
Unity.VisualScripting.Flow.asmdef
Unity.VisualScripting.Flow.asmdef.meta
VisualScripting.State
VisualScripting.Core.meta
VisualScripting.Flow.meta
VisualScripting.State.meta
.npmignore.release
.signature
CHANGELOG.md
CHANGELOG.md.meta
Editor.meta
Graphics.meta
LICENSE.md
LICENSE.md.meta
README.md
README.md.meta
Runtime.meta
Third Party Notices.md
Third Party Notices.md.meta
ValidationConfig.json
ValidationConfig.json.meta
ValidationExceptions.json
ValidationExceptions.json.meta
package.json
package.json.meta
PackageManager
PlayModeViewStates
PlayerDataCache
ScriptAssemblies
Search
ShaderCache
SplashScreenCache
StateCache
UIElements
AnnotationManager
ArtifactDB
ArtifactDB-lock
BuildPlayer.prefs
BuildSettings.asset
EditorOnlyScriptingSettings.json
EditorOnlyVirtualTextureState.json
EditorSnapSettings.asset
EditorUserBuildSettings.asset
InspectorExpandedItems.asset
LastBuild.buildreport
LastSceneManagerSetup.txt
LibraryFormatVersion.txt
MonoManager.asset
SceneVisibilityState.asset
ScriptMapper
ShaderCache.db
SourceAssetDB
SourceAssetDB-lock
SpriteAtlasDatabase.asset
Style.catalog
expandedItems
ilpp.pid
Logs
Packages
ProjectSettings
UserSettings
obj
.vsconfig
Assembly-CSharp.Player.csproj
Assembly-CSharp.csproj
TM1.sln
Unity.CollabProxy.Editor.csproj
Unity.EditorCoroutines.Editor.csproj
Unity.Performance.Profile-Analyzer.Editor.csproj
Unity.PlasticSCM.Editor.csproj
Unity.Rider.Editor.csproj
Unity.Settings.Editor.csproj
Unity.TestTools.CodeCoverage.Editor.OpenCover.Model.csproj
Unity.TestTools.CodeCoverage.Editor.OpenCover.Mono.Reflection.csproj
Unity.TestTools.CodeCoverage.Editor.csproj
Unity.TextMeshPro.Editor.csproj
Unity.TextMeshPro.Player.csproj
Unity.TextMeshPro.csproj
Unity.Timeline.Editor.csproj
Unity.Timeline.Player.csproj
Unity.Timeline.csproj
Unity.VSCode.Editor.csproj
Unity.VisualScripting.Core.Editor.csproj
Unity.VisualScripting.Core.Player.csproj
Unity.VisualScripting.Core.csproj
Unity.VisualScripting.Flow.Editor.csproj
Unity.VisualScripting.Flow.Player.csproj
Unity.VisualScripting.Flow.csproj
Unity.VisualScripting.SettingsProvider.Editor.csproj
Unity.VisualScripting.Shared.Editor.csproj
Unity.VisualScripting.State.Editor.csproj
Unity.VisualScripting.State.Player.csproj
Unity.VisualScripting.State.csproj
Unity.VisualStudio.Editor.csproj
UnityEditor.TestRunner.csproj
UnityEditor.UI.csproj
UnityEngine.TestRunner.Player.csproj
UnityEngine.TestRunner.csproj
UnityEngine.UI.Player.csproj
UnityEngine.UI.csproj

421 lines
12 KiB
C#
Raw Normal View History

2025-01-17 13:10:20 +01:00
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace Unity.VisualScripting
{
[SerializationVersion("A")]
public abstract class Unit : GraphElement<FlowGraph>, IUnit
{
public class DebugData : IUnitDebugData
{
public int lastInvokeFrame { get; set; }
public float lastInvokeTime { get; set; }
public Exception runtimeException { get; set; }
}
protected Unit() : base()
{
controlInputs = new UnitPortCollection<ControlInput>(this);
controlOutputs = new UnitPortCollection<ControlOutput>(this);
valueInputs = new UnitPortCollection<ValueInput>(this);
valueOutputs = new UnitPortCollection<ValueOutput>(this);
invalidInputs = new UnitPortCollection<InvalidInput>(this);
invalidOutputs = new UnitPortCollection<InvalidOutput>(this);
relations = new ConnectionCollection<IUnitRelation, IUnitPort, IUnitPort>();
defaultValues = new Dictionary<string, object>();
}
public virtual IGraphElementDebugData CreateDebugData()
{
return new DebugData();
}
public override void AfterAdd()
{
// Important to define before notifying instances
Define();
base.AfterAdd();
}
public override void BeforeRemove()
{
base.BeforeRemove();
Disconnect();
}
public override void Instantiate(GraphReference instance)
{
base.Instantiate(instance);
if (this is IGraphEventListener listener && XGraphEventListener.IsHierarchyListening(instance))
{
listener.StartListening(instance);
}
}
public override void Uninstantiate(GraphReference instance)
{
if (this is IGraphEventListener listener)
{
listener.StopListening(instance);
}
base.Uninstantiate(instance);
}
#region Poutine
protected void CopyFrom(Unit source)
{
base.CopyFrom(source);
defaultValues = source.defaultValues;
}
#endregion
#region Definition
[DoNotSerialize]
public virtual bool canDefine => true;
[DoNotSerialize]
public bool failedToDefine => definitionException != null;
[DoNotSerialize]
public bool isDefined { get; private set; }
protected abstract void Definition();
protected virtual void AfterDefine() { }
protected virtual void BeforeUndefine() { }
private void Undefine()
{
// Because a node is always undefined on definition,
// even if it wasn't defined before, we make sure the user
// code for undefinition can safely presume it was defined.
if (isDefined)
{
BeforeUndefine();
}
Disconnect();
defaultValues.Clear();
controlInputs.Clear();
controlOutputs.Clear();
valueInputs.Clear();
valueOutputs.Clear();
invalidInputs.Clear();
invalidOutputs.Clear();
relations.Clear();
isDefined = false;
}
public void EnsureDefined()
{
if (!isDefined)
{
Define();
}
}
public void Define()
{
var preservation = UnitPreservation.Preserve(this);
// A node needs to undefine even if it wasn't defined,
// because there might be invalid ports and connections
// that we need to clear to avoid duplicates on definition.
Undefine();
if (canDefine)
{
try
{
Definition();
isDefined = true;
definitionException = null;
AfterDefine();
}
catch (Exception ex)
{
Undefine();
definitionException = ex;
Debug.LogWarning($"Failed to define {this}:\n{ex}");
}
}
preservation.RestoreTo(this);
}
public void RemoveUnconnectedInvalidPorts()
{
foreach (var unconnectedInvalidInput in invalidInputs.Where(p => !p.hasAnyConnection).ToArray())
{
invalidInputs.Remove(unconnectedInvalidInput);
}
foreach (var unconnectedInvalidOutput in invalidOutputs.Where(p => !p.hasAnyConnection).ToArray())
{
invalidOutputs.Remove(unconnectedInvalidOutput);
}
}
#endregion
#region Ports
[DoNotSerialize]
public IUnitPortCollection<ControlInput> controlInputs { get; }
[DoNotSerialize]
public IUnitPortCollection<ControlOutput> controlOutputs { get; }
[DoNotSerialize]
public IUnitPortCollection<ValueInput> valueInputs { get; }
[DoNotSerialize]
public IUnitPortCollection<ValueOutput> valueOutputs { get; }
[DoNotSerialize]
public IUnitPortCollection<InvalidInput> invalidInputs { get; }
[DoNotSerialize]
public IUnitPortCollection<InvalidOutput> invalidOutputs { get; }
[DoNotSerialize]
public IEnumerable<IUnitInputPort> inputs => LinqUtility.Concat<IUnitInputPort>(controlInputs, valueInputs, invalidInputs);
[DoNotSerialize]
public IEnumerable<IUnitOutputPort> outputs => LinqUtility.Concat<IUnitOutputPort>(controlOutputs, valueOutputs, invalidOutputs);
[DoNotSerialize]
public IEnumerable<IUnitInputPort> validInputs => LinqUtility.Concat<IUnitInputPort>(controlInputs, valueInputs);
[DoNotSerialize]
public IEnumerable<IUnitOutputPort> validOutputs => LinqUtility.Concat<IUnitOutputPort>(controlOutputs, valueOutputs);
[DoNotSerialize]
public IEnumerable<IUnitPort> ports => LinqUtility.Concat<IUnitPort>(inputs, outputs);
[DoNotSerialize]
public IEnumerable<IUnitPort> invalidPorts => LinqUtility.Concat<IUnitPort>(invalidInputs, invalidOutputs);
[DoNotSerialize]
public IEnumerable<IUnitPort> validPorts => LinqUtility.Concat<IUnitPort>(validInputs, validOutputs);
public event Action onPortsChanged;
public void PortsChanged()
{
onPortsChanged?.Invoke();
}
#endregion
#region Default Values
[Serialize]
public Dictionary<string, object> defaultValues { get; private set; }
#endregion
#region Connections
[DoNotSerialize]
public IConnectionCollection<IUnitRelation, IUnitPort, IUnitPort> relations { get; private set; }
[DoNotSerialize]
public IEnumerable<IUnitConnection> connections => ports.SelectMany(p => p.connections);
public void Disconnect()
{
// Can't use a foreach because invalid ports may get removed as they disconnect
while (ports.Any(p => p.hasAnyConnection))
{
ports.First(p => p.hasAnyConnection).Disconnect();
}
}
#endregion
#region Analysis
[DoNotSerialize]
public virtual bool isControlRoot { get; protected set; } = false;
#endregion
#region Helpers
protected void EnsureUniqueInput(string key)
{
if (controlInputs.Contains(key) || valueInputs.Contains(key) || invalidInputs.Contains(key))
{
throw new ArgumentException($"Duplicate input for '{key}' in {GetType()}.");
}
}
protected void EnsureUniqueOutput(string key)
{
if (controlOutputs.Contains(key) || valueOutputs.Contains(key) || invalidOutputs.Contains(key))
{
throw new ArgumentException($"Duplicate output for '{key}' in {GetType()}.");
}
}
protected ControlInput ControlInput(string key, Func<Flow, ControlOutput> action)
{
EnsureUniqueInput(key);
var port = new ControlInput(key, action);
controlInputs.Add(port);
return port;
}
protected ControlInput ControlInputCoroutine(string key, Func<Flow, IEnumerator> coroutineAction)
{
EnsureUniqueInput(key);
var port = new ControlInput(key, coroutineAction);
controlInputs.Add(port);
return port;
}
protected ControlInput ControlInputCoroutine(string key, Func<Flow, ControlOutput> action, Func<Flow, IEnumerator> coroutineAction)
{
EnsureUniqueInput(key);
var port = new ControlInput(key, action, coroutineAction);
controlInputs.Add(port);
return port;
}
protected ControlOutput ControlOutput(string key)
{
EnsureUniqueOutput(key);
var port = new ControlOutput(key);
controlOutputs.Add(port);
return port;
}
protected ValueInput ValueInput(Type type, string key)
{
EnsureUniqueInput(key);
var port = new ValueInput(key, type);
valueInputs.Add(port);
return port;
}
protected ValueInput ValueInput<T>(string key)
{
return ValueInput(typeof(T), key);
}
protected ValueInput ValueInput<T>(string key, T @default)
{
var port = ValueInput<T>(key);
port.SetDefaultValue(@default);
return port;
}
protected ValueOutput ValueOutput(Type type, string key)
{
EnsureUniqueOutput(key);
var port = new ValueOutput(key, type);
valueOutputs.Add(port);
return port;
}
protected ValueOutput ValueOutput(Type type, string key, Func<Flow, object> getValue)
{
EnsureUniqueOutput(key);
var port = new ValueOutput(key, type, getValue);
valueOutputs.Add(port);
return port;
}
protected ValueOutput ValueOutput<T>(string key)
{
return ValueOutput(typeof(T), key);
}
protected ValueOutput ValueOutput<T>(string key, Func<Flow, T> getValue)
{
return ValueOutput(typeof(T), key, (recursion) => getValue(recursion));
}
private void Relation(IUnitPort source, IUnitPort destination)
{
relations.Add(new UnitRelation(source, destination));
}
/// <summary>
/// Triggering the destination may fetch the source value.
/// </summary>
protected void Requirement(ValueInput source, ControlInput destination)
{
Relation(source, destination);
}
/// <summary>
/// Getting the value of the destination may fetch the value of the source.
/// </summary>
protected void Requirement(ValueInput source, ValueOutput destination)
{
Relation(source, destination);
}
/// <summary>
/// Triggering the source may assign the destination value on the flow.
/// </summary>
protected void Assignment(ControlInput source, ValueOutput destination)
{
Relation(source, destination);
}
/// <summary>
/// Triggering the source may trigger the destination.
/// </summary>
protected void Succession(ControlInput source, ControlOutput destination)
{
Relation(source, destination);
}
#endregion
#region Widget
[Serialize]
public Vector2 position { get; set; }
[DoNotSerialize]
public Exception definitionException { get; protected set; }
#endregion
#region Analytics
public override AnalyticsIdentifier GetAnalyticsIdentifier()
{
var aid = new AnalyticsIdentifier
{
Identifier = GetType().FullName,
Namespace = GetType().Namespace,
};
aid.Hashcode = aid.Identifier.GetHashCode();
return aid;
}
#endregion
}
}