Made outline around errored node as well as fixed NativeArray on texture import being disposed

This commit is contained in:
Chromium 2025-04-27 20:05:39 +01:00
parent c24a52bee8
commit 499d187c96
11 changed files with 110 additions and 24 deletions

View File

@ -1,4 +1,5 @@
using System;
using System.Reflection;
using UnityEditor.Experimental.GraphView;
using UnityEngine.UIElements;
@ -6,6 +7,8 @@ namespace ImageProcessingGraph.Editor
{
public class IPTPort : Port
{
public FieldInfo fieldInfo;
protected IPTPort(Orientation portOrientation, Direction portDirection, Capacity portCapacity, Type type) : base(portOrientation, portDirection, portCapacity, type)
{

View File

@ -37,7 +37,7 @@ public struct ImageData
/// <param name="sourceTexture">The source texture to extract pixel data from.</param>
public ImageData(Texture2D sourceTexture)
{
PixelData = sourceTexture.GetPixelData<Color32>(0);
PixelData = new NativeArray<Color32>(sourceTexture.GetPixelData<Color32>(0), Allocator.Persistent);
Dimensions = (sourceTexture.width, sourceTexture.height);
isRGBA = sourceTexture.format == TextureFormat.RGBA32;
}
@ -70,7 +70,7 @@ public struct ImageData
byte[] data = texture.EncodeToPNG();
string thePath;
if (path.StartsWith("Assets\\"))
if (path.StartsWith("Assets/"))
{
thePath = path.Substring("Assets/".Length);
}
@ -79,6 +79,8 @@ public struct ImageData
thePath = path;
}
thePath.Replace("/", "\\");
if (data != null)
{
System.IO.File.WriteAllBytes(Path.Combine(Application.dataPath, thePath), data);

View File

@ -21,6 +21,11 @@ namespace ImageProcessingGraph.Editor
public List<BaseImageNode> Nodes => nodes;
public List<GraphConnection> Connections => connections;
public delegate void OnRunEvent();
public event OnRunEvent OnRun;
public OnRunEvent OnRunEnd;
public ImageProcessingGraphAsset()
{
nodes = new List<BaseImageNode>();
@ -42,6 +47,8 @@ namespace ImageProcessingGraph.Editor
public void RunGraph()
{
OnRun?.Invoke();
// Create and start the stopwatch to measure time
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
@ -49,9 +56,15 @@ namespace ImageProcessingGraph.Editor
if (runOrder == null)
runOrder = GetExecutionOrder(this.nodes, this.connections);
bool failed = false;
foreach (var VARIABLE in runOrder)
{
VARIABLE.RunNode();
if (!VARIABLE.RunNode())
{
failed = true;
break;
}
}
// Stop the stopwatch after running the nodes

View File

@ -26,10 +26,13 @@ namespace ImageProcessingGraph.Editor
public ImageProcessingGraphAsset asset;
public delegate void OnFailed();
public event OnFailed onFailed;
public BaseImageNode()
{
guid = Guid.NewGuid().ToString();
/*Type t = this.GetType();
Debug.Log(t.Name);*/
}
@ -101,10 +104,20 @@ namespace ImageProcessingGraph.Editor
}
public void RunNode()
public bool RunNode()
{
SetNodeInputs();
this.Process();
try
{
SetNodeInputs();
this.Process();
return true;
}
catch (Exception e)
{
onFailed?.Invoke();
Debug.LogError(e);
return false;
}
}
public virtual void Process()

View File

@ -23,10 +23,10 @@ namespace ImageProcessingGraph.Editor.Nodes.Fun_Nodes.Texture
public override void Process()
{
int length = inputTexture.PixelData.Length;
int length = inputTexture.PixelData.Length;;
// Allocate NativeArrays for the pixel data and the individual RGBA channels
NativeArray<Color32> pixelData = new NativeArray<Color32>(inputTexture.PixelData, Allocator.Persistent);
NativeArray<Color32> pixelData = inputTexture.PixelData;
NativeArray<byte> rChannel = new NativeArray<byte>(length, Allocator.Persistent);
NativeArray<byte> gChannel = new NativeArray<byte>(length, Allocator.Persistent);
NativeArray<byte> bChannel = new NativeArray<byte>(length, Allocator.Persistent);

View File

@ -6,7 +6,7 @@ using UnityEngine;
namespace ImageProcessingGraph.Editor.Nodes.Output
{
[NodeInfo("Texture Export", "Export/Texture2D", true)]
[NodeInfo("Texture Export", "Export/Export Texture", true)]
public class Texture2DOutput : BaseImageNode
{
[NodeAttributes.Input("")] public ImageData inputPixels;

View File

@ -23,7 +23,7 @@ namespace ImageProcessingGraph.Editor.Nodes.Types.Image.Utilities
{
int pixelCount = Width * Height;
NativeArray<byte> outputData = new NativeArray<byte>(pixelCount * 4, Allocator.TempJob);
NativeArray<byte> outputData = new NativeArray<byte>(pixelCount * 4, Allocator.Persistent);
CreateSingleColorJob job = new CreateSingleColorJob
{
@ -36,8 +36,6 @@ namespace ImageProcessingGraph.Editor.Nodes.Types.Image.Utilities
job.Run();
OutputColor = new SplitChannelData(outputData.ToArray(), (Width, Height));
outputData.Dispose();
}
[BurstCompile]

View File

@ -3,6 +3,7 @@ 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;
@ -21,6 +22,8 @@ namespace ImageProcessingGraph.Editor.Unity_Image_Processing.Scripts.Editor.Wind
private ImageProcessingGraphViewWindow window;
private StyleSheet errorStyleSheet;
public ImageProcessingGraphNodeVisual(BaseImageNode node, ImageProcessingGraphViewWindow window)
{
this.AddToClassList("image-node-visual");
@ -62,9 +65,27 @@ namespace ImageProcessingGraph.Editor.Unity_Image_Processing.Scripts.Editor.Wind
}
}
CreateInputPorts(inputFieldInfo);
CreateOutputPorts(outputFieldInfo);
errorStyleSheet = AssetDatabase.LoadAssetAtPath<StyleSheet>("Assets/Unity Image Processing/Node.uss");
if (errorStyleSheet == null)
{
errorStyleSheet = EditorGUIUtility.Load("Packages/com.chromium.imageprocessingrah/Node.uss") as StyleSheet;
}
graphNode.onFailed += () =>
{
styleSheets.Add(errorStyleSheet);
};
window.asset.OnRun += () =>
{
if (styleSheets.Contains(errorStyleSheet))
styleSheets.Remove(errorStyleSheet);
};
this.name = typeInfo.Name;
}
@ -74,10 +95,6 @@ namespace ImageProcessingGraph.Editor.Unity_Image_Processing.Scripts.Editor.Wind
for (var index = 0; index < fields.Count; index++)
{
var field = fields[index];
/*
Port port = InstantiatePort(Orientation.Horizontal, Direction.Input, Port.Capacity.Multi, field.FieldType);
*/
var port = IPTPort.Create(window.edgeConnectorListener, true, field.FieldType);
string label = field.GetCustomAttribute<Input>().Label;
@ -87,7 +104,8 @@ namespace ImageProcessingGraph.Editor.Unity_Image_Processing.Scripts.Editor.Wind
inputContainer.Add(port);
ExposeVariableToPort(port, field);
port.fieldInfo = field;
}
}
@ -102,13 +120,14 @@ namespace ImageProcessingGraph.Editor.Unity_Image_Processing.Scripts.Editor.Wind
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
private void ExposeVariableToPort(Port port, FieldInfo field)
public void ExposeVariableToPort(Port port, FieldInfo field)
{
// Only expose when the port is not connected
if (port.connections.Count() == 0)
@ -207,6 +226,13 @@ namespace ImageProcessingGraph.Editor.Unity_Image_Processing.Scripts.Editor.Wind
else
{
// If the port is connected, remove the exposed UI element
List<VisualElement> children = new List<VisualElement>();
foreach (var child in port.Children())
{
children.Add(child);
}
var existingPropertyFieldContainer = port.Q<VisualElement>("property-field-container");
if (existingPropertyFieldContainer != null)
{

View File

@ -290,15 +290,34 @@ namespace ImageProcessingGraph.Editor
GraphConnection connection = new GraphConnection(inputNode.GraphNode.ID,inputIndex, inputType,outputNode.GraphNode.ID, outputIndex, outputType, edge);
edge.output.Connect(edge);
edge.input.Connect(edge);
IPTPort portIn = (IPTPort)edge.output;
IPTPort portOut = (IPTPort)edge.output;
if (portIn.fieldInfo != null)
inputNode.ExposeVariableToPort(edge.input, portOut.fieldInfo);
asset.Connections.Add(connection);
}
private void RemoveEdge(Edge variable)
private void RemoveEdge(Edge edge)
{
if (connectionDictionary.TryGetValue(variable, out GraphConnection connection))
if (connectionDictionary.TryGetValue(edge, out GraphConnection connection))
{
asset.Connections.Remove(connection);
connectionDictionary.Remove(variable);
connectionDictionary.Remove(edge);
edge.output.Disconnect(edge);
edge.input.Disconnect(edge);
ImageProcessingGraphNodeVisual inputNode = (ImageProcessingGraphNodeVisual)edge.input.node;
IPTPort portIn = (IPTPort)edge.input;
if(portIn.fieldInfo != null)
inputNode.ExposeVariableToPort(edge.input, portIn.fieldInfo);
}
}
@ -319,6 +338,8 @@ namespace ImageProcessingGraph.Editor
Edge edge = inPort.ConnectTo(outPort);
AddElement(edge);
connectionDictionary.Add(edge, conn);
}
}

7
Node.uss Normal file
View File

@ -0,0 +1,7 @@
#node-border
{
border-bottom-color: red;
border-left-color: red;
border-right-color: red;
border-top-color: red;
}

3
Node.uss.meta Normal file
View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: f213bce165884ca7ae5d567d6bb7f3cb
timeCreated: 1745777804