private static void MasterLoadData(MultiStructItemTemplateBase template, MhwMultiStructData structData)
        {
            // Master LoadData.
            template.WriteLine("");
            template.WriteLine("        public override void LoadFile(string targetFile) {");
            template.WriteLine("            using var reader = new BinaryReader(OpenFile(targetFile, EncryptionKey), Encoding.UTF8);");
            template.WriteLine("            data = new LinkedList<MhwStructDataContainer>();");

            foreach (var @struct in structData.structs)
            {
                var name        = @struct.SafeName;
                var targetList  = "";
                var genericType = $"<{name}";

                if (@struct.Has010Link)
                {
                    var targetName = @[email protected];
                    targetList   = $", {targetName}_.list";
                    genericType += $", {targetName}";
                }

                genericType += ">";

                template.WriteLine($"            var {name}_ = new MhwStructDataContainer{genericType}({name}.LoadData(reader{targetList}), typeof({name}));");

                if (@struct.Has010Link)
                {
                    template.WriteLine($"            {name}_.SetCountTargetToUpdate({@[email protected]}_, -1, \"{@struct._010Link.entry.SafeName}\");");
                }

                template.WriteLine($"            data.AddLast({name}_);");
            }

            template.WriteLine("        }");
        }
 public static void WriteLine(this MultiStructItemTemplateBase template, uint indentation, string line)
 {
     for (var i = 0; i < indentation; i++)
     {
         template.Write("    ");
     }
     template.WriteLine(line);
 }
        public static void Generate(MultiStructItemTemplateBase template, MhwMultiStructData structData)
        {
            foreach (var @struct in structData.structs)
            {
                GenerateInnerClass(template, @struct);
            }

            MasterLoadData(template, structData);
        }
        private static void MakeButtonProperty(MultiStructItemTemplateBase template, uint indentation, MhwMultiStructData.Entry entry, string propName)
        {
            var dataSourceLookup = GenerationHelper.GetDataSourceType(entry.dataSourceType ?? throw new Exception());

            template.WriteLine("");
            template.WriteLine(indentation, $"            [SortOrder({propName}_sortIndex)]");
            template.WriteLine(indentation, $"            [DisplayName({propName}_displayName)]");
            template.WriteLine(indentation, $"            [CustomSorter(typeof({entry.dataSourceCustomSorter}))]");
            template.WriteLine(indentation, $"            public string {propName}_button => {dataSourceLookup}.TryGet({propName}).ToStringWithId({propName});");
        }
 private static void MakePercentProperty(MultiStructItemTemplateBase template, uint indentation, string propName)
 {
     template.WriteLine("");
     template.WriteLine(indentation, $"            private float _{propName}Percent;");
     template.WriteLine(indentation, $"            [SortOrder({propName}_sortIndex + 1)]");
     template.WriteLine(indentation, $"            [DisplayName({propName}_displayName + \"%\")]");
     template.WriteLine(indentation, $"            public float {propName}_percent {{");
     template.WriteLine(indentation, $"                get => _{propName}Percent;");
     template.WriteLine(indentation, "                set {");
     template.WriteLine(indentation, $"                    _{propName}Percent = value.Clamp(0f, 100f);");
     template.WriteLine(indentation, $"                    OnPropertyChanged(nameof({propName}_percent));");
     template.WriteLine(indentation, "                }");
     template.WriteLine(indentation, "            }");
 }
        private static void GetCustomView(MultiStructItemTemplateBase template, uint indentation, MhwMultiStructData.StructData @struct)
        {
            template.WriteLine("");
            template.WriteLine(indentation, "            public ObservableCollection<MultiStructItemCustomView> GetCustomView() {");
            template.WriteLine(indentation, "                return new ObservableCollection<MultiStructItemCustomView> {");

            foreach (var entry in @struct.entries)
            {
                var propName = entry.SafeName;

                template.WriteLine(indentation, $"                    new MultiStructItemCustomView(this, \"{entry.name}\", \"{propName}\", \"{propName}_offset\"),");
            }

            template.WriteLine(indentation, "                };");
            template.WriteLine(indentation, "            }");
        }
        private static void InnerEnumerateChildren(MultiStructItemTemplateBase template, uint indentation, MhwMultiStructData.StructData @struct, MhwMultiStructData.StructData parent = null)
        {
            template.WriteLine("");
            template.WriteLine(indentation, "            public IEnumerable<F> GetAllEnumerableChildrenOfType<F>() {");

            foreach (var entry in @struct.entries)
            {
                if (entry.HasSubStruct)
                {
                    var subStructSafeName = entry.subStruct.SafeName;

                    template.WriteLine(indentation, $"                if (typeof({subStructSafeName}).Is(typeof(F)) || typeof({subStructSafeName}).IsGeneric(typeof(F))) {{");
                    template.WriteLine(indentation, $"                    foreach (var item in {entry.SafeName}_raw.Cast<F>()) {{");
                    template.WriteLine(indentation, "                        yield return item;");
                    template.WriteLine(indentation, "                    }");
                    template.WriteLine(indentation, "                }");
                }
            }

            template.WriteLine(indentation, "            }");
        }
        private static void MakeSubProperty(MultiStructItemTemplateBase template, uint indentation, MhwMultiStructData.Entry entry, string entryName, string propName, int sortIndex)
        {
            var accessLevel = entry.accessLevel;

            if (accessLevel != "private")
            {
                accessLevel += " virtual";
            }

            var typeString = $"ObservableCollection<{entry.subStruct.SafeName}>";

            // Auto-Property for sub-struct.
            template.WriteLine("");
            template.WriteLine(indentation, $"            public const string {propName}_displayName = \"{entry.name}\";");
            if (!entry.overrideSortIndex)
            {
                template.WriteLine(indentation, $"            public const int {propName}_sortIndex = {sortIndex};");
            }
            template.WriteLine(indentation, $"            [SortOrder({propName}_sortIndex)]");
            template.WriteLine(indentation, $"            [DisplayName({propName}_displayName)]");
            template.WriteLine(indentation, $"            {accessLevel} {typeString} {entryName} {{ get; {(accessLevel.Contains("protected") ? "" : "protected ")}set; }}");
        }
        private static void InnerLoadData(MultiStructItemTemplateBase template, uint indentation, MhwMultiStructData.StructData @struct, MhwMultiStructData.StructData parent = null)
        {
            if (@struct.customSaveLoad)
            {
                return;
            }

            var name = @struct.SafeName;

            // Individual LoadData (loop).
            template.WriteLine("");

            // ReSharper disable once ConvertIfStatementToConditionalTernaryExpression
            if (parent != null)
            {
                template.WriteLine(indentation, $"            public static ObservableMhwStructCollection<{name}> LoadData(BinaryReader reader, {parent.SafeName} parent) {{");
            }
            else if (@struct.Has010Link)
            {
                var targetName = @[email protected];
                template.WriteLine(indentation, $"            public static ObservableMhwStructCollection<{name}> LoadData(BinaryReader reader, ObservableMhwStructCollection<{targetName}> lastStruct) {{");
            }
            else
            {
                template.WriteLine(indentation, $"            public static ObservableMhwStructCollection<{name}> LoadData(BinaryReader reader) {{");
            }

            template.WriteLine(indentation, $"                var list = new ObservableMhwStructCollection<{name}>();");

            if (@struct.Has010Link)
            {
                var linkStruct = @struct._010Link.@struct;
                var linkEntry  = @struct._010Link.entry;

                if (linkStruct == null)
                {
                    template.WriteLine(indentation, $"                var count = (ulong) parent.{linkEntry.SafeName};");
                }
                else
                {
                    template.WriteLine(indentation, $"                var countTarget = ({linkStruct.SafeName}) lastStruct.Last();");
                    template.WriteLine(indentation, $"                var count = (ulong) countTarget.{linkEntry.SafeName};");
                }
            }
            else
            {
                // ReSharper disable once ConvertIfStatementToConditionalTernaryExpression
                if (@struct.customCount)
                {
                    template.WriteLine(indentation, "                ulong count = GetLoadCount(reader, parent);");
                }
                else
                {
                    template.WriteLine(indentation, $"                const ulong count = {@struct.fixedSizeCount}UL;");
                }
            }

            template.WriteLine(indentation, "                for (ulong i = 0; i < count; i++) {");

            // ReSharper disable once ConvertIfStatementToConditionalTernaryExpression
            if (parent != null)
            {
                template.WriteLine(indentation, "                    list.Add(LoadData(reader, i, parent));");
            }
            else
            {
                template.WriteLine(indentation, "                    list.Add(LoadData(reader, i));");
            }

            template.WriteLine(indentation, "                }");
            template.WriteLine(indentation, "                return list;");
            template.WriteLine(indentation, "            }");

            // Individual LoadData.
            template.WriteLine("");

            // ReSharper disable once ConvertIfStatementToConditionalTernaryExpression
            if (parent != null)
            {
                template.WriteLine(indentation, $"            public static {name} LoadData(BinaryReader reader, ulong i, {parent.SafeName} parent) {{");
            }
            else
            {
                template.WriteLine(indentation, $"            public static {name} LoadData(BinaryReader reader, ulong i) {{");
            }

            template.WriteLine(indentation, $"                var data = new {name}();");
            template.WriteLine(indentation, "                data.Index = i;");

            foreach (var entry in @struct.entries)
            {
                var propName  = entry.SafeName;
                var entryName = $"{propName}_raw";

                var condition = "";
                if (entry.condition != null)
                {
                    condition = $"{entry.condition} ".Replace("|ref|", "data.");
                }

                if (@struct.showVertically)
                {
                    template.WriteLine(indentation, $"                {condition}data.{propName}_offset = reader.BaseStream.Position;");
                }

                if (entry.arrayCount > -1)
                {
                    template.WriteLine(indentation, $"                {condition}data.{entryName} = reader.Read{GetReadType(entry.type)}s({entry.arrayCount});");
                }
                else if (entry.isNullTerminatedString)
                {
                    template.WriteLine(indentation, $"                {condition}data.{entryName} = reader.ReadNullTermString();");
                }
                else if (entry.HasSubStruct)
                {
                    template.WriteLine(indentation, $"                {condition}data.{entryName} = {entry.subStruct.SafeName}.LoadData(reader, data);");
                    if (!string.IsNullOrEmpty(condition))
                    {
                        template.WriteLine(indentation, $"                else data.{entryName} = new ObservableCollection<{entry.subStruct.SafeName}>();");
                    }
                }
                else
                {
                    template.WriteLine(indentation, $"                {condition}data.{entryName} = reader.Read{GetReadType(entry.type)}();");
                }
            }

            template.WriteLine(indentation, "                return data;");
            template.WriteLine(indentation, "            }");
        }
예제 #10
0
        private static void InnerWriteData(MultiStructItemTemplateBase template, uint indentation, MhwMultiStructData.StructData @struct, MhwMultiStructData.StructData parent)
        {
            // Individual WriteData.
            template.WriteLine("");
            // ReSharper disable once ConvertIfStatementToConditionalTernaryExpression
            if (parent != null)
            {
                template.WriteLine(indentation, $"            public void WriteData(BinaryWriter writer, {parent.SafeName} parent) {{");
            }
            else
            {
                template.WriteLine(indentation, "            public void WriteData(BinaryWriter writer) {");
            }

            // Do first since we need to update counts before writing them.
            foreach (var entry in @struct.entries)
            {
                var propName  = entry.SafeName;
                var entryName = $"{propName}_raw";

                if (entry.HasSubStruct)
                {
                    if (entry.subStruct._010Link != null)
                    {
                        var linkEntry  = entry.subStruct._010Link.entry;
                        var typeString = COMPILER.GetTypeOutput(new CodeTypeReference(linkEntry.type));

                        var condition = "";
                        if (entry.condition != null)
                        {
                            condition = $"{entry.condition} ".Replace("|ref|", "");
                        }

                        template.WriteLine(indentation, $"                {condition}{linkEntry.SafeName} = ({typeString}) {entryName}.Count;");
                    }
                }
            }

            foreach (var entry in @struct.entries)
            {
                var propName  = entry.SafeName;
                var entryName = $"{propName}_raw";

                var condition = "";
                if (entry.condition != null)
                {
                    condition = $"{entry.condition} ".Replace("|ref|", "");
                }

                if (entry.type == typeof(string))
                {
                    template.WriteLine(indentation, $"                {condition}writer.Write({entryName}.ToNullTermCharArray());");
                }
                else if (entry.HasSubStruct)
                {
                    template.WriteLine(indentation, $"                {condition}foreach (var obj in {entryName}) {{");
                    template.WriteLine(indentation, "                    obj.WriteData(writer, this);");
                    template.WriteLine(indentation, "                }");
                }
                else
                {
                    template.WriteLine(indentation, $"                {condition}writer.Write({entryName});");
                }
            }

            template.WriteLine(indentation, "            }");
        }
예제 #11
0
 private static void MakeOffsetProperty(MultiStructItemTemplateBase template, uint indentation, MhwMultiStructData.Entry entry, string propName)
 {
     template.WriteLine("");
     template.WriteLine(indentation, "            [DisplayName(\"Offset\")]");
     template.WriteLine(indentation, $"            public long {propName}_offset {{ get; private set; }}");
 }
예제 #12
0
        private static void GenerateInnerClass(MultiStructItemTemplateBase template, MhwMultiStructData.StructData @struct, MhwMultiStructData.StructData parent = null, uint indentation = 0)
        {
            var sortIndex   = SORT_INDEX_STEP;
            var name        = @struct.SafeName;
            var interfaces  = "MhwStructItem";
            var hasChildren = @struct.entries.Any(entry => entry.HasSubStruct);

            if (@struct.showVertically)
            {
                interfaces += ", IHasCustomView<MultiStructItemCustomView>";
            }

            if (parent == null)
            {
                interfaces += ", IWriteData";
            }
            else
            {
                interfaces += $", IWriteDataInner<{parent.SafeName}>";
            }

            if (hasChildren)
            {
                interfaces += ", IHasChildren";
            }

            template.WriteLine("");
            template.WriteLine(indentation, $"        public partial class {name} : {interfaces} {{");
            template.WriteLine(indentation, $"            public const ulong FixedSizeCount = {@struct.fixedSizeCount};");
            template.WriteLine(indentation, $"            public const string GridName = \"{@struct.name}\";");

            if (@struct.uniqueIdFormula != null)
            {
                template.WriteLine(indentation, $"            public override string UniqueId => $\"{@struct.uniqueIdFormula}\";");
            }

            if (@struct.hidden)
            {
                template.WriteLine(indentation, $"            public const bool IsHidden = {@struct.hidden.ToString().ToLower()};");
            }

            if (@struct.description != null)
            {
                template.WriteLine(indentation, $"            public const string Description = \"{@struct.description}\";");
            }

            if (@struct.canAddRows)
            {
                template.WriteLine(indentation, $"            public const bool IsAddingAllowed = {@struct.canAddRows.ToString().ToLower()};");

                template.WriteLine("");
                template.WriteLine(indentation, "            [SortOrder(-1)]");
                template.WriteLine(indentation, "            [IsReadOnly]");
                template.WriteLine(indentation, "            [DisplayName(\"X\")]");
                template.WriteLine(indentation, "            public string Delete => \"X\";");
            }

            foreach (var entry in @struct.entries)
            {
                var propName  = entry.SafeName;
                var entryName = $"{propName}_raw";

                if (entry.HasSubStruct)
                {
                    GenerateInnerClass(template, entry.subStruct, @struct, indentation + 1);

                    MakeSubProperty(template, indentation, entry, entryName, propName, sortIndex);
                }
                else
                {
                    MakeMainProperty(template, indentation, entry, entryName, propName, sortIndex);

                    if (entry.dataSourceType != null)
                    {
                        MakeButtonProperty(template, indentation, entry, propName);
                    }

                    if (entry.createPercentField)
                    {
                        MakePercentProperty(template, indentation, propName);
                    }

                    if (@struct.showVertically)
                    {
                        MakeOffsetProperty(template, indentation, entry, propName);
                    }
                }

                sortIndex += SORT_INDEX_STEP;
            }

            template.WriteLine("");
            template.WriteLine(indentation, $"            public const int lastSortIndex = {sortIndex};");

            if (hasChildren)
            {
                InnerEnumerateChildren(template, indentation, @struct, parent);
            }

            InnerLoadData(template, indentation, @struct, parent);
            InnerWriteData(template, indentation, @struct, parent);

            // GetCustomView (if needed).
            if (@struct.showVertically)
            {
                GetCustomView(template, indentation, @struct);
            }

            template.WriteLine(indentation, "        }");
        }
예제 #13
0
        private static void MakeMainProperty(MultiStructItemTemplateBase template, uint indentation, MhwMultiStructData.Entry entry, string entryName, string propName, int sortIndex)
        {
            var accessLevel = entry.accessLevel;

            if (entry.name == "Index")
            {
                accessLevel += " override";
            }
            else if (accessLevel != "private")
            {
                accessLevel += " virtual";
            }

            var typeString = COMPILER.GetTypeOutput(new CodeTypeReference(entry.type));

            if (entry.arrayCount > -1)
            {
                typeString += "[]";
            }

            string returnString;
            var    setCast = "";
            var    getCast = "";

            if (entry.enumReturn == null)
            {
                returnString = typeString;
            }
            else
            {
                returnString = COMPILER.GetTypeOutput(new CodeTypeReference(entry.enumReturn));
                getCast      = $"({returnString}) ";
                setCast      = $"({typeString}) ";
            }

            if (entry.name == "Index")
            {
                getCast      = "(ulong) ";
                setCast      = $"({returnString}) ";
                returnString = "ulong";
            }

            // Main Property.
            template.WriteLine("");
            template.WriteLine(indentation, $"            protected {typeString} {entryName};");
            template.WriteLine(indentation, $"            public const string {propName}_displayName = \"{entry.name}\";");
            if (!entry.overrideSortIndex)
            {
                template.WriteLine(indentation, $"            public const int {propName}_sortIndex = {sortIndex};");
            }
            template.WriteLine(indentation, $"            [SortOrder({propName}_sortIndex)]");
            template.WriteLine(indentation, $"            [DisplayName({propName}_displayName)]");

            if (entry.dataSourceType != null)
            {
                template.WriteLine(indentation, $"            [DataSource(DataSourceType.{entry.dataSourceType})]");
            }

            if (entry.readOnly)
            {
                template.WriteLine(indentation, "            [IsReadOnly]");
            }

            if (entry.showAsHex)
            {
                template.WriteLine(indentation, "            [ShowAsHex]");
            }

            template.WriteLine(indentation, $"            {accessLevel} {returnString} {propName} {{");

            if (returnString == "bool")
            {
                template.WriteLine(indentation, $"                get => {getCast}Convert.ToBoolean({entryName});");
            }
            else if (typeString == "char[]")
            {
                template.WriteLine(indentation, $"                get => {getCast}new string({entryName});");
            }
            else
            {
                template.WriteLine(indentation, $"                get => {getCast}{entryName};");
            }

            // Always include a setter, even for readOnly. This enables us to bypass readOnly via command line switch.
            template.WriteLine(indentation, "                set {");

            if (returnString == "bool")
            {
                template.WriteLine(indentation, $"                    if (Convert.ToBoolean({entryName}) == {entry.valueString}) return;"); // Do nothing if the value is the same.
                template.WriteLine(indentation, $"                    {entryName} = Convert.ToByte({entry.valueString});");
            }
            else if (typeString == "char[]")
            {
                template.WriteLine(indentation, $"                    if ({getCast}new string({entryName}) == {entry.valueString}) return;"); // Do nothing if the value is the same.
                template.WriteLine(indentation, $"                    {entryName} = {setCast}{entry.valueString}.ToCharArray(0, {entry.arrayCount - 1});");
            }
            else
            {
                template.WriteLine(indentation, $"                    if ({getCast}{entryName} == {entry.valueString}) return;"); // Do nothing if the value is the same.
                template.WriteLine(indentation, $"                    {entryName} = {setCast}{entry.valueString};");
            }

            template.WriteLine(indentation, $"                    ChangedItems.Add(nameof({propName}));");
            template.WriteLine(indentation, $"                    OnPropertyChanged(nameof({propName}));");

            if (entry.dataSourceType != null)
            {
                template.WriteLine(indentation, $"                    OnPropertyChanged(nameof({propName}_button));");
            }

            if (entry.extraOnPropertyChanged != null)
            {
                foreach (var propertyToChange in entry.extraOnPropertyChanged)
                {
                    var propertyToChangeName = Regex.Replace(propertyToChange, @"[^\w\d]+", "_");

                    template.WriteLine(indentation, $"                    OnPropertyChanged(nameof({propertyToChangeName}));");
                }
            }

            template.WriteLine(indentation, "                }");
            template.WriteLine(indentation, "            }");
        }