Decompiled source of AssimpLibaries v0.2.3

plugins/AssimpNet.dll

Decompiled 3 hours ago
#define DEBUG
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using Assimp.Configs;
using Assimp.Unmanaged;
using Microsoft.CodeAnalysis;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("AssimpNet")]
[assembly: AssemblyDescription("A .NET Wrapper for the Open Asset Import (Assimp) library.")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Nicholas Woodfield")]
[assembly: AssemblyProduct("AssimpNet")]
[assembly: AssemblyCopyright("Copyright © 2012-2020 AssimpNet - Nicholas Woodfield")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("a2aee677-907b-4ec9-a9d4-a52d60542083")]
[assembly: AssemblyFileVersion("5.0.0")]
[assembly: AssemblyInformationalVersion("5.0.0-beta1")]
[assembly: TargetFramework(".NETFramework,Version=v4.0", FrameworkDisplayName = ".NET Framework 4")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("5.0.0.0")]
[module: UnverifiableCode]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class IsReadOnlyAttribute : Attribute
	{
	}
	[CompilerGenerated]
	[Embedded]
	internal sealed class IsUnmanagedAttribute : Attribute
	{
	}
}
namespace Assimp
{
	public sealed class Animation : IMarshalable<Animation, AiAnimation>
	{
		private string m_name;

		private double m_duration;

		private double m_ticksPerSecond;

		private List<NodeAnimationChannel> m_nodeChannels;

		private List<MeshAnimationChannel> m_meshChannels;

		private List<MeshMorphAnimationChannel> m_meshMorphChannels;

		public string Name
		{
			get
			{
				return m_name;
			}
			set
			{
				m_name = value;
			}
		}

		public double DurationInTicks
		{
			get
			{
				return m_duration;
			}
			set
			{
				m_duration = value;
			}
		}

		public double TicksPerSecond
		{
			get
			{
				return m_ticksPerSecond;
			}
			set
			{
				m_ticksPerSecond = value;
			}
		}

		public bool HasNodeAnimations => m_nodeChannels.Count > 0;

		public int NodeAnimationChannelCount => m_nodeChannels.Count;

		public List<NodeAnimationChannel> NodeAnimationChannels => m_nodeChannels;

		public bool HasMeshAnimations => m_meshChannels.Count > 0;

		public int MeshAnimationChannelCount => m_meshChannels.Count;

		public int MeshMorphAnimationChannelCount => m_meshMorphChannels.Count;

		public List<MeshAnimationChannel> MeshAnimationChannels => m_meshChannels;

		public List<MeshMorphAnimationChannel> MeshMorphAnimationChannels => m_meshMorphChannels;

		bool IMarshalable<Animation, AiAnimation>.IsNativeBlittable => true;

		public Animation()
		{
			m_name = string.Empty;
			m_duration = 0.0;
			m_ticksPerSecond = 0.0;
			m_nodeChannels = new List<NodeAnimationChannel>();
			m_meshChannels = new List<MeshAnimationChannel>();
			m_meshMorphChannels = new List<MeshMorphAnimationChannel>();
		}

		void IMarshalable<Animation, AiAnimation>.ToNative(IntPtr thisPtr, out AiAnimation nativeValue)
		{
			nativeValue.Name = new AiString(m_name);
			nativeValue.Duration = m_duration;
			nativeValue.TicksPerSecond = m_ticksPerSecond;
			nativeValue.NumChannels = (uint)NodeAnimationChannelCount;
			nativeValue.NumMeshChannels = (uint)MeshAnimationChannelCount;
			nativeValue.NumMeshMorphChannels = (uint)MeshMorphAnimationChannelCount;
			nativeValue.Channels = IntPtr.Zero;
			nativeValue.MeshChannels = IntPtr.Zero;
			nativeValue.MeshMorphChannels = IntPtr.Zero;
			if (nativeValue.NumChannels != 0)
			{
				nativeValue.Channels = MemoryHelper.ToNativeArray<NodeAnimationChannel, AiNodeAnim>(m_nodeChannels.ToArray(), arrayOfPointers: true);
			}
			if (nativeValue.NumMeshChannels != 0)
			{
				nativeValue.MeshChannels = MemoryHelper.ToNativeArray<MeshAnimationChannel, AiMeshAnim>(m_meshChannels.ToArray(), arrayOfPointers: true);
			}
			if (nativeValue.NumMeshMorphChannels != 0)
			{
				nativeValue.MeshMorphChannels = MemoryHelper.ToNativeArray<MeshMorphAnimationChannel, AiMeshMorphAnim>(m_meshMorphChannels.ToArray(), arrayOfPointers: true);
			}
		}

		void IMarshalable<Animation, AiAnimation>.FromNative(in AiAnimation nativeValue)
		{
			m_nodeChannels.Clear();
			m_meshChannels.Clear();
			m_meshMorphChannels.Clear();
			m_name = AiString.GetString(in nativeValue.Name);
			m_duration = nativeValue.Duration;
			m_ticksPerSecond = nativeValue.TicksPerSecond;
			if (nativeValue.NumChannels != 0 && nativeValue.Channels != IntPtr.Zero)
			{
				m_nodeChannels.AddRange(MemoryHelper.FromNativeArray<NodeAnimationChannel, AiNodeAnim>(nativeValue.Channels, (int)nativeValue.NumChannels, arrayOfPointers: true));
			}
			if (nativeValue.NumMeshChannels != 0 && nativeValue.MeshChannels != IntPtr.Zero)
			{
				m_meshChannels.AddRange(MemoryHelper.FromNativeArray<MeshAnimationChannel, AiMeshAnim>(nativeValue.MeshChannels, (int)nativeValue.NumMeshChannels, arrayOfPointers: true));
			}
			if (nativeValue.NumMeshMorphChannels != 0 && nativeValue.MeshMorphChannels != IntPtr.Zero)
			{
				m_meshMorphChannels.AddRange(MemoryHelper.FromNativeArray<MeshMorphAnimationChannel, AiMeshMorphAnim>(nativeValue.MeshMorphChannels, (int)nativeValue.NumMeshMorphChannels, arrayOfPointers: true));
			}
		}

		public static void FreeNative(IntPtr nativeValue, bool freeNative)
		{
			if (!(nativeValue == IntPtr.Zero))
			{
				AiAnimation aiAnimation = MemoryHelper.Read<AiAnimation>(nativeValue);
				if (aiAnimation.NumChannels != 0 && aiAnimation.Channels != IntPtr.Zero)
				{
					MemoryHelper.FreeNativeArray<AiNodeAnim>(aiAnimation.Channels, (int)aiAnimation.NumChannels, NodeAnimationChannel.FreeNative, arrayOfPointers: true);
				}
				if (aiAnimation.NumMeshChannels != 0 && aiAnimation.MeshChannels != IntPtr.Zero)
				{
					MemoryHelper.FreeNativeArray<AiMeshAnim>(aiAnimation.MeshChannels, (int)aiAnimation.NumMeshChannels, MeshAnimationChannel.FreeNative, arrayOfPointers: true);
				}
				if (aiAnimation.NumMeshMorphChannels != 0 && aiAnimation.MeshMorphChannels != IntPtr.Zero)
				{
					MemoryHelper.FreeNativeArray<AiMeshMorphAnim>(aiAnimation.MeshMorphChannels, (int)aiAnimation.NumMeshMorphChannels, MeshMorphAnimationChannel.FreeNative, arrayOfPointers: true);
				}
				if (freeNative)
				{
					MemoryHelper.FreeMemory(nativeValue);
				}
			}
		}
	}
	public sealed class AssimpContext : IDisposable
	{
		private bool m_isDisposed;

		private Dictionary<string, PropertyConfig> m_configs;

		private IOSystem m_ioSystem;

		private ExportFormatDescription[] m_exportFormats;

		private string[] m_importFormats;

		private ImporterDescription[] m_importerDescrs;

		private float m_scale = 1f;

		private float m_xAxisRotation = 0f;

		private float m_yAxisRotation = 0f;

		private float m_zAxisRotation = 0f;

		private bool m_buildMatrix = false;

		private Matrix4x4 m_scaleRot = Matrix4x4.Identity;

		private IntPtr m_propStore = IntPtr.Zero;

		public bool IsDisposed => m_isDisposed;

		public float Scale
		{
			get
			{
				return m_scale;
			}
			set
			{
				if (m_scale != value)
				{
					m_scale = value;
					m_buildMatrix = true;
				}
			}
		}

		public float XAxisRotation
		{
			get
			{
				return m_xAxisRotation;
			}
			set
			{
				if (m_xAxisRotation != value)
				{
					m_xAxisRotation = value;
					m_buildMatrix = true;
				}
			}
		}

		public float YAxisRotation
		{
			get
			{
				return m_yAxisRotation;
			}
			set
			{
				if (m_yAxisRotation != value)
				{
					m_yAxisRotation = value;
					m_buildMatrix = true;
				}
			}
		}

		public float ZAxisRotation
		{
			get
			{
				return m_zAxisRotation;
			}
			set
			{
				if (m_zAxisRotation != value)
				{
					m_zAxisRotation = value;
					m_buildMatrix = true;
				}
			}
		}

		public bool UsingCustomIOSystem => m_ioSystem != null && !m_ioSystem.IsDisposed;

		public Dictionary<string, PropertyConfig> PropertyConfigurations => m_configs;

		public AssimpContext()
		{
			m_configs = new Dictionary<string, PropertyConfig>();
		}

		public Scene ImportFileFromStream(Stream stream, string formatHint = null)
		{
			return ImportFileFromStream(stream, PostProcessSteps.None, formatHint);
		}

		public Scene ImportFileFromStream(Stream stream, PostProcessSteps postProcessFlags, string formatHint = null)
		{
			CheckDisposed();
			if (stream == null || !stream.CanRead)
			{
				throw new AssimpException("stream", "Can't read from the stream it's null or write-only");
			}
			IntPtr intPtr = IntPtr.Zero;
			PrepareImport();
			try
			{
				intPtr = AssimpLibrary.Instance.ImportFileFromStream(stream, PostProcessSteps.None, formatHint, m_propStore);
				if (intPtr == IntPtr.Zero)
				{
					throw new AssimpException("Error importing file: " + AssimpLibrary.Instance.GetErrorString());
				}
				TransformScene(intPtr);
				if (postProcessFlags != PostProcessSteps.None)
				{
					intPtr = AssimpLibrary.Instance.ApplyPostProcessing(intPtr, postProcessFlags);
				}
				return Scene.FromUnmanagedScene(intPtr);
			}
			finally
			{
				CleanupImport();
				if (intPtr != IntPtr.Zero)
				{
					AssimpLibrary.Instance.ReleaseImport(intPtr);
				}
			}
		}

		public Scene ImportFile(string file)
		{
			return ImportFile(file, PostProcessSteps.None);
		}

		public Scene ImportFile(string file, PostProcessSteps postProcessFlags)
		{
			CheckDisposed();
			IntPtr intPtr = IntPtr.Zero;
			IntPtr fileIO = IntPtr.Zero;
			if (UsingCustomIOSystem)
			{
				fileIO = m_ioSystem.AiFileIO;
			}
			else if (string.IsNullOrEmpty(file) || !File.Exists(file))
			{
				throw new FileNotFoundException("Filename was null or could not be found", file);
			}
			PrepareImport();
			try
			{
				intPtr = AssimpLibrary.Instance.ImportFile(file, PostProcessSteps.None, fileIO, m_propStore);
				if (intPtr == IntPtr.Zero)
				{
					throw new AssimpException("Error importing file: " + AssimpLibrary.Instance.GetErrorString());
				}
				TransformScene(intPtr);
				if (postProcessFlags != PostProcessSteps.None)
				{
					intPtr = AssimpLibrary.Instance.ApplyPostProcessing(intPtr, postProcessFlags);
				}
				return Scene.FromUnmanagedScene(intPtr);
			}
			finally
			{
				CleanupImport();
				if (intPtr != IntPtr.Zero)
				{
					AssimpLibrary.Instance.ReleaseImport(intPtr);
				}
			}
		}

		public bool ExportFile(Scene scene, string fileName, string exportFormatId)
		{
			return ExportFile(scene, fileName, exportFormatId, PostProcessSteps.None);
		}

		public bool ExportFile(Scene scene, string fileName, string exportFormatId, PostProcessSteps preProcessing)
		{
			CheckDisposed();
			IntPtr zero = IntPtr.Zero;
			IntPtr intPtr = IntPtr.Zero;
			if (scene == null)
			{
				throw new ArgumentNullException("scene", "Scene must exist.");
			}
			if (!TestIfExportIdIsValid(exportFormatId))
			{
				return false;
			}
			try
			{
				intPtr = Scene.ToUnmanagedScene(scene);
				ReturnCode returnCode = AssimpLibrary.Instance.ExportScene(intPtr, exportFormatId, fileName, zero, preProcessing);
				return returnCode == ReturnCode.Success;
			}
			finally
			{
				if (intPtr != IntPtr.Zero)
				{
					Scene.FreeUnmanagedScene(intPtr);
				}
			}
		}

		public ExportDataBlob ExportToBlob(Scene scene, string exportFormatId)
		{
			return ExportToBlob(scene, exportFormatId, PostProcessSteps.None);
		}

		public ExportDataBlob ExportToBlob(Scene scene, string exportFormatId, PostProcessSteps preProcessing)
		{
			CheckDisposed();
			IntPtr zero = IntPtr.Zero;
			IntPtr intPtr = IntPtr.Zero;
			if (scene == null)
			{
				throw new ArgumentNullException("scene", "Scene must exist.");
			}
			if (!TestIfExportIdIsValid(exportFormatId))
			{
				return null;
			}
			try
			{
				intPtr = Scene.ToUnmanagedScene(scene);
				return AssimpLibrary.Instance.ExportSceneToBlob(intPtr, exportFormatId, preProcessing);
			}
			finally
			{
				if (intPtr != IntPtr.Zero)
				{
					Scene.FreeUnmanagedScene(intPtr);
				}
			}
		}

		public bool ConvertFromFileToFile(string inputFilename, string outputFilename, string exportFormatId)
		{
			return ConvertFromFileToFile(inputFilename, PostProcessSteps.None, outputFilename, exportFormatId, PostProcessSteps.None);
		}

		public bool ConvertFromFileToFile(string inputFilename, string outputFilename, string exportFormatId, PostProcessSteps exportProcessSteps)
		{
			return ConvertFromFileToFile(inputFilename, PostProcessSteps.None, outputFilename, exportFormatId, exportProcessSteps);
		}

		public bool ConvertFromFileToFile(string inputFilename, PostProcessSteps importProcessSteps, string outputFilename, string exportFormatId, PostProcessSteps exportProcessSteps)
		{
			CheckDisposed();
			if (!TestIfExportIdIsValid(exportFormatId))
			{
				return false;
			}
			IntPtr intPtr = IntPtr.Zero;
			IntPtr fileIO = IntPtr.Zero;
			if (UsingCustomIOSystem)
			{
				fileIO = m_ioSystem.AiFileIO;
			}
			else if (string.IsNullOrEmpty(inputFilename) || !File.Exists(inputFilename))
			{
				throw new FileNotFoundException("Filename was null or could not be found", inputFilename);
			}
			PrepareImport();
			try
			{
				intPtr = AssimpLibrary.Instance.ImportFile(inputFilename, PostProcessSteps.None, fileIO, m_propStore);
				if (intPtr == IntPtr.Zero)
				{
					throw new AssimpException("Error importing file: " + AssimpLibrary.Instance.GetErrorString());
				}
				TransformScene(intPtr);
				if (importProcessSteps != PostProcessSteps.None)
				{
					intPtr = AssimpLibrary.Instance.ApplyPostProcessing(intPtr, importProcessSteps);
				}
				ReturnCode returnCode = AssimpLibrary.Instance.ExportScene(intPtr, exportFormatId, outputFilename, fileIO, exportProcessSteps);
				return returnCode == ReturnCode.Success;
			}
			finally
			{
				CleanupImport();
				if (intPtr != IntPtr.Zero)
				{
					AssimpLibrary.Instance.ReleaseImport(intPtr);
				}
			}
		}

		public ExportDataBlob ConvertFromFileToBlob(string inputFilename, string exportFormatId)
		{
			return ConvertFromFileToBlob(inputFilename, PostProcessSteps.None, exportFormatId, PostProcessSteps.None);
		}

		public ExportDataBlob ConvertFromFileToBlob(string inputFilename, string exportFormatId, PostProcessSteps exportProcessSteps)
		{
			return ConvertFromFileToBlob(inputFilename, PostProcessSteps.None, exportFormatId, exportProcessSteps);
		}

		public ExportDataBlob ConvertFromFileToBlob(string inputFilename, PostProcessSteps importProcessSteps, string exportFormatId, PostProcessSteps exportProcessSteps)
		{
			CheckDisposed();
			if (!TestIfExportIdIsValid(exportFormatId))
			{
				return null;
			}
			IntPtr intPtr = IntPtr.Zero;
			IntPtr fileIO = IntPtr.Zero;
			if (UsingCustomIOSystem)
			{
				fileIO = m_ioSystem.AiFileIO;
			}
			else if (string.IsNullOrEmpty(inputFilename) || !File.Exists(inputFilename))
			{
				throw new FileNotFoundException("Filename was null or could not be found", inputFilename);
			}
			PrepareImport();
			try
			{
				intPtr = AssimpLibrary.Instance.ImportFile(inputFilename, PostProcessSteps.None, fileIO, m_propStore);
				if (intPtr == IntPtr.Zero)
				{
					throw new AssimpException("Error importing file: " + AssimpLibrary.Instance.GetErrorString());
				}
				TransformScene(intPtr);
				if (importProcessSteps != PostProcessSteps.None)
				{
					intPtr = AssimpLibrary.Instance.ApplyPostProcessing(intPtr, importProcessSteps);
				}
				return AssimpLibrary.Instance.ExportSceneToBlob(intPtr, exportFormatId, exportProcessSteps);
			}
			finally
			{
				CleanupImport();
				if (intPtr != IntPtr.Zero)
				{
					AssimpLibrary.Instance.ReleaseImport(intPtr);
				}
			}
		}

		public bool ConvertFromStreamToFile(Stream inputStream, string importFormatHint, string outputFilename, string exportFormatId)
		{
			return ConvertFromStreamToFile(inputStream, importFormatHint, PostProcessSteps.None, outputFilename, exportFormatId, PostProcessSteps.None);
		}

		public bool ConvertFromStreamToFile(Stream inputStream, string importFormatHint, string outputFilename, string exportFormatId, PostProcessSteps exportProcessSteps)
		{
			return ConvertFromStreamToFile(inputStream, importFormatHint, PostProcessSteps.None, outputFilename, exportFormatId, exportProcessSteps);
		}

		public bool ConvertFromStreamToFile(Stream inputStream, string importFormatHint, PostProcessSteps importProcessSteps, string outputFilename, string exportFormatId, PostProcessSteps exportProcessSteps)
		{
			CheckDisposed();
			if (inputStream == null || !inputStream.CanRead)
			{
				throw new AssimpException("stream", "Can't read from the stream it's null or write-only");
			}
			if (!TestIfExportIdIsValid(exportFormatId))
			{
				return false;
			}
			IntPtr intPtr = IntPtr.Zero;
			PrepareImport();
			try
			{
				intPtr = AssimpLibrary.Instance.ImportFileFromStream(inputStream, importProcessSteps, importFormatHint, m_propStore);
				if (intPtr == IntPtr.Zero)
				{
					throw new AssimpException("Error importing file: " + AssimpLibrary.Instance.GetErrorString());
				}
				TransformScene(intPtr);
				if (importProcessSteps != PostProcessSteps.None)
				{
					intPtr = AssimpLibrary.Instance.ApplyPostProcessing(intPtr, importProcessSteps);
				}
				ReturnCode returnCode = AssimpLibrary.Instance.ExportScene(intPtr, exportFormatId, outputFilename, exportProcessSteps);
				return returnCode == ReturnCode.Success;
			}
			finally
			{
				CleanupImport();
				if (intPtr != IntPtr.Zero)
				{
					AssimpLibrary.Instance.ReleaseImport(intPtr);
				}
			}
		}

		public ExportDataBlob ConvertFromStreamToBlob(Stream inputStream, string importFormatHint, string exportFormatId)
		{
			return ConvertFromStreamToBlob(inputStream, importFormatHint, PostProcessSteps.None, exportFormatId, PostProcessSteps.None);
		}

		public ExportDataBlob ConvertFromStreamToBlob(Stream inputStream, string importFormatHint, string exportFormatId, PostProcessSteps exportProcessSteps)
		{
			return ConvertFromStreamToBlob(inputStream, importFormatHint, PostProcessSteps.None, exportFormatId, exportProcessSteps);
		}

		public ExportDataBlob ConvertFromStreamToBlob(Stream inputStream, string importFormatHint, PostProcessSteps importProcessSteps, string exportFormatId, PostProcessSteps exportProcessSteps)
		{
			CheckDisposed();
			if (inputStream == null || !inputStream.CanRead)
			{
				throw new AssimpException("stream", "Can't read from the stream it's null or write-only");
			}
			if (!TestIfExportIdIsValid(exportFormatId))
			{
				return null;
			}
			IntPtr intPtr = IntPtr.Zero;
			PrepareImport();
			try
			{
				intPtr = AssimpLibrary.Instance.ImportFileFromStream(inputStream, importProcessSteps, importFormatHint, m_propStore);
				if (intPtr == IntPtr.Zero)
				{
					throw new AssimpException("Error importing file: " + AssimpLibrary.Instance.GetErrorString());
				}
				TransformScene(intPtr);
				if (importProcessSteps != PostProcessSteps.None)
				{
					intPtr = AssimpLibrary.Instance.ApplyPostProcessing(intPtr, importProcessSteps);
				}
				return AssimpLibrary.Instance.ExportSceneToBlob(intPtr, exportFormatId, exportProcessSteps);
			}
			finally
			{
				CleanupImport();
				if (intPtr != IntPtr.Zero)
				{
					AssimpLibrary.Instance.ReleaseImport(intPtr);
				}
			}
		}

		public void SetIOSystem(IOSystem ioSystem)
		{
			if (ioSystem == null || ioSystem.IsDisposed)
			{
				ioSystem = null;
			}
			m_ioSystem = ioSystem;
		}

		public void RemoveIOSystem()
		{
			m_ioSystem = null;
		}

		public ExportFormatDescription[] GetSupportedExportFormats()
		{
			QueryExportFormatsIfNecessary();
			return (ExportFormatDescription[])m_exportFormats.Clone();
		}

		public string[] GetSupportedImportFormats()
		{
			QueryImportFormatsIfNecessary();
			return (string[])m_importFormats.Clone();
		}

		public ImporterDescription[] GetImporterDescriptions()
		{
			QueryImporterDescriptionsIfNecessary();
			return (ImporterDescription[])m_importerDescrs.Clone();
		}

		public ImporterDescription GetImporterDescriptionFor(string fileExtension)
		{
			if (string.IsNullOrEmpty(fileExtension))
			{
				return null;
			}
			QueryImporterDescriptionsIfNecessary();
			if (fileExtension.StartsWith(".") && fileExtension.Length >= 2)
			{
				fileExtension = fileExtension.Substring(1);
			}
			ImporterDescription[] importerDescrs = m_importerDescrs;
			foreach (ImporterDescription importerDescription in importerDescrs)
			{
				string[] fileExtensions = importerDescription.FileExtensions;
				foreach (string b in fileExtensions)
				{
					if (string.Equals(fileExtension, b, StringComparison.Ordinal))
					{
						return importerDescription;
					}
				}
			}
			return null;
		}

		public bool IsImportFormatSupported(string format)
		{
			return AssimpLibrary.Instance.IsExtensionSupported(format);
		}

		public bool IsExportFormatSupported(string format)
		{
			if (string.IsNullOrEmpty(format))
			{
				return false;
			}
			QueryExportFormatsIfNecessary();
			if (format.StartsWith(".") && format.Length >= 2)
			{
				format = format.Substring(1);
			}
			ExportFormatDescription[] exportFormats = m_exportFormats;
			foreach (ExportFormatDescription exportFormatDescription in exportFormats)
			{
				if (string.Equals(exportFormatDescription.FileExtension, format, StringComparison.Ordinal))
				{
					return true;
				}
			}
			return false;
		}

		public void SetConfig(PropertyConfig config)
		{
			if (config != null)
			{
				string name = config.Name;
				m_configs[config.Name] = config;
			}
		}

		public void RemoveConfig(string configName)
		{
			if (!string.IsNullOrEmpty(configName) && m_configs.TryGetValue(configName, out var _))
			{
				m_configs.Remove(configName);
			}
		}

		public void RemoveConfigs()
		{
			m_configs.Clear();
		}

		public bool ContainsConfig(string configName)
		{
			if (string.IsNullOrEmpty(configName))
			{
				return false;
			}
			return m_configs.ContainsKey(configName);
		}

		public void Dispose()
		{
			Dispose(disposing: true);
			GC.SuppressFinalize(this);
		}

		private void Dispose(bool disposing)
		{
			if (!m_isDisposed)
			{
				if (disposing && UsingCustomIOSystem)
				{
					m_ioSystem.Dispose();
				}
				m_isDisposed = true;
			}
		}

		private void CheckDisposed()
		{
			if (m_isDisposed)
			{
				throw new ObjectDisposedException("Assimp Context has been disposed.");
			}
		}

		private void QueryExportFormatsIfNecessary()
		{
			if (m_exportFormats == null)
			{
				m_exportFormats = AssimpLibrary.Instance.GetExportFormatDescriptions();
			}
		}

		private void QueryImportFormatsIfNecessary()
		{
			if (m_importFormats == null)
			{
				m_importFormats = AssimpLibrary.Instance.GetExtensionList();
			}
		}

		private void QueryImporterDescriptionsIfNecessary()
		{
			if (m_importerDescrs == null)
			{
				m_importerDescrs = AssimpLibrary.Instance.GetImporterDescriptions();
			}
		}

		private void BuildMatrix()
		{
			if (m_buildMatrix)
			{
				Matrix4x4 matrix4x = Matrix4x4.FromScaling(new Vector3D(m_scale, m_scale, m_scale));
				Matrix4x4 matrix4x2 = Matrix4x4.FromRotationX(m_xAxisRotation * ((float)Math.PI / 180f));
				Matrix4x4 matrix4x3 = Matrix4x4.FromRotationY(m_yAxisRotation * ((float)Math.PI / 180f));
				Matrix4x4 matrix4x4 = Matrix4x4.FromRotationZ(m_zAxisRotation * ((float)Math.PI / 180f));
				m_scaleRot = matrix4x * (matrix4x2 * matrix4x3 * matrix4x4);
			}
			m_buildMatrix = false;
		}

		private bool TransformScene(IntPtr scene)
		{
			BuildMatrix();
			try
			{
				if (!m_scaleRot.IsIdentity)
				{
					AiScene aiScene = MemoryHelper.MarshalStructure<AiScene>(scene);
					if (aiScene.RootNode == IntPtr.Zero)
					{
						return false;
					}
					IntPtr intPtr = MemoryHelper.AddIntPtr(aiScene.RootNode, MemoryHelper.SizeOf<AiString>());
					Matrix4x4 matrix4x = MemoryHelper.Read<Matrix4x4>(intPtr);
					MemoryHelper.Write<Matrix4x4>(intPtr, matrix4x * m_scaleRot);
					return true;
				}
			}
			catch (Exception)
			{
			}
			return false;
		}

		private void CreateConfigs()
		{
			m_propStore = AssimpLibrary.Instance.CreatePropertyStore();
			foreach (KeyValuePair<string, PropertyConfig> config in m_configs)
			{
				config.Value.ApplyValue(m_propStore);
			}
		}

		private void ReleaseConfigs()
		{
			if (m_propStore != IntPtr.Zero)
			{
				AssimpLibrary.Instance.ReleasePropertyStore(m_propStore);
			}
		}

		private void PrepareImport()
		{
			CreateConfigs();
		}

		private void CleanupImport()
		{
			ReleaseConfigs();
			if (UsingCustomIOSystem)
			{
				m_ioSystem.CloseAllFiles();
			}
		}

		private bool TestIfExportIdIsValid(string exportFormatId)
		{
			if (m_exportFormats == null)
			{
				m_exportFormats = AssimpLibrary.Instance.GetExportFormatDescriptions();
			}
			ExportFormatDescription[] exportFormats = m_exportFormats;
			foreach (ExportFormatDescription exportFormatDescription in exportFormats)
			{
				if (exportFormatDescription.FormatId.Equals(exportFormatId, StringComparison.Ordinal))
				{
					return true;
				}
			}
			IEnumerable<LogStream> attachedLogStreams = LogStream.GetAttachedLogStreams();
			foreach (LogStream item in attachedLogStreams)
			{
				item.Log($"Info,  Invalid export format: {exportFormatId}");
			}
			return false;
		}
	}
	public class AssimpException : Exception
	{
		public AssimpException()
		{
		}

		public AssimpException(string msg)
			: base(msg)
		{
		}

		public AssimpException(string paramName, string msg)
			: base("Parameter: " + paramName + " Error: " + msg)
		{
		}

		public AssimpException(string msg, Exception innerException)
			: base(msg, innerException)
		{
		}
	}
	public sealed class Bone : IMarshalable<Bone, AiBone>
	{
		private string m_name;

		private List<VertexWeight> m_weights;

		private Matrix4x4 m_offsetMatrix;

		public string Name
		{
			get
			{
				return m_name;
			}
			set
			{
				m_name = value;
			}
		}

		public int VertexWeightCount => m_weights.Count;

		public bool HasVertexWeights => m_weights.Count > 0;

		public List<VertexWeight> VertexWeights => m_weights;

		public Matrix4x4 OffsetMatrix
		{
			get
			{
				return m_offsetMatrix;
			}
			set
			{
				m_offsetMatrix = value;
			}
		}

		bool IMarshalable<Bone, AiBone>.IsNativeBlittable => true;

		public Bone()
		{
			m_name = null;
			m_offsetMatrix = Matrix3x3.Identity;
			m_weights = new List<VertexWeight>();
		}

		public Bone(string name, Matrix3x3 offsetMatrix, VertexWeight[] weights)
		{
			m_name = name;
			m_offsetMatrix = offsetMatrix;
			m_weights = new List<VertexWeight>();
			if (weights != null)
			{
				m_weights.AddRange(weights);
			}
		}

		void IMarshalable<Bone, AiBone>.ToNative(IntPtr thisPtr, out AiBone nativeValue)
		{
			nativeValue.Name = new AiString(m_name);
			nativeValue.OffsetMatrix = m_offsetMatrix;
			nativeValue.NumWeights = (uint)m_weights.Count;
			nativeValue.Weights = IntPtr.Zero;
			if (nativeValue.NumWeights != 0)
			{
				nativeValue.Weights = MemoryHelper.ToNativeArray(m_weights.ToArray());
			}
		}

		void IMarshalable<Bone, AiBone>.FromNative(in AiBone nativeValue)
		{
			m_name = AiString.GetString(in nativeValue.Name);
			m_offsetMatrix = nativeValue.OffsetMatrix;
			m_weights.Clear();
			if (nativeValue.NumWeights != 0 && nativeValue.Weights != IntPtr.Zero)
			{
				m_weights.AddRange(MemoryHelper.FromNativeArray<VertexWeight>(nativeValue.Weights, (int)nativeValue.NumWeights));
			}
		}

		public static void FreeNative(IntPtr nativeValue, bool freeNative)
		{
			if (!(nativeValue == IntPtr.Zero))
			{
				AiBone aiBone = MemoryHelper.Read<AiBone>(nativeValue);
				int num = MemoryHelper.Read<int>(MemoryHelper.AddIntPtr(nativeValue, MemoryHelper.SizeOf<AiString>()));
				IntPtr intPtr = MemoryHelper.AddIntPtr(nativeValue, MemoryHelper.SizeOf<AiString>() + 4);
				if (aiBone.NumWeights != 0 && aiBone.Weights != IntPtr.Zero)
				{
					MemoryHelper.FreeMemory(aiBone.Weights);
				}
				if (freeNative)
				{
					MemoryHelper.FreeMemory(nativeValue);
				}
			}
		}
	}
	public struct BoundingBox : IEquatable<BoundingBox>
	{
		public Vector3D Min;

		public Vector3D Max;

		public BoundingBox(Vector3D min, Vector3D max)
		{
			Min = min;
			Max = max;
		}

		public static bool operator ==(BoundingBox a, BoundingBox b)
		{
			return a.Min == b.Min && a.Max == b.Max;
		}

		public static bool operator !=(BoundingBox a, BoundingBox b)
		{
			return a.Min != b.Min || a.Max != b.Max;
		}

		public bool Equals(BoundingBox other)
		{
			return Min == other.Min && Max == other.Max;
		}

		public override bool Equals(object obj)
		{
			if (obj is BoundingBox)
			{
				return Equals((BoundingBox)obj);
			}
			return false;
		}

		public override int GetHashCode()
		{
			return Min.GetHashCode() + Max.GetHashCode();
		}

		public override string ToString()
		{
			CultureInfo currentCulture = CultureInfo.CurrentCulture;
			return string.Format(currentCulture, "{{Min:{0} Max:{1}}", new object[2]
			{
				Min.ToString(),
				Max.ToString()
			});
		}
	}
	public sealed class Camera : IMarshalable<Camera, AiCamera>
	{
		private string m_name;

		private Vector3D m_position;

		private Vector3D m_up;

		private Vector3D m_direction;

		private float m_fieldOfView;

		private float m_clipPlaneNear;

		private float m_clipPlaneFar;

		private float m_aspectRatio;

		public string Name
		{
			get
			{
				return m_name;
			}
			set
			{
				m_name = value;
			}
		}

		public Vector3D Position
		{
			get
			{
				return m_position;
			}
			set
			{
				m_position = value;
			}
		}

		public Vector3D Up
		{
			get
			{
				return m_up;
			}
			set
			{
				m_up = value;
			}
		}

		public Vector3D Direction
		{
			get
			{
				return m_direction;
			}
			set
			{
				m_direction = value;
			}
		}

		public float FieldOfview
		{
			get
			{
				return m_fieldOfView;
			}
			set
			{
				m_fieldOfView = value;
			}
		}

		public float ClipPlaneNear
		{
			get
			{
				return m_clipPlaneNear;
			}
			set
			{
				m_clipPlaneNear = value;
			}
		}

		public float ClipPlaneFar
		{
			get
			{
				return m_clipPlaneFar;
			}
			set
			{
				m_clipPlaneFar = value;
			}
		}

		public float AspectRatio
		{
			get
			{
				return m_aspectRatio;
			}
			set
			{
				m_aspectRatio = value;
			}
		}

		public Matrix4x4 ViewMatrix
		{
			get
			{
				Vector3D direction = m_direction;
				direction.Normalize();
				Vector3D up = m_up;
				up.Normalize();
				Vector3D a = Vector3D.Cross(m_up, m_direction);
				direction.Normalize();
				Matrix4x4 result = default(Matrix4x4);
				result.A1 = a.X;
				result.A2 = a.Y;
				result.A3 = a.Z;
				result.A4 = 0f;
				result.B1 = up.X;
				result.B2 = up.Y;
				result.B3 = up.Z;
				result.B4 = 0f;
				result.C1 = direction.X;
				result.C2 = direction.Y;
				result.C3 = direction.Z;
				result.C4 = 0f;
				result.D1 = 0f - Vector3D.Dot(a, m_position);
				result.D2 = 0f - Vector3D.Dot(up, m_position);
				result.D3 = 0f - Vector3D.Dot(direction, m_position);
				result.D4 = 1f;
				return result;
			}
		}

		bool IMarshalable<Camera, AiCamera>.IsNativeBlittable => true;

		public Camera()
		{
			m_name = string.Empty;
		}

		void IMarshalable<Camera, AiCamera>.ToNative(IntPtr thisPtr, out AiCamera nativeValue)
		{
			nativeValue.Name = new AiString(m_name);
			nativeValue.Position = m_position;
			nativeValue.LookAt = m_direction;
			nativeValue.Up = m_up;
			nativeValue.HorizontalFOV = m_fieldOfView;
			nativeValue.ClipPlaneFar = m_clipPlaneFar;
			nativeValue.ClipPlaneNear = m_clipPlaneNear;
			nativeValue.Aspect = m_aspectRatio;
		}

		void IMarshalable<Camera, AiCamera>.FromNative(in AiCamera nativeValue)
		{
			m_name = AiString.GetString(in nativeValue.Name);
			m_position = nativeValue.Position;
			m_direction = nativeValue.LookAt;
			m_up = nativeValue.Up;
			m_fieldOfView = nativeValue.HorizontalFOV;
			m_clipPlaneFar = nativeValue.ClipPlaneFar;
			m_clipPlaneNear = nativeValue.ClipPlaneNear;
			m_aspectRatio = nativeValue.Aspect;
		}

		public static void FreeNative(IntPtr nativeValue, bool freeNative)
		{
			if (nativeValue != IntPtr.Zero && freeNative)
			{
				MemoryHelper.FreeMemory(nativeValue);
			}
		}
	}
	public struct Color3D
	{
		public float R;

		public float G;

		public float B;

		public float this[int index]
		{
			get
			{
				return index switch
				{
					0 => R, 
					1 => G, 
					2 => B, 
					_ => 0f, 
				};
			}
			set
			{
				switch (index)
				{
				case 0:
					R = value;
					break;
				case 1:
					G = value;
					break;
				case 2:
					B = value;
					break;
				}
			}
		}

		public Color3D(float r, float g, float b)
		{
			R = r;
			G = g;
			B = b;
		}

		public Color3D(float value)
		{
			R = value;
			G = value;
			B = value;
		}

		public bool IsBlack()
		{
			float num = 0.01f;
			return Math.Abs(R) < num && Math.Abs(G) < num && Math.Abs(B) < num;
		}

		public static Color3D operator +(Color3D a, Color3D b)
		{
			Color3D result = default(Color3D);
			result.R = a.R + b.R;
			result.G = a.G + b.G;
			result.B = a.B + b.B;
			return result;
		}

		public static Color3D operator +(Color3D color, float value)
		{
			Color3D result = default(Color3D);
			result.R = color.R + value;
			result.G = color.G + value;
			result.B = color.B + value;
			return result;
		}

		public static Color3D operator +(float value, Color3D color)
		{
			Color3D result = default(Color3D);
			result.R = color.R + value;
			result.G = color.G + value;
			result.B = color.B + value;
			return result;
		}

		public static Color3D operator -(Color3D a, Color3D b)
		{
			Color3D result = default(Color3D);
			result.R = a.R - b.R;
			result.G = a.G - b.G;
			result.B = a.B - b.B;
			return result;
		}

		public static Color3D operator -(Color3D color, float value)
		{
			Color3D result = default(Color3D);
			result.R = color.R - value;
			result.G = color.G - value;
			result.B = color.B - value;
			return result;
		}

		public static Color3D operator -(float value, Color3D color)
		{
			Color3D result = default(Color3D);
			result.R = value - color.R;
			result.G = value - color.G;
			result.B = value - color.B;
			return result;
		}

		public static Color3D operator *(Color3D a, Color3D b)
		{
			Color3D result = default(Color3D);
			result.R = a.R * b.R;
			result.G = a.G * b.G;
			result.B = a.B * b.B;
			return result;
		}

		public static Color3D operator *(Color3D value, float scale)
		{
			Color3D result = default(Color3D);
			result.R = value.R * scale;
			result.G = value.G * scale;
			result.B = value.B * scale;
			return result;
		}

		public static Color3D operator *(float scale, Color3D value)
		{
			Color3D result = default(Color3D);
			result.R = value.R * scale;
			result.G = value.G * scale;
			result.B = value.B * scale;
			return result;
		}

		public static Color3D operator /(Color3D a, Color3D b)
		{
			Color3D result = default(Color3D);
			result.R = a.R / b.R;
			result.G = a.G / b.G;
			result.B = a.B / b.B;
			return result;
		}

		public static Color3D operator /(Color3D color, float divisor)
		{
			float num = 1f / divisor;
			Color3D result = default(Color3D);
			result.R = color.R * num;
			result.G = color.G * num;
			result.B = color.B * num;
			return result;
		}

		public static bool operator ==(Color3D a, Color3D b)
		{
			return a.R == b.R && a.G == b.G && a.B == b.B;
		}

		public static bool operator !=(Color3D a, Color3D b)
		{
			return a.R != b.R || a.G != b.G || a.B != b.B;
		}

		public bool Equals(Color3D other)
		{
			return R == other.R && G == other.G && B == other.B;
		}

		public override bool Equals(object obj)
		{
			if (obj is Color3D)
			{
				return Equals((Color3D)obj);
			}
			return false;
		}

		public override int GetHashCode()
		{
			return R.GetHashCode() + G.GetHashCode() + B.GetHashCode();
		}

		public override string ToString()
		{
			CultureInfo currentCulture = CultureInfo.CurrentCulture;
			return string.Format(currentCulture, "{{R:{0} G:{1} B:{2}}}", new object[3]
			{
				R.ToString(currentCulture),
				G.ToString(currentCulture),
				B.ToString(currentCulture)
			});
		}
	}
	public struct Color4D : IEquatable<Color4D>
	{
		public float R;

		public float G;

		public float B;

		public float A;

		public float this[int index]
		{
			get
			{
				return index switch
				{
					0 => R, 
					1 => G, 
					2 => B, 
					3 => A, 
					_ => 0f, 
				};
			}
			set
			{
				switch (index)
				{
				case 0:
					R = value;
					break;
				case 1:
					G = value;
					break;
				case 2:
					B = value;
					break;
				case 3:
					A = value;
					break;
				}
			}
		}

		public Color4D(float r, float g, float b, float a)
		{
			R = r;
			G = g;
			B = b;
			A = a;
		}

		public Color4D(float r, float g, float b)
		{
			R = r;
			G = g;
			B = b;
			A = 1f;
		}

		public Color4D(float value)
		{
			R = value;
			G = value;
			B = value;
			A = value;
		}

		public Color4D(Color3D rgb)
		{
			R = rgb.R;
			G = rgb.G;
			B = rgb.B;
			A = 1f;
		}

		public Color4D(Color3D rgb, float alpha)
		{
			R = rgb.R;
			G = rgb.G;
			B = rgb.B;
			A = alpha;
		}

		public bool IsBlack()
		{
			float num = 0.01f;
			return Math.Abs(R) < num && Math.Abs(G) < num && Math.Abs(B) < num;
		}

		public static Color4D operator +(Color4D a, Color4D b)
		{
			Color4D result = default(Color4D);
			result.R = a.R + b.R;
			result.G = a.G + b.G;
			result.B = a.B + b.B;
			result.A = a.A + b.A;
			return result;
		}

		public static Color4D operator +(Color4D color, float value)
		{
			Color4D result = default(Color4D);
			result.R = color.R + value;
			result.G = color.G + value;
			result.B = color.B + value;
			result.A = color.A + value;
			return result;
		}

		public static Color4D operator +(float value, Color4D color)
		{
			Color4D result = default(Color4D);
			result.R = color.R + value;
			result.G = color.G + value;
			result.B = color.B + value;
			result.A = color.A + value;
			return result;
		}

		public static Color4D operator -(Color4D a, Color4D b)
		{
			Color4D result = default(Color4D);
			result.R = a.R - b.R;
			result.G = a.G - b.G;
			result.B = a.B - b.B;
			result.A = a.A - b.A;
			return result;
		}

		public static Color4D operator -(Color4D color, float value)
		{
			Color4D result = default(Color4D);
			result.R = color.R - value;
			result.G = color.G - value;
			result.B = color.B - value;
			result.A = color.A - value;
			return result;
		}

		public static Color4D operator -(float value, Color4D color)
		{
			Color4D result = default(Color4D);
			result.R = value - color.R;
			result.G = value - color.G;
			result.B = value - color.B;
			result.A = value - color.A;
			return result;
		}

		public static Color4D operator *(Color4D a, Color4D b)
		{
			Color4D result = default(Color4D);
			result.R = a.R * b.R;
			result.G = a.G * b.G;
			result.B = a.B * b.B;
			result.A = a.A * b.A;
			return result;
		}

		public static Color4D operator *(Color4D value, float scale)
		{
			Color4D result = default(Color4D);
			result.R = value.R * scale;
			result.G = value.G * scale;
			result.B = value.B * scale;
			result.A = value.A * scale;
			return result;
		}

		public static Color4D operator *(float scale, Color4D value)
		{
			Color4D result = default(Color4D);
			result.R = value.R * scale;
			result.G = value.G * scale;
			result.B = value.B * scale;
			result.A = value.A * scale;
			return result;
		}

		public static Color4D operator /(Color4D a, Color4D b)
		{
			Color4D result = default(Color4D);
			result.R = a.R / b.R;
			result.G = a.G / b.G;
			result.B = a.B / b.B;
			result.A = a.A / b.A;
			return result;
		}

		public static Color4D operator /(Color4D color, float divisor)
		{
			float num = 1f / divisor;
			Color4D result = default(Color4D);
			result.R = color.R * num;
			result.G = color.G * num;
			result.B = color.B * num;
			result.A = color.A * num;
			return result;
		}

		public static bool operator ==(Color4D a, Color4D b)
		{
			return a.R == b.R && a.G == b.G && a.B == b.B && a.A == b.A;
		}

		public static bool operator !=(Color4D a, Color4D b)
		{
			return a.R != b.R || a.G != b.G || a.B != b.B || a.A != b.A;
		}

		public bool Equals(Color4D other)
		{
			return R == other.R && G == other.G && B == other.B && A == other.A;
		}

		public override bool Equals(object obj)
		{
			if (obj is Color4D)
			{
				return Equals((Color4D)obj);
			}
			return false;
		}

		public override int GetHashCode()
		{
			return R.GetHashCode() + G.GetHashCode() + B.GetHashCode() + A.GetHashCode();
		}

		public override string ToString()
		{
			CultureInfo currentCulture = CultureInfo.CurrentCulture;
			return string.Format(currentCulture, "{{R:{0} G:{1} B:{2} A:{3}}}", R.ToString(currentCulture), G.ToString(currentCulture), B.ToString(currentCulture), A.ToString(currentCulture));
		}
	}
	public sealed class EmbeddedTexture : IMarshalable<EmbeddedTexture, AiTexture>
	{
		private string m_filename;

		private bool m_isCompressed;

		private int m_width;

		private int m_height;

		private Texel[] m_nonCompressedData;

		private byte[] m_compressedData;

		private string m_compressedFormatHint;

		public string Filename
		{
			get
			{
				return m_filename;
			}
			set
			{
				m_filename = value;
			}
		}

		public bool IsCompressed => m_isCompressed;

		public int Width => m_width;

		public int Height => m_height;

		public bool HasNonCompressedData => m_nonCompressedData != null || m_nonCompressedData.Length != 0;

		public int NonCompressedDataSize => (m_nonCompressedData != null) ? m_nonCompressedData.Length : 0;

		public Texel[] NonCompressedData => m_nonCompressedData;

		public bool HasCompressedData => m_compressedData != null || m_compressedData.Length != 0;

		public int CompressedDataSize => (m_compressedData != null) ? m_compressedData.Length : 0;

		public byte[] CompressedData => m_compressedData;

		public string CompressedFormatHint => m_compressedFormatHint;

		bool IMarshalable<EmbeddedTexture, AiTexture>.IsNativeBlittable => true;

		public EmbeddedTexture()
		{
			m_isCompressed = false;
		}

		public EmbeddedTexture(string compressedFormatHint, byte[] compressedData, string originalFileName = "")
		{
			m_filename = originalFileName;
			m_compressedFormatHint = compressedFormatHint;
			m_compressedData = compressedData;
			m_isCompressed = true;
			m_width = 0;
			m_height = 0;
			m_nonCompressedData = null;
		}

		public EmbeddedTexture(int width, int height, Texel[] uncompressedData, string originalFileName = "")
		{
			m_filename = originalFileName;
			m_width = width;
			m_height = height;
			m_nonCompressedData = uncompressedData;
			if (m_width * m_height != NonCompressedDataSize)
			{
				throw new ArgumentException("Texel data size does not match width * height.");
			}
			m_isCompressed = false;
			m_compressedFormatHint = null;
			m_compressedData = null;
		}

		void IMarshalable<EmbeddedTexture, AiTexture>.ToNative(IntPtr thisPtr, out AiTexture nativeValue)
		{
			nativeValue.Filename = new AiString(m_filename);
			if (IsCompressed)
			{
				nativeValue.Width = (uint)CompressedDataSize;
				nativeValue.Height = 0u;
				nativeValue.Data = IntPtr.Zero;
				if (CompressedDataSize > 0)
				{
					nativeValue.Data = MemoryHelper.ToNativeArray(m_compressedData);
				}
				nativeValue.SetFormatHint(m_compressedFormatHint);
			}
			else
			{
				nativeValue.Width = (uint)m_width;
				nativeValue.Height = (uint)m_height;
				nativeValue.Data = IntPtr.Zero;
				if (NonCompressedDataSize > 0)
				{
					nativeValue.Data = MemoryHelper.ToNativeArray(m_nonCompressedData);
				}
				nativeValue.SetFormatHint(null);
			}
		}

		void IMarshalable<EmbeddedTexture, AiTexture>.FromNative(in AiTexture nativeValue)
		{
			m_filename = AiString.GetString(in nativeValue.Filename);
			m_isCompressed = nativeValue.Height == 0;
			if (IsCompressed)
			{
				m_width = 0;
				m_height = 0;
				m_nonCompressedData = null;
				m_compressedData = null;
				if (nativeValue.Width != 0 && nativeValue.Data != IntPtr.Zero)
				{
					m_compressedData = MemoryHelper.FromNativeArray<byte>(nativeValue.Data, (int)nativeValue.Width);
				}
				m_compressedFormatHint = AiTexture.GetFormatHint(in nativeValue);
				return;
			}
			m_compressedData = null;
			m_compressedFormatHint = null;
			m_nonCompressedData = null;
			m_width = (int)nativeValue.Width;
			m_height = (int)nativeValue.Height;
			int num = m_width * m_height;
			if (num > 0 && nativeValue.Data != IntPtr.Zero)
			{
				m_nonCompressedData = MemoryHelper.FromNativeArray<Texel>(nativeValue.Data, num);
			}
		}

		public static void FreeNative(IntPtr nativeValue, bool freeNative)
		{
			if (!(nativeValue == IntPtr.Zero))
			{
				AiTexture aiTexture = MemoryHelper.Read<AiTexture>(nativeValue);
				if (aiTexture.Width != 0 && aiTexture.Data != IntPtr.Zero)
				{
					MemoryHelper.FreeMemory(aiTexture.Data);
				}
				if (freeNative)
				{
					MemoryHelper.FreeMemory(nativeValue);
				}
			}
		}
	}
	public enum MetaDataType
	{
		Bool,
		Int32,
		UInt64,
		Float,
		Double,
		String,
		Vector3D
	}
	[Flags]
	public enum PostProcessSteps : uint
	{
		None = 0u,
		CalculateTangentSpace = 1u,
		JoinIdenticalVertices = 2u,
		MakeLeftHanded = 4u,
		Triangulate = 8u,
		RemoveComponent = 0x10u,
		GenerateNormals = 0x20u,
		GenerateSmoothNormals = 0x40u,
		SplitLargeMeshes = 0x80u,
		PreTransformVertices = 0x100u,
		LimitBoneWeights = 0x200u,
		ValidateDataStructure = 0x400u,
		ImproveCacheLocality = 0x800u,
		RemoveRedundantMaterials = 0x1000u,
		FixInFacingNormals = 0x2000u,
		SortByPrimitiveType = 0x8000u,
		FindDegenerates = 0x10000u,
		FindInvalidData = 0x20000u,
		GenerateUVCoords = 0x40000u,
		TransformUVCoords = 0x80000u,
		FindInstances = 0x100000u,
		OptimizeMeshes = 0x200000u,
		OptimizeGraph = 0x400000u,
		FlipUVs = 0x800000u,
		FlipWindingOrder = 0x1000000u,
		SplitByBoneCount = 0x2000000u,
		Debone = 0x4000000u,
		GlobalScale = 0x8000000u,
		EmbedTextures = 0x10000000u,
		ForceGenerateNormals = 0x20000000u,
		DropNormals = 0x40000000u,
		GenerateBoundingBoxes = 0x80000000u
	}
	[Flags]
	public enum ExcludeComponent
	{
		None = 0,
		Normals = 2,
		TangentBasis = 4,
		Colors = 8,
		TexCoords = 0x10,
		Boneweights = 0x20,
		Animations = 0x40,
		Textures = 0x80,
		Lights = 0x100,
		Cameras = 0x200,
		Meshes = 0x400,
		Materials = 0x800
	}
	[Flags]
	public enum PrimitiveType
	{
		Point = 1,
		Line = 2,
		Triangle = 4,
		Polygon = 8
	}
	public enum AnimationBehaviour
	{
		Default,
		Constant,
		Linear,
		Repeat
	}
	public enum MeshMorphingMethod
	{
		None,
		VertexBlend,
		MorphNormalized,
		MorphRelative
	}
	public enum LightSourceType
	{
		Undefined,
		Directional,
		Point,
		Spot,
		Ambient,
		Area
	}
	public enum BlendMode
	{
		Default,
		Additive
	}
	public enum ShadingMode
	{
		None,
		Flat,
		Gouraud,
		Phong,
		Blinn,
		Toon,
		OrenNayar,
		Minnaert,
		CookTorrance,
		NoShading,
		Fresnel
	}
	[Flags]
	public enum TextureFlags
	{
		Invert = 1,
		UseAlpha = 2,
		IgnoreAlpha = 4
	}
	public enum TextureWrapMode
	{
		Wrap,
		Clamp,
		Mirror,
		Decal
	}
	public enum TextureMapping
	{
		FromUV,
		Sphere,
		Cylinder,
		Box,
		Plane,
		Unknown
	}
	public enum TextureOperation
	{
		Multiply,
		Add,
		Subtract,
		Divide,
		SmoothAdd,
		SignedAdd
	}
	public enum TextureType
	{
		None,
		Diffuse,
		Specular,
		Ambient,
		Emissive,
		Height,
		Normals,
		Shininess,
		Opacity,
		Displacement,
		Lightmap,
		Reflection,
		BaseColor,
		NormalCamera,
		EmissionColor,
		Metalness,
		Roughness,
		AmbientOcclusion,
		Unknown
	}
	[Flags]
	public enum SceneFlags
	{
		None = 0,
		Incomplete = 1,
		Validated = 2,
		ValidationWarning = 4,
		NonVerboseFormat = 8,
		Terrain = 0x10,
		AllowShared = 0x20
	}
	public enum ReturnCode
	{
		Success = 0,
		Failure = -1,
		OutOfMemory = -3
	}
	public enum Origin
	{
		Set,
		Current,
		End
	}
	[Flags]
	public enum DefaultLogStream
	{
		File = 1,
		StdOut = 2,
		StdErr = 4,
		Debugger = 8
	}
	public enum PropertyType
	{
		Float = 1,
		Double,
		String,
		Integer,
		Buffer
	}
	public enum CompileFlags
	{
		Shared = 1,
		STLport = 2,
		Debug = 4,
		NoBoost = 8,
		SingleThreaded = 0x10
	}
	[Flags]
	public enum UVTransformFlags
	{
		Scaling = 1,
		Rotation = 2,
		Translation = 4
	}
	public enum FileIOMode
	{
		Write,
		WriteBinary,
		WriteText,
		Read,
		ReadBinary,
		ReadText
	}
	[Flags]
	public enum ImporterFeatureFlags
	{
		SupportsText = 1,
		SupportsBinary = 2,
		SupportsCompressed = 4,
		LimitedSupport = 8,
		Experimental = 0x10
	}
	public sealed class ExportDataBlob
	{
		private class BlobBinaryReader : BinaryReader
		{
			public BlobBinaryReader(Stream stream)
				: base(stream, Encoding.UTF8)
			{
			}

			protected override void Dispose(bool disposing)
			{
				base.Dispose(disposing: false);
			}
		}

		private string m_name;

		private byte[] m_data;

		private ExportDataBlob m_next;

		public string Name => m_name;

		public byte[] Data => m_data;

		public ExportDataBlob NextBlob => m_next;

		public bool HasData => m_data != null;

		internal ExportDataBlob(ref AiExportDataBlob dataBlob)
		{
			m_name = dataBlob.Name.GetString();
			if (dataBlob.Size.ToUInt32() != 0 && dataBlob.Data != IntPtr.Zero)
			{
				m_data = MemoryHelper.FromNativeArray<byte>(dataBlob.Data, (int)dataBlob.Size.ToUInt32());
			}
			m_next = null;
			if (dataBlob.NextBlob != IntPtr.Zero)
			{
				AiExportDataBlob dataBlob2 = MemoryHelper.MarshalStructure<AiExportDataBlob>(dataBlob.NextBlob);
				m_next = new ExportDataBlob(ref dataBlob2);
			}
		}

		internal ExportDataBlob(string name, byte[] data)
		{
			m_name = name;
			m_data = data;
			m_next = null;
		}

		public void ToStream(Stream stream)
		{
			MemoryStream memoryStream = new MemoryStream();
			using BinaryWriter writer = new BinaryWriter(memoryStream);
			WriteBlob(this, writer);
			memoryStream.Position = 0L;
			memoryStream.WriteTo(stream);
		}

		public static ExportDataBlob FromStream(Stream stream)
		{
			if (stream == null || !stream.CanRead)
			{
				return null;
			}
			using BlobBinaryReader reader = new BlobBinaryReader(stream);
			return ReadBlob(reader);
		}

		private static void WriteBlob(ExportDataBlob blob, BinaryWriter writer)
		{
			if (blob != null && writer != null)
			{
				bool flag = blob.NextBlob != null;
				writer.Write(blob.Name);
				writer.Write(blob.Data.Length);
				writer.Write(blob.Data);
				writer.Write(flag);
				if (flag)
				{
					WriteBlob(blob.NextBlob, writer);
				}
			}
		}

		private static ExportDataBlob ReadBlob(BinaryReader reader)
		{
			if (reader == null)
			{
				return null;
			}
			string name = reader.ReadString();
			int count = reader.ReadInt32();
			byte[] data = reader.ReadBytes(count);
			bool flag = reader.ReadBoolean();
			ExportDataBlob exportDataBlob = new ExportDataBlob(name, data);
			if (flag)
			{
				exportDataBlob.m_next = ReadBlob(reader);
			}
			return exportDataBlob;
		}
	}
	[DebuggerDisplay("{Description}")]
	public sealed class ExportFormatDescription
	{
		private string m_formatId;

		private string m_description;

		private string m_fileExtension;

		public string FormatId => m_formatId;

		public string Description => m_description;

		public string FileExtension => m_fileExtension;

		internal ExportFormatDescription(in AiExportFormatDesc formatDesc)
		{
			m_formatId = Marshal.PtrToStringAnsi(formatDesc.FormatId);
			m_description = Marshal.PtrToStringAnsi(formatDesc.Description);
			m_fileExtension = Marshal.PtrToStringAnsi(formatDesc.FileExtension);
			if (m_fileExtension == "dae")
			{
				m_formatId = "collada";
			}
		}
	}
	public sealed class Face : IMarshalable<Face, AiFace>
	{
		private List<int> m_indices;

		public int IndexCount => m_indices.Count;

		public bool HasIndices => m_indices.Count > 0;

		public List<int> Indices => m_indices;

		bool IMarshalable<Face, AiFace>.IsNativeBlittable => true;

		public Face()
		{
			m_indices = new List<int>();
		}

		public Face(int[] indices)
		{
			m_indices = new List<int>();
			if (indices != null)
			{
				m_indices.AddRange(indices);
			}
		}

		void IMarshalable<Face, AiFace>.ToNative(IntPtr thisPtr, out AiFace nativeValue)
		{
			nativeValue.NumIndices = (uint)IndexCount;
			nativeValue.Indices = IntPtr.Zero;
			if (nativeValue.NumIndices != 0)
			{
				nativeValue.Indices = MemoryHelper.ToNativeArray(m_indices.ToArray());
			}
		}

		void IMarshalable<Face, AiFace>.FromNative(in AiFace nativeValue)
		{
			m_indices.Clear();
			if (nativeValue.NumIndices != 0 && nativeValue.Indices != IntPtr.Zero)
			{
				m_indices.AddRange(MemoryHelper.FromNativeArray<int>(nativeValue.Indices, (int)nativeValue.NumIndices));
			}
		}

		public static void FreeNative(IntPtr nativeValue, bool freeNative)
		{
			if (!(nativeValue == IntPtr.Zero))
			{
				AiFace aiFace = MemoryHelper.Read<AiFace>(nativeValue);
				if (aiFace.NumIndices != 0 && aiFace.Indices != IntPtr.Zero)
				{
					MemoryHelper.FreeMemory(aiFace.Indices);
				}
				if (freeNative)
				{
					MemoryHelper.FreeMemory(nativeValue);
				}
			}
		}
	}
	public class FileIOSystem : IOSystem
	{
		private List<DirectoryInfo> m_searchDirectories;

		public FileIOSystem()
			: this((string[])null)
		{
		}

		public FileIOSystem(params string[] searchPaths)
		{
			m_searchDirectories = new List<DirectoryInfo>();
			SetSearchDirectories(searchPaths);
		}

		public void SetSearchDirectories(params string[] searchPaths)
		{
			m_searchDirectories.Clear();
			if (searchPaths == null || searchPaths.Length == 0)
			{
				return;
			}
			foreach (string text in searchPaths)
			{
				if (!string.IsNullOrEmpty(text) && Directory.Exists(text))
				{
					m_searchDirectories.Add(new DirectoryInfo(text));
				}
			}
		}

		public string[] GetSearchDirectories()
		{
			List<string> list = new List<string>();
			foreach (DirectoryInfo searchDirectory in m_searchDirectories)
			{
				list.Add(searchDirectory.FullName);
			}
			return list.ToArray();
		}

		public override IOStream OpenFile(string pathToFile, FileIOMode fileMode)
		{
			return new FileIOStream(this, pathToFile, fileMode);
		}

		public bool FindFile(string fileName, out string pathToFile)
		{
			pathToFile = null;
			if (string.IsNullOrEmpty(fileName) || m_searchDirectories.Count == 0)
			{
				return false;
			}
			foreach (DirectoryInfo searchDirectory in m_searchDirectories)
			{
				string text = Path.Combine(searchDirectory.FullName, fileName);
				if (File.Exists(text))
				{
					pathToFile = text;
					return true;
				}
			}
			return false;
		}
	}
	internal class FileIOStream : IOStream
	{
		private FileIOSystem m_parent;

		private FileStream m_fileStream;

		public override bool IsValid => m_fileStream != null;

		public FileIOStream(FileIOSystem parent, string pathToFile, FileIOMode fileMode)
			: base(pathToFile, fileMode)
		{
			m_parent = parent;
			switch (fileMode)
			{
			case FileIOMode.Read:
			case FileIOMode.ReadBinary:
			case FileIOMode.ReadText:
				OpenRead(pathToFile, fileMode);
				break;
			case FileIOMode.Write:
			case FileIOMode.WriteBinary:
			case FileIOMode.WriteText:
				OpenWrite(pathToFile, fileMode);
				break;
			}
		}

		public override long Write(byte[] dataToWrite, long count)
		{
			if (dataToWrite == null)
			{
				throw new ArgumentOutOfRangeException("dataToWrite", "Data to write cannot be null.");
			}
			if (count < 0 || dataToWrite.Length < count)
			{
				throw new ArgumentOutOfRangeException("count", "Number of bytes to write is greater than data size.");
			}
			if (m_fileStream == null || !m_fileStream.CanWrite)
			{
				throw new IOException("Stream is not writable.");
			}
			if (m_fileStream.Position >= m_fileStream.Length)
			{
				return 0L;
			}
			m_fileStream.Write(dataToWrite, (int)m_fileStream.Position, (int)count);
			return count;
		}

		public override long Read(byte[] dataRead, long count)
		{
			if (dataRead == null)
			{
				throw new ArgumentOutOfRangeException("dataRead", "Array to store data in cannot be null.");
			}
			if (count < 0 || dataRead.Length < count)
			{
				throw new ArgumentOutOfRangeException("count", "Number of bytes to read is greater than data store size.");
			}
			if (m_fileStream == null || !m_fileStream.CanRead)
			{
				throw new IOException("Stream is not readable.");
			}
			if (m_fileStream.Position >= m_fileStream.Length)
			{
				return 0L;
			}
			m_fileStream.Read(dataRead, (int)m_fileStream.Position, (int)count);
			return count;
		}

		public override ReturnCode Seek(long offset, Origin seekOrigin)
		{
			if (m_fileStream == null || !m_fileStream.CanSeek)
			{
				throw new IOException("Stream does not support seeking.");
			}
			SeekOrigin origin = SeekOrigin.Begin;
			switch (seekOrigin)
			{
			case Origin.Set:
				origin = SeekOrigin.Begin;
				break;
			case Origin.Current:
				origin = SeekOrigin.Current;
				break;
			case Origin.End:
				origin = SeekOrigin.End;
				break;
			}
			m_fileStream.Seek(offset, origin);
			return ReturnCode.Success;
		}

		public override long GetPosition()
		{
			if (m_fileStream == null)
			{
				return -1L;
			}
			return m_fileStream.Position;
		}

		public override long GetFileSize()
		{
			if (m_fileStream == null)
			{
				return 0L;
			}
			return m_fileStream.Length;
		}

		public override void Flush()
		{
			if (m_fileStream != null)
			{
				m_fileStream.Flush();
			}
		}

		protected override void Dispose(bool disposing)
		{
			if (!base.IsDisposed && disposing)
			{
				if (m_fileStream != null)
				{
					m_fileStream.Dispose();
				}
				m_fileStream = null;
				base.Dispose(disposing);
			}
		}

		private void OpenRead(string pathToFile, FileIOMode fileMode)
		{
			string fileName = Path.GetFileName(pathToFile);
			if (m_parent.FindFile(fileName, out var pathToFile2))
			{
				pathToFile = pathToFile2;
			}
			if (File.Exists(pathToFile))
			{
				m_fileStream = File.OpenRead(pathToFile);
			}
		}

		private void OpenWrite(string pathToFile, FileIOMode fileMode)
		{
			m_fileStream = File.OpenWrite(pathToFile);
		}
	}
	[DebuggerDisplay("{Name}")]
	public sealed class ImporterDescription
	{
		private string m_name;

		private string m_author;

		private string m_maintainer;

		private string m_comments;

		private ImporterFeatureFlags m_featureFlags;

		private Version m_minVersion;

		private Version m_maxVersion;

		private string[] m_fileExtensions;

		public string Name => m_name;

		public string Author => m_author;

		public string Maintainer => m_maintainer;

		public string Comments => m_comments;

		public ImporterFeatureFlags FeatureFlags => m_featureFlags;

		public Version MinVersion => m_minVersion;

		public Version MaxVersion => m_maxVersion;

		public string[] FileExtensions => m_fileExtensions;

		internal ImporterDescription(in AiImporterDesc descr)
		{
			m_name = Marshal.PtrToStringAnsi(descr.Name);
			m_author = Marshal.PtrToStringAnsi(descr.Author);
			m_maintainer = Marshal.PtrToStringAnsi(descr.Maintainer);
			m_comments = Marshal.PtrToStringAnsi(descr.Comments);
			m_featureFlags = descr.Flags;
			m_minVersion = new Version((int)descr.MinMajor, (int)descr.MinMinor);
			m_maxVersion = new Version((int)descr.MaxMajor, (int)descr.MaxMajor);
			string text = Marshal.PtrToStringAnsi(descr.FileExtensions);
			if (string.IsNullOrEmpty(text))
			{
				m_fileExtensions = new string[0];
				return;
			}
			m_fileExtensions = text.Split(new char[1] { ' ' });
		}
	}
	public interface IMarshalable<Managed, Native> where Managed : class, new() where Native : struct
	{
		bool IsNativeBlittable { get; }

		void ToNative(IntPtr thisPtr, out Native nativeValue);

		void FromNative(in Native nativeValue);
	}
	public interface INativeCustomMarshaler
	{
		int NativeDataSize { get; }

		void MarshalManagedToNative(object managedObj, IntPtr nativeData);

		object MarshalNativeToManaged(IntPtr nativeData);
	}
	public abstract class IOStream : IDisposable
	{
		private AiFileWriteProc m_writeProc;

		private AiFileReadProc m_readProc;

		private AiFileTellProc m_tellProc;

		private AiFileTellProc m_fileSizeProc;

		private AiFileSeek m_seekProc;

		private AiFileFlushProc m_flushProc;

		private IntPtr m_filePtr;

		private bool m_isDiposed;

		private string m_pathToFile;

		private FileIOMode m_fileMode;

		private byte[] m_byteBuffer;

		public bool IsDisposed => m_isDiposed;

		public string PathToFile => m_pathToFile;

		public FileIOMode FileMode => m_fileMode;

		public abstract bool IsValid { get; }

		internal IntPtr AiFile => m_filePtr;

		public IOStream(string pathToFile, FileIOMode fileMode)
		{
			m_pathToFile = pathToFile;
			m_fileMode = fileMode;
			m_writeProc = OnAiFileWriteProc;
			m_readProc = OnAiFileReadProc;
			m_tellProc = OnAiFileTellProc;
			m_fileSizeProc = OnAiFileSizeProc;
			m_seekProc = OnAiFileSeekProc;
			m_flushProc = OnAiFileFlushProc;
			AiFile aiFile = default(AiFile);
			aiFile.WriteProc = Marshal.GetFunctionPointerForDelegate((Delegate)m_writeProc);
			aiFile.ReadProc = Marshal.GetFunctionPointerForDelegate((Delegate)m_readProc);
			aiFile.TellProc = Marshal.GetFunctionPointerForDelegate((Delegate)m_tellProc);
			aiFile.FileSizeProc = Marshal.GetFunctionPointerForDelegate((Delegate)m_fileSizeProc);
			aiFile.SeekProc = Marshal.GetFunctionPointerForDelegate((Delegate)m_seekProc);
			aiFile.FlushProc = Marshal.GetFunctionPointerForDelegate((Delegate)m_flushProc);
			aiFile.UserData = IntPtr.Zero;
			m_filePtr = MemoryHelper.AllocateMemory(MemoryHelper.SizeOf<AiFile>());
			Marshal.StructureToPtr((object)aiFile, m_filePtr, fDeleteOld: false);
		}

		~IOStream()
		{
			Dispose(disposing: false);
		}

		public void Dispose()
		{
			Dispose(disposing: true);
			GC.SuppressFinalize(this);
		}

		protected virtual void Dispose(bool disposing)
		{
			if (!m_isDiposed)
			{
				if (m_filePtr != IntPtr.Zero)
				{
					MemoryHelper.FreeMemory(m_filePtr);
					m_filePtr = IntPtr.Zero;
				}
				if (disposing)
				{
					m_writeProc = null;
					m_readProc = null;
					m_tellProc = null;
					m_fileSizeProc = null;
					m_seekProc = null;
					m_flushProc = null;
				}
				m_isDiposed = true;
			}
		}

		public abstract long Write(byte[] dataToWrite, long count);

		public abstract long Read(byte[] dataRead, long count);

		public abstract ReturnCode Seek(long offset, Origin seekOrigin);

		public abstract long GetPosition();

		public abstract long GetFileSize();

		public abstract void Flush();

		public virtual void Close()
		{
			Flush();
			Dispose();
		}

		private UIntPtr OnAiFileWriteProc(IntPtr file, IntPtr dataToWrite, UIntPtr sizeOfElemInBytes, UIntPtr numElements)
		{
			if (m_filePtr != file)
			{
				return UIntPtr.Zero;
			}
			long num = (long)sizeOfElemInBytes.ToUInt64();
			long num2 = (long)numElements.ToUInt64();
			long num3 = num * num2;
			if (num3 == 0)
			{
				return UIntPtr.Zero;
			}
			byte[] byteBuffer = GetByteBuffer(num, num2);
			MemoryHelper.Read(dataToWrite, byteBuffer, 0, (int)num3);
			long num4 = 0L;
			try
			{
				num4 = Write(byteBuffer, num3);
			}
			catch (Exception)
			{
			}
			return new UIntPtr((ulong)num4 / (ulong)num);
		}

		private UIntPtr OnAiFileReadProc(IntPtr file, IntPtr dataRead, UIntPtr sizeOfElemInBytes, UIntPtr numElements)
		{
			if (m_filePtr != file)
			{
				return UIntPtr.Zero;
			}
			long num = (long)sizeOfElemInBytes.ToUInt64();
			long num2 = (long)numElements.ToUInt64();
			long count = num * num2;
			byte[] byteBuffer = GetByteBuffer(num, num2);
			long num3 = 0L;
			try
			{
				num3 = Read(byteBuffer, count);
				if (num3 > 0)
				{
					MemoryHelper.Write(dataRead, byteBuffer, 0, (int)num3);
				}
			}
			catch (Exception)
			{
			}
			return new UIntPtr((ulong)num3 / (ulong)num);
		}

		private UIntPtr OnAiFileTellProc(IntPtr file)
		{
			if (m_filePtr != file)
			{
				return UIntPtr.Zero;
			}
			long value = 0L;
			try
			{
				value = GetPosition();
			}
			catch (Exception)
			{
			}
			return new UIntPtr((ulong)value);
		}

		private UIntPtr OnAiFileSizeProc(IntPtr file)
		{
			if (m_filePtr != file)
			{
				return UIntPtr.Zero;
			}
			long value = 0L;
			try
			{
				value = GetFileSize();
			}
			catch (Exception)
			{
			}
			return new UIntPtr((ulong)value);
		}

		private ReturnCode OnAiFileSeekProc(IntPtr file, UIntPtr offset, Origin seekOrigin)
		{
			if (m_filePtr != file)
			{
				return ReturnCode.Failure;
			}
			ReturnCode result = ReturnCode.Failure;
			try
			{
				result = Seek((long)offset.ToUInt64(), seekOrigin);
			}
			catch (Exception)
			{
			}
			return result;
		}

		private void OnAiFileFlushProc(IntPtr file)
		{
			if (m_filePtr != file)
			{
				return;
			}
			try
			{
				Flush();
			}
			catch (Exception)
			{
			}
		}

		private byte[] GetByteBuffer(long sizeOfElemInBytes, long numElements)
		{
			if (m_byteBuffer == null || m_byteBuffer.Length < sizeOfElemInBytes * numElements)
			{
				m_byteBuffer = new byte[sizeOfElemInBytes * numElements];
			}
			return m_byteBuffer;
		}
	}
	public abstract class IOSystem : IDisposable
	{
		private AiFileOpenProc m_openProc;

		private AiFileCloseProc m_closeProc;

		private IntPtr m_fileIOPtr;

		private bool m_isDisposed;

		private Dictionary<IntPtr, IOStream> m_openedFiles;

		public bool IsDisposed => m_isDisposed;

		public int OpenFileCount => m_openedFiles.Count;

		internal IntPtr AiFileIO => m_fileIOPtr;

		public IOSystem()
		{
			m_openProc = OnAiFileOpenProc;
			m_closeProc = OnAiFileCloseProc;
			AiFileIO aiFileIO = default(AiFileIO);
			aiFileIO.OpenProc = Marshal.GetFunctionPointerForDelegate((Delegate)m_openProc);
			aiFileIO.CloseProc = Marshal.GetFunctionPointerForDelegate((Delegate)m_closeProc);
			aiFileIO.UserData = IntPtr.Zero;
			m_fileIOPtr = MemoryHelper.AllocateMemory(MemoryHelper.SizeOf<AiFileIO>());
			Marshal.StructureToPtr((object)aiFileIO, m_fileIOPtr, fDeleteOld: false);
			m_openedFiles = new Dictionary<IntPtr, IOStream>();
		}

		~IOSystem()
		{
			Dispose(disposing: false);
		}

		public abstract IOStream OpenFile(string pathToFile, FileIOMode fileMode);

		public virtual void CloseFile(IOStream stream)
		{
			if (stream != null && m_openedFiles.ContainsKey(stream.AiFile))
			{
				m_openedFiles.Remove(stream.AiFile);
				if (!stream.IsDisposed)
				{
					stream.Close();
				}
			}
		}

		public virtual void CloseAllFiles()
		{
			foreach (KeyValuePair<IntPtr, IOStream> openedFile in m_openedFiles)
			{
				if (!openedFile.Value.IsDisposed)
				{
					openedFile.Value.Close();
				}
			}
			m_openedFiles.Clear();
		}

		public void Dispose()
		{
			Dispose(disposing: true);
			GC.SuppressFinalize(this);
		}

		protected virtual void Dispose(bool disposing)
		{
			if (!m_isDisposed)
			{
				if (m_fileIOPtr != IntPtr.Zero)
				{
					MemoryHelper.FreeMemory(m_fileIOPtr);
					m_fileIOPtr = IntPtr.Zero;
				}
				if (disposing)
				{
					m_openProc = null;
					m_closeProc = null;
					CloseAllFiles();
				}
				m_isDisposed = true;
			}
		}

		private IntPtr OnAiFileOpenProc(IntPtr fileIO, string pathToFile, string mode)
		{
			if (m_fileIOPtr != fileIO)
			{
				return IntPtr.Zero;
			}
			FileIOMode fileMode = ConvertFileMode(mode);
			IOStream iOStream = OpenFile(pathToFile, fileMode);
			IntPtr intPtr = IntPtr.Zero;
			if (iOStream != null)
			{
				if (iOStream.IsValid)
				{
					intPtr = iOStream.AiFile;
					m_openedFiles.Add(intPtr, iOStream);
				}
				else
				{
					iOStream.Dispose();
				}
			}
			return intPtr;
		}

		private void OnAiFileCloseProc(IntPtr fileIO, IntPtr file)
		{
			if (!(m_fileIOPtr != fileIO) && m_openedFiles.TryGetValue(file, out var value))
			{
				CloseFile(value);
			}
		}

		private FileIOMode ConvertFileMode(string mode)
		{
			FileIOMode result = FileIOMode.Read;
			switch (mode)
			{
			case "w":
				result = FileIOMode.Write;
				break;
			case "wb":
				result = FileIOMode.WriteBinary;
				break;
			case "wt":
				result = FileIOMode.WriteText;
				break;
			case "r":
				result = FileIOMode.Read;
				break;
			case "rb":
				result = FileIOMode.ReadBinary;
				break;
			case "rt":
				result = FileIOMode.ReadText;
				break;
			}
			return result;
		}
	}
	public sealed class Light : IMarshalable<Light, AiLight>
	{
		private string m_name;

		private LightSourceType m_lightType;

		private float m_angleInnerCone;

		private float m_angleOuterCone;

		private float m_attConstant;

		private float m_attLinear;

		private float m_attQuadratic;

		private Vector3D m_position;

		private Vector3D m_direction;

		private Vector3D m_up;

		private Color3D m_diffuse;

		private Color3D m_specular;

		private Color3D m_ambient;

		private Vector2D m_areaSize;

		public string Name
		{
			get
			{
				return m_name;
			}
			set
			{
				m_name = value;
			}
		}

		public LightSourceType LightType
		{
			get
			{
				return m_lightType;
			}
			set
			{
				m_lightType = value;
			}
		}

		public float AngleInnerCone
		{
			get
			{
				return m_angleInnerCone;
			}
			set
			{
				m_angleInnerCone = value;
			}
		}

		public float AngleOuterCone
		{
			get
			{
				return m_angleOuterCone;
			}
			set
			{
				m_angleOuterCone = value;
			}
		}

		public float AttenuationConstant
		{
			get
			{
				return m_attConstant;
			}
			set
			{
				m_attConstant = value;
			}
		}

		public float AttenuationLinear
		{
			get
			{
				return m_attLinear;
			}
			set
			{
				m_attLinear = value;
			}
		}

		public float AttenuationQuadratic
		{
			get
			{
				return m_attQuadratic;
			}
			set
			{
				m_attQuadratic = value;
			}
		}

		public Vector3D Position
		{
			get
			{
				return m_position;
			}
			set
			{
				m_position = value;
			}
		}

		public Vector3D Direction
		{
			get
			{
				return m_direction;
			}
			set
			{
				m_direction = value;
			}
		}

		public Vector3D Up
		{
			get
			{
				return m_up;
			}
			set
			{
				m_up = value;
			}
		}

		public Color3D ColorDiffuse
		{
			get
			{
				return m_diffuse;
			}
			set
			{
				m_diffuse = value;
			}
		}

		public Color3D ColorSpecular
		{
			get
			{
				return m_specular;
			}
			set
			{
				m_specular = value;
			}
		}

		public Color3D ColorAmbient
		{
			get
			{
				return m_ambient;
			}
			set
			{
				m_ambient = value;
			}
		}

		public Vector2D AreaSize
		{
			get
			{
				return m_areaSize;
			}
			set
			{
				m_areaSize = value;
			}
		}

		bool IMarshalable<Light, AiLight>.IsNativeBlittable => true;

		public Light()
		{
			m_lightType = LightSourceType.Undefined;
			m_attConstant = 0f;
			m_attLinear = 1f;
			m_attQuadratic = 0f;
			m_angleInnerCone = (float)Math.PI * 2f;
			m_angleOuterCone = (float)Math.PI * 2f;
			m_areaSize = new Vector2D(0f, 0f);
		}

		void IMarshalable<Light, AiLight>.ToNative(IntPtr thisPtr, out AiLight nativeValue)
		{
			nativeValue.Name = new AiString(m_name);
			nativeValue.Type = m_lightType;
			nativeValue.AngleInnerCone = m_angleInnerCone;
			nativeValue.AngleOuterCone = m_angleOuterCone;
			nativeValue.AttenuationConstant = m_attConstant;
			nativeValue.AttenuationLinear = m_attLinear;
			nativeValue.AttenuationQuadratic = m_attQuadratic;
			nativeValue.ColorAmbient = m_ambient;
			nativeValue.ColorDiffuse = m_diffuse;
			nativeValue.ColorSpecular = m_specular;
			nativeValue.Direction = m_direction;
			nativeValue.Up = m_up;
			nativeValue.Position = m_position;
			nativeValue.AreaSize = m_areaSize;
		}

		void IMarshalable<Light, AiLight>.FromNative(in AiLight nativeValue)
		{
			m_name = AiString.GetString(in nativeValue.Name);
			m_lightType = nativeValue.Type;
			m_angleInnerCone = nativeValue.AngleInnerCone;
			m_angleOuterCone = nativeValue.AngleOuterCone;
			m_attConstant = nativeValue.AttenuationConstant;
			m_attLinear = nativeValue.AttenuationLinear;
			m_attQuadratic = nativeValue.AttenuationQuadratic;
			m_position = nativeValue.Position;
			m_direction = nativeValue.Direction;
			m_up = nativeValue.Up;
			m_diffuse = nativeValue.ColorDiffuse;
			m_specular = nativeValue.ColorSpecular;
			m_ambient = nativeValue.ColorAmbient;
			m_areaSize = nativeValue.AreaSize;
		}

		public static void FreeNative(IntPtr nativeValue, bool freeNative)
		{
			if (nativeValue != IntPtr.Zero && freeNative)
			{
				MemoryHelper.FreeMemory(nativeValue);
			}
		}
	}
	public delegate void LoggingCallback(string msg, string userData);
	[DebuggerDisplay("IsAttached = {IsAttached}")]
	public class LogStream : IDisposable
	{
		private static object s_sync;

		private static List<LogStream> s_activeLogstreams;

		private LoggingCallback m_logCallback;

		private AiLogStreamCallback m_assimpCallback;

		private IntPtr m_logstreamPtr;

		private string m_userData;

		private bool m_isDisposed;

		private bool m_isAttached;

		public static bool IsVerboseLoggingEnabled
		{
			get
			{
				return AssimpLibrary.Instance.GetVerboseLoggingEnabled();
			}
			set
			{
				AssimpLibrary.Instance.EnableVerboseLogging(value);
			}
		}

		public string UserData
		{
			get
			{
				return m_userData;
			}
			set
			{
				m_userData = value;
			}
		}

		public bool IsDisposed => m_isDisposed;

		public bool IsAttached => m_isAttached;

		static LogStream()
		{
			s_sync = new object();
			s_activeLogstreams = new List<LogStream>();
			AssimpLibrary.Instance.LibraryFreed += AssimpLibraryFreed;
		}

		protected LogStream()
			: this("")
		{
		}

		protected LogStream(string userData)
		{
			Initialize(null, userData);
		}

		public LogStream(LoggingCallback callback)
		{
			Initialize(callback, string.Empty);
		}

		public LogStream(LoggingCallback callback, string userData)
		{
			Initialize(callback, userData);
		}

		~LogStream()
		{
			Dispose(disposing: false);
		}

		public static void DetachAllLogstreams()
		{
			lock (s_sync)
			{
				foreach (LogStream s_activeLogstream in s_activeLogstreams)
				{
					s_activeLogstream.m_isAttached = false;
					AssimpLibrary.Instance.DetachLogStream(s_activeLogstream.m_logstreamPtr);
					s_activeLogstream.OnDetach();
				}
				s_activeLogstreams.Clear();
			}
		}

		public static IEnumerable<LogStream> GetAttachedLogStreams()
		{
			lock (s_sync)
			{
				return s_activeLogstreams.ToArray();
			}
		}

		private static void AssimpLibraryFreed(object sender, EventArgs e)
		{
			DetachAllLogstreams();
		}

		public void Attach()
		{
			if (m_isAttached)
			{
				return;
			}
			lock (s_sync)
			{
				s_activeLogstreams.Add(this);
				m_isAttached = true;
				AssimpLibrary.Instance.AttachLogStream(m_logstreamPtr);
				OnAttach();
			}
		}

		public void Detach()
		{
			if (!m_isAttached)
			{
				return;
			}
			lock (s_sync)
			{
				s_activeLogstreams.Remove(this);
				m_isAttached = false;
				AssimpLibrary.Instance.DetachLogStream(m_logstreamPtr);
				OnDetach();
			}
		}

		public void Log(string msg)
		{
			if (m_isAttached && !string.IsNullOrEmpty(msg))
			{
				OnAiLogStreamCallback(msg, IntPtr.Zero);
			}
		}

		public void Dispose()
		{
			Dispose(disposing: true);
			GC.SuppressFinalize(this);
		}

		protected virtual void Dispose(bool disposing)
		{
			if (!m_isDisposed)
			{
				if (m_logstreamPtr != IntPtr.Zero)
				{
					MemoryHelper.FreeMemory(m_logstreamPtr);
					m_logstreamPtr = IntPtr.Zero;
				}
				if (disposing)
				{
					m_assimpCallback = null;
				}
				m_isDisposed = true;
			}
		}

		protected virtual void LogMessage(string msg, string userData)
		{
		}

		protected virtual void OnAttach()
		{
		}

		protected virtual void OnDetach()
		{
		}

		private void OnAiLogStreamCallback(string msg, IntPtr userData)
		{
			if (m_logCallback != null)
			{
				m_logCallback(msg, m_userData);
			}
			else
			{
				LogMessage(msg, m_userData);
			}
		}

		private void Initialize(LoggingCallback callback, string userData)
		{
			if (userData == null)
			{
				userData = string.Empty;
			}
			m_assimpCallback = OnAiLogStreamCallback;
			m_logCallback = callback;
			m_userData = userData;
			AiLogStream aiLogStream = default(AiLogStream);
			aiLogStream.Callback = Marshal.GetFunctionPointerForDelegate((Delegate)m_assimpCallback);
			aiLogStream.UserData = IntPtr.Zero;
			m_logstreamPtr = MemoryHelper.AllocateMemory(MemoryHelper.SizeOf<AiLogStream>());
			Marshal.StructureToPtr((object)aiLogStream, m_logstreamPtr, fDeleteOld: false);
		}
	}
	public sealed class ConsoleLogStream : LogStream
	{
		public ConsoleLogStream()
		{
		}

		public ConsoleLogStream(string userData)
			: base(userData)
		{
		}

		protected override void LogMessage(string msg, string userData)
		{
			if (string.IsNullOrEmpty(userData))
			{
				Console.WriteLine(msg);
			}
			else
			{
				Console.WriteLine($"{userData}: {msg}");
			}
		}
	}
	public sealed class Material : IMarshalable<Material, AiMaterial>
	{
		public sealed class PBRMaterialProperties
		{
			private Material m_parent;

			public bool HasTextureBaseColor => m_parent.HasProperty("$tex.file", TextureType.BaseColor, 0);

			public TextureSlot TextureBaseColor
			{
				get
				{
					m_parent.GetMaterialTexture(TextureType.BaseColor, 0, out var texture);
					return texture;
				}
				set
				{
					if (value.TextureIndex == 0 && value.TextureType == TextureType.BaseColor)
					{
						m_parent.AddMaterialTexture(in value);
					}
				}
			}

			public bool HasTextureNormalCamera => m_parent.HasProperty("$tex.file", TextureType.NormalCamera, 0);

			public TextureSlot TextureNormalCamera
			{
				get
				{
					m_parent.GetMaterialTexture(TextureType.NormalCamera, 0, out var texture);
					return texture;
				}
				set
				{
					if (value.TextureIndex == 0 && value.TextureType == TextureType.NormalCamera)
					{
						m_parent.AddMaterialTexture(in value);
					}
				}
			}

			public bool HasTextureEmissionColor => m_parent.HasProperty("$tex.file", TextureType.EmissionColor, 0);

			public TextureSlot TextureEmissionColor
			{
				get
				{
					m_parent.GetMaterialTexture(TextureType.EmissionColor, 0, out var texture);
					return texture;
				}
				set
				{
					if (value.TextureIndex == 0 && value.TextureType == TextureType.EmissionColor)
					{
						m_parent.AddMaterialTexture(in value);
					}
				}
			}

			public bool HasTextureMetalness => m_parent.HasProperty("$tex.file", TextureType.Metalness, 0);

			public TextureSlot TextureMetalness
			{
				get
				{
					m_parent.GetMaterialTexture(TextureType.Metalness, 0, out var texture);
					return texture;
				}
				set
				{
					if (value.TextureIndex == 0 && value.TextureType == TextureType.Metalness)
					{
						m_parent.AddMaterialTexture(in value);
					}
				}
			}

			public bool HasTextureRoughness => m_parent.HasProperty("$tex.file", TextureType.Roughness, 0);

			public TextureSlot TextureRoughness
			{
				get
				{
					m_parent.GetMaterialTexture(TextureType.Roughness, 0, out var texture);
					return texture;
				}
				set
				{
					if (value.TextureIndex == 0 && value.TextureType == TextureType.Roughness)
					{
						m_parent.AddMaterialTexture(in value);
					}
				}
			}

			internal PBRMaterialProperties(Material parent)
			{
				m_parent = parent;
			}
		}

		public sealed class ShaderMaterialProperties
		{
			private Material m_parent;

			public bool HasShaderLanguageType => m_parent.HasProperty("?sh.lang,0,0");

			public string ShaderLanguageType
			{
				get
				{
					return GetStringProperty("?sh.lang,0,0");
				}
				set
				{
					SetStringProperty("?sh.lang,0,0", "?sh.lang", value);
				}
			}

			public bool HasVertexShader => m_parent.HasProperty("?sh.vs,0,0");

			public string VertexShader
			{
				get
				{
					return GetStringProperty("?sh.vs,0,0");
				}
				set
				{
					SetStringProperty("?sh.vs,0,0", "?sh.vs", value);
				}
			}

			public bool HasFragmentShader => m_parent.HasProperty("?sh.fs,0,0");

			public string FragmentShader
			{
				get
				{
					return GetStringProperty("?sh.fs,0,0");
				}
				set
				{
					SetStringProperty("?sh.fs,0,0", "?sh.fs", value);
				}
			}

			public bool HasGeometryShader => m_parent.HasProperty("?sh.gs,0,0");

			public string GeometryShader
			{
				get
				{
					return GetStringProperty("?sh.gs,0,0");
				}
				set
				{
					SetStringProperty("?sh.gs,0,0", "?sh.gs", value);
				}
			}

			public bool HasTesselationShader => m_parent.HasProperty("?sh.ts,0,0");

			public string TesselationShader
			{
				get
				{
					return GetStringProperty("?sh.ts,0,0");
				}
				set
				{
					SetStringProperty("?sh.ts,0,0", "?sh.ts", value);
				}
			}

			public bool HasPrimitiveShader => m_parent.HasProperty("?sh.ps,0,0");

			public string PrimitiveShader
			{
				get
				{
					return GetStringProperty("?sh.ps,0,0");
				}
				set
				{
					SetStringProperty("?sh.ps,0,0", "?sh.ps", value);
				}
			}

			public bool HasComputeShader => m_parent.HasProperty("?sh.cs,0,0");

			public string ComputeShader
			{
				get
				{
					return GetStringProperty("?sh.cs,0,0");
				}
				set
				{
					SetStringProperty("?sh.cs,0,0", "?sh.cs", value);
				}
			}

			internal ShaderMaterialProperties(Material parent)
			{
				m_parent = parent;
			}

			private string GetStringProperty(string fullName)
			{
				MaterialProperty property = m_parent.GetProperty(fullName);
				if (property != null)
				{
					return property.GetStringValue();
				}
				return string.Empty;
			}

			private void SetStringProperty(string fullName, string baseName, string value)
			{
				if (string.IsNullOrEmpty(value))
				{
					value = string.Empty;
				}
				MaterialProperty property = m_parent.GetProperty(fullName);
				if (property == null)
				{
					property = new MaterialProperty(baseName, value);
					m_parent.AddProperty(property);
				}
				else
				{
					property.SetStringValue(value);
				}
			}
		}

		private Dictionary<string, MaterialProperty> m_properties;

		private PBRMaterialProperties m_pbrProperties;

		private ShaderMaterialProperties m_shaderProperties;

		public int PropertyCount => m_properties.Count;

		public bool HasName => HasProperty("?mat.name,0,0");

		public string Name
		{
			get
			{
				MaterialProperty property = GetProperty("?mat.name,0,0");
				if (property != null)
				{
					return property.GetStringValue();
				}
				return string.Empty;
			}
			set
			{
				MaterialProperty property = GetProperty("?mat.name,0,0");
				if (property == null)
				{
					property = new MaterialProperty("?mat.name", value);
					AddProperty(property);
				}
				else
				{
					property.SetStringValue(value);
				}
			}
		}

		public bool HasTwoSided => HasProperty("$mat.twosided,0,0");

		public bool IsTwoSided
		{
			get
			{
				return GetProperty("$mat.twosided,0,0")?.GetBooleanValue() ?? false;
			}
			set
			{
				MaterialProperty property = GetProperty("$mat.twosided,0,0");
				if (property == null)
				{
					property = new MaterialProperty("$mat.twosided", value);
					AddProperty(property);
				}
				else
				{
					property.SetBooleanValue(value);
				}
			}
		}

		public bool HasShadingMode => HasProperty("$mat.shadingm,0,0");

		public ShadingMode ShadingMode
		{
			get
			{
				return (ShadingMode)(GetProperty("$mat.shadingm,0,0")?.GetIntegerValue() ?? 0);
			}
			set
			{
				MaterialProperty property = GetProperty("$mat.shadingm,0,0");
				if (property == null)
				{
					property = new MaterialProperty("$mat.shadingm", (int)value);
					AddProperty(property);
				}
				else
				{
					property.SetIntegerValue((int)value);
				}
			}
		}

		public bool HasWireFrame => HasProperty("$mat.wireframe,0,0");

		public bool IsWireFrameEnabled
		{
			get
			{
				return GetProperty("$mat.wireframe,0,0")?.GetBooleanValue() ?? false;
			}
			set
			{
				MaterialProperty property = GetProperty("$mat.wireframe,0,0");
				if (property == null)
				{
					property = new MaterialProperty("$mat.wireframe", value);
					AddProperty(property);
				}
				else
				{
					property.SetBooleanValue(value);
				}
			}
		}

		public bool HasBlendMode => HasProperty("$mat.blend,0,0");

		public BlendMode BlendMode
		{
			get
			{
				return (BlendMode)(GetProperty("$mat.blend,0,0")?.GetIntegerValue() ?? 0);
			}
			set
			{
				MaterialProperty property = GetProperty("$mat.blend,0,0");
				if (property == null)
				{
					property = new MaterialProperty("$mat.blend", (int)value);
					AddProperty(property);
				}
				else
				{
					property.SetIntegerValue((int)value);
				}
			}
		}

		public bool HasOpacity => HasProperty("$mat.opacity,0,0");

		public float Opacity
		{
			get
			{
				return GetProperty("$mat.opacity,0,0")?.GetFloatValue() ?? 1f;
			}
			set
			{
				MaterialProperty property = GetProperty("$mat.opacity,0,0");
				if (property == null)
				{
					property = new MaterialProperty("$mat.opacity", value);
					AddProperty(property);
				}
				else
				{
					property.SetFloatValue(value);
				}
			}
		}

		public bool HasTransparencyFactor => HasProperty("$mat.transparencyfactor,0,0");

		public float TransparencyFactor
		{
			get
			{
				return GetProperty("$mat.transparencyfactor,0,0")?.GetFloatValue() ?? 0f;
			}
			set
			{
				MaterialProperty property = GetProperty("$mat.transparencyfactor,0,0");
				if (property == null)
				{
					property = new MaterialProperty("$mat.transparencyfactor", value);
					AddProperty(property);
				}
				else
				{
					property.SetFloatValue(value);
				}
			}
		}

		public bool HasBumpScaling => HasProperty("$mat.bumpscaling,0,0");

		public float BumpScaling
		{
			get
			{
				return GetProperty("$mat.bumpscaling,0,0")?.GetFloatValue() ?? 0f;
			}
			set
			{
				MaterialProperty property = GetProperty("$mat.bumpscaling,0,0");
				if (property == null)
				{
					property = new MaterialProperty("$mat.bumpscaling", value);
					AddProperty(property);
				}
				else
				{
					property.SetFloatValue(value);
				}
			}
		}

		public bool HasShininess => HasProperty("$mat.shininess,0,0");

		public float Shininess
		{
			get
			{
				return GetProperty("$mat.shininess,0,0")?.GetFloatValue() ?? 0f;
			}
			set
			{
				MaterialProperty property = GetProperty("$mat.shininess,0,0");
				if (property == null)
				{
					property = new MaterialProperty("$mat.shininess", value);
					AddProperty(property);
				}
				else
				{
					property.SetFloatValue(value);
				}
			}
		}

		public bool HasShininessStrength => HasProperty("$mat.shinpercent,0,0");

		public float ShininessStrength
		{
			get
			{
				return GetProperty("$mat.shinpercent,0,0")?.GetFloatValue() ?? 1f;
			}
			set
			{
				MaterialProperty property = GetProperty("$mat.shinpercent,0,0");
				if (property == null)
				{
					property = new MaterialProperty("$mat.shinpercent", value);
					AddProperty(property);
				}
				else
				{
					property.SetFloatValue(value);
				}
			}
		}

		public bool HasReflectivity => HasProperty("$mat.reflectivity,0,0");

		public float Reflectivity
		{
			get
			{
				return GetProperty("$mat.reflectivity,0,0")?.GetFloatValue() ?? 0f;
			}
			set
			{
				MaterialProperty property = GetProperty("$mat.reflectivity,0,0");
				if (property == null)
				{
					property = new MaterialProperty("$mat.reflectivity", value);
					AddProperty(property);
				}
				else
				{
					property.SetFloatValue(value);
				}
			}
		}

		public bool HasColorDiffuse => HasProperty("$clr.diffuse,0,0");

		public Color4D ColorDiffuse
		{
			get
			{
				return GetProperty("$clr.diffuse,0,0")?.GetColor4DValue() ?? new Color4D(1f, 1f, 1f, 1f);
			}
			set
			{
				MaterialProperty property = GetProperty("$clr.diffuse,0,0");
				if (property == null)
				{
					property = new MaterialProperty("$clr.diffuse", value);
					AddProperty(property);
				}
				else
				{
					property.SetColor4DValue(value);
				}
			}
		}

		public bool HasColorAmbient => HasProperty("$clr.ambient,0,0");

		public Color4D ColorAmbient
		{
			get
			{
				return GetProperty("$clr.ambient,0,0")?.GetColor4DValue() ?? new Color4D(0.2f, 0.2f, 0.2f, 1f);
			}
			set
			{
				MaterialProperty property = GetProperty("$clr.ambient,0,0");
				if (property == null)
				{
					property = new MaterialProperty("$clr.ambient", value);
					AddProperty(property);
				}
				else
				{
					property.SetColor4DValue(value);
				}
			}
		}

		public bool HasColorSpecular => HasProperty("$clr.specular,0,0");

		public Color4D ColorSpecular
		{
			get
			{
				return GetProperty("$clr.specular,0,0")?.GetColor4DValue() ?? new Color4D(0f, 0f, 0f, 1f);
			}
			set
			{
				MaterialProperty property = GetProperty("$clr.specular,0,0");
				if (property == null)
				{
					property = new MaterialProperty("$clr.specular", value);
					AddProperty(property);
				}
				else
				{
					property.SetColor4DValue(value);
				}
			}
		}

		public bool HasColorEmissive => HasProperty("$clr.emissive,0,0");

		public Color4D ColorEmissive
		{
			get
			{
				return GetProperty("$clr.emissive,0,0")?.GetColor4DValue() ?? new Color4D(0f, 0f, 0f, 1f);
			}
			set
			{
				MaterialProperty property = GetProperty("$clr.emissive,0,0");
				if (property == null)
				{
					property = new MaterialProperty("$clr.emissive", value);
					AddProperty(property);
				}
				else
				{
					property.SetColor4DValue(value);
				}
			}
		}

		public bool HasColorTransparent => HasProperty("$clr.transparent,0,0");

		public Color4D ColorTransparent
		{
			get
			{
				return GetProperty("$clr.transparent,0,0")?.GetColor4DValue() ?? new Color4D(0f, 0f, 0f, 1f);
			}
			set
			{
				MaterialProperty property = GetProperty("$clr.transparent,0,0");
				if (property == null)
				{
					property = new MaterialProperty("$clr.transparent", value);
					AddProperty(property);
				}
				else
				{
					property.SetColor4DValue(value);
				}
			}
		}

		public bool HasColorReflective => HasProperty("$clr.reflective,0,0");

		public Color4D ColorReflective
		{
			get
			{
				return GetProperty("$clr.reflective,0,0")?.GetColor4DValue() ?? new Color4D(0f, 0f, 0f, 1f);
			}
			set
			{
				MaterialProperty property = GetProperty("$clr.reflective,0,0");
				if (property == null)
				{
					property = new MaterialProperty("$clr.reflective", value);
					AddProperty(property);
				}
				else
				{
					property.SetColor4DValue(value);
				}
			}
		}

		public bool HasTextureDiffuse => HasProperty("$tex.file", TextureType.Diffuse, 0);

		public TextureSlot TextureDiffuse
		{
			get
			{
				GetMaterialTexture(TextureType.Diffuse, 0, out var texture);
				return texture;
			}
			set
			{
				if (value.TextureIndex == 0 && value.TextureType == TextureType.Diffuse)
				{
					AddMaterialTexture(in value);
				}
			}
		}

		public bool HasTextureSpecular => HasProperty("$tex.file", TextureType.Specular, 0);

		public TextureSlot TextureSpecular
		{
			get
			{
				GetMaterialTexture(TextureType.Specular, 0, out var texture);
				return texture;
			}
			set
			{
				if (value.TextureIndex == 0 && value.TextureType == TextureType.Specular)
				{
					AddMaterialTexture(in value);
				}
			}
		}

		public bool HasTextureAmbient => HasProperty("$tex.file", TextureType.Ambient, 0);

		public TextureSlot TextureAmbient
		{
			get
			{
				GetMaterialTexture(TextureType.Ambient, 0, out var texture);
				return texture;
			}
			set
			{
				if (value.TextureIndex == 0 && value.TextureType == TextureType.Ambient)
				{
					AddMaterialTexture(in value);
				}
			}
		}

		public bool HasTextureEmissive => HasProperty("$tex.file", TextureType.Emissive, 0);

		public TextureSlot TextureEmissive
		{
			get
			{
				GetMaterialTexture(TextureType.Emissive, 0, out var texture);
				return texture;
			}
			set
			{
				if (value.TextureIndex == 0 && value.TextureType == TextureType.Emissive)
				{
					AddMaterialTexture(in value);
				}
			}
		}

		public bool HasTextureHeight => HasProperty("$tex.file", TextureType.Height, 0);

		public TextureSlot TextureHeight
		{
			get
			{
				GetMaterialTexture(TextureType.Height, 0, out var texture);
				return texture;
			}
			set
			{
				if (value.TextureIndex == 0 && value.TextureType == TextureType.Height)
				{
					AddMaterialTexture(in value);
				}
			}
		}

		public bool HasTextureNormal => HasProperty("$tex.file", TextureType.Normals, 0);

		public TextureSlot TextureNormal
		{
			get
			{
				GetMaterialTexture(TextureType.Normals, 0, out var texture);
				return texture;
			}
			set
			{
				if (value.TextureIndex == 0 && value.TextureType == TextureType.Normals)
				{
					AddMaterialTexture(in value);
				}
			}
		}

		public bool HasTextureOpacity => HasProperty("$tex.file", TextureType.Opacity, 0);

		public TextureSlot TextureOpacity
		{
			get
			{
				GetMaterialTexture(TextureType.Opacity, 0, out var texture);
				return texture;
			}
			set
			{
				if (value.TextureIndex == 0 && value.TextureType == TextureType.Opacity)
				{
					AddMaterialTexture(in value);
				}
			}
		}

		public bool HasTextureDisplacement => HasProperty("$tex.file", TextureType.Displacement, 0);

		public TextureSlot TextureDisplacement
		{
			get
			{
				GetMaterialTexture(TextureType.Displacement, 0, out var texture);
				return texture;
			}
			set
			{
				if (value.TextureIndex == 0 && value.TextureType == TextureType.Displacement)
				{
					AddMaterialTexture(in value);
				}
			}
		}

		public bool HasTextureLightMap => HasProperty("$tex.file", TextureType.Lightmap, 0);

		public TextureSlot TextureLightMap
		{
			get
			{
				GetMaterialTexture(TextureType.Lightmap, 0, out var texture);
				return texture;
			}
			set
			{
				if (value.TextureIndex == 0 && value.TextureType == TextureType.Lightmap)
				{
					AddMaterialTexture(in value);
				}
			}
		}

		public bool HasTextureAmbientOcclusion => HasProperty("$tex.file", TextureType.AmbientOcclusion, 0);

		public TextureSlot TextureAmbientOcclusion
		{
			get
			{
				GetMaterialTexture(TextureType.AmbientOcclusion, 0, out var texture);
				return texture;
			}
			set
			{
				if (value.TextureIndex == 0 && value.TextureType == TextureType.AmbientOcclusion)
				{
					AddMaterialTexture(in value);
				}
			}
		}

		public bool HasTextureReflection => HasProperty("$tex.file", TextureType.Reflection, 0);

		public TextureSlot TextureReflection
		{
			get
			{
				GetMaterialTexture(TextureType.Reflection, 0, out var texture);
				return texture;
			}
			set
			{
				if (value.TextureIndex == 0 && value.TextureType == TextureType.Reflection)
				{
					AddMaterialTexture(in value);
				}
			}
		}

		public bool IsPBRMaterial
		{
			get
			{
				PBRMaterialProperties pbrProperties = m_pbrProperties;
				return pbrProperties.HasTextureBaseColor || pbrProperties.HasTextureMetalness || pbrProperties.HasTextureRoughness || pbrProperties.HasTextureNormalCamera || pbrProperties.HasTextureEmissionColor;
			}
		}

		public PBRMaterialProperties PBR => m_pbrProperties;

		public bool HasShaders
		{
			get
			{
				ShaderMaterialProperties shaderProperties = m_shaderProperties;
				return shaderProperties.HasShaderLanguageType && (shaderProperties.HasVertexShader || shaderProperties.HasFragmentShader || shaderProperties.HasGeometryShader || shaderProperties.HasTesselationShader || shaderProperties.HasPrimitiveShader || shaderProperties.HasComputeShader);
			}
		}

		public ShaderMaterialProperties Shaders => m_shaderProperties;

		bool IMarshalable<Material, AiMaterial>.IsNativeBlittable => true;

		public Material()
		{
			m_properties = new Dictionary<string, MaterialProperty>();
			m_pbrProperties = new PBRMaterialProperties(this);
			m_shaderProperties = new ShaderMaterialProperties(this);
		}

		public static string CreateFullyQualifiedName(string baseName, TextureType texType, int texIndex)
		{
			if (string.IsNullOrEmpty(baseName))
			{
				return string.Empty;
			}
			return $"{baseName},{(int)texType},{texIndex}";
		}

		public MaterialProperty GetNonTextureProperty(string baseName)
		{
			if (string.IsNullOrEmpty(baseName))
			{
				return null;
			}
			string fullyQualifiedName = CreateFullyQualifiedName(baseName, TextureType.None, 0);
			return GetProperty(fullyQualifiedName);
		}

		public MaterialProperty GetProperty(string baseName, TextureType texType, int texIndex)
		{
			if (string.IsNullOrEmpty(baseName))
			{
				return null;
			}
			string fullyQualifiedName = CreateFullyQualifiedName(baseName, texType, texIndex);
			return GetProperty(fullyQualifiedName);
		}

		public MaterialProperty GetProperty(string fullyQualifiedName)
		{
			if (string.IsNullOrEmpty(fullyQualifiedName))
			{
				return null;
			}
			if (!m_properties.TryGetValue(fullyQualifiedName, out var value))
			{
				return null;
			}
			return value;
		}

		public bool HasNonTextureProperty(string baseName)
		{
			if (string.IsNullOrEmpty(baseName))
			{
				return false;
			}
			string fullyQualifiedName = CreateFullyQualifiedName(baseName, TextureType.None, 0);
			return HasProperty(fullyQualifiedName);
		}

		public bool HasProperty(string baseName, TextureType texType, int texIndex)
		{
			if (string.IsNullOrEmpty(baseName))
			{
				return false;
			}
			string fullyQualifiedName = CreateFullyQualifiedName(baseName, texType, texIndex);
			return HasProperty(fullyQualifiedName);
		}

		public bool HasProperty(string fullyQualifiedName)
		{
			if (string.IsNullOrEmpty(fullyQualifiedName))
			{
				return false;
			}
			return m_properties.ContainsKey(fullyQualifiedName);
		}

		public bool AddProperty(MaterialProperty matProp)
		{
			if (matProp == null || string.IsNullOrEmpty(matProp.FullyQualifiedName))
			{
				return false;
			}
			if (m_properties.ContainsKey(matProp.FullyQualifiedName))
			{
				return false;
			}
			m_properties.Add(matProp.FullyQualifiedName, matProp);
			return true;
		}

		public bool RemoveNonTextureProperty(string baseName)
		{
			if (string.IsNullOrEmpty(baseName))
			{
				return false;
			}
			return RemoveProperty(CreateFullyQualifiedName(baseName, TextureType.None, 0));
		}

		public bool RemoveProperty(string baseName, TextureType texType, int texIndex)
		{
			if (string.IsNullOrEmpty(baseName))
			{
				return false;
			}
			return RemoveProperty(CreateFullyQualifiedName(baseName, texType, texIndex));
		}

		public bool RemoveProperty(string fullyQualifiedName)
		{
			if (string.IsNullOrEmpty(fullyQualifiedName))
			{
				return false;
			}
			return m_properties.Remove(fullyQualifiedName);
		}

		public void Clear()
		{
			m_properties.Clear();
		}

		public MaterialProperty[] GetAllProperties()
		{
			MaterialProperty[] array = new MaterialProperty[m_properties.Values.Count];
			m_properties.Values.CopyTo(array, 0);
			return array;
		}

		public int GetMaterialTextureCount(TextureType texType)
		{
			int num = 0;
			foreach (KeyValuePair<string, MaterialProperty> property in m_properties)
			{
				MaterialProperty value = property.Value;
				if (value.Name.StartsWith("$tex.file") && value.TextureType == texType)
				{
					num++;
				}
			}
			return num;
		}

		public bool AddMaterialTexture(in TextureSlot texture)
		{
			return AddMaterialTexture(in texture, onlySetFilePath: false);
		}

		public bool AddMaterialTexture(in TextureSlot texture, bool onlySetFilePath)
		{
			if (string.IsNullOrEmpty(texture.FilePath))
			{
				return false;
			}
			TextureType textureType = texture.TextureType;
			int textureIndex = texture.TextureIndex;
			string fullyQualifiedName = CreateFullyQualifiedName("$tex.file", textureType, textureIndex);
			MaterialProperty property = GetProperty(fullyQualifiedName);
			if (property == null)
			{
				AddProperty(new MaterialProperty("$tex.file", texture.FilePath, textureType, textureIndex));
			}
			else
			{
				property.SetStringValue(texture.FilePath);
			}
			if (onlySetFilePath)
			{
				return true;
			}
			string fullyQualifiedName2 = CreateFullyQualifiedName("$tex.mapping", textureType, textureIndex);
			string fullyQualifiedName3 = CreateFullyQualifiedName("$tex.uvwsrc", textureType, textureIndex);
			string fullyQualifiedName4 = CreateFullyQualifiedName("$tex.blend", textureType, textureIndex);
			string fullyQualifiedName5 = CreateFullyQualifiedName("$tex.op", textureType, textureIndex);
			string fullyQualifiedName6 = CreateFullyQualifiedName("$tex.mapmodeu", textureType, textureIndex);
			string fullyQualifiedName7 = CreateFullyQualifiedName("$tex.mapmodev", textureType, textureIndex);
			string fullyQualifiedName8 = CreateFullyQualifiedName("$tex.flags", textureType, textureIndex);
			MaterialProperty property2 = GetProperty(fullyQualifiedName2);
			MaterialProperty property3 = GetProperty(fullyQualifiedName3);
			MaterialProperty property4 = GetProperty(fullyQualifiedName4);
			MaterialProperty property5 = GetProperty(fullyQualifiedName5);
			MaterialProperty property6 = GetProperty(fullyQualifiedName6);
			MaterialProperty property7 = GetProperty(fullyQualifiedName7);
			MaterialProperty property8 = GetProperty(fullyQualifiedName8);
			if (property2 == null)
			{
				AddProperty(new MaterialProperty("$tex.mapping", (int)texture.Mapping));
			}
			else
			{
				property2.SetIntegerValue((int)texture.Mapping);
			}
			if (property3 == null)
			{
				AddProperty(new MaterialProperty("$tex.mapping", (int)texture.Mapping));
			}
			else
			{
				property3.SetIntegerValue(texture.UVIndex);
			}
			if (property4 == null)
			{
				AddProperty(new MaterialProperty("$tex.blend", texture.BlendFactor));
			}
			else
			{
				property4.SetFloatValue(texture.BlendFactor);
			}
			if (property5 == null)
			{
				AddProperty(new MaterialProperty("$tex.op", (int)texture.Operation));
			}
			else
			{
				property5.SetIntegerValue((int)texture.Operation);
			}
			if (property6 == null)
			{
				AddProperty(new MaterialProperty("$tex.mapmodeu", (int)texture.WrapModeU));
			}
			else
			{
				property6.SetIntegerValue((int)texture.WrapModeU);
			}
			if (property7 == null)
			{
				AddProperty(new MaterialProperty("$tex.mapmodev", (int)texture.WrapModeV));
			}
			else
			{
				property7.SetIntegerValue((int)texture.WrapModeV);
			}
			if (property8 == null)
			{
				AddProperty(new MaterialProperty("$tex.flags", texture.Flags));
			}
			else
			{
				property8.SetIntegerValue(texture.Flags)