private void UpdateMaterialsList()
        {
            // Remove the Custom Tag at the end if it's there.
            _view.MaterialsSource.Remove(CustomTag);

            // If we don't have this already, we're in our first itteration of this function.
            if (!_view.MaterialsSource.Contains(SkinTag))
            {
                _view.MaterialsSource.Add(SkinTag);
            }

            // Add in any new item materials.
            foreach (var m in _newModel.MeshGroups)
            {
                var result = ItemMaterialRegex.Match(m.Material);
                if (result.Success)
                {
                    if (_view.MaterialsSource.Any(x => x.Key == m.Material))
                    {
                        continue;
                    }

                    // We have a new item material here that we haven't added to the list yet.
                    var raceId = result.Groups[1].Value;
                    var partId = result.Groups[2].Value;
                    var race   = XivRaces.GetXivRace(raceId);
                    _view.MaterialsSource.Add(new KeyValuePair <string, string>(m.Material, "Material " + partId.ToUpper() + " - " + XivRaces.GetDisplayName(race)));
                }
            }

            // Re-Add the custom tag.
            _view.MaterialsSource.Add(CustomTag);
        }
        private void AddMaterial(string m)
        {
            if (_view.MaterialsSource.Any(x => x.Key == m))
            {
                return;
            }

            var result = ItemMaterialRegex.Match(m);

            if (result.Success
                // This check is a little janky, but it's to avoid reading cross-slot references as the same item.
                // ... Not that this should ever really happen, but it's *technically* possible.
                && (_root.Info.Slot == null || m.Contains(_root.Info.Slot)))
            {
                // We have a new item material here that we haven't added to the list yet.
                var raceId = result.Groups[1].Value;
                var partId = result.Groups[2].Value;
                var race   = XivRaces.GetXivRace(raceId);
                _view.MaterialsSource.Add(new KeyValuePair <string, string>(m, "Material " + partId.ToUpper() + " - " + XivRaces.GetDisplayName(race)));
            }
            else
            {
                _view.MaterialsSource.Add(new KeyValuePair <string, string>(m, Path.GetFileNameWithoutExtension(m)));
            }
        }
        /// <summary>
        /// Automatically attempts to set the racial override status based upon a selected file name.
        /// </summary>
        private void SetRaceOverrideByFileName()
        {
            if (String.IsNullOrWhiteSpace(_view.FileNameTextBox.Text))
            {
                return;
            }

            var fileName  = Path.GetFileNameWithoutExtension(_view.FileNameTextBox.Text);
            var raceRegex = new Regex("c([0-9]{4})");
            var match     = raceRegex.Match(fileName);

            if (match.Success)
            {
                // Swap the race to a non-NPC version if it's an NPC race.
                var raceCode = match.Groups[1].Value.Substring(0, 2) + "01";
                var race     = XivRaces.GetXivRace(raceCode);

                if (race != _race && race != XivRace.All_Races && _race != XivRace.All_Races)
                {
                    // We have a valid race.
                    _view.OverrideRaceButton.IsChecked = true;
                    _view.RaceComboBox.SelectedValue   = race;
                }
            }
        }
        private static async Task <Dictionary <XivRace, ExtraSkeletonEntry> > DeserializeEstData(byte[] data, XivDependencyRoot root, uint dataVersion)
        {
            if (dataVersion == 1)
            {
                // Version 1 didn't include EST data, so just get the defaults.
                return(await Est.GetExtraSkeletonEntries(root));
            }


            // 6 Bytes per entry.
            var count = data.Length / 6;
            var ret   = new Dictionary <XivRace, ExtraSkeletonEntry>(count);

            for (int i = 0; i < count; i++)
            {
                var offset   = i * 6;
                var raceCode = BitConverter.ToUInt16(data, offset);
                var setId    = BitConverter.ToUInt16(data, offset + 2);
                var skelId   = BitConverter.ToUInt16(data, offset + 4);

                var race = XivRaces.GetXivRace(raceCode);

                ret.Add(race, new ExtraSkeletonEntry(race, setId, skelId));
            }

            return(ret);
        }
        private void SetupRaces()
        {
            var races = Eqp.PlayableRaces;

            _view.RaceComboBox.SelectedValuePath = "Key";
            _view.RaceComboBox.DisplayMemberPath = "Value";

            _view.RaceComboBox.IsEnabled = false;

            if (_race == XivRace.All_Races)
            {
                _view.OverrideRaceButton.IsEnabled = false;
                var kv = new KeyValuePair <XivRace, string>(XivRace.All_Races, "--");
                _view.RaceComboBox.Items.Add(kv);
            }
            else
            {
                foreach (var race in races)
                {
                    var kv = new KeyValuePair <XivRace, string>(race, XivRaces.GetDisplayName(race));
                    _view.RaceComboBox.Items.Add(kv);
                }
            }

            _view.RaceComboBox.SelectedValue = _race;
        }
Esempio n. 6
0
        private static async Task <string> GetExtraSkelbPath(XivDependencyRootInfo root, XivRace race = XivRace.All_Races)
        {
            var type = Est.GetEstType(root);

            // Type doesn't use extra skels.
            if (type == Est.EstType.Invalid)
            {
                return(null);
            }


            var id = (ushort)root.PrimaryId;

            if (type == Est.EstType.Face || type == Est.EstType.Hair)
            {
                id = (ushort)root.SecondaryId;
            }

            // Hair and face types have a race defined at root level.
            if ((type == Est.EstType.Face || type == Est.EstType.Hair) && race == XivRace.All_Races)
            {
                var ret = new Dictionary <XivRace, ExtraSkeletonEntry>();
                race = XivRaces.GetXivRace(root.PrimaryId);
            }


            var entry = await Est.GetExtraSkeletonEntry(type, race, id);

            var skelId = entry.SkelId;

            if (skelId == 0)
            {
                if (race == XivRace.Hyur_Midlander_Male)
                {
                    return(null);
                }

                // Okay, this model, *as defined* has no EX Skeleton.  _HOWEVER_ its parent skeleton could.
                // So we need to re-call and check up the chain until we hit Hyur M.

                var parent = XivRaceTree.GetNode(race).Parent;
                if (parent == null)
                {
                    return(null);
                }

                // It's worth noting in these cases, the Skeletal bones themselves will still be using the matrices appropriate
                // for their parent race in this method, but that should be sufficient for now.
                return(await GetExtraSkelbPath(root, parent.Race));
            }

            var prefix   = Est.GetSystemPrefix(type);
            var slot     = Est.GetSystemSlot(type);
            var raceCode = XivRaces.GetRaceCode(race);
            var skelCode = skelId.ToString().PadLeft(4, '0');
            var path     = $"chara/human/c{raceCode}/skeleton/{slot}/{prefix}{skelCode}/skl_c{raceCode}{prefix}{skelCode}.sklb";

            return(path);
        }
Esempio n. 7
0
        /// <summary>
        /// Gets the race from the path
        /// </summary>
        /// <param name="modPath">The mod path</param>
        /// <returns>The race as XivRace</returns>
        public static XivRace GetRace(string modPath)
        {
            // I'm 99% sure we have another function somewhere that already does this, but whatever.
            var match = _extractRaceRegex.Match(modPath);

            if (match.Success)
            {
                return(XivRaces.GetXivRace(match.Groups[1].Value));
            }
            return(XivRace.All_Races);
        }
Esempio n. 8
0
        /// <summary>
        /// Retrieves the base racial or body skeleton for a given model file, parsing it from the base
        /// game files to generate it, if necessary.
        /// </summary>
        /// <param name="fullMdlPath"></param>
        /// <returns></returns>
        public static async Task <string> GetBaseSkeletonFile(string fullMdlPath)
        {
            var root = await XivCache.GetFirstRoot(fullMdlPath);

            var race = XivRace.All_Races;

            if (root.Info.PrimaryType == XivItemType.human || root.Info.PrimaryType == XivItemType.equipment || root.Info.PrimaryType == XivItemType.accessory)
            {
                race = XivRaces.GetXivRace(fullMdlPath.Substring(1, 4));
            }

            return(await GetBaseSkeletonFile(root.Info, race));
        }
        public static void Write(byte[] data, ExtraSkeletonEntry entry, int count, int index)
        {
            int   offset = (int)(4 + (index * 4));
            short raceId = Int16.Parse(XivRaces.GetRaceCode(entry.Race));

            IOUtil.ReplaceBytesAt(data, BitConverter.GetBytes(entry.SetId), offset);
            IOUtil.ReplaceBytesAt(data, BitConverter.GetBytes(raceId), offset + 2);

            var baseOffset = 4 + (count * 4);

            offset = (int)(baseOffset + (index * 2));
            IOUtil.ReplaceBytesAt(data, BitConverter.GetBytes(entry.SkelId), offset);
        }
Esempio n. 10
0
        /// <summary>
        /// Retrieves the Ex skeleton file for a given model file, parsing it from the base
        /// game files to generate it, if necessary.
        /// </summary>
        /// <param name="fullMdlPath"></param>
        /// <returns></returns>
        public static async Task <string> GetExtraSkeletonFile(string fullMdlPath)
        {
            var root = await XivCache.GetFirstRoot(fullMdlPath);

            var estType = Est.GetEstType(root);

            if (estType == Est.EstType.Invalid)
            {
                return(null);
            }

            // This is a hair/hat/face/body model at this point so this is a safe pull.
            var race = XivRaces.GetXivRace(fullMdlPath.Substring(1, 4));

            return(await GetExtraSkeletonFile(root.Info, race));
        }
        /// <summary>
        /// Gets the race from the path
        /// </summary>
        /// <param name="modPath">The mod path</param>
        /// <returns>The race as XivRace</returns>
        private Task <XivRace> GetRace(string modPath)
        {
            return(Task.Run(() =>
            {
                var xivRace = XivRace.All_Races;

                if (modPath.Contains("ui/") || modPath.Contains(".avfx"))
                {
                    xivRace = XivRace.All_Races;
                }
                else if (modPath.Contains("monster"))
                {
                    xivRace = XivRace.Monster;
                }
                else if (modPath.Contains("bgcommon"))
                {
                    xivRace = XivRace.All_Races;
                }
                else if (modPath.Contains(".tex") || modPath.Contains(".mdl") || modPath.Contains(".atex"))
                {
                    if (modPath.Contains("accessory") || modPath.Contains("weapon") || modPath.Contains("/common/"))
                    {
                        xivRace = XivRace.All_Races;
                    }
                    else
                    {
                        if (modPath.Contains("demihuman"))
                        {
                            xivRace = XivRace.DemiHuman;
                        }
                        else if (modPath.Contains("/v"))
                        {
                            var raceCode = modPath.Substring(modPath.IndexOf("_c") + 2, 4);
                            xivRace = XivRaces.GetXivRace(raceCode);
                        }
                        else
                        {
                            var raceCode = modPath.Substring(modPath.IndexOf("/c") + 2, 4);
                            xivRace = XivRaces.GetXivRace(raceCode);
                        }
                    }
                }

                return xivRace;
            }));
        }
Esempio n. 12
0
        private static (XivRace Race, string BodyID) GetSettingsRace(int gender)
        {
            var settingsRace = Settings.Default.Default_Race;
            var defaultBody  = "0001";

            if (settingsRace.Equals(XivStringRaces.Hyur_M))
            {
                if (gender == 0)
                {
                    return(XivRaces.GetXivRace("0101"), defaultBody);
                }
            }

            if (settingsRace.Equals(XivStringRaces.Hyur_H))
            {
                if (gender == 0)
                {
                    return(XivRaces.GetXivRace("0301"), defaultBody);
                }

                return(XivRaces.GetXivRace("0401"), defaultBody);
            }

            if (settingsRace.Equals(XivStringRaces.Aura_R))
            {
                if (gender == 0)
                {
                    return(XivRaces.GetXivRace("1301"), defaultBody);
                }

                return(XivRaces.GetXivRace("1401"), defaultBody);
            }

            if (settingsRace.Equals(XivStringRaces.Aura_X))
            {
                if (gender == 0)
                {
                    return(XivRaces.GetXivRace("1301"), "0101");
                }

                return(XivRaces.GetXivRace("1401"), "0101");
            }

            return(XivRaces.GetXivRace("0201"), defaultBody);
        }
Esempio n. 13
0
        public static XivRace GetRaceFromPath(string path)
        {
            if (path == null)
            {
                return(XivRace.All_Races);
            }

            var xivRace = XivRace.All_Races;

            if (path.Contains("ui/") || path.Contains(".avfx"))
            {
                xivRace = XivRace.All_Races;
            }
            else if (path.Contains("monster"))
            {
                xivRace = XivRace.Monster;
            }
            else if (path.Contains(".tex") || path.Contains(".mdl") || path.Contains(".atex"))
            {
                if (path.Contains("weapon") || path.Contains("/common/"))
                {
                    xivRace = XivRace.All_Races;
                }
                else
                {
                    if (path.Contains("demihuman"))
                    {
                        xivRace = XivRace.DemiHuman;
                    }
                    else if (path.Contains("/v"))
                    {
                        var raceCode = path.Substring(path.IndexOf("_c") + 2, 4);
                        xivRace = XivRaces.GetXivRace(raceCode);
                    }
                    else
                    {
                        var raceCode = path.Substring(path.IndexOf("/c") + 2, 4);
                        xivRace = XivRaces.GetXivRace(raceCode);
                    }
                }
            }

            return(xivRace);
        }
        public static ExtraSkeletonEntry Read(byte[] data, uint count, uint index)
        {
            int offset = (int)(4 + (index * 4));

            var setId  = BitConverter.ToUInt16(data, offset);
            var raceId = BitConverter.ToUInt16(data, offset + 2);
            var race   = XivRaces.GetXivRace(raceId.ToString().PadLeft(4, '0'));


            var baseOffset = 4 + (count * 4);

            offset = (int)(baseOffset + (index * 2));

            var skelId = BitConverter.ToUInt16(data, offset);

            var ret = new ExtraSkeletonEntry(race, setId, skelId);

            return(ret);
        }
        /// <summary>
        /// Gets the race from the path
        /// </summary>
        /// <param name="modPath">The mod path</param>
        /// <returns>The race as XivRace</returns>
        private XivRace GetRace(string modPath)
        {
            XivRace xivRace = XivRace.All_Races;

            if (modPath.Contains("ui/") || modPath.Contains(".avfx"))
            {
                xivRace = XivRace.All_Races;
            }
            else if (modPath.Contains("monster"))
            {
                xivRace = XivRace.Monster;
            }
            else if (modPath.Contains("bgcommon"))
            {
                xivRace = XivRace.All_Races;
            }
            else if (modPath.Contains(".tex") || modPath.Contains(".mdl") || modPath.Contains(".atex"))
            {
                if (modPath.Contains("accessory") || modPath.Contains("weapon") || modPath.Contains("/common/"))
                {
                    xivRace = XivRace.All_Races;
                }
                else
                {
                    if (modPath.Contains("demihuman"))
                    {
                        xivRace = XivRace.DemiHuman;
                    }
                    else if (modPath.Contains("/v"))
                    {
                        string raceCode = modPath.Substring(modPath.IndexOf("_c") + 2, 4);
                        xivRace = XivRaces.GetXivRace(raceCode);
                    }
                    else
                    {
                        string raceCode = modPath.Substring(modPath.IndexOf("/c") + 2, 4);
                        xivRace = XivRaces.GetXivRace(raceCode);
                    }
                }
            }

            return(xivRace);
        }
            public FileEntry(string path)
            {
                File = path;

                var fName = System.IO.Path.GetFileName(File);

                DisplayName = fName; // File name first.

                var match = _variantMatch.Match(path);

                if (match.Success)
                {
                    var variant = match.Groups[1].Value;
                    DisplayName += " - v" + variant;
                }
                match = _raceRegx.Match(fName);
                if (match.Success)
                {
                    var race = XivRaces.GetXivRace(match.Groups[1].Value);
                    DisplayName += " - " + race.GetDisplayName();
                }
            }
        /// <summary>
        /// Deserializes the binary EQDP data into a dictionary of EQDP entries.
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        private static Dictionary <XivRace, EquipmentDeformationParameter> DeserializeEqdpData(byte[] data, XivDependencyRoot root, uint dataVersion)
        {
            const int eqdpEntrySize = 5;
            var       entries       = data.Length / eqdpEntrySize;

            var ret = new Dictionary <XivRace, EquipmentDeformationParameter>();

            var read = 0;

            using (var reader = new BinaryReader(new MemoryStream(data)))
            {
                while (read < entries)
                {
                    var raceCode = reader.ReadInt32();
                    var race     = XivRaces.GetXivRace(raceCode.ToString().PadLeft(4, '0'));

                    var eqpByte = reader.ReadByte();
                    var entry   = EquipmentDeformationParameter.FromByte(eqpByte);

                    ret.Add(race, entry);

                    read++;
                }
            }

            // Catch for cases where for some reason the EQP doesn't have all races,
            // for example, SE adding more races in the future, and we're
            // reading old metadata entries.
            foreach (var race in Eqp.PlayableRaces)
            {
                if (!ret.ContainsKey(race))
                {
                    ret.Add(race, new EquipmentDeformationParameter());
                }
            }

            return(ret);
        }
Esempio n. 18
0
        public static async Task <Dictionary <XivRace, ExtraSkeletonEntry> > GetExtraSkeletonEntries(XivDependencyRootInfo root, bool forceDefault = false)
        {
            var type = GetEstType(root);

            if (type == EstType.Invalid)
            {
                return(new Dictionary <XivRace, ExtraSkeletonEntry>());
            }

            var id = (ushort)root.PrimaryId;

            if (type == EstType.Face || type == EstType.Hair)
            {
                id = (ushort)root.SecondaryId;
            }
            var entries = await GetExtraSkeletonEntries(type, id, forceDefault);


            // Hair and Faces have to be further trimmed down to only the entries associated with their root.
            if (type == EstType.Face || type == EstType.Hair)
            {
                var ret  = new Dictionary <XivRace, ExtraSkeletonEntry>();
                var race = XivRaces.GetXivRace(root.PrimaryId);

                if (entries.ContainsKey(race))
                {
                    ret.Add(race, entries[race]);
                }
                else
                {
                    ret.Add(race, new ExtraSkeletonEntry(race, id));
                }
                entries = ret;
            }

            return(entries);
        }
Esempio n. 19
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);
        }
Esempio n. 20
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));
                    }
                }
            }
        }
Esempio n. 21
0
        private async Task <List <IItem> > BuildCategoryTree()
        {
            foreach (var kv in _categoryStructure)
            {
                // Make the top level node.
                var e = new ItemTreeElement(null, null, kv.Key);

                foreach (var secondary in kv.Value)
                {
                    var e2 = new ItemTreeElement(e, null, secondary);
                    e.Children.Add(e2);
                }
                CategoryElements.Add(e);
            }

            var gameDir  = XivCache.GameInfo.GameDirectory;
            var language = XivCache.GameInfo.GameLanguage;

            var items = await XivCache.GetFullItemList();

            foreach (var item in items)
            {
                // Find what node we should be attached to.
                ItemTreeElement catParent = null;
                var             topLevel  = CategoryElements.FirstOrDefault(x => x.DisplayName == item.PrimaryCategory);
                if (topLevel == null)
                {
                    topLevel = new ItemTreeElement(null, null, item.PrimaryCategory);
                    CategoryElements.Add(topLevel);
                }

                var secondLevel = topLevel.Children.FirstOrDefault(x => x.DisplayName == item.SecondaryCategory);
                if (secondLevel == null)
                {
                    if (item.SecondaryCategory == item.Name)
                    {
                        // These are a special snowflake case.
                        secondLevel = topLevel;
                    }
                    else
                    {
                        secondLevel = new ItemTreeElement(topLevel, null, item.SecondaryCategory);
                        topLevel.Children.Add(secondLevel);
                    }
                }

                catParent = secondLevel;

                ItemTreeElement setParent = null;

                // Try and see if we have a valid root parent to attach to in the sets tree.
                try
                {
                    var type = item.GetType();
                    // Perf.  Much faster to just not test those types at all, as we know they won't resolve.
                    if (type != typeof(XivUi))
                    {
                        var itemRoot = item.GetRootInfo();
                        if (itemRoot.PrimaryType != XivItemType.unknown)
                        {
                            var st = itemRoot.ToString();
                            if (DependencyRootNodes.ContainsKey(st))
                            {
                                setParent = DependencyRootNodes[st];
                            }
                        }
                    }
                } catch (Exception ex)
                {
                    throw;
                }

                ItemTreeElement e2;
                if (ExpandCharacterMenu && typeof(XivCharacter) == item.GetType())
                {
                    var charItem = (XivCharacter)item;
                    if (charItem.ModelInfo != null && charItem.ModelInfo.PrimaryID > 0)
                    {
                        e2 = new ItemTreeElement(catParent, setParent, item.Name);
                    }
                    else
                    {
                        e2 = new ItemTreeElement(catParent, setParent, item);
                    }
                }
                else
                {
                    e2 = new ItemTreeElement(catParent, setParent, item);
                }
                if (catParent != null)
                {
                    catParent.Children.Add(e2);
                }
                if (setParent != null)
                {
                    setParent.Children.Add(e2);
                }

                if (ExpandCharacterMenu)
                {
                    if (typeof(XivCharacter) == item.GetType())
                    {
                        // Cache the references to our human root nodes.
                        var charItem = (XivCharacter)item;
                        var type     = charItem.GetSecondaryItemType();
                        if (type != XivItemType.none)
                        {
                            var raceCode = charItem.ModelInfo.PrimaryID;
                            var race     = XivRaces.GetXivRace(raceCode);

                            if (!HumanParentNodes.ContainsKey(type))
                            {
                                HumanParentNodes.Add(type, new Dictionary <XivRace, ItemTreeElement>());
                            }

                            HumanParentNodes[type].Add(race, e2);
                        }
                    }
                }
            }
            return(items);
        }
Esempio n. 22
0
        private async void AnyTextChanged(object sender, TextChangedEventArgs e)
        {
            var to   = ToBox.Text;
            var from = FromBox.Text;

            if (string.IsNullOrWhiteSpace(to) || string.IsNullOrWhiteSpace(from))
            {
                CopyButton.IsEnabled = false;
                return;
            }

            to   = to.Trim().ToLower();
            from = from.Trim().ToLower();

            if (!to.EndsWith(".mdl") || !from.EndsWith(".mdl"))
            {
                MaterialCopyNotice.Text       = "--";
                MaterialCopyNotice.Foreground = Brushes.Black;

                RaceChangeNotice.Text       = "--";
                RaceChangeNotice.Foreground = Brushes.Black;

                CopyButton.IsEnabled = false;
                return;
            }

            try
            {
                var df  = IOUtil.GetDataFileFromPath(to);
                var df2 = IOUtil.GetDataFileFromPath(from);

                if (df != df2)
                {
                    MaterialCopyNotice.Text       = "Source and target files must exist within the same data file.";
                    MaterialCopyNotice.Foreground = Brushes.Red;

                    RaceChangeNotice.Text       = "--";
                    RaceChangeNotice.Foreground = Brushes.Black;

                    CopyButton.IsEnabled = false;
                    return;
                }
            } catch
            {
                MaterialCopyNotice.Text       = "At least one file path is not a valid internal FFXIV file path.";
                MaterialCopyNotice.Foreground = Brushes.Red;

                RaceChangeNotice.Text       = "--";
                RaceChangeNotice.Foreground = Brushes.Black;

                CopyButton.IsEnabled = false;
                return;
            }

            CopyButton.IsEnabled = true;
            var toRoot = await XivCache.GetFirstRoot(to);

            var fromRoot = await XivCache.GetFirstRoot(from);

            if (toRoot == null || fromRoot == null)
            {
                MaterialCopyNotice.Text       = "Unknown File Root - Materials and textures will not be copied.";
                MaterialCopyNotice.Foreground = Brushes.DarkGoldenrod;

                RaceChangeNotice.Text       = "Unknown File Root - Model will not be racially adjusted.";
                RaceChangeNotice.Foreground = Brushes.DarkGoldenrod;
                return;
            }
            else
            {
                MaterialCopyNotice.Text       = "Materials and textures will be copied to destination root folder.";
                MaterialCopyNotice.Foreground = Brushes.Green;
            }

            var raceRegex = new Regex("c([0-9]{4})");

            var toMatch   = raceRegex.Match(to);
            var fromMatch = raceRegex.Match(from);

            if (!toMatch.Success || !fromMatch.Success)
            {
                RaceChangeNotice.Text       = "Model is not racial - Model will not be racially adjusted.";
                RaceChangeNotice.Foreground = Brushes.Black;
                return;
            }

            var toRace   = XivRaces.GetXivRace(toMatch.Groups[1].Value);
            var fromRace = XivRaces.GetXivRace(fromMatch.Groups[1].Value);

            if (toRace == fromRace)
            {
                RaceChangeNotice.Text       = "Model races are identical - Model will not be racially adjusted.";
                RaceChangeNotice.Foreground = Brushes.Black;
                return;
            }


            RaceChangeNotice.Text       = "Model will be adjusted from " + fromRace.GetDisplayName() + " to " + toRace.GetDisplayName() + ".";
            RaceChangeNotice.Foreground = Brushes.Green;
        }
Esempio n. 23
0
        /// <summary>
        /// This should only really be called directly if the control was created with DeferLoading set to true.
        /// </summary>
        /// <returns></returns>
        public async Task LoadItems()
        {
            if (_READY)
            {
                SearchTimer.Stop();
                SearchTimer.Dispose();
                ClearSelection();
            }

            if (LockUiFunction != null)
            {
                await LockUiFunction(UIStrings.Loading_Items, null, this);
            }


            // Pump us into another thread so the UI stays nice and fresh.
            await Task.Run(async() =>
            {
                CategoryElements    = new ObservableCollection <ItemTreeElement>();
                SetElements         = new ObservableCollection <ItemTreeElement>();
                DependencyRootNodes = new Dictionary <string, ItemTreeElement>();

                try
                {
                    // Gotta build set tree first, so the items from the item list can latch onto the nodes there.
                    BuildSetTree();
                    await BuildCategoryTree();
                }
                catch (Exception ex)
                {
                    FlexibleMessageBox.Show("An error occurred while loading the item list.\n" + ex.Message, "Item List Error", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Warning);
                    return;
                }


                var toAdd = new List <(ItemTreeElement parent, ItemTreeElement child)>();
                foreach (var kv in DependencyRootNodes)
                {
                    // This dependency root had no EXD-Items associated with it.
                    // Gotta make a generic item for it.
                    if (kv.Value.Children.Count == 0)
                    {
                        // See if we can actually turn this root into a fully fledged item.
                        try
                        {
                            var root = await XivCache.GetFirstRoot(kv.Key);
                            ItemTreeElement e;
                            if (root != null)
                            {
                                // If we can, add it into the list.
                                var item = root.ToRawItem();
                                e        = new ItemTreeElement(null, kv.Value, item);
                                toAdd.Add((kv.Value, e));

                                if (ExpandCharacterMenu && root.Info.PrimaryType == XivItemType.human)
                                {
                                    // Cache our human type elements if we need them later.
                                    var race  = XivRaces.GetXivRace(root.Info.PrimaryId);
                                    var sType = (XivItemType)root.Info.SecondaryType;

                                    if (!HumanParentNodes.ContainsKey(sType))
                                    {
                                        continue;
                                    }
                                    if (!HumanParentNodes[sType].ContainsKey(race))
                                    {
                                        continue;
                                    }

                                    var parent       = HumanParentNodes[sType][race];
                                    e.CategoryParent = parent;
                                    parent.Children.Add(e);
                                }
                            }
                            else
                            {
                                e = new ItemTreeElement(null, kv.Value, "[Unsupported]");
                                toAdd.Add((kv.Value, e));
                            }
                        }
                        catch (Exception ex)
                        {
                            throw;
                        }
                    }
                }

                // Loop back through to add the new items, so we're not affecting the previous iteration.
                foreach (var tup in toAdd)
                {
                    tup.parent.Children.Add(tup.child);
                }
            });

            var view = (CollectionView)CollectionViewSource.GetDefaultView(CategoryElements);

            view.Filter = SearchFilter;


            view        = (CollectionView)CollectionViewSource.GetDefaultView(SetElements);
            view.Filter = SearchFilter;

            SearchTimer          = new Timer(300);
            SearchTimer.Elapsed += Search;

            CategoryTree.ItemsSource = CategoryElements;
            SetTree.ItemsSource      = SetElements;

            _READY = true;

            Search(this, null);

            if (UnlockUiFunction != null)
            {
                await UnlockUiFunction(this);
            }

            if (ItemsLoaded != null)
            {
                ItemsLoaded.Invoke(this, null);
            }
        }