Exemplo n.º 1
0
        private async void ShowPaths(object sender, RoutedEventArgs e)
        {
            var entry = _metadata.ImcEntries[(int)ImcVariantBox.SelectedItem];

            var paths = new List <(string title, string path)>();

            var mtrl   = new Mtrl(XivCache.GameInfo.GameDirectory);
            var folder = mtrl.GetMtrlFolder(_metadata.Root.Info, entry.MaterialSet) + "/";

            paths.Add(("Material Folder", folder));

            if (entry.Vfx > 0)
            {
                var pair = await ATex.GetVfxPath(_metadata.Root.Info, entry.Vfx);

                paths.Add(("VFX File Path", pair.Folder + "/" + pair.File));
            }
            else
            {
                paths.Add(("VFX File Path", "--"));
            }


            var wind = new PathDisplay(paths);

            wind.Show();
        }
Exemplo n.º 2
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));
        }
        /// <summary>
        /// The event handler for the add custom texture button clicked
        /// </summary>
        private async void AddCustomTextureButton_Click(object sender, RoutedEventArgs e)
        {
            var selectedItem = TextureMapComboBox.SelectedItem as ModComboBox;

            var mod = selectedItem.SelectedMod;

            byte[] modData;

            var includedMod = new IncludedMods
            {
                Name     = $"{Path.GetFileNameWithoutExtension(mod.fullPath)} ({((Category)ModListTreeView.SelectedItem).Name})",
                FullPath = mod.fullPath
            };

            var includedModsList = IncludedModsList.Items.Cast <IncludedMods>().ToList();

            var tex = new Tex(_gameDirectory);

            var ddsDirectory = new DirectoryInfo(CustomTextureTextBox.Text);

            if (selectedItem.TexTypePath.Type == XivTexType.ColorSet)
            {
                var mtrl = new Mtrl(_gameDirectory, XivDataFiles.GetXivDataFile(mod.datFile), GetLanguage());

                var xivMtrl = await mtrl.GetMtrlData(mod.data.modOffset, mod.fullPath, int.Parse(Settings.Default.DX_Version));

                modData = tex.DDStoMtrlData(xivMtrl, ddsDirectory, ((Category)ModListTreeView.SelectedItem).Item, GetLanguage());
            }
            else
            {
                var texData = await tex.GetTexData(selectedItem.TexTypePath);

                modData = await tex.DDStoTexData(texData, ((Category)ModListTreeView.SelectedItem).Item, ddsDirectory);
            }

            if (includedModsList.Any(item => item.Name.Equals(includedMod.Name)))
            {
                if (FlexibleMessageBox.Show(
                        string.Format(UIMessages.ExistingOption, includedMod.Name),
                        UIMessages.OverwriteTitle, MessageBoxButtons.YesNo, MessageBoxIcon.Question) ==
                    System.Windows.Forms.DialogResult.Yes)
                {
                    _selectedModOption.Mods[mod.fullPath].ModDataBytes = modData;
                }
            }
            else
            {
                IncludedModsList.Items.Add(includedMod);
                _selectedModOption.Mods.Add(mod.fullPath, new ModData
                {
                    Name         = mod.name,
                    Category     = mod.category,
                    FullPath     = mod.fullPath,
                    ModDataBytes = modData
                });
            }
        }
Exemplo n.º 4
0
        private static string UpdateFileName(XivDependencyRoot Source, XivDependencyRoot Destination, string path)
        {
            var file = Path.GetFileName(path);

            if (Destination.Info.PrimaryType == XivItemType.human && Destination.Info.SecondaryType == XivItemType.hair && Path.GetExtension(path) == ".mtrl")
            {
                var hairRoot = Mtrl.GetHairMaterialRoot(Destination.Info);

                // Force replace the root information to the correct one for this target hair.
                var raceReplace = new Regex("^mt_c[0-9]{4}h[0-9]{4}");
                file = raceReplace.Replace(file, "mt_c" + hairRoot.PrimaryId.ToString().PadLeft(4, '0') + "h" + hairRoot.SecondaryId.ToString().PadLeft(4, '0'));

                // Jam in a suffix into the MTRL to make it unique/non-colliding.
                var initialPartRex = new Regex("^(mt_c[0-9]{4}h[0-9]{4})(?:_c[0-9]{4})?(.+)$");
                var m = initialPartRex.Match(file);

                // ???
                if (!m.Success)
                {
                    return(file);
                }

                file = m.Groups[1].Value + "_c" + Destination.Info.PrimaryId.ToString().PadLeft(4, '0') + m.Groups[2].Value;
                return(file);
            }

            var rex   = new Regex("[a-z][0-9]{4}([a-z][0-9]{4})");
            var match = rex.Match(file);

            if (!match.Success)
            {
                return(file);
            }

            if (Source.Info.SecondaryType == null)
            {
                // Equipment/Accessory items. Only replace the back half of the file names.
                var srcString = match.Groups[1].Value;
                var dstString = Destination.Info.GetBaseFileName(false);

                file = file.Replace(srcString, dstString);
            }
            else
            {
                // Replace the entire root chunk for roots that have two identifiers.
                var srcString = match.Groups[0].Value;
                var dstString = Destination.Info.GetBaseFileName(false);

                file = file.Replace(srcString, dstString);
            }

            return(file);
        }
Exemplo 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));
        }
Exemplo n.º 6
0
        private static string UpdateFolder(XivDependencyRoot Source, XivDependencyRoot Destination, string path)
        {
            if (Destination.Info.PrimaryType == XivItemType.human && Destination.Info.SecondaryType == XivItemType.hair && Path.GetExtension(path) == ".mtrl")
            {
                var hairRoot = Mtrl.GetHairMaterialRoot(Destination.Info);

                // Force the race code to the appropriate one.
                var raceReplace = new Regex("/c[0-9]{4}");
                path = raceReplace.Replace(path, "/c" + hairRoot.PrimaryId.ToString().PadLeft(4, '0'));

                var hairReplace = new Regex("/h[0-9]{4}");
                path = hairReplace.Replace(path, "/h" + hairRoot.SecondaryId.ToString().PadLeft(4, '0'));

                // Hairs between 115 and 200 have forced material path sharing enabled.
                path = Path.GetDirectoryName(path);
                path = path.Replace('\\', '/');
                return(path);
            }

            // So first off, just copy anything from the old root folder to the new one.
            var match = RemoveRootPathRegex.Match(path);

            if (match.Success)
            {
                // The item existed in an old root path, so we can just clone the same post-root path into the new root folder.
                var afterRootPath = match.Groups[1].Value;
                path = Destination.Info.GetRootFolder() + afterRootPath;
                path = Path.GetDirectoryName(path);
                path = path.Replace('\\', '/');
                return(path);
            }

            // Okay, stuff at this point didn't actually exist in any root path, and didn't exist in the common path either.
            // Just copy this crap into our root folder.

            // The only way we can really get here is if some mod author created textures in a totally arbitrary path.
            path = Path.GetDirectoryName(Destination.Info.GetRootFolder());
            path = path.Replace('\\', '/');
            return(path);
        }
Exemplo n.º 7
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));
        }
        /// <summary>
        /// Saves the material to file.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void SaveButton_Click(object sender, RoutedEventArgs e)
        {
            var mw = MainWindow.GetMainWindow();
            await mw.LockUi();

            try
            {
                var mtrlLib = new Mtrl(XivCache.GameInfo.GameDirectory);

                var item = mw.GetSelectedItem();
                await mtrlLib.ImportMtrl(_mtrl, item, XivStrings.TexTools);

                MaterialSaved.Invoke(this, null);
            }
            catch (Exception ex)
            {
                FlexibleMessageBox.Show("Unable to save Material.\n\nError: " + ex.Message, "Material Save Error", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
                return;
            }
            finally
            {
                await mw.UnlockUi();
            }
        }
        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);
        }
Exemplo n.º 10
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 Dictionary <int, ModelTextureData> GetMaterials(
            DirectoryInfo gameDirectory, IItemModel item, XivMdl mdlData, XivRace race)
        {
            var      textureDataDictionary = new Dictionary <int, ModelTextureData>();
            var      mtrlDictionary        = new Dictionary <int, XivMtrl>();
            var      mtrl                 = new Mtrl(gameDirectory, item.DataFile);
            var      mtrlFilePaths        = mdlData.PathData.MaterialList;
            var      hasColorChangeShader = false;
            Color?   customColor          = null;
            WinColor winColor;

            var materialNum = 0;

            foreach (var mtrlFilePath in mtrlFilePaths)
            {
                var mtrlItem = new XivGenericItemModel
                {
                    Category        = item.Category,
                    ItemCategory    = item.ItemCategory,
                    ItemSubCategory = item.ItemSubCategory,
                    ModelInfo       = new XivModelInfo
                    {
                        Body      = item.ModelInfo.Body,
                        ModelID   = item.ModelInfo.ModelID,
                        ModelType = item.ModelInfo.ModelType,
                        Variant   = item.ModelInfo.Variant
                    },
                    Name = item.Name
                };

                var modelID  = mtrlItem.ModelInfo.ModelID;
                var bodyID   = mtrlItem.ModelInfo.Body;
                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
                    {
                        Category     = XivStrings.Character,
                        ItemCategory = XivStrings.Body,
                        Name         = XivStrings.Body,
                        ModelInfo    = new XivModelInfo
                        {
                            Body = int.Parse(body)
                        }
                    };

                    winColor    = (WinColor)ColorConverter.ConvertFromString(Settings.Default.Skin_Color);
                    customColor = new 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
                    {
                        Category     = XivStrings.Character,
                        ItemCategory = XivStrings.Face,
                        Name         = XivStrings.Face,
                        ModelInfo    = new XivModelInfo
                        {
                            Body = 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
                    {
                        Category     = XivStrings.Character,
                        ItemCategory = XivStrings.Hair,
                        Name         = XivStrings.Hair,
                        ModelInfo    = new XivModelInfo
                        {
                            Body = bodyID
                        }
                    };

                    winColor    = (WinColor)ColorConverter.ConvertFromString(Settings.Default.Hair_Color);
                    customColor = new 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
                    {
                        Category     = XivStrings.Character,
                        ItemCategory = XivStrings.Tail,
                        Name         = XivStrings.Tail,
                        ModelInfo    = new XivModelInfo
                        {
                            Body = bodyID
                        }
                    };

                    winColor    = (WinColor)ColorConverter.ConvertFromString(Settings.Default.Hair_Color);
                    customColor = new 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.ModelID = 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.ModelID = 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.ModelID = modelID;
                    mtrlItem.ModelInfo.Body    = 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.ModelID = modelID;
                    mtrlItem.ModelInfo.Body    = 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.ModelID = modelID;
                    mtrlItem.ModelInfo.Body    = bodyID;
                    break;

                default:
                    break;
                }

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

                var     mtrlFile = filePath.Remove(0, 1);
                XivMtrl mtrlData;
                try
                {
                    mtrlData = mtrl.GetMtrlData(mtrlItem, race, mtrlFile, dxVersion);
                }
                catch (Exception)
                {
                    if (mtrlItem.ModelInfo.ModelID == item.ModelInfo.ModelID)
                    {
                        throw;
                    }

                    // Fall back to material data from the primary model.
                    mtrlData = mtrl.GetMtrlData(item, race, mtrlFile, dxVersion);
                }


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

                mtrlDictionary.Add(materialNum, mtrlData);

                materialNum++;
            }

            foreach (var xivMtrl in mtrlDictionary)
            {
                var modelTexture = new ModelTexture(gameDirectory, xivMtrl.Value);

                if (hasColorChangeShader)
                {
                    var modelMaps = modelTexture.GetModelMaps(null, true);

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

                        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 Color(winColor.R, winColor.G, winColor.B, winColor.A);
                    }

                    var modelMaps = modelTexture.GetModelMaps(customColor);

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

            return(textureDataDictionary);
        }
Exemplo n.º 11
0
        public async Task AsyncInit()
        {
            var root = _item.GetRoot();

            if (root == null)
            {
                return;
            }

            var gd   = XivCache.GameInfo.GameDirectory;
            var lang = XivCache.GameInfo.GameLanguage;
            var df   = IOUtil.GetDataFileFromPath(root.Info.GetRootFile());

            var _index    = new Index(gd);
            var _mtrl     = new Mtrl(XivCache.GameInfo.GameDirectory);
            var _mdl      = new Mdl(gd, df);
            var _imc      = new Imc(gd);
            var raceRegex = new Regex("c([0-9]{4})[^b]");

            ItemNameBox.Text = _item.Name;

            var setName = root.Info.GetBaseFileName(false);

            SetLabel.Text = "Set: " + setName;

            if (!String.IsNullOrWhiteSpace(root.Info.Slot))
            {
                var niceSlot = Mdl.SlotAbbreviationDictionary.FirstOrDefault(x => x.Value == root.Info.Slot);
                if (niceSlot.Key != null)
                {
                    SlotLabel.Text = "Slot: " + niceSlot.Key + " (" + root.Info.Slot + ")";
                }
                else
                {
                    SlotLabel.Text = "Slot: Unknown (" + root.Info.Slot + ")";
                }
            }
            else
            {
                SlotLabel.Text = "Slot: --";
            }

            var usesImc = Imc.UsesImc(_item);

            if (usesImc)
            {
                VariantLabel.Text = "Variant: " + _item.ModelInfo.ImcSubsetID;
            }
            else
            {
                VariantLabel.Text = "Variant: --";
            }

            var mSet = await _imc.GetMaterialSetId(_item);

            if (mSet > 0)
            {
                MaterialSetLabel.Text = "Material Set: " + mSet;
            }
            else
            {
                MaterialSetLabel.Text = "Material Set: --";
            }

            var races = XivRaces.PlayableRaces;

            var models = await root.GetModelFiles();

            var materials = await root.GetMaterialFiles(mSet);

            #region Race Chart
            var rowIdx = 1;
            foreach (var race in races)
            {
                var rCode = race.GetRaceCode();

                var row = new RowDefinition();
                row.Height = new GridLength(30);
                RacialGrid.RowDefinitions.Add(row);

                var lBase = new Label();
                lBase.Content = race.GetDisplayName();
                lBase.SetValue(Grid.RowProperty, rowIdx);

                RacialGrid.Children.Add(lBase);

                XivRace?usedMdlRace = race;

                string usedMdl = null;;
                if (race != XivRace.All_Races)
                {
                    // Check if the race has a model.
                    var mdl = models.FirstOrDefault(x => x.Contains("c" + rCode));
                    if (mdl == null)
                    {
                        // Gotta see which race they're shared from.
                        var node   = XivRaceTree.GetNode(race);
                        var parent = node.Parent;

                        while (parent != null)
                        {
                            var code = parent.Race.GetRaceCode();
                            mdl = models.FirstOrDefault(x => x.Contains("c" + code));
                            if (mdl != null)
                            {
                                usedMdlRace = parent.Race;
                                usedMdl     = mdl;
                                break;
                            }
                            parent = parent.Parent;
                        }

                        if (mdl == null)
                        {
                            // No model exists for this item.
                            usedMdlRace = null;
                        }
                    }
                    else
                    {
                        usedMdl = mdl;
                    }
                }

                var mdlRaceString = "None";
                if (usedMdlRace == race)
                {
                    mdlRaceString = "Own";
                }
                else
                {
                    if (usedMdlRace != null)
                    {
                        mdlRaceString = ((XivRace)usedMdlRace).GetDisplayName();
                    }
                }

                XivRace?usedMtrlRace = usedMdlRace;
                if (race != XivRace.All_Races)
                {
                    if (usedMdlRace == null)
                    {
                        usedMtrlRace = null;
                    }
                    else
                    {
                        // Get the materials used by this racial's model.
                        var mdl          = usedMdl;
                        var mdlMaterials = await XivCache.GetChildFiles(mdl);

                        var mtrl = mdlMaterials.FirstOrDefault(x => raceRegex.IsMatch(x));

                        if (mtrl == null)
                        {
                            usedMtrlRace = null;
                        }
                        else
                        {
                            var code = raceRegex.Match(mtrl).Groups[1].Value;
                            usedMtrlRace = XivRaces.GetXivRace(code);
                            if (usedMtrlRace == XivRace.All_Races)
                            {
                                usedMtrlRace = null;
                            }
                        }
                    }
                }

                var mtrlRaceString = "None";
                if (usedMtrlRace == race)
                {
                    mtrlRaceString = "Own";
                }
                else
                {
                    if (usedMtrlRace != null)
                    {
                        mtrlRaceString = ((XivRace)usedMtrlRace).GetDisplayName();
                    }
                }

                var lMdl = new Label();
                lMdl.Content = mdlRaceString;
                lMdl.SetValue(Grid.RowProperty, rowIdx);
                lMdl.SetValue(Grid.ColumnProperty, 1);
                RacialGrid.Children.Add(lMdl);

                var lMtrl = new Label();
                lMtrl.Content = mtrlRaceString;
                lMtrl.SetValue(Grid.RowProperty, rowIdx);
                lMtrl.SetValue(Grid.ColumnProperty, 2);
                RacialGrid.Children.Add(lMtrl);


                rowIdx++;
            }
            #endregion


            if (Imc.UsesImc(_item) && _item.ModelInfo != null)
            {
                var myImcSubsetId = _item.ModelInfo.ImcSubsetID;
                var allItems      = await root.GetAllItems();

                var fInfo = await _imc.GetFullImcInfo(_item);

                var entries = fInfo.GetAllEntries(_item.GetItemSlotAbbreviation(), true);

                foreach (var item in allItems)
                {
                    SameModelItems.Add(new KeyValuePair <string, IItem>(item.Name, item));
                    if (entries.Count > item.ModelInfo.ImcSubsetID)
                    {
                        var imSet = entries[item.ModelInfo.ImcSubsetID].MaterialSet;

                        if (mSet == imSet)
                        {
                            SameMSetItems.Add(new KeyValuePair <string, IItem>(item.Name, item));
                        }
                    }
                    if (item.ModelInfo.ImcSubsetID == myImcSubsetId)
                    {
                        SameVariantItems.Add(new KeyValuePair <string, IItem>(item.Name, item));
                    }
                }
            }
        }
Exemplo n.º 12
0
        /// <summary>
        /// Copies the entirety of a given root to a new root.
        /// </summary>
        /// <param name="Source">Original Root to copy from.</param>
        /// <param name="Destination">Destination root to copy to.</param>
        /// <param name="ApplicationSource">Application to list as the source for the resulting mod entries.</param>
        /// <returns>Returns a Dictionary of all the file conversion</returns>
        public static async Task <Dictionary <string, string> > CloneRoot(XivDependencyRoot Source, XivDependencyRoot Destination, string ApplicationSource, int singleVariant = -1, string saveDirectory = null, IProgress <string> ProgressReporter = null, IndexFile index = null, ModList modlist = null, ModPack modPack = null)
        {
            if (!IsSupported(Source) || !IsSupported(Destination))
            {
                throw new InvalidDataException("Cannot clone unsupported root.");
            }


            if (ProgressReporter != null)
            {
                ProgressReporter.Report("Stopping Cache Worker...");
            }
            var workerStatus = XivCache.CacheWorkerEnabled;

            XivCache.CacheWorkerEnabled = false;
            try
            {
                var df = IOUtil.GetDataFileFromPath(Source.ToString());

                var _imc     = new Imc(XivCache.GameInfo.GameDirectory);
                var _mdl     = new Mdl(XivCache.GameInfo.GameDirectory, df);
                var _dat     = new Dat(XivCache.GameInfo.GameDirectory);
                var _index   = new Index(XivCache.GameInfo.GameDirectory);
                var _mtrl    = new Mtrl(XivCache.GameInfo.GameDirectory);
                var _modding = new Modding(XivCache.GameInfo.GameDirectory);

                var doSave = false;
                if (index == null)
                {
                    doSave = true;
                    index  = await _index.GetIndexFile(df);

                    modlist = await _modding.GetModListAsync();
                }


                bool locked = _index.IsIndexLocked(df);
                if (locked)
                {
                    throw new Exception("Game files currently in use.");
                }


                if (ProgressReporter != null)
                {
                    ProgressReporter.Report("Analyzing items and variants...");
                }

                // First, try to get everything, to ensure it's all valid.
                ItemMetadata originalMetadata = await GetCachedMetadata(index, modlist, Source, df, _dat);


                var originalModelPaths = await Source.GetModelFiles(index, modlist);

                var originalMaterialPaths = await Source.GetMaterialFiles(-1, index, modlist);

                var originalTexturePaths = await Source.GetTextureFiles(-1, index, modlist);

                var originalVfxPaths = new HashSet <string>();
                if (Imc.UsesImc(Source))
                {
                    var avfxSets = originalMetadata.ImcEntries.Select(x => x.Vfx).Distinct();
                    foreach (var avfx in avfxSets)
                    {
                        var avfxStuff = await ATex.GetVfxPath(Source.Info, avfx);

                        if (String.IsNullOrEmpty(avfxStuff.Folder) || String.IsNullOrEmpty(avfxStuff.File))
                        {
                            continue;
                        }

                        var path = avfxStuff.Folder + "/" + avfxStuff.File;
                        if (index.FileExists(path))
                        {
                            originalVfxPaths.Add(path);
                        }
                    }
                }

                // Time to start editing things.

                // First, get a new, clean copy of the metadata, pointed at the new root.
                var newMetadata = await GetCachedMetadata(index, modlist, Source, df, _dat);

                newMetadata.Root = Destination.Info.ToFullRoot();
                ItemMetadata originalDestinationMetadata = null;
                try
                {
                    originalDestinationMetadata = await GetCachedMetadata(index, modlist, Destination, df, _dat);
                } catch
                {
                    originalDestinationMetadata = new ItemMetadata(Destination);
                }

                // Set 0 needs special handling.
                if (Source.Info.PrimaryType == XivItemType.equipment && Source.Info.PrimaryId == 0)
                {
                    var set1Root     = new XivDependencyRoot(Source.Info.PrimaryType, 1, null, null, Source.Info.Slot);
                    var set1Metadata = await GetCachedMetadata(index, modlist, set1Root, df, _dat);

                    newMetadata.EqpEntry = set1Metadata.EqpEntry;

                    if (Source.Info.Slot == "met")
                    {
                        newMetadata.GmpEntry = set1Metadata.GmpEntry;
                    }
                }
                else if (Destination.Info.PrimaryType == XivItemType.equipment && Destination.Info.PrimaryId == 0)
                {
                    newMetadata.EqpEntry = null;
                    newMetadata.GmpEntry = null;
                }


                // Now figure out the path names for all of our new paths.
                // These dictionarys map Old Path => New Path
                Dictionary <string, string> newModelPaths        = new Dictionary <string, string>();
                Dictionary <string, string> newMaterialPaths     = new Dictionary <string, string>();
                Dictionary <string, string> newMaterialFileNames = new Dictionary <string, string>();
                Dictionary <string, string> newTexturePaths      = new Dictionary <string, string>();
                Dictionary <string, string> newAvfxPaths         = new Dictionary <string, string>();

                if (ProgressReporter != null)
                {
                    ProgressReporter.Report("Calculating files to copy...");
                }

                // For each path, replace any instances of our primary and secondary types.
                foreach (var path in originalModelPaths)
                {
                    newModelPaths.Add(path, UpdatePath(Source, Destination, path));
                }

                foreach (var path in originalMaterialPaths)
                {
                    var nPath = UpdatePath(Source, Destination, path);
                    newMaterialPaths.Add(path, nPath);
                    var fName = Path.GetFileName(path);

                    if (!newMaterialFileNames.ContainsKey(fName))
                    {
                        newMaterialFileNames.Add(fName, Path.GetFileName(nPath));
                    }
                }

                foreach (var path in originalTexturePaths)
                {
                    newTexturePaths.Add(path, UpdatePath(Source, Destination, path));
                }

                foreach (var path in originalVfxPaths)
                {
                    newAvfxPaths.Add(path, UpdatePath(Source, Destination, path));
                }

                var destItem = Destination.GetFirstItem();
                var srcItem  = (await Source.GetAllItems(singleVariant))[0];
                var iCat     = destItem.SecondaryCategory;
                var iName    = destItem.Name;


                var files = newModelPaths.Select(x => x.Value).Union(
                    newMaterialPaths.Select(x => x.Value)).Union(
                    newAvfxPaths.Select(x => x.Value)).Union(
                    newTexturePaths.Select(x => x.Value));
                var allFiles = new HashSet <string>();
                foreach (var f in files)
                {
                    allFiles.Add(f);
                }

                allFiles.Add(Destination.Info.GetRootFile());

                if (ProgressReporter != null)
                {
                    ProgressReporter.Report("Getting modlist...");
                }

                if (ProgressReporter != null)
                {
                    ProgressReporter.Report("Removing existing modifications to destination root...");
                }

                if (Destination != Source)
                {
                    var dPath   = Destination.Info.GetRootFolder();
                    var allMods = modlist.Mods.ToList();
                    foreach (var mod in allMods)
                    {
                        if (mod.fullPath.StartsWith(dPath) && !mod.IsInternal())
                        {
                            if (Destination.Info.SecondaryType != null || Destination.Info.Slot == null)
                            {
                                // If this is a slotless root, purge everything.
                                await _modding.DeleteMod(mod.fullPath, false, index, modlist);
                            }
                            else if (allFiles.Contains(mod.fullPath) || mod.fullPath.Contains(Destination.Info.GetBaseFileName(true)))
                            {
                                // Otherwise, only purge the files we're replacing, and anything else that
                                // contains our slot name.
                                await _modding.DeleteMod(mod.fullPath, false, index, modlist);
                            }
                        }
                    }
                }

                if (ProgressReporter != null)
                {
                    ProgressReporter.Report("Copying models...");
                }

                // Load, Edit, and resave the model files.
                foreach (var kv in newModelPaths)
                {
                    var src    = kv.Key;
                    var dst    = kv.Value;
                    var offset = index.Get8xDataOffset(src);
                    var xmdl   = await _mdl.GetRawMdlData(src, false, offset);

                    var tmdl = TTModel.FromRaw(xmdl);

                    if (xmdl == null || tmdl == null)
                    {
                        continue;
                    }

                    tmdl.Source  = dst;
                    xmdl.MdlPath = dst;

                    // Replace any material references as needed.
                    foreach (var m in tmdl.MeshGroups)
                    {
                        foreach (var matKv in newMaterialFileNames)
                        {
                            m.Material = m.Material.Replace(matKv.Key, matKv.Value);
                        }
                    }

                    // Save new Model.
                    var bytes = await _mdl.MakeNewMdlFile(tmdl, xmdl, null);

                    await _dat.WriteModFile(bytes, dst, ApplicationSource, destItem, index, modlist);
                }

                if (ProgressReporter != null)
                {
                    ProgressReporter.Report("Copying textures...");
                }

                // Raw Copy all Texture files to the new destinations to avoid having the MTRL save functions auto-generate blank textures.
                foreach (var kv in newTexturePaths)
                {
                    var src = kv.Key;
                    var dst = kv.Value;

                    await _dat.CopyFile(src, dst, ApplicationSource, true, destItem, index, modlist);
                }


                if (ProgressReporter != null)
                {
                    ProgressReporter.Report("Copying materials...");
                }
                HashSet <string> CopiedMaterials = new HashSet <string>();
                // Load every Material file and edit the texture references to the new texture paths.
                foreach (var kv in newMaterialPaths)
                {
                    var src = kv.Key;
                    var dst = kv.Value;
                    try
                    {
                        var offset = index.Get8xDataOffset(src);
                        if (offset == 0)
                        {
                            continue;
                        }
                        var xivMtrl = await _mtrl.GetMtrlData(offset, src, 11);

                        xivMtrl.MTRLPath = dst;

                        for (int i = 0; i < xivMtrl.TexturePathList.Count; i++)
                        {
                            foreach (var tkv in newTexturePaths)
                            {
                                xivMtrl.TexturePathList[i] = xivMtrl.TexturePathList[i].Replace(tkv.Key, tkv.Value);
                            }
                        }

                        await _mtrl.ImportMtrl(xivMtrl, destItem, ApplicationSource, index, modlist);

                        CopiedMaterials.Add(dst);
                    }
                    catch (Exception ex)
                    {
                        // Let functions later handle this mtrl then.
                    }
                }

                if (ProgressReporter != null)
                {
                    ProgressReporter.Report("Copying VFX...");
                }
                // Copy VFX files.
                foreach (var kv in newAvfxPaths)
                {
                    var src = kv.Key;
                    var dst = kv.Value;

                    await _dat.CopyFile(src, dst, ApplicationSource, true, destItem, index, modlist);
                }

                if (ProgressReporter != null)
                {
                    ProgressReporter.Report("Creating missing variants...");
                }
                // Check to see if we need to add any variants
                var cloneNum = newMetadata.ImcEntries.Count >= 2 ? 1 : 0;
                while (originalDestinationMetadata.ImcEntries.Count > newMetadata.ImcEntries.Count)
                {
                    // Clone Variant 1 into the variants we are missing.
                    newMetadata.ImcEntries.Add((XivImc)newMetadata.ImcEntries[cloneNum].Clone());
                }


                if (singleVariant >= 0)
                {
                    if (ProgressReporter != null)
                    {
                        ProgressReporter.Report("Setting single-variant data...");
                    }

                    if (singleVariant < newMetadata.ImcEntries.Count)
                    {
                        var v = newMetadata.ImcEntries[singleVariant];

                        for (int i = 0; i < newMetadata.ImcEntries.Count; i++)
                        {
                            newMetadata.ImcEntries[i] = (XivImc)v.Clone();
                        }
                    }
                }

                // Update Skeleton references to be for the correct set Id.
                var setId = Destination.Info.SecondaryId == null ? (ushort)Destination.Info.PrimaryId : (ushort)Destination.Info.SecondaryId;
                foreach (var entry in newMetadata.EstEntries)
                {
                    entry.Value.SetId = setId;
                }

                if (ProgressReporter != null)
                {
                    ProgressReporter.Report("Copying metdata...");
                }

                // Poke through the variants and adjust any that point to null Material Sets to instead use a valid one.
                if (newMetadata.ImcEntries.Count > 0 && originalMetadata.ImcEntries.Count > 0)
                {
                    var valid = newMetadata.ImcEntries.FirstOrDefault(x => x.MaterialSet != 0).MaterialSet;
                    if (valid <= 0)
                    {
                        valid = originalMetadata.ImcEntries.FirstOrDefault(x => x.MaterialSet != 0).MaterialSet;
                    }

                    for (int i = 0; i < newMetadata.ImcEntries.Count; i++)
                    {
                        var entry = newMetadata.ImcEntries[i];
                        if (entry.MaterialSet == 0)
                        {
                            entry.MaterialSet = valid;
                        }
                    }
                }

                await ItemMetadata.SaveMetadata(newMetadata, ApplicationSource, index, modlist);

                // Save the new Metadata file via the batch function so that it's only written to the memory cache for now.
                await ItemMetadata.ApplyMetadataBatched(new List <ItemMetadata>() { newMetadata }, index, modlist, false);



                if (ProgressReporter != null)
                {
                    ProgressReporter.Report("Filling in missing material sets...");
                }
                // Validate all variants/material sets for valid materials, and copy materials as needed to fix.
                if (Imc.UsesImc(Destination))
                {
                    var mSets = newMetadata.ImcEntries.Select(x => x.MaterialSet).Distinct();
                    foreach (var mSetId in mSets)
                    {
                        var path = Destination.Info.GetRootFolder() + "material/v" + mSetId.ToString().PadLeft(4, '0') + "/";
                        foreach (var mkv in newMaterialFileNames)
                        {
                            // See if the material was copied over.
                            var destPath = path + mkv.Value;
                            if (CopiedMaterials.Contains(destPath))
                            {
                                continue;
                            }

                            string existentCopy = null;

                            // If not, find a material where one *was* copied over.
                            foreach (var mSetId2 in mSets)
                            {
                                var p2 = Destination.Info.GetRootFolder() + "material/v" + mSetId2.ToString().PadLeft(4, '0') + "/";
                                foreach (var cmat2 in CopiedMaterials)
                                {
                                    if (cmat2 == p2 + mkv.Value)
                                    {
                                        existentCopy = cmat2;
                                        break;
                                    }
                                }
                            }

                            // Shouldn't ever actually hit this, but if we do, nothing to be done about it.
                            if (existentCopy == null)
                            {
                                continue;
                            }

                            // Copy the material over.
                            await _dat.CopyFile(existentCopy, destPath, ApplicationSource, true, destItem, index, modlist);
                        }
                    }
                }

                if (ProgressReporter != null)
                {
                    ProgressReporter.Report("Updating modlist...");
                }

                if (modPack == null)
                {
                    modPack = new ModPack()
                    {
                        author = "System", name = "Item Copy - " + srcItem.Name + " to " + iName, url = "", version = "1.0"
                    };
                }

                List <Mod> mods = new List <Mod>();
                foreach (var mod in modlist.Mods)
                {
                    if (allFiles.Contains(mod.fullPath))
                    {
                        // Ensure all of our modified files are attributed correctly.
                        mod.name     = iName;
                        mod.category = iCat;
                        mod.source   = ApplicationSource;
                        mod.modPack  = modPack;

                        mods.Add(mod);
                    }
                }

                if (!modlist.ModPacks.Any(x => x.name == modPack.name))
                {
                    modlist.ModPacks.Add(modPack);
                }

                if (doSave)
                {
                    // Save everything.
                    await _index.SaveIndexFile(index);

                    await _modding.SaveModListAsync(modlist);
                }

                XivCache.QueueDependencyUpdate(allFiles.ToList());

                if (saveDirectory != null)
                {
                    ProgressReporter.Report("Creating TTMP File...");
                    var desc = "Item Converter Modpack - " + srcItem.Name + " -> " + iName + "\nCreated at: " + DateTime.Now.ToString();
                    // Time to save the modlist to file.
                    var dir   = new DirectoryInfo(saveDirectory);
                    var _ttmp = new TTMP(dir, ApplicationSource);
                    var smpd  = new SimpleModPackData()
                    {
                        Author            = modPack.author,
                        Description       = desc,
                        Url               = modPack.url,
                        Version           = new Version(1, 0, 0),
                        Name              = modPack.name,
                        SimpleModDataList = new List <SimpleModData>()
                    };

                    foreach (var mod in mods)
                    {
                        var size = await _dat.GetCompressedFileSize(mod.data.modOffset, df);

                        var smd = new SimpleModData()
                        {
                            Name      = iName,
                            FullPath  = mod.fullPath,
                            DatFile   = df.GetDataFileName(),
                            Category  = iCat,
                            IsDefault = false,
                            ModSize   = size,
                            ModOffset = mod.data.modOffset
                        };
                        smpd.SimpleModDataList.Add(smd);
                    }

                    await _ttmp.CreateSimpleModPack(smpd, XivCache.GameInfo.GameDirectory, null, true);
                }



                if (ProgressReporter != null)
                {
                    ProgressReporter.Report("Root copy complete.");
                }

                // Return the final file conversion listing.
                var ret  = newModelPaths.Union(newMaterialPaths).Union(newAvfxPaths).Union(newTexturePaths);
                var dict = ret.ToDictionary(x => x.Key, x => x.Value);
                dict.Add(Source.Info.GetRootFile(), Destination.Info.GetRootFile());
                return(dict);
            } finally
            {
                XivCache.CacheWorkerEnabled = workerStatus;
            }
        }
Exemplo n.º 13
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));
        }