using System; using System.Collections; using System.Collections.Generic; using UnityEngine; namespace Adobe.Substance { /// /// Extensions for handling enum type convertion. /// internal static class Extensions { /// /// Transforms a unity value type enum into an enum used by native code. /// /// Unity enum. /// Native enum. 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."); } } /// /// Transforms a native value type enum into an enum used by the unity plugin. /// /// Native enum. /// Unity enum. 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."); } } /// /// Convert Substance Texture Format to Unity Texture Format /// 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 } }