StationObscurum/Assets/Adobe/Substance3DForUnity/Runtime/Scripts/SubstanceNativeGraph.cs

914 lines
35 KiB
C#

//! @file substancearchive.cs
//! @brief Substance archive interface
//! @author Galen Helfter - Adobe
//! @date 20210609
//! @copyright Adobe. All rights reserved.
using System;
using System.Runtime.InteropServices;
using UnityEngine;
using Adobe.Substance.Input;
using Adobe.Substance.Input.Description;
namespace Adobe.Substance
{
/// <summary>
/// Object that represents a native C++ substance graph.
/// </summary>
public sealed class SubstanceNativeGraph : IDisposable
{
private IntPtr _handler;
private bool _disposedValue;
private bool _inRenderWork;
public bool IsInitialized { get; set; }
public bool InRenderWork
{
get
{
lock (this)
{
return _inRenderWork;
}
}
set
{
lock (this)
{
_inRenderWork = value;
}
}
}
private readonly int _fileGraphID;
/// <summary>
/// Create a object that acts as a brige between Unity and Substance C++ SDK.
/// </summary>
/// <param name="fileContent">Content of the sbsar file.</param>
/// <param name="targetGraphID">Target graph ID inside the file.</param>
internal SubstanceNativeGraph(byte[] fileContent, int targetGraphID)
{
_fileGraphID = targetGraphID;
int size = Marshal.SizeOf(fileContent[0]) * fileContent.Length;
var nativeMemory = Marshal.AllocHGlobal(size);
Marshal.Copy(fileContent, 0, nativeMemory, size);
try
{
_handler = NativeMethods.sbsario_sbsar_load_from_memory(nativeMemory, (IntPtr)size);
if (_handler == default)
throw new ArgumentException();
}
finally
{
if (nativeMemory != default)
Marshal.FreeHGlobal(nativeMemory);
}
}
/// <summary>
/// Renders graph.
/// </summary>
/// <returns>Native render result.</returns>
public IntPtr Render()
{
ErrorCode errorCode = (ErrorCode)NativeMethods.sbsario_sbsar_render(_handler, (IntPtr)_fileGraphID, out IntPtr result);
if (errorCode != ErrorCode.SBSARIO_ERROR_OK)
throw new SubstanceException(errorCode);
return result;
}
/// <summary>
/// Get raw thumbnail data from graph.
/// </summary>
/// <returns>Raw graph thumbnail RGBA data.</returns>
public byte[] GetThumbnail()
{
ErrorCode result = (ErrorCode)NativeMethods.sbsario_sbsar_get_graph_thumbnail(_handler, (IntPtr)_fileGraphID, out NativeThumbnail thumbnail);
if (result != ErrorCode.SBSARIO_ERROR_OK)
throw new SubstanceException(result);
if (thumbnail.Size == IntPtr.Zero)
return null;
var thumbnailData = new byte[(int)thumbnail.Size];
Marshal.Copy(thumbnail.Data, thumbnailData, 0, thumbnailData.Length);
return thumbnailData;
}
#region Presets
public string CreatePresetFromCurrentState()
{
//Alocate 1Mb for the preset file text.
NativePreset preset = new NativePreset
{
XMLString = Marshal.AllocHGlobal(1024 * 1024)
};
try
{
ErrorCode result = (ErrorCode)NativeMethods.sbsario_sbsar_make_preset_from_current_state(_handler, (IntPtr)_fileGraphID, ref preset);
if (result != ErrorCode.SBSARIO_ERROR_OK)
throw new SubstanceException(result);
var stringResult = Marshal.PtrToStringAnsi(preset.XMLString);
return stringResult;
}
finally
{
//Free native allocated memory.
Marshal.FreeHGlobal(preset.XMLString);
}
}
/// <summary>
/// Apply preset string to graph.
/// </summary>
/// <param name="presetXML"></param>
public void ApplyPreset(string presetXML)
{
NativePreset preset = new NativePreset();
preset.XMLString = Marshal.StringToHGlobalAnsi(presetXML);
try
{
ErrorCode result = (ErrorCode)NativeMethods.sbsario_sbsar_apply_preset(_handler, (IntPtr)_fileGraphID, ref preset);
if (result != ErrorCode.SBSARIO_ERROR_OK)
throw new SubstanceException(result);
}
finally
{
// Always free the unmanaged string.
Marshal.FreeHGlobal(preset.XMLString);
}
}
#endregion Presets
#region Output
/// <summary>
/// Get the total output count for a given graph in the substance object.
/// </summary>
/// <returns>Total graph output count.</returns>
public int GetOutputCount()
{
return (int)NativeMethods.sbsario_sbsar_get_output_count(_handler, (IntPtr)_fileGraphID);
}
public SubstanceOutputDescription GetOutputDescription(int outputID)
{
ErrorCode result = (ErrorCode)NativeMethods.sbsario_sbsar_get_output_desc(_handler, (IntPtr)_fileGraphID, (IntPtr)outputID, out NativeOutputDesc inputDesc);
if (result != ErrorCode.SBSARIO_ERROR_OK)
throw new SubstanceException(result);
var identifier = Marshal.PtrToStringAnsi(inputDesc.mIdentifier);
var label = Marshal.PtrToStringAnsi(inputDesc.mIdentifier);
var channel = Marshal.PtrToStringAnsi(inputDesc.mChannelUsage);
if (string.IsNullOrEmpty(channel))
{
Debug.LogWarning($"Output {outputID} does not have a channel type. This output will not be rendered. ");
channel = "unkown";
}
if (string.IsNullOrEmpty(identifier))
{
Debug.LogWarning($"Output {outputID} does not have a identifier.");
identifier = "unkown";
}
if (string.IsNullOrEmpty(label))
{
Debug.LogWarning($"Output {outputID} does not have a label.");
label = "unkown";
}
return new SubstanceOutputDescription()
{
Identifier = identifier,
Label = label,
Index = (int)inputDesc.mIndex,
Type = inputDesc.mValueType.ToUnity(),
Channel = channel
};
}
public SubstanceOutputDescription CreateVirtualOutput(SubstanceVirtualOutputCreateInfo info)
{
var description = info.CreateOutputDesc();
var format = info.CreateOutputFormat();
ErrorCode result = (ErrorCode)NativeMethods.sbsario_sbsar_create_virtual_output(_handler, (IntPtr)_fileGraphID, ref description, ref format);
if (result != ErrorCode.SBSARIO_ERROR_OK)
throw new SubstanceException(result);
var identifier = Marshal.PtrToStringAnsi(description.mIdentifier);
var label = Marshal.PtrToStringAnsi(description.mIdentifier);
var channel = Marshal.PtrToStringAnsi(description.mChannelUsage);
return new SubstanceOutputDescription()
{
Identifier = identifier,
Label = label,
Index = (int)description.mIndex,
Type = description.mValueType.ToUnity(),
Channel = channel,
};
}
public int CreateOutputCopy(int outputID)
{
ErrorCode result = (ErrorCode)NativeMethods.sbsario_sbsar_create_output_copy(_handler, (IntPtr)_fileGraphID, (IntPtr)outputID, out NativeOutputDesc inputDesc);
if (result != ErrorCode.SBSARIO_ERROR_OK)
throw new SubstanceException(result);
return (int)inputDesc.mIndex;
}
public uint GetOutputUID(int outputIndex)
{
ErrorCode result = (ErrorCode)NativeMethods.sbsario_sbsar_get_output_uid(_handler, (IntPtr)_fileGraphID, (IntPtr)outputIndex, out IntPtr outputUID);
if (result != ErrorCode.SBSARIO_ERROR_OK)
throw new SubstanceException(result);
return (uint)outputUID;
}
public void AssignOutputToAlphaChannel(int targetOutputID, int alphaChannelID, bool invert = false)
{
float minValue = invert ? 1f : 0f;
float maxValue = invert ? 0f : 1f;
ErrorCode result = (ErrorCode)NativeMethods.sbsario_sbsar_assign_as_alpha_channel(_handler, (IntPtr)_fileGraphID, (IntPtr)targetOutputID, (IntPtr)alphaChannelID, minValue, maxValue);
if (result != ErrorCode.SBSARIO_ERROR_OK)
throw new SubstanceException(result);
}
public void ResetAlphaChannelAssignment(int targetOutputID)
{
ErrorCode result = (ErrorCode)NativeMethods.sbsario_sbsar_get_output_desc(_handler, (IntPtr)_fileGraphID, (IntPtr)targetOutputID, out NativeOutputDesc outputDesc);
if (result != ErrorCode.SBSARIO_ERROR_OK)
throw new SubstanceException(result);
result = (ErrorCode)NativeMethods.sbsario_sbsar_get_output_format_override(_handler, (IntPtr)_fileGraphID, (IntPtr)targetOutputID, out IntPtr isFormatOverridenPtr, out NativeOutputFormat oldFormat);
if (result != ErrorCode.SBSARIO_ERROR_OK)
throw new SubstanceException(result);
bool isFormatOverriden = (int)isFormatOverridenPtr != 0;
if (!isFormatOverriden)
return;
if (oldFormat.format == NativeConsts.UseDefault)
return;
NativeOutputFormat newFormat = oldFormat;
newFormat.format = NativeConsts.UseDefault;
result = (ErrorCode)NativeMethods.sbsario_sbsar_set_output_format_override(_handler, (IntPtr)_fileGraphID, (IntPtr)targetOutputID, ref newFormat);
if (result != ErrorCode.SBSARIO_ERROR_OK)
throw new SubstanceException(result);
}
public void ChangeOutputRBChannels(int targetOutputID)
{
ErrorCode result = (ErrorCode)NativeMethods.sbsario_sbsar_get_output_format_override(_handler, (IntPtr)_fileGraphID, (IntPtr)targetOutputID, out IntPtr isFormatOverridenPtr, out NativeOutputFormat oldFormat);
if (result != ErrorCode.SBSARIO_ERROR_OK)
throw new SubstanceException(result);
bool isFormatOverriden = (int)isFormatOverridenPtr != 0;
NativeOutputFormat newFormat = NativeOutputFormat.CreateDefault();
if (isFormatOverriden)
newFormat = oldFormat;
var redChannel = newFormat.ChannelComponent0;
var blueChannel = newFormat.ChannelComponent2;
if (blueChannel.outputIndex == NativeConsts.UseDefault || redChannel.outputIndex == NativeConsts.UseDefault)
return;
if (newFormat.ChannelComponent0.ShuffleIndex == ShuffleIndex.Blue &&
newFormat.ChannelComponent2.ShuffleIndex == ShuffleIndex.Red)
{
return;
}
newFormat.ChannelComponent0.ShuffleIndex = ShuffleIndex.Blue;
newFormat.ChannelComponent2.ShuffleIndex = ShuffleIndex.Red;
result = (ErrorCode)NativeMethods.sbsario_sbsar_set_output_format_override(_handler, (IntPtr)_fileGraphID, (IntPtr)targetOutputID, ref newFormat);
if (result != ErrorCode.SBSARIO_ERROR_OK)
throw new SubstanceException(result);
}
#endregion Output
#region Input
/// <summary>
/// Get the total input count for a given graph in the substance object.
/// </summary>
/// <returns>Total graph input count.</returns>
public int GetInputCount()
{
return (int)NativeMethods.sbsario_sbsar_get_input_count(_handler, (IntPtr)_fileGraphID);
}
/// <summary>
/// Get the input object for a given graph in the substance object.
/// </summary>
/// <param name="inputID">Input index.</param>
/// <returns>Substance input object.</returns>
public SubstanceInputBase GetInputObject(int inputID)
{
ErrorCode result = (ErrorCode)NativeMethods.sbsario_sbsar_get_input(_handler, (IntPtr)_fileGraphID, (IntPtr)inputID, out NativeData inputDesc);
if (result != ErrorCode.SBSARIO_ERROR_OK)
{
if (result == ErrorCode.SBSARIO_ERROR_FAILURE)
{
Debug.LogWarning($"Unable to load input from graphID: {_fileGraphID} and inputID:{inputID}. The input type is not supported.");
return SubstanceInputFactory.CreateInvalidInput(inputID);
}
throw new SubstanceException(result);
}
var input = SubstanceInputFactory.CreateInput(inputDesc);
AssignInputDescription(inputID, input);
return input;
}
/// <summary>
/// Returns true if the target input should be visible in the editor.
/// </summary>
/// <param name="inputID">Target input ID.</param>
/// <returns>True if the target input should be visible in the editor.</returns>
public bool IsInputVisible(int inputID)
{
ErrorCode result = (ErrorCode)NativeMethods.sbsario_sbsar_get_input_visibility(_handler, (IntPtr)_fileGraphID, (IntPtr)inputID, out NativeInputVisibility visibility);
if (result != ErrorCode.SBSARIO_ERROR_OK)
throw new SubstanceException(result);
return (int)visibility.IsVisible == 1;
}
/// <summary>
/// Sets a float input.
/// </summary>
/// <param name="inputID">Input index.</param>
/// <param name="value">Input value.</param>
public void SetInputFloat(int inputID, float value)
{
NativeData inputData = new NativeData();
inputData.DataType = DataType.SBSARIO_DATA_INPUT;
inputData.ValueType = ValueType.SBSARIO_VALUE_FLOAT;
inputData.Index = (IntPtr)inputID;
inputData.Data = new DataInternalNumeric();
inputData.Data.mFloatData0 = value;
ErrorCode result = (ErrorCode)NativeMethods.sbsario_sbsar_set_input(_handler, (IntPtr)_fileGraphID, ref inputData);
if (result != ErrorCode.SBSARIO_ERROR_OK)
{
Debug.LogError($"Fail to update Substance input {inputID} for graph {_fileGraphID}");
throw new SubstanceException(result);
}
}
/// <summary>
/// Sets a float2 input.
/// </summary>
/// <param name="inputID">Input index.</param>
/// <param name="value">Input value.</param>
public void SetInputFloat2(int inputID, Vector2 value)
{
NativeData inputData = new NativeData();
inputData.DataType = DataType.SBSARIO_DATA_INPUT;
inputData.ValueType = ValueType.SBSARIO_VALUE_FLOAT2;
inputData.Index = (IntPtr)inputID;
inputData.Data = new DataInternalNumeric();
inputData.Data.mFloatData0 = value.x;
inputData.Data.mFloatData1 = value.y;
ErrorCode result = (ErrorCode)NativeMethods.sbsario_sbsar_set_input(_handler, (IntPtr)_fileGraphID, ref inputData);
if (result != ErrorCode.SBSARIO_ERROR_OK)
{
Debug.LogError($"Fail to update Substance input {inputID} for graph {_fileGraphID}");
throw new SubstanceException(result);
}
}
/// <summary>
/// Sets a float3 input.
/// </summary>
/// <param name="inputID">Input index.</param>
/// <param name="value">Input value.</param>
public void SetInputFloat3(int inputID, Vector3 value)
{
NativeData inputData = new NativeData();
inputData.DataType = DataType.SBSARIO_DATA_INPUT;
inputData.ValueType = ValueType.SBSARIO_VALUE_FLOAT3;
inputData.Index = (IntPtr)inputID;
inputData.Data = new DataInternalNumeric();
inputData.Data.mFloatData0 = value.x;
inputData.Data.mFloatData1 = value.y;
inputData.Data.mFloatData2 = value.z;
ErrorCode result = (ErrorCode)NativeMethods.sbsario_sbsar_set_input(_handler, (IntPtr)_fileGraphID, ref inputData);
if (result != ErrorCode.SBSARIO_ERROR_OK)
{
Debug.LogError($"Fail to update Substance input {inputID} for graph {_fileGraphID}");
throw new SubstanceException(result);
}
}
/// <summary>
/// Sets a float4 input.
/// </summary>
/// <param name="inputID">Input index.</param>
/// <param name="value">Input value.</param>
public void SetInputFloat4(int inputID, Vector4 value)
{
NativeData inputData = new NativeData();
inputData.DataType = DataType.SBSARIO_DATA_INPUT;
inputData.ValueType = ValueType.SBSARIO_VALUE_FLOAT4;
inputData.Index = (IntPtr)inputID;
inputData.Data = new DataInternalNumeric();
inputData.Data.mFloatData0 = value.x;
inputData.Data.mFloatData1 = value.y;
inputData.Data.mFloatData2 = value.z;
inputData.Data.mFloatData3 = value.w;
ErrorCode result = (ErrorCode)NativeMethods.sbsario_sbsar_set_input(_handler, (IntPtr)_fileGraphID, ref inputData);
if (result != ErrorCode.SBSARIO_ERROR_OK)
{
Debug.LogError($"Fail to update Substance input {inputID} for graph {_fileGraphID}");
throw new SubstanceException(result);
}
}
/// <summary>
/// Sets a int input.
/// </summary>
/// <param name="inputID">Input index.</param>
/// <param name="value">Input value.</param>
public void SetInputInt(int inputID, int value)
{
NativeData inputData = new NativeData();
inputData.DataType = DataType.SBSARIO_DATA_INPUT;
inputData.ValueType = ValueType.SBSARIO_VALUE_INT;
inputData.Index = (IntPtr)inputID;
inputData.Data = new DataInternalNumeric();
inputData.Data.mIntData0 = value;
ErrorCode result = (ErrorCode)NativeMethods.sbsario_sbsar_set_input(_handler, (IntPtr)_fileGraphID, ref inputData);
if (result != ErrorCode.SBSARIO_ERROR_OK)
{
Debug.LogError($"Fail to update Substance input {inputID} for graph {_fileGraphID}");
throw new SubstanceException(result);
}
}
/// <summary>
/// Sets a int2 input.
/// </summary>
/// <param name="inputID">Input index.</param>
/// <param name="value">Input value.</param>
public void SetInputInt2(int inputID, Vector2Int value)
{
NativeData inputData = new NativeData();
inputData.DataType = DataType.SBSARIO_DATA_INPUT;
inputData.ValueType = ValueType.SBSARIO_VALUE_INT2;
inputData.Index = (IntPtr)inputID;
inputData.Data = new DataInternalNumeric();
inputData.Data.mIntData0 = value.x;
inputData.Data.mIntData1 = value.y;
ErrorCode result = (ErrorCode)NativeMethods.sbsario_sbsar_set_input(_handler, (IntPtr)_fileGraphID, ref inputData);
if (result != ErrorCode.SBSARIO_ERROR_OK)
{
Debug.LogError($"Fail to update Substance input {inputID} for graph {_fileGraphID}");
throw new SubstanceException(result);
}
}
/// <summary>
/// Sets a int3 input.
/// </summary>
/// <param name="inputID">Input index.</param>
/// <param name="value">Input value.</param>
public void SetInputInt3(int inputID, Vector3Int value)
{
NativeData inputData = new NativeData();
inputData.DataType = DataType.SBSARIO_DATA_INPUT;
inputData.ValueType = ValueType.SBSARIO_VALUE_INT3;
inputData.Index = (IntPtr)inputID;
inputData.Data = new DataInternalNumeric();
inputData.Data.mIntData0 = value.x;
inputData.Data.mIntData1 = value.y;
inputData.Data.mIntData2 = value.z;
ErrorCode result = (ErrorCode)NativeMethods.sbsario_sbsar_set_input(_handler, (IntPtr)_fileGraphID, ref inputData);
if (result != ErrorCode.SBSARIO_ERROR_OK)
{
Debug.LogError($"Fail to update Substance input {inputID} for graph {_fileGraphID}");
throw new SubstanceException(result);
}
}
/// <summary>
/// Sets a int4 input.
/// </summary>
/// <param name="inputID">Input index.</param>
/// <param name="x">Input x value.</param>
/// <param name="y">Input y value.</param>
/// <param name="z">Input z value.</param>
/// <param name="w">Input w value.</param>
public void SetInputInt4(int inputID, int x, int y, int z, int w)
{
NativeData inputData = new NativeData();
inputData.DataType = DataType.SBSARIO_DATA_INPUT;
inputData.ValueType = ValueType.SBSARIO_VALUE_INT4;
inputData.Index = (IntPtr)inputID;
inputData.Data = new DataInternalNumeric();
inputData.Data.mIntData0 = x;
inputData.Data.mIntData1 = y;
inputData.Data.mIntData2 = z;
inputData.Data.mIntData3 = w;
ErrorCode result = (ErrorCode)NativeMethods.sbsario_sbsar_set_input(_handler, (IntPtr)_fileGraphID, ref inputData);
if (result != ErrorCode.SBSARIO_ERROR_OK)
{
Debug.LogError($"Fail to update Substance input {inputID} for graph {_fileGraphID}");
throw new SubstanceException(result);
}
}
public void SetInputString(int inputID, string value)
{
NativeData inputData = new NativeData();
inputData.DataType = DataType.SBSARIO_DATA_INPUT;
inputData.ValueType = ValueType.SBSARIO_VALUE_STRING;
inputData.Index = (IntPtr)inputID;
inputData.Data = new DataInternalNumeric();
inputData.Data.mPtr = Marshal.StringToHGlobalAnsi(value);
ErrorCode result = (ErrorCode)NativeMethods.sbsario_sbsar_set_input(_handler, (IntPtr)_fileGraphID, ref inputData);
if (result != ErrorCode.SBSARIO_ERROR_OK)
{
Debug.LogError($"Fail to update Substance input {inputID} for graph {_fileGraphID}");
throw new SubstanceException(result);
}
}
public void SetInputTexture2DNull(int inputID)
{
var imageData = new NativeDataImage
{
channel_order = ChannelOrder.SBSARIO_CHANNEL_ORDER_RGBA,
height = IntPtr.Zero,
width = IntPtr.Zero
};
var numericData = new DataInternalNumeric
{
ImageData = imageData
};
NativeData inputData = new NativeData
{
DataType = DataType.SBSARIO_DATA_INPUT,
ValueType = ValueType.SBSARIO_VALUE_IMAGE,
Index = (IntPtr)inputID,
Data = numericData
};
ErrorCode result = (ErrorCode)NativeMethods.sbsario_sbsar_set_input(_handler, (IntPtr)_fileGraphID, ref inputData);
if (result != ErrorCode.SBSARIO_ERROR_OK)
{
Debug.LogError($"Fail to update Substance input {inputID} for graph {_fileGraphID}");
throw new SubstanceException(result);
}
}
public void SetInputTexture2D(int inputID, Color32[] pixelData, int width, int height)
{
if (pixelData == null)
return;
Color32[] flippedData = TextureExtensions.FlipY(pixelData, width, height);
byte[] textureBytes = TextureExtensions.Color32ArrayToByteArray(flippedData);
int textureSize = Marshal.SizeOf(textureBytes[0]) * textureBytes.Length;
IntPtr tempNativeMemory = Marshal.AllocHGlobal(textureSize);
Marshal.Copy(textureBytes, 0, tempNativeMemory, textureBytes.Length);
var imageData = new NativeDataImage
{
channel_order = ChannelOrder.SBSARIO_CHANNEL_ORDER_RGBA,
height = (IntPtr)width,
width = (IntPtr)height,
mipmaps = (IntPtr)0,
image_format = TextureFormat.RGBA32.ToSubstance(),
data = tempNativeMemory
};
var numericData = new DataInternalNumeric
{
ImageData = imageData
};
NativeData inputData = new NativeData
{
DataType = DataType.SBSARIO_DATA_INPUT,
ValueType = ValueType.SBSARIO_VALUE_IMAGE,
Index = (IntPtr)inputID,
Data = numericData
};
try
{
ErrorCode result = (ErrorCode)NativeMethods.sbsario_sbsar_set_input(_handler, (IntPtr)_fileGraphID, ref inputData);
if (result != ErrorCode.SBSARIO_ERROR_OK)
{
Debug.LogError($"Fail to update Substance input {inputID} for graph {_fileGraphID}");
throw new SubstanceException(result);
}
}
catch (Exception)
{
throw;
}
finally
{
Marshal.FreeHGlobal(tempNativeMemory);
}
}
public float GetInputFloat(int inputID)
{
ErrorCode result = (ErrorCode)NativeMethods.sbsario_sbsar_get_input(_handler, (IntPtr)_fileGraphID, (IntPtr)inputID, out NativeData inputDesc);
if (result != ErrorCode.SBSARIO_ERROR_OK)
{
Debug.LogError($"Fail to get Substance input {inputID} for graph {_fileGraphID}");
throw new SubstanceException(result);
}
return inputDesc.Data.mFloatData0;
}
public Vector2 GetInputFloat2(int inputID)
{
ErrorCode result = (ErrorCode)NativeMethods.sbsario_sbsar_get_input(_handler, (IntPtr)_fileGraphID, (IntPtr)inputID, out NativeData inputDesc);
if (result != ErrorCode.SBSARIO_ERROR_OK)
{
Debug.LogError($"Fail to get Substance input {inputID} for graph {_fileGraphID}");
throw new SubstanceException(result);
}
return new Vector2(inputDesc.Data.mFloatData0, inputDesc.Data.mFloatData1);
}
public Vector3 GetInputFloat3(int inputID)
{
ErrorCode result = (ErrorCode)NativeMethods.sbsario_sbsar_get_input(_handler, (IntPtr)_fileGraphID, (IntPtr)inputID, out NativeData inputDesc);
if (result != ErrorCode.SBSARIO_ERROR_OK)
{
Debug.LogError($"Fail to get Substance input {inputID} for graph {_fileGraphID}");
throw new SubstanceException(result);
}
return new Vector3(inputDesc.Data.mFloatData0, inputDesc.Data.mFloatData1, inputDesc.Data.mFloatData2);
}
public Vector4 GetInputFloat4(int inputID)
{
ErrorCode result = (ErrorCode)NativeMethods.sbsario_sbsar_get_input(_handler, (IntPtr)_fileGraphID, (IntPtr)inputID, out NativeData inputDesc);
if (result != ErrorCode.SBSARIO_ERROR_OK)
{
Debug.LogError($"Fail to get Substance input {inputID} for graph {_fileGraphID}");
throw new SubstanceException(result);
}
return new Vector4(inputDesc.Data.mFloatData0, inputDesc.Data.mFloatData1, inputDesc.Data.mFloatData2, inputDesc.Data.mFloatData2);
}
public int GetInputInt(int inputID)
{
ErrorCode result = (ErrorCode)NativeMethods.sbsario_sbsar_get_input(_handler, (IntPtr)_fileGraphID, (IntPtr)inputID, out NativeData inputDesc);
if (result != ErrorCode.SBSARIO_ERROR_OK)
{
Debug.LogError($"Fail to get Substance input {inputID} for graph {_fileGraphID}");
throw new SubstanceException(result);
}
return inputDesc.Data.mIntData0;
}
public Vector2Int GetInputInt2(int inputID)
{
ErrorCode result = (ErrorCode)NativeMethods.sbsario_sbsar_get_input(_handler, (IntPtr)_fileGraphID, (IntPtr)inputID, out NativeData inputDesc);
if (result != ErrorCode.SBSARIO_ERROR_OK)
{
Debug.LogError($"Fail to get Substance input {inputID} for graph {_fileGraphID}");
throw new SubstanceException(result);
}
return new Vector2Int(inputDesc.Data.mIntData0, inputDesc.Data.mIntData1);
}
public Vector3Int GetInputInt3(int inputID)
{
ErrorCode result = (ErrorCode)NativeMethods.sbsario_sbsar_get_input(_handler, (IntPtr)_fileGraphID, (IntPtr)inputID, out NativeData inputDesc);
if (result != ErrorCode.SBSARIO_ERROR_OK)
{
Debug.LogError($"Fail to get Substance input {inputID} for graph {_fileGraphID}");
throw new SubstanceException(result);
}
return new Vector3Int(inputDesc.Data.mIntData0, inputDesc.Data.mIntData1, inputDesc.Data.mIntData2);
}
public int[] GetInputInt4(int inputID)
{
ErrorCode result = (ErrorCode)NativeMethods.sbsario_sbsar_get_input(_handler, (IntPtr)_fileGraphID, (IntPtr)inputID, out NativeData inputDesc);
if (result != ErrorCode.SBSARIO_ERROR_OK)
{
Debug.LogError($"Fail to get Substance input {inputID} for graph {_fileGraphID}");
throw new SubstanceException(result);
}
return new int[] { inputDesc.Data.mIntData0, inputDesc.Data.mIntData1, inputDesc.Data.mIntData2, inputDesc.Data.mIntData2 };
}
public string GetInputString(int inputID)
{
ErrorCode result = (ErrorCode)NativeMethods.sbsario_sbsar_get_input(_handler, (IntPtr)_fileGraphID, (IntPtr)inputID, out NativeData inputDesc);
if (result != ErrorCode.SBSARIO_ERROR_OK)
{
Debug.LogError($"Fail to get Substance input {inputID} for graph {_fileGraphID}");
throw new SubstanceException(result);
}
return Marshal.PtrToStringAnsi(inputDesc.Data.mPtr);
}
#endregion Input
public IntPtr GetNativeHandle()
{
return _handler;
}
public int GetFileGraphID()
{
return _fileGraphID;
}
#region IDisposable
public void Dispose()
{
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if (!_disposedValue)
{
if (_handler != default)
{
NativeMethods.sbsario_sbsar_close(_handler);
_handler = default;
}
_disposedValue = true;
}
}
~SubstanceNativeGraph()
{
Dispose(disposing: false);
}
#endregion IDisposable
private void AssignInputDescription(int inputID, SubstanceInputBase input)
{
ErrorCode result = (ErrorCode)NativeMethods.sbsario_sbsar_get_input_desc(_handler, (IntPtr)_fileGraphID, (IntPtr)inputID, out NativeInputDesc inputDesc);
if (result != ErrorCode.SBSARIO_ERROR_OK)
throw new SubstanceException(result);
var identifier = inputDesc.mIdentifier == default ? null : Marshal.PtrToStringAnsi(inputDesc.mIdentifier);
var label = inputDesc.mLabel == default ? null : Marshal.PtrToStringAnsi(inputDesc.mLabel);
var guiGroup = inputDesc.GuiGroup == default ? null : Marshal.PtrToStringAnsi(inputDesc.GuiGroup);
var guiDescription = inputDesc.GuiDescription == default ? null : Marshal.PtrToStringAnsi(inputDesc.GuiDescription);
input.Description = new SubstanceInputDescription()
{
Identifier = identifier,
Label = label,
GuiGroup = guiGroup,
GuiDescription = guiDescription,
Type = ((ValueType)inputDesc.mValueType).ToUnity(),
WidgetType = ((WidgetType)inputDesc.inputWidgetType).ToUnity()
};
if (input.IsNumeric)
AssignNumericInputDescription(inputID, input);
}
private void AssignNumericInputDescription(int inputID, SubstanceInputBase substanceInput)
{
ErrorCode result = (ErrorCode)NativeMethods.sbsario_sbsar_get_numeric_input_desc(_handler, (IntPtr)_fileGraphID, (IntPtr)inputID, out NativeNumericInputDesc inputDesc);
if (result != ErrorCode.SBSARIO_ERROR_OK)
throw new SubstanceException(result);
substanceInput.SetNumericDescription(inputDesc);
if ((int)(inputDesc.enumValueCount) != 0)
{
var count = (int)inputDesc.enumValueCount;
NativeEnumInputDesc[] buffer = new NativeEnumInputDesc[count];
GCHandle gcHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
IntPtr pointer = gcHandle.AddrOfPinnedObject();
try
{
result = (ErrorCode)NativeMethods.sbsario_sbsar_get_enum_input_desc(_handler, (IntPtr)_fileGraphID, (IntPtr)inputID, pointer, inputDesc.enumValueCount);
substanceInput.SetEnumOptions(buffer);
if (result != ErrorCode.SBSARIO_ERROR_OK)
{
Debug.LogError("Unable to get data for enum.");
return;
}
}
finally
{
gcHandle.Free();
}
}
}
public Vector3 GetPhysicalSize()
{
ErrorCode result = (ErrorCode)NativeMethods.sbsario_sbsar_get_physical_size(_handler, (IntPtr)_fileGraphID, out NativePhysicalSize nativePhysicalSize);
if (result != ErrorCode.SBSARIO_ERROR_OK)
{
Debug.LogError($"Fail to get Substance input physical size for graph {_fileGraphID}");
throw new SubstanceException(result);
}
return new Vector3(nativePhysicalSize.X, nativePhysicalSize.Y, nativePhysicalSize.Z);
}
}
} // namespace Adobe.Substance