public static Texture2D ProcessTexture(
            EmbeddedTextureData embeddedTextureData,
            string name,
            ref bool hasAlphaChannel,
            bool isNormalMap = false,
            TextureWrapMode textureWrapMode       = TextureWrapMode.Repeat,
            FilterMode textureFilterMode          = FilterMode.Bilinear,
            TextureCompression textureCompression = TextureCompression.None,
            bool checkAlphaChannel = false,
            bool generateMipMaps   = true
            )
        {
            Texture2D finalTexture2D = null;

            if (embeddedTextureData.DataPointer == IntPtr.Zero || embeddedTextureData.DataLength <= 0)
            {
#if TRILIB_OUTPUT_MESSAGES
                Debug.LogWarningFormat("Texture '{0}' not found", path);
#endif
            }
            else
            {
                Texture2D tempTexture2D;
                if (ApplyTextureData(embeddedTextureData, out tempTexture2D))
                {
                    finalTexture2D = ProcessTextureData(tempTexture2D, name, ref hasAlphaChannel, textureWrapMode, textureFilterMode, textureCompression, isNormalMap, checkAlphaChannel, generateMipMaps);
                }
#if TRILIB_OUTPUT_MESSAGES
                Debug.LogErrorFormat("Unable to load texture '{0}'", path);
#endif
            }
            embeddedTextureData.Dispose();
            return(finalTexture2D);
        }
        public static Texture2D ProcessTexture(int width,
                                               int height,
                                               string name,
                                               ref bool hasAlphaChannel,
                                               byte[] data,
                                               bool isRawData   = false,
                                               bool isNormalMap = false,
                                               TextureWrapMode textureWrapMode       = TextureWrapMode.Repeat,
                                               TextureCompression textureCompression = TextureCompression.None,
                                               bool checkAlphaChannel = false,
                                               bool generateMipMaps   = true
                                               )
        {
            if (data == null || data.Length == 0)
            {
                return(null);
            }
            Texture2D tempTexture2D;

            if (ApplyTextureData(data, isRawData, out tempTexture2D, width, height, generateMipMaps))
            {
                return(ProccessTextureData(tempTexture2D, name, ref hasAlphaChannel, textureWrapMode, textureCompression, isNormalMap, checkAlphaChannel));
            }
            return(null);
        }
Beispiel #3
0
        public static Texture2D ProcessTexture(int width,
                                               int height,
                                               string name,
                                               ref bool hasAlphaChannel,
                                               byte[] data,
                                               bool isRawData   = false,
                                               bool isNormalMap = false,
                                               TextureWrapMode textureWrapMode       = TextureWrapMode.Repeat,
                                               TextureCompression textureCompression = TextureCompression.None,
                                               bool checkAlphaChannel = false,
                                               bool generateMipMaps   = true
                                               )
        {
            if (data == null || data.Length == 0)
            {
#if TRILIB_OUTPUT_MESSAGES || ASSIMP_OUTPUT_MESSAGES
                Debug.LogWarningFormat("Texture '{0}' not found", path);
#endif
                return(null);
            }
            Texture2D tempTexture2D;
            if (ApplyTextureData(data, isRawData, out tempTexture2D, width, height, generateMipMaps))
            {
                return(ProccessTextureData(tempTexture2D, name, ref hasAlphaChannel, textureWrapMode, textureCompression, isNormalMap, checkAlphaChannel));
            }
#if TRILIB_OUTPUT_MESSAGES || ASSIMP_OUTPUT_MESSAGES
            Debug.LogErrorFormat("Unable to load texture '{0}'", path);
#endif
            return(null);
        }
 public TextureOutput(bool a, string n, TextureScale s, bool sr, TextureChannels c, TextureCompression nc, ImageFormat i)
 {
     Active      = a;
     Name        = n;
     Scale       = s;
     SRGB        = sr;
     Channels    = c;
     Compression = nc;
     ImageFormat = i;
 }
Beispiel #5
0
        public static Texture2D LoadTextureFromFile(
            string path,
            int width,
            int height,
            string name,
            ref bool checkAlphaChannel,
            byte[] data,
            bool isRawData   = false,
            bool isNormalMap = false,
            string basePath  = null,
            TextureWrapMode textureWrapMode       = TextureWrapMode.Repeat,
            TextureCompression textureCompression = TextureCompression.None
            )
        {
            var finalPath = path;

            if (data == null)
            {
                string filename = null;
                data = FileUtils.LoadFileData(finalPath);
                if (data.Length == 0 && basePath != null)
                {
                    finalPath = Path.Combine(basePath, path);
                    data      = FileUtils.LoadFileData(finalPath);
                }
                if (data.Length == 0)
                {
                    filename  = FileUtils.GetFilename(path);
                    finalPath = filename;
                    data      = FileUtils.LoadFileData(finalPath);
                }
                if (data.Length == 0 && basePath != null && filename != null)
                {
                    finalPath = Path.Combine(basePath, filename);
                    data      = FileUtils.LoadFileData(finalPath);
                }
                if (data.Length == 0)
                {
#if TRILIB_OUTPUT_MESSAGES || ASSIMP_OUTPUT_MESSAGES
                    Debug.LogWarningFormat("Texture '{0}' not found", path);
#endif
                    return(null);
                }
            }
            Texture2D tempTexture2D;
            if (ApplyTextureData(data, isRawData, out tempTexture2D, width, height))
            {
                return(ProccessTextureData(tempTexture2D, name, ref checkAlphaChannel, textureWrapMode, finalPath, textureCompression, isNormalMap));
            }
#if TRILIB_OUTPUT_MESSAGES || ASSIMP_OUTPUT_MESSAGES
            Debug.LogErrorFormat("Unable to load texture '{0}'", path);
#endif
            return(null);
        }
		/// <summary>
		/// 
		/// </summary>
		/// <param name="buildContext"></param>
		/// <param name="src"></param>
		/// <param name="dst"></param>
		/// <param name="noMips"></param>
		/// <param name="fast"></param>
		/// <param name="toNormal"></param>
		/// <param name="color"></param>
		/// <param name="alpha"></param>
		/// <param name="normal"></param>
		/// <param name="compression"></param>
		internal static void RunNVCompress( BuildContext buildContext, string src, string dst, bool noMips, bool fast, bool toNormal, bool color, bool alpha, bool normal, TextureCompression compression )
		{
			string commandLine = "";

			if ( noMips		) 	commandLine	+=	" -nomips"	;
			if ( fast		) 	commandLine	+=	" -fast"	;
			if ( toNormal	) 	commandLine	+=	" -tonormal";
			if ( color		) 	commandLine	+=	" -color"	;
			if ( alpha		) 	commandLine	+=	" -alpha"	;
			if ( normal		) 	commandLine	+=	" -normal"	;

			commandLine += ( " -" + compression.ToString().ToLower() );
			commandLine += ( " \"" + src + "\"" );
			commandLine += ( " \"" + dst + "\"" );

			buildContext.RunTool( @"nvcompress.exe", commandLine );//*/
		}
Beispiel #7
0
        /// <summary>
        /// Loads a <see cref="UnityEngine.Texture2D"/> from an external source.
        /// </summary>
        /// <param name="scene">Scene where the texture belongs.</param>
        /// <param name="path">Path to load the texture data.</param>
        /// <param name="name">Name of the <see cref="UnityEngine.Texture2D"/> to be created.</param>
        /// <param name="material"><see cref="UnityEngine.Material"/> to assign the <see cref="UnityEngine.Texture2D"/>.</param>
        /// <param name="propertyName"><see cref="UnityEngine.Material"/> property name to assign to the <see cref="UnityEngine.Texture2D"/>.</param>
        /// <param name="checkAlphaChannel">If True, checks every image pixel to determine if alpha channel is being used and sets this value.</param>
        /// <param name="textureWrapMode">Wrap mode of the <see cref="UnityEngine.Texture2D"/> to be created.</param>
        /// <param name="basePath">Base path to lookup for the <see cref="UnityEngine.Texture2D"/>.</param>
        /// <param name="onTextureLoaded">Event to trigger when the <see cref="UnityEngine.Texture2D"/> finishes loading.</param>
        /// <param name="textureCompression">Texture loading compression level.</param>
        /// <param name="textureFileNameWithoutExtension">Texture filename without the extension.</param>
        /// <param name="isNormalMap">Is the Texture a Normal Map?</param>
        /// <returns>The loaded <see cref="UnityEngine.Texture2D"/>.</returns>
        public static Texture2D LoadTextureFromFile(IntPtr scene, string path, string name, Material material, string propertyName, ref bool checkAlphaChannel, TextureWrapMode textureWrapMode = TextureWrapMode.Repeat, string basePath = null, TextureLoadHandle onTextureLoaded = null, TextureCompression textureCompression = TextureCompression.None, string textureFileNameWithoutExtension = null, bool isNormalMap = false)
        {
            if (string.IsNullOrEmpty(path))
            {
                return(null);
            }
            bool   assimpUncompressed;
            string finalPath;

            byte[] data;
            var    texture = AssimpInterop.aiScene_GetEmbeddedTexture(scene, path);

            if (texture != IntPtr.Zero)
            {
                assimpUncompressed = !AssimpInterop.aiMaterial_IsEmbeddedTextureCompressed(scene, texture);
                var dataLength = AssimpInterop.aiMaterial_GetEmbeddedTextureDataSize(scene, texture, !assimpUncompressed);
                data      = AssimpInterop.aiMaterial_GetEmbeddedTextureData(scene, texture, dataLength);
                finalPath = Path.GetFileNameWithoutExtension(path);
            }
            else
            {
                string filename = null;
                finalPath = path;
                data      = FileUtils.LoadFileData(finalPath);
                if (data.Length == 0 && basePath != null)
                {
                    finalPath = Path.Combine(basePath, path);
                }
                data = FileUtils.LoadFileData(finalPath);
                if (data.Length == 0)
                {
                    filename  = Path.GetFileName(path);
                    finalPath = filename;
                }
                data = FileUtils.LoadFileData(finalPath);
                if (data.Length == 0 && basePath != null && filename != null)
                {
                    finalPath = Path.Combine(basePath, filename);
                }
                data = FileUtils.LoadFileData(finalPath);
                if (data.Length == 0)
                {
#if ASSIMP_OUTPUT_MESSAGES
                    Debug.LogWarningFormat("Texture '{0}' not found", path);
#endif
                    return(null);
                }
                assimpUncompressed = false;
            }
            bool      loaded;
            Texture2D tempTexture2D;
            if (assimpUncompressed)
            {
                //TODO: additional DLL methods to load actual resolution
                var textureResolution = Mathf.FloorToInt(Mathf.Sqrt(data.Length / 4));
                tempTexture2D = new Texture2D(textureResolution, textureResolution, TextureFormat.ARGB32, true);
                tempTexture2D.LoadRawTextureData(data);
                tempTexture2D.Apply();
                loaded = true;
            }
            else
            {
#if USE_DEVIL && (UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN)
                loaded = IlLoader.LoadTexture2DFromByteArray(data, data.Length, out tempTexture2D);
#else
                tempTexture2D = new Texture2D(2, 2, TextureFormat.RGBA32, true);
                loaded        = tempTexture2D.LoadImage(data);
#endif
            }
            tempTexture2D.name     = name;
            tempTexture2D.wrapMode = textureWrapMode;
            if (loaded)
            {
                var colors         = tempTexture2D.GetPixels32();
                var finalTexture2D = new Texture2D(tempTexture2D.width, tempTexture2D.height, TextureFormat.ARGB32, true);
                if (isNormalMap)
                {
                    for (var i = 0; i < colors.Length; i++)
                    {
                        var color = colors[i];
                        color.a   = color.r;
                        color.r   = 0;
                        color.b   = 0;
                        colors[i] = color;
                    }
                    finalTexture2D.SetPixels32(colors);
                    finalTexture2D.Apply();
                }
                else
                {
                    finalTexture2D.SetPixels32(colors);
                    finalTexture2D.Apply();
                    if (textureCompression != TextureCompression.None)
                    {
                        tempTexture2D.Compress(textureCompression == TextureCompression.HighQuality);
                    }
                }
                if (checkAlphaChannel)
                {
                    checkAlphaChannel = false;
                    foreach (var color in colors)
                    {
                        if (color.a != 255)
                        {
                            checkAlphaChannel = true;
                            break;
                        }
                    }
                }
                if (material != null)
                {
                    material.SetTexture(propertyName, finalTexture2D);
                }
                if (onTextureLoaded != null)
                {
                    onTextureLoaded(finalPath, material, propertyName, finalTexture2D);
                }
                return(finalTexture2D);
            }
            else
            {
#if ASSIMP_OUTPUT_MESSAGES
                Debug.LogErrorFormat("Unable to load texture '{0}'", path);
#endif
            }
            return(null);
        }
        public static string Replace(this Texture2D t2d, Image image, PropertyCollection props, string fileSourcePath = null, string forcedTFCName = null)
        {
            string      errors       = "";
            var         textureCache = forcedTFCName ?? t2d.GetTopMip().TextureCacheName;
            string      fmt          = t2d.TextureFormat;
            PixelFormat pixelFormat  = Image.getPixelFormatType(fmt);

            t2d.RemoveEmptyMipsFromMipList();

            // Not sure what this does?
            // Remove all but one mip?
            //if (Export.Game == MEGame.ME1 && texture.mipMapsList.Count < 6)
            //{
            //    for (int i = texture.mipMapsList.Count - 1; i != 0; i--)
            //        texture.mipMapsList.RemoveAt(i);
            //}
            PixelFormat newPixelFormat = pixelFormat;

            //Changing Texture Type. Not sure what this is, exactly.
            //if (mod.markConvert)
            //    newPixelFormat = changeTextureType(pixelFormat, image.pixelFormat, ref package, ref texture);


            if (!image.checkDDSHaveAllMipmaps() || t2d.Mips.Count > 1 && image.mipMaps.Count() <= 1 || image.pixelFormat != newPixelFormat)
            //(!mod.markConvert && image.pixelFormat != pixelFormat))
            {
                bool dxt1HasAlpha  = false;
                byte dxt1Threshold = 128;
                if (pixelFormat == PixelFormat.DXT1 && props.GetProp <EnumProperty>("CompressionSettings") is EnumProperty compressionSettings && compressionSettings.Value.Name == "TC_OneBitAlpha")
                {
                    dxt1HasAlpha = true;
                    if (image.pixelFormat == PixelFormat.ARGB ||
                        image.pixelFormat == PixelFormat.DXT3 ||
                        image.pixelFormat == PixelFormat.DXT5)
                    {
                        errors += "Warning: Texture was converted from full alpha to binary alpha." + Environment.NewLine;
                    }
                }

                //Generate lower mips
                image.correctMips(newPixelFormat, dxt1HasAlpha, dxt1Threshold);
            }

            if (t2d.Mips.Count == 1)
            {
                var topMip = image.mipMaps[0];
                image.mipMaps.Clear();
                image.mipMaps.Add(topMip);
            }
            else
            {
                // remove lower mipmaps from source image which not exist in game data
                //Not sure what this does since we just generated most of these mips
                for (int t = 0; t < image.mipMaps.Count(); t++)
                {
                    if (image.mipMaps[t].origWidth <= t2d.Mips[0].width &&
                        image.mipMaps[t].origHeight <= t2d.Mips[0].height &&
                        t2d.Mips.Count > 1)
                    {
                        if (!t2d.Mips.Exists(m => m.width == image.mipMaps[t].origWidth && m.height == image.mipMaps[t].origHeight))
                        {
                            image.mipMaps.RemoveAt(t--);
                        }
                    }
                }

                // put empty mips if missing
                for (int t = 0; t < t2d.Mips.Count; t++)
                {
                    if (t2d.Mips[t].width <= image.mipMaps[0].origWidth &&
                        t2d.Mips[t].height <= image.mipMaps[0].origHeight)
                    {
                        if (!image.mipMaps.Exists(m => m.origWidth == t2d.Mips[t].width && m.origHeight == t2d.Mips[t].height))
                        {
                            MipMap mipmap = new MipMap(t2d.Mips[t].width, t2d.Mips[t].height, pixelFormat);
                            image.mipMaps.Add(mipmap);
                        }
                    }
                }
            }

            //if (!texture.properties.exists("LODGroup"))
            //    texture.properties.setByteValue("LODGroup", "TEXTUREGROUP_Character", "TextureGroup", 1025);
            List <byte[]> compressedMips = new List <byte[]>();

            for (int m = 0; m < image.mipMaps.Count(); m++)
            {
                if (t2d.Export.Game == MEGame.ME2)
                {
                    compressedMips.Add(TextureCompression.CompressTexture(image.mipMaps[m].data, StorageTypes.extLZO)); //LZO
                }
                else
                {
                    compressedMips.Add(TextureCompression.CompressTexture(image.mipMaps[m].data, StorageTypes.extZlib)); //ZLib
                }
            }

            List <Texture2DMipInfo> mipmaps = new List <Texture2DMipInfo>();

            for (int m = 0; m < image.mipMaps.Count(); m++)
            {
                Texture2DMipInfo mipmap = new Texture2DMipInfo();
                mipmap.Export           = t2d.Export;
                mipmap.width            = image.mipMaps[m].origWidth;
                mipmap.height           = image.mipMaps[m].origHeight;
                mipmap.TextureCacheName = textureCache;
                if (t2d.Mips.Exists(x => x.width == mipmap.width && x.height == mipmap.height))
                {
                    var oldMip = t2d.Mips.First(x => x.width == mipmap.width && x.height == mipmap.height);
                    mipmap.storageType = oldMip.storageType;
                }
                else
                {
                    mipmap.storageType = t2d.Mips[0].storageType;
                    if (t2d.Mips.Count() > 1)
                    {
                        //Will implement later. ME3Explorer won't support global relinking, that's MEM's job.
                        //if (Export.Game == MEGame.ME1 && matched.linkToMaster == -1)
                        //{
                        //    if (mipmap.storageType == StorageTypes.pccUnc)
                        //    {
                        //        mipmap.storageType = StorageTypes.pccLZO;
                        //    }
                        //}
                        //else if (Export.Game == MEGame.ME1 && matched.linkToMaster != -1)
                        //{
                        //    if (mipmap.storageType == StorageTypes.pccUnc ||
                        //        mipmap.storageType == StorageTypes.pccLZO ||
                        //        mipmap.storageType == StorageTypes.pccZlib)
                        //    {
                        //        mipmap.storageType = StorageTypes.extLZO;
                        //    }
                        //}
                        //else
                    }
                }

                //ME2,ME3: Force compression type (not implemented yet)
                if (t2d.Export.Game == MEGame.ME3)
                {
                    if (mipmap.storageType == StorageTypes.extLZO) //ME3 LZO -> ZLIB
                    {
                        mipmap.storageType = StorageTypes.extZlib;
                    }
                    if (mipmap.storageType == StorageTypes.pccLZO) //ME3 PCC LZO -> PCCZLIB
                    {
                        mipmap.storageType = StorageTypes.pccZlib;
                    }
                    if (mipmap.storageType == StorageTypes.extUnc) //ME3 Uncomp -> ZLib
                    {
                        mipmap.storageType = StorageTypes.extZlib;
                    }
                    //Leave here for future. WE might need this after dealing with double compression
                    //if (mipmap.storageType == StorageTypes.pccUnc && mipmap.width > 32) //ME3 Uncomp -> ZLib
                    //    mipmap.storageType = StorageTypes.pccZlib;
                    if (mipmap.storageType == StorageTypes.pccUnc && m < image.mipMaps.Count() - 6 && textureCache != null) //Moving texture to store externally.
                    {
                        mipmap.storageType = StorageTypes.extZlib;
                    }
                }
                else if (t2d.Export.Game == MEGame.ME2)
                {
                    if (mipmap.storageType == StorageTypes.extZlib) //ME2 ZLib -> LZO
                    {
                        mipmap.storageType = StorageTypes.extLZO;
                    }
                    if (mipmap.storageType == StorageTypes.pccZlib) //M2 ZLib -> LZO
                    {
                        mipmap.storageType = StorageTypes.pccLZO;
                    }
                    if (mipmap.storageType == StorageTypes.extUnc) //ME2 Uncomp -> LZO
                    {
                        mipmap.storageType = StorageTypes.extLZO;
                    }
                    //Leave here for future. We might neable this after dealing with double compression
                    //if (mipmap.storageType == StorageTypes.pccUnc && mipmap.width > 32) //ME2 Uncomp -> LZO
                    //    mipmap.storageType = StorageTypes.pccLZO;
                    if (mipmap.storageType == StorageTypes.pccUnc && m < image.mipMaps.Count() - 6 && textureCache != null) //Moving texture to store externally. make sure bottom 6 are pcc stored
                    {
                        mipmap.storageType = StorageTypes.extLZO;
                    }
                }


                //Investigate. this has something to do with archive storage types
                //if (mod.arcTexture != null)
                //{
                //    if (mod.arcTexture[m].storageType != mipmap.storageType)
                //    {
                //        mod.arcTexture = null;
                //    }
                //}

                mipmap.width  = image.mipMaps[m].width;
                mipmap.height = image.mipMaps[m].height;
                mipmaps.Add(mipmap);
                if (t2d.Mips.Count() == 1)
                {
                    break;
                }
            }

            #region MEM code comments. Should probably leave for reference

            //if (texture.properties.exists("TextureFileCacheName"))
            //{
            //    string archive = texture.properties.getProperty("TextureFileCacheName").valueName;
            //    if (mod.arcTfcDLC && mod.arcTfcName != archive)
            //        mod.arcTexture = null;

            //    if (mod.arcTexture == null)
            //    {
            //        archiveFile = Path.Combine(GameData.MainData, archive + ".tfc");
            //        if (matched.path.ToLowerInvariant().Contains("\\dlc"))
            //        {
            //            mod.arcTfcDLC = true;
            //            string DLCArchiveFile = Path.Combine(Path.GetDirectoryName(GameData.GamePath + matched.path), archive + ".tfc");
            //            if (File.Exists(DLCArchiveFile))
            //                archiveFile = DLCArchiveFile;
            //            else if (!File.Exists(archiveFile))
            //            {
            //                List<string> files = Directory.GetFiles(GameData.bioGamePath, archive + ".tfc",
            //                    SearchOption.AllDirectories).Where(item => item.EndsWith(".tfc", StringComparison.OrdinalIgnoreCase)).ToList();
            //                if (files.Count == 1)
            //                    archiveFile = files[0];
            //                else if (files.Count == 0)
            //                {
            //                    using (FileStream fs = new FileStream(DLCArchiveFile, FileMode.CreateNew, FileAccess.Write))
            //                    {
            //                        fs.WriteFromBuffer(texture.properties.getProperty("TFCFileGuid").valueStruct);
            //                    }
            //                    archiveFile = DLCArchiveFile;
            //                    newTfcFile = true;
            //                }
            //                else
            //                    throw new Exception("More instnces of TFC file: " + archive + ".tfc");
            //            }
            //        }
            //        else
            //        {
            //            mod.arcTfcDLC = false;
            //        }

            //        // check if texture fit in old space
            //        for (int mip = 0; mip < image.mipMaps.Count(); mip++)
            //        {
            //            Texture.MipMap testMipmap = new Texture.MipMap();
            //            testMipmap.width = image.mipMaps[mip].origWidth;
            //            testMipmap.height = image.mipMaps[mip].origHeight;
            //            if (ExistMipmap(testMipmap.width, testMipmap.height))
            //                testMipmap.storageType = texture.getMipmap(testMipmap.width, testMipmap.height).storageType;
            //            else
            //            {
            //                oldSpace = false;
            //                break;
            //            }

            //            if (testMipmap.storageType == StorageTypes.extZlib ||
            //                testMipmap.storageType == StorageTypes.extLZO)
            //            {
            //                Texture.MipMap oldTestMipmap = texture.getMipmap(testMipmap.width, testMipmap.height);
            //                if (mod.cacheCprMipmaps[mip].Length > oldTestMipmap.compressedSize)
            //                {
            //                    oldSpace = false;
            //                    break;
            //                }
            //            }
            //            if (texture.mipMapsList.Count() == 1)
            //                break;
            //        }

            //        long fileLength = new FileInfo(archiveFile).Length;
            //        if (!oldSpace && fileLength + 0x5000000 > 0x80000000)
            //        {
            //            archiveFile = "";
            //            foreach (TFCTexture newGuid in guids)
            //            {
            //                archiveFile = Path.Combine(GameData.MainData, newGuid.name + ".tfc");
            //                if (!File.Exists(archiveFile))
            //                {
            //                    texture.properties.setNameValue("TextureFileCacheName", newGuid.name);
            //                    texture.properties.setStructValue("TFCFileGuid", "Guid", newGuid.guid);
            //                    using (FileStream fs = new FileStream(archiveFile, FileMode.CreateNew, FileAccess.Write))
            //                    {
            //                        fs.WriteFromBuffer(newGuid.guid);
            //                    }
            //                    newTfcFile = true;
            //                    break;
            //                }
            //                else
            //                {
            //                    fileLength = new FileInfo(archiveFile).Length;
            //                    if (fileLength + 0x5000000 < 0x80000000)
            //                    {
            //                        texture.properties.setNameValue("TextureFileCacheName", newGuid.name);
            //                        texture.properties.setStructValue("TFCFileGuid", "Guid", newGuid.guid);
            //                        break;
            //                    }
            //                }
            //                archiveFile = "";
            //            }
            //            if (archiveFile == "")
            //                throw new Exception("No free TFC texture file!");
            //        }
            //    }
            //    else
            //    {
            //        texture.properties.setNameValue("TextureFileCacheName", mod.arcTfcName);
            //        texture.properties.setStructValue("TFCFileGuid", "Guid", mod.arcTfcGuid);
            //    }
            //}

            #endregion

            int allextmipssize = 0;

            for (int m = 0; m < image.mipMaps.Count(); m++)
            {
                Texture2DMipInfo x = mipmaps[m];
                var compsize       = image.mipMaps[m].data.Length;

                if (x.storageType == StorageTypes.extZlib ||
                    x.storageType == StorageTypes.extLZO ||
                    x.storageType == StorageTypes.extUnc)
                {
                    allextmipssize += compsize; //compsize on Unc textures is same as LZO/ZLib
                }
            }
            //todo: check to make sure TFC will not be larger than 2GiB
            Guid tfcGuid       = Guid.NewGuid(); //make new guid as storage
            bool locallyStored = mipmaps[0].storageType == StorageTypes.pccUnc || mipmaps[0].storageType == StorageTypes.pccZlib || mipmaps[0].storageType == StorageTypes.pccLZO;
            for (int m = 0; m < image.mipMaps.Count(); m++)
            {
                Texture2DMipInfo mipmap = mipmaps[m];
                //if (mipmap.width > 32)
                //{
                //    if (mipmap.storageType == StorageTypes.pccUnc)
                //    {
                //        mipmap.storageType = Export.Game == MEGame.ME2 ? StorageTypes.pccLZO : StorageTypes.pccZlib;
                //    }
                //    if (mipmap.storageType == StorageTypes.extUnc)
                //    {
                //        mipmap.storageType = Export.Game == MEGame.ME2 ? StorageTypes.extLZO : StorageTypes.extZlib;
                //    }
                //}

                mipmap.uncompressedSize = image.mipMaps[m].data.Length;
                if (t2d.Export.Game == MEGame.ME1)
                {
                    if (mipmap.storageType == StorageTypes.pccLZO ||
                        mipmap.storageType == StorageTypes.pccZlib)
                    {
                        mipmap.Mip            = compressedMips[m];
                        mipmap.compressedSize = mipmap.Mip.Length;
                    }
                    else if (mipmap.storageType == StorageTypes.pccUnc)
                    {
                        mipmap.compressedSize = mipmap.uncompressedSize;
                        mipmap.Mip            = image.mipMaps[m].data;
                    }
                    else
                    {
                        throw new Exception("Unknown mip storage type!");
                    }
                }
                else
                {
                    if (mipmap.storageType == StorageTypes.extZlib ||
                        mipmap.storageType == StorageTypes.extLZO)
                    {
                        if (compressedMips.Count != image.mipMaps.Count())
                        {
                            throw new Exception("Amount of compressed mips does not match number of mips of incoming image!");
                        }
                        mipmap.Mip            = compressedMips[m];
                        mipmap.compressedSize = mipmap.Mip.Length;
                    }


                    if (mipmap.storageType == StorageTypes.pccUnc ||
                        mipmap.storageType == StorageTypes.extUnc)
                    {
                        mipmap.compressedSize = mipmap.uncompressedSize;
                        mipmap.Mip            = image.mipMaps[m].data;
                    }

                    if (mipmap.storageType == StorageTypes.pccLZO || mipmap.storageType == StorageTypes.pccZlib)
                    {
                        mipmap.Mip            = compressedMips[m];
                        mipmap.compressedSize = mipmap.Mip.Length;
                    }

                    if (mipmap.storageType == StorageTypes.extZlib ||
                        mipmap.storageType == StorageTypes.extLZO ||
                        mipmap.storageType == StorageTypes.extUnc)
                    {
                        if (!string.IsNullOrEmpty(mipmap.TextureCacheName) && mipmap.Export.Game != MEGame.ME1)
                        {
                            //Check local dir
                            string tfcarchive            = mipmap.TextureCacheName + ".tfc";
                            var    localDirectoryTFCPath = Path.Combine(Path.GetDirectoryName(mipmap.Export.FileRef.FilePath), tfcarchive);
                            if (File.Exists(localDirectoryTFCPath))
                            {
                                try
                                {
                                    using (FileStream fs = new FileStream(localDirectoryTFCPath, FileMode.Open, FileAccess.ReadWrite))
                                    {
                                        tfcGuid = fs.ReadGuid();
                                        fs.Seek(0, SeekOrigin.End);
                                        mipmap.externalOffset = (int)fs.Position;
                                        fs.Write(mipmap.Mip, 0, mipmap.compressedSize);
                                    }
                                }
                                catch (Exception e)
                                {
                                    throw new Exception("Problem appending to TFC file " + tfcarchive + ": " + e.Message);
                                }
                                continue;
                            }

                            //Check game
                            var gameFiles = MELoadedFiles.GetFilesLoadedInGame(mipmap.Export.Game, includeTFCs: true);
                            if (gameFiles.TryGetValue(tfcarchive, out string archiveFile))
                            {
                                try
                                {
                                    using (FileStream fs = new FileStream(archiveFile, FileMode.Open, FileAccess.ReadWrite))
                                    {
                                        tfcGuid = fs.ReadGuid();
                                        fs.Seek(0, SeekOrigin.End);
                                        mipmap.externalOffset = (int)fs.Position;
                                        fs.Write(mipmap.Mip, 0, mipmap.compressedSize);
                                    }
                                }
                                catch (Exception e)
                                {
                                    throw new Exception("Problem appending to TFC file " + archiveFile + ": " + e.Message);
                                }
                                continue;
                            }


                            //Cache not found. Make new TFC
                            try
                            {
                                using (FileStream fs = new FileStream(localDirectoryTFCPath, FileMode.OpenOrCreate, FileAccess.Write))
                                {
                                    fs.WriteGuid(tfcGuid);
                                    mipmap.externalOffset = (int)fs.Position;
                                    fs.Write(mipmap.Mip, 0, mipmap.compressedSize);
                                }
                            }
                            catch (Exception e)
                            {
                                throw new Exception("Problem creating new TFC file " + tfcarchive + ": " + e.Message);
                            }
                            continue;
                        }
                    }
                }
                mipmaps[m] = mipmap;
                if (t2d.Mips.Count() == 1)
                {
                    break;
                }
            }

            t2d.ReplaceMips(mipmaps);

            //Set properties


            // The bottom 6 mips are apparently always pcc stored. If there is less than 6 mips, set neverstream to true, which tells game
            // and toolset to never look into archives for mips.
            //if (Export.Game == MEGame.ME2 || Export.Game == MEGame.ME3)
            //{
            //    if (texture.properties.exists("TextureFileCacheName"))
            //    {
            //        if (texture.mipMapsList.Count < 6)
            //        {
            //            mipmap.storageType = StorageTypes.pccUnc;
            //            texture.properties.setBoolValue("NeverStream", true);
            //        }
            //        else
            //        {
            //            if (Export.Game == MEGame.ME2)
            //                mipmap.storageType = StorageTypes.extLZO;
            //            else
            //                mipmap.storageType = StorageTypes.extZlib;
            //        }
            //    }
            //}

            var hasNeverStream = props.GetProp <BoolProperty>("NeverStream") != null;
            if (locallyStored)
            {
                // Rules for default neverstream
                // 1. Must be Package Stored
                // 2. Must have at least 6 not empty mips
                if (mipmaps.Count >= 6)
                {
                    props.AddOrReplaceProp(new BoolProperty(true, "NeverStream"));
                }
                // Side case: NeverStream property was already set, we should respect the value
                // But won't that always be set here?
                // Is there a time where we should remove NeverStream? I can't see any logical way
                // neverstream would be here
            }

            if (mipmaps.Count < 6)
            {
                props.RemoveNamedProperty("NeverStream");
            }

            if (!locallyStored)
            {
                props.AddOrReplaceProp(tfcGuid.ToGuidStructProp("TFCFileGuid"));
                if (mipmaps[0].storageType == StorageTypes.extLZO || mipmaps[0].storageType == StorageTypes.extUnc || mipmaps[0].storageType == StorageTypes.extZlib)
                {
                    //Requires texture cache name
                    props.AddOrReplaceProp(new NameProperty(textureCache, "TextureFileCacheName"));
                }
                else
                {
                    //Should not have texture cache name
                    var cacheProp = props.GetProp <NameProperty>("TextureFileCacheName");
                    if (cacheProp != null)
                    {
                        props.Remove(cacheProp);
                    }
                }
            }
            else
            {
                props.RemoveNamedProperty("TFCFileGuid");
            }

            props.AddOrReplaceProp(new IntProperty(t2d.Mips.First().width, "SizeX"));
            props.AddOrReplaceProp(new IntProperty(t2d.Mips.First().height, "SizeY"));
            if (t2d.Export.Game < MEGame.ME3 && fileSourcePath != null)
            {
                props.AddOrReplaceProp(new StrProperty(fileSourcePath, "SourceFilePath"));
                props.AddOrReplaceProp(new StrProperty(File.GetLastWriteTimeUtc(fileSourcePath).ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture), "SourceFileTimestamp"));
            }

            var mipTailIdx = props.GetProp <IntProperty>("MipTailBaseIdx");
            if (mipTailIdx != null)
            {
                mipTailIdx.Value = t2d.Mips.Count - 1;
            }

            EndianReader mem = new EndianReader(new MemoryStream())
            {
                Endian = t2d.Export.FileRef.Endian
            };
            props.WriteTo(mem.Writer, t2d.Export.FileRef);
            mem.Position = 0;
            var test      = PropertyCollection.ReadProps(t2d.Export, mem.BaseStream, "Texture2D", true, true); //do not set properties as this may interfere with some other code. may change later.
            int propStart = t2d.Export.GetPropertyStart();
            var pos       = mem.Position;
            mem.Position = 0;
            byte[] propData = mem.ToArray();
            if (t2d.Export.Game == MEGame.ME3)
            {
                t2d.Export.Data = t2d.Export.Data.Take(propStart).Concat(propData).Concat(t2d.SerializeNewData()).ToArray();
            }
            else
            {
                var array    = t2d.Export.Data.Take(propStart).Concat(propData).ToArray();
                var testdata = new MemoryStream(array);
                var test2    = PropertyCollection.ReadProps(t2d.Export, testdata, "Texture2D", true, true, t2d.Export); //do not set properties as this may interfere with some other code. may change later.
                                                                                                                        //ME2 post-data is this right?
                t2d.Export.Data = t2d.Export.Data.Take(propStart).Concat(propData).Concat(t2d.SerializeNewData()).ToArray();
            }

            //using (MemoryStream newData = new MemoryStream())
            //{
            //    newData.WriteFromBuffer(texture.properties.toArray());
            //    newData.WriteFromBuffer(texture.toArray(0, false)); // filled later
            //    package.setExportData(matched.exportID, newData.ToArray());
            //}

            //using (MemoryStream newData = new MemoryStream())
            //{
            //    newData.WriteFromBuffer(texture.properties.toArray());
            //    newData.WriteFromBuffer(texture.toArray(package.exportsTable[matched.exportID].dataOffset + (uint)newData.Position));
            //    package.setExportData(matched.exportID, newData.ToArray());
            //}

            //Since this is single replacement, we don't want to relink to master
            //We want to ensure names are different though, will have to implement into UI
            //if (Export.Game == MEGame.ME1)
            //{
            //    if (matched.linkToMaster == -1)
            //        mod.masterTextures.Add(texture.mipMapsList, entryMap.listIndex);
            //}
            //else
            //{
            //    if (triggerCacheArc)
            //    {
            //        mod.arcTexture = texture.mipMapsList;
            //        mod.arcTfcGuid = texture.properties.getProperty("TFCFileGuid").valueStruct;
            //        mod.arcTfcName = texture.properties.getProperty("TextureFileCacheName").valueName;
            //    }
            //}


            return(errors);
        }
Beispiel #9
0
        /// <summary>
        /// Loads a <see cref="UnityEngine.Texture2D"/> from a local source.
        /// </summary>
        /// <param name="scene">Scene where the texture belongs.</param>
        /// <param name="path">Path to load the texture data.</param>
        /// <param name="name">Name of the <see cref="UnityEngine.Texture2D"/> to be created.</param>
        /// <param name="material"><see cref="UnityEngine.Material"/> to assign the <see cref="UnityEngine.Texture2D"/>.</param>
        /// <param name="propertyName"><see cref="UnityEngine.Material"/> property name to assign to the <see cref="UnityEngine.Texture2D"/>.</param>
        /// <param name="checkAlphaChannel">If True, checks every image pixel to determine if alpha channel is being used and sets this value.</param>
        /// <param name="textureWrapMode">Wrap mode of the <see cref="UnityEngine.Texture2D"/> to be created.</param>
        /// <param name="basePath">Base path to lookup for the <see cref="UnityEngine.Texture2D"/>.</param>
        /// <param name="onTextureLoaded">Event to trigger when the <see cref="UnityEngine.Texture2D"/> finishes loading.</param>
        /// <param name="textureCompression">Texture loading compression level.</param>
        /// <param name="textureFileNameWithoutExtension">Texture filename without the extension.</param>
        /// <param name="isNormalMap">Is the Texture a Normal Map?</param>
        /// <returns>The loaded <see cref="UnityEngine.Texture2D"/>.</returns>
        public static Texture2D LoadTextureFromFile(IntPtr scene, string path, string name, Material material, string propertyName, ref bool checkAlphaChannel, TextureWrapMode textureWrapMode = TextureWrapMode.Repeat, string basePath = null, TextureLoadHandle onTextureLoaded = null, TextureCompression textureCompression = TextureCompression.None, string textureFileNameWithoutExtension = null, bool isNormalMap = false)
        {
            if (scene == IntPtr.Zero || string.IsNullOrEmpty(path))
            {
                return(null);
            }
            string finalPath;

            byte[] data;
            bool   isRawData;
            var    width  = 0;
            var    height = 0;

            if (!LoadEmbeddedTextureData(scene, path, out finalPath, out data, out isRawData, out width, out height))
            {
                string filename = null;
                finalPath = path;
                data      = FileUtils.LoadFileData(finalPath);
                if (data.Length == 0 && basePath != null)
                {
                    finalPath = Path.Combine(basePath, path);
                    data      = FileUtils.LoadFileData(finalPath);
                }
                if (data.Length == 0)
                {
                    filename  = FileUtils.GetFilename(path);
                    finalPath = filename;
                    data      = FileUtils.LoadFileData(finalPath);
                }
                if (data.Length == 0 && basePath != null && filename != null)
                {
                    finalPath = Path.Combine(basePath, filename);
                    data      = FileUtils.LoadFileData(finalPath);
                }
                if (data.Length == 0)
                {
#if TRILIB_OUTPUT_MESSAGES || ASSIMP_OUTPUT_MESSAGES
                    Debug.LogWarningFormat("Texture '{0}' not found", path);
#endif
                    return(null);
                }
            }
            Texture2D tempTexture2D;
            if (ApplyTextureData(data, isRawData, out tempTexture2D, width, height))
            {
                return(ProccessTextureData(tempTexture2D, name, material, propertyName, ref checkAlphaChannel, textureWrapMode, finalPath, onTextureLoaded, textureCompression, isNormalMap));
            }
#if TRILIB_OUTPUT_MESSAGES || ASSIMP_OUTPUT_MESSAGES
            Debug.LogErrorFormat("Unable to load texture '{0}'", path);
#endif
            return(null);
        }
Beispiel #10
0
        /// <summary>
        /// Proccesses the texture.
        /// </summary>
        /// <returns>The texture.</returns>
        /// <param name="tempTexture2D">Temp <see cref="UnityEngine.Texture2D"/>.</param>
        /// <param name="name">Name.</param>
        /// <param name="material">Material.</param>
        /// <param name="propertyName">Property name.</param>
        /// <param name="checkAlphaChannel">Check alpha channel.</param>
        /// <param name="textureWrapMode">Texture wrap mode.</param>
        /// <param name="finalPath">Final path.</param>
        /// <param name="onTextureLoaded">On texture loaded.</param>
        /// <param name="textureCompression">Texture compression.</param>
        /// <param name="isNormalMap">If set to <c>true</c> is normal map.</param>
        public static Texture2D ProccessTextureData(Texture2D tempTexture2D, string name, Material material, string propertyName, ref bool checkAlphaChannel, TextureWrapMode textureWrapMode = TextureWrapMode.Repeat, string finalPath = null, TextureLoadHandle onTextureLoaded = null, TextureCompression textureCompression = TextureCompression.None, bool isNormalMap = false)
        {
            if (tempTexture2D == null)
            {
                return(null);
            }
            tempTexture2D.name     = name;
            tempTexture2D.wrapMode = textureWrapMode;
            var       colors = tempTexture2D.GetPixels32();
            Texture2D finalTexture2D;

            if (isNormalMap)
            {
#if UNITY_5
                finalTexture2D = new Texture2D(tempTexture2D.width, tempTexture2D.height, TextureFormat.ARGB32, true);
                for (var i = 0; i < colors.Length; i++)
                {
                    var color = colors[i];
                    color.a   = color.r;
                    color.r   = 0;
                    color.b   = 0;
                    colors[i] = color;
                }
#else
                finalTexture2D            = Texture2D.Instantiate(AssetLoader.NormalBaseTexture);
                finalTexture2D.filterMode = tempTexture2D.filterMode;
                finalTexture2D.wrapMode   = tempTexture2D.wrapMode;
                finalTexture2D.Resize(tempTexture2D.width, tempTexture2D.height);
#endif
                finalTexture2D.SetPixels32(colors);
                finalTexture2D.Apply();
            }
            else

            {
                finalTexture2D = new Texture2D(tempTexture2D.width, tempTexture2D.height, TextureFormat.ARGB32, true);
                finalTexture2D.SetPixels32(colors);
                finalTexture2D.Apply();
                if (textureCompression != TextureCompression.None)
                {
                    tempTexture2D.Compress(textureCompression == TextureCompression.HighQuality);
                }
            }
            if (checkAlphaChannel)
            {
                checkAlphaChannel = false;
                foreach (var color in colors)
                {
                    if (color.a != 255)
                    {
                        checkAlphaChannel = true;
                        break;
                    }
                }
            }
            if (material != null)
            {
                material.SetTexture(propertyName, finalTexture2D);
            }
            if (onTextureLoaded != null)
            {
                onTextureLoaded(finalPath, material, propertyName, finalTexture2D);
            }
            return(finalTexture2D);
        }
Beispiel #11
0
        public void ConvertTo(MEGame newGame)
        {
            MEGame oldGame         = Game;
            var    prePropBinary   = new List <byte[]>(ExportCount);
            var    propCollections = new List <PropertyCollection>(ExportCount);
            var    postPropBinary  = new List <ObjectBinary>(ExportCount);

            if (oldGame == MEGame.ME1 && newGame != MEGame.ME1)
            {
                int idx = names.IndexOf("BIOC_Base");
                if (idx >= 0)
                {
                    names[idx] = "SFXGame";
                }
            }
            else if (newGame == MEGame.ME1)
            {
                int idx = names.IndexOf("SFXGame");
                if (idx >= 0)
                {
                    names[idx] = "BIOC_Base";
                }
            }

            //fix up Default_ imports
            if (newGame == MEGame.ME3)
            {
                using (IMEPackage core = MEPackageHandler.OpenMEPackage(Path.Combine(ME3Directory.cookedPath, "Core.pcc")))
                    using (IMEPackage engine = MEPackageHandler.OpenMEPackage(Path.Combine(ME3Directory.cookedPath, "Engine.pcc")))
                        using (IMEPackage sfxGame = MEPackageHandler.OpenMEPackage(Path.Combine(ME3Directory.cookedPath, "SFXGame.pcc")))
                        {
                            foreach (ImportEntry defImp in imports.Where(imp => imp.ObjectName.Name.StartsWith("Default_")).ToList())
                            {
                                string     packageName = defImp.FullPath.Split('.')[0];
                                IMEPackage pck         = packageName == "Core" ? core : packageName == "Engine" ? engine : packageName == "SFXGame" ? sfxGame : null;
                                if (pck != null && pck.Exports.FirstOrDefault(exp => exp.ObjectName == defImp.ObjectName) is ExportEntry defExp)
                                {
                                    var impChildren = defImp.GetChildren();
                                    var expChildren = defExp.GetChildren();
                                    foreach (IEntry expChild in expChildren)
                                    {
                                        if (impChildren.FirstOrDefault(imp => imp.ObjectName == expChild.ObjectName) is ImportEntry matchingImp)
                                        {
                                            impChildren.Remove(matchingImp);
                                        }
                                        else
                                        {
                                            AddImport(new ImportEntry(this)
                                            {
                                                idxLink     = defImp.UIndex,
                                                ClassName   = expChild.ClassName,
                                                ObjectName  = expChild.ObjectName,
                                                PackageFile = defImp.PackageFile
                                            });
                                        }
                                    }

                                    foreach (IEntry impChild in impChildren)
                                    {
                                        EntryPruner.TrashEntries(this, impChild.GetAllDescendants().Prepend(impChild));
                                    }
                                }
                            }
                        }
            }

            //purge MaterialExpressions
            if (newGame == MEGame.ME3)
            {
                var entriesToTrash = new List <IEntry>();
                foreach (ExportEntry mat in exports.Where(exp => exp.ClassName == "Material").ToList())
                {
                    entriesToTrash.AddRange(mat.GetAllDescendants());
                }
                EntryPruner.TrashEntries(this, entriesToTrash.ToHashSet());
            }

            EntryPruner.TrashIncompatibleEntries(this, oldGame, newGame);

            foreach (ExportEntry export in exports)
            {
                //convert stack, or just get the pre-prop binary if no stack
                prePropBinary.Add(ExportBinaryConverter.ConvertPrePropBinary(export, newGame));

                if (export.ClassName == "Class")
                {
                    propCollections.Add(null);
                }
                else
                {
                    //read in all properties in the old format, and remove ones that are incompatible with newGame
                    propCollections.Add(EntryPruner.RemoveIncompatibleProperties(this, export.GetProperties(), export.ClassName, newGame));
                }

                //convert binary data
                postPropBinary.Add(ExportBinaryConverter.ConvertPostPropBinary(export, newGame));

                //writes header in whatever format is correct for newGame
                export.RegenerateHeader(newGame, true);
            }

            Game = newGame;

            for (int i = 0; i < exports.Count; i++)
            {
                var newData = new MemoryStream();
                newData.WriteFromBuffer(prePropBinary[i]);
                //write back properties in new format
                propCollections[i]?.WriteTo(newData, this);

                postPropBinary[i].WriteTo(newData, this, exports[i].DataOffset + exports[i].propsEnd()); //should do this again during Save to get offsets correct
                //might not matter though

                exports[i].Data = newData.ToArray();
            }

            if (newGame == MEGame.ME3)
            {
                //change all materials to default material, but try to preserve diff and norm textures
                using var resourcePCC = MEPackageHandler.OpenME3Package(App.CustomResourceFilePath(MEGame.ME3));
                var normDiffMat = resourcePCC.Exports.First(exp => exp.ObjectName == "NormDiffMaterial");

                foreach (ExportEntry mat in exports.Where(exp => exp.ClassName == "Material" || exp.ClassName == "MaterialInstanceConstant"))
                {
                    UIndex[] textures = Array.Empty <UIndex>();
                    if (mat.ClassName == "Material")
                    {
                        textures = ObjectBinary.From <Material>(mat).SM3MaterialResource.UniformExpressionTextures;
                    }
                    else if (mat.GetProperty <BoolProperty>("bHasStaticPermutationResource")?.Value == true)
                    {
                        textures = ObjectBinary.From <MaterialInstance>(mat).SM3StaticPermutationResource.UniformExpressionTextures;
                    }
                    else if (mat.GetProperty <ArrayProperty <StructProperty> >("TextureParameterValues") is ArrayProperty <StructProperty> texParams)
                    {
                        textures = texParams.Select(structProp => new UIndex(structProp.GetProp <ObjectProperty>("ParameterValue")?.Value ?? 0)).ToArray();
                    }
                    else if (mat.GetProperty <ObjectProperty>("Parent") is ObjectProperty parentProp && GetEntry(parentProp.Value) is ExportEntry parent && parent.ClassName == "Material")
                    {
                        textures = ObjectBinary.From <Material>(parent).SM3MaterialResource.UniformExpressionTextures;
                    }

                    EntryImporter.ReplaceExportDataWithAnother(normDiffMat, mat);
                    int norm = 0;
                    int diff = 0;
                    foreach (UIndex texture in textures)
                    {
                        if (GetEntry(texture) is IEntry tex)
                        {
                            if (diff == 0 && tex.ObjectName.Name.Contains("diff", StringComparison.OrdinalIgnoreCase))
                            {
                                diff = texture;
                            }
                            else if (norm == 0 && tex.ObjectName.Name.Contains("norm", StringComparison.OrdinalIgnoreCase))
                            {
                                norm = texture;
                            }
                        }
                    }
                    if (diff == 0)
                    {
                        diff = EntryImporter.GetOrAddCrossImportOrPackage("EngineMaterials.DefaultDiffuse", resourcePCC, this).UIndex;
                    }

                    var matBin = ObjectBinary.From <Material>(mat);
                    matBin.SM3MaterialResource.UniformExpressionTextures = new UIndex[] { norm, diff };
                    mat.setBinaryData(matBin.ToBytes(this));
                    mat.Class = imports.First(imp => imp.ObjectName == "Material");
                }
            }

            if (newGame != MEGame.ME3)
            {
                foreach (ExportEntry texport in exports.Where(exp => exp.IsTexture()))
                {
                    texport.WriteProperty(new BoolProperty(true, "NeverStream"));
                }
            }
            else if (exports.Any(exp => exp.IsTexture() && Texture2D.GetTexture2DMipInfos(exp, null)
                                 .Any(mip => mip.storageType == StorageTypes.pccLZO ||
                                      mip.storageType == StorageTypes.pccZlib)))
            {
                //ME3 can't deal with compressed textures in a pcc, so we'll need to stuff them into a tfc
                string tfcName = Path.GetFileNameWithoutExtension(FilePath);
                using var tfc = File.OpenWrite(Path.ChangeExtension(FilePath, "tfc"));
                Guid tfcGuid = Guid.NewGuid();
                tfc.WriteGuid(tfcGuid);

                foreach (ExportEntry texport in exports.Where(exp => exp.IsTexture()))
                {
                    List <Texture2DMipInfo> mips = Texture2D.GetTexture2DMipInfos(texport, null);
                    var offsets = new List <int>();
                    foreach (Texture2DMipInfo mipInfo in mips)
                    {
                        if (mipInfo.storageType == StorageTypes.pccLZO || mipInfo.storageType == StorageTypes.pccZlib)
                        {
                            offsets.Add((int)tfc.Position);
                            byte[] mip;
                            if (mipInfo.storageType == StorageTypes.pccLZO)
                            {
                                mip = TextureCompression.CompressTexture(Texture2D.GetTextureData(mipInfo), StorageTypes.extZlib);
                            }
                            else
                            {
                                mip = Texture2D.GetTextureData(mipInfo, false);
                            }
                            tfc.WriteFromBuffer(mip);
                        }
                    }
                    offsets.Add((int)tfc.Position);
                    texport.setBinaryData(ExportBinaryConverter.ConvertTexture2D(texport, Game, offsets, StorageTypes.extZlib));
                    texport.WriteProperty(new NameProperty(tfcName, "TextureFileCacheName"));
                    texport.WriteProperty(tfcGuid.ToGuidStructProp("TFCFileGuid"));
                }
            }
        }
Beispiel #12
0
        private static Texture2D ProcessTextureData(Texture2D texture2D, string name, ref bool hasAlphaChannel, TextureWrapMode textureWrapMode, FilterMode textureFilterMode, TextureCompression textureCompression, bool isNormalMap, bool checkAlphaChannel = false, bool generateMipMaps = false)
        {
            if (texture2D == null)
            {
                return(null);
            }
            if (string.IsNullOrEmpty(name))
            {
                texture2D.name = StringUtils.GenerateUniqueName(texture2D);
            }
            texture2D.name       = name;
            texture2D.wrapMode   = textureWrapMode;
            texture2D.filterMode = textureFilterMode;
            var colors = texture2D.GetPixels32();

            if (isNormalMap)
            {
                var tempTexture2D = new Texture2D(texture2D.width, texture2D.height, TextureFormat.RGBA32, generateMipMaps);
                tempTexture2D.name       = texture2D.name;
                tempTexture2D.wrapMode   = texture2D.wrapMode;
                tempTexture2D.filterMode = texture2D.filterMode;
                for (var i = 0; i < colors.Length; i++)
                {
                    var color = colors[i];
                    var r     = color.r;
                    color.r   = color.a;
                    color.a   = r;
                    colors[i] = color;
                }
                tempTexture2D.SetPixels32(colors);
                tempTexture2D.Apply(generateMipMaps);
                UnityEngine.Object.Destroy(texture2D);
                texture2D = tempTexture2D;
            }
            if (!isNormalMap && generateMipMaps)
            {
                var tempTexture2D = new Texture2D(texture2D.width, texture2D.height, TextureFormat.RGBA32, true);
                tempTexture2D.name       = texture2D.name;
                tempTexture2D.wrapMode   = texture2D.wrapMode;
                tempTexture2D.filterMode = texture2D.filterMode;
                tempTexture2D.SetPixels32(colors);
                tempTexture2D.Apply(true);
                if (Application.isPlaying)
                {
                    UnityEngine.Object.Destroy(texture2D);
                }
                else
                {
                    UnityEngine.Object.DestroyImmediate(texture2D);
                }
                texture2D = tempTexture2D;
            }
            if (textureCompression != TextureCompression.None)
            {
                texture2D.Compress(textureCompression == TextureCompression.HighQuality);
            }
            if (checkAlphaChannel)
            {
                hasAlphaChannel = false;
                foreach (var color in colors)
                {
                    if (color.a == 255)
                    {
                        continue;
                    }
                    hasAlphaChannel = true;
                    break;
                }
            }
            return(texture2D);
        }
Beispiel #13
0
        private static Texture2D ProccessTextureData(Texture2D tempTexture2D, string name, ref bool checkAlphaChannel, TextureWrapMode textureWrapMode, string finalPath, TextureCompression textureCompression, bool isNormalMap)
        {
            if (tempTexture2D == null)
            {
                return(null);
            }
            tempTexture2D.name     = name;
            tempTexture2D.wrapMode = textureWrapMode;
            var       colors = tempTexture2D.GetPixels32();
            Texture2D finalTexture2D;

            if (isNormalMap)
            {
#if UNITY_5
                finalTexture2D = new Texture2D(tempTexture2D.width, tempTexture2D.height, TextureFormat.ARGB32, true);
                for (var i = 0; i < colors.Length; i++)
                {
                    var color = colors[i];
                    color.a   = color.r;
                    color.r   = 0;
                    color.b   = 0;
                    colors[i] = color;
                }
                finalTexture2D.SetPixels32(colors);
                finalTexture2D.Apply();
#else
                finalTexture2D            = Object.Instantiate(AssetLoaderBase.NormalBaseTexture);
                finalTexture2D.filterMode = tempTexture2D.filterMode;
                finalTexture2D.wrapMode   = tempTexture2D.wrapMode;
                finalTexture2D.Resize(tempTexture2D.width, tempTexture2D.height);
                finalTexture2D.SetPixels32(colors);
                finalTexture2D.Apply();
#endif
            }
            else
            {
                finalTexture2D = new Texture2D(tempTexture2D.width, tempTexture2D.height, TextureFormat.ARGB32, true);
                finalTexture2D.SetPixels32(colors);
                finalTexture2D.Apply();
                if (textureCompression != TextureCompression.None)
                {
                    tempTexture2D.Compress(textureCompression == TextureCompression.HighQuality);
                }
            }
            if (checkAlphaChannel)
            {
                checkAlphaChannel = false;
                foreach (var color in colors)
                {
                    if (color.a == 255)
                    {
                        continue;
                    }
                    checkAlphaChannel = true;
                    break;
                }
            }
            return(finalTexture2D);
        }
Beispiel #14
0
        internal static void RunNVCompress(BuildContext buildContext, string src, string dst, bool noMips, bool fast, bool toNormal, bool color, bool alpha, bool normal, TextureCompression compression)
        {
            string commandLine = "";

            if (noMips)
            {
                commandLine += " -nomips";
            }
            if (fast)
            {
                commandLine += " -fast";
            }
            if (toNormal)
            {
                commandLine += " -tonormal";
            }
            if (color)
            {
                commandLine += " -color";
            }
            if (alpha)
            {
                commandLine += " -alpha";
            }
            if (normal)
            {
                commandLine += " -normal";
            }

            commandLine += (" -" + compression.ToString().ToLower());
            commandLine += (" \"" + src + "\"");
            commandLine += (" \"" + dst + "\"");

            buildContext.RunTool(@"nvcompress.exe", commandLine);              //*/
        }
Beispiel #15
0
        private static Texture2D ProccessTextureData(Texture2D inputTexture2D, string name, ref bool hasAlphaChannel, TextureWrapMode textureWrapMode, TextureCompression textureCompression, bool isNormalMap, bool checkAlphaChannel = false)
        {
            if (inputTexture2D == null)
            {
                return(null);
            }
            inputTexture2D.name     = name;
            inputTexture2D.wrapMode = textureWrapMode;
            if (isNormalMap)
            {
                var colors = inputTexture2D.GetPixels32();
#if UNITY_5
                Texture2D outputTexture2D = new Texture2D(inputTexture2D.width, inputTexture2D.height, TextureFormat.ARGB32, true);
                for (var i = 0; i < colors.Length; i++)
                {
                    var color = colors[i];
                    color.a   = color.r;
                    color.r   = 0;
                    color.b   = 0;
                    colors[i] = color;
                }
                outputTexture2D.SetPixels32(colors);
                outputTexture2D.Apply();
#else
                Texture2D outputTexture2D = UnityEngine.Object.Instantiate(AssetLoaderBase.NormalBaseTexture);
                outputTexture2D.filterMode = inputTexture2D.filterMode;
                outputTexture2D.wrapMode   = inputTexture2D.wrapMode;
                outputTexture2D.Resize(inputTexture2D.width, inputTexture2D.height);
                outputTexture2D.SetPixels32(colors);
                outputTexture2D.Apply();
#endif
                return(outputTexture2D);
            }
            if (textureCompression != TextureCompression.None)
            {
                inputTexture2D.Compress(textureCompression == TextureCompression.HighQuality);
            }
            if (checkAlphaChannel)
            {
                hasAlphaChannel = false;
                var colors = inputTexture2D.GetPixels32();
                foreach (var color in colors)
                {
                    if (color.a == 255)
                    {
                        continue;
                    }
                    hasAlphaChannel = true;
                    break;
                }
            }
            return(inputTexture2D);
        }
 private static Texture2D ProcessTextureData(Texture2D texture2D, string name, ref bool hasAlphaChannel, TextureWrapMode textureWrapMode, FilterMode textureFilterMode, TextureCompression textureCompression, bool isNormalMap, bool checkAlphaChannel = false, bool generateMipMaps = false)
 {
     //FIXME           //THIS WAS THE TRUE CULPRIT OF CAMERA FREEZING ON IMPORT I BET IT IS THE SETPIXELLS FUNCTION -- MAYBE THE SETTING IS NOT ACTIVATED ON TEXTURE
     if (texture2D == null)
     {
         return(null);
     }
     if (string.IsNullOrEmpty(name))
     {
         name = StringUtils.GenerateUniqueName(texture2D);
     }
     texture2D.name       = name;
     texture2D.wrapMode   = textureWrapMode;
     texture2D.filterMode = textureFilterMode;
     //   var colors = texture2D.GetPixels32();
     //if (isNormalMap)
     //{
     //    var tempTexture2D = new Texture2D(texture2D.width, texture2D.height, TextureFormat.RGBA32, generateMipMaps);
     //    tempTexture2D.name = texture2D.name;
     //    tempTexture2D.wrapMode = texture2D.wrapMode;
     //    tempTexture2D.filterMode = texture2D.filterMode;
     //    for (var i = 0; i < colors.Length; i++)
     //    {
     //        var color = colors[i];
     //        var r = color.r;
     //        color.r = color.a;
     //        color.a = r;
     //        colors[i] = color;
     //    }
     //    tempTexture2D.SetPixels32(colors);
     //    tempTexture2D.Apply(generateMipMaps);
     //    if (Application.isPlaying)
     //    {
     //        UnityEngine.Object.Destroy(texture2D);
     //    }
     //    else
     //    {
     //        UnityEngine.Object.DestroyImmediate(texture2D);
     //    }
     //    texture2D = tempTexture2D;
     //}
     //if (!isNormalMap && generateMipMaps)
     //{
     //    var tempTexture2D = new Texture2D(texture2D.width, texture2D.height, TextureFormat.RGBA32, true);
     //    tempTexture2D.name = texture2D.name;
     //    tempTexture2D.wrapMode = texture2D.wrapMode;
     //    tempTexture2D.filterMode = texture2D.filterMode;
     //    tempTexture2D.SetPixels32(colors);
     //    tempTexture2D.Apply(true);
     //    if (Application.isPlaying)
     //    {
     //        UnityEngine.Object.Destroy(texture2D);
     //    }
     //    else
     //    {
     //        UnityEngine.Object.DestroyImmediate(texture2D);
     //    }
     //    texture2D = tempTexture2D;
     //}
     //THIS DOESNT CAUSE CRASH
     if (textureCompression != TextureCompression.None)
     {
         var isPowerOfTwo = IsPowerOf2(texture2D.width) && IsPowerOf2(texture2D.height);
         if (isPowerOfTwo)
         {
             texture2D.Compress(textureCompression == TextureCompression.HighQuality);
         }
     }
     //if (checkAlphaChannel)
     //{
     //    hasAlphaChannel = false;
     //    foreach (var color in colors)
     //    {
     //        if (color.a == 255) continue;
     //        hasAlphaChannel = true;
     //        break;
     //    }
     //}
     return(texture2D);
 }
Beispiel #17
0
        /// <summary>
        /// Loads a <see cref="UnityEngine.Texture2D"/> from an external source.
        /// </summary>
        /// <param name="scene">Scene where the texture belongs.</param>
        /// <param name="path">Path to load the texture data.</param>
        /// <param name="name">Name of the <see cref="UnityEngine.Texture2D"/> to be created.</param>
        /// <param name="material"><see cref="UnityEngine.Material"/> to assign the <see cref="UnityEngine.Texture2D"/>.</param>
        /// <param name="propertyName"><see cref="UnityEngine.Material"/> property name to assign to the <see cref="UnityEngine.Texture2D"/>.</param>
        /// <param name="textureWrapMode">Wrap mode of the <see cref="UnityEngine.Texture2D"/> to be created.</param>
        /// <param name="basePath">Base path to lookup for the <see cref="UnityEngine.Texture2D"/>.</param>
        /// <param name="onTextureLoaded">Event to trigger when the <see cref="UnityEngine.Texture2D"/> finishes loading.</param>
        /// <param name="textureCompression">Texture loading compression level.</param>
        /// <param name="textureFileNameWithoutExtension">Texture filename without the extension.</param>
        public static void LoadTextureFromFile(IntPtr scene, string path, string name, Material material, string propertyName, TextureWrapMode textureWrapMode = TextureWrapMode.Repeat, string basePath = null, TextureLoadHandle onTextureLoaded = null, TextureCompression textureCompression = TextureCompression.None, string textureFileNameWithoutExtension = null)
        {
            if (string.IsNullOrEmpty(path))
            {
                return;
            }
            bool   assimpUncompressed;
            string finalPath;

            byte[] data;
            if (path[0] == '*')
            {
                UInt32 slotIndex;
                if (UInt32.TryParse(path.Substring(1), out slotIndex))
                {
                    assimpUncompressed = !AssimpInterop.aiMaterial_IsEmbeddedTextureCompressed(scene, slotIndex);
                    var dataLength = AssimpInterop.aiMaterial_GetEmbeddedTextureDataSize(scene, slotIndex, !assimpUncompressed);
                    data = AssimpInterop.aiMaterial_GetEmbeddedTextureData(scene, slotIndex, dataLength);
                }
                else
                {
#if ASSIMP_OUTPUT_MESSAGES
                    Debug.LogWarningFormat("Unable to process embedded texture '{0}'", path);
#endif
                    return;
                }
                finalPath = StringUtils.GenerateUniqueName(path);
            }
            else
            {
                finalPath = path;
                if (!File.Exists(finalPath))
                {
                    if (basePath != null)
                    {
                        finalPath = Path.Combine(basePath, path);
                    }
                }
                if (!File.Exists(finalPath))
                {
                    var filename = Path.GetFileName(path);
                    if (basePath != null)
                    {
                        finalPath = Path.Combine(basePath, filename);
                    }
                }
                if (!File.Exists(finalPath))
                {
#if ASSIMP_OUTPUT_MESSAGES
                    Debug.LogWarningFormat("Texture '{0}' not found", path);
#endif
                    return;
                }
                data = File.ReadAllBytes(finalPath);
                assimpUncompressed = false;
            }
            bool      loaded;
            Texture2D texture2D;
            if (assimpUncompressed)
            {
                //TODO: additional DLL methods to load actual resolution
                var textureResolution = Mathf.FloorToInt(Mathf.Sqrt(data.Length / 4));
                texture2D = new Texture2D(textureResolution, textureResolution, TextureFormat.ARGB32, false);
                texture2D.LoadRawTextureData(data);
                texture2D.Apply();
                loaded = true;
            }
            else
            {
#if USE_DEVIL && (UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN)
                loaded = IlLoader.LoadTexture2DFromByteArray(data, data.Length, out texture2D);
#else
                texture2D = new Texture2D(2, 2, TextureFormat.RGBA32, false);
                loaded    = texture2D.LoadImage(data);
#endif
            }
            texture2D.name     = name;
            texture2D.wrapMode = textureWrapMode;
            if (loaded)
            {
                if (textureCompression != TextureCompression.None)
                {
                    texture2D.Compress(textureCompression == TextureCompression.HighQuality);
                }
                material.SetTexture(propertyName, texture2D);
                if (onTextureLoaded != null)
                {
                    onTextureLoaded(finalPath, material, propertyName, texture2D);
                }
            }
            else
            {
#if ASSIMP_OUTPUT_MESSAGES
                Debug.LogErrorFormat("Unable to load texture '{0}'", path);
#endif
            }
        }
Beispiel #18
0
        /// <summary>
        /// Draws the chart to a texture.
        /// </summary>
        /// <param name="texture">The output texture.</param>
        /// <param name="filtering">The filtering applied to the texture when rendered.</param>
        /// <param name="compression">How much the output texture will be compressed.</param>
        public static ChartOption DrawToTexture(Texture2D texture, FilterMode filtering, TextureCompression compression)
        {
            TextureSettings settings = new TextureSettings();

            settings.filtering   = filtering;
            settings.compression = compression;

            return(new DrawToTextureOption(texture, settings));
        }
Beispiel #19
0
        public static Texture2D LoadTextureFromMemory(byte[] data, string path, ref bool checkAlphaChannel, TextureWrapMode textureWrapMode = TextureWrapMode.Repeat, TextureCompression textureCompression = TextureCompression.None, bool isNormalMap = false, bool isRawData = false, int width = 0, int height = 0)
        {
            if (data.Length == 0 || string.IsNullOrEmpty(path))
            {
                return(null);
            }
            Texture2D tempTexture2D;

            if (ApplyTextureData(data, isRawData, out tempTexture2D, width, height))
            {
                return(ProccessTextureData(tempTexture2D, StringUtils.GenerateUniqueName(path.GetHashCode()), ref checkAlphaChannel, textureWrapMode, null, textureCompression, isNormalMap));
            }
#if TRILIB_OUTPUT_MESSAGES || ASSIMP_OUTPUT_MESSAGES
            Debug.LogErrorFormat("Unable to load texture '{0}'", path);
#endif
            return(null);
        }
Beispiel #20
0
        public static byte[] GetTextureData(Texture2DMipInfo mipToLoad, GameTarget target, bool decompress = true, List <string> additionalTFCs = null)
        {
            var imagebytes = new byte[decompress ? mipToLoad.uncompressedSize : mipToLoad.compressedSize];

            //Debug.WriteLine("getting texture data for " + mipToLoad.Export.FullPath);
            if (mipToLoad.storageType == StorageTypes.pccUnc)
            {
                Buffer.BlockCopy(mipToLoad.Export.Data, mipToLoad.localExportOffset, imagebytes, 0, mipToLoad.uncompressedSize);
            }
            else if (mipToLoad.storageType == StorageTypes.pccLZO || mipToLoad.storageType == StorageTypes.pccZlib)
            {
                if (decompress)
                {
                    try
                    {
                        TextureCompression.DecompressTexture(imagebytes,
                                                             new MemoryStream(mipToLoad.Export.Data, mipToLoad.localExportOffset, mipToLoad.compressedSize),
                                                             mipToLoad.storageType, mipToLoad.uncompressedSize, mipToLoad.compressedSize);
                    }
                    catch (Exception e)
                    {
                        throw new Exception($"{e.Message}\nStorageType: {mipToLoad.storageType}\n");
                    }
                }
                else
                {
                    Buffer.BlockCopy(mipToLoad.Export.Data, mipToLoad.localExportOffset, imagebytes, 0, mipToLoad.compressedSize);
                }
            }
            else if (mipToLoad.storageType == StorageTypes.extUnc || mipToLoad.storageType == StorageTypes.extLZO || mipToLoad.storageType == StorageTypes.extZlib)
            {
                string        filename    = null;
                List <string> loadedFiles = MEDirectories.EnumerateGameFiles(target.Game, target.TargetPath);
                if (mipToLoad.Export.Game == Mod.MEGame.ME1)
                {
                    var fullPath = loadedFiles.FirstOrDefault(x => Path.GetFileName(x).Equals(mipToLoad.TextureCacheName, StringComparison.InvariantCultureIgnoreCase));

                    if (fullPath != null)
                    {
                        filename = fullPath;
                    }
                    else
                    {
                        throw new FileNotFoundException($"Externally referenced texture file not found in game: {mipToLoad.TextureCacheName}.");
                    }
                }
                else
                {
                    string archive = mipToLoad.TextureCacheName + ".tfc";

                    var localDirectoryTFCPath = Path.Combine(Path.GetDirectoryName(mipToLoad.Export.FileRef.FilePath), archive);
                    if (File.Exists(localDirectoryTFCPath))
                    {
                        filename = localDirectoryTFCPath;
                    }
                    else if (additionalTFCs != null && additionalTFCs.Any(x => Path.GetFileName(x).Equals(archive, StringComparison.InvariantCultureIgnoreCase)))
                    {
                        filename = additionalTFCs.First(x => Path.GetFileName(x).Equals(archive, StringComparison.InvariantCultureIgnoreCase));
                    }
                    else
                    {
                        var tfcs = loadedFiles.Where(x => x.EndsWith(@".tfc")).ToList();

                        var fullPath = loadedFiles.FirstOrDefault(x => Path.GetFileName(x).Equals(archive, StringComparison.InvariantCultureIgnoreCase));
                        if (fullPath != null)
                        {
                            filename = fullPath;
                        }
                        else
                        {
                            throw new FileNotFoundException($@"Externally referenced texture cache not found: {archive}.");
                        }
                    }
                }

                //exceptions above will prevent filename from being null here

                try
                {
                    using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read))
                    {
                        try
                        {
                            fs.Seek(mipToLoad.externalOffset, SeekOrigin.Begin);
                            if (mipToLoad.storageType == StorageTypes.extLZO || mipToLoad.storageType == StorageTypes.extZlib)
                            {
                                if (decompress)
                                {
                                    using (MemoryStream tmpStream = new MemoryStream(fs.ReadToBuffer(mipToLoad.compressedSize)))
                                    {
                                        try
                                        {
                                            TextureCompression.DecompressTexture(imagebytes, tmpStream, mipToLoad.storageType, mipToLoad.uncompressedSize, mipToLoad.compressedSize);
                                        }
                                        catch (Exception e)
                                        {
                                            throw new Exception(e.Message + "\n" + "File: " + filename + "\n" +
                                                                "StorageType: " + mipToLoad.storageType + "\n" +
                                                                "External file offset: " + mipToLoad.externalOffset);
                                        }
                                    }
                                }
                                else
                                {
                                    fs.Read(imagebytes, 0, mipToLoad.compressedSize);
                                }
                            }
                            else
                            {
                                fs.Read(imagebytes, 0, mipToLoad.uncompressedSize);
                            }
                        }
                        catch (Exception e)
                        {
                            throw new Exception(e.Message + "\n" + "File: " + filename + "\n" +
                                                "StorageType: " + mipToLoad.storageType + "\n" +
                                                "External file offset: " + mipToLoad.externalOffset);
                        }
                    }
                }
                catch (Exception e)
                {
                    throw new Exception(e.Message + "\n" + "File: " + filename + "\n" +
                                        "StorageType: " + mipToLoad.storageType + "\n" +
                                        "External file offset: " + mipToLoad.externalOffset);
                }
            }
            return(imagebytes);
        }
        public static void ConvertTo(this MEPackage package, MEGame newGame, string tfcPath = null, bool preserveMaterialInstances = false)
        {
            MEGame oldGame         = package.Game;
            var    prePropBinary   = new List <byte[]>(package.ExportCount);
            var    propCollections = new List <PropertyCollection>(package.ExportCount);
            var    postPropBinary  = new List <ObjectBinary>(package.ExportCount);

            if (oldGame == MEGame.ME1 && newGame != MEGame.ME1)
            {
                int idx = package.Names.IndexOf("BIOC_Base");
                if (idx >= 0)
                {
                    package.replaceName(idx, "SFXGame");
                }
            }
            else if (newGame == MEGame.ME1)
            {
                int idx = package.Names.IndexOf("SFXGame");
                if (idx >= 0)
                {
                    package.replaceName(idx, "BIOC_Base");
                }
            }

            //fix up Default_ package.Imports
            if (newGame == MEGame.ME3)
            {
                using IMEPackage core    = MEPackageHandler.OpenMEPackage(Path.Combine(ME3Directory.CookedPCPath, "Core.pcc"));
                using IMEPackage engine  = MEPackageHandler.OpenMEPackage(Path.Combine(ME3Directory.CookedPCPath, "Engine.pcc"));
                using IMEPackage sfxGame = MEPackageHandler.OpenMEPackage(Path.Combine(ME3Directory.CookedPCPath, "SFXGame.pcc"));
                foreach (ImportEntry defImp in package.Imports.Where(imp => imp.ObjectName.Name.StartsWith("Default_")).ToList())
                {
                    string     packageName = defImp.FullPath.Split('.')[0];
                    IMEPackage pck         = packageName switch
                    {
                        "Core" => core,
                        "Engine" => engine,
                        "SFXGame" => sfxGame,
                        _ => null
                    };
                    if (pck != null && pck.Exports.FirstOrDefault(exp => exp.ObjectName == defImp.ObjectName) is ExportEntry defExp)
                    {
                        List <IEntry> impChildren = defImp.GetChildren();
                        List <IEntry> expChildren = defExp.GetChildren();
                        foreach (IEntry expChild in expChildren)
                        {
                            if (impChildren.FirstOrDefault(imp => imp.ObjectName == expChild.ObjectName) is ImportEntry matchingImp)
                            {
                                impChildren.Remove(matchingImp);
                            }
                            else
                            {
                                package.AddImport(new ImportEntry(package)
                                {
                                    idxLink     = defImp.UIndex,
                                    ClassName   = expChild.ClassName,
                                    ObjectName  = expChild.ObjectName,
                                    PackageFile = defImp.PackageFile
                                });
                            }
                        }

                        foreach (IEntry impChild in impChildren)
                        {
                            EntryPruner.TrashEntries(package, impChild.GetAllDescendants().Prepend(impChild));
                        }
                    }
                }
            }

            //purge MaterialExpressions
            if (newGame == MEGame.ME3)
            {
                var entriesToTrash = new List <IEntry>();
                foreach (ExportEntry mat in package.Exports.Where(exp => exp.ClassName == "Material").ToList())
                {
                    entriesToTrash.AddRange(mat.GetAllDescendants());
                }
                EntryPruner.TrashEntries(package, entriesToTrash.ToHashSet());
            }

            EntryPruner.TrashIncompatibleEntries(package, oldGame, newGame);

            foreach (ExportEntry export in package.Exports)
            {
                //convert stack, or just get the pre-prop binary if no stack
                prePropBinary.Add(ExportBinaryConverter.ConvertPrePropBinary(export, newGame));

                PropertyCollection props = export.ClassName == "Class" ? null : EntryPruner.RemoveIncompatibleProperties(package, export.GetProperties(), export.ClassName, newGame);
                propCollections.Add(props);

                //convert binary data
                postPropBinary.Add(ExportBinaryConverter.ConvertPostPropBinary(export, newGame, props));

                //writes header in whatever format is correct for newGame
                export.RegenerateHeader(newGame, true);
            }

            package.setGame(newGame);

            for (int i = 0; i < package.Exports.Count; i++)
            {
                package.Exports[i].WritePrePropsAndPropertiesAndBinary(prePropBinary[i], propCollections[i], postPropBinary[i]);
            }

            if (newGame != MEGame.ME3)  //Fix Up Textures before Materials
            {
                foreach (ExportEntry texport in package.Exports.Where(exp => exp.IsTexture()))
                {
                    texport.WriteProperty(new BoolProperty(true, "NeverStream"));
                }
            }
            else if (package.Exports.Any(exp => exp.IsTexture() && Texture2D.GetTexture2DMipInfos(exp, null)
                                         .Any(mip => mip.storageType == StorageTypes.pccLZO ||
                                              mip.storageType == StorageTypes.pccZlib)))
            {
                //ME3 can't deal with compressed textures in a pcc, so we'll need to stuff them into a tfc
                tfcPath ??= Path.ChangeExtension(package.FilePath, "tfc");
                string tfcName = Path.GetFileNameWithoutExtension(tfcPath);
                using var tfc = new FileStream(tfcPath, FileMode.OpenOrCreate, FileAccess.ReadWrite);
                Guid tfcGuid;
                if (tfc.Length >= 16)
                {
                    tfcGuid = tfc.ReadGuid();
                    tfc.SeekEnd();
                }
                else
                {
                    tfcGuid = Guid.NewGuid();
                    tfc.WriteGuid(tfcGuid);
                }

                foreach (ExportEntry texport in package.Exports.Where(exp => exp.IsTexture()))
                {
                    List <Texture2DMipInfo> mips = Texture2D.GetTexture2DMipInfos(texport, null);
                    var offsets = new List <int>();
                    foreach (Texture2DMipInfo mipInfo in mips)
                    {
                        if (mipInfo.storageType == StorageTypes.pccLZO || mipInfo.storageType == StorageTypes.pccZlib)
                        {
                            offsets.Add((int)tfc.Position);
                            byte[] mip = mipInfo.storageType == StorageTypes.pccLZO
                                ? TextureCompression.CompressTexture(Texture2D.GetTextureData(mipInfo, texport.Game), StorageTypes.extZlib)
                                : Texture2D.GetTextureData(mipInfo, texport.Game, decompress: false);
                            tfc.WriteFromBuffer(mip);
                        }
                    }
                    offsets.Add((int)tfc.Position);
                    texport.WriteBinary(ExportBinaryConverter.ConvertTexture2D(texport, package.Game, offsets, StorageTypes.extZlib));
                    texport.WriteProperty(new NameProperty(tfcName, "TextureFileCacheName"));
                    texport.WriteProperty(tfcGuid.ToGuidStructProp("TFCFileGuid"));
                }
            }
            if (oldGame == MEGame.ME3 && newGame != MEGame.ME3)
            {
                int idx = package.Names.IndexOf("location");
                if (idx >= 0)
                {
                    package.replaceName(idx, "Location");
                }
            }
            else if (newGame == MEGame.ME3)
            {
                int idx = package.Names.IndexOf("Location");
                if (idx >= 0)
                {
                    package.replaceName(idx, "location");
                }
            }

            if (newGame == MEGame.ME3) //Special handling where materials have been ported between games.
            {
                //change all materials to default material, but try to preserve diff and norm textures
                using var resourcePCC = MEPackageHandler.OpenMEPackageFromStream(ME3ExplorerCoreUtilities.GetCustomAppResourceStream(MEGame.ME3));
                var defaultmaster = resourcePCC.Exports.First(exp => exp.ObjectName == "NormDiffMaterial");
                var materiallist  = package.Exports.Where(exp => exp.ClassName == "Material" || exp.ClassName == "MaterialInstanceConstant").ToList();
                foreach (var mat in materiallist)
                {
                    Debug.WriteLine($"Fixing up {mat.FullPath}");
                    var      masterMat        = defaultmaster;
                    var      hasDefaultMaster = true;
                    UIndex[] textures         = Array.Empty <UIndex>();
                    if (mat.ClassName == "Material")
                    {
                        textures = ObjectBinary.From <Material>(mat).SM3MaterialResource.UniformExpressionTextures;
                        switch (mat.FullPath)
                        {
                        case "BioT_Volumetric.LAG_MM_Volumetric":
                        case "BioT_Volumetric.LAG_MM_FalloffSphere":
                        case "BioT_LevelMaster.Materials.Opaque_MM":
                        case "BioT_LevelMaster.Materials.GUI_Lit_MM":
                        case "BioT_LevelMaster.Materials.Signage.MM_GUIMaster_Emissive":
                        case "BioT_LevelMaster.Materials.Signage.MM_GUIMaster_Emissive_Fallback":
                        case "BioT_LevelMaster.Materials.Opaque_Standard_MM":
                        case "BioT_LevelMaster.Tech_Inset_MM":
                        case "BioT_LevelMaster.Tech_Border_MM":
                        case "BioT_LevelMaster.Brushed_Metal":
                            masterMat        = resourcePCC.Exports.First(exp => exp.FullPath == mat.FullPath);
                            hasDefaultMaster = false;
                            break;

                        default:
                            break;
                        }
                    }
                    else if (mat.GetProperty <BoolProperty>("bHasStaticPermutationResource")?.Value == true)
                    {
                        if (mat.GetProperty <ObjectProperty>("Parent") is ObjectProperty parentProp && package.GetEntry(parentProp.Value) is IEntry parent && parent.ClassName == "Material")
                        {
                            switch (parent.FullPath)
                            {
                            case "BioT_LevelMaster.Materials.Opaque_MM":
                                masterMat        = resourcePCC.Exports.First(exp => exp.FullPath == "Materials.Opaque_MM_INST");
                                hasDefaultMaster = false;
                                break;

                            case "BIOG_APL_MASTER_MATERIAL.Placeable_MM":
                                masterMat        = resourcePCC.Exports.First(exp => exp.FullPath == "Materials.Placeable_MM_INST");
                                hasDefaultMaster = false;
                                break;

                            case "BioT_LevelMaster.Materials.Opaque_Standard_MM":
                                masterMat        = resourcePCC.Exports.First(exp => exp.FullPath == "Materials.Opaque_Standard_MM_INST");
                                hasDefaultMaster = false;
                                break;

                            default:
                                textures = ObjectBinary.From <MaterialInstance>(mat).SM3StaticPermutationResource.UniformExpressionTextures;
                                break;
                            }

                            if (!hasDefaultMaster && mat.GetProperty <ArrayProperty <StructProperty> >("TextureParameterValues") is ArrayProperty <StructProperty> texParams)
                            {
                                textures = texParams.Select(structProp => new UIndex(structProp.GetProp <ObjectProperty>("ParameterValue")?.Value ?? 0)).ToArray();
                            }
                        }
                    }
                    else if (preserveMaterialInstances)
                    {
                        continue;
                    }
                    else if (mat.GetProperty <ArrayProperty <StructProperty> >("TextureParameterValues") is ArrayProperty <StructProperty> texParams)
                    {
                        textures = texParams.Select(structProp => new UIndex(structProp.GetProp <ObjectProperty>("ParameterValue")?.Value ?? 0)).ToArray();
                    }
                    else if (mat.GetProperty <ObjectProperty>("Parent") is ObjectProperty parentProp && package.GetEntry(parentProp.Value) is ExportEntry parent && parent.ClassName == "Material")
                    {
                        textures = ObjectBinary.From <Material>(parent).SM3MaterialResource.UniformExpressionTextures;
                    }

                    if (hasDefaultMaster)
                    {
                        EntryImporter.ReplaceExportDataWithAnother(masterMat, mat);
                        int norm = 0;
                        int diff = 0;
                        foreach (UIndex texture in textures)
                        {
                            if (package.GetEntry(texture) is IEntry tex)
                            {
                                if (diff == 0 && tex.ObjectName.Name.Contains("diff", StringComparison.OrdinalIgnoreCase))
                                {
                                    diff = texture;
                                }
                                else if (norm == 0 && tex.ObjectName.Name.Contains("norm", StringComparison.OrdinalIgnoreCase))
                                {
                                    norm = texture;
                                }
                            }
                        }
                        if (diff == 0)
                        {
                            diff = EntryImporter.GetOrAddCrossImportOrPackage("EngineMaterials.DefaultDiffuse", resourcePCC, package).UIndex;
                        }

                        var matBin = ObjectBinary.From <Material>(mat);
                        matBin.SM3MaterialResource.UniformExpressionTextures = new UIndex[] { norm, diff };
                        mat.WriteBinary(matBin);
                        mat.Class = package.Imports.First(imp => imp.ObjectName == "Material");
                    }
                    else if (mat.ClassName == "Material")
                    {
                        var mmparent = EntryImporter.GetOrAddCrossImportOrPackage(masterMat.ParentFullPath, resourcePCC, package);
                        EntryImporter.ImportAndRelinkEntries(EntryImporter.PortingOption.CloneAllDependencies, masterMat, package, mmparent, true, out IEntry targetexp);
                        mat.ReplaceAllReferencesToThisOne(targetexp);
                        EntryPruner.TrashEntryAndDescendants(mat);
                    }
                    else if (mat.ClassName == "MaterialInstanceConstant")
                    {
                        try
                        {
                            var matprops        = mat.GetProperties();
                            var parentlightguid = masterMat.GetProperty <StructProperty>("ParentLightingGuid");
                            matprops.AddOrReplaceProp(parentlightguid);
                            var mguid = masterMat.GetProperty <StructProperty>("m_Guid");
                            matprops.AddOrReplaceProp(mguid);
                            var lguid = masterMat.GetProperty <StructProperty>("LightingGuid");
                            matprops.AddOrReplaceProp(lguid);
                            var    masterBin          = ObjectBinary.From <MaterialInstance>(masterMat);
                            var    matBin             = ObjectBinary.From <MaterialInstance>(mat);
                            var    staticResTextures3 = masterBin.SM3StaticPermutationResource.UniformExpressionTextures.ToList();
                            var    newtextures3       = new List <UIndex>();
                            var    staticResTextures2 = masterBin.SM2StaticPermutationResource.UniformExpressionTextures.ToList();
                            var    newtextures2       = new List <UIndex>();
                            IEntry norm = null;
                            IEntry diff = null;
                            IEntry spec = null;
                            foreach (var texref in textures)
                            {
                                IEntry texEnt  = package.GetEntry(texref);
                                string texName = texEnt?.ObjectName ?? "None";
                                if (texName.ToLowerInvariant().Contains("norm"))
                                {
                                    norm = texEnt;
                                }
                                else if (texName.ToLowerInvariant().Contains("diff"))
                                {
                                    diff = texEnt;
                                }
                                else if (texName.ToLowerInvariant().Contains("spec"))
                                {
                                    spec = texEnt;
                                }
                                else if (texName.ToLowerInvariant().Contains("msk"))
                                {
                                    spec = texEnt;
                                }
                            }

                            foreach (var texidx in staticResTextures2)
                            {
                                var    masterTxt = resourcePCC.GetEntry(texidx);
                                IEntry newTxtEnt = masterTxt;
                                switch (masterTxt?.ObjectName.Name)
                                {
                                case "DefaultDiffuse":
                                    if (diff != null)
                                    {
                                        newTxtEnt = diff;
                                    }
                                    break;

                                case "DefaultNormal":
                                    if (norm != null)
                                    {
                                        newTxtEnt = norm;
                                    }
                                    break;

                                case "Gray":      //Spec
                                    if (spec != null)
                                    {
                                        newTxtEnt = spec;
                                    }
                                    break;

                                default:
                                    break;
                                }

                                var newtexidx = package.Exports.FirstOrDefault(x => x.FullPath == newTxtEnt.FullPath)?.UIndex ?? 0;
                                if (newtexidx == 0)
                                {
                                    newtexidx = package.Imports.FirstOrDefault(x => x.FullPath == newTxtEnt.FullPath)?.UIndex ?? 0;
                                }
                                if (newTxtEnt == masterTxt && newtexidx == 0)
                                {
                                    var texparent = EntryImporter.GetOrAddCrossImportOrPackage(newTxtEnt.ParentFullPath, resourcePCC, package);
                                    EntryImporter.ImportAndRelinkEntries(EntryImporter.PortingOption.CloneAllDependencies, newTxtEnt, package, texparent, true, out IEntry newtext);
                                    newtextures2.Add(newtext?.UIndex ?? 0);
                                }
                                else
                                {
                                    newtextures2.Add(newtexidx);
                                }
                            }

                            foreach (var texidx in staticResTextures3)
                            {
                                var    masterTxt = resourcePCC.GetEntry(texidx);
                                IEntry newTxtEnt = masterTxt;
                                switch (masterTxt?.ObjectName)
                                {
                                case "DefaultDiffuse":
                                    if (diff != null)
                                    {
                                        newTxtEnt = diff;
                                    }
                                    break;

                                case "DefaultNormal":
                                    if (norm != null)
                                    {
                                        newTxtEnt = norm;
                                    }
                                    break;

                                case "Gray":      //Spec
                                    if (spec != null)
                                    {
                                        newTxtEnt = spec;
                                    }
                                    break;

                                default:
                                    break;
                                }
                                var newtexidx = package.Exports.FirstOrDefault(x => x.FullPath == newTxtEnt.FullPath)?.UIndex ?? 0;
                                if (newtexidx == 0)
                                {
                                    newtexidx = package.Imports.FirstOrDefault(x => x.FullPath == newTxtEnt.FullPath)?.UIndex ?? 0;
                                }
                                if (newTxtEnt == masterTxt && newtexidx == 0)
                                {
                                    var texparent = EntryImporter.GetOrAddCrossImportOrPackage(newTxtEnt.ParentFullPath, resourcePCC, package);
                                    EntryImporter.ImportAndRelinkEntries(EntryImporter.PortingOption.CloneAllDependencies, newTxtEnt, package, texparent, true, out IEntry newtext);
                                    newtextures3.Add(newtext?.UIndex ?? 0);
                                }
                                else
                                {
                                    newtextures3.Add(newtexidx);
                                }
                            }
                            masterBin.SM2StaticPermutationResource.UniformExpressionTextures = newtextures2.ToArray();
                            masterBin.SM3StaticPermutationResource.UniformExpressionTextures = newtextures3.ToArray();
                            mat.WritePropertiesAndBinary(matprops, masterBin);
                        }
                        catch
                        {
                            Debug.WriteLine("MaterialInstanceConversion error");
                        }
                    }
                }
            }
        }
    }
Beispiel #22
0
        public static byte[] GetTextureData(Texture2DMipInfo mipToLoad, MEGame game, string gamePathToUse = null, bool decompress = true, List <string> additionalTFCs = null)
        {
            var imagebytes = new byte[decompress ? mipToLoad.uncompressedSize : mipToLoad.compressedSize];

            //Debug.WriteLine("getting texture data for " + mipToLoad.Export.FullPath);
            if (mipToLoad.storageType == StorageTypes.pccUnc)
            {
                Buffer.BlockCopy(mipToLoad.Mip, 0, imagebytes, 0, mipToLoad.uncompressedSize);
            }
            else if (mipToLoad.storageType == StorageTypes.pccLZO || mipToLoad.storageType == StorageTypes.pccZlib)
            {
                if (decompress)
                {
                    try
                    {
                        TextureCompression.DecompressTexture(imagebytes,
                                                             new MemoryStream(mipToLoad.Mip),
                                                             mipToLoad.storageType, mipToLoad.uncompressedSize, mipToLoad.compressedSize);
                    }
                    catch (Exception e)
                    {
                        throw new Exception(GetLocalizedTextureExceptionInternalMessage(e.Message, mipToLoad.storageType.ToString()));
                    }
                }
                else
                {
                    Buffer.BlockCopy(mipToLoad.Mip, 0, imagebytes, 0, mipToLoad.compressedSize);
                }
            }
            else if (mipToLoad.storageType == StorageTypes.extUnc || mipToLoad.storageType == StorageTypes.extLZO || mipToLoad.storageType == StorageTypes.extZlib || mipToLoad.storageType == StorageTypes.extLZMA)
            {
                string        filename    = null;
                List <string> loadedFiles = MELoadedFiles.GetAllGameFiles(gamePathToUse, game, false, true);
                if (mipToLoad.Export.Game == MEGame.ME1)
                {
                    var fullPath = loadedFiles.FirstOrDefault(x => Path.GetFileName(x).Equals(mipToLoad.TextureCacheName, StringComparison.InvariantCultureIgnoreCase));

                    if (fullPath != null)
                    {
                        filename = fullPath;
                    }
                    else
                    {
                        throw new FileNotFoundException(GetLocalizedCouldNotFindME1TexturePackageMessage(mipToLoad.TextureCacheName));
                    }
                }
                else
                {
                    string archive = mipToLoad.TextureCacheName + @".tfc";

                    var localDirectoryTFCPath = Path.Combine(Path.GetDirectoryName(mipToLoad.Export.FileRef.FilePath), archive);
                    if (File.Exists(localDirectoryTFCPath))
                    {
                        filename = localDirectoryTFCPath;
                    }
                    else if (additionalTFCs != null && additionalTFCs.Any(x => Path.GetFileName(x).Equals(archive, StringComparison.InvariantCultureIgnoreCase)))
                    {
                        filename = additionalTFCs.First(x => Path.GetFileName(x).Equals(archive, StringComparison.InvariantCultureIgnoreCase));
                    }
                    else
                    {
                        var tfcs = loadedFiles.Where(x => x.EndsWith(@".tfc")).ToList();

                        var fullPath = loadedFiles.FirstOrDefault(x => Path.GetFileName(x).Equals(archive, StringComparison.InvariantCultureIgnoreCase));
                        if (fullPath != null)
                        {
                            filename = fullPath;
                        }
                        else
                        {
                            throw new FileNotFoundException(GetLocalizedCouldNotFindME2ME3TextureCacheMessage(archive));
                        }
                    }
                }

                //exceptions above will prevent filename from being null here

                try
                {
                    using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read))
                    {
                        try
                        {
                            fs.Seek(mipToLoad.externalOffset, SeekOrigin.Begin);
                            if (mipToLoad.storageType == StorageTypes.extLZO || mipToLoad.storageType == StorageTypes.extZlib)
                            {
                                if (decompress)
                                {
                                    using (MemoryStream tmpStream = fs.ReadToMemoryStream(mipToLoad.compressedSize))
                                    {
                                        try
                                        {
                                            TextureCompression.DecompressTexture(imagebytes, tmpStream, mipToLoad.storageType, mipToLoad.uncompressedSize, mipToLoad.compressedSize);
                                        }
                                        catch (Exception e)
                                        {
                                            throw new Exception(GetLocalizedTextureExceptionExternalMessage(e.Message, filename, mipToLoad.storageType.ToString(), mipToLoad.externalOffset.ToString()));
                                        }
                                    }
                                }
                                else
                                {
                                    fs.Read(imagebytes, 0, mipToLoad.compressedSize);
                                }
                            }
                            else
                            {
                                fs.Read(imagebytes, 0, mipToLoad.uncompressedSize);
                            }
                        }
                        catch (Exception e)
                        {
                            throw new Exception(GetLocalizedTextureExceptionExternalMessage(e.Message, filename, mipToLoad.storageType.ToString(), mipToLoad.externalOffset.ToString()));
                        }
                    }
                }
                catch (Exception e)
                {
                    throw new Exception(GetLocalizedTextureExceptionExternalMessage(e.Message, filename, mipToLoad.storageType.ToString(), mipToLoad.externalOffset.ToString()));
                }
            }
            return(imagebytes);
        }