public async Task <bool> SetMaterial(XivMtrl material, IItemModel item, MaterialEditorMode mode = MaterialEditorMode.EditSingle)
 {
     _material = material;
     _item     = item;
     _mode     = mode;
     return(await viewModel.SetMaterial(material, item, mode));
 }
Ejemplo n.º 2
0
        private static void ComputeColorsetBlending(XivMtrl mtrl, byte colorsetByte, byte[] colorSetData, Color baseDiffuse, Color baseSpecular, out Color newDiffuse, out Color newSpecular, out Color emissiveColor)
        {
            int   rowNumber    = colorsetByte / 17;
            int   nextRow      = rowNumber >= 15 ? 15 : rowNumber + 1;
            int   blendAmount  = (colorsetByte % 17);
            float fBlendAmount = blendAmount / 17.0f;

            Color diffuse1, diffuse2;
            Color spec1, spec2;
            Color emiss1, emiss2;

            // Byte offset to rows
            var row1Offset = Clamp(rowNumber * 16);
            var row2Offset = Clamp(nextRow * 16);

            diffuse1 = new Color(colorSetData[row1Offset + 0], colorSetData[row1Offset + 1], colorSetData[row1Offset + 2], (byte)255);
            diffuse2 = new Color(colorSetData[row2Offset + 0], colorSetData[row2Offset + 1], colorSetData[row2Offset + 2], (byte)255);

            spec1 = new Color(colorSetData[row1Offset + 4], colorSetData[row1Offset + 5], colorSetData[row1Offset + 6], (byte)255);
            spec2 = new Color(colorSetData[row2Offset + 4], colorSetData[row2Offset + 5], colorSetData[row2Offset + 6], (byte)255);

            emiss1 = new Color(colorSetData[row1Offset + 8], colorSetData[row1Offset + 9], colorSetData[row1Offset + 10], (byte)255);
            emiss2 = new Color(colorSetData[row2Offset + 8], colorSetData[row2Offset + 9], colorSetData[row2Offset + 10], (byte)255);


            // These are now our base values to multiply the base values by.
            Color diffuse  = Blend(diffuse1, diffuse2, fBlendAmount);
            Color specular = Blend(spec1, spec2, fBlendAmount);
            Color emissive = Blend(emiss1, emiss2, fBlendAmount);

            newDiffuse    = MultiplyColor(baseDiffuse, diffuse);
            newSpecular   = MultiplyColor(baseSpecular, specular);
            emissiveColor = emissive;  // Nothing to multiply by here.
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Converts a DDS file into a mtrl file and returns the raw data
        /// </summary>
        /// <param name="xivMtrl">The XivMtrl data of the original</param>
        /// <param name="ddsFileDirectory">The dds directory of the new ColorSet</param>
        /// <param name="item">The item</param>
        /// <returns>The raw mtrl data</returns>
        public byte[] DDStoMtrlData(XivMtrl xivMtrl, DirectoryInfo ddsFileDirectory, IItem item, XivLanguage lang)
        {
            var colorSetData = GetColorsetDataFromDDS(ddsFileDirectory);

            var colorSetExtraData = new byte[32];

            // If the colorset size is 544, it contains extra data that must be imported
            try
            {
                colorSetExtraData = GetColorsetExtraDataFromDDS(ddsFileDirectory);
            } catch
            {
                colorSetExtraData = new byte[32];
            }

            // Replace the color set data with the imported data
            xivMtrl.ColorSetData    = colorSetData;
            xivMtrl.ColorSetDyeData = colorSetExtraData;

            if (xivMtrl.Unknown2.Length > 0)
            {
                // This byte enables the dye set if it's not already enabled.
                xivMtrl.Unknown2[0] = 12;
            }

            var _mtrl = new Mtrl(XivCache.GameInfo.GameDirectory);

            return(_mtrl.CreateMtrlFile(xivMtrl, item));
        }
Ejemplo n.º 4
0
        public async Task SetMaterial(XivMtrl mtrl, StainingTemplateFile dyeFile)
        {
            _mtrl           = mtrl;
            DyeTemplateFile = dyeFile;

            _viewport = _view.ColorsetRowViewport;
            _viewport.BackgroundColor = System.Windows.Media.Colors.Gray;
            _viewport.Background      = Brushes.Gray;

            if (_NeedLights)
            {
                _NeedLights = false;
            }

            _viewport.Camera.UpDirection   = new System.Windows.Media.Media3D.Vector3D(0, 1, 0);
            _viewport.Camera.LookDirection = new System.Windows.Media.Media3D.Vector3D(0, 0, -1);
            _viewport.Camera.Position      = new System.Windows.Media.Media3D.Point3D(0, 0, 3);



            if (TileTextureNormal == null)
            {
                var _tex = new Tex(XivCache.GameInfo.GameDirectory);
                TileTextureNormal = await _tex.GetTexData("chara/common/texture/-tile_n.tex");

                TileTextureDiffuse = await _tex.GetTexData("chara/common/texture/-tile_d.tex");
            }
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Converts a DDS file into a mtrl file and returns the raw data
        /// </summary>
        /// <param name="xivMtrl">The XivMtrl data of the original</param>
        /// <param name="ddsFileDirectory">The dds directory of the new ColorSet</param>
        /// <param name="item">The item</param>
        /// <returns>The raw mtrl data</returns>
        public byte[] DDStoMtrlData(XivMtrl xivMtrl, DirectoryInfo ddsFileDirectory, IItem item, XivLanguage lang)
        {
            var colorSetData = new List <Half>();

            using (var br = new BinaryReader(File.OpenRead(ddsFileDirectory.FullName)))
            {
                // skip DDS header
                br.BaseStream.Seek(128, SeekOrigin.Begin);

                // color data is always 512 (4w x 16h = 64 x 8bpp = 512)
                // this reads 256 ushort values which is 256 x 2 = 512
                for (var i = 0; i < 256; i++)
                {
                    colorSetData.Add(new Half(br.ReadUInt16()));
                }
            }
            var colorSetExtraData = new byte[32];

            // If the colorset size is 544, it contains extra data that must be imported
            if (xivMtrl.ColorSetDataSize == 544)
            {
                var flagsPath = Path.Combine(Path.GetDirectoryName(ddsFileDirectory.FullName), (Path.GetFileNameWithoutExtension(ddsFileDirectory.FullName) + ".dat"));

                if (File.Exists(flagsPath))
                {
                    colorSetExtraData = File.ReadAllBytes(flagsPath);
                    //using (var br = new BinaryReader(File.OpenRead(flagsPath)))
                    //{
                    //    // The extra data after the colorset is always 32 bytes
                    //    // This reads 16 ushort values which is 16 x 2 = 32
                    //    for (var i = 0; i < 16; i++)
                    //    {
                    //        colorSetData.Add(new Half(br.ReadUInt16()));
                    //    }
                    //}
                }
            }

            // Replace the color set data with the imported data
            xivMtrl.ColorSetData      = colorSetData;
            xivMtrl.ColorSetExtraData = colorSetExtraData;

            var mtrl = new Mtrl(_gameDirectory, xivMtrl.TextureTypePathList[0].DataFile, lang);

            return(mtrl.CreateMtrlFile(xivMtrl, item));
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Imports a ColorSet file
        /// </summary>
        /// <param name="xivMtrl">The XivMtrl data of the original</param>
        /// <param name="ddsFileDirectory">The dds directory of the new ColorSet</param>
        /// <param name="item">The item</param>
        /// <param name="source">The source importing the file</param>
        /// <returns>The new offset</returns>
        public async Task <long> TexColorImporter(XivMtrl xivMtrl, DirectoryInfo ddsFileDirectory, IItem item, string source, XivLanguage lang)
        {
            var colorSetData = new List <Half>();

            byte[] colorSetExtraData = null;


            colorSetData      = GetColorsetDataFromDDS(ddsFileDirectory);
            colorSetExtraData = GetColorsetExtraDataFromDDS(ddsFileDirectory);

            // Replace the color set data with the imported data
            xivMtrl.ColorSetData    = colorSetData;
            xivMtrl.ColorSetDyeData = colorSetExtraData;
            if (xivMtrl.Unknown2.Length > 0)
            {
                // This byte enables the dye set if it's not already enabled.
                xivMtrl.Unknown2[0] = 12;
            }

            var _mtrl = new Mtrl(XivCache.GameInfo.GameDirectory);

            return(await _mtrl.ImportMtrl(xivMtrl, item, source));
        }
        private async void SaveButton_Click(object sender, RoutedEventArgs e)
        {
            _material = await viewModel.SaveChanges();

            Close(true);
        }
        public async Task <bool> SetMaterial(XivMtrl material, IItemModel item, MaterialEditorMode mode)
        {
            if (material == null)
            {
                return(false);
            }

            _mode     = mode;
            _material = material;
            _item     = item;

            var gameDirectory = new DirectoryInfo(Properties.Settings.Default.FFXIV_Directory);

            _mtrl    = new Mtrl(gameDirectory, item.DataFile, GetLanguage());
            _index   = new Index(gameDirectory);
            _modding = new Modding(gameDirectory);
            _gear    = new Gear(gameDirectory, GetLanguage());


            // Drop the multi functions down to singles if they only have one Material to edit anyways.
            if (_mode == MaterialEditorMode.EditMulti || _mode == MaterialEditorMode.NewMulti)
            {
                // This isn't an actual perfect check for if there's only one Variant, but doing so
                // would be a bit expensive here, and passing it through EditMulti isn't harmful anyways.
                var sameModelItems = await _item.GetSharedModelItems();

                if (sameModelItems.Count == 1)
                {
                    if (_mode == MaterialEditorMode.EditMulti)
                    {
                        _mode = MaterialEditorMode.EditSingle;
                    }
                    else
                    {
                        _mode = MaterialEditorMode.NewSingle;
                    }
                }
            }

            /*
             * // Debug code for finding unknown Shader Parameters.
             * var unknowns = new List<ShaderParameterStruct>();
             * foreach(var sp in material.ShaderParameterList)
             * {
             *  if (!Enum.IsDefined(typeof(MtrlShaderParameterId), sp.ParameterID))
             *  {
             *      unknowns.Add(sp);
             *  }
             * }
             * if(unknowns.Count > 0)
             * {
             *  // Debug line
             *  var json = JsonConvert.SerializeObject(unknowns.ToArray());
             * }
             */


            // Update to new material name
            switch (_mode)
            {
            case MaterialEditorMode.EditSingle:
                _view.MaterialPathLabel.Text = _material.MTRLPath;
                break;

            case MaterialEditorMode.EditMulti:
                _view.MaterialPathLabel.Text = "Editing Multiple Materials: Material " + _material.GetMaterialIdentifier();
                break;

            case MaterialEditorMode.NewSingle:
                _view.MaterialPathLabel.Text = "New Material";
                break;

            case MaterialEditorMode.NewMulti:
                _view.MaterialPathLabel.Text = "New Materials";
                break;
            }

            var shader     = _material.GetShaderInfo();
            var normal     = _material.GetMapInfo(XivTexType.Normal);
            var diffuse    = _material.GetMapInfo(XivTexType.Diffuse);
            var specular   = _material.GetMapInfo(XivTexType.Specular);
            var multi      = _material.GetMapInfo(XivTexType.Multi);
            var reflection = _material.GetMapInfo(XivTexType.Reflection);

            // Show Paths
            _view.NormalTextBox.Text   = normal == null ? "" : normal.path;
            _view.SpecularTextBox.Text = specular == null ? "" : specular.path;
            _view.SpecularTextBox.Text = multi == null ? _view.SpecularTextBox.Text : multi.path;
            _view.DiffuseTextBox.Text  = diffuse == null ? "" : diffuse.path;
            _view.DiffuseTextBox.Text  = reflection == null ? _view.DiffuseTextBox.Text : reflection.path;

            // Add Other option if needed.
            if (shader.Shader == MtrlShader.Other)
            {
                _view.ShaderSource.Add(new KeyValuePair <MtrlShader, string>(MtrlShader.Other, "Other"));
            }

            // Show Settings
            _view.TransparencyComboBox.SelectedValue = shader.TransparencyEnabled;
            _view.BackfacesComboBox.SelectedValue    = shader.RenderBackfaces;
            _view.ColorsetComboBox.SelectedValue     = shader.HasColorset;
            _view.ShaderComboBox.SelectedValue       = shader.Shader;
            _view.PresetComboBox.SelectedValue       = shader.Preset;


            if (_mode == MaterialEditorMode.NewMulti)
            {
                // Bump up the material identifier letter.
                _newMaterialIdentifier = await GetNewMaterialIdentifier();

                _view.MaterialPathLabel.Text = "New Materials: Material " + _newMaterialIdentifier;
            }
            else if (_mode == MaterialEditorMode.NewSingle)
            {
                _newMaterialIdentifier = await GetNewMaterialIdentifier();

                _view.MaterialPathLabel.Text = "New Material: Material " + _newMaterialIdentifier;
            }

            // Get the mod entry.
            if (_mode == MaterialEditorMode.EditSingle || _mode == MaterialEditorMode.EditMulti)
            {
                var mod = await _modding.TryGetModEntry(_material.MTRLPath);

                if (mod != null && mod.enabled)
                {
                    _view.DisableButton.IsEnabled  = true;
                    _view.DisableButton.Visibility = System.Windows.Visibility.Visible;
                }
            }

            return(true);
        }
Ejemplo n.º 9
0
 public ModelTexture(DirectoryInfo gameDirectory, XivMtrl mtrlData)
 {
     _mtrlData      = mtrlData;
     _gameDirectory = gameDirectory;
 }
Ejemplo n.º 10
0
        /// <summary>
        /// Toggles Translucency for an item on or off
        /// </summary>
        /// <param name="xivMtrl">The XivMtrl containing the mtrl data</param>
        /// <param name="item">The item to toggle translucency for</param>
        /// <param name="translucencyEnabled">Flag determining if translucency is to be enabled or disabled</param>
        public void ToggleTranslucency(XivMtrl xivMtrl, IItem item, bool translucencyEnabled)
        {
            xivMtrl.ShaderNumber = !translucencyEnabled ? (short)0x0D : (short)0x1D;

            ImportMtrl(xivMtrl, item);
        }
Ejemplo n.º 11
0
        /// <summary>
        /// Gets the customized texture map data for a model.
        /// Null custom model colors uses the defaults at ModelTexture.GetCustomColors().
        /// </summary>
        /// <param name="gameDirectory"></param>
        /// <param name="mtrl"></param>
        /// <param name="colors"></param>
        /// <returns></returns>
        public static async Task <ModelTextureData> GetModelMaps(DirectoryInfo gameDirectory, XivMtrl mtrl, CustomModelColors colors = null)
        {
            var tex = new Tex(gameDirectory);

            return(await GetModelMaps(tex, mtrl));
        }
Ejemplo n.º 12
0
        /// <summary>
        /// Gets the materials for the model
        /// </summary>
        /// <returns>A dictionary containing the mesh number(key) and the associated texture data (value)</returns>
        public static async Task <Dictionary <string, ModelTextureData> > GetMaterials(
            DirectoryInfo gameDirectory, IItemModel item, XivMdl mdlData, XivRace race)
        {
            var textureDataDictionary = new Dictionary <string, ModelTextureData>();
            var mtrlDictionary        = new Dictionary <string, XivMtrl>();
            var mtrl                      = new Mtrl(gameDirectory);
            var mtrlFilePaths             = mdlData.PathData.MaterialList;
            var hasColorChangeShader      = false;
            CustomModelColors customColor = new CustomModelColors();
            WinColor          winColor;

            var materialNum = 0;

            foreach (var mtrlFilePath in mtrlFilePaths)
            {
                var mtrlItem = new XivGenericItemModel
                {
                    PrimaryCategory   = item.PrimaryCategory,
                    SecondaryCategory = item.SecondaryCategory,
                    TertiaryCategory  = item.TertiaryCategory,
                    ModelInfo         = new XivModelInfo
                    {
                        SecondaryID = item.ModelInfo.SecondaryID,
                        PrimaryID   = item.ModelInfo.PrimaryID,
                        ModelKey    = item.ModelInfo.ModelKey,
                        ImcSubsetID = item.ModelInfo.ImcSubsetID
                    },
                    Name = item.Name
                };

                var modelID  = mtrlItem.ModelInfo.PrimaryID;
                var bodyID   = mtrlItem.ModelInfo.SecondaryID;
                var filePath = mtrlFilePath;

                if (!filePath.Contains("hou") && mtrlFilePath.Count(x => x == '/') > 1)
                {
                    filePath = mtrlFilePath.Substring(mtrlFilePath.LastIndexOf("/"));
                }

                var typeChar = $"{mtrlFilePath[4]}{mtrlFilePath[9]}";

                var raceString = "";
                switch (typeChar)
                {
                // Character Body
                case "cb":
                    var body = mtrlFilePath.Substring(mtrlFilePath.IndexOf("b") + 1, 4);
                    raceString = mtrlFilePath.Substring(mtrlFilePath.IndexOf("c") + 1, 4);
                    race       = XivRaces.GetXivRace(raceString);

                    if (!raceString.Equals("0901") && !raceString.Equals("1001") && !raceString.Equals("1101"))
                    {
                        var gender = 0;
                        if (int.Parse(raceString.Substring(0, 2)) % 2 == 0)
                        {
                            gender = 1;
                        }

                        var settingsRace = GetSettingsRace(gender);

                        race = settingsRace.Race;

                        filePath = mtrlFilePath.Replace(raceString, race.GetRaceCode()).Replace(body, settingsRace.BodyID);

                        body = settingsRace.BodyID;
                    }


                    mtrlItem = new XivGenericItemModel
                    {
                        PrimaryCategory   = XivStrings.Character,
                        SecondaryCategory = XivStrings.Body,
                        Name      = XivStrings.Body,
                        ModelInfo = new XivModelInfo
                        {
                            SecondaryID = int.Parse(body)
                        }
                    };

                    //winColor = (WinColor)ColorConverter.ConvertFromString(Settings.Default.Skin_Color);
                    //customColor.SkinColor = new SharpDX.Color(winColor.R, winColor.G, winColor.B, winColor.A);

                    break;

                // Face
                case "cf":
                    bodyID     = int.Parse(mtrlFilePath.Substring(mtrlFilePath.IndexOf("f") + 1, 4));
                    raceString = mtrlFilePath.Substring(mtrlFilePath.IndexOf("c") + 1, 4);
                    race       = XivRaces.GetXivRace(raceString);

                    mtrlItem = new XivGenericItemModel
                    {
                        PrimaryCategory   = XivStrings.Character,
                        SecondaryCategory = XivStrings.Face,
                        Name      = XivStrings.Face,
                        ModelInfo = new XivModelInfo
                        {
                            SecondaryID = bodyID
                        }
                    };

                    break;

                // Hair
                case "ch":
                    bodyID     = int.Parse(mtrlFilePath.Substring(mtrlFilePath.IndexOf("h") + 1, 4));
                    raceString = mtrlFilePath.Substring(mtrlFilePath.IndexOf("c") + 1, 4);
                    race       = XivRaces.GetXivRace(raceString);

                    mtrlItem = new XivGenericItemModel
                    {
                        PrimaryCategory   = XivStrings.Character,
                        SecondaryCategory = XivStrings.Hair,
                        Name      = XivStrings.Hair,
                        ModelInfo = new XivModelInfo
                        {
                            SecondaryID = bodyID
                        }
                    };

                    //winColor = (WinColor)ColorConverter.ConvertFromString(Settings.Default.Hair_Color);
                    //customColor.HairColor = new SharpDX.Color(winColor.R, winColor.G, winColor.B, winColor.A);

                    break;

                // Tail
                case "ct":
                    var tempPath = mtrlFilePath.Substring(4);
                    bodyID     = int.Parse(tempPath.Substring(tempPath.IndexOf("t") + 1, 4));
                    raceString = mtrlFilePath.Substring(mtrlFilePath.IndexOf("c") + 1, 4);
                    race       = XivRaces.GetXivRace(raceString);

                    mtrlItem = new XivGenericItemModel
                    {
                        PrimaryCategory   = XivStrings.Character,
                        SecondaryCategory = XivStrings.Tail,
                        Name      = XivStrings.Tail,
                        ModelInfo = new XivModelInfo
                        {
                            SecondaryID = bodyID
                        }
                    };

                    //winColor = (WinColor)ColorConverter.ConvertFromString(Settings.Default.Hair_Color);
                    //customColor.HairColor = new SharpDX.Color(winColor.R, winColor.G, winColor.B, winColor.A);

                    break;

                // Equipment
                case "ce":
                    modelID    = int.Parse(mtrlFilePath.Substring(mtrlFilePath.IndexOf("e") + 1, 4));
                    raceString = mtrlFilePath.Substring(mtrlFilePath.IndexOf("c") + 1, 4);
                    race       = XivRaces.GetXivRace(raceString);

                    mtrlItem.ModelInfo.PrimaryID = modelID;
                    break;

                // Accessory
                case "ca":
                    modelID    = int.Parse(mtrlFilePath.Substring(mtrlFilePath.IndexOf("a") + 1, 4));
                    raceString = mtrlFilePath.Substring(mtrlFilePath.IndexOf("c") + 1, 4);
                    race       = XivRaces.GetXivRace(raceString);

                    mtrlItem.ModelInfo.PrimaryID = modelID;
                    break;

                // Weapon
                case "wb":
                    modelID = int.Parse(mtrlFilePath.Substring(mtrlFilePath.IndexOf("w") + 1, 4));
                    bodyID  = int.Parse(mtrlFilePath.Substring(mtrlFilePath.IndexOf("b") + 1, 4));
                    mtrlItem.ModelInfo.PrimaryID   = modelID;
                    mtrlItem.ModelInfo.SecondaryID = bodyID;
                    break;

                // Monster
                case "mb":
                    modelID = int.Parse(mtrlFilePath.Substring(mtrlFilePath.IndexOf("_m") + 2, 4));
                    bodyID  = int.Parse(mtrlFilePath.Substring(mtrlFilePath.IndexOf("b") + 1, 4));
                    mtrlItem.ModelInfo.PrimaryID   = modelID;
                    mtrlItem.ModelInfo.SecondaryID = bodyID;
                    break;

                // DemiHuman
                case "de":
                    modelID = int.Parse(mtrlFilePath.Substring(mtrlFilePath.IndexOf("d") + 1, 4));
                    bodyID  = int.Parse(mtrlFilePath.Substring(mtrlFilePath.IndexOf("e") + 1, 4));
                    mtrlItem.ModelInfo.PrimaryID   = modelID;
                    mtrlItem.ModelInfo.SecondaryID = bodyID;
                    break;

                default:
                    break;
                }

                var dxVersion = int.Parse(Settings.Default.DX_Version);

                var mtrlFile = filePath;
                if (mtrlFile.StartsWith("/"))
                {
                    mtrlFile = mtrlFile.Remove(0, 1);
                }
                XivMtrl mtrlData = null;

                try
                {
                    mtrlData = await mtrl.GetMtrlData(mtrlItem, mtrlFile, dxVersion);
                }
                catch (Exception e)
                {
                    if (mtrlItem.ModelInfo.PrimaryID == item.ModelInfo.PrimaryID)
                    {
                        Console.WriteLine(e.Message);
                        throw;
                    }
                }

                if (mtrlData == null)
                {
                    // Fall back to material data from the primary model.
                    try
                    {
                        mtrlData = await mtrl.GetMtrlData(item, mtrlFile, dxVersion);
                    }
                    catch (Exception ee)
                    {
                        Console.WriteLine(ee.Message);
                        throw;
                    }
                }

                if (mtrlData == null)
                {
                    continue;
                }

                if (mtrlData.Shader.Contains("colorchange"))
                {
                    hasColorChangeShader = true;
                }

                mtrlDictionary.Add(mtrlFilePath, mtrlData);

                materialNum++;
            }

            foreach (var xivMtrl in mtrlDictionary)
            {
                if (hasColorChangeShader)
                {
                    var modelMaps = await ModelTexture.GetModelMaps(gameDirectory, xivMtrl.Value);

                    textureDataDictionary.Add(xivMtrl.Key, modelMaps);
                }
                else
                {
                    if (item.SecondaryCategory.Equals(XivStrings.Face))
                    {
                        var path = xivMtrl.Value.MTRLPath;
                        customColor = new CustomModelColors();

                        if (path.Contains("_iri_"))
                        {
                            winColor = (WinColor)ColorConverter.ConvertFromString(Settings.Default.Iris_Color);
                        }
                        else if (path.Contains("_etc_"))
                        {
                            winColor = (WinColor)ColorConverter.ConvertFromString(Settings.Default.Etc_Color);
                        }
                        else
                        {
                            winColor = (WinColor)ColorConverter.ConvertFromString(Settings.Default.Skin_Color);
                        }

                        //customColor = new CustomModelColors(winColor.R, winColor.G, winColor.B, winColor.A);
                    }

                    var modelMaps = await ModelTexture.GetModelMaps(gameDirectory, xivMtrl.Value, customColor);

                    textureDataDictionary.Add(xivMtrl.Key, modelMaps);
                }
            }

            return(textureDataDictionary);
        }
Ejemplo n.º 13
0
        /// <summary>
        /// Gets the MTRL data for the given offset and path
        /// </summary>
        /// <param name="mtrlOffset">The offset to the mtrl in the dat file</param>
        /// <param name="mtrlPath">The full internal game path for the mtrl</param>
        /// <returns>XivMtrl containing all the mtrl data</returns>
        public XivMtrl GetMtrlData(int mtrlOffset, string mtrlPath, int dxVersion)
        {
            var dat   = new Dat(_gameDirectory);
            var index = new Index(_gameDirectory);

            // Get uncompressed mtrl data
            var mtrlData = dat.GetType2Data(mtrlOffset, _dataFile);

            XivMtrl xivMtrl;

            using (var br = new BinaryReader(new MemoryStream(mtrlData)))
            {
                xivMtrl = new XivMtrl
                {
                    Signature            = br.ReadInt32(),
                    FileSize             = br.ReadInt16(),
                    ColorSetDataSize     = br.ReadUInt16(),
                    MaterialDataSize     = br.ReadUInt16(),
                    TexturePathsDataSize = br.ReadUInt16(),
                    TextureCount         = br.ReadByte(),
                    MapCount             = br.ReadByte(),
                    ColorSetCount        = br.ReadByte(),
                    UnknownDataSize      = br.ReadByte(),
                    TextureTypePathList  = new List <TexTypePath>(),
                    MTRLPath             = mtrlPath
                };

                var pathSizeList = new List <int>();

                // get the texture path offsets
                xivMtrl.TexturePathOffsetList  = new List <int>(xivMtrl.TextureCount);
                xivMtrl.TexturePathUnknownList = new List <short>(xivMtrl.TextureCount);
                for (var i = 0; i < xivMtrl.TextureCount; i++)
                {
                    xivMtrl.TexturePathOffsetList.Add(br.ReadInt16());
                    xivMtrl.TexturePathUnknownList.Add(br.ReadInt16());

                    // add the size of the paths
                    if (i > 0)
                    {
                        pathSizeList.Add(xivMtrl.TexturePathOffsetList[i] - xivMtrl.TexturePathOffsetList[i - 1]);
                    }
                }

                // get the map path offsets
                xivMtrl.MapPathOffsetList  = new List <int>(xivMtrl.MapCount);
                xivMtrl.MapPathUnknownList = new List <short>(xivMtrl.MapCount);
                for (var i = 0; i < xivMtrl.MapCount; i++)
                {
                    xivMtrl.MapPathOffsetList.Add(br.ReadInt16());
                    xivMtrl.MapPathUnknownList.Add(br.ReadInt16());

                    // add the size of the paths
                    if (i > 0)
                    {
                        pathSizeList.Add(xivMtrl.MapPathOffsetList[i] - xivMtrl.MapPathOffsetList[i - 1]);
                    }
                    else
                    {
                        pathSizeList.Add(xivMtrl.MapPathOffsetList[i] - xivMtrl.TexturePathOffsetList[xivMtrl.TextureCount - 1]);
                    }
                }

                // get the color set offsets
                xivMtrl.ColorSetPathOffsetList  = new List <int>(xivMtrl.ColorSetCount);
                xivMtrl.ColorSetPathUnknownList = new List <short>(xivMtrl.ColorSetCount);
                for (var i = 0; i < xivMtrl.ColorSetCount; i++)
                {
                    xivMtrl.ColorSetPathOffsetList.Add(br.ReadInt16());
                    xivMtrl.ColorSetPathUnknownList.Add(br.ReadInt16());

                    // add the size of the paths
                    if (i > 0)
                    {
                        pathSizeList.Add(xivMtrl.ColorSetPathOffsetList[i] - xivMtrl.ColorSetPathOffsetList[i - 1]);
                    }
                    else
                    {
                        pathSizeList.Add(xivMtrl.ColorSetPathOffsetList[i] - xivMtrl.MapPathOffsetList[xivMtrl.MapCount - 1]);
                    }
                }

                pathSizeList.Add(xivMtrl.TexturePathsDataSize - xivMtrl.ColorSetPathOffsetList[xivMtrl.ColorSetCount - 1]);

                var count = 0;

                // get the texture path strings
                xivMtrl.TexturePathList = new List <string>(xivMtrl.TextureCount);
                for (var i = 0; i < xivMtrl.TextureCount; i++)
                {
                    var texturePath  = Encoding.UTF8.GetString(br.ReadBytes(pathSizeList[count])).Replace("\0", "");
                    var dx11FileName = Path.GetFileName(texturePath).Insert(0, "--");

                    if (index.FileExists(HashGenerator.GetHash(dx11FileName),
                                         HashGenerator.GetHash(Path.GetDirectoryName(texturePath).Replace("\\", "/")), _dataFile))
                    {
                        texturePath = texturePath.Insert(texturePath.LastIndexOf("/") + 1, "--");
                    }

                    xivMtrl.TexturePathList.Add(texturePath);
                    count++;
                }

                // add the textures to the TextureTypePathList
                xivMtrl.TextureTypePathList.AddRange(GetTexNames(xivMtrl.TexturePathList, _dataFile));

                // get the map path strings
                xivMtrl.MapPathList = new List <string>(xivMtrl.MapCount);
                for (var i = 0; i < xivMtrl.MapCount; i++)
                {
                    xivMtrl.MapPathList.Add(Encoding.UTF8.GetString(br.ReadBytes(pathSizeList[count])).Replace("\0", ""));
                    count++;
                }

                // get the color set path strings
                xivMtrl.ColorSetPathList = new List <string>(xivMtrl.ColorSetCount);
                for (var i = 0; i < xivMtrl.ColorSetCount; i++)
                {
                    xivMtrl.ColorSetPathList.Add(Encoding.UTF8.GetString(br.ReadBytes(pathSizeList[count])).Replace("\0", ""));
                    count++;
                }

                // If the mtrl file contains a color set, add it to the TextureTypePathList
                if (xivMtrl.ColorSetDataSize > 0)
                {
                    var ttp = new TexTypePath
                    {
                        Path     = mtrlPath,
                        Type     = XivTexType.ColorSet,
                        DataFile = _dataFile
                    };
                    xivMtrl.TextureTypePathList.Add(ttp);
                }

                var shaderPathSize = xivMtrl.MaterialDataSize - xivMtrl.TexturePathsDataSize;

                xivMtrl.Shader = Encoding.UTF8.GetString(br.ReadBytes(shaderPathSize)).Replace("\0", "");

                xivMtrl.Unknown2 = br.ReadBytes(xivMtrl.UnknownDataSize);

                if (xivMtrl.ColorSetDataSize > 0)
                {
                    // Color Data is always 512 (6 x 14 = 64 x 8bpp = 512)
                    var colorDataSize = 512;

                    xivMtrl.ColorSetData = new List <Half>();
                    for (var i = 0; i < colorDataSize / 2; i++)
                    {
                        xivMtrl.ColorSetData.Add(new Half(br.ReadUInt16()));
                    }

                    // If the color set is 544 in length, it has an extra 32 bytes at the end
                    if (xivMtrl.ColorSetDataSize == 544)
                    {
                        xivMtrl.ColorSetExtraData = br.ReadBytes(32);
                    }
                }

                xivMtrl.AdditionalDataSize = br.ReadUInt16();

                xivMtrl.DataStruct1Count = br.ReadUInt16();

                xivMtrl.DataStruct2Count = br.ReadUInt16();

                xivMtrl.ParameterStructCount = br.ReadUInt16();

                xivMtrl.ShaderNumber = br.ReadUInt16();

                xivMtrl.Unknown3 = br.ReadUInt16();

                xivMtrl.DataStruct1List = new List <DataStruct1>(xivMtrl.DataStruct1Count);
                for (var i = 0; i < xivMtrl.DataStruct1Count; i++)
                {
                    xivMtrl.DataStruct1List.Add(new DataStruct1 {
                        ID = br.ReadUInt32(), Unknown1 = br.ReadUInt32()
                    });
                }

                xivMtrl.DataStruct2List = new List <DataStruct2>(xivMtrl.DataStruct2Count);
                for (var i = 0; i < xivMtrl.DataStruct2Count; i++)
                {
                    xivMtrl.DataStruct2List.Add(new DataStruct2 {
                        ID = br.ReadUInt32(), Offset = br.ReadInt16(), Size = br.ReadInt16()
                    });
                }

                xivMtrl.ParameterStructList = new List <ParameterStruct>(xivMtrl.ParameterStructCount);
                for (var i = 0; i < xivMtrl.ParameterStructCount; i++)
                {
                    xivMtrl.ParameterStructList.Add(new ParameterStruct {
                        ID = br.ReadUInt32(), Unknown1 = br.ReadInt16(), Unknown2 = br.ReadInt16(), TextureIndex = br.ReadUInt32()
                    });
                }

                xivMtrl.AdditionalData = br.ReadBytes(xivMtrl.AdditionalDataSize);
            }

            return(xivMtrl);
        }
Ejemplo n.º 14
0
        /// <summary>
        /// Toggles Translucency for an item on or off
        /// </summary>
        /// <param name="xivMtrl">The XivMtrl containing the mtrl data</param>
        /// <param name="item">The item to toggle translucency for</param>
        /// <param name="translucencyEnabled">Flag determining if translucency is to be enabled or disabled</param>
        /// <param name="source">The source/application that is writing to the dat.</param>
        public void ToggleTranslucency(XivMtrl xivMtrl, IItem item, bool translucencyEnabled, string source)
        {
            xivMtrl.ShaderNumber = !translucencyEnabled ? (ushort)0x0D : (ushort)0x1D;

            ImportMtrl(xivMtrl, item, source);
        }
Ejemplo n.º 15
0
 public ModelTexture(Modding modding, XivMtrl mtrlData)
 {
     _modding  = modding;
     _mtrlData = mtrlData;
 }
Ejemplo n.º 16
0
        /// <summary>
        /// Imports an MTRL file
        /// </summary>
        /// <param name="xivMtrl">The XivMtrl containing the mtrl data</param>
        /// <param name="item">The item whos mtrl is being imported</param>
        public void ImportMtrl(XivMtrl xivMtrl, IItem item)
        {
            var mtrlBytes = new List <byte>();

            mtrlBytes.AddRange(BitConverter.GetBytes(xivMtrl.Signature));
            mtrlBytes.AddRange(BitConverter.GetBytes(xivMtrl.FileSize));
            mtrlBytes.AddRange(BitConverter.GetBytes(xivMtrl.ColorSetDataSize));
            mtrlBytes.AddRange(BitConverter.GetBytes(xivMtrl.MaterialDataSize));
            mtrlBytes.Add(xivMtrl.TexturePathsDataSize);
            mtrlBytes.Add(xivMtrl.Unknown);
            mtrlBytes.Add(xivMtrl.TextureCount);
            mtrlBytes.Add(xivMtrl.MapCount);
            mtrlBytes.Add(xivMtrl.ColorSetCount);
            mtrlBytes.Add(xivMtrl.Unknown1);

            foreach (var texPath in xivMtrl.TexturePathOffsetList)
            {
                mtrlBytes.AddRange(BitConverter.GetBytes(texPath));
            }

            foreach (var mapPath in xivMtrl.MapPathOffsetList)
            {
                mtrlBytes.AddRange(BitConverter.GetBytes(mapPath));
            }

            foreach (var colorPath in xivMtrl.ColorSetPathOffsetList)
            {
                mtrlBytes.AddRange(BitConverter.GetBytes(colorPath));
            }

            foreach (var texPathString in xivMtrl.TexturePathList)
            {
                mtrlBytes.AddRange(Encoding.UTF8.GetBytes(texPathString));
                mtrlBytes.Add(0);
            }

            foreach (var mapPathString in xivMtrl.MapPathList)
            {
                mtrlBytes.AddRange(Encoding.UTF8.GetBytes(mapPathString));
                mtrlBytes.Add(0);
            }

            foreach (var colorSetPathString in xivMtrl.ColorSetPathList)
            {
                mtrlBytes.AddRange(Encoding.UTF8.GetBytes(colorSetPathString));
                mtrlBytes.Add(0);
            }

            mtrlBytes.AddRange(Encoding.UTF8.GetBytes(xivMtrl.Shader));
            mtrlBytes.Add(0);
            mtrlBytes.AddRange(BitConverter.GetBytes(xivMtrl.Unknown2));

            foreach (var colorSetHalf in xivMtrl.ColorSetData)
            {
                mtrlBytes.AddRange(BitConverter.GetBytes(colorSetHalf.RawValue));
            }

            mtrlBytes.AddRange(BitConverter.GetBytes(xivMtrl.AdditionalDataSize));
            mtrlBytes.AddRange(BitConverter.GetBytes(xivMtrl.DataStruct1Count));
            mtrlBytes.AddRange(BitConverter.GetBytes(xivMtrl.DataStruct2Count));
            mtrlBytes.AddRange(BitConverter.GetBytes(xivMtrl.ParameterStructCount));
            mtrlBytes.AddRange(BitConverter.GetBytes(xivMtrl.ShaderNumber));
            mtrlBytes.AddRange(BitConverter.GetBytes(xivMtrl.Unknown3));

            foreach (var dataStruct1 in xivMtrl.DataStruct1List)
            {
                mtrlBytes.AddRange(BitConverter.GetBytes(dataStruct1.ID));
                mtrlBytes.AddRange(BitConverter.GetBytes(dataStruct1.Unknown1));
            }

            foreach (var dataStruct2 in xivMtrl.DataStruct2List)
            {
                mtrlBytes.AddRange(BitConverter.GetBytes(dataStruct2.ID));
                mtrlBytes.AddRange(BitConverter.GetBytes(dataStruct2.Offset));
                mtrlBytes.AddRange(BitConverter.GetBytes(dataStruct2.Size));
            }

            foreach (var parameterStruct in xivMtrl.ParameterStructList)
            {
                mtrlBytes.AddRange(BitConverter.GetBytes(parameterStruct.ID));
                mtrlBytes.AddRange(BitConverter.GetBytes(parameterStruct.Unknown1));
                mtrlBytes.AddRange(BitConverter.GetBytes(parameterStruct.Unknown2));
                mtrlBytes.AddRange(BitConverter.GetBytes(parameterStruct.TextureIndex));
            }

            mtrlBytes.AddRange(xivMtrl.AdditionalData);

            var dat = new Dat(_gameDirectory);

            dat.ImportType2Data(mtrlBytes.ToArray(), item.Name, xivMtrl.MTRLPath, item.Category);
        }
Ejemplo n.º 17
0
        /// <summary>
        /// Gets the MTRL data for the given item
        /// </summary>
        /// <remarks>
        /// It requires a race (The default is usually <see cref="XivRace.Hyur_Midlander_Male"/>)
        /// It also requires an mtrl part <see cref="GearInfo.GetPartList(IItemModel, XivRace)"/> (default is 'a')
        /// </remarks>
        /// <param name="itemModel">Item that contains model data</param>
        /// <param name="race">The race for the requested data</param>
        /// <param name="part">The Mtrl part </param>
        /// <returns></returns>
        public XivMtrl GetMtrlData(IItemModel itemModel, XivRace race, char part)
        {
            var index    = new Index(_gameDirectory);
            var dat      = new Dat(_gameDirectory);
            var itemType = ItemType.GetItemType(itemModel);

            // Get mtrl path
            var mtrlPath = GetMtrlPath(itemModel, race, part, itemType);

            // Get mtrl offset
            var mtrlOffset = index.GetDataOffset(HashGenerator.GetHash(mtrlPath.Folder), HashGenerator.GetHash(mtrlPath.File),
                                                 _dataFile);

            if (mtrlOffset == 0)
            {
                throw new Exception($"Could not find offest for {mtrlPath.Folder}/{mtrlPath.File}");
            }

            // Get uncompressed mtrl data
            var mtrlData = dat.GetType2Data(mtrlOffset, _dataFile);

            XivMtrl xivMtrl;

            using (var br = new BinaryReader(new MemoryStream(mtrlData)))
            {
                xivMtrl = new XivMtrl
                {
                    Signature            = br.ReadInt32(),
                    FileSize             = br.ReadInt16(),
                    ColorSetDataSize     = br.ReadInt16(),
                    MaterialDataSize     = br.ReadInt16(),
                    TexturePathsDataSize = br.ReadByte(),
                    Unknown             = br.ReadByte(),
                    TextureCount        = br.ReadByte(),
                    MapCount            = br.ReadByte(),
                    ColorSetCount       = br.ReadByte(),
                    Unknown1            = br.ReadByte(),
                    TextureTypePathList = new List <TexTypePath>(),
                    MTRLPath            = $"{mtrlPath.Folder}/{mtrlPath.File}"
                };

                var pathSizeList = new List <int>();

                // get the texture path offsets
                xivMtrl.TexturePathOffsetList = new List <int>(xivMtrl.TextureCount);
                for (var i = 0; i < xivMtrl.TextureCount; i++)
                {
                    xivMtrl.TexturePathOffsetList.Add(br.ReadInt16());
                    br.ReadBytes(2);

                    // add the size of the paths
                    if (i > 0)
                    {
                        pathSizeList.Add(xivMtrl.TexturePathOffsetList[i] - xivMtrl.TexturePathOffsetList[i - 1]);
                    }
                }

                // get the map path offsets
                xivMtrl.MapPathOffsetList = new List <int>(xivMtrl.MapCount);
                for (var i = 0; i < xivMtrl.MapCount; i++)
                {
                    xivMtrl.MapPathOffsetList.Add(br.ReadInt16());
                    br.ReadBytes(2);

                    // add the size of the paths
                    if (i > 0)
                    {
                        pathSizeList.Add(xivMtrl.MapPathOffsetList[i] - xivMtrl.MapPathOffsetList[i - 1]);
                    }
                    else
                    {
                        pathSizeList.Add(xivMtrl.MapPathOffsetList[i] - xivMtrl.TexturePathOffsetList[xivMtrl.TextureCount - 1]);
                    }
                }

                // get the color set offsets
                xivMtrl.ColorSetPathOffsetList = new List <int>(xivMtrl.ColorSetCount);
                for (var i = 0; i < xivMtrl.ColorSetCount; i++)
                {
                    xivMtrl.ColorSetPathOffsetList.Add(br.ReadInt16());
                    br.ReadBytes(2);

                    // add the size of the paths
                    if (i > 0)
                    {
                        pathSizeList.Add(xivMtrl.ColorSetPathOffsetList[i] - xivMtrl.ColorSetPathOffsetList[i - 1]);
                    }
                    else
                    {
                        pathSizeList.Add(xivMtrl.ColorSetPathOffsetList[i] - xivMtrl.MapPathOffsetList[xivMtrl.MapCount - 1]);
                    }
                }

                pathSizeList.Add(xivMtrl.TexturePathsDataSize - xivMtrl.ColorSetPathOffsetList[xivMtrl.ColorSetCount - 1]);

                var count = 0;

                // get the texture path strings
                xivMtrl.TexturePathList = new List <string>(xivMtrl.TextureCount);
                for (var i = 0; i < xivMtrl.TextureCount; i++)
                {
                    xivMtrl.TexturePathList.Add(Encoding.UTF8.GetString(br.ReadBytes(pathSizeList[count])).Replace("\0", ""));
                    count++;
                }

                // add the textures to the TextureTypePathList
                xivMtrl.TextureTypePathList.AddRange(GetTexNames(xivMtrl.TexturePathList, _dataFile));

                // get the map path strings
                xivMtrl.MapPathList = new List <string>(xivMtrl.MapCount);
                for (var i = 0; i < xivMtrl.MapCount; i++)
                {
                    xivMtrl.MapPathList.Add(Encoding.UTF8.GetString(br.ReadBytes(pathSizeList[count])).Replace("\0", ""));
                    count++;
                }

                // get the color set path strings
                xivMtrl.ColorSetPathList = new List <string>(xivMtrl.ColorSetCount);
                for (var i = 0; i < xivMtrl.ColorSetCount; i++)
                {
                    xivMtrl.ColorSetPathList.Add(Encoding.UTF8.GetString(br.ReadBytes(pathSizeList[count])).Replace("\0", ""));
                    count++;
                }

                // If the mtrl file contains a color set, add it to the TextureTypePathList
                if (xivMtrl.ColorSetDataSize > 0)
                {
                    var ttp = new TexTypePath
                    {
                        Path     = mtrlPath.Folder + "/" + mtrlPath.File,
                        Type     = XivTexType.ColorSet,
                        DataFile = _dataFile
                    };
                    xivMtrl.TextureTypePathList.Add(ttp);
                }

                var shaderPathSize = xivMtrl.MaterialDataSize - xivMtrl.TexturePathsDataSize;

                xivMtrl.Shader = Encoding.UTF8.GetString(br.ReadBytes(shaderPathSize)).Replace("\0", "");

                xivMtrl.Unknown2 = br.ReadInt32();

                xivMtrl.ColorSetData = new List <Half>();
                for (var i = 0; i < xivMtrl.ColorSetDataSize / 2; i++)
                {
                    xivMtrl.ColorSetData.Add(new Half(br.ReadUInt16()));
                }

                xivMtrl.AdditionalDataSize = br.ReadInt16();

                xivMtrl.DataStruct1Count = br.ReadInt16();

                xivMtrl.DataStruct2Count = br.ReadInt16();

                xivMtrl.ParameterStructCount = br.ReadInt16();

                xivMtrl.ShaderNumber = br.ReadInt16();

                xivMtrl.Unknown3 = br.ReadInt16();

                xivMtrl.DataStruct1List = new List <DataStruct1>(xivMtrl.DataStruct1Count);
                for (var i = 0; i < xivMtrl.DataStruct1Count; i++)
                {
                    xivMtrl.DataStruct1List.Add(new DataStruct1 {
                        ID = br.ReadUInt32(), Unknown1 = br.ReadUInt32()
                    });
                }

                xivMtrl.DataStruct2List = new List <DataStruct2>(xivMtrl.DataStruct2Count);
                for (var i = 0; i < xivMtrl.DataStruct2Count; i++)
                {
                    xivMtrl.DataStruct2List.Add(new DataStruct2 {
                        ID = br.ReadUInt32(), Offset = br.ReadInt16(), Size = br.ReadInt16()
                    });
                }

                xivMtrl.ParameterStructList = new List <ParameterStruct>(xivMtrl.ParameterStructCount);
                for (var i = 0; i < xivMtrl.ParameterStructCount; i++)
                {
                    xivMtrl.ParameterStructList.Add(new ParameterStruct {
                        ID = br.ReadUInt32(), Unknown1 = br.ReadInt16(), Unknown2 = br.ReadInt16(), TextureIndex = br.ReadUInt32()
                    });
                }

                xivMtrl.AdditionalData = br.ReadBytes(xivMtrl.AdditionalDataSize);
            }

            return(xivMtrl);
        }
Ejemplo n.º 18
0
        /// <summary>
        /// Retreives the raw pixel data for each texture, collated into a class to hold them.
        /// </summary>
        /// <returns>The texure map data</returns>
        private static async Task <TexMapData> GetTexMapData(Tex tex, XivMtrl mtrl)
        {
            var texMapData = new TexMapData();

            // Use the function that returns proper sane reuslts.
            var ttps = mtrl.GetTextureTypePathList();

            foreach (var ttp in ttps)
            {
                if (ttp.Type != XivTexType.ColorSet)
                {
                    var texData = await tex.GetTexData(ttp);

                    var imageData = await tex.GetImageData(texData);

                    switch (ttp.Type)
                    {
                    case XivTexType.Diffuse:
                        texMapData.Diffuse = new TexInfo {
                            Width = texData.Width, Height = texData.Height, Data = imageData
                        };
                        break;

                    case XivTexType.Specular:
                    case XivTexType.Multi:
                    case XivTexType.Skin:
                        texMapData.Specular = new TexInfo {
                            Width = texData.Width, Height = texData.Height, Data = imageData
                        };;
                        break;

                    case XivTexType.Normal:
                        texMapData.Normal = new TexInfo {
                            Width = texData.Width, Height = texData.Height, Data = imageData
                        };;
                        break;

                    default:
                        // Do not render textures that we do not know how to use
                        break;
                    }
                }
            }

            if (mtrl.ColorSetDataSize > 0)
            {
                var colorSetData = new List <byte>();
                foreach (var half in mtrl.ColorSetData)
                {
                    var colorByte = (byte)(half * 255);

                    if (half > 1)
                    {
                        colorByte = 255;
                    }

                    colorSetData.Add(colorByte);
                }

                texMapData.ColorSet = new TexInfo {
                    Width = 4, Height = 16, Data = colorSetData.ToArray()
                };;
            }

            return(texMapData);
        }
Ejemplo n.º 19
0
        /// <summary>
        /// Gets the texture maps for the model
        /// </summary>
        /// <returns>The texture maps in byte arrays inside a ModelTextureData class</returns>
        public static async Task <ModelTextureData> GetModelMaps(Tex tex, XivMtrl mtrl, CustomModelColors colors = null)
        {
            // Use static values as needed.
            if (colors == null)
            {
                colors = GetCustomColors();
            }

            var shaderInfo = mtrl.GetShaderInfo();
            var mtrlMaps   = mtrl.GetAllMapInfos();

            var texMapData = await GetTexMapData(tex, mtrl);

            var dimensions = await EqualizeTextureSizes(texMapData);

            var diffuseMap  = new List <byte>();
            var normalMap   = new List <byte>();
            var specularMap = new List <byte>();
            var emissiveMap = new List <byte>();
            var alphaMap    = new List <byte>();

            var diffuseColorList  = new List <Color>();
            var specularColorList = new List <Color>();
            var emissiveColorList = new List <Color>();

            byte[] diffusePixels = null, specularPixels = null, normalPixels = null;

            if (texMapData.Normal != null)
            {
                normalPixels = texMapData.Normal.Data;
            }

            if (texMapData.Diffuse != null)
            {
                diffusePixels = texMapData.Diffuse.Data;
            }

            if (texMapData.Specular != null)
            {
                specularPixels = texMapData.Specular.Data;
            }

            if (normalPixels == null && diffusePixels == null)
            {
                // This material doesn't actually have any readable data.

                var empty = new ModelTextureData
                {
                    Width        = 0,
                    Height       = 0,
                    Normal       = new byte[0],
                    Diffuse      = new byte[0],
                    Specular     = new byte[0],
                    Emissive     = new byte[0],
                    Alpha        = new byte[0],
                    MaterialPath = mtrl.MTRLPath.Substring(mtrl.MTRLPath.LastIndexOf('/'))
                };
                return(empty);
            }

            var dataLength = normalPixels != null ? normalPixels.Length : diffusePixels.Length;

            await Task.Run(() =>
            {
                for (var i = 3; i < dataLength; i += 4)
                {
                    // Load the individual pixels into memory.
                    Color baseNormalColor   = new Color(127, 127, 255, 255);
                    Color baseDiffuseColor  = new Color(255, 255, 255, 255);
                    Color baseSpecularColor = new Color(255, 255, 255, 255);


                    if (normalPixels != null)
                    {
                        baseNormalColor = new Color(normalPixels[i - 3], normalPixels[i - 2], normalPixels[i - 1], normalPixels[i]);
                    }

                    if (diffusePixels != null)
                    {
                        baseDiffuseColor = new Color(diffusePixels[i - 3], diffusePixels[i - 2], diffusePixels[i - 1], diffusePixels[i]);
                    }

                    if (specularPixels != null)
                    {
                        baseSpecularColor = new Color(specularPixels[i - 3], specularPixels[i - 2], specularPixels[i - 1], specularPixels[i]);
                    }

                    byte colorsetValue = baseNormalColor.A;

                    // Calculate real colors from the inputs and shader.
                    Color normalColor, diffuseColor, specularColor;
                    byte opacity;
                    ComputeShaderColors(colors, shaderInfo, baseNormalColor, baseDiffuseColor, baseSpecularColor, out normalColor, out diffuseColor, out specularColor, out opacity);
                    Color alphaColor = new Color(opacity, opacity, opacity, opacity);

                    // Apply colorset if needed.  (This could really be baked into ComputeShaderColors)
                    Color emissiveColor = new Color(0, 0, 0, 0);
                    if (mtrl.ColorSetData.Count > 0)
                    {
                        var cs = texMapData.ColorSet.Data;
                        Color finalDiffuseColor, finalSpecularColor;
                        ComputeColorsetBlending(mtrl, colorsetValue, cs, diffuseColor, specularColor, out finalDiffuseColor, out finalSpecularColor, out emissiveColor);
                        diffuseColor  = finalDiffuseColor;
                        specularColor = finalSpecularColor;
                    }

                    // White out the opacity channels where appropriate.
                    diffuseColor.A  = opacity;
                    specularColor.A = 255;
                    normalColor.A   = 255;


                    diffuseMap.AddRange(BitConverter.GetBytes(diffuseColor.ToRgba()));
                    specularMap.AddRange(BitConverter.GetBytes(specularColor.ToRgba()));
                    emissiveMap.AddRange(BitConverter.GetBytes(emissiveColor.ToRgba()));
                    alphaMap.AddRange(BitConverter.GetBytes(alphaColor.ToRgba()));
                    normalMap.AddRange(BitConverter.GetBytes(normalColor.ToRgba()));
                }
            });

            var modelTextureData = new ModelTextureData
            {
                Width        = dimensions.Width,
                Height       = dimensions.Height,
                Normal       = normalMap.ToArray(),
                Diffuse      = diffuseMap.ToArray(),
                Specular     = specularMap.ToArray(),
                Emissive     = emissiveMap.ToArray(),
                Alpha        = alphaMap.ToArray(),
                MaterialPath = mtrl.MTRLPath.Substring(mtrl.MTRLPath.LastIndexOf('/'))
            };

            return(modelTextureData);
        }
 private void CopyMaterialButton_Click(object sender, RoutedEventArgs e)
 {
     _copiedMaterial = _material;
     PasteMaterialButton.IsEnabled = true;
 }
Ejemplo n.º 21
0
        /// <summary>
        /// Creates an MTRL file
        /// </summary>
        /// <param name="xivMtrl">The XivMtrl containing the mtrl data</param>
        /// <param name="item">The item</param>
        /// <returns>The new mtrl file byte data</returns>
        public byte[] CreateMtrlFile(XivMtrl xivMtrl, IItem item)
        {
            var mtrlBytes = new List <byte>();

            mtrlBytes.AddRange(BitConverter.GetBytes(xivMtrl.Signature));
            mtrlBytes.AddRange(BitConverter.GetBytes(xivMtrl.FileSize));
            mtrlBytes.AddRange(BitConverter.GetBytes(xivMtrl.ColorSetDataSize));
            mtrlBytes.AddRange(BitConverter.GetBytes(xivMtrl.MaterialDataSize));
            mtrlBytes.AddRange(BitConverter.GetBytes(xivMtrl.TexturePathsDataSize));
            mtrlBytes.Add(xivMtrl.TextureCount);
            mtrlBytes.Add(xivMtrl.MapCount);
            mtrlBytes.Add(xivMtrl.ColorSetCount);
            mtrlBytes.Add(xivMtrl.UnknownDataSize);

            for (int i = 0; i < xivMtrl.TexturePathOffsetList.Count; i++)
            {
                mtrlBytes.AddRange(BitConverter.GetBytes((short)xivMtrl.TexturePathOffsetList[i]));
                mtrlBytes.AddRange(BitConverter.GetBytes((short)xivMtrl.TexturePathUnknownList[i]));
            }

            for (int i = 0; i < xivMtrl.MapPathOffsetList.Count; i++)
            {
                mtrlBytes.AddRange(BitConverter.GetBytes((short)xivMtrl.MapPathOffsetList[i]));
                mtrlBytes.AddRange(BitConverter.GetBytes((short)xivMtrl.MapPathUnknownList[i]));
            }

            for (int i = 0; i < xivMtrl.ColorSetPathOffsetList.Count; i++)
            {
                mtrlBytes.AddRange(BitConverter.GetBytes((short)xivMtrl.ColorSetPathOffsetList[i]));
                mtrlBytes.AddRange(BitConverter.GetBytes((short)xivMtrl.ColorSetPathUnknownList[i]));
            }

            var pathStringList = new List <byte>();

            foreach (var texPathString in xivMtrl.TexturePathList)
            {
                pathStringList.AddRange(Encoding.UTF8.GetBytes(texPathString));
                pathStringList.Add(0);
            }

            foreach (var mapPathString in xivMtrl.MapPathList)
            {
                pathStringList.AddRange(Encoding.UTF8.GetBytes(mapPathString));
                pathStringList.Add(0);
            }

            foreach (var colorSetPathString in xivMtrl.ColorSetPathList)
            {
                pathStringList.AddRange(Encoding.UTF8.GetBytes(colorSetPathString));
                pathStringList.Add(0);
            }

            pathStringList.AddRange(Encoding.UTF8.GetBytes(xivMtrl.Shader));
            pathStringList.Add(0);

            var paddingSize = xivMtrl.MaterialDataSize - pathStringList.Count;

            pathStringList.AddRange(new byte[paddingSize]);

            mtrlBytes.AddRange(pathStringList);

            mtrlBytes.AddRange(xivMtrl.Unknown2);

            foreach (var colorSetHalf in xivMtrl.ColorSetData)
            {
                mtrlBytes.AddRange(BitConverter.GetBytes(colorSetHalf.RawValue));
            }

            if (xivMtrl.ColorSetDataSize == 544)
            {
                mtrlBytes.AddRange(xivMtrl.ColorSetExtraData);
            }

            mtrlBytes.AddRange(BitConverter.GetBytes(xivMtrl.AdditionalDataSize));
            mtrlBytes.AddRange(BitConverter.GetBytes(xivMtrl.DataStruct1Count));
            mtrlBytes.AddRange(BitConverter.GetBytes(xivMtrl.DataStruct2Count));
            mtrlBytes.AddRange(BitConverter.GetBytes(xivMtrl.ParameterStructCount));
            mtrlBytes.AddRange(BitConverter.GetBytes(xivMtrl.ShaderNumber));
            mtrlBytes.AddRange(BitConverter.GetBytes(xivMtrl.Unknown3));

            foreach (var dataStruct1 in xivMtrl.DataStruct1List)
            {
                mtrlBytes.AddRange(BitConverter.GetBytes(dataStruct1.ID));
                mtrlBytes.AddRange(BitConverter.GetBytes(dataStruct1.Unknown1));
            }

            foreach (var dataStruct2 in xivMtrl.DataStruct2List)
            {
                mtrlBytes.AddRange(BitConverter.GetBytes(dataStruct2.ID));
                mtrlBytes.AddRange(BitConverter.GetBytes(dataStruct2.Offset));
                mtrlBytes.AddRange(BitConverter.GetBytes(dataStruct2.Size));
            }

            foreach (var parameterStruct in xivMtrl.ParameterStructList)
            {
                mtrlBytes.AddRange(BitConverter.GetBytes(parameterStruct.ID));
                mtrlBytes.AddRange(BitConverter.GetBytes(parameterStruct.Unknown1));
                mtrlBytes.AddRange(BitConverter.GetBytes(parameterStruct.Unknown2));
                mtrlBytes.AddRange(BitConverter.GetBytes(parameterStruct.TextureIndex));
            }

            mtrlBytes.AddRange(xivMtrl.AdditionalData);

            return(mtrlBytes.ToArray());
        }
        /// <summary>
        /// Sets the material and selects a given row (or row 0)
        /// </summary>
        /// <param name="mtrl"></param>
        /// <param name="row"></param>
        /// <returns></returns>
        public async Task SetMaterial(XivMtrl mtrl, int row = 0)
        {
            if (mtrl == null)
            {
                return;
            }

            _LOADING = true;


            var   appStyle = ThemeManager.DetectAppStyle(Application.Current);
            Brush bgBrush  = MainWindow.GetMainWindow().Background;
            Brush fgBrush  = MainWindow.GetMainWindow().Foreground;


            DiffuseColorPicker.Background  = bgBrush;
            DiffuseColorPicker.Foreground  = fgBrush;
            SpecularColorPicker.Background = bgBrush;
            SpecularColorPicker.Foreground = fgBrush;
            EmissiveColorPicker.Background = bgBrush;
            EmissiveColorPicker.Foreground = fgBrush;

            DiffuseColorPicker.DropDownBackground = bgBrush;
            DiffuseColorPicker.HeaderForeground   = fgBrush;
            DiffuseColorPicker.TabForeground      = fgBrush;
            DiffuseColorPicker.TabBackground      = bgBrush;
            DiffuseColorPicker.HeaderBackground   = bgBrush;

            SpecularColorPicker.DropDownBackground = bgBrush;
            SpecularColorPicker.HeaderForeground   = fgBrush;
            SpecularColorPicker.TabForeground      = fgBrush;
            SpecularColorPicker.TabBackground      = bgBrush;
            SpecularColorPicker.HeaderBackground   = bgBrush;

            EmissiveColorPicker.DropDownBackground = bgBrush;
            EmissiveColorPicker.HeaderForeground   = fgBrush;
            EmissiveColorPicker.TabForeground      = fgBrush;
            EmissiveColorPicker.TabBackground      = bgBrush;
            EmissiveColorPicker.HeaderBackground   = bgBrush;

            try
            {
                DyeTemplateFile = await STM.GetStainingTemplateFile(false);

                DyeTemplateCollection.Clear();

                DyePreviewIdBox.SelectedValue = -1;

                var keys = DyeTemplateFile.GetKeys();
                DyeTemplateCollection.Add(new KeyValuePair <ushort, string>(0, "Undyable"));
                foreach (var key in keys)
                {
                    DyeTemplateCollection.Add(new KeyValuePair <ushort, string>(key, key.ToString()));
                }

                if (CopiedRow == null)
                {
                    PasteRowButton.IsEnabled = false;
                }
                else
                {
                    PasteRowButton.IsEnabled = true;
                }

                var dyes = await STM.GetDyeNames();

                PreviewDyeCollection.Clear();
                PreviewDyeCollection.Add(new KeyValuePair <int, string>(-1, "Undyed"));
                for (ushort i = 0; i < 128; i++)
                {
                    var name = "Dye " + i.ToString();
                    if (dyes.ContainsKey(i))
                    {
                        name = dyes[i];
                    }
                    PreviewDyeCollection.Add(new KeyValuePair <int, string>(i, name));
                }
                DyePreviewIdBox.SelectedValue = -1;

                _mtrl = mtrl;
                await _vm.SetMaterial(_mtrl, DyeTemplateFile);
                await SetRow(row);

                for (int i = 0; i < 16; i++)
                {
                    await UpdateRowVisual(i);
                }
            } catch (Exception ex)
            {
                FlexibleMessageBox.Show("Unable to load material into colorset editor.\n\nError: " + ex.Message, "Colorset Editor Error", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Warning);
            }
            _LOADING = false;
        }
Ejemplo n.º 23
0
        /// <summary>
        /// Imports a ColorSet file
        /// </summary>
        /// <param name="xivMtrl">The XivMtrl data of the original</param>
        /// <param name="ddsFileDirectory">The dds directory of the new ColorSet</param>
        /// <param name="item">The item</param>
        /// <param name="source">The source importing the file</param>
        /// <returns>The new offset</returns>
        public async Task <int> TexColorImporter(XivMtrl xivMtrl, DirectoryInfo ddsFileDirectory, IItem item, string source, XivLanguage lang)
        {
            var colorSetData = new List <Half>();

            byte[] colorSetExtraData = null;

            using (var br = new BinaryReader(File.OpenRead(ddsFileDirectory.FullName)))
            {
                // Check DDS type
                br.BaseStream.Seek(84, SeekOrigin.Begin);

                var          texType = br.ReadInt32();
                XivTexFormat textureType;

                if (DDSType.ContainsKey(texType))
                {
                    textureType = DDSType[texType];
                }
                else
                {
                    throw new Exception($"DDS Type ({texType}) not recognized. Expecting A16B16G16R16F.");
                }

                if (textureType != XivTexFormat.A16B16G16R16F)
                {
                    throw new Exception($"Incorrect file type. Expected: A16B16G16R16F  Given: {textureType}");
                }

                // Skip past rest of the DDS header
                br.BaseStream.Seek(128, SeekOrigin.Begin);

                // color data is always 512 (4w x 16h = 64 x 8bpp = 512)
                // this reads 256 ushort values which is 256 x 2 = 512
                for (var i = 0; i < 256; i++)
                {
                    colorSetData.Add(new Half(br.ReadUInt16()));
                }
            }

            // If the colorset size is 544, it contains extra data that must be imported
            if (xivMtrl.ColorSetDataSize == 544)
            {
                var flagsPath = Path.Combine(Path.GetDirectoryName(ddsFileDirectory.FullName), (Path.GetFileNameWithoutExtension(ddsFileDirectory.FullName) + ".dat"));

                if (File.Exists(flagsPath))
                {
                    // The extra data after the colorset is always 32 bytes
                    // This reads 16 ushort values which is 16 x 2 = 32
                    colorSetExtraData = File.ReadAllBytes(flagsPath);

                    // If for whatever reason there is a .dat file but it's missing data
                    if (colorSetExtraData.Length != 32)
                    {
                        // Set all dye modifiers to 0 (undyeable)
                        colorSetExtraData = new byte[32];
                    }
                }
                else
                {
                    // If .dat file is missing set all values to 0 (undyeable)
                    colorSetExtraData = new byte[32];
                }
            }

            // Replace the color set data with the imported data
            xivMtrl.ColorSetData      = colorSetData;
            xivMtrl.ColorSetExtraData = colorSetExtraData;

            var mtrl = new Mtrl(_gameDirectory, xivMtrl.TextureTypePathList[0].DataFile, lang);

            return(await mtrl.ImportMtrl(xivMtrl, item, source));
        }