public static alien_mtl Load(string FullFilePath)
        {
            alien_mtl    Result = new alien_mtl();
            BinaryReader Stream = new BinaryReader(File.OpenRead(FullFilePath));

            alien_mtl_header Header = Utilities.Consume <alien_mtl_header>(ref Stream);

            Result.MaterialNames = new List <string>(Header.MaterialCount);
            for (int MaterialIndex = 0; MaterialIndex < Header.MaterialCount; ++MaterialIndex)
            {
                Result.MaterialNames.Add(Utilities.ReadString(ref Stream));
            }

            Stream.BaseStream.Position = Header.FirstMaterialOffset + Marshal.SizeOf(Header.BytesRemainingAfterThis);

            Result.Header    = Header;
            Result.Materials = Utilities.ConsumeArray <alien_mtl_material>(ref Stream, Header.MaterialCount);

            Result.TextureReferenceCounts = new List <int>(Result.Header.MaterialCount);
            for (int MaterialIndex = 0; MaterialIndex < Header.MaterialCount; ++MaterialIndex)
            {
                alien_mtl_material Material = Result.Materials[MaterialIndex];

                int count = 0;
                for (int I = 0; I < Material.TextureReferences.Length; ++I)
                {
                    alien_mtl_texture_reference Pair = Material.TextureReferences[I];
                    if (Pair.TextureTableIndex == 2 || Pair.TextureTableIndex == 0)
                    {
                        count++;
                    }
                }
                Result.TextureReferenceCounts.Add(count);
            }

            return(Result);
        }
    public void LoadMaterial(int MTLIndex)
    {
        alien_mtl_material InMaterial  = Result.ModelsMTL.Materials[MTLIndex];
        int RemappedIndex              = Result.ShadersIDXRemap.Datas[InMaterial.UberShaderIndex].Index;
        alien_shader_pak_shader Shader = Result.ShadersPAK.Shaders[RemappedIndex];

        Material toReturn = new Material(UnityEngine.Shader.Find("Standard"));

        toReturn.name = Result.ModelsMTL.MaterialNames[MTLIndex];

        List <alien_slot_ids> SlotOffsets    = new List <alien_slot_ids>();
        alien_shader_category ShaderCategory = (alien_shader_category)Shader.Header2.ShaderCategory;

        switch (ShaderCategory)
        {
        case alien_shader_category.AlienShaderCategory_Particle:
            SlotOffsets.Add(alien_slot_ids.DIFFUSE_MAP);
            SlotOffsets.Add(alien_slot_ids.COLOR_RAMP_MAP);
            break;

        case alien_shader_category.AlienShaderCategory_Ribbon:
            SlotOffsets.Add(alien_slot_ids.DIFFUSE_MAP);
            SlotOffsets.Add(alien_slot_ids.SECONDARY_DIFFUSE_MAP);
            SlotOffsets.Add(alien_slot_ids.COLOR_RAMP_MAP);
            break;

        case alien_shader_category.AlienShaderCategory_Environment:
            SlotOffsets.Add(alien_slot_ids.OPACITY);
            SlotOffsets.Add(alien_slot_ids.DIFFUSE_MAP);
            SlotOffsets.Add(alien_slot_ids.SECONDARY_DIFFUSE_MAP);
            SlotOffsets.Add(alien_slot_ids.NORMAL_MAP);
            SlotOffsets.Add(alien_slot_ids.SECONDARY_NORMAL_MAP);
            SlotOffsets.Add(alien_slot_ids.SPECULAR_MAP);
            SlotOffsets.Add(alien_slot_ids.SECONDARY_SPECULAR_MAP);
            SlotOffsets.Add(alien_slot_ids.ENVIRONMENT_MAP);
            SlotOffsets.Add(alien_slot_ids.OCCLUSION);
            SlotOffsets.Add(alien_slot_ids.NONE);
            SlotOffsets.Add(alien_slot_ids.FRESNEL_LUT);
            SlotOffsets.Add(alien_slot_ids.PARALLAX_MAP);
            SlotOffsets.Add(alien_slot_ids.OPACITY_NOISE_MAP);
            SlotOffsets.Add(alien_slot_ids.NONE);
            SlotOffsets.Add(alien_slot_ids.DIRT_MAP);
            SlotOffsets.Add(alien_slot_ids.WETNESS_NOISE);
            break;

        case alien_shader_category.AlienShaderCategory_DecalEnvironment:
            SlotOffsets.Add(alien_slot_ids.NONE);
            SlotOffsets.Add(alien_slot_ids.NONE);
            SlotOffsets.Add(alien_slot_ids.NONE);
            SlotOffsets.Add(alien_slot_ids.NONE);
            SlotOffsets.Add(alien_slot_ids.DIFFUSE_MAP);
            SlotOffsets.Add(alien_slot_ids.NONE);
            SlotOffsets.Add(alien_slot_ids.NORMAL_MAP);
            SlotOffsets.Add(alien_slot_ids.NONE);
            SlotOffsets.Add(alien_slot_ids.NONE);
            SlotOffsets.Add(alien_slot_ids.NONE);
            SlotOffsets.Add(alien_slot_ids.NONE);
            SlotOffsets.Add(alien_slot_ids.NONE);
            SlotOffsets.Add(alien_slot_ids.NONE);
            SlotOffsets.Add(alien_slot_ids.NONE);
            SlotOffsets.Add(alien_slot_ids.PARALLAX_MAP);
            SlotOffsets.Add(alien_slot_ids.NONE);
            SlotOffsets.Add(alien_slot_ids.ALPHA_THRESHOLD);
            break;

        case alien_shader_category.AlienShaderCategory_Character:
            SlotOffsets.Add(alien_slot_ids.DIRT_MAP);
            SlotOffsets.Add(alien_slot_ids.OPACITY_NOISE_MAP);
            SlotOffsets.Add(alien_slot_ids.OPACITY);
            SlotOffsets.Add(alien_slot_ids.DIFFUSE_MAP);
            SlotOffsets.Add(alien_slot_ids.SECONDARY_DIFFUSE_MAP);
            SlotOffsets.Add(alien_slot_ids.NORMAL_MAP);
            SlotOffsets.Add(alien_slot_ids.SECONDARY_NORMAL_MAP);
            SlotOffsets.Add(alien_slot_ids.SPECULAR_MAP);
            SlotOffsets.Add(alien_slot_ids.SECONDARY_SPECULAR_MAP);
            SlotOffsets.Add(alien_slot_ids.ENVIRONMENT_MAP);
            SlotOffsets.Add(alien_slot_ids.OCCLUSION);
            SlotOffsets.Add(alien_slot_ids.NONE);
            SlotOffsets.Add(alien_slot_ids.IRRADIANCE_MAP);
            break;

        case alien_shader_category.AlienShaderCategory_Skin:
            SlotOffsets.Add(alien_slot_ids.CONVOLVED_DIFFUSE);
            SlotOffsets.Add(alien_slot_ids.DIFFUSE_MAP);
            SlotOffsets.Add(alien_slot_ids.SECONDARY_DIFFUSE_MAP);
            SlotOffsets.Add(alien_slot_ids.NORMAL_MAP);
            SlotOffsets.Add(alien_slot_ids.SECONDARY_NORMAL_MAP);
            SlotOffsets.Add(alien_slot_ids.WRINKLE_MASK);
            SlotOffsets.Add(alien_slot_ids.WRINKLE_NORMAL_MAP);
            SlotOffsets.Add(alien_slot_ids.SPECULAR_MAP);
            SlotOffsets.Add(alien_slot_ids.SECONDARY_SPECULAR_MAP);
            SlotOffsets.Add(alien_slot_ids.ENVIRONMENT_MAP);
            SlotOffsets.Add(alien_slot_ids.IRRADIANCE_MAP);
            SlotOffsets.Add(alien_slot_ids.DIRT_MAP);
            SlotOffsets.Add(alien_slot_ids.OPACITY_NOISE_MAP);
            break;

        case alien_shader_category.AlienShaderCategory_Hair:
            SlotOffsets.Add(alien_slot_ids.FLOW_MAP);
            SlotOffsets.Add(alien_slot_ids.DIFFUSE_MAP);
            SlotOffsets.Add(alien_slot_ids.NONE);
            SlotOffsets.Add(alien_slot_ids.IRRADIANCE_MAP);
            SlotOffsets.Add(alien_slot_ids.SPECULAR_MAP);
            SlotOffsets.Add(alien_slot_ids.NORMAL_MAP);
            break;

        case alien_shader_category.AlienShaderCategory_Eye:
            SlotOffsets.Add(alien_slot_ids.CONVOLVED_DIFFUSE);
            SlotOffsets.Add(alien_slot_ids.DIFFUSE_MAP);           //IrisMap
            SlotOffsets.Add(alien_slot_ids.SECONDARY_DIFFUSE_MAP); //VeinsMap
            SlotOffsets.Add(alien_slot_ids.SCATTER_MAP);
            SlotOffsets.Add(alien_slot_ids.NORMAL_MAP);
            SlotOffsets.Add(alien_slot_ids.ENVIRONMENT_MAP);
            SlotOffsets.Add(alien_slot_ids.IRRADIANCE_MAP);
            break;

        case alien_shader_category.AlienShaderCategory_SkinOcclusion:
            SlotOffsets.Add(alien_slot_ids.DIFFUSE_MAP);
            break;

        case alien_shader_category.AlienShaderCategory_Decal:
            SlotOffsets.Add(alien_slot_ids.DIFFUSE_MAP);
            SlotOffsets.Add(alien_slot_ids.SECONDARY_DIFFUSE_MAP);
            SlotOffsets.Add(alien_slot_ids.NORMAL_MAP);
            SlotOffsets.Add(alien_slot_ids.EMISSIVE);
            SlotOffsets.Add(alien_slot_ids.SPECULAR_MAP);
            SlotOffsets.Add(alien_slot_ids.PARALLAX_MAP);
            SlotOffsets.Add(alien_slot_ids.BURN_THROUGH);
            SlotOffsets.Add(alien_slot_ids.LIQUIFY);
            SlotOffsets.Add(alien_slot_ids.ALPHA_THRESHOLD);
            SlotOffsets.Add(alien_slot_ids.LIQUIFY2);
            SlotOffsets.Add(alien_slot_ids.ENVIRONMENT_MAP);
            SlotOffsets.Add(alien_slot_ids.COLOR_RAMP);
            break;

        case alien_shader_category.AlienShaderCategory_FogPlane:
            SlotOffsets.Add(alien_slot_ids.DIFFUSE_MAP);
            SlotOffsets.Add(alien_slot_ids.SECONDARY_DIFFUSE_MAP);
            // TODO: Should be 'DiffuseMapStatic' - but I am not using that yet.  In order to keep the light cones
            //  visually appealing and not slabs of solid white, I am using normal diffuse for now.
            SlotOffsets.Add(alien_slot_ids.DIFFUSE_MAP_STATIC);
            break;

        case alien_shader_category.AlienShaderCategory_Refraction:
            SlotOffsets.Add(alien_slot_ids.NORMAL_MAP);
            SlotOffsets.Add(alien_slot_ids.SECONDARY_NORMAL_MAP);
            SlotOffsets.Add(alien_slot_ids.ALPHA_MASK);
            SlotOffsets.Add(alien_slot_ids.FLOW_MAP);
            SlotOffsets.Add(alien_slot_ids.ALPHA_THRESHOLD);
            //Material->Material.BaseColor = { };
            break;

        case alien_shader_category.AlienShaderCategory_NonInteractiveWater:
            SlotOffsets.Add(alien_slot_ids.NORMAL_MAP);
            SlotOffsets.Add(alien_slot_ids.SECONDARY_NORMAL_MAP);
            SlotOffsets.Add(alien_slot_ids.ALPHA_MASK);
            SlotOffsets.Add(alien_slot_ids.FLOW_MAP);
            break;

        case alien_shader_category.AlienShaderCategory_LowLODCharacter:
            SlotOffsets.Add(alien_slot_ids.DIFFUSE_MAP);
            SlotOffsets.Add(alien_slot_ids.NORMAL_MAP);
            SlotOffsets.Add(alien_slot_ids.SPECULAR_MAP);
            SlotOffsets.Add(alien_slot_ids.LOW_LOD_CHARACTER_MASK);
            SlotOffsets.Add(alien_slot_ids.IRRADIANCE_MAP);
            SlotOffsets.Add(alien_slot_ids.ENVIRONMENT_MAP);
            break;

        case alien_shader_category.AlienShaderCategory_LightDecal:
            SlotOffsets.Add(alien_slot_ids.EMISSIVE);
            break;

        case alien_shader_category.AlienShaderCategory_SpaceSuitVisor:
            SlotOffsets.Add(alien_slot_ids.ENVIRONMENT_MAP);
            SlotOffsets.Add(alien_slot_ids.NORMAL_MAP);
            SlotOffsets.Add(alien_slot_ids.MASKING_MAP);
            SlotOffsets.Add(alien_slot_ids.FACE_MAP);
            SlotOffsets.Add(alien_slot_ids.NONE);
            SlotOffsets.Add(alien_slot_ids.UNSCALED_DIRT_MAP);
            SlotOffsets.Add(alien_slot_ids.DIRT_MAP);
            break;

        case alien_shader_category.AlienShaderCategory_Planet:
            SlotOffsets.Add(alien_slot_ids.ATMOSPHERE_MAP);
            SlotOffsets.Add(alien_slot_ids.DETAIL_MAP);
            SlotOffsets.Add(alien_slot_ids.NONE);
            SlotOffsets.Add(alien_slot_ids.NONE);
            SlotOffsets.Add(alien_slot_ids.NONE);
            SlotOffsets.Add(alien_slot_ids.FLOW_MAP);
            break;

        case alien_shader_category.AlienShaderCategory_LightMapEnvironment:
            SlotOffsets.Add(alien_slot_ids.LIGHT_MAP);
            SlotOffsets.Add(alien_slot_ids.NONE);
            SlotOffsets.Add(alien_slot_ids.DIRT_MAP);
            SlotOffsets.Add(alien_slot_ids.OPACITY_NOISE_MAP);
            SlotOffsets.Add(alien_slot_ids.OPACITY);
            SlotOffsets.Add(alien_slot_ids.DIFFUSE_MAP);
            SlotOffsets.Add(alien_slot_ids.SECONDARY_DIFFUSE_MAP);
            SlotOffsets.Add(alien_slot_ids.NORMAL_MAP);
            SlotOffsets.Add(alien_slot_ids.SECONDARY_NORMAL_MAP);
            SlotOffsets.Add(alien_slot_ids.SPECULAR_MAP);
            SlotOffsets.Add(alien_slot_ids.SECONDARY_SPECULAR_MAP);
            SlotOffsets.Add(alien_slot_ids.ENVIRONMENT_MAP);
            SlotOffsets.Add(alien_slot_ids.NONE);     //Occlusion?
            SlotOffsets.Add(alien_slot_ids.NONE);
            SlotOffsets.Add(alien_slot_ids.NONE);
            SlotOffsets.Add(alien_slot_ids.NONE);
            SlotOffsets.Add(alien_slot_ids.NONE);
            break;

        case alien_shader_category.AlienShaderCategory_Terrain:
            SlotOffsets.Add(alien_slot_ids.DIFFUSE_MAP);
            SlotOffsets.Add(alien_slot_ids.SECONDARY_DIFFUSE_MAP);
            SlotOffsets.Add(alien_slot_ids.NORMAL_MAP);
            SlotOffsets.Add(alien_slot_ids.SECONDARY_NORMAL_MAP);
            SlotOffsets.Add(alien_slot_ids.SPECULAR_MAP);
            SlotOffsets.Add(alien_slot_ids.SECONDARY_SPECULAR_MAP);
            SlotOffsets.Add(alien_slot_ids.NONE);
            SlotOffsets.Add(alien_slot_ids.OPACITY_NOISE_MAP);
            SlotOffsets.Add(alien_slot_ids.ENVIRONMENT_MAP);
            SlotOffsets.Add(alien_slot_ids.NONE);
            break;

        //Unsupported shader slot types - draw transparent for now
        default:
            toReturn.name  = "UNRESOLVED: " + ShaderCategory.ToString();
            toReturn.color = new Color(0, 0, 0, 0);
            toReturn.SetFloat("_Mode", 1.0f);
            toReturn.EnableKeyword("_ALPHATEST_ON");
            LoadedMaterials[MTLIndex] = toReturn;
            return;
        }

        List <Texture> availableTextures = new List <Texture>();

        for (int SlotIndex = 0; SlotIndex < Shader.Header.TextureLinkCount; ++SlotIndex)
        {
            int PairIndex = Shader.TextureLinks[SlotIndex];
            // NOTE: PairIndex == 255 means no index.
            if (PairIndex < Result.ModelsMTL.TextureReferenceCounts[MTLIndex])
            {
                alien_mtl_texture_reference Pair = InMaterial.TextureReferences[PairIndex];
                if (Pair.TextureTableIndex == 0)
                {
                    availableTextures.Add(LoadedTexturesLevel[Pair.TextureIndex].texture);
                }
                else if (Pair.TextureTableIndex == 2)
                {
                    availableTextures.Add(LoadedTexturesGlobal[Pair.TextureIndex].texture);
                }
                else
                {
                    availableTextures.Add(null);
                }
            }
            else
            {
                availableTextures.Add(null);
            }
        }

        //Apply materials
        for (int i = 0; i < SlotOffsets.Count; i++)
        {
            if (i >= availableTextures.Count)
            {
                continue;
            }
            switch (SlotOffsets[i])
            {
            case alien_slot_ids.DIFFUSE_MAP:
                toReturn.SetTexture("_MainTex", availableTextures[i]);
                break;

            case alien_slot_ids.DETAIL_MAP:
                toReturn.EnableKeyword("_DETAIL_MULX2");
                toReturn.SetTexture("_DetailMask", availableTextures[i]);
                break;

            case alien_slot_ids.EMISSIVE:
                toReturn.EnableKeyword("_EMISSION");
                toReturn.SetTexture("_EmissionMap", availableTextures[i]);
                break;

            case alien_slot_ids.PARALLAX_MAP:
                toReturn.EnableKeyword("_PARALLAXMAP");
                toReturn.SetTexture("_ParallaxMap", availableTextures[i]);
                break;

            case alien_slot_ids.OCCLUSION:
                toReturn.SetTexture("_OcclusionMap", availableTextures[i]);
                break;

            case alien_slot_ids.SPECULAR_MAP:
                toReturn.EnableKeyword("_METALLICGLOSSMAP");
                toReturn.SetTexture("_MetallicGlossMap", availableTextures[i]);     //TODO _SPECGLOSSMAP?
                toReturn.SetFloat("_Glossiness", 0.0f);
                toReturn.SetFloat("_GlossMapScale", 0.0f);
                break;

            case alien_slot_ids.NORMAL_MAP:
                toReturn.EnableKeyword("_NORMALMAP");
                toReturn.SetTexture("_BumpMap", availableTextures[i]);
                break;
            }
        }

        //Apply properties
        MaterialPropertyIndex cstIndex  = GetMaterialPropertyIndex(MTLIndex);
        BinaryReader          cstReader = new BinaryReader(new MemoryStream(Result.ModelsCST));
        int baseOffset = Result.ModelsMTL.Header.CSTOffsets[2] + (InMaterial.CSTOffsets[2] * 4);

        if (CSTIndexValid(cstIndex.DiffuseIndex, ref Shader))
        {
            Vector4 colour = LoadFromCST <Vector4>(ref cstReader, baseOffset + (Shader.CSTLinks[2][cstIndex.DiffuseIndex] * 4));
            toReturn.SetColor("_Color", colour);
            if (colour.w != 1)
            {
                toReturn.SetFloat("_Mode", 1.0f);
                toReturn.EnableKeyword("_ALPHATEST_ON");
            }
        }
        if (CSTIndexValid(cstIndex.DiffuseUVMultiplierIndex, ref Shader))
        {
            float offset = LoadFromCST <float>(ref cstReader, baseOffset + (Shader.CSTLinks[2][cstIndex.DiffuseUVMultiplierIndex] * 4));
            toReturn.SetTextureScale("_MainTex", new Vector2(offset, offset));
        }
        if (CSTIndexValid(cstIndex.DiffuseUVAdderIndex, ref Shader))
        {
            float offset = LoadFromCST <float>(ref cstReader, baseOffset + (Shader.CSTLinks[2][cstIndex.DiffuseUVAdderIndex] * 4));
            toReturn.SetTextureOffset("_MainTex", new Vector2(offset, offset));
        }
        if (CSTIndexValid(cstIndex.NormalUVMultiplierIndex, ref Shader))
        {
            float offset = LoadFromCST <float>(ref cstReader, baseOffset + (Shader.CSTLinks[2][cstIndex.NormalUVMultiplierIndex] * 4));
            toReturn.SetTextureScale("_BumpMap", new Vector2(offset, offset));
            toReturn.SetFloat("_BumpScale", offset);
        }
        if (CSTIndexValid(cstIndex.OcclusionUVMultiplierIndex, ref Shader))
        {
            float offset = LoadFromCST <float>(ref cstReader, baseOffset + (Shader.CSTLinks[2][cstIndex.OcclusionUVMultiplierIndex] * 4));
            toReturn.SetTextureScale("_OcclusionMap", new Vector2(offset, offset));
        }
        if (CSTIndexValid(cstIndex.SpecularUVMultiplierIndex, ref Shader))
        {
            float offset = LoadFromCST <float>(ref cstReader, baseOffset + (Shader.CSTLinks[2][cstIndex.SpecularUVMultiplierIndex] * 4));
            toReturn.SetTextureScale("_MetallicGlossMap", new Vector2(offset, offset));
            toReturn.SetFloat("_GlossMapScale", offset);
        }
        if (CSTIndexValid(cstIndex.SpecularFactorIndex, ref Shader))
        {
            float spec = LoadFromCST <float>(ref cstReader, baseOffset + (Shader.CSTLinks[2][cstIndex.SpecularFactorIndex] * 4));
            toReturn.SetFloat("_Glossiness", spec);
            toReturn.SetFloat("_GlossMapScale", spec);
        }
        cstReader.Close();

        LoadedMaterials[MTLIndex] = toReturn;
    }