Compare commits
No commits in common. "REALLY-SPOOKY-DONT-TOUCH-BRANCH" and "main" have entirely different histories.
REALLY-SPO
...
main
@ -1,3 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 43834c706e924da6b7f11712b89420bc
|
|
||||||
timeCreated: 1747472390
|
|
66
Editor/Scripts/Editor/Data Types/IPTPort.cs
Normal file
66
Editor/Scripts/Editor/Data Types/IPTPort.cs
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
using UnityEditor.Experimental.GraphView;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UIElements;
|
||||||
|
|
||||||
|
namespace ImageProcessingGraph.Editor
|
||||||
|
{
|
||||||
|
public class IPTPort : Port
|
||||||
|
{
|
||||||
|
public FieldInfo fieldInfo;
|
||||||
|
private VisualElement _exposedPropertyContainer;
|
||||||
|
|
||||||
|
public delegate void OnPortConnectedEvent();
|
||||||
|
public OnPortConnectedEvent OnPortConnected;
|
||||||
|
|
||||||
|
public delegate void OnPortDisconnectedEvent();
|
||||||
|
public OnPortDisconnectedEvent OnPortDisconnected;
|
||||||
|
|
||||||
|
public VisualElement ExposedPropertyContainer
|
||||||
|
{
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_exposedPropertyContainer = value;
|
||||||
|
}
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _exposedPropertyContainer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected IPTPort(Orientation portOrientation, Direction portDirection, Capacity portCapacity, Type type) : base(portOrientation, portDirection, portCapacity, type)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Connect(Edge edge)
|
||||||
|
{
|
||||||
|
base.Connect(edge);
|
||||||
|
OnPortConnected?.Invoke();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Disconnect(Edge edge)
|
||||||
|
{
|
||||||
|
base.Disconnect(edge);
|
||||||
|
OnPortDisconnected?.Invoke();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void PublicOnConnected(Port obj)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IPTPort Create(IEdgeConnectorListener connectorListener, bool isInput, Type type)
|
||||||
|
{
|
||||||
|
var port = new IPTPort(Orientation.Horizontal, isInput ? Direction.Input : Direction.Output,
|
||||||
|
isInput ? Capacity.Single : Capacity.Multi, type)
|
||||||
|
{
|
||||||
|
m_EdgeConnector = new EdgeConnector<Edge>(connectorListener),
|
||||||
|
};
|
||||||
|
port.AddManipulator(port.m_EdgeConnector);
|
||||||
|
return port;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
11
Editor/Scripts/Editor/Data Types/IPT_Preferences.cs
Normal file
11
Editor/Scripts/Editor/Data Types/IPT_Preferences.cs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace ImageProcessingGraph.Editor
|
||||||
|
{
|
||||||
|
public class IPT_Preferences : ScriptableObject
|
||||||
|
{
|
||||||
|
public bool debugMode = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
2
Editor/Scripts/Editor/Data Types/IPT_Preferences.cs.meta
Normal file
2
Editor/Scripts/Editor/Data Types/IPT_Preferences.cs.meta
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 80dcc02594d68e3439df7dc743c9d4b2
|
@ -3,17 +3,29 @@ using System.IO;
|
|||||||
using Unity.Collections;
|
using Unity.Collections;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
namespace AssetGraph.Core.DataTypes
|
/// A structure that holds image pixel data and its dimensions.
|
||||||
|
/// </summary>
|
||||||
|
[Serializable]
|
||||||
|
public struct ImageData
|
||||||
{
|
{
|
||||||
[Serializable]
|
/// <summary>
|
||||||
|
/// The pixel data of the image in Color32 format.
|
||||||
public struct ImageData
|
/// </summary>
|
||||||
{
|
|
||||||
public NativeArray<Color32> PixelData;
|
public NativeArray<Color32> PixelData;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The width and height of the image (width, height).
|
||||||
|
/// </summary>
|
||||||
public (int width, int height) Dimensions;
|
public (int width, int height) Dimensions;
|
||||||
|
|
||||||
public bool isRGBA;
|
public bool isRGBA;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="ImageData"/> struct using existing pixel data and dimensions.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="imageData">The pixel data as a NativeArray of Color32.</param>
|
||||||
|
/// <param name="widthHeight">A tuple containing the width and height of the image.</param>
|
||||||
public ImageData(NativeArray<Color32> imageData, (int width, int height) widthHeight, bool isRgba)
|
public ImageData(NativeArray<Color32> imageData, (int width, int height) widthHeight, bool isRgba)
|
||||||
{
|
{
|
||||||
PixelData = imageData;
|
PixelData = imageData;
|
||||||
@ -21,6 +33,10 @@ namespace AssetGraph.Core.DataTypes
|
|||||||
isRGBA = isRgba;
|
isRGBA = isRgba;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="ImageData"/> struct from a Texture2D object.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sourceTexture">The source texture to extract pixel data from.</param>
|
||||||
public ImageData(Texture2D sourceTexture)
|
public ImageData(Texture2D sourceTexture)
|
||||||
{
|
{
|
||||||
PixelData = new NativeArray<Color32>(sourceTexture.GetPixelData<Color32>(0), Allocator.Persistent);
|
PixelData = new NativeArray<Color32>(sourceTexture.GetPixelData<Color32>(0), Allocator.Persistent);
|
||||||
@ -28,9 +44,20 @@ namespace AssetGraph.Core.DataTypes
|
|||||||
isRGBA = sourceTexture.format == TextureFormat.RGBA32;
|
isRGBA = sourceTexture.format == TextureFormat.RGBA32;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the width of the image.
|
||||||
|
/// </summary>
|
||||||
public int Width => Dimensions.width;
|
public int Width => Dimensions.width;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the height of the image.
|
||||||
|
/// </summary>
|
||||||
public int Height => Dimensions.height;
|
public int Height => Dimensions.height;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts the ImageData back into a new Texture2D.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A Texture2D object created from the stored pixel data.</returns>
|
||||||
public Texture2D ToTexture2D()
|
public Texture2D ToTexture2D()
|
||||||
{
|
{
|
||||||
var texture = new Texture2D(Width, Height, TextureFormat.RGBA32, false);
|
var texture = new Texture2D(Width, Height, TextureFormat.RGBA32, false);
|
||||||
@ -46,8 +73,7 @@ namespace AssetGraph.Core.DataTypes
|
|||||||
|
|
||||||
if (data != null)
|
if (data != null)
|
||||||
{
|
{
|
||||||
File.WriteAllBytes(path, data);
|
System.IO.File.WriteAllBytes(path, data);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,22 +2,46 @@
|
|||||||
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace AssetGraph.Core.DataTypes
|
/// <summary>
|
||||||
|
/// Represents a single image channel (e.g., Red, Green, Blue, Alpha) as a 1D byte array,
|
||||||
|
/// along with the original image dimensions.
|
||||||
|
/// </summary>
|
||||||
|
public struct SplitChannelData
|
||||||
{
|
{
|
||||||
public struct SplitChannelData
|
/// <summary>
|
||||||
{
|
/// The 8-bit intensity values for a single image channel, stored in row-major order.
|
||||||
|
/// </summary>
|
||||||
public byte[] ChannelData;
|
public byte[] ChannelData;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The width and height of the channel data (width, height).
|
||||||
|
/// </summary>
|
||||||
public (int width, int height) Dimensions;
|
public (int width, int height) Dimensions;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="SplitChannelData"/> struct
|
||||||
|
/// using channel data and dimensions.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="channelData">The byte array representing the single channel values.</param>
|
||||||
|
/// <param name="widthHeight">A tuple of (width, height) representing the dimensions.</param>
|
||||||
public SplitChannelData(byte[] channelData, (int width, int height) widthHeight)
|
public SplitChannelData(byte[] channelData, (int width, int height) widthHeight)
|
||||||
{
|
{
|
||||||
ChannelData = channelData;
|
ChannelData = channelData;
|
||||||
Dimensions = widthHeight;
|
Dimensions = widthHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the width of the channel data.
|
||||||
|
/// </summary>
|
||||||
public int Width => Dimensions.width;
|
public int Width => Dimensions.width;
|
||||||
public int Height => Dimensions.height;
|
|
||||||
public bool IsValid => ChannelData != null && ChannelData.Length == Width * Height;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the height of the channel data.
|
||||||
|
/// </summary>
|
||||||
|
public int Height => Dimensions.height;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks whether the channel data is valid (non-null and matches the expected size).
|
||||||
|
/// </summary>
|
||||||
|
public bool IsValid => ChannelData != null && ChannelData.Length == Width * Height;
|
||||||
}
|
}
|
@ -1,3 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 458de9252a6744148203b96771e2ad90
|
|
||||||
timeCreated: 1747472377
|
|
@ -1,68 +0,0 @@
|
|||||||
using System;
|
|
||||||
using UnityEditor.Experimental.GraphView;
|
|
||||||
using UnityEngine;
|
|
||||||
using UnityEngine.UIElements;
|
|
||||||
|
|
||||||
namespace AssetGraph.Core.GraphElements
|
|
||||||
{
|
|
||||||
[System.Serializable]
|
|
||||||
public class AssetGraphStickyNoteData
|
|
||||||
{
|
|
||||||
[SerializeField] private string guid;
|
|
||||||
[SerializeField] private string title;
|
|
||||||
[SerializeField] private string content;
|
|
||||||
[SerializeField] private Rect position;
|
|
||||||
[SerializeField] private Vector2 size;
|
|
||||||
|
|
||||||
|
|
||||||
public string GUID { get => guid; }
|
|
||||||
|
|
||||||
public string Title { get => title; set => title = value; }
|
|
||||||
|
|
||||||
public string Content { get => content; set => content = value; }
|
|
||||||
public Rect Position { get => position; set => position = value; }
|
|
||||||
public Vector2 Size { get => size; set => size = value; }
|
|
||||||
|
|
||||||
public AssetGraphStickyNoteData(string title)
|
|
||||||
{
|
|
||||||
this.guid = Guid.NewGuid().ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public class AssetGraphStickyNote : StickyNote
|
|
||||||
{
|
|
||||||
private AssetGraphStickyNoteData data;
|
|
||||||
public AssetGraphStickyNoteData Data => data;
|
|
||||||
|
|
||||||
private AssetGraphViewWindow window;
|
|
||||||
|
|
||||||
public AssetGraphStickyNote(AssetGraphStickyNoteData data, AssetGraphViewWindow window)
|
|
||||||
{
|
|
||||||
this.theme = StickyNoteTheme.Black;
|
|
||||||
this.window = window;
|
|
||||||
this.data = data;
|
|
||||||
|
|
||||||
this.title = data.Title;
|
|
||||||
this.contents = data.Content;
|
|
||||||
this.SetPosition(data.Position);
|
|
||||||
|
|
||||||
var le = this.Q<TextField>("contents-field");
|
|
||||||
|
|
||||||
le.RegisterValueChangedCallback(evt =>
|
|
||||||
{
|
|
||||||
this.data.Content = evt.newValue;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void OnResized()
|
|
||||||
{
|
|
||||||
base.OnResized();
|
|
||||||
data.Size = new Vector2(this.resolvedStyle.width, this.resolvedStyle.height);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SavePosition() => data.Position = GetPosition();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,3 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 119eef6b9f4b410da217f8a12be9973d
|
|
||||||
timeCreated: 1746345401
|
|
@ -1,3 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 1403355e956148e3a298f151e782e76c
|
|
||||||
timeCreated: 1747472333
|
|
@ -1,10 +0,0 @@
|
|||||||
using UnityEditor.Experimental.GraphView;
|
|
||||||
using UnityEngine.UIElements;
|
|
||||||
|
|
||||||
namespace AssetGraph.Core
|
|
||||||
{
|
|
||||||
public class AssetGraphEdge : Edge
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,3 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 76cd012b608644caa127970fd3caf115
|
|
||||||
timeCreated: 1746343590
|
|
@ -1,104 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
|
||||||
using AssetGraph.Nodes;
|
|
||||||
using UnityEditor.Experimental.GraphView;
|
|
||||||
using UnityEngine;
|
|
||||||
using UnityEngine.UIElements;
|
|
||||||
|
|
||||||
namespace AssetGraph.Core
|
|
||||||
{
|
|
||||||
public class AssetGraphPort : Port
|
|
||||||
{
|
|
||||||
public FieldInfo fieldInfo;
|
|
||||||
private VisualElement _exposedPropertyContainer;
|
|
||||||
|
|
||||||
public delegate void OnPortConnectedEvent();
|
|
||||||
public OnPortConnectedEvent OnPortConnected;
|
|
||||||
|
|
||||||
public delegate void OnPortDisconnectedEvent();
|
|
||||||
public OnPortDisconnectedEvent OnPortDisconnected;
|
|
||||||
|
|
||||||
public VisualElement ExposedPropertyContainer
|
|
||||||
{
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_exposedPropertyContainer = value;
|
|
||||||
}
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return _exposedPropertyContainer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected AssetGraphPort(Orientation portOrientation, Direction portDirection, Capacity portCapacity, Type type) : base(portOrientation, portDirection, portCapacity, type)
|
|
||||||
{
|
|
||||||
this.tooltip = $"{this.portType.ToString()}";
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Connect(Edge edge)
|
|
||||||
{
|
|
||||||
if (this.node is AssetGraphNodeEditor IPTVis && IPTVis.GraphNode is GenericConnection)
|
|
||||||
{
|
|
||||||
foreach (var port in IPTVis.AllPorts)
|
|
||||||
{
|
|
||||||
port.portType = edge.output.portType;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
base.Connect(edge);
|
|
||||||
OnPortConnected?.Invoke();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Disconnect(Edge edge)
|
|
||||||
{
|
|
||||||
AssetGraphNodeEditor IPTVis = this.node as AssetGraphNodeEditor;
|
|
||||||
|
|
||||||
if (IPTVis != null && IPTVis.GraphNode is GenericConnection bleh)
|
|
||||||
{
|
|
||||||
bool allPortsDisconnected = true;
|
|
||||||
|
|
||||||
foreach (var port in IPTVis.AllPorts)
|
|
||||||
{
|
|
||||||
if (port.connections != null && port.connections.Any())
|
|
||||||
{
|
|
||||||
allPortsDisconnected = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (allPortsDisconnected)
|
|
||||||
{
|
|
||||||
foreach (var port in IPTVis.AllPorts)
|
|
||||||
{
|
|
||||||
port.portType = typeof(object);
|
|
||||||
}
|
|
||||||
|
|
||||||
bleh.InternalType = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
base.Disconnect(edge);
|
|
||||||
OnPortDisconnected?.Invoke();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void PublicOnConnected(Port obj)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static AssetGraphPort Create(IEdgeConnectorListener connectorListener, bool isInput, Type type)
|
|
||||||
{
|
|
||||||
var port = new AssetGraphPort(Orientation.Horizontal, isInput ? Direction.Input : Direction.Output,
|
|
||||||
isInput ? Capacity.Single : Capacity.Multi, type)
|
|
||||||
{
|
|
||||||
m_EdgeConnector = new EdgeConnector<Edge>(connectorListener),
|
|
||||||
};
|
|
||||||
port.AddManipulator(port.m_EdgeConnector);
|
|
||||||
return port;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,56 +1,52 @@
|
|||||||
|
using ImageProcessingGraph.Editor.Windows;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEditor;
|
using UnityEditor;
|
||||||
using UnityEditor.Callbacks;
|
using UnityEditor.Callbacks;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using AssetGraph.Core.GraphElements;
|
|
||||||
using AssetGraph.Nodes;
|
|
||||||
using ImageProcessingGraph.Editor;
|
|
||||||
using UnityEditor.Experimental.GraphView;
|
using UnityEditor.Experimental.GraphView;
|
||||||
using Debug = UnityEngine.Debug;
|
using Debug = UnityEngine.Debug;
|
||||||
|
|
||||||
// ReSharper disable once CheckNamespace
|
// ReSharper disable once CheckNamespace
|
||||||
namespace AssetGraph.Core
|
namespace ImageProcessingGraph.Editor
|
||||||
{
|
{
|
||||||
[CreateAssetMenu(menuName = "Image Processing Graph/New Graph")]
|
[CreateAssetMenu(menuName = "Image Processing Graph/New Graph")]
|
||||||
public class AssetGraphData : ScriptableObject
|
public class ImageProcessingGraphAsset : ScriptableObject
|
||||||
{
|
{
|
||||||
[SerializeReference] private List<AssetGraphNode> nodes;
|
[SerializeReference] private List<BaseImageNode> nodes;
|
||||||
[SerializeField] private List<GraphConnection> connections;
|
[SerializeField] private List<GraphConnection> connections;
|
||||||
[SerializeReference] public List<AssetGraphNode> runOrder;
|
[SerializeReference] public List<BaseImageNode> runOrder;
|
||||||
[SerializeField] public List<AssetGraphStickyNoteData> stickyNotes;
|
[SerializeField] public List<StickyNote> stickyNotes;
|
||||||
|
|
||||||
public List<AssetGraphNode> Nodes => nodes;
|
public List<BaseImageNode> Nodes => nodes;
|
||||||
public List<GraphConnection> Connections => connections;
|
public List<GraphConnection> Connections => connections;
|
||||||
|
|
||||||
public delegate void OnRunEvent();
|
public delegate void OnRunEvent();
|
||||||
public event OnRunEvent OnRun;
|
public event OnRunEvent OnRun;
|
||||||
public OnRunEvent OnRunEnd;
|
public OnRunEvent OnRunEnd;
|
||||||
|
|
||||||
public AssetGraphData()
|
public ImageProcessingGraphAsset()
|
||||||
{
|
{
|
||||||
nodes = new List<AssetGraphNode>();
|
nodes = new List<BaseImageNode>();
|
||||||
connections = new List<GraphConnection>();
|
connections = new List<GraphConnection>();
|
||||||
stickyNotes = new List<AssetGraphStickyNoteData>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[OnOpenAsset(1)]
|
[OnOpenAsset(1)]
|
||||||
public static bool OpenGraphAsset(int instanceID, int line)
|
public static bool OpenGraphAsset(int instanceID, int line)
|
||||||
{
|
{
|
||||||
var asset = EditorUtility.InstanceIDToObject(instanceID) as AssetGraphData;
|
var asset = EditorUtility.InstanceIDToObject(instanceID) as ImageProcessingGraphAsset;
|
||||||
if (asset != null)
|
if (asset != null)
|
||||||
{
|
{
|
||||||
AssetGraphEditorWindow.Open(asset);
|
ImageProcessingGraphEditorWindow.Open(asset);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public void RunGraph()
|
public void RunGraph()
|
||||||
{
|
{
|
||||||
var bleh = GetAllVariableNodesWithTypes();
|
|
||||||
OnRun?.Invoke();
|
OnRun?.Invoke();
|
||||||
|
|
||||||
// Create and start the stopwatch to measure time
|
// Create and start the stopwatch to measure time
|
||||||
@ -59,19 +55,24 @@ namespace AssetGraph.Core
|
|||||||
|
|
||||||
runOrder = GetExecutionOrder(this.nodes, this.connections);
|
runOrder = GetExecutionOrder(this.nodes, this.connections);
|
||||||
|
|
||||||
|
bool failed = false;
|
||||||
|
|
||||||
foreach (var VARIABLE in runOrder)
|
foreach (var VARIABLE in runOrder)
|
||||||
{
|
{
|
||||||
if (!VARIABLE.RunNode())
|
if (!VARIABLE.RunNode())
|
||||||
{
|
{
|
||||||
|
failed = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var VARIABLE in runOrder)
|
foreach (var VARIABLE in runOrder)
|
||||||
{
|
{
|
||||||
VARIABLE.RunCleanUp();
|
if(!VARIABLE.RunCleanUp())
|
||||||
|
failed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Stop the stopwatch after running the nodes
|
||||||
stopwatch.Stop();
|
stopwatch.Stop();
|
||||||
|
|
||||||
// Log the elapsed time
|
// Log the elapsed time
|
||||||
@ -80,32 +81,15 @@ namespace AssetGraph.Core
|
|||||||
AssetDatabase.Refresh();
|
AssetDatabase.Refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<(AssetGraphNode node, System.Type type)> GetAllVariableNodesWithTypes()
|
|
||||||
{
|
|
||||||
var result = new List<(AssetGraphNode node, System.Type type)>();
|
|
||||||
|
|
||||||
foreach (var node in nodes)
|
/// <summary>
|
||||||
{
|
/// Computes a topological execution order of nodes based on their dependencies.
|
||||||
var nodeType = node.GetType();
|
/// Throws if a cycle is detected or nodes are missing from the input list.
|
||||||
var baseType = nodeType.BaseType;
|
/// </summary>
|
||||||
|
public List<BaseImageNode> GetExecutionOrder(List<BaseImageNode> nodes, List<GraphConnection> connections, bool debug = false)
|
||||||
if (baseType != null && baseType.IsGenericType)
|
|
||||||
{
|
|
||||||
if (baseType.GetGenericTypeDefinition() == typeof(VariableNode<>))
|
|
||||||
{
|
|
||||||
var genericArgument = baseType.GetGenericArguments()[0];
|
|
||||||
result.Add((node, genericArgument));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<AssetGraphNode> GetExecutionOrder(List<AssetGraphNode> nodes, List<GraphConnection> connections, bool debug = false)
|
|
||||||
{
|
{
|
||||||
// === Initialization ===
|
// === Initialization ===
|
||||||
var nodeMap = new Dictionary<string, AssetGraphNode>(nodes.Count);
|
var nodeMap = new Dictionary<string, BaseImageNode>(nodes.Count);
|
||||||
var adjList = new Dictionary<string, List<string>>(nodes.Count);
|
var adjList = new Dictionary<string, List<string>>(nodes.Count);
|
||||||
var inDegree = new Dictionary<string, int>(nodes.Count);
|
var inDegree = new Dictionary<string, int>(nodes.Count);
|
||||||
|
|
||||||
@ -142,7 +126,7 @@ namespace AssetGraph.Core
|
|||||||
}
|
}
|
||||||
|
|
||||||
// === Topological Sort (Kahn's Algorithm) ===
|
// === Topological Sort (Kahn's Algorithm) ===
|
||||||
var executionOrder = new List<AssetGraphNode>(nodes.Count);
|
var executionOrder = new List<BaseImageNode>(nodes.Count);
|
||||||
var queue = new Queue<string>(nodes.Count);
|
var queue = new Queue<string>(nodes.Count);
|
||||||
|
|
||||||
foreach (var kvp in inDegree)
|
foreach (var kvp in inDegree)
|
@ -2,18 +2,16 @@ using System;
|
|||||||
using System.Configuration;
|
using System.Configuration;
|
||||||
using UnityEditor.Experimental.GraphView;
|
using UnityEditor.Experimental.GraphView;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using ImageProcessingGraph.Editor.Nodes.NodeAttributes;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using Input = ImageProcessingGraph.Editor.Nodes.NodeAttributes.Input;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using AssetGraph.Core;
|
|
||||||
using AssetGraph.Core.Attributes;
|
|
||||||
using ImageProcessingGraph.Editor;
|
|
||||||
using Input = AssetGraph.Core.Attributes.Input;
|
|
||||||
|
|
||||||
namespace AssetGraph.Nodes
|
namespace ImageProcessingGraph.Editor
|
||||||
{
|
{
|
||||||
[System.Serializable]
|
[System.Serializable]
|
||||||
public abstract class AssetGraphNode
|
public abstract class BaseImageNode
|
||||||
{
|
{
|
||||||
[SerializeField] private string guid;
|
[SerializeField] private string guid;
|
||||||
|
|
||||||
@ -26,14 +24,17 @@ namespace AssetGraph.Nodes
|
|||||||
public string ID => guid;
|
public string ID => guid;
|
||||||
public Rect Position => position;
|
public Rect Position => position;
|
||||||
|
|
||||||
public AssetGraphData asset;
|
public ImageProcessingGraphAsset asset;
|
||||||
|
|
||||||
public delegate void OnFailed();
|
public delegate void OnFailed();
|
||||||
public event OnFailed onFailed;
|
public event OnFailed onFailed;
|
||||||
|
|
||||||
public AssetGraphNode()
|
public BaseImageNode()
|
||||||
{
|
{
|
||||||
guid = Guid.NewGuid().ToString();
|
guid = Guid.NewGuid().ToString();
|
||||||
|
|
||||||
|
/*Type t = this.GetType();
|
||||||
|
Debug.Log(t.Name);*/
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetNodeInputs()
|
public void SetNodeInputs()
|
||||||
@ -50,7 +51,7 @@ namespace AssetGraph.Nodes
|
|||||||
// Find the connection that leads to this input property
|
// Find the connection that leads to this input property
|
||||||
GraphConnection connection = default;
|
GraphConnection connection = default;
|
||||||
|
|
||||||
foreach (GraphConnection conn in asset.Connections)
|
foreach (var conn in asset.Connections)
|
||||||
{
|
{
|
||||||
if (conn.inputPort.nodeID == this.ID)
|
if (conn.inputPort.nodeID == this.ID)
|
||||||
{
|
{
|
13
Editor/Scripts/Editor/Nodes/Base/ExposedPropertyPort.cs
Normal file
13
Editor/Scripts/Editor/Nodes/Base/ExposedPropertyPort.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
using System;
|
||||||
|
using UnityEditor.Experimental.GraphView;
|
||||||
|
|
||||||
|
namespace ImageProcessingGraph.Editor
|
||||||
|
{
|
||||||
|
public class ExposedPropertyPort : Port
|
||||||
|
{
|
||||||
|
protected ExposedPropertyPort(Orientation portOrientation, Direction portDirection, Capacity portCapacity, Type type) : base(portOrientation, portDirection, portCapacity, type)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 31313dec455d4407bb6fffc7b167dabb
|
||||||
|
timeCreated: 1743744035
|
@ -6,7 +6,7 @@ using UnityEditor.UIElements;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
namespace AssetGraph.Core.GraphElements
|
namespace ImageProcessingGraph.Editor
|
||||||
{
|
{
|
||||||
[Serializable]
|
[Serializable]
|
||||||
public class GreyscaleValue
|
public class GreyscaleValue
|
3
Editor/Scripts/Editor/Nodes/NodeAttributes.meta
Normal file
3
Editor/Scripts/Editor/Nodes/NodeAttributes.meta
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: dbd7cd37cae147f3a54f12c52ef54217
|
||||||
|
timeCreated: 1742158168
|
@ -0,0 +1,17 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
using System.Collections;
|
||||||
|
|
||||||
|
public class NewMonoBehaviour : MonoBehaviour
|
||||||
|
{
|
||||||
|
// Use this for initialization
|
||||||
|
void Start()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update is called once per frame
|
||||||
|
void Update()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 78c0de359ceae406cb2985637a2e6c97
|
@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using ImageProcessingGraph.Editor.Unity_Image_Processing.Scripts.Editor.Windows;
|
||||||
|
|
||||||
namespace AssetGraph.Core.Attributes
|
namespace ImageProcessingGraph.Editor.Nodes.NodeAttributes
|
||||||
{
|
{
|
||||||
[AttributeUsage(AttributeTargets.Class)]
|
[AttributeUsage(AttributeTargets.Class)]
|
||||||
public class NodeInfoAttribute : Attribute
|
public class NodeInfoAttribute : Attribute
|
||||||
@ -9,46 +10,40 @@ namespace AssetGraph.Core.Attributes
|
|||||||
private string menuItem;
|
private string menuItem;
|
||||||
private string ussPath;
|
private string ussPath;
|
||||||
private Type editorType;
|
private Type editorType;
|
||||||
private string docuementationURL;
|
|
||||||
|
|
||||||
public string Title => name;
|
public string Title => name;
|
||||||
public string MenuItem => menuItem;
|
public string MenuItem => menuItem;
|
||||||
public string UssPath => ussPath;
|
public string UssPath => ussPath;
|
||||||
public Type EditorType => editorType;
|
public Type EditorType => editorType;
|
||||||
public string DocumentationationURL => docuementationURL;
|
|
||||||
|
|
||||||
public NodeInfoAttribute(string name, string menuItem = "", bool requiresImage = false, string ussPath = null, Type editorType = null, string docuementationURL = null)
|
public NodeInfoAttribute(string name, string menuItem = "", bool requiresImage = false, string ussPath = null, Type editorType = null)
|
||||||
{
|
{
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.menuItem = menuItem;
|
this.menuItem = menuItem;
|
||||||
this.ussPath = ussPath;
|
this.ussPath = ussPath;
|
||||||
this.editorType = editorType;
|
this.editorType = editorType;
|
||||||
this.docuementationURL = docuementationURL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Base type for Input and Output attributes
|
[AttributeUsage(AttributeTargets.Field)]
|
||||||
public abstract class PortAttribute : Attribute
|
public class Input : Attribute
|
||||||
{
|
{
|
||||||
public string Label { get; }
|
public string Label { get; }
|
||||||
|
|
||||||
protected PortAttribute(string label)
|
public Input(string _label)
|
||||||
{
|
{
|
||||||
Label = label;
|
Label = _label;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Input attribute inherits from base type
|
|
||||||
[AttributeUsage(AttributeTargets.Field)]
|
[AttributeUsage(AttributeTargets.Field)]
|
||||||
public class Input : PortAttribute
|
public class Output : Attribute
|
||||||
{
|
{
|
||||||
public Input(string label) : base(label) { }
|
public string Label { get; }
|
||||||
}
|
|
||||||
|
|
||||||
// Output attribute inherits from base type
|
public Output(string _label)
|
||||||
[AttributeUsage(AttributeTargets.Field)]
|
|
||||||
public class Output : PortAttribute
|
|
||||||
{
|
{
|
||||||
public Output(string label) : base(label) { }
|
Label = _label;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
3
Editor/Scripts/Editor/Nodes/String Nodes.meta
Normal file
3
Editor/Scripts/Editor/Nodes/String Nodes.meta
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 587f3b2d6fad453fbf6664066f807f21
|
||||||
|
timeCreated: 1745299284
|
18
Editor/Scripts/Editor/Nodes/String Nodes/StringAppend.cs
Normal file
18
Editor/Scripts/Editor/Nodes/String Nodes/StringAppend.cs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
using ImageProcessingGraph.Editor.Nodes.NodeAttributes;
|
||||||
|
|
||||||
|
namespace ImageProcessingGraph.Editor.Nodes.String_Nodes
|
||||||
|
{
|
||||||
|
[NodeInfo("String Append", "String/Append")]
|
||||||
|
public class StringAppend : BaseImageNode
|
||||||
|
{
|
||||||
|
[NodeAttributes.Input("String A")] public string baseString;
|
||||||
|
[NodeAttributes.Input("String B")] public string appendString;
|
||||||
|
|
||||||
|
[NodeAttributes.Output("Appended String")] public string output;
|
||||||
|
|
||||||
|
public override void Process()
|
||||||
|
{
|
||||||
|
this.output = baseString + appendString;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,19 +1,18 @@
|
|||||||
using AssetGraph.Core.Attributes;
|
using ImageProcessingGraph.Editor.Nodes.NodeAttributes;
|
||||||
using AssetGraph.Core.DataTypes;
|
|
||||||
using Unity.Burst;
|
using Unity.Burst;
|
||||||
using Unity.Collections;
|
using Unity.Collections;
|
||||||
using Unity.Jobs;
|
using Unity.Jobs;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace AssetGraph.Nodes
|
namespace ImageProcessingGraph.Editor.Nodes.Fun_Nodes.Texture
|
||||||
{
|
{
|
||||||
[NodeInfo("Invert Channel", "Adjustments/InvertChannel", true, docuementationURL: "https://git.sam-green.dev/Chromum/UnityImageProcessing_Package/wiki/Nodes%2FImage%2FInvertChannel")]
|
[NodeInfoAttribute("Invert Channel", "Adjustments/InvertChannel", true)]
|
||||||
public class ChannelInvertNode : AssetGraphNode
|
public class ChannelInvertNode : BaseImageNode
|
||||||
{
|
{
|
||||||
[Core.Attributes.Input("Input Channel")]
|
[NodeAttributes.Input("Input Channel")]
|
||||||
public SplitChannelData inputChannel;
|
public SplitChannelData inputChannel;
|
||||||
|
|
||||||
[Core.Attributes.Output("Output Channel")]
|
[NodeAttributes.Output("Output Channel")]
|
||||||
public SplitChannelData outputChannel;
|
public SplitChannelData outputChannel;
|
||||||
|
|
||||||
public override void Process()
|
public override void Process()
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
using AssetGraph.Core.Attributes;
|
using ImageProcessingGraph.Editor.Nodes.NodeAttributes;
|
||||||
using AssetGraph.Core.DataTypes;
|
|
||||||
using Unity.Burst;
|
using Unity.Burst;
|
||||||
using Unity.Collections;
|
using Unity.Collections;
|
||||||
using Unity.Jobs;
|
using Unity.Jobs;
|
||||||
@ -7,16 +6,16 @@ using UnityEngine;
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
namespace AssetGraph.Nodes
|
namespace ImageProcessingGraph.Editor.Nodes.Fun_Nodes.Texture
|
||||||
{
|
{
|
||||||
[NodeInfo("Desaturate", "Adjustments/Desaturate", true, docuementationURL: "https://git.sam-green.dev/Chromum/UnityImageProcessing_Package/wiki/Nodes%2FImage%2FDesaturate")]
|
[NodeInfoAttribute("Desaturate", "Adjustments/Desaturate", true)]
|
||||||
public class Texture2DDesaturate : AssetGraphNode
|
public class Texture2DDesaturate : BaseImageNode
|
||||||
{
|
{
|
||||||
[Core.Attributes.Input("")]
|
[NodeAttributes.Input("")]
|
||||||
public ImageData inputTexture;
|
public ImageData inputTexture; // Changed to ImageData
|
||||||
|
|
||||||
[Core.Attributes.Output("")]
|
[NodeAttributes.Output("")]
|
||||||
public ImageData outputTexture;
|
public ImageData outputTexture; // Changed to ImageData
|
||||||
|
|
||||||
public override void Process()
|
public override void Process()
|
||||||
{
|
{
|
||||||
|
@ -1,25 +1,26 @@
|
|||||||
using AssetGraph.Core.Attributes;
|
using ImageProcessingGraph.Editor.Nodes.NodeAttributes;
|
||||||
using AssetGraph.Core.DataTypes;
|
|
||||||
using Unity.Burst;
|
using Unity.Burst;
|
||||||
using Unity.Collections;
|
using Unity.Collections;
|
||||||
using Unity.Jobs;
|
using Unity.Jobs;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace AssetGraph.Nodes
|
namespace ImageProcessingGraph.Editor.Nodes.Fun_Nodes.Texture
|
||||||
{
|
{
|
||||||
[NodeInfo("Invert", "Adjustments/Invert", true, docuementationURL:"https://git.sam-green.dev/Chromum/UnityImageProcessing_Package/wiki/Nodes%2FImage%2FInvert")]
|
[NodeInfoAttribute("Invert", "Adjustments/Invert", true)]
|
||||||
public class Texture2DInvert : AssetGraphNode
|
public class Texture2DInvert : BaseImageNode
|
||||||
{
|
{
|
||||||
[Core.Attributes.Input("")]
|
[NodeAttributes.Input("")]
|
||||||
public ImageData inputTexture;
|
public ImageData inputTexture; // Changed to ImageData
|
||||||
|
|
||||||
[Core.Attributes.Output("")]
|
[NodeAttributes.Output("")]
|
||||||
public ImageData outputTexture;
|
public ImageData outputTexture; // Changed to ImageData
|
||||||
|
|
||||||
public override void Process()
|
public override void Process()
|
||||||
{
|
{
|
||||||
|
// Create an empty NativeArray for the output
|
||||||
NativeArray<Color32> output = new NativeArray<Color32>(inputTexture.PixelData.Length, Allocator.Persistent);
|
NativeArray<Color32> output = new NativeArray<Color32>(inputTexture.PixelData.Length, Allocator.Persistent);
|
||||||
|
|
||||||
|
// Create and run the InvertJob
|
||||||
InvertJob job = new InvertJob
|
InvertJob job = new InvertJob
|
||||||
{
|
{
|
||||||
pixels = inputTexture.PixelData,
|
pixels = inputTexture.PixelData,
|
||||||
@ -28,6 +29,7 @@ namespace AssetGraph.Nodes
|
|||||||
|
|
||||||
job.Run();
|
job.Run();
|
||||||
|
|
||||||
|
// Store the result in the outputImage as an ImageData instance
|
||||||
outputTexture = new ImageData(output, (inputTexture.Width, inputTexture.Height), inputTexture.isRGBA);
|
outputTexture = new ImageData(output, (inputTexture.Width, inputTexture.Height), inputTexture.isRGBA);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -35,13 +37,14 @@ namespace AssetGraph.Nodes
|
|||||||
[BurstCompile]
|
[BurstCompile]
|
||||||
public struct InvertJob : IJob
|
public struct InvertJob : IJob
|
||||||
{
|
{
|
||||||
[ReadOnly] public NativeArray<Color32> pixels;
|
[ReadOnly] public NativeArray<Color32> pixels; // Input pixels
|
||||||
[WriteOnly] public NativeArray<Color32> outputPixels;
|
[WriteOnly] public NativeArray<Color32> outputPixels; // Output pixels
|
||||||
|
|
||||||
public void Execute()
|
public void Execute()
|
||||||
{
|
{
|
||||||
int length = pixels.Length;
|
int length = pixels.Length;
|
||||||
|
|
||||||
|
// Invert each pixel color
|
||||||
for (int i = 0; i < length; i++)
|
for (int i = 0; i < length; i++)
|
||||||
{
|
{
|
||||||
Color32 pixel = pixels[i];
|
Color32 pixel = pixels[i];
|
||||||
|
@ -1,28 +1,27 @@
|
|||||||
using AssetGraph.Core.Attributes;
|
using ImageProcessingGraph.Editor.Nodes.NodeAttributes;
|
||||||
using AssetGraph.Core.DataTypes;
|
|
||||||
using Unity.Burst;
|
using Unity.Burst;
|
||||||
using Unity.Collections;
|
using Unity.Collections;
|
||||||
using Unity.Jobs;
|
using Unity.Jobs;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace AssetGraph.Nodes
|
namespace ImageProcessingGraph.Editor.Nodes.Fun_Nodes.Texture
|
||||||
{
|
{
|
||||||
[NodeInfo("RGBA Combine", "Channels/RGBA Combine", true, docuementationURL:"https://git.sam-green.dev/Chromum/UnityImageProcessing_Package/wiki/Nodes%2FImage%2FRGBACombine")]
|
[NodeInfo("RGBA Combine", "Channels/RGBA Combine", true)]
|
||||||
public class RGBASCombine : AssetGraphNode
|
public class RGBASCombine : BaseImageNode
|
||||||
{
|
{
|
||||||
[Core.Attributes.Input("R")]
|
[NodeAttributes.Input("R")]
|
||||||
public SplitChannelData r;
|
public SplitChannelData r;
|
||||||
|
|
||||||
[Core.Attributes.Input("G")]
|
[NodeAttributes.Input("G")]
|
||||||
public SplitChannelData g;
|
public SplitChannelData g;
|
||||||
|
|
||||||
[Core.Attributes.Input("B")]
|
[NodeAttributes.Input("B")]
|
||||||
public SplitChannelData b;
|
public SplitChannelData b;
|
||||||
|
|
||||||
[Core.Attributes.Input("A")]
|
[NodeAttributes.Input("A")]
|
||||||
public SplitChannelData a;
|
public SplitChannelData a;
|
||||||
|
|
||||||
[Core.Attributes.Output("")]
|
[NodeAttributes.Output("")]
|
||||||
public ImageData inputTexture;
|
public ImageData inputTexture;
|
||||||
|
|
||||||
// Job struct for combining RGBA channels
|
// Job struct for combining RGBA channels
|
||||||
|
@ -1,25 +1,24 @@
|
|||||||
using AssetGraph.Core.Attributes;
|
using ImageProcessingGraph.Editor.Nodes.NodeAttributes;
|
||||||
using AssetGraph.Core.DataTypes;
|
|
||||||
using Unity.Burst;
|
using Unity.Burst;
|
||||||
using Unity.Collections;
|
using Unity.Collections;
|
||||||
using Unity.Jobs;
|
using Unity.Jobs;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace AssetGraph.Nodes
|
namespace ImageProcessingGraph.Editor.Nodes.Fun_Nodes.Texture
|
||||||
{
|
{
|
||||||
[NodeInfo("RGBA Split", "Channels/RGBA Split", true, docuementationURL:"https://git.sam-green.dev/Chromum/UnityImageProcessing_Package/wiki/Nodes%2FImage%2FRGBASplit")]
|
[NodeInfoAttribute("RGBA Split", "Channels/RGBA Split", true)]
|
||||||
public class RGBASplit : AssetGraphNode
|
public class RGBASplit : BaseImageNode
|
||||||
{
|
{
|
||||||
[Core.Attributes.Input("")]
|
[NodeAttributes.Input("")]
|
||||||
public ImageData inputTexture;
|
public ImageData inputTexture;
|
||||||
|
|
||||||
[Core.Attributes.Output("R")]
|
[NodeAttributes.Output("R")]
|
||||||
public SplitChannelData r;
|
public SplitChannelData r;
|
||||||
[Core.Attributes.Output("G")]
|
[NodeAttributes.Output("G")]
|
||||||
public SplitChannelData g;
|
public SplitChannelData g;
|
||||||
[Core.Attributes.Output("B")]
|
[NodeAttributes.Output("B")]
|
||||||
public SplitChannelData b;
|
public SplitChannelData b;
|
||||||
[Core.Attributes.Output("A")]
|
[NodeAttributes.Output("A")]
|
||||||
public SplitChannelData a;
|
public SplitChannelData a;
|
||||||
|
|
||||||
public override void Process()
|
public override void Process()
|
||||||
|
@ -1,22 +1,21 @@
|
|||||||
using AssetGraph.Core.Attributes;
|
using ImageProcessingGraph.Editor.Nodes.NodeAttributes;
|
||||||
using AssetGraph.Core.DataTypes;
|
|
||||||
using Unity.Burst;
|
using Unity.Burst;
|
||||||
using Unity.Collections;
|
using Unity.Collections;
|
||||||
using Unity.Jobs;
|
using Unity.Jobs;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace AssetGraph.Nodes
|
namespace ImageProcessingGraph.Editor.Nodes.Fun_Nodes.Texture
|
||||||
{
|
{
|
||||||
[NodeInfo("Get Dimensions", "Dimensions/Get Dimensions", false, docuementationURL:"https://git.sam-green.dev/Chromum/UnityImageProcessing_Package/wiki/Nodes%2FImage%2FGetDimensions")]
|
[NodeInfoAttribute("Get Dimensions", "Dimensions/Get Dimensions", false)]
|
||||||
public class TextureGetDimensions : AssetGraphNode
|
public class TextureGetDimensions : BaseImageNode
|
||||||
{
|
{
|
||||||
[Core.Attributes.Input("")]
|
[NodeAttributes.Input("")]
|
||||||
public ImageData inputTexture;
|
public ImageData inputTexture;
|
||||||
|
|
||||||
[Core.Attributes.Output("Width")]
|
[NodeAttributes.Output("Width")]
|
||||||
public int width;
|
public int width;
|
||||||
|
|
||||||
[Core.Attributes.Output("Height")]
|
[NodeAttributes.Output("Height")]
|
||||||
public int height;
|
public int height;
|
||||||
|
|
||||||
public override void Process()
|
public override void Process()
|
||||||
|
@ -1,18 +1,17 @@
|
|||||||
using System.ComponentModel.Composition.Primitives;
|
using System.ComponentModel.Composition.Primitives;
|
||||||
using AssetGraph.Core.Attributes;
|
using ImageProcessingGraph.Editor.Nodes.NodeAttributes;
|
||||||
using AssetGraph.Core.DataTypes;
|
|
||||||
using Unity.Collections;
|
using Unity.Collections;
|
||||||
using UnityEditor;
|
using UnityEditor;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace AssetGraph.Nodes
|
namespace ImageProcessingGraph.Editor.Nodes.Output
|
||||||
{
|
{
|
||||||
[NodeInfo("Texture Export", "Export/Texture Export", true,docuementationURL:"https://git.sam-green.dev/Chromum/UnityImageProcessing_Package/wiki/Nodes%2FImage%2FTexture2DOutput")]
|
[NodeInfo("Texture Export", "Export/Texture Export", true)]
|
||||||
public class Texture2DOutput : AssetGraphNode
|
public class Texture2DOutput : BaseImageNode
|
||||||
{
|
{
|
||||||
[Core.Attributes.Input("")] public ImageData inputPixels;
|
[NodeAttributes.Input("")] public ImageData inputPixels;
|
||||||
[Core.Attributes.Input("File Name")] public string fileName;
|
[NodeAttributes.Input("File Name")] public string fileName;
|
||||||
[Core.Attributes.Input("File Directory")] public string fileDirectory;
|
[NodeAttributes.Input("File Directory")] public string fileDirectory;
|
||||||
|
|
||||||
public enum ExportType
|
public enum ExportType
|
||||||
{
|
{
|
||||||
@ -20,10 +19,10 @@ namespace AssetGraph.Nodes
|
|||||||
PNG
|
PNG
|
||||||
}
|
}
|
||||||
|
|
||||||
[Core.Attributes.Input("Export Type")] public ExportType exportType;
|
[NodeAttributes.Input("Export Type")] public ExportType exportType;
|
||||||
[Core.Attributes.Input("Texture Type")] public TextureImporterType textureType;
|
[NodeAttributes.Input("Texture Type")] public TextureImporterType textureType;
|
||||||
|
|
||||||
[Core.Attributes.Output("Output Texture")] public Texture2D textureOutput;
|
[NodeAttributes.Output("Output Texture")] public Texture2D textureOutput;
|
||||||
|
|
||||||
public override void Process()
|
public override void Process()
|
||||||
{
|
{
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 077795206494544448685fbd8458fa0c
|
|
||||||
TextScriptImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,3 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: fd58cf45d01e429abcb9b8f4e3894b7a
|
|
||||||
timeCreated: 1746240608
|
|
@ -1,43 +0,0 @@
|
|||||||
using System.IO;
|
|
||||||
using System.Security.Policy;
|
|
||||||
using AssetGraph.Core.Attributes;
|
|
||||||
using UnityEditor;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace AssetGraph.Nodes
|
|
||||||
{
|
|
||||||
public class FromPathNode<T> : AssetGraphNode where T : UnityEngine.Object
|
|
||||||
{
|
|
||||||
[Core.Attributes.Input("Path")] public string path;
|
|
||||||
[Core.Attributes.Output("Output")] public T output;
|
|
||||||
|
|
||||||
public override void Process()
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(path))
|
|
||||||
{
|
|
||||||
throw new System.ArgumentException("Path is empty or null. Cannot load asset.");
|
|
||||||
}
|
|
||||||
|
|
||||||
output = AssetDatabase.LoadAssetAtPath<T>(path);
|
|
||||||
|
|
||||||
if (output == null)
|
|
||||||
{
|
|
||||||
throw new System.Exception($"Failed to load asset of type {typeof(T)} at path: {path}.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void CleanUp()
|
|
||||||
{
|
|
||||||
output = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[NodeInfo("Load Texture2D From path", "Load From Path/Texture2D", docuementationURL: "https://git.sam-green.dev/Chromum/UnityImageProcessing_Package/wiki/Nodes%2FImages%2FFromPathNode")]
|
|
||||||
public class Texture2DFromPath : FromPathNode<Texture2D> { }
|
|
||||||
|
|
||||||
[NodeInfo("Load Mesh From path", "Load From Path/Mesh", docuementationURL: "https://git.sam-green.dev/Chromum/UnityImageProcessing_Package/wiki/Nodes%2FImages%2FFromPathNode")]
|
|
||||||
public class MeshFromPath : FromPathNode<Mesh> { }
|
|
||||||
|
|
||||||
[NodeInfo("Load Prefab From path", "Load From Path/Prefab", docuementationURL: "https://git.sam-green.dev/Chromum/UnityImageProcessing_Package/wiki/Nodes%2FImages%2FFromPathNode")]
|
|
||||||
public class PrefabFromPath : FromPathNode<GameObject> { }
|
|
||||||
}
|
|
@ -1,3 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: dbdf66c38fa94127a4665bf6fd1ac011
|
|
||||||
timeCreated: 1746240631
|
|
@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: c2fcf5cdfdc07ba479efe9544501e5e6
|
|
||||||
TextScriptImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,23 +1,22 @@
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using AssetGraph.Core.Attributes;
|
using ImageProcessingGraph.Editor.Nodes.NodeAttributes;
|
||||||
using AssetGraph.Core.DataTypes;
|
|
||||||
using Unity.Collections;
|
using Unity.Collections;
|
||||||
using UnityEditor;
|
using UnityEditor;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace AssetGraph.Nodes
|
namespace ImageProcessingGraph.Editor.Nodes.Import_Nodes
|
||||||
{
|
{
|
||||||
[NodeInfo("Texture Import", "Imports/Import Texture", docuementationURL:"https://git.sam-green.dev/Chromum/UnityImageProcessing_Package/wiki/Nodes%2FImage%2FTexture2DImport")]
|
[NodeInfo("Texture Import", "Imports/Import Texture")]
|
||||||
public class Texture2DImport : AssetGraphNode
|
public class Texture2DImport : BaseImageNode
|
||||||
{
|
{
|
||||||
[Core.Attributes.Input("")]
|
[NodeAttributes.Input("")]
|
||||||
public Texture2D textureImport;
|
public Texture2D textureImport;
|
||||||
|
|
||||||
[Core.Attributes.Output("")]
|
[NodeAttributes.Output("")]
|
||||||
public ImageData textureOutput;
|
public ImageData textureOutput;
|
||||||
[Core.Attributes.Output("File Name")]
|
[NodeAttributes.Output("File Name")]
|
||||||
public string fileName;
|
public string fileName;
|
||||||
[Core.Attributes.Output("File Directory")]
|
[NodeAttributes.Output("File Directory")]
|
||||||
public string filePath;
|
public string filePath;
|
||||||
|
|
||||||
public override void Process()
|
public override void Process()
|
||||||
|
@ -1,25 +1,23 @@
|
|||||||
using AssetGraph.Core.Attributes;
|
using ImageProcessingGraph.Editor.Nodes.NodeAttributes;
|
||||||
using AssetGraph.Core.DataTypes;
|
|
||||||
using AssetGraph.Core.GraphElements;
|
|
||||||
using Unity.Burst;
|
using Unity.Burst;
|
||||||
using Unity.Collections;
|
using Unity.Collections;
|
||||||
using Unity.Jobs;
|
using Unity.Jobs;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace AssetGraph.Nodes
|
namespace ImageProcessingGraph.Editor.Nodes.Types.Image.Utilities
|
||||||
{
|
{
|
||||||
public class SingleChannelColor
|
public class SingleChannelColor
|
||||||
{
|
{
|
||||||
[NodeInfo("Channel Color", "Utility/Channel Color", false, docuementationURL:"https://git.sam-green.dev/Chromum/UnityImageProcessing_Package/wiki/Nodes%2FImages%2FSingleChannelColor")]
|
[NodeInfoAttribute("Channel Color", "Utility/Channel Color", false)]
|
||||||
public class SingleColorChannel : AssetGraphNode
|
public class SingleColorChannel : BaseImageNode
|
||||||
{
|
{
|
||||||
[Core.Attributes.Input("Color")] public GreyscaleValue range;
|
[NodeAttributes.Input("Color")] public GreyscaleValue range;
|
||||||
|
|
||||||
[Core.Attributes.Input("Width")] public int Width;
|
[NodeAttributes.Input("Width")] public int Width;
|
||||||
|
|
||||||
[Core.Attributes.Input("Height")] public int Height;
|
[NodeAttributes.Input("Height")] public int Height;
|
||||||
|
|
||||||
[Core.Attributes.Output("Color")] public SplitChannelData OutputColor;
|
[NodeAttributes.Output("Color")] public SplitChannelData OutputColor;
|
||||||
|
|
||||||
public override void Process()
|
public override void Process()
|
||||||
{
|
{
|
||||||
|
@ -1,17 +1,16 @@
|
|||||||
using AssetGraph.Core.Attributes;
|
using ImageProcessingGraph.Editor.Nodes.NodeAttributes;
|
||||||
using AssetGraph.Core.DataTypes;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using Unity.Collections;
|
using Unity.Collections;
|
||||||
using Unity.Jobs;
|
using Unity.Jobs;
|
||||||
using Unity.Burst;
|
using Unity.Burst;
|
||||||
|
|
||||||
namespace AssetGraph.Nodes
|
namespace ImageProcessingGraph.Editor.Nodes.Types.Image.Utilities.ViewNode
|
||||||
{
|
{
|
||||||
[NodeInfo("View Texture", "Utility/View Texture", false, null , editorType: typeof(ViewTextureNodeEditor), docuementationURL: "https://git.sam-green.dev/Chromum/UnityImageProcessing_Package/wiki/Nodes%2FImage%2FViewImageNode")]
|
[NodeInfo("View Texture", "Utility/View Texture", false, null , editorType: typeof(ViewTextureNodeEditor))]
|
||||||
public partial class ViewTextureNode : AssetGraphNode
|
public partial class ViewTextureNode : BaseImageNode
|
||||||
{
|
{
|
||||||
[Core.Attributes.Input("Texture")] public Texture2D texture;
|
[NodeAttributes.Input("Texture")] public Texture2D texture;
|
||||||
[Core.Attributes.Input("Image Data")] public ImageData imageData;
|
[NodeAttributes.Input("Image Data")] public ImageData imageData;
|
||||||
|
|
||||||
public delegate void OnImageUpdated();
|
public delegate void OnImageUpdated();
|
||||||
public OnImageUpdated onImageUpdated;
|
public OnImageUpdated onImageUpdated;
|
||||||
|
@ -1,23 +1,22 @@
|
|||||||
using AssetGraph.Core;
|
using ImageProcessingGraph.Editor.Unity_Image_Processing.Scripts.Editor.Windows;
|
||||||
using UnityEditor.UIElements;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UIElements;
|
using UnityEngine.UIElements;
|
||||||
|
|
||||||
namespace AssetGraph.Nodes
|
namespace ImageProcessingGraph.Editor.Nodes.Types.Image.Utilities.ViewNode
|
||||||
{
|
{
|
||||||
public class ViewTextureNodeEditor : AssetGraphNodeEditor
|
public class ViewTextureNodeEditor : ImageProcessingGraphNodeVisual
|
||||||
{
|
{
|
||||||
private UnityEngine.UIElements.Image viewableImage;
|
private UnityEngine.UIElements.Image viewableImage;
|
||||||
private Foldout foldout;
|
private Foldout foldout;
|
||||||
private VisualElement buttonRow;
|
private VisualElement buttonRow;
|
||||||
|
|
||||||
public ViewTextureNodeEditor(AssetGraphNode node, AssetGraphViewWindow window) : base(node, window)
|
public ViewTextureNodeEditor(BaseImageNode node, ImageProcessingGraphViewWindow window) : base(node, window)
|
||||||
{
|
{
|
||||||
//Port 0 is Texture2D
|
//Port 0 is Texture2D
|
||||||
//Port 1 is ImageData
|
//Port 1 is ImageData
|
||||||
|
|
||||||
AssetGraphPort tex2DPort = InputPorts[0] as AssetGraphPort;
|
IPTPort tex2DPort = InputPorts[0] as IPTPort;
|
||||||
AssetGraphPort imageDataPort = InputPorts[1] as AssetGraphPort;
|
IPTPort imageDataPort = InputPorts[1] as IPTPort;
|
||||||
|
|
||||||
tex2DPort.OnPortConnected += () => { imageDataPort.style.display = DisplayStyle.None; };
|
tex2DPort.OnPortConnected += () => { imageDataPort.style.display = DisplayStyle.None; };
|
||||||
|
|
||||||
@ -51,9 +50,6 @@ namespace AssetGraph.Nodes
|
|||||||
|
|
||||||
viewImageNode.onImageUpdated += () => { viewableImage.image = viewImageNode.texture; };
|
viewImageNode.onImageUpdated += () => { viewableImage.image = viewImageNode.texture; };
|
||||||
|
|
||||||
Toolbar tb = new Toolbar();
|
|
||||||
tb.style.height = 32;
|
|
||||||
|
|
||||||
buttonRow = new VisualElement
|
buttonRow = new VisualElement
|
||||||
{
|
{
|
||||||
style =
|
style =
|
||||||
@ -74,11 +70,10 @@ namespace AssetGraph.Nodes
|
|||||||
text = channel
|
text = channel
|
||||||
};
|
};
|
||||||
btn.style.flexGrow = 1;
|
btn.style.flexGrow = 1;
|
||||||
tb.Add(btn);
|
buttonRow.Add(btn);
|
||||||
}
|
}
|
||||||
|
|
||||||
// foldout.Add(buttonRow);
|
foldout.Add(buttonRow);
|
||||||
foldout.Add(tb);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnChannelClicked(ViewTextureNode viewNode, string channel)
|
private void OnChannelClicked(ViewTextureNode viewNode, string channel)
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 899a77acab6b46d9af23756a397e7eea
|
|
||||||
timeCreated: 1746228396
|
|
@ -1,41 +0,0 @@
|
|||||||
using AssetGraph.Nodes;
|
|
||||||
using UnityEngine;
|
|
||||||
using AssetGraph.Core;
|
|
||||||
using AssetGraph.Core.Attributes;
|
|
||||||
|
|
||||||
namespace AssetGraph.Nodes
|
|
||||||
{
|
|
||||||
public class VariableNodeBase : AssetGraphNode
|
|
||||||
{
|
|
||||||
[Core.Attributes.Input("Variable Name")] public string variableName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public class VariableNode<T> : VariableNodeBase
|
|
||||||
{
|
|
||||||
public T input;
|
|
||||||
[Core.Attributes.Output("Output")] public T output;
|
|
||||||
|
|
||||||
public override void Process()
|
|
||||||
{
|
|
||||||
if(input != null)
|
|
||||||
this.output = input;
|
|
||||||
else
|
|
||||||
throw new System.NullReferenceException($"Input to VariableNode<{typeof(T).Name}> is null");
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void CleanUp()
|
|
||||||
{
|
|
||||||
input = default;
|
|
||||||
output = default;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[NodeInfo("Texture2D Variable", "Variable/Texture2D", docuementationURL:"https://git.sam-green.dev/Chromum/UnityImageProcessing_Package/wiki/Nodes%2FImage%2FVariableNode")]
|
|
||||||
public class Texture2DVariableNode : VariableNode<Texture2D> { }
|
|
||||||
|
|
||||||
[NodeInfo("Mesh Variable", "Variable/Mesh", docuementationURL:"https://git.sam-green.dev/Chromum/UnityImageProcessing_Package/wiki/Nodes%2FImage%2FVariableNode")]
|
|
||||||
public class MeshVariableNode : VariableNode<Mesh> { }
|
|
||||||
|
|
||||||
[NodeInfo("Prefab Variable", "Variable/Prefab", docuementationURL:"https://git.sam-green.dev/Chromum/UnityImageProcessing_Package/wiki/Nodes%2FImage%2FVariableNode")]
|
|
||||||
public class PrefabVariableNode : VariableNode<GameObject> { }
|
|
||||||
}
|
|
@ -1,3 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: b10ad5cecfc74b548431deb876d3cb9a
|
|
||||||
timeCreated: 1746228592
|
|
@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 35175651a2c0f6947b7cc63fde04829f
|
|
||||||
TextScriptImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,58 +0,0 @@
|
|||||||
using System.IO;
|
|
||||||
using AssetGraph.Core;
|
|
||||||
using UnityEngine;
|
|
||||||
using UnityEditor;
|
|
||||||
using AssetGraph.Core.Attributes;
|
|
||||||
using AssetGraph.Nodes;
|
|
||||||
using UnityEngine.UIElements;
|
|
||||||
|
|
||||||
namespace ImageProcessingGraph.Editor.Nodes.MazStuff
|
|
||||||
{
|
|
||||||
[NodeInfo("Debug Log", "Debug/Debug Log", editorType: typeof(DebugLogNodeEditor))]
|
|
||||||
public class DebugLogNode : AssetGraphNode
|
|
||||||
{
|
|
||||||
[AssetGraph.Core.Attributes.Input("Log Text")]
|
|
||||||
public string logText;
|
|
||||||
|
|
||||||
public delegate void OnNodeUpdated();
|
|
||||||
public OnNodeUpdated onNodeUpdated;
|
|
||||||
|
|
||||||
public override void Process()
|
|
||||||
{
|
|
||||||
Debug.Log(logText);
|
|
||||||
onNodeUpdated?.Invoke();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class DebugLogNodeEditor : AssetGraphNodeEditor
|
|
||||||
{
|
|
||||||
DebugLogNode logNode;
|
|
||||||
Label label;
|
|
||||||
|
|
||||||
public DebugLogNodeEditor(AssetGraphNode node, AssetGraphViewWindow window) : base(node, window)
|
|
||||||
{
|
|
||||||
logNode = node as DebugLogNode;
|
|
||||||
logNode.onNodeUpdated += UpdateEditor;
|
|
||||||
label = new Label();
|
|
||||||
label.style.flexGrow = 1;
|
|
||||||
label.style.flexShrink = 1;
|
|
||||||
label.style.paddingBottom = label.style.paddingTop = label.style.paddingLeft = label.style.paddingRight = 6;
|
|
||||||
label.style.backgroundColor = new Color(0.24705f, 0.24705f, 0.24705f, 0.8039216f);
|
|
||||||
label.style.whiteSpace = WhiteSpace.Normal;
|
|
||||||
|
|
||||||
VisualElement bar = new VisualElement();
|
|
||||||
bar.name = "divider";
|
|
||||||
bar.AddToClassList("horizontal");
|
|
||||||
|
|
||||||
var contents = this.Q("contents");
|
|
||||||
|
|
||||||
contents.Add(bar);
|
|
||||||
contents.Add(label);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void UpdateEditor()
|
|
||||||
{
|
|
||||||
label.text = logNode.logText;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: ee2323729ea6fa84788137af3807d8b7
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,26 +0,0 @@
|
|||||||
using System.IO;
|
|
||||||
using AssetGraph.Core.Attributes;
|
|
||||||
using AssetGraph.Nodes;
|
|
||||||
using UnityEngine;
|
|
||||||
using UnityEditor;
|
|
||||||
|
|
||||||
namespace ImageProcessingGraph.Editor.Nodes.MazStuff
|
|
||||||
{
|
|
||||||
[NodeInfo("Import Text", "Imports/Import Text")]
|
|
||||||
public class ImportTextNode : AssetGraphNode
|
|
||||||
{
|
|
||||||
[AssetGraph.Core.Attributes.Input("File Name")]
|
|
||||||
public string fileName;
|
|
||||||
|
|
||||||
[AssetGraph.Core.Attributes.Input("Directory")]
|
|
||||||
public string directory;
|
|
||||||
|
|
||||||
[AssetGraph.Core.Attributes.Output("Text")]
|
|
||||||
public string outputText;
|
|
||||||
|
|
||||||
public override void Process()
|
|
||||||
{
|
|
||||||
outputText = File.ReadAllText(Path.Combine(directory, fileName));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 455f8a7df4c9c2e4691f68b537e29573
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,69 +0,0 @@
|
|||||||
using AssetGraph.Core.Attributes;
|
|
||||||
|
|
||||||
|
|
||||||
namespace AssetGraph.Nodes
|
|
||||||
{
|
|
||||||
[NodeInfo("String Append", "String/Append", docuementationURL: "https://git.sam-green.dev/Chromum/UnityImageProcessing_Package/wiki/Nodes/String/Append")]
|
|
||||||
public class StringAppend : AssetGraphNode
|
|
||||||
{
|
|
||||||
[Core.Attributes.Input("String A")] public string baseString;
|
|
||||||
[Core.Attributes.Input("String B")] public string appendString;
|
|
||||||
|
|
||||||
[Core.Attributes.Output("Appended String")] public string output;
|
|
||||||
|
|
||||||
public override void Process()
|
|
||||||
{
|
|
||||||
this.output = baseString + appendString;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[NodeInfo("String Replace", "String/Replace", docuementationURL: "https://git.sam-green.dev/Chromum/UnityImageProcessing_Package/wiki/Nodes/String/Replace")]
|
|
||||||
public class StringReplace : AssetGraphNode
|
|
||||||
{
|
|
||||||
[Core.Attributes.Input("Original String")] public string original;
|
|
||||||
[Core.Attributes.Input("Old Value")] public string oldValue;
|
|
||||||
[Core.Attributes.Input("New Value")] public string newValue;
|
|
||||||
|
|
||||||
[Core.Attributes.Output("Replaced String")] public string output;
|
|
||||||
|
|
||||||
public override void Process()
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrEmpty(original) && oldValue != null)
|
|
||||||
output = original.Replace(oldValue, newValue);
|
|
||||||
else
|
|
||||||
output = original;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[NodeInfo("String Split", "String/Split", docuementationURL: "https://git.sam-green.dev/Chromum/UnityImageProcessing_Package/wiki/Nodes/String/Split")]
|
|
||||||
public class StringSplit : AssetGraphNode
|
|
||||||
{
|
|
||||||
[Input("Source String")] public string source;
|
|
||||||
[Input("Delimiter")] public string delimiter;
|
|
||||||
|
|
||||||
[Core.Attributes.Output("Before Delimiter")] public string before;
|
|
||||||
[Core.Attributes.Output("After Delimiter")] public string after;
|
|
||||||
|
|
||||||
public override void Process()
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(source) || string.IsNullOrEmpty(delimiter))
|
|
||||||
{
|
|
||||||
before = source;
|
|
||||||
after = string.Empty;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int index = source.IndexOf(delimiter);
|
|
||||||
if (index >= 0)
|
|
||||||
{
|
|
||||||
before = source.Substring(0, index);
|
|
||||||
after = source.Substring(index + delimiter.Length);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
before = source;
|
|
||||||
after = string.Empty;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,3 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: e4a21d5960ac4b858705aec0bdaddab4
|
|
||||||
timeCreated: 1746343737
|
|
@ -1,3 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: b77f4983d61d4a2ab1916ea59a0ec6fa
|
|
||||||
timeCreated: 1746343741
|
|
@ -1,31 +0,0 @@
|
|||||||
using AssetGraph.Core;
|
|
||||||
using AssetGraph.Core.Attributes;
|
|
||||||
using UnityEditor;
|
|
||||||
using UnityEngine;
|
|
||||||
using UnityEngine.UIElements;
|
|
||||||
|
|
||||||
namespace AssetGraph.Nodes
|
|
||||||
{
|
|
||||||
[NodeInfo("", "Utility/Connection", false, null , editorType: typeof(GenericConnectionEditor), docuementationURL: "https://git.sam-green.dev/Chromum/UnityImageProcessing_Package/wiki/Nodes%2FUtils%2FGenericConnection")]
|
|
||||||
public class GenericConnection : AssetGraphNode
|
|
||||||
{
|
|
||||||
private System.Type internalType;
|
|
||||||
public System.Type InternalType { get { return internalType; } set { internalType = value; } }
|
|
||||||
|
|
||||||
[Core.Attributes.Input(" ")] public object input;
|
|
||||||
[Core.Attributes.Output(" ")] public object output;
|
|
||||||
|
|
||||||
public override void Process()
|
|
||||||
{
|
|
||||||
this.output = this.input;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class GenericConnectionEditor : AssetGraphNodeEditor
|
|
||||||
{
|
|
||||||
public GenericConnectionEditor(AssetGraphNode node, AssetGraphViewWindow window) : base(node, window)
|
|
||||||
{
|
|
||||||
this.Q("title").style.display = DisplayStyle.None;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,3 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: c3fb7dc03aa647a8a99146ef19bb663e
|
|
||||||
timeCreated: 1746343749
|
|
@ -1,25 +0,0 @@
|
|||||||
using System.IO;
|
|
||||||
using UnityEngine;
|
|
||||||
using UnityEditor;
|
|
||||||
using AssetGraph.Core.Attributes;
|
|
||||||
using AssetGraph.Nodes;
|
|
||||||
|
|
||||||
namespace ImageProcessingGraph.Editor.Nodes.MazStuff
|
|
||||||
{
|
|
||||||
[NodeInfo("Create Directory", "Directory/Create Directory")]
|
|
||||||
public class CreateDirectoryNode : AssetGraphNode
|
|
||||||
{
|
|
||||||
[AssetGraph.Core.Attributes.Input("Directory")] public string inputDirectory;
|
|
||||||
|
|
||||||
[AssetGraph.Core.Attributes.Output("Directory")] public string outputDirectory;
|
|
||||||
|
|
||||||
public override void Process()
|
|
||||||
{
|
|
||||||
if (!Directory.Exists(inputDirectory))
|
|
||||||
{
|
|
||||||
Directory.CreateDirectory(inputDirectory);
|
|
||||||
}
|
|
||||||
outputDirectory = inputDirectory;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 8a32e947621c08940b8f9c68c3bc0bdc
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,62 +0,0 @@
|
|||||||
using System.IO;
|
|
||||||
using UnityEngine;
|
|
||||||
using UnityEditor;
|
|
||||||
using AssetGraph.Core.Attributes;
|
|
||||||
using AssetGraph.Nodes;
|
|
||||||
|
|
||||||
namespace ImageProcessingGraph.Editor.Nodes.MazStuff
|
|
||||||
{
|
|
||||||
[NodeInfo("Create Prefab", "Prefab/Create")]
|
|
||||||
public class CreatePrefabNode : AssetGraphNode
|
|
||||||
{
|
|
||||||
[AssetGraph.Core.Attributes.Input("Prefab Name")]
|
|
||||||
public string prefabName;
|
|
||||||
|
|
||||||
[AssetGraph.Core.Attributes.Input("Directory")]
|
|
||||||
public string directory;
|
|
||||||
|
|
||||||
[AssetGraph.Core.Attributes.Input("")]
|
|
||||||
public Mesh mesh;
|
|
||||||
|
|
||||||
[AssetGraph.Core.Attributes.Input("Submesh Count")]
|
|
||||||
public int submeshCount = 1;
|
|
||||||
|
|
||||||
[AssetGraph.Core.Attributes.Input("")]
|
|
||||||
public Material material;
|
|
||||||
|
|
||||||
[AssetGraph.Core.Attributes.Output("Prefab")]
|
|
||||||
public GameObject prefab;
|
|
||||||
|
|
||||||
public override void Process()
|
|
||||||
{
|
|
||||||
GameObject newGO = new GameObject(prefabName);
|
|
||||||
var prefabPath = Path.Combine(directory, $"{prefabName}.prefab");
|
|
||||||
PrefabUtility.SaveAsPrefabAsset(newGO, prefabPath);
|
|
||||||
Object.DestroyImmediate(newGO);
|
|
||||||
|
|
||||||
using (var editScope = new PrefabUtility.EditPrefabContentsScope(prefabPath))
|
|
||||||
{
|
|
||||||
var root = editScope.prefabContentsRoot;
|
|
||||||
var meshRenderer = root.AddComponent<MeshRenderer>();
|
|
||||||
var meshFilter = root.AddComponent<MeshFilter>();
|
|
||||||
meshFilter.sharedMesh = mesh;
|
|
||||||
if (submeshCount > 1)
|
|
||||||
{
|
|
||||||
Material[] materials = new Material[submeshCount];
|
|
||||||
for (int i = 0; i < submeshCount; i++)
|
|
||||||
{
|
|
||||||
materials[i] = material;
|
|
||||||
}
|
|
||||||
|
|
||||||
meshRenderer.sharedMaterials = materials;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
meshRenderer.sharedMaterial = material;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
prefab = AssetDatabase.LoadAssetAtPath<GameObject>(prefabPath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 851727f1cfe10de4b8073aa6a334518c
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,69 +0,0 @@
|
|||||||
using System.IO;
|
|
||||||
using AssetGraph.Core.Attributes;
|
|
||||||
using AssetGraph.Nodes;
|
|
||||||
using ImageProcessingGraph.Editor;
|
|
||||||
using UnityEditor;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace ImageProcessingGraph.Editor.Nodes.MazStuff
|
|
||||||
{
|
|
||||||
[NodeInfo("Model Import", "Imports/Import Model", true)]
|
|
||||||
public class ModelImportNode : AssetGraphNode
|
|
||||||
{
|
|
||||||
[AssetGraph.Core.Attributes.Input("Model")]
|
|
||||||
public GameObject modelImport;
|
|
||||||
|
|
||||||
[AssetGraph.Core.Attributes.Output("")]
|
|
||||||
public Mesh mesh;
|
|
||||||
|
|
||||||
[AssetGraph.Core.Attributes.Output("")]
|
|
||||||
public Material material;
|
|
||||||
|
|
||||||
[AssetGraph.Core.Attributes.Output("Model Name")]
|
|
||||||
public string modelName;
|
|
||||||
|
|
||||||
[AssetGraph.Core.Attributes.Output("Directory")]
|
|
||||||
public string directory;
|
|
||||||
|
|
||||||
public override void Process()
|
|
||||||
{
|
|
||||||
var modelPath = AssetDatabase.GetAssetPath(modelImport);
|
|
||||||
var allAssets = AssetDatabase.LoadAllAssetsAtPath(modelPath);
|
|
||||||
|
|
||||||
material = null;
|
|
||||||
mesh = null;
|
|
||||||
foreach (var asset in allAssets)
|
|
||||||
{
|
|
||||||
if (material && mesh) break;
|
|
||||||
|
|
||||||
if (!material && asset is Material foundMaterial)
|
|
||||||
{
|
|
||||||
material = foundMaterial;
|
|
||||||
}
|
|
||||||
if (!mesh && asset is Mesh foundMesh)
|
|
||||||
{
|
|
||||||
mesh = foundMesh;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
modelName = modelImport.name;
|
|
||||||
directory = Path.GetDirectoryName(modelPath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
[NodeInfo("Mesh Info", "Mesh/Mesh Info", true)]
|
|
||||||
public class MeshInfo : AssetGraphNode
|
|
||||||
{
|
|
||||||
[AssetGraph.Core.Attributes.Input("")]
|
|
||||||
public Mesh mesh;
|
|
||||||
|
|
||||||
[AssetGraph.Core.Attributes.Output("Submeshes")]
|
|
||||||
public int submeshes;
|
|
||||||
|
|
||||||
public override void Process()
|
|
||||||
{
|
|
||||||
submeshes = mesh.subMeshCount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 612cfa8fb6e00e14d9f78091cb61cdde
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,60 +0,0 @@
|
|||||||
using System.IO;
|
|
||||||
using AssetGraph.Core.Attributes;
|
|
||||||
using AssetGraph.Nodes;
|
|
||||||
using UnityEngine;
|
|
||||||
using UnityEditor;
|
|
||||||
|
|
||||||
namespace ImageProcessingGraph.Editor.Nodes.MazStuff
|
|
||||||
{
|
|
||||||
[NodeInfo("Material Get Name", "Material/Material Get Name")]
|
|
||||||
public class MaterialGetNameNode : AssetGraphNode
|
|
||||||
{
|
|
||||||
[AssetGraph.Core.Attributes.Input("")] public Material inputObject;
|
|
||||||
|
|
||||||
[AssetGraph.Core.Attributes.Output("Name")] public string objectName;
|
|
||||||
|
|
||||||
public override void Process()
|
|
||||||
{
|
|
||||||
objectName = inputObject.name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[NodeInfo("Mesh Get Name", "Mesh/Mesh Get Name")]
|
|
||||||
public class MeshGetNameNode : AssetGraphNode
|
|
||||||
{
|
|
||||||
[AssetGraph.Core.Attributes.Input("")] public Mesh inputObject;
|
|
||||||
|
|
||||||
[AssetGraph.Core.Attributes.Output("Name")] public string objectName;
|
|
||||||
|
|
||||||
public override void Process()
|
|
||||||
{
|
|
||||||
objectName = inputObject.name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[NodeInfo("Texture Get Name", "Texture/Texture Get Name")]
|
|
||||||
public class TextureGetNameNode : AssetGraphNode
|
|
||||||
{
|
|
||||||
[AssetGraph.Core.Attributes.Input("")] public Texture2D inputObject;
|
|
||||||
|
|
||||||
[AssetGraph.Core.Attributes.Output("Name")] public string objectName;
|
|
||||||
|
|
||||||
public override void Process()
|
|
||||||
{
|
|
||||||
objectName = inputObject.name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[NodeInfo("GameObject Get Name", "GameObject/GameObject Get Name")]
|
|
||||||
public class GameObjectGetNameNode : AssetGraphNode
|
|
||||||
{
|
|
||||||
[AssetGraph.Core.Attributes.Input("")] public GameObject inputObject;
|
|
||||||
|
|
||||||
[AssetGraph.Core.Attributes.Output("Name")] public string objectName;
|
|
||||||
|
|
||||||
public override void Process()
|
|
||||||
{
|
|
||||||
objectName = inputObject.name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 79f6818ae71efcd48a44d3fb422891bb
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,31 +0,0 @@
|
|||||||
using UnityEditor;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace AssetGraph.Core
|
|
||||||
{
|
|
||||||
[CustomEditor(typeof(AssetGraphData))]
|
|
||||||
public class AssetGraphDataEditor : UnityEditor.Editor
|
|
||||||
{
|
|
||||||
public override void OnInspectorGUI()
|
|
||||||
{
|
|
||||||
var assetGraphData = (AssetGraphData)target;
|
|
||||||
|
|
||||||
DrawButton("Open", () => AssetGraphEditorWindow.Open(assetGraphData));
|
|
||||||
DrawButton("Calculate Dependency Graph",
|
|
||||||
() =>
|
|
||||||
{
|
|
||||||
assetGraphData.runOrder =
|
|
||||||
assetGraphData.GetExecutionOrder(assetGraphData.Nodes, assetGraphData.Connections, true);
|
|
||||||
});
|
|
||||||
DrawButton("Run Graph", assetGraphData.RunGraph);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DrawButton(string label, System.Action action)
|
|
||||||
{
|
|
||||||
if (GUILayout.Button(label))
|
|
||||||
{
|
|
||||||
action?.Invoke();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,142 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
using ImageProcessingGraph.Editor;
|
|
||||||
using UnityEditor.Experimental.GraphView;
|
|
||||||
using UnityEngine;
|
|
||||||
using UnityEngine.UIElements;
|
|
||||||
|
|
||||||
namespace AssetGraph.Core
|
|
||||||
{
|
|
||||||
public class AssetGraphEdgeConnector : IEdgeConnectorListener
|
|
||||||
{
|
|
||||||
private readonly GraphViewChange graphViewChange;
|
|
||||||
private readonly List<Edge> edgesToCreate;
|
|
||||||
private readonly List<GraphElement> edgesToDelete;
|
|
||||||
private readonly AssetGraphViewWindow window;
|
|
||||||
|
|
||||||
public AssetGraphEdgeConnector(AssetGraphViewWindow window)
|
|
||||||
{
|
|
||||||
this.window = window;
|
|
||||||
edgesToCreate = new List<Edge>();
|
|
||||||
edgesToDelete = new List<GraphElement>();
|
|
||||||
graphViewChange = new GraphViewChange
|
|
||||||
{
|
|
||||||
edgesToCreate = edgesToCreate
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnDropOutsidePort(Edge edge, Vector2 position)
|
|
||||||
{
|
|
||||||
HandleSearchProvider(edge);
|
|
||||||
|
|
||||||
RemoveExistingConnections(edge);
|
|
||||||
|
|
||||||
if (edge.input?.node != null)
|
|
||||||
{
|
|
||||||
((AssetGraphNodeEditor)edge.input.node)
|
|
||||||
.ToggleExposedVariable((AssetGraphPort)edge.input, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnDrop(GraphView graphView, Edge edge)
|
|
||||||
{
|
|
||||||
RemoveExistingConnections(edge);
|
|
||||||
|
|
||||||
if (edge.input?.node != null)
|
|
||||||
{
|
|
||||||
((AssetGraphNodeEditor)edge.input.node)
|
|
||||||
.ToggleExposedVariable((AssetGraphPort)edge.input, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
UpdateConnections(graphView, edge);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void HandleSearchProvider(Edge edge)
|
|
||||||
{
|
|
||||||
// Set the target for the search provider
|
|
||||||
window.searchProvider.target = (VisualElement)window.focusController.focusedElement;
|
|
||||||
|
|
||||||
var mousePos = window.ChangeCoordinatesTo(window, window.cachedMousePos - window.Window.position.position);
|
|
||||||
var graphMousePosition = window.contentViewContainer.WorldToLocal(mousePos);
|
|
||||||
|
|
||||||
var searchProviderInstance =
|
|
||||||
ScriptableObject.CreateInstance<AssetGraphSearchProvider.CustomSearchProviderForEdge>();
|
|
||||||
searchProviderInstance.Init(window.searchProvider, edge, (AssetGraphPort)edge.input,
|
|
||||||
(AssetGraphPort)edge.output);
|
|
||||||
|
|
||||||
SearchWindow.Open(
|
|
||||||
new SearchWindowContext(GUIUtility.GUIToScreenPoint(Event.current.mousePosition)),
|
|
||||||
searchProviderInstance
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void RemoveExistingConnections(Edge edge)
|
|
||||||
{
|
|
||||||
// Collect and remove connections associated with the edge
|
|
||||||
var connectionsToRemove = new List<GraphConnection>();
|
|
||||||
foreach (var connection in window.asset.Connections)
|
|
||||||
{
|
|
||||||
if (connection.internalEdge == edge)
|
|
||||||
{
|
|
||||||
connectionsToRemove.Add(connection);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var connection in connectionsToRemove)
|
|
||||||
{
|
|
||||||
window.asset.Connections.Remove(connection);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UpdateConnections(GraphView graphView, Edge edge)
|
|
||||||
{
|
|
||||||
// Clear the list of created and deleted edges
|
|
||||||
edgesToCreate.Clear();
|
|
||||||
edgesToDelete.Clear();
|
|
||||||
|
|
||||||
// Add the current edge to edgesToCreate
|
|
||||||
edgesToCreate.Add(edge);
|
|
||||||
|
|
||||||
// Handle single-capacity input ports
|
|
||||||
if (edge.input.capacity == Port.Capacity.Single)
|
|
||||||
{
|
|
||||||
foreach (var connection in edge.input.connections)
|
|
||||||
{
|
|
||||||
if (connection != edge)
|
|
||||||
{
|
|
||||||
edgesToDelete.Add(connection);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle single-capacity output ports
|
|
||||||
if (edge.output.capacity == Port.Capacity.Single)
|
|
||||||
{
|
|
||||||
foreach (var connection in edge.output.connections)
|
|
||||||
{
|
|
||||||
if (connection != edge)
|
|
||||||
{
|
|
||||||
edgesToDelete.Add(connection);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete unwanted connections
|
|
||||||
if (edgesToDelete.Count > 0)
|
|
||||||
{
|
|
||||||
graphView.DeleteElements(edgesToDelete);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create new connections
|
|
||||||
var createdEdges = graphView.graphViewChanged != null
|
|
||||||
? graphView.graphViewChanged(graphViewChange).edgesToCreate
|
|
||||||
: edgesToCreate;
|
|
||||||
|
|
||||||
foreach (var createdEdge in createdEdges)
|
|
||||||
{
|
|
||||||
graphView.AddElement(createdEdge);
|
|
||||||
edge.input.Connect(createdEdge);
|
|
||||||
edge.output.Connect(createdEdge);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,82 +0,0 @@
|
|||||||
using System;
|
|
||||||
using UnityEditor;
|
|
||||||
using UnityEditor.Experimental.GraphView;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace AssetGraph.Core
|
|
||||||
{
|
|
||||||
public class AssetGraphEditorWindow : EditorWindow
|
|
||||||
{
|
|
||||||
[SerializeField] private AssetGraphData currentGraph;
|
|
||||||
[SerializeField] private SerializedObject serializedObject;
|
|
||||||
[SerializeField] private AssetGraphViewWindow currentView;
|
|
||||||
|
|
||||||
public AssetGraphData CurrentGraph => currentGraph;
|
|
||||||
|
|
||||||
public static void Open(AssetGraphData asset)
|
|
||||||
{
|
|
||||||
foreach (var window in Resources.FindObjectsOfTypeAll<AssetGraphEditorWindow>())
|
|
||||||
{
|
|
||||||
if (window.CurrentGraph == asset)
|
|
||||||
{
|
|
||||||
window.Focus();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var newWindow = CreateWindow<AssetGraphEditorWindow>(typeof(SceneView));
|
|
||||||
newWindow.Initialize(asset);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Initialize(AssetGraphData asset)
|
|
||||||
{
|
|
||||||
titleContent = new GUIContent(
|
|
||||||
asset.name,
|
|
||||||
EditorGUIUtility.ObjectContent(null, typeof(AssetGraphData)).image
|
|
||||||
);
|
|
||||||
Load(asset);
|
|
||||||
Focus();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnEnable()
|
|
||||||
{
|
|
||||||
if (currentGraph != null)
|
|
||||||
{
|
|
||||||
DrawGraph();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnGUI()
|
|
||||||
{
|
|
||||||
if (currentGraph != null)
|
|
||||||
{
|
|
||||||
hasUnsavedChanges = EditorUtility.IsDirty(currentGraph);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Load(AssetGraphData asset)
|
|
||||||
{
|
|
||||||
currentGraph = asset;
|
|
||||||
DrawGraph();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DrawGraph()
|
|
||||||
{
|
|
||||||
serializedObject = new SerializedObject(currentGraph);
|
|
||||||
currentView = new AssetGraphViewWindow(serializedObject, this)
|
|
||||||
{
|
|
||||||
graphViewChanged = OnGraphChanged
|
|
||||||
};
|
|
||||||
|
|
||||||
rootVisualElement.Clear();
|
|
||||||
rootVisualElement.style.flexGrow = 1;
|
|
||||||
rootVisualElement.Add(currentView);
|
|
||||||
}
|
|
||||||
|
|
||||||
private GraphViewChange OnGraphChanged(GraphViewChange graphViewChange)
|
|
||||||
{
|
|
||||||
EditorUtility.SetDirty(currentGraph);
|
|
||||||
return graphViewChange;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,281 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
|
||||||
using AssetGraph.Core.Attributes;
|
|
||||||
using AssetGraph.Core.GraphElements;
|
|
||||||
using AssetGraph.Nodes;
|
|
||||||
using UnityEditor;
|
|
||||||
using UnityEditor.Experimental.GraphView;
|
|
||||||
using UnityEditor.UIElements;
|
|
||||||
using UnityEngine;
|
|
||||||
using UnityEngine.UIElements;
|
|
||||||
using Input = AssetGraph.Core.Attributes.Input;
|
|
||||||
|
|
||||||
namespace AssetGraph.Core
|
|
||||||
{
|
|
||||||
public class AssetGraphNodeEditor : Node
|
|
||||||
{
|
|
||||||
private readonly StyleSheet defaultStyleSheet;
|
|
||||||
private readonly StyleSheet errorStyleSheet;
|
|
||||||
private readonly NodeInfoAttribute info;
|
|
||||||
|
|
||||||
public AssetGraphNode GraphNode { get; }
|
|
||||||
public List<Port> AllPorts { get; } = new List<Port>();
|
|
||||||
public List<Port> InputPorts { get; } = new List<Port>();
|
|
||||||
public List<Port> OutputPorts { get; } = new List<Port>();
|
|
||||||
|
|
||||||
private readonly AssetGraphViewWindow window;
|
|
||||||
|
|
||||||
public AssetGraphNodeEditor(AssetGraphNode node, AssetGraphViewWindow window)
|
|
||||||
{
|
|
||||||
this.window = window;
|
|
||||||
GraphNode = node;
|
|
||||||
|
|
||||||
// Initialize node UI
|
|
||||||
info = InitializeNode(node);
|
|
||||||
|
|
||||||
// Collect input and output ports
|
|
||||||
CreatePorts(node.GetType());
|
|
||||||
|
|
||||||
// Load stylesheets
|
|
||||||
defaultStyleSheet = LoadStyleSheet("Node.uss", "Packages/com.chromium.imageprocessingrah/Node.uss");
|
|
||||||
errorStyleSheet = LoadStyleSheet("NodeError.uss", "Packages/com.chromium.imageprocessingrah/NodeError.uss");
|
|
||||||
styleSheets.Add(defaultStyleSheet);
|
|
||||||
|
|
||||||
// Set up error handling and cleanup
|
|
||||||
SetUpErrorHandling();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes the node, including title, name, and class lists.
|
|
||||||
/// </summary>
|
|
||||||
private NodeInfoAttribute InitializeNode(AssetGraphNode node)
|
|
||||||
{
|
|
||||||
var typeInfo = node.GetType();
|
|
||||||
var nodeInfo = typeInfo.GetCustomAttribute<NodeInfoAttribute>();
|
|
||||||
|
|
||||||
title = nodeInfo.Title;
|
|
||||||
name = typeInfo.Name;
|
|
||||||
|
|
||||||
foreach (var depth in nodeInfo.MenuItem.Split('/'))
|
|
||||||
{
|
|
||||||
AddToClassList(depth.ToLower().Replace(' ', '-'));
|
|
||||||
}
|
|
||||||
|
|
||||||
return nodeInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Creates input and output ports for the node from its fields.
|
|
||||||
/// </summary>
|
|
||||||
private void CreatePorts(Type typeInfo)
|
|
||||||
{
|
|
||||||
var fields = typeInfo.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
|
|
||||||
|
|
||||||
// Collect input and output fields
|
|
||||||
var inputFields = fields.Where(f => f.GetCustomAttribute<Input>() != null).ToList();
|
|
||||||
var outputFields = fields.Where(f => f.GetCustomAttribute<Output>() != null).ToList();
|
|
||||||
|
|
||||||
// Create ports
|
|
||||||
CreateInputPorts(inputFields);
|
|
||||||
CreateOutputPorts(outputFields);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CreateInputPorts(List<FieldInfo> fields)
|
|
||||||
{
|
|
||||||
foreach (var field in fields)
|
|
||||||
{
|
|
||||||
var port = CreatePort(field, true, field.GetCustomAttribute<Input>().Label);
|
|
||||||
InputPorts.Add(port);
|
|
||||||
AllPorts.Add(port);
|
|
||||||
|
|
||||||
inputContainer.Add(port);
|
|
||||||
ExposeVariableToPort(port, field);
|
|
||||||
((AssetGraphPort)port).fieldInfo = field;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CreateOutputPorts(List<FieldInfo> fields)
|
|
||||||
{
|
|
||||||
foreach (var field in fields)
|
|
||||||
{
|
|
||||||
var port = CreatePort(field, false, field.GetCustomAttribute<Output>().Label);
|
|
||||||
OutputPorts.Add(port);
|
|
||||||
AllPorts.Add(port);
|
|
||||||
|
|
||||||
outputContainer.Add(port);
|
|
||||||
((AssetGraphPort)port).fieldInfo = field;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Port CreatePort(FieldInfo field, bool isInput, string label)
|
|
||||||
{
|
|
||||||
var port = AssetGraphPort.Create(window.edgeConnectorListener, isInput, field.FieldType);
|
|
||||||
if (!string.IsNullOrEmpty(label)) port.portName = label;
|
|
||||||
return port;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SetUpErrorHandling()
|
|
||||||
{
|
|
||||||
GraphNode.onFailed += () => styleSheets.Add(errorStyleSheet);
|
|
||||||
|
|
||||||
window.asset.OnRun += () =>
|
|
||||||
{
|
|
||||||
if (styleSheets.Contains(errorStyleSheet))
|
|
||||||
styleSheets.Remove(errorStyleSheet);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private StyleSheet LoadStyleSheet(string path, string fallbackPath)
|
|
||||||
{
|
|
||||||
var styleSheet = AssetDatabase.LoadAssetAtPath<StyleSheet>($"Assets/Unity Image Processing/{path}");
|
|
||||||
return styleSheet ?? EditorGUIUtility.Load(fallbackPath) as StyleSheet;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Exposes a variable on the port for editing when it's not connected.
|
|
||||||
/// </summary>
|
|
||||||
public void ExposeVariableToPort(Port port, FieldInfo field)
|
|
||||||
{
|
|
||||||
var variableContainer = ((AssetGraphPort)port).ExposedPropertyContainer;
|
|
||||||
|
|
||||||
if (variableContainer == null)
|
|
||||||
{
|
|
||||||
var newElement = CreatePropertyFieldForType(field.FieldType, field.GetValue(GraphNode));
|
|
||||||
if (newElement != null)
|
|
||||||
{
|
|
||||||
variableContainer = newElement;
|
|
||||||
((AssetGraphPort)port).ExposedPropertyContainer = newElement;
|
|
||||||
|
|
||||||
// Add the edited element to the port
|
|
||||||
port.Add(newElement);
|
|
||||||
RegisterFieldChangeCallback(field, newElement);
|
|
||||||
variableContainer.style.display = DisplayStyle.Flex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void RegisterFieldChangeCallback(FieldInfo field, VisualElement element)
|
|
||||||
{
|
|
||||||
// Register value change callbacks for various field types
|
|
||||||
switch (element)
|
|
||||||
{
|
|
||||||
case IntegerField intField:
|
|
||||||
if (field.FieldType == typeof(GreyscaleValue))
|
|
||||||
{
|
|
||||||
// Handle GreyscaleValue specifically
|
|
||||||
intField.RegisterValueChangedCallback(evt =>
|
|
||||||
{
|
|
||||||
var value = (GreyscaleValue)field.GetValue(GraphNode);
|
|
||||||
|
|
||||||
if (intField is GreyscaleField greyscaleField && value != null)
|
|
||||||
{
|
|
||||||
if (evt.newValue > greyscaleField.minMax.Item2)
|
|
||||||
value.value = greyscaleField.minMax.Item2;
|
|
||||||
else if (evt.newValue < greyscaleField.minMax.Item1)
|
|
||||||
value.value = greyscaleField.minMax.Item1;
|
|
||||||
else
|
|
||||||
value.value = evt.newValue;
|
|
||||||
|
|
||||||
field.SetValue(GraphNode, value);
|
|
||||||
intField.SetValueWithoutNotify((int)value.value);
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Default case for IntegerField
|
|
||||||
intField.RegisterValueChangedCallback(evt => field.SetValue(GraphNode, evt.newValue));
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FloatField floatField:
|
|
||||||
floatField.RegisterValueChangedCallback(evt => field.SetValue(GraphNode, evt.newValue));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Toggle boolField:
|
|
||||||
boolField.RegisterValueChangedCallback(evt => field.SetValue(GraphNode, evt.newValue));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TextField stringField:
|
|
||||||
stringField.RegisterValueChangedCallback(evt => field.SetValue(GraphNode, evt.newValue));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ColorField colorField:
|
|
||||||
colorField.RegisterValueChangedCallback(evt => field.SetValue(GraphNode, evt.newValue));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Vector3Field vector3Field:
|
|
||||||
vector3Field.RegisterValueChangedCallback(evt => field.SetValue(GraphNode, evt.newValue));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Vector2Field vector2Field:
|
|
||||||
vector2Field.RegisterValueChangedCallback(evt => field.SetValue(GraphNode, evt.newValue));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case EnumField enumField:
|
|
||||||
enumField.RegisterValueChangedCallback(evt => field.SetValue(GraphNode, evt.newValue));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ObjectField objectField:
|
|
||||||
objectField.RegisterValueChangedCallback(evt => field.SetValue(GraphNode, evt.newValue));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private VisualElement CreatePropertyFieldForType(Type type, object value)
|
|
||||||
{
|
|
||||||
return type switch
|
|
||||||
{
|
|
||||||
{ } when type == typeof(int) => new IntegerField { value = (int)value },
|
|
||||||
{ } when type == typeof(float) => new FloatField { value = (float)value },
|
|
||||||
{ } when type == typeof(bool) => new Toggle { value = (bool)value },
|
|
||||||
{ } when type == typeof(string) => new TextField { value = (string)value },
|
|
||||||
{ } when type == typeof(Color) => new ColorField { value = (Color)value },
|
|
||||||
{ } when type == typeof(Vector3) => new Vector3Field { value = (Vector3)value },
|
|
||||||
{ } when type == typeof(Vector2) => new Vector2Field { value = (Vector2)value },
|
|
||||||
{ } when type == typeof(GreyscaleValue) => new GreyscaleField { value = ((GreyscaleValue)value).value },
|
|
||||||
{ } when type.IsEnum => new EnumField((Enum)value),
|
|
||||||
{ } when typeof(UnityEngine.Object).IsAssignableFrom(type) => new ObjectField
|
|
||||||
{
|
|
||||||
value = (UnityEngine.Object)value,
|
|
||||||
objectType = type
|
|
||||||
},
|
|
||||||
_ => null
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ToggleExposedVariable(Port port, bool isVisible)
|
|
||||||
{
|
|
||||||
var assetGraphPort = port as AssetGraphPort;
|
|
||||||
if (assetGraphPort?.ExposedPropertyContainer != null)
|
|
||||||
assetGraphPort.ExposedPropertyContainer.style.display =
|
|
||||||
isVisible ? DisplayStyle.Flex : DisplayStyle.None;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void BuildContextualMenu(ContextualMenuPopulateEvent evt)
|
|
||||||
{
|
|
||||||
evt.menu.InsertAction(evt.menu.MenuItems().Count, "Open Documentation", OpenDocumentation);
|
|
||||||
evt.menu.AppendSeparator();
|
|
||||||
base.BuildContextualMenu(evt);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OpenDocumentation(DropdownMenuAction obj)
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrEmpty(info.DocumentationationURL))
|
|
||||||
{
|
|
||||||
Application.OpenURL(info.DocumentationationURL);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Debug.LogWarning($"No documentation URL provided for node {GraphNode.asset.name}!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SavePosition() => GraphNode.SetPosition(GetPosition());
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,246 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
|
||||||
using AssetGraph.Core.Attributes;
|
|
||||||
using AssetGraph.Nodes;
|
|
||||||
using UnityEditor;
|
|
||||||
using UnityEditor.Experimental.GraphView;
|
|
||||||
using UnityEngine;
|
|
||||||
using UnityEngine.UIElements;
|
|
||||||
|
|
||||||
namespace AssetGraph.Core
|
|
||||||
{
|
|
||||||
public struct SearchContextElement
|
|
||||||
{
|
|
||||||
public object target { get; private set; }
|
|
||||||
public string title { get; private set; }
|
|
||||||
|
|
||||||
public Dictionary<int, Type> ImportPortTypes { get; private set; }
|
|
||||||
public Dictionary<int, Type> ExportPortTypes { get; private set; }
|
|
||||||
public int portID;
|
|
||||||
|
|
||||||
public SearchContextElement(object target, string title, Dictionary<int, Type> importPortTypes,
|
|
||||||
Dictionary<int, Type> exportPortTypes, int portID)
|
|
||||||
{
|
|
||||||
this.target = target;
|
|
||||||
this.title = title;
|
|
||||||
ImportPortTypes = importPortTypes;
|
|
||||||
ExportPortTypes = exportPortTypes;
|
|
||||||
this.portID = portID;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class AssetGraphSearchProvider : ScriptableObject, ISearchWindowProvider
|
|
||||||
{
|
|
||||||
public AssetGraphViewWindow graph;
|
|
||||||
public VisualElement target;
|
|
||||||
|
|
||||||
public static List<SearchContextElement> elements;
|
|
||||||
private Assembly[] assemblies;
|
|
||||||
|
|
||||||
// Create Search Tree for Nodes
|
|
||||||
public List<SearchTreeEntry> CreateSearchTree(SearchWindowContext context)
|
|
||||||
{
|
|
||||||
List<SearchTreeEntry> tree = new List<SearchTreeEntry>();
|
|
||||||
tree.Add(new SearchTreeGroupEntry(new GUIContent("Nodes"), 0));
|
|
||||||
|
|
||||||
elements = new List<SearchContextElement>();
|
|
||||||
|
|
||||||
foreach (var type in TypeCache.GetTypesWithAttribute<NodeInfoAttribute>())
|
|
||||||
{
|
|
||||||
var attr = type.GetCustomAttribute<NodeInfoAttribute>();
|
|
||||||
if (attr == null || string.IsNullOrEmpty(attr.MenuItem)) continue;
|
|
||||||
|
|
||||||
var node = Activator.CreateInstance(type);
|
|
||||||
|
|
||||||
var fields = type.GetFields();
|
|
||||||
var importPortTypes = GetPortsByAttribute(fields, typeof(Core.Attributes.Input));
|
|
||||||
var exportPortTypes = GetPortsByAttribute(fields, typeof(Output));
|
|
||||||
|
|
||||||
elements.Add(new SearchContextElement(node, attr.MenuItem, importPortTypes, exportPortTypes, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
elements.Sort(SortElementsByTitle);
|
|
||||||
|
|
||||||
var groups = new HashSet<string>();
|
|
||||||
|
|
||||||
foreach (var element in elements)
|
|
||||||
{
|
|
||||||
string[] entryTitle = element.title.Split('/');
|
|
||||||
string currentGroup = "";
|
|
||||||
|
|
||||||
for (int i = 0; i < entryTitle.Length - 1; i++)
|
|
||||||
{
|
|
||||||
currentGroup += entryTitle[i];
|
|
||||||
if (groups.Add(currentGroup))
|
|
||||||
tree.Add(new SearchTreeGroupEntry(new GUIContent(entryTitle[i]), i + 1));
|
|
||||||
|
|
||||||
currentGroup += '/';
|
|
||||||
}
|
|
||||||
|
|
||||||
tree.Add(new SearchTreeEntry(new GUIContent(entryTitle.Last()))
|
|
||||||
{
|
|
||||||
level = entryTitle.Length,
|
|
||||||
userData = element
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return tree;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle Selection from Search Tree
|
|
||||||
public bool OnSelectEntry(SearchTreeEntry SearchTreeEntry, SearchWindowContext context)
|
|
||||||
{
|
|
||||||
var mousePos =
|
|
||||||
graph.ChangeCoordinatesTo(graph, context.screenMousePosition - graph.Window.position.position);
|
|
||||||
var graphMousePosition = graph.contentViewContainer.WorldToLocal(mousePos);
|
|
||||||
|
|
||||||
SearchContextElement element = (SearchContextElement)SearchTreeEntry.userData;
|
|
||||||
AssetGraphNode node = (AssetGraphNode)element.target;
|
|
||||||
node.SetPosition(new Rect(graphMousePosition, new Vector2()));
|
|
||||||
graph.Add(node);
|
|
||||||
node.asset = graph.asset;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create Search Tree for Edge Connections
|
|
||||||
public List<SearchTreeEntry> CreateSearchTreeForEdge(SearchWindowContext context, Edge edge)
|
|
||||||
{
|
|
||||||
var tree = new List<SearchTreeEntry>();
|
|
||||||
tree.Add(new SearchTreeGroupEntry(new GUIContent("Compatible Nodes"), 0));
|
|
||||||
|
|
||||||
elements = new List<SearchContextElement>();
|
|
||||||
var groups = new HashSet<string>();
|
|
||||||
|
|
||||||
var sourcePort = edge.output ?? edge.input;
|
|
||||||
bool isSourceOutput = edge.output != null;
|
|
||||||
Type targetType = (sourcePort as AssetGraphPort)?.portType;
|
|
||||||
|
|
||||||
if (targetType == null)
|
|
||||||
{
|
|
||||||
Debug.LogWarning("Could not determine port type from edge!");
|
|
||||||
return tree;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var type in TypeCache.GetTypesWithAttribute<NodeInfoAttribute>())
|
|
||||||
{
|
|
||||||
var attr = type.GetCustomAttribute<NodeInfoAttribute>();
|
|
||||||
if (attr == null || string.IsNullOrEmpty(attr.MenuItem)) continue;
|
|
||||||
|
|
||||||
var node = Activator.CreateInstance(type);
|
|
||||||
var fields = type.GetFields();
|
|
||||||
|
|
||||||
var inputPorts = GetPortsByAttributeList(fields, typeof(Core.Attributes.Input));
|
|
||||||
var outputPorts = GetPortsByAttributeList(fields, typeof(Output));
|
|
||||||
|
|
||||||
var compatiblePorts = isSourceOutput
|
|
||||||
? inputPorts.Where(port => port.FieldType.IsAssignableFrom(targetType)).ToList()
|
|
||||||
: outputPorts.Where(port => targetType.IsAssignableFrom(port.FieldType)).ToList();
|
|
||||||
|
|
||||||
if (!compatiblePorts.Any()) continue;
|
|
||||||
|
|
||||||
string[] menuPath = attr.MenuItem.Split('/');
|
|
||||||
string currentGroupPath = "";
|
|
||||||
|
|
||||||
for (int i = 0; i < menuPath.Length - 1; i++)
|
|
||||||
{
|
|
||||||
currentGroupPath += menuPath[i];
|
|
||||||
if (groups.Add(currentGroupPath))
|
|
||||||
tree.Add(new SearchTreeGroupEntry(new GUIContent(menuPath[i]), i + 1));
|
|
||||||
|
|
||||||
currentGroupPath += "/";
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var compatiblePort in compatiblePorts)
|
|
||||||
{
|
|
||||||
tree.Add(new SearchTreeEntry(new GUIContent($"{attr.Title}: {compatiblePort.Name}"))
|
|
||||||
{
|
|
||||||
level = menuPath.Length,
|
|
||||||
userData = new SearchContextElement(
|
|
||||||
node,
|
|
||||||
attr.Title,
|
|
||||||
inputPorts.ToDictionary(field => inputPorts.IndexOf(field), field => field.FieldType),
|
|
||||||
outputPorts.ToDictionary(field => outputPorts.IndexOf(field), field => field.FieldType),
|
|
||||||
inputPorts.IndexOf(compatiblePort))
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return tree;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Dictionary<int, Type> GetPortsByAttribute(FieldInfo[] fields, Type attributeType)
|
|
||||||
{
|
|
||||||
return fields
|
|
||||||
.Where(f => f.GetCustomAttribute(attributeType) != null)
|
|
||||||
.Select((f, index) => new { f, index })
|
|
||||||
.ToDictionary(a => a.index, a => a.f.FieldType);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static List<FieldInfo> GetPortsByAttributeList(FieldInfo[] fields, Type attributeType)
|
|
||||||
{
|
|
||||||
return fields.Where(f => f.GetCustomAttribute(attributeType) != null).ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int SortElementsByTitle(SearchContextElement a, SearchContextElement b)
|
|
||||||
{
|
|
||||||
return string.Compare(a.title, b.title, StringComparison.Ordinal);
|
|
||||||
}
|
|
||||||
|
|
||||||
// CustomSearchProviderForEdge
|
|
||||||
public class CustomSearchProviderForEdge : ScriptableObject, ISearchWindowProvider
|
|
||||||
{
|
|
||||||
private AssetGraphSearchProvider original;
|
|
||||||
private Edge edge;
|
|
||||||
private AssetGraphPort inputPort;
|
|
||||||
private AssetGraphPort outputPort;
|
|
||||||
|
|
||||||
public CustomSearchProviderForEdge(AssetGraphSearchProvider original, Edge edge, AssetGraphPort inputPort,
|
|
||||||
AssetGraphPort outputPort)
|
|
||||||
{
|
|
||||||
Init(original, edge, inputPort, outputPort);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Init(AssetGraphSearchProvider original, Edge edge, AssetGraphPort inputPort,
|
|
||||||
AssetGraphPort outputPort)
|
|
||||||
{
|
|
||||||
this.original = original;
|
|
||||||
this.edge = edge;
|
|
||||||
this.inputPort = inputPort;
|
|
||||||
this.outputPort = outputPort;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<SearchTreeEntry> CreateSearchTree(SearchWindowContext context)
|
|
||||||
{
|
|
||||||
return original.CreateSearchTreeForEdge(context, edge);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool OnSelectEntry(SearchTreeEntry selectedEntry, SearchWindowContext context)
|
|
||||||
{
|
|
||||||
var mousePos = original.graph.ChangeCoordinatesTo(original.graph,
|
|
||||||
context.screenMousePosition - original.graph.Window.position.position);
|
|
||||||
var graphMousePosition = original.graph.contentViewContainer.WorldToLocal(mousePos);
|
|
||||||
|
|
||||||
var element = (SearchContextElement)selectedEntry.userData;
|
|
||||||
var node = (AssetGraphNode)element.target;
|
|
||||||
|
|
||||||
node.SetPosition(new Rect(graphMousePosition, new Vector2()));
|
|
||||||
original.graph.Add(node);
|
|
||||||
node.asset = original.graph.asset;
|
|
||||||
|
|
||||||
Edge newEdge = new Edge();
|
|
||||||
if (inputPort != null)
|
|
||||||
newEdge = inputPort.ConnectTo(original.graph.nodeDictionary[node.ID].OutputPorts[element.portID]);
|
|
||||||
else if (outputPort != null)
|
|
||||||
newEdge = outputPort.ConnectTo(original.graph.nodeDictionary[node.ID].InputPorts[element.portID]);
|
|
||||||
|
|
||||||
original.graph.CreateEdge(newEdge);
|
|
||||||
original.graph.AddElement(newEdge);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,30 @@
|
|||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace ImageProcessingGraph.Editor.Windows
|
||||||
|
{
|
||||||
|
[CustomEditor(typeof(ImageProcessingGraphAsset))]
|
||||||
|
public class ImageProcessingGraphAssetEditorWindow : UnityEditor.Editor
|
||||||
|
{
|
||||||
|
public override void OnInspectorGUI()
|
||||||
|
{
|
||||||
|
if (GUILayout.Button("Open"))
|
||||||
|
{
|
||||||
|
ImageProcessingGraphEditorWindow.Open((ImageProcessingGraphAsset)target);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(GUILayout.Button("Calculate Dependancy Graph"))
|
||||||
|
{
|
||||||
|
var bleh = (ImageProcessingGraphAsset)target;
|
||||||
|
bleh.runOrder = bleh.GetExecutionOrder(bleh.Nodes, bleh.Connections, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(GUILayout.Button("Run Graph"))
|
||||||
|
{
|
||||||
|
var bleh = (ImageProcessingGraphAsset)target;
|
||||||
|
bleh.RunGraph();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,106 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEditor.Experimental.GraphView;
|
||||||
|
using UnityEditor.MemoryProfiler;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UIElements;
|
||||||
|
|
||||||
|
namespace ImageProcessingGraph.Editor.Unity_Image_Processing.Scripts.Editor.Windows
|
||||||
|
{
|
||||||
|
|
||||||
|
public class ImageProcessingGraphEdgeConnectorListener : IEdgeConnectorListener
|
||||||
|
{
|
||||||
|
private GraphViewChange m_GraphViewChange;
|
||||||
|
private List<Edge> m_EdgesToCreate;
|
||||||
|
private List<GraphElement> m_EdgesToDelete;
|
||||||
|
|
||||||
|
private ImageProcessingGraphViewWindow window;
|
||||||
|
|
||||||
|
public ImageProcessingGraphEdgeConnectorListener(ImageProcessingGraphViewWindow window)
|
||||||
|
{
|
||||||
|
this.m_EdgesToCreate = new List<Edge>();
|
||||||
|
this.m_EdgesToDelete = new List<GraphElement>();
|
||||||
|
this.m_GraphViewChange.edgesToCreate = this.m_EdgesToCreate;
|
||||||
|
this.window = window;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnDropOutsidePort(Edge edge, Vector2 position)
|
||||||
|
{
|
||||||
|
window.searchProvider.target = (VisualElement)window.focusController.focusedElement;
|
||||||
|
|
||||||
|
// ⚡ Override the search window open with a customized search tree
|
||||||
|
SearchWindow.Open(new SearchWindowContext(position), new ImageProcessingGraphSearchProvider.CustomSearchProviderForEdge(window.searchProvider, edge, (IPTPort)edge.input, (IPTPort)edge.output));
|
||||||
|
|
||||||
|
// Remove connections as you did
|
||||||
|
List<GraphConnection> connections = new List<GraphConnection>();
|
||||||
|
foreach (var conn in window.asset.Connections)
|
||||||
|
{
|
||||||
|
if (conn.internalEdge == edge)
|
||||||
|
connections.Add(conn);
|
||||||
|
}
|
||||||
|
foreach (var VARIABLE in connections)
|
||||||
|
{
|
||||||
|
window.asset.Connections.Remove(VARIABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (edge.input != null)
|
||||||
|
if (edge.input.node != null)
|
||||||
|
((ImageProcessingGraphNodeVisual)edge.input.node).ToggleExposedVariable((IPTPort)edge.input, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public void OnDrop(UnityEditor.Experimental.GraphView.GraphView graphView, Edge edge)
|
||||||
|
{
|
||||||
|
List<GraphConnection> connections = new List<GraphConnection>();
|
||||||
|
|
||||||
|
foreach (var conn in window.asset.Connections)
|
||||||
|
{
|
||||||
|
if (conn.internalEdge == edge)
|
||||||
|
{
|
||||||
|
connections.Add(conn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var VARIABLE in connections)
|
||||||
|
{
|
||||||
|
window.asset.Connections.Remove(VARIABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
((ImageProcessingGraphNodeVisual)edge.input.node).ToggleExposedVariable((IPTPort)edge.input, true);
|
||||||
|
|
||||||
|
|
||||||
|
this.m_EdgesToCreate.Clear();
|
||||||
|
this.m_EdgesToCreate.Add(edge);
|
||||||
|
this.m_EdgesToDelete.Clear();
|
||||||
|
if (edge.input.capacity == Port.Capacity.Single)
|
||||||
|
{
|
||||||
|
foreach (Edge connection in edge.input.connections)
|
||||||
|
{
|
||||||
|
if (connection != edge)
|
||||||
|
this.m_EdgesToDelete.Add((GraphElement)connection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (edge.output.capacity == Port.Capacity.Single)
|
||||||
|
{
|
||||||
|
foreach (Edge connection in edge.output.connections)
|
||||||
|
{
|
||||||
|
if (connection != edge)
|
||||||
|
this.m_EdgesToDelete.Add((GraphElement)connection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.m_EdgesToDelete.Count > 0)
|
||||||
|
graphView.DeleteElements((IEnumerable<GraphElement>)this.m_EdgesToDelete);
|
||||||
|
List<Edge> edgesToCreate = this.m_EdgesToCreate;
|
||||||
|
if (graphView.graphViewChanged != null)
|
||||||
|
edgesToCreate = graphView.graphViewChanged(this.m_GraphViewChange).edgesToCreate;
|
||||||
|
foreach (Edge edge1 in edgesToCreate)
|
||||||
|
{
|
||||||
|
graphView.AddElement((GraphElement)edge1);
|
||||||
|
edge.input.Connect(edge1);
|
||||||
|
edge.output.Connect(edge1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,73 @@
|
|||||||
|
using System;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEditor.Experimental.GraphView;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace ImageProcessingGraph.Editor.Windows
|
||||||
|
{
|
||||||
|
public class ImageProcessingGraphEditorWindow : EditorWindow
|
||||||
|
{
|
||||||
|
[SerializeField] private ImageProcessingGraphAsset currentGraph;
|
||||||
|
[SerializeField] private SerializedObject serializedObject;
|
||||||
|
[SerializeField] private ImageProcessingGraphViewWindow currentView;
|
||||||
|
public ImageProcessingGraphAsset CurrentGraph => currentGraph;
|
||||||
|
|
||||||
|
public static void Open(ImageProcessingGraphAsset asset)
|
||||||
|
{
|
||||||
|
var existingWindows = Resources.FindObjectsOfTypeAll<ImageProcessingGraphEditorWindow>();
|
||||||
|
foreach (var w in existingWindows)
|
||||||
|
{
|
||||||
|
if (w.CurrentGraph == asset)
|
||||||
|
{
|
||||||
|
w.Focus(); // 👁 focus the OG window
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var window = CreateWindow<ImageProcessingGraphEditorWindow>(typeof(SceneView));
|
||||||
|
window.titleContent = new GUIContent($"{asset.name}",
|
||||||
|
EditorGUIUtility.ObjectContent(null, typeof(ImageProcessingGraphAsset)).image);
|
||||||
|
window.Load(asset);
|
||||||
|
window.Focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void OnEnable()
|
||||||
|
{
|
||||||
|
if(currentGraph != null)
|
||||||
|
DrawGraph();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnGUI()
|
||||||
|
{
|
||||||
|
if (currentGraph != null)
|
||||||
|
{
|
||||||
|
if(EditorUtility.IsDirty(currentGraph))
|
||||||
|
this.hasUnsavedChanges = true;
|
||||||
|
else
|
||||||
|
this.hasUnsavedChanges = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Load(ImageProcessingGraphAsset asset)
|
||||||
|
{
|
||||||
|
currentGraph = asset;
|
||||||
|
DrawGraph();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DrawGraph()
|
||||||
|
{
|
||||||
|
serializedObject = new SerializedObject(currentGraph);
|
||||||
|
currentView = new ImageProcessingGraphViewWindow(serializedObject, this);
|
||||||
|
currentView.graphViewChanged += OnChange;
|
||||||
|
rootVisualElement.Add(currentView);
|
||||||
|
}
|
||||||
|
|
||||||
|
private GraphViewChange OnChange(GraphViewChange graphviewchange)
|
||||||
|
{
|
||||||
|
EditorUtility.SetDirty(currentGraph);
|
||||||
|
return graphviewchange;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
330
Editor/Scripts/Editor/Windows/ImageProcessingGraphNodeVisual.cs
Normal file
330
Editor/Scripts/Editor/Windows/ImageProcessingGraphNodeVisual.cs
Normal file
@ -0,0 +1,330 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using ImageProcessingGraph.Editor.Nodes.NodeAttributes;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEditor.Experimental.GraphView;
|
||||||
|
using UnityEditor.UIElements;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UIElements;
|
||||||
|
using Input = ImageProcessingGraph.Editor.Nodes.NodeAttributes.Input;
|
||||||
|
|
||||||
|
namespace ImageProcessingGraph.Editor.Unity_Image_Processing.Scripts.Editor.Windows
|
||||||
|
{
|
||||||
|
public class ImageProcessingGraphNodeVisual : Node
|
||||||
|
{
|
||||||
|
private BaseImageNode graphNode;
|
||||||
|
public BaseImageNode GraphNode => graphNode;
|
||||||
|
|
||||||
|
public List<Port> InputPorts { get; }
|
||||||
|
public List<Port> OutputPorts { get; }
|
||||||
|
|
||||||
|
private ImageProcessingGraphViewWindow window;
|
||||||
|
|
||||||
|
private StyleSheet defaaStyleSheet;
|
||||||
|
private StyleSheet errorStyleSheet;
|
||||||
|
|
||||||
|
public ImageProcessingGraphNodeVisual(BaseImageNode node, ImageProcessingGraphViewWindow window)
|
||||||
|
{
|
||||||
|
this.AddToClassList("image-node-visual");
|
||||||
|
this.window = window;
|
||||||
|
graphNode = node;
|
||||||
|
|
||||||
|
|
||||||
|
Type typeInfo = node.GetType();
|
||||||
|
NodeInfoAttribute info = typeInfo.GetCustomAttribute<NodeInfoAttribute>();
|
||||||
|
title = info.Title;
|
||||||
|
this.name = typeInfo.Name;
|
||||||
|
|
||||||
|
string[] depths = info.MenuItem.Split('/');
|
||||||
|
foreach (var depth in depths)
|
||||||
|
{
|
||||||
|
this.AddToClassList(depth.ToLower().Replace(' ', '-'));
|
||||||
|
}
|
||||||
|
|
||||||
|
this.InputPorts = new List<Port>();
|
||||||
|
this.OutputPorts = new List<Port>();
|
||||||
|
|
||||||
|
List<Input> inputs = new List<Input>();
|
||||||
|
List<FieldInfo> inputFieldInfo = new List<FieldInfo>();
|
||||||
|
List<FieldInfo> outputFieldInfo = new List<FieldInfo>();
|
||||||
|
|
||||||
|
FieldInfo[] fields = typeInfo.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
|
||||||
|
foreach (var field in fields)
|
||||||
|
{
|
||||||
|
if (field.GetCustomAttribute(typeof(Input)) != null)
|
||||||
|
{
|
||||||
|
Input input = field.GetCustomAttribute<Input>();
|
||||||
|
inputs.Add(input);
|
||||||
|
inputFieldInfo.Add(field);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (field.GetCustomAttribute(typeof(Output)) != null)
|
||||||
|
{
|
||||||
|
Output output = field.GetCustomAttribute<Output>();
|
||||||
|
outputFieldInfo.Add(field);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
CreateInputPorts(inputFieldInfo);
|
||||||
|
CreateOutputPorts(outputFieldInfo);
|
||||||
|
|
||||||
|
defaaStyleSheet = AssetDatabase.LoadAssetAtPath<StyleSheet>("Assets/Unity Image Processing/Node.uss");
|
||||||
|
if (defaaStyleSheet == null)
|
||||||
|
{
|
||||||
|
defaaStyleSheet = EditorGUIUtility.Load("Packages/com.chromium.imageprocessingrah/Node.uss") as StyleSheet;
|
||||||
|
}
|
||||||
|
styleSheets.Add(defaaStyleSheet);
|
||||||
|
|
||||||
|
errorStyleSheet = AssetDatabase.LoadAssetAtPath<StyleSheet>("Assets/Unity Image Processing/NodeError.uss");
|
||||||
|
if (errorStyleSheet == null)
|
||||||
|
{
|
||||||
|
errorStyleSheet = EditorGUIUtility.Load("Packages/com.chromium.imageprocessingrah/NodeError.uss") as StyleSheet;
|
||||||
|
}
|
||||||
|
|
||||||
|
graphNode.onFailed += () =>
|
||||||
|
{
|
||||||
|
styleSheets.Add(errorStyleSheet);
|
||||||
|
};
|
||||||
|
|
||||||
|
window.asset.OnRun += () =>
|
||||||
|
{
|
||||||
|
if (styleSheets.Contains(errorStyleSheet))
|
||||||
|
styleSheets.Remove(errorStyleSheet);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateInputPorts(List<FieldInfo> fields)
|
||||||
|
{
|
||||||
|
for (var index = 0; index < fields.Count; index++)
|
||||||
|
{
|
||||||
|
var field = fields[index];
|
||||||
|
var port = IPTPort.Create(window.edgeConnectorListener, true, field.FieldType);
|
||||||
|
|
||||||
|
string label = field.GetCustomAttribute<Input>().Label;
|
||||||
|
if (label != "")
|
||||||
|
port.portName = label;
|
||||||
|
InputPorts.Add(port);
|
||||||
|
|
||||||
|
|
||||||
|
inputContainer.Add(port);
|
||||||
|
ExposeVariableToPort(port, field);
|
||||||
|
port.fieldInfo = field;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateOutputPorts(List<FieldInfo> fields)
|
||||||
|
{
|
||||||
|
for (var index = 0; index < fields.Count; index++)
|
||||||
|
{
|
||||||
|
var field = fields[index];
|
||||||
|
var port = IPTPort.Create(window.edgeConnectorListener, false, field.FieldType);
|
||||||
|
|
||||||
|
string label = field.GetCustomAttribute<Output>().Label;
|
||||||
|
if (label != "")
|
||||||
|
port.portName = label;
|
||||||
|
OutputPorts.Add(port);
|
||||||
|
outputContainer.Add(port);
|
||||||
|
|
||||||
|
port.fieldInfo = field;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exposes a variable on the port for editing when it's not connected
|
||||||
|
public void ExposeVariableToPort(Port port, FieldInfo field)
|
||||||
|
{
|
||||||
|
VisualElement NewElement = new VisualElement();
|
||||||
|
var ExposedPropertyContainer = ((IPTPort)port).ExposedPropertyContainer;
|
||||||
|
Type containerType = null;
|
||||||
|
|
||||||
|
if (ExposedPropertyContainer == null)
|
||||||
|
{
|
||||||
|
NewElement.name = "property-field-container";
|
||||||
|
VisualElement the = CreatePropertyFieldForType(field.FieldType, field.GetValue(graphNode));
|
||||||
|
|
||||||
|
if(the != null)
|
||||||
|
containerType = the.GetType();
|
||||||
|
|
||||||
|
NewElement.Add(the);
|
||||||
|
((IPTPort)port).ExposedPropertyContainer = the;
|
||||||
|
ExposedPropertyContainer = ((IPTPort)port).ExposedPropertyContainer;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
containerType = ExposedPropertyContainer.GetType();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (containerType == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (ExposedPropertyContainer.GetType() == typeof(IntegerField))
|
||||||
|
{
|
||||||
|
var intField = ExposedPropertyContainer as IntegerField;
|
||||||
|
intField.RegisterValueChangedCallback(evt =>
|
||||||
|
{
|
||||||
|
field.SetValue(graphNode, evt.newValue); // Update the field with the new value
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else if (ExposedPropertyContainer is FloatField floatField)
|
||||||
|
{
|
||||||
|
floatField.RegisterValueChangedCallback(evt =>
|
||||||
|
{
|
||||||
|
field.SetValue(graphNode, evt.newValue); // Update the field with the new value
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else if (ExposedPropertyContainer is Toggle boolField)
|
||||||
|
{
|
||||||
|
boolField.RegisterValueChangedCallback(evt =>
|
||||||
|
{
|
||||||
|
field.SetValue(graphNode, evt.newValue); // Update the field with the new value
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else if (ExposedPropertyContainer is TextField stringField)
|
||||||
|
{
|
||||||
|
stringField.RegisterValueChangedCallback(evt =>
|
||||||
|
{
|
||||||
|
field.SetValue(graphNode, evt.newValue); // Update the field with the new value
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else if (ExposedPropertyContainer is ColorField colorField)
|
||||||
|
{
|
||||||
|
colorField.RegisterValueChangedCallback(evt =>
|
||||||
|
{
|
||||||
|
field.SetValue(graphNode, evt.newValue); // Update the field with the new value
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else if (ExposedPropertyContainer is Vector3Field vector3Field)
|
||||||
|
{
|
||||||
|
vector3Field.RegisterValueChangedCallback(evt =>
|
||||||
|
{
|
||||||
|
field.SetValue(graphNode, evt.newValue); // Update the field with the new value
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else if (ExposedPropertyContainer is Vector2Field vector2Field)
|
||||||
|
{
|
||||||
|
vector2Field.RegisterValueChangedCallback(evt =>
|
||||||
|
{
|
||||||
|
field.SetValue(graphNode, evt.newValue); // Update the field with the new value
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else if (ExposedPropertyContainer is ObjectField objectField)
|
||||||
|
{
|
||||||
|
objectField.RegisterValueChangedCallback(evt =>
|
||||||
|
{
|
||||||
|
field.SetValue(graphNode, evt.newValue); // Update the field with the new value
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else if (ExposedPropertyContainer is EnumField enumField)
|
||||||
|
{
|
||||||
|
enumField.RegisterValueChangedCallback(evt =>
|
||||||
|
{
|
||||||
|
field.SetValue(graphNode, evt.newValue); // 🎯 Update the field with the new enum value
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else if (ExposedPropertyContainer.GetType() == typeof(GreyscaleField))
|
||||||
|
{
|
||||||
|
var greyscaleField = ExposedPropertyContainer as GreyscaleField;
|
||||||
|
greyscaleField.RegisterValueChangedCallback(evt =>
|
||||||
|
{
|
||||||
|
var value = (GreyscaleValue)field.GetValue(graphNode);
|
||||||
|
|
||||||
|
if (evt.newValue > greyscaleField.minMax.Item2)
|
||||||
|
value.value = greyscaleField.minMax.Item2;
|
||||||
|
else if (evt.newValue < greyscaleField.minMax.Item1) value.value = greyscaleField.minMax.Item1;
|
||||||
|
|
||||||
|
value.value = evt.newValue;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
port.Add(NewElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ToggleExposedVariable(Port port, bool value)
|
||||||
|
{
|
||||||
|
IPTPort iptPort = port as IPTPort;
|
||||||
|
if(iptPort.ExposedPropertyContainer != null)
|
||||||
|
iptPort.ExposedPropertyContainer.style.display = value ? DisplayStyle.Flex : DisplayStyle.None;
|
||||||
|
}
|
||||||
|
|
||||||
|
private VisualElement CreatePropertyFieldForType(Type type, object value)
|
||||||
|
{
|
||||||
|
if (type == typeof(int))
|
||||||
|
{
|
||||||
|
var intField = new IntegerField { value = (int)value };
|
||||||
|
return intField;
|
||||||
|
}
|
||||||
|
else if (type == typeof(float))
|
||||||
|
{
|
||||||
|
var floatField = new FloatField { value = (float)value };
|
||||||
|
return floatField;
|
||||||
|
}
|
||||||
|
else if (type == typeof(bool))
|
||||||
|
{
|
||||||
|
var boolField = new Toggle { value = (bool)value };
|
||||||
|
return boolField;
|
||||||
|
}
|
||||||
|
else if (type == typeof(string))
|
||||||
|
{
|
||||||
|
var stringField = new TextField { value = (string)value };
|
||||||
|
return stringField;
|
||||||
|
}
|
||||||
|
else if (type == typeof(Color))
|
||||||
|
{
|
||||||
|
var colorField = new ColorField() { value = (Color)value };
|
||||||
|
return colorField;
|
||||||
|
}
|
||||||
|
else if (type == typeof(Vector3))
|
||||||
|
{
|
||||||
|
var vector3Field = new Vector3Field { value = (Vector3)value };
|
||||||
|
return vector3Field;
|
||||||
|
}
|
||||||
|
else if (type == typeof(Vector2))
|
||||||
|
{
|
||||||
|
var vector2Field = new Vector2Field { value = (Vector2)value };
|
||||||
|
return vector2Field;
|
||||||
|
}
|
||||||
|
else if (type == typeof(Texture2D))
|
||||||
|
{
|
||||||
|
var objectField = new ObjectField { value = (Texture2D)value, objectType = typeof(Texture2D) };
|
||||||
|
return objectField;
|
||||||
|
}
|
||||||
|
else if (type.IsEnum) // 💥✨ ENUMS, BABY! 💥✨
|
||||||
|
{
|
||||||
|
var enumField = new EnumField((Enum)value);
|
||||||
|
return enumField;
|
||||||
|
}
|
||||||
|
else if (type == typeof(GreyscaleValue))
|
||||||
|
{
|
||||||
|
|
||||||
|
var greyscaleValue = (GreyscaleValue)value;
|
||||||
|
var intField = new GreyscaleField { value = (int)greyscaleValue.value };
|
||||||
|
return intField;
|
||||||
|
}
|
||||||
|
else if (typeof(UnityEngine.Object).IsAssignableFrom(type))
|
||||||
|
{
|
||||||
|
var objectField = new ObjectField { value = (UnityEngine.Object)value, objectType = typeof(UnityEngine.Object) };
|
||||||
|
return objectField;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add more types as needed
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void BuildContextualMenu(ContextualMenuPopulateEvent evt)
|
||||||
|
{
|
||||||
|
evt.menu.InsertAction(evt.menu.MenuItems().Count, "Open Documentation", OpenDocumentation);
|
||||||
|
evt.menu.AppendSeparator();
|
||||||
|
base.BuildContextualMenu(evt);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OpenDocumentation(DropdownMenuAction obj)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SavePosition() => graphNode.SetPosition(GetPosition());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,282 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using Codice.Client.Common;
|
||||||
|
using ImageProcessingGraph.Editor.Nodes.NodeAttributes;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEditor.Experimental.GraphView;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UIElements;
|
||||||
|
using Input = ImageProcessingGraph.Editor.Nodes.NodeAttributes.Input;
|
||||||
|
|
||||||
|
namespace ImageProcessingGraph.Editor.Unity_Image_Processing.Scripts.Editor.Windows
|
||||||
|
{
|
||||||
|
public struct SearchContextElement
|
||||||
|
{
|
||||||
|
public object target { get; private set; }
|
||||||
|
public string title { get; private set; }
|
||||||
|
|
||||||
|
public Dictionary<int, Type> ImportPortTypes { get; private set; }
|
||||||
|
public Dictionary<int, Type> ExportPortTypes { get; private set; }
|
||||||
|
public int portID;
|
||||||
|
|
||||||
|
public SearchContextElement(object target, string title, Dictionary<int, Type> importPortTypes,
|
||||||
|
Dictionary<int, Type> exportPortTypes, int portID)
|
||||||
|
{
|
||||||
|
this.target = target;
|
||||||
|
this.title = title;
|
||||||
|
this.ImportPortTypes = importPortTypes;
|
||||||
|
this.ExportPortTypes = exportPortTypes;
|
||||||
|
this.portID = portID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ImageProcessingGraphSearchProvider : ScriptableObject, ISearchWindowProvider
|
||||||
|
{
|
||||||
|
public ImageProcessingGraphViewWindow graph;
|
||||||
|
public VisualElement target;
|
||||||
|
|
||||||
|
public static List<SearchContextElement> elements;
|
||||||
|
private Assembly[] assemblies;
|
||||||
|
|
||||||
|
public List<SearchTreeEntry> CreateSearchTree(SearchWindowContext context)
|
||||||
|
{
|
||||||
|
List<SearchTreeEntry> tree = new List<SearchTreeEntry>();
|
||||||
|
tree.Add(new SearchTreeGroupEntry(new GUIContent("Nodes"), 0));
|
||||||
|
|
||||||
|
elements = new List<SearchContextElement>();
|
||||||
|
|
||||||
|
foreach (var type in TypeCache.GetTypesWithAttribute<NodeInfoAttribute>())
|
||||||
|
{
|
||||||
|
var attr = type.GetCustomAttribute<NodeInfoAttribute>();
|
||||||
|
NodeInfoAttribute info = attr as NodeInfoAttribute;
|
||||||
|
var node = Activator.CreateInstance(type);
|
||||||
|
if (string.IsNullOrEmpty(info.MenuItem)) continue;
|
||||||
|
|
||||||
|
var Fields = type.GetFields();
|
||||||
|
Dictionary<int, Type> ImportPortTypes = new Dictionary<int, Type>();
|
||||||
|
Dictionary<int, Type> OutputPortTypes = new Dictionary<int, Type>();
|
||||||
|
|
||||||
|
foreach (var field in Fields)
|
||||||
|
{
|
||||||
|
if (field.GetCustomAttribute<Input>() != null)
|
||||||
|
ImportPortTypes.Add(ImportPortTypes.Count, field.FieldType);
|
||||||
|
if (field.GetCustomAttribute<Output>() != null)
|
||||||
|
OutputPortTypes.Add(OutputPortTypes.Count, field.FieldType);
|
||||||
|
}
|
||||||
|
|
||||||
|
elements.Add(new SearchContextElement(node, info.MenuItem, ImportPortTypes, OutputPortTypes, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
elements.Sort((entry1, entry2) =>
|
||||||
|
{
|
||||||
|
string[] splits1 = entry1.title.Split('/');
|
||||||
|
string[] splits2 = entry2.title.Split('/');
|
||||||
|
|
||||||
|
for (int i = 0; i < splits1.Length; i++)
|
||||||
|
{
|
||||||
|
if (i >= splits2.Length) return 1;
|
||||||
|
|
||||||
|
int value = splits1[i].CompareTo(splits2[i]);
|
||||||
|
if (value != 0)
|
||||||
|
{
|
||||||
|
if (splits1.Length != splits2.Length && (i == splits1.Length - 1 || i == splits2.Length - 1))
|
||||||
|
return splits1.Length < splits2.Length ? 1 : -1;
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
List<string> groups = new List<string>();
|
||||||
|
|
||||||
|
foreach (var element in elements)
|
||||||
|
{
|
||||||
|
string[] entryTitle = element.title.Split('/');
|
||||||
|
|
||||||
|
string groupName = "";
|
||||||
|
|
||||||
|
for (int i = 0; i < entryTitle.Length - 1; i++)
|
||||||
|
{
|
||||||
|
groupName += entryTitle[i];
|
||||||
|
if (!groups.Contains(groupName))
|
||||||
|
{
|
||||||
|
tree.Add(new SearchTreeGroupEntry(new GUIContent(groupName), i + 1));
|
||||||
|
groups.Add(groupName);
|
||||||
|
}
|
||||||
|
|
||||||
|
groupName += '/';
|
||||||
|
}
|
||||||
|
|
||||||
|
SearchTreeEntry entry = new SearchTreeEntry(new GUIContent(entryTitle.Last()));
|
||||||
|
entry.level = entryTitle.Length;
|
||||||
|
entry.userData = element;
|
||||||
|
tree.Add(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
return tree;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool OnSelectEntry(SearchTreeEntry SearchTreeEntry, SearchWindowContext context)
|
||||||
|
{
|
||||||
|
var mousePos =
|
||||||
|
graph.ChangeCoordinatesTo(graph, context.screenMousePosition - graph.Window.position.position);
|
||||||
|
var graphMousePosition = graph.contentViewContainer.WorldToLocal(mousePos);
|
||||||
|
|
||||||
|
SearchContextElement element = (SearchContextElement)SearchTreeEntry.userData;
|
||||||
|
|
||||||
|
BaseImageNode node = (BaseImageNode)element.target;
|
||||||
|
node.SetPosition(new Rect(graphMousePosition, new Vector2()));
|
||||||
|
graph.Add(node);
|
||||||
|
node.asset = graph.asset;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<SearchTreeEntry> CreateSearchTreeForEdge(SearchWindowContext context, Edge edge)
|
||||||
|
{
|
||||||
|
var tree = new List<SearchTreeEntry>();
|
||||||
|
tree.Add(new SearchTreeGroupEntry(new GUIContent("Compatible Nodes"), 0));
|
||||||
|
|
||||||
|
elements = new List<SearchContextElement>();
|
||||||
|
var groups = new List<string>();
|
||||||
|
|
||||||
|
var sourcePort = edge.output ?? edge.input;
|
||||||
|
bool isSourceOutput = edge.output != null;
|
||||||
|
Type targetType = (sourcePort as IPTPort)?.portType;
|
||||||
|
|
||||||
|
if (targetType == null)
|
||||||
|
{
|
||||||
|
Debug.LogWarning("Could not determine port type from edge!");
|
||||||
|
return tree;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var type in TypeCache.GetTypesWithAttribute<NodeInfoAttribute>())
|
||||||
|
{
|
||||||
|
var attr = type.GetCustomAttribute<NodeInfoAttribute>();
|
||||||
|
if (string.IsNullOrEmpty(attr.MenuItem)) continue;
|
||||||
|
|
||||||
|
var node = Activator.CreateInstance(type);
|
||||||
|
var fields = type.GetFields();
|
||||||
|
|
||||||
|
// Get all ports
|
||||||
|
var inputPorts = fields.Where(f => f.GetCustomAttribute<Input>() != null).ToList();
|
||||||
|
var outputPorts = fields.Where(f => f.GetCustomAttribute<Output>() != null).ToList();
|
||||||
|
|
||||||
|
// REVERSED LOGIC:
|
||||||
|
// If dragging from output, we want compatible INPUT ports
|
||||||
|
// If dragging from input, we want compatible OUTPUT ports
|
||||||
|
var compatiblePorts = isSourceOutput
|
||||||
|
? inputPorts.Where(f => f.FieldType.IsAssignableFrom(targetType)).ToList()
|
||||||
|
: outputPorts.Where(f => targetType.IsAssignableFrom(f.FieldType)).ToList();
|
||||||
|
|
||||||
|
if (compatiblePorts.Count == 0) continue;
|
||||||
|
|
||||||
|
// Build group hierarchy
|
||||||
|
var menuPath = attr.MenuItem.Split('/');
|
||||||
|
var currentGroupPath = "";
|
||||||
|
|
||||||
|
for (int i = 0; i < menuPath.Length - 1; i++)
|
||||||
|
{
|
||||||
|
currentGroupPath += menuPath[i];
|
||||||
|
if (!groups.Contains(currentGroupPath))
|
||||||
|
{
|
||||||
|
tree.Add(new SearchTreeGroupEntry(new GUIContent(menuPath[i]), i + 1));
|
||||||
|
groups.Add(currentGroupPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
currentGroupPath += "/";
|
||||||
|
}
|
||||||
|
|
||||||
|
// // Add node entry
|
||||||
|
// var nodeTitle = $"{type.Name}: {menuPath.Last()}";
|
||||||
|
// tree.Add(new SearchTreeEntry(new GUIContent(nodeTitle))
|
||||||
|
// {
|
||||||
|
// level = menuPath.Length,
|
||||||
|
// userData = new SearchContextElement(
|
||||||
|
// node,
|
||||||
|
// nodeTitle,
|
||||||
|
// inputPorts.ToDictionary(f => inputPorts.IndexOf(f), f => f.FieldType),
|
||||||
|
// outputPorts.ToDictionary(f => outputPorts.IndexOf(f), f => f.FieldType))
|
||||||
|
// });
|
||||||
|
|
||||||
|
// Add compatible port entries
|
||||||
|
foreach (var portField in compatiblePorts)
|
||||||
|
{
|
||||||
|
var portList = portField.GetCustomAttribute<Input>() != null ? inputPorts : outputPorts;
|
||||||
|
int portIndex = portList.IndexOf(portField);
|
||||||
|
|
||||||
|
var portTitle = $"{attr.Title}: {portField.Name}";
|
||||||
|
tree.Add(new SearchTreeEntry(new GUIContent(portTitle))
|
||||||
|
{
|
||||||
|
level = menuPath.Length,
|
||||||
|
userData = new SearchContextElement(
|
||||||
|
node,
|
||||||
|
portTitle,
|
||||||
|
inputPorts.ToDictionary(f => inputPorts.IndexOf(f), f => f.FieldType),
|
||||||
|
outputPorts.ToDictionary(f => outputPorts.IndexOf(f), f => f.FieldType),
|
||||||
|
portIndex)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return tree;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CustomSearchProviderForEdge : ScriptableObject, ISearchWindowProvider
|
||||||
|
{
|
||||||
|
private readonly ImageProcessingGraphSearchProvider original;
|
||||||
|
private readonly Edge edge;
|
||||||
|
private readonly IPTPort inputPort;
|
||||||
|
private readonly IPTPort outputPort;
|
||||||
|
|
||||||
|
public CustomSearchProviderForEdge(ImageProcessingGraphSearchProvider original, Edge edge, IPTPort inputPort, IPTPort outputPort)
|
||||||
|
{
|
||||||
|
this.original = original;
|
||||||
|
this.edge = edge;
|
||||||
|
this.inputPort = inputPort;
|
||||||
|
this.outputPort = outputPort;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<SearchTreeEntry> CreateSearchTree(SearchWindowContext context)
|
||||||
|
{
|
||||||
|
return original.CreateSearchTreeForEdge(context, edge);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool OnSelectEntry(SearchTreeEntry selectedEntry, SearchWindowContext context)
|
||||||
|
{
|
||||||
|
var mousePos =
|
||||||
|
original.graph.ChangeCoordinatesTo(original.graph, context.screenMousePosition - original.graph.Window.position.position);
|
||||||
|
var graphMousePosition = original.graph.contentViewContainer.WorldToLocal(mousePos);
|
||||||
|
|
||||||
|
SearchContextElement element = (SearchContextElement)selectedEntry.userData;
|
||||||
|
|
||||||
|
BaseImageNode node = (BaseImageNode)element.target;
|
||||||
|
node.SetPosition(new Rect(graphMousePosition, new Vector2()));
|
||||||
|
original.graph.Add(node);
|
||||||
|
node.asset = original.graph.asset;
|
||||||
|
|
||||||
|
|
||||||
|
Edge edge = new Edge();
|
||||||
|
|
||||||
|
if (inputPort != null)
|
||||||
|
{
|
||||||
|
edge = inputPort.ConnectTo(original.graph.nodeDictionary[node.ID].OutputPorts[element.portID]);
|
||||||
|
}
|
||||||
|
else if (outputPort != null)
|
||||||
|
{
|
||||||
|
edge = outputPort.ConnectTo(original.graph.nodeDictionary[node.ID].InputPorts[element.portID]);
|
||||||
|
}
|
||||||
|
|
||||||
|
original.graph.CreateEdge(edge);
|
||||||
|
original.graph.AddElement((GraphElement)edge);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -2,61 +2,53 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using AssetGraph.Core.Attributes;
|
using ImageProcessingGraph.Editor.Nodes.NodeAttributes;
|
||||||
using AssetGraph.Core.GraphElements;
|
using ImageProcessingGraph.Editor.Unity_Image_Processing.Scripts.Editor.Windows;
|
||||||
using AssetGraph.Nodes;
|
using ImageProcessingGraph.Editor.Windows;
|
||||||
using ImageProcessingGraph.Editor;
|
|
||||||
using UnityEditor;
|
using UnityEditor;
|
||||||
using UnityEditor.Experimental.GraphView;
|
using UnityEditor.Experimental.GraphView;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UIElements;
|
using UnityEngine.UIElements;
|
||||||
|
|
||||||
namespace AssetGraph.Core
|
namespace ImageProcessingGraph.Editor
|
||||||
{
|
{
|
||||||
public class AssetGraphViewWindow : GraphView
|
public class ImageProcessingGraphViewWindow : GraphView
|
||||||
{
|
{
|
||||||
internal AssetGraphData asset;
|
internal ImageProcessingGraphAsset asset;
|
||||||
private SerializedObject serializedObject;
|
private SerializedObject serializedObject;
|
||||||
private AssetGraphEditorWindow window;
|
private ImageProcessingGraphEditorWindow window;
|
||||||
public AssetGraphEditorWindow Window => window;
|
public ImageProcessingGraphEditorWindow Window => window;
|
||||||
|
|
||||||
public List<AssetGraphNodeEditor> graphNodes;
|
public List<ImageProcessingGraphNodeVisual> graphNodes;
|
||||||
public Dictionary<string, AssetGraphNodeEditor> nodeDictionary;
|
public Dictionary<string, ImageProcessingGraphNodeVisual> nodeDictionary;
|
||||||
public Dictionary<Edge, GraphConnection> connectionDictionary;
|
public Dictionary<Edge, GraphConnection> connectionDictionary;
|
||||||
public Dictionary<string, AssetGraphStickyNote> stickyNoteDictionary;
|
|
||||||
|
|
||||||
internal AssetGraphSearchProvider searchProvider;
|
internal ImageProcessingGraphSearchProvider searchProvider;
|
||||||
public AssetGraphEdgeConnector edgeConnectorListener;
|
internal ImageProcessingGraphEdgeConnectorListener edgeConnectorListener;
|
||||||
|
|
||||||
private bool isDropdownEnabled = false;
|
private bool isDropdownEnabled = false;
|
||||||
public Vector2 cachedMousePos;
|
|
||||||
|
|
||||||
|
|
||||||
private Button debugModeButton;
|
private Button debugModeButton;
|
||||||
private Button outputRunOrder;
|
private Button outputRunOrder;
|
||||||
private Button makeStickyNode;
|
|
||||||
|
|
||||||
public AssetGraphViewWindow(SerializedObject obeject, AssetGraphEditorWindow window)
|
public ImageProcessingGraphViewWindow(SerializedObject obeject, ImageProcessingGraphEditorWindow window)
|
||||||
{
|
{
|
||||||
this.serializedObject = obeject;
|
this.serializedObject = obeject;
|
||||||
this.asset = obeject.targetObject as AssetGraphData;
|
this.asset = obeject.targetObject as ImageProcessingGraphAsset;
|
||||||
|
|
||||||
this.graphNodes = new List<AssetGraphNodeEditor>();
|
this.graphNodes = new List<ImageProcessingGraphNodeVisual>();
|
||||||
nodeDictionary = new Dictionary<string, AssetGraphNodeEditor>();
|
nodeDictionary = new Dictionary<string, ImageProcessingGraphNodeVisual>();
|
||||||
stickyNoteDictionary = new Dictionary<string, AssetGraphStickyNote>();
|
|
||||||
connectionDictionary = new Dictionary<Edge, GraphConnection>();
|
connectionDictionary = new Dictionary<Edge, GraphConnection>();
|
||||||
|
|
||||||
searchProvider = ScriptableObject.CreateInstance<AssetGraphSearchProvider>();
|
searchProvider = ScriptableObject.CreateInstance<ImageProcessingGraphSearchProvider>();
|
||||||
searchProvider.graph = this;
|
searchProvider.graph = this;
|
||||||
|
|
||||||
edgeConnectorListener = new AssetGraphEdgeConnector(this);
|
edgeConnectorListener = new ImageProcessingGraphEdgeConnectorListener(this);
|
||||||
|
|
||||||
this.nodeCreationRequest = ShowSearchWindow;
|
this.nodeCreationRequest = ShowSearchWindow;
|
||||||
|
|
||||||
this.window = window;
|
this.window = window;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
StyleSheet styleSheet = AssetDatabase.LoadAssetAtPath<StyleSheet>("Assets/Unity Image Processing/GraphView.uss");
|
StyleSheet styleSheet = AssetDatabase.LoadAssetAtPath<StyleSheet>("Assets/Unity Image Processing/GraphView.uss");
|
||||||
if (styleSheet == null)
|
if (styleSheet == null)
|
||||||
{
|
{
|
||||||
@ -66,7 +58,7 @@ namespace AssetGraph.Core
|
|||||||
|
|
||||||
GridBackground background = new GridBackground();
|
GridBackground background = new GridBackground();
|
||||||
background.name = "Grid";
|
background.name = "Grid";
|
||||||
this.Add(background);
|
Add(background);
|
||||||
background.SendToBack();
|
background.SendToBack();
|
||||||
|
|
||||||
CreateButtons();
|
CreateButtons();
|
||||||
@ -80,25 +72,16 @@ namespace AssetGraph.Core
|
|||||||
|
|
||||||
DrawNodes();
|
DrawNodes();
|
||||||
DrawConnections();
|
DrawConnections();
|
||||||
DrawStickyNotes();
|
|
||||||
|
|
||||||
graphViewChanged += OnGraphViewChanged;
|
graphViewChanged += OnGraphViewChanged;
|
||||||
|
|
||||||
Undo.undoRedoPerformed += UndoRedoPerformed;
|
Undo.undoRedoPerformed += UndoRedoPerformed;
|
||||||
RegisterCallback<MouseMoveEvent>(OnMouseMove);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnMouseMove(MouseMoveEvent evt)
|
|
||||||
{
|
|
||||||
cachedMousePos = evt.localMousePosition;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void UndoRedoPerformed()
|
private void UndoRedoPerformed()
|
||||||
{
|
{
|
||||||
DrawNodes();
|
DrawNodes();
|
||||||
DrawConnections();
|
DrawConnections();
|
||||||
DrawStickyNotes();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CreateButtons()
|
private void CreateButtons()
|
||||||
@ -164,27 +147,6 @@ namespace AssetGraph.Core
|
|||||||
asset.runOrder = asset.GetExecutionOrder(asset.Nodes, asset.Connections);
|
asset.runOrder = asset.GetExecutionOrder(asset.Nodes, asset.Connections);
|
||||||
};
|
};
|
||||||
|
|
||||||
makeStickyNode = new Button
|
|
||||||
{
|
|
||||||
text = "Make Sticky Node",
|
|
||||||
style =
|
|
||||||
{
|
|
||||||
width = 120,
|
|
||||||
height = 40,
|
|
||||||
position = Position.Absolute,
|
|
||||||
top = 55+45,
|
|
||||||
right = 10,
|
|
||||||
fontSize = 9
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
makeStickyNode.clicked += () =>
|
|
||||||
{
|
|
||||||
var noteData = new AssetGraphStickyNoteData("");
|
|
||||||
asset.stickyNotes.Add(noteData);
|
|
||||||
this.DrawStickyNote(noteData);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
Button dropdownButton = new Button
|
Button dropdownButton = new Button
|
||||||
{
|
{
|
||||||
@ -207,7 +169,6 @@ namespace AssetGraph.Core
|
|||||||
Add(debugModeButton);
|
Add(debugModeButton);
|
||||||
#endif
|
#endif
|
||||||
Add(outputRunOrder);
|
Add(outputRunOrder);
|
||||||
Add(makeStickyNode);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -215,7 +176,6 @@ namespace AssetGraph.Core
|
|||||||
Remove(debugModeButton);
|
Remove(debugModeButton);
|
||||||
#endif
|
#endif
|
||||||
Remove(outputRunOrder);
|
Remove(outputRunOrder);
|
||||||
Remove(makeStickyNode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
isDropdownEnabled = !isDropdownEnabled;
|
isDropdownEnabled = !isDropdownEnabled;
|
||||||
@ -225,9 +185,9 @@ namespace AssetGraph.Core
|
|||||||
Add(dropdownButton);
|
Add(dropdownButton);
|
||||||
}
|
}
|
||||||
|
|
||||||
private AssetGraphNodeEditor GetNode(string NodeID)
|
private ImageProcessingGraphNodeVisual GetNode(string NodeID)
|
||||||
{
|
{
|
||||||
AssetGraphNodeEditor node = null;
|
ImageProcessingGraphNodeVisual node = null;
|
||||||
nodeDictionary.TryGetValue(NodeID, out node);
|
nodeDictionary.TryGetValue(NodeID, out node);
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
@ -236,53 +196,33 @@ namespace AssetGraph.Core
|
|||||||
{
|
{
|
||||||
List<Port> compatiblePorts = new List<Port>();
|
List<Port> compatiblePorts = new List<Port>();
|
||||||
|
|
||||||
|
|
||||||
foreach (var node in graphNodes)
|
foreach (var node in graphNodes)
|
||||||
{
|
{
|
||||||
|
// Prevent connections to self
|
||||||
if (node == startPort.node)
|
if (node == startPort.node)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var ports = node.inputContainer.Children()
|
foreach (var port in node.inputContainer.Children().Concat(node.outputContainer.Children()).OfType<Port>())
|
||||||
.Concat(node.outputContainer.Children())
|
|
||||||
.OfType<Port>();
|
|
||||||
|
|
||||||
foreach (var port in ports)
|
|
||||||
{
|
{
|
||||||
if (startPort.direction == port.direction)
|
// Prevent connecting input to input or output to output
|
||||||
|
if (port.direction == startPort.direction)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Type typeA = GetPortEffectiveType(startPort);
|
if (port.portType != startPort.portType)
|
||||||
Type typeB = GetPortEffectiveType(port);
|
{
|
||||||
|
if (DoesConversionNodeExist())
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
// if (typeA == typeof(object))
|
else
|
||||||
// {
|
|
||||||
// var BaseGenPort = startPort.node as ImageProcessingGraphNodeVisual;
|
|
||||||
// var GenPort = BaseGenPort.GraphNode as GenericConnection;
|
|
||||||
//
|
|
||||||
// if (GenPort.InternalType != null)
|
|
||||||
// {
|
|
||||||
// if(!GenPort.InternalType.IsAssignableFrom(typeB))
|
|
||||||
// continue;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if (typeB == typeof(object))
|
|
||||||
// {
|
|
||||||
// var BaseGenPort = port.node as ImageProcessingGraphNodeVisual;
|
|
||||||
// var GenPort = BaseGenPort.GraphNode as GenericConnection;
|
|
||||||
//
|
|
||||||
// if (GenPort.InternalType != null)
|
|
||||||
// {
|
|
||||||
// if(!GenPort.InternalType.IsAssignableFrom(typeA))
|
|
||||||
// continue;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (!typeA.IsAssignableFrom(typeB) && !typeB.IsAssignableFrom(typeA))
|
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prevent connection if it creates a cycle
|
||||||
if (startPort.direction == Direction.Output && CreatesCycle(startPort, port))
|
if (startPort.direction == Direction.Output && CreatesCycle(startPort, port))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (startPort.direction == Direction.Input && CreatesCycle(port, startPort))
|
if (startPort.direction == Direction.Input && CreatesCycle(port, startPort))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -293,37 +233,13 @@ namespace AssetGraph.Core
|
|||||||
return compatiblePorts;
|
return compatiblePorts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private Type GetPortEffectiveType(Port port)
|
|
||||||
{
|
|
||||||
if (port is AssetGraphPort iptPort)
|
|
||||||
{
|
|
||||||
if (iptPort.node is AssetGraphNodeEditor vis &&
|
|
||||||
vis.GraphNode is GenericConnection conn &&
|
|
||||||
conn.InternalType != null)
|
|
||||||
{
|
|
||||||
return conn.InternalType;
|
|
||||||
}
|
|
||||||
return port.portType ?? typeof(object);
|
|
||||||
}
|
|
||||||
|
|
||||||
return port.portType ?? typeof(object);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private GraphViewChange OnGraphViewChanged(GraphViewChange graphviewchange)
|
private GraphViewChange OnGraphViewChanged(GraphViewChange graphviewchange)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (graphviewchange.movedElements != null)
|
if (graphviewchange.movedElements != null)
|
||||||
{
|
{
|
||||||
Undo.RecordObject(serializedObject.targetObject, "Moved Graph Elements");
|
Undo.RecordObject(serializedObject.targetObject, "Moved Graph Elements");
|
||||||
foreach (var VARIABLE in graphviewchange.movedElements.OfType<AssetGraphNodeEditor>())
|
foreach (var VARIABLE in graphviewchange.movedElements.OfType<ImageProcessingGraphNodeVisual>())
|
||||||
{
|
|
||||||
VARIABLE.SavePosition();
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var VARIABLE in graphviewchange.movedElements.OfType<AssetGraphStickyNote>())
|
|
||||||
{
|
{
|
||||||
VARIABLE.SavePosition();
|
VARIABLE.SavePosition();
|
||||||
}
|
}
|
||||||
@ -331,7 +247,7 @@ namespace AssetGraph.Core
|
|||||||
|
|
||||||
if (graphviewchange.elementsToRemove != null)
|
if (graphviewchange.elementsToRemove != null)
|
||||||
{
|
{
|
||||||
List<AssetGraphNodeEditor> nodesToRemove = graphviewchange.elementsToRemove.OfType<AssetGraphNodeEditor>().ToList();
|
List<ImageProcessingGraphNodeVisual> nodesToRemove = graphviewchange.elementsToRemove.OfType<ImageProcessingGraphNodeVisual>().ToList();
|
||||||
List<Edge> edges = graphviewchange.elementsToRemove.OfType<Edge>().ToList();
|
List<Edge> edges = graphviewchange.elementsToRemove.OfType<Edge>().ToList();
|
||||||
|
|
||||||
if (nodesToRemove.Count > 0)
|
if (nodesToRemove.Count > 0)
|
||||||
@ -378,8 +294,8 @@ namespace AssetGraph.Core
|
|||||||
|
|
||||||
public void CreateEdge(Edge edge)
|
public void CreateEdge(Edge edge)
|
||||||
{
|
{
|
||||||
AssetGraphNodeEditor outputNode = (AssetGraphNodeEditor)edge.output.node;
|
ImageProcessingGraphNodeVisual outputNode = (ImageProcessingGraphNodeVisual)edge.output.node;
|
||||||
AssetGraphNodeEditor inputNode = (AssetGraphNodeEditor)edge.input.node;
|
ImageProcessingGraphNodeVisual inputNode = (ImageProcessingGraphNodeVisual)edge.input.node;
|
||||||
|
|
||||||
|
|
||||||
int outputIndex = outputNode.OutputPorts.IndexOf(edge.output);
|
int outputIndex = outputNode.OutputPorts.IndexOf(edge.output);
|
||||||
@ -393,8 +309,8 @@ namespace AssetGraph.Core
|
|||||||
edge.output.Connect(edge);
|
edge.output.Connect(edge);
|
||||||
edge.input.Connect(edge);
|
edge.input.Connect(edge);
|
||||||
|
|
||||||
AssetGraphPort portIn = (AssetGraphPort)edge.output;
|
IPTPort portIn = (IPTPort)edge.output;
|
||||||
AssetGraphPort portOut = (AssetGraphPort)edge.output;
|
IPTPort portOut = (IPTPort)edge.output;
|
||||||
|
|
||||||
if (portIn.fieldInfo != null)
|
if (portIn.fieldInfo != null)
|
||||||
inputNode.ToggleExposedVariable(edge.input, false);
|
inputNode.ToggleExposedVariable(edge.input, false);
|
||||||
@ -413,9 +329,9 @@ namespace AssetGraph.Core
|
|||||||
edge.output.Disconnect(edge);
|
edge.output.Disconnect(edge);
|
||||||
edge.input.Disconnect(edge);
|
edge.input.Disconnect(edge);
|
||||||
|
|
||||||
AssetGraphNodeEditor inputNode = (AssetGraphNodeEditor)edge.input.node;
|
ImageProcessingGraphNodeVisual inputNode = (ImageProcessingGraphNodeVisual)edge.input.node;
|
||||||
|
|
||||||
AssetGraphPort portIn = (AssetGraphPort)edge.input;
|
IPTPort portIn = (IPTPort)edge.input;
|
||||||
|
|
||||||
if(portIn.fieldInfo != null)
|
if(portIn.fieldInfo != null)
|
||||||
inputNode.ToggleExposedVariable(edge.input, true);
|
inputNode.ToggleExposedVariable(edge.input, true);
|
||||||
@ -434,20 +350,20 @@ namespace AssetGraph.Core
|
|||||||
{
|
{
|
||||||
foreach (GraphConnection conn in asset.Connections)
|
foreach (GraphConnection conn in asset.Connections)
|
||||||
{
|
{
|
||||||
AssetGraphNodeEditor inputNode = GetNode(conn.inputPort.nodeID);
|
ImageProcessingGraphNodeVisual inputNode = GetNode(conn.inputPort.nodeID);
|
||||||
AssetGraphNodeEditor outputNode = GetNode(conn.outputPort.nodeID);
|
ImageProcessingGraphNodeVisual outputNode = GetNode(conn.outputPort.nodeID);
|
||||||
|
|
||||||
if (inputNode != null && outputNode != null)
|
if (inputNode != null && outputNode != null)
|
||||||
{
|
{
|
||||||
AssetGraphPort inPort = inputNode.InputPorts[conn.inputPort.portID] as AssetGraphPort;
|
IPTPort inPort = inputNode.InputPorts[conn.inputPort.portID] as IPTPort;
|
||||||
AssetGraphPort outPort = outputNode.OutputPorts[conn.outputPort.portID] as AssetGraphPort;
|
IPTPort outPort = outputNode.OutputPorts[conn.outputPort.portID] as IPTPort;
|
||||||
|
|
||||||
Edge edge = inPort.ConnectTo(outPort);
|
Edge edge = inPort.ConnectTo(outPort);
|
||||||
AddElement(edge);
|
AddElement(edge);
|
||||||
connectionDictionary.Add(edge, conn);
|
connectionDictionary.Add(edge, conn);
|
||||||
conn.SetInternalEdge(edge);
|
conn.SetInternalEdge(edge);
|
||||||
|
|
||||||
((AssetGraphNodeEditor)inPort.node).ToggleExposedVariable(inPort, false);
|
((ImageProcessingGraphNodeVisual)inPort.node).ToggleExposedVariable(inPort, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -498,13 +414,13 @@ namespace AssetGraph.Core
|
|||||||
#region Nodes
|
#region Nodes
|
||||||
private void DrawNodes()
|
private void DrawNodes()
|
||||||
{
|
{
|
||||||
foreach (AssetGraphNodeEditor node in graphNodes)
|
foreach (ImageProcessingGraphNodeVisual node in graphNodes)
|
||||||
{
|
{
|
||||||
RemoveElement(node);
|
RemoveElement(node);
|
||||||
}
|
}
|
||||||
graphNodes.Clear();
|
graphNodes.Clear();
|
||||||
|
|
||||||
foreach (KeyValuePair<string, AssetGraphNodeEditor> node in nodeDictionary)
|
foreach (KeyValuePair<string, ImageProcessingGraphNodeVisual> node in nodeDictionary)
|
||||||
{
|
{
|
||||||
RemoveElement(node.Value);
|
RemoveElement(node.Value);
|
||||||
}
|
}
|
||||||
@ -516,20 +432,20 @@ namespace AssetGraph.Core
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddNodeToGraph(AssetGraphNode node)
|
private void AddNodeToGraph(BaseImageNode node)
|
||||||
{
|
{
|
||||||
node.typeName = node.GetType().AssemblyQualifiedName;
|
node.typeName = node.GetType().AssemblyQualifiedName;
|
||||||
|
|
||||||
var infoAttr = node.GetType().GetCustomAttribute<NodeInfoAttribute>();
|
var infoAttr = node.GetType().GetCustomAttribute<NodeInfoAttribute>();
|
||||||
|
|
||||||
AssetGraphNodeEditor editorNode = null;
|
ImageProcessingGraphNodeVisual editorNode = null;
|
||||||
if (typeof(AssetGraphNodeEditor).IsAssignableFrom(infoAttr.EditorType))
|
if (typeof(ImageProcessingGraphNodeVisual).IsAssignableFrom(infoAttr.EditorType))
|
||||||
{
|
{
|
||||||
editorNode = (AssetGraphNodeEditor)Activator.CreateInstance(infoAttr.EditorType, node, this);
|
editorNode = (ImageProcessingGraphNodeVisual)Activator.CreateInstance(infoAttr.EditorType, node, this);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
editorNode = new AssetGraphNodeEditor(node, this);
|
editorNode = new ImageProcessingGraphNodeVisual(node, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
editorNode.SetPosition(node.Position);
|
editorNode.SetPosition(node.Position);
|
||||||
@ -541,7 +457,7 @@ namespace AssetGraph.Core
|
|||||||
AddElement(editorNode);
|
AddElement(editorNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Add(AssetGraphNode node)
|
public void Add(BaseImageNode node)
|
||||||
{
|
{
|
||||||
Undo.RecordObject(serializedObject.targetObject, "Added Node");
|
Undo.RecordObject(serializedObject.targetObject, "Added Node");
|
||||||
asset.Nodes.Add(node);
|
asset.Nodes.Add(node);
|
||||||
@ -552,7 +468,7 @@ namespace AssetGraph.Core
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RemoveNode(AssetGraphNodeEditor variable)
|
private void RemoveNode(ImageProcessingGraphNodeVisual variable)
|
||||||
{
|
{
|
||||||
List<GraphConnection> connectionsToRemove = new List<GraphConnection>();
|
List<GraphConnection> connectionsToRemove = new List<GraphConnection>();
|
||||||
|
|
||||||
@ -586,30 +502,5 @@ namespace AssetGraph.Core
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
#region Sticky Note
|
|
||||||
|
|
||||||
public void DrawStickyNotes()
|
|
||||||
{
|
|
||||||
foreach (var stick in asset.stickyNotes)
|
|
||||||
{
|
|
||||||
this.stickyNoteDictionary.Add(stick.GUID, DrawStickyNote(stick));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public AssetGraphStickyNote DrawStickyNote(AssetGraphStickyNoteData stickyNote)
|
|
||||||
{
|
|
||||||
AssetGraphStickyNote stickyNoteVisual = new AssetGraphStickyNote(stickyNote, this);
|
|
||||||
|
|
||||||
stickyNoteVisual.SetPosition(stickyNote.Position);
|
|
||||||
stickyNoteVisual.style.width = stickyNote.Size.x;
|
|
||||||
stickyNoteVisual.style.height = stickyNote.Size.y;
|
|
||||||
|
|
||||||
this.Add(stickyNoteVisual);
|
|
||||||
return stickyNoteVisual;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +0,0 @@
|
|||||||
#Title
|
|
||||||
{
|
|
||||||
display: none;
|
|
||||||
}
|
|
@ -1,3 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 79b350a401ed4074ab5fc42f451a8125
|
|
||||||
timeCreated: 1746344909
|
|
@ -1,4 +1,4 @@
|
|||||||
AssetGraphViewWindow
|
ImageProcessingGraphViewWindow
|
||||||
{
|
{
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user