425 lines
15 KiB
C#
425 lines
15 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
namespace Adobe.Substance
|
|
{
|
|
/// <summary>
|
|
/// Extensions for handling enum type convertion.
|
|
/// </summary>
|
|
internal static class Extensions
|
|
{
|
|
/// <summary>
|
|
/// Transforms a unity value type enum into an enum used by native code.
|
|
/// </summary>
|
|
/// <param name="unityType">Unity enum.</param>
|
|
/// <returns>Native enum.</returns>
|
|
internal static ValueType ToNative(this SubstanceValueType unityType)
|
|
{
|
|
switch (unityType)
|
|
{
|
|
case SubstanceValueType.Float:
|
|
return ValueType.SBSARIO_VALUE_FLOAT;
|
|
|
|
case SubstanceValueType.Float2:
|
|
return ValueType.SBSARIO_VALUE_FLOAT2;
|
|
|
|
case SubstanceValueType.Float3:
|
|
return ValueType.SBSARIO_VALUE_FLOAT3;
|
|
|
|
case SubstanceValueType.Float4:
|
|
return ValueType.SBSARIO_VALUE_FLOAT4;
|
|
|
|
case SubstanceValueType.Int:
|
|
return ValueType.SBSARIO_VALUE_INT;
|
|
|
|
case SubstanceValueType.Int2:
|
|
return ValueType.SBSARIO_VALUE_INT2;
|
|
|
|
case SubstanceValueType.Int3:
|
|
return ValueType.SBSARIO_VALUE_INT3;
|
|
|
|
case SubstanceValueType.Int4:
|
|
return ValueType.SBSARIO_VALUE_INT4;
|
|
|
|
case SubstanceValueType.Image:
|
|
return ValueType.SBSARIO_VALUE_IMAGE;
|
|
|
|
case SubstanceValueType.String:
|
|
return ValueType.SBSARIO_VALUE_STRING;
|
|
|
|
case SubstanceValueType.Font:
|
|
return ValueType.SBSARIO_VALUE_FONT;
|
|
|
|
default:
|
|
throw new System.InvalidOperationException($"Value type {unityType} can not be converted to native enum.");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Transforms a native value type enum into an enum used by the unity plugin.
|
|
/// </summary>
|
|
/// <param name="nativeType">Native enum.</param>
|
|
/// <returns>Unity enum.</returns>
|
|
internal static SubstanceValueType ToUnity(this ValueType nativeType)
|
|
{
|
|
switch (nativeType)
|
|
{
|
|
case ValueType.SBSARIO_VALUE_FLOAT:
|
|
return SubstanceValueType.Float;
|
|
|
|
case ValueType.SBSARIO_VALUE_FLOAT2:
|
|
return SubstanceValueType.Float2;
|
|
|
|
case ValueType.SBSARIO_VALUE_FLOAT3:
|
|
return SubstanceValueType.Float3;
|
|
|
|
case ValueType.SBSARIO_VALUE_FLOAT4:
|
|
return SubstanceValueType.Float4;
|
|
|
|
case ValueType.SBSARIO_VALUE_INT:
|
|
return SubstanceValueType.Int;
|
|
|
|
case ValueType.SBSARIO_VALUE_INT2:
|
|
return SubstanceValueType.Int2;
|
|
|
|
case ValueType.SBSARIO_VALUE_INT3:
|
|
return SubstanceValueType.Int3;
|
|
|
|
case ValueType.SBSARIO_VALUE_INT4:
|
|
return SubstanceValueType.Int4;
|
|
|
|
case ValueType.SBSARIO_VALUE_IMAGE:
|
|
return SubstanceValueType.Image;
|
|
|
|
case ValueType.SBSARIO_VALUE_STRING:
|
|
return SubstanceValueType.String;
|
|
|
|
case ValueType.SBSARIO_VALUE_FONT:
|
|
return SubstanceValueType.Font;
|
|
|
|
default:
|
|
throw new System.InvalidOperationException($"Value type {nativeType} can not be converted to unity enum.");
|
|
}
|
|
}
|
|
|
|
internal static SubstanceWidgetType ToUnity(this WidgetType nativeType)
|
|
{
|
|
switch (nativeType)
|
|
{
|
|
case WidgetType.SBSARIO_WIDGET_NOWIDGET:
|
|
return SubstanceWidgetType.NoWidget;
|
|
|
|
case WidgetType.SBSARIO_WIDGET_SLIDER:
|
|
return SubstanceWidgetType.Slider;
|
|
|
|
case WidgetType.SBSARIO_WIDGET_ANGLE:
|
|
return SubstanceWidgetType.Angle;
|
|
|
|
case WidgetType.SBSARIO_WIDGET_COLOR:
|
|
return SubstanceWidgetType.Color;
|
|
|
|
case WidgetType.SBSARIO_WIDGET_TOGGLEBUTTON:
|
|
return SubstanceWidgetType.ToggleButton;
|
|
|
|
case WidgetType.SBSARIO_WIDGET_COMBOBOX:
|
|
return SubstanceWidgetType.ComboBox;
|
|
|
|
case WidgetType.SBSARIO_WIDGET_IMAGE:
|
|
return SubstanceWidgetType.Image;
|
|
|
|
case WidgetType.SBSARIO_WIDGET_POSITION:
|
|
return SubstanceWidgetType.Position;
|
|
|
|
default:
|
|
throw new System.InvalidOperationException($"Value type {nativeType} can not be converted to unity enum.");
|
|
}
|
|
}
|
|
|
|
internal static string GetMessage(this ErrorCode code)
|
|
{
|
|
switch (code)
|
|
{
|
|
case ErrorCode.SBSARIO_ERROR_OK:
|
|
return "No error has occurred";
|
|
|
|
case ErrorCode.SBSARIO_ERROR_STATE:
|
|
return "Call made with an invalid state";
|
|
|
|
case ErrorCode.SBSARIO_ERROR_INVALID:
|
|
return "An invalid argument was given to the api";
|
|
|
|
case ErrorCode.SBSARIO_ERROR_UNKNOWN:
|
|
return "An unspecified error has occurred";
|
|
|
|
case ErrorCode.SBSARIO_ERROR_FAILURE:
|
|
return "The operation failed to complete";
|
|
|
|
default:
|
|
return "No error has occurred";
|
|
}
|
|
}
|
|
|
|
public static HVFlip ToSubstance(this TextureFlip flip)
|
|
{
|
|
switch (flip)
|
|
{
|
|
case TextureFlip.None:
|
|
return HVFlip.SBSARIO_HVFLIP_NO;
|
|
|
|
case TextureFlip.Horizontal:
|
|
return HVFlip.SBSARIO_HVFLIP_HORIZONTAL;
|
|
|
|
case TextureFlip.Vertical:
|
|
return HVFlip.SBSARIO_HVFLIP_VERTICAL;
|
|
|
|
case TextureFlip.Both:
|
|
return HVFlip.SBSARIO_HVFLIP_BOTH;
|
|
|
|
default:
|
|
throw new System.InvalidOperationException($"Unable to convert {flip} to native enum.");
|
|
}
|
|
}
|
|
|
|
public static ChannelOrder GetChannelOrder(this TextureFormat unityFormat)
|
|
{
|
|
switch (unityFormat)
|
|
{
|
|
case TextureFormat.RGB24:
|
|
case TextureFormat.RGBA32:
|
|
case TextureFormat.RGBA64:
|
|
case TextureFormat.RGB48:
|
|
return ChannelOrder.SBSARIO_CHANNEL_ORDER_RGBA;
|
|
|
|
case TextureFormat.BGRA32:
|
|
return ChannelOrder.SBSARIO_CHANNEL_ORDER_BGRA;
|
|
|
|
default:
|
|
return ChannelOrder.SBSARIO_CHANNEL_ORDER_INVALID;
|
|
}
|
|
}
|
|
|
|
#region Image Format
|
|
|
|
public static ImageFormat ToSubstance(this TextureFormat unityFormat)
|
|
{
|
|
switch (unityFormat)
|
|
{
|
|
//Byte types.
|
|
case TextureFormat.BGRA32:
|
|
case TextureFormat.RGBA32:
|
|
return ImageFormat.SBSARIO_IMAGE_FORMAT_8B | ImageFormat.SBSARIO_IMAGE_FORMAT_RGBA | ImageFormat.SBSARIO_IMAGE_FORMAT_INT;
|
|
|
|
case TextureFormat.RGB24:
|
|
return ImageFormat.SBSARIO_IMAGE_FORMAT_8B | ImageFormat.SBSARIO_IMAGE_FORMAT_RGB | ImageFormat.SBSARIO_IMAGE_FORMAT_INT;
|
|
|
|
case TextureFormat.R8:
|
|
return ImageFormat.SBSARIO_IMAGE_FORMAT_8B | ImageFormat.SBSARIO_IMAGE_FORMAT_L | ImageFormat.SBSARIO_IMAGE_FORMAT_INT;
|
|
|
|
//Short types
|
|
case TextureFormat.R16:
|
|
return ImageFormat.SBSARIO_IMAGE_FORMAT_16B | ImageFormat.SBSARIO_IMAGE_FORMAT_L | ImageFormat.SBSARIO_IMAGE_FORMAT_INT;
|
|
|
|
case TextureFormat.RGBA64:
|
|
return ImageFormat.SBSARIO_IMAGE_FORMAT_16B | ImageFormat.SBSARIO_IMAGE_FORMAT_RGBA | ImageFormat.SBSARIO_IMAGE_FORMAT_INT;
|
|
|
|
//Float types
|
|
case TextureFormat.RGBAFloat:
|
|
return ImageFormat.SBSARIO_IMAGE_FORMAT_32B | ImageFormat.SBSARIO_IMAGE_FORMAT_RGBA | ImageFormat.SBSARIO_IMAGE_FORMAT_FLOAT;
|
|
|
|
case TextureFormat.RFloat:
|
|
return ImageFormat.SBSARIO_IMAGE_FORMAT_32B | ImageFormat.SBSARIO_IMAGE_FORMAT_L | ImageFormat.SBSARIO_IMAGE_FORMAT_FLOAT;
|
|
|
|
//Half types
|
|
case TextureFormat.RGBAHalf:
|
|
return ImageFormat.SBSARIO_IMAGE_FORMAT_16B | ImageFormat.SBSARIO_IMAGE_FORMAT_RGBA | ImageFormat.SBSARIO_IMAGE_FORMAT_FLOAT;
|
|
|
|
case TextureFormat.RHalf:
|
|
return ImageFormat.SBSARIO_IMAGE_FORMAT_16B | ImageFormat.SBSARIO_IMAGE_FORMAT_L | ImageFormat.SBSARIO_IMAGE_FORMAT_FLOAT;
|
|
|
|
default:
|
|
throw new ArgumentException($"Texture format {unityFormat} not supported.");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Convert Substance Texture Format to Unity Texture Format
|
|
/// </summary>
|
|
internal static TextureFormat ToUnityFormat(this ImageFormat imageFormat)
|
|
{
|
|
var channelCount = ChannelCount(imageFormat);
|
|
var bytesPerChannel = GetBytesPerChannel(imageFormat);
|
|
|
|
if (imageFormat.HasMask(ImageFormat.SBSARIO_IMAGE_FORMAT_FLOAT))
|
|
{
|
|
if (channelCount == 1)
|
|
{
|
|
if (bytesPerChannel == 2)
|
|
{
|
|
return TextureFormat.RHalf;
|
|
}
|
|
else if (bytesPerChannel == 4)
|
|
{
|
|
return TextureFormat.RFloat;
|
|
}
|
|
}
|
|
else if (channelCount == 2)
|
|
{
|
|
if (bytesPerChannel == 2)
|
|
{
|
|
return TextureFormat.RGHalf;
|
|
}
|
|
else if (bytesPerChannel == 4)
|
|
{
|
|
return TextureFormat.RGFloat;
|
|
}
|
|
}
|
|
else if (channelCount == 4)
|
|
{
|
|
if (bytesPerChannel == 2)
|
|
{
|
|
return TextureFormat.RGBAHalf;
|
|
}
|
|
else if (bytesPerChannel == 4)
|
|
{
|
|
return TextureFormat.RGBAFloat;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (channelCount == 1)
|
|
{
|
|
if (bytesPerChannel == 1)
|
|
{
|
|
return TextureFormat.R8;
|
|
}
|
|
else if (bytesPerChannel == 2)
|
|
{
|
|
return TextureFormat.R16;
|
|
}
|
|
}
|
|
else if (channelCount == 2)
|
|
{
|
|
if (bytesPerChannel == 1)
|
|
{
|
|
return TextureFormat.RG16;
|
|
}
|
|
else if (bytesPerChannel == 2)
|
|
{
|
|
return TextureFormat.RG32;
|
|
}
|
|
}
|
|
else if (channelCount == 3)
|
|
{
|
|
if (bytesPerChannel == 1)
|
|
{
|
|
return TextureFormat.RGB24;
|
|
}
|
|
else if (bytesPerChannel == 2)
|
|
{
|
|
return TextureFormat.RGB48;
|
|
}
|
|
}
|
|
else if (channelCount == 4)
|
|
{
|
|
if (bytesPerChannel == 1)
|
|
{
|
|
return TextureFormat.RGBA32;
|
|
}
|
|
else if (bytesPerChannel == 2)
|
|
{
|
|
return TextureFormat.RGBA64;
|
|
}
|
|
}
|
|
}
|
|
|
|
Debug.LogError($"Not supported image format with channel count = {channelCount} and bytes per channel = {bytesPerChannel}");
|
|
throw new FormatException();
|
|
}
|
|
|
|
internal static int GetSizeWithMipMaps(this NativeDataImage imageData)
|
|
{
|
|
int width = (int)imageData.width;
|
|
int height = (int)imageData.height;
|
|
int mipCount = (int)imageData.mipmaps;
|
|
ImageFormat imageFormat = imageData.image_format;
|
|
|
|
var bytesPerPixel = GetBytesPerChannel(imageFormat) * ChannelCount(imageFormat);
|
|
|
|
if (width == 0 || height == 0)
|
|
return 0;
|
|
|
|
int size = 0;
|
|
for (int i = 0; i < mipCount; i++)
|
|
{
|
|
size += width * height * bytesPerPixel;
|
|
width >>= 1;
|
|
height >>= 1;
|
|
|
|
if (width < 1) width = 1;
|
|
if (height < 1) height = 1;
|
|
}
|
|
|
|
return size;
|
|
}
|
|
|
|
internal static int GetSize(this NativeDataImage imageData)
|
|
{
|
|
int width = (int)imageData.width;
|
|
int height = (int)imageData.height;
|
|
ImageFormat imageFormat = imageData.image_format;
|
|
|
|
if (width <= 0 || height <= 0)
|
|
return 0;
|
|
|
|
var bytesPerPixel = GetBytesPerChannel(imageFormat) * ChannelCount(imageFormat);
|
|
return width * height * bytesPerPixel;
|
|
}
|
|
|
|
internal static int GetBytesPerChannel(this ImageFormat imageFormat)
|
|
{
|
|
switch (imageFormat & ImageFormat.SBSARIO_IMAGE_FORMAT_BITDEPTH_MASK)
|
|
{
|
|
case ImageFormat.SBSARIO_IMAGE_FORMAT_32B:
|
|
return 4;
|
|
|
|
case ImageFormat.SBSARIO_IMAGE_FORMAT_16B:
|
|
return 2;
|
|
|
|
case ImageFormat.SBSARIO_IMAGE_FORMAT_8B:
|
|
return 1;
|
|
|
|
default:
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
internal static int ChannelCount(this ImageFormat imageFormat)
|
|
{
|
|
switch (imageFormat & ImageFormat.SBSARIO_IMAGE_FORMAT_CHANNELS_MASK)
|
|
{
|
|
case ImageFormat.SBSARIO_IMAGE_FORMAT_RGBA:
|
|
case ImageFormat.SBSARIO_IMAGE_FORMAT_RGBX:
|
|
return 4;
|
|
|
|
case ImageFormat.SBSARIO_IMAGE_FORMAT_RGB:
|
|
return 3;
|
|
|
|
case ImageFormat.SBSARIO_IMAGE_FORMAT_L:
|
|
return 1;
|
|
|
|
default:
|
|
return 4;
|
|
}
|
|
}
|
|
|
|
private static bool HasMask(this ImageFormat imageFormat, ImageFormat mask)
|
|
{
|
|
return ((imageFormat & mask) != 0);
|
|
}
|
|
|
|
#endregion Image Format
|
|
}
|
|
} |