예제 #1
0
        public void GetFieldValue(object owner, object value = null, object definition = null)
        {
            if (value == null)
            {
                value = Field.GetValue(owner);
            }

            Owner   = owner;
            Loading = true;

            if (value == null)
            {
                textBox1.Text = "<null>";
                Loading       = false;
                return;
            }

            var type = value.GetType();

            if (type == typeof(StringId))
            {
                textBox1.Text = CacheContext.GetString((StringId)value);
            }
            else if (type == typeof(Angle))
            {
                textBox1.Text = ((Angle)value).Degrees.ToString();
            }
            else
            {
                textBox1.Text = value.ToString();
            }

            Loading = false;
        }
예제 #2
0
        public void SetFieldValue(object owner, object value = null, object definition = null)
        {
            if (Loading || owner == null)
            {
                return;
            }

            if (value == null)
            {
                if (!CacheContext.TryGetTag(textBox.Text, out var tag))
                {
                    textBox.ForeColor = Color.Red;
                    return;
                }

                textBox.ForeColor = SystemColors.WindowText;

                value = tag;

                var tagName = tag.Name ?? $"0x{tag.Index:X4}";

                textBox.Text = $"{tagName}.{CacheContext.GetString(tag.Group.Name)}";
            }

            Field.SetValue(owner, value);
        }
예제 #3
0
        public override object Execute(List <string> args)
        {
            if (args.Count != 1 || !CacheContext.TryGetTag(args[0], out var tag))
            {
                return(false);
            }

            var oldContext = ContextStack.Context;

            TagInstance = tag;

            using (var stream = CacheContext.OpenTagCacheRead())
                TagDefinition = CacheContext.Deserialize(stream, TagInstance);

            ContextStack.Push(EditTagContextFactory.Create(ContextStack, CacheContext, TagInstance, TagDefinition));

            var groupName = CacheContext.GetString(TagInstance.Group.Name);
            var tagName   = TagInstance?.Name ?? $"0x{TagInstance.Index:X4}";

            Console.WriteLine($"Tag {tagName}.{groupName} has been opened for editing.");
            Console.WriteLine("New commands are now available. Enter \"help\" to view them.");
            Console.WriteLine("Use \"exit\" to return to {0}.", oldContext.Name);

            return(true);
        }
예제 #4
0
        private void importToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (tagTreeView.SelectedNode?.Tag is CachedTagInstance tag)
            {
                using (var ofd = new OpenFileDialog())
                {
                    var groupName = CacheContext.GetString(tag.Group.Name);

                    ofd.Filter = $"{groupName} files (*.{groupName})|*.{groupName}";

                    if (ofd.ShowDialog() != DialogResult.OK)
                    {
                        return;
                    }

                    byte[] data;

                    using (var stream = File.OpenRead(ofd.FileName))
                    {
                        data = new byte[stream.Length];
                        stream.Read(data, 0, data.Length);
                    }

                    using (var stream = CacheContext.OpenTagCacheReadWrite())
                        CacheContext.TagCache.SetTagDataRaw(stream, tag, data);

                    MessageBox.Show($"Imported {ofd.FileName} successfully.", "Import Tag", MessageBoxButtons.OK);
                }
            }
        }
예제 #5
0
        private void extractToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (tagTreeView.SelectedNode?.Tag is CachedTagInstance tag)
            {
                using (var sfd = new SaveFileDialog())
                {
                    var groupName = CacheContext.GetString(tag.Group.Name);

                    sfd.Filter = $"{groupName} files (*.{groupName})|*.{groupName}";

                    if (sfd.ShowDialog() != DialogResult.OK)
                    {
                        return;
                    }

                    byte[] data;

                    using (var stream = CacheContext.OpenTagCacheRead())
                        data = CacheContext.TagCache.ExtractTagRaw(stream, tag);

                    using (var stream = File.Open(sfd.FileName, FileMode.Create, FileAccess.Write))
                        stream.Write(data, 0, data.Length);

                    MessageBox.Show($"Extracted {sfd.FileName} successfully.", "Extract Tag", MessageBoxButtons.OK);
                }
            }
        }
예제 #6
0
        private void SetRenderModelName(Stream stream, CachedTagInstance tag, ref Dictionary <int, string> tagNames)
        {
            if (tagNames.ContainsKey(tag.Index))
            {
                return;
            }

            tagNames[tag.Index] = $"{CacheContext.GetString(GetTagDefinition<RenderModel>(stream, tag).Name)}";
        }
예제 #7
0
        private void browseButton_Click(object sender, EventArgs e)
        {
            using (var sid = new StringIdDialog(CacheContext))
            {
                if (sid.ShowDialog() != DialogResult.OK)
                {
                    return;
                }

                textBox.Text = CacheContext.GetString(sid.Value);
            }
        }
예제 #8
0
            public override string ToString()
            {
                if (Tag == null)
                {
                    return("<null>");
                }

                var tagName = Tag.Name != null ?
                              $"[0x{Tag.Index:X4}] {Tag.Name}" :
                              $"0x{Tag.Index:X4}";

                return($"{tagName}.{CacheContext.GetString(Tag.Group.Name)}");
            }
예제 #9
0
        private bool ExtractObj(string variantName, FileInfo modelFile, RenderModel renderModel, RenderGeometryApiResourceDefinition resourceDefinition, Stream resourceStream)
        {
            var meshes           = new Dictionary <string, Mesh>();
            var vertexCompressor = new VertexCompressor(renderModel.Geometry.Compression[0]);

            foreach (var region in renderModel.Regions)
            {
                var regionName = CacheContext.GetString(region.Name);

                foreach (var permutation in region.Permutations)
                {
                    var permutationName = CacheContext.GetString(permutation.Name);

                    if (variantName != "*" && variantName != permutationName)
                    {
                        continue;
                    }

                    for (var i = 0; i < permutation.MeshCount; i++)
                    {
                        var name = $"{regionName}_{permutationName}_{i}";
                        meshes[name] = renderModel.Geometry.Meshes[permutation.MeshIndex + i];
                    }
                }
            }

            if (meshes.Count == 0)
            {
                Console.WriteLine($"ERROR: No meshes found under variant '{variantName}'!");
                return(false);
            }

            Console.Write("Extracting {0} mesh(es)...", meshes.Count);

            using (var objFile = new StreamWriter(modelFile.Create()))
            {
                var objExtractor = new ObjExtractor(objFile);

                foreach (var entry in meshes)
                {
                    var meshReader = new MeshReader(CacheContext.Version, entry.Value, resourceDefinition);
                    objExtractor.ExtractMesh(meshReader, vertexCompressor, resourceStream, entry.Key);
                }

                objExtractor.Finish();
            }

            Console.WriteLine("done!");

            return(true);
        }
예제 #10
0
        public void GetFieldValue(object owner, object value = null, object definition = null)
        {
            if (value == null)
            {
                value = Field.GetValue(owner);
            }

            Owner   = owner;
            Loading = true;

            textBox.Text = CacheContext.GetString((StringId)value);

            Loading = false;
        }
예제 #11
0
        int GetArgumentIndex(string name, List <RenderMethodTemplate.ShaderArgument> args)
        {
            int index = -1;

            for (int i = 0; i < args.Count; i++)
            {
                var varg = args[i];
                if (name == CacheContext.GetString(varg.Name))
                {
                    index = i;
                    break;
                }
            }
            return(index);
        }
예제 #12
0
        private void openButton_Click(object sender, EventArgs e)
        {
            if (!CacheContext.TryGetTag(textBox.Text, out var tag))
            {
                textBox.ForeColor = Color.Red;
                return;
            }

            textBox.ForeColor = SystemColors.WindowText;

            var tagName = tag.Name ?? $"0x{tag.Index:X4}";

            textBox.Text = $"{tagName}.{CacheContext.GetString(tag.Group.Name)}";

            Form.LoadTagEditor(tag);
        }
예제 #13
0
        private void browseButton_Click(object sender, EventArgs e)
        {
            using (var td = new TagDialog(CacheContext))
            {
                if (td.ShowDialog() != DialogResult.OK)
                {
                    return;
                }

                var tag = td.Value;

                var tagName = tag.Name ?? $"0x{tag.Index:X4}";

                textBox.Text = $"{tagName}.{CacheContext.GetString(tag.Group.Name)}";
            }
        }
예제 #14
0
        public override object Execute(List <string> args)
        {
            if (args.Count != 0)
            {
                return(false);
            }

            var shaderMaps = new Dictionary <StringId, CachedTagInstance>();

            foreach (var property in Definition.ShaderProperties)
            {
                RenderMethodTemplate template = null;

                using (var cacheStream = CacheContext.OpenTagCacheRead())
                    template = CacheContext.Deserialize <RenderMethodTemplate>(cacheStream, property.Template);

                for (var i = 0; i < template.SamplerArguments.Count; i++)
                {
                    var mapTemplate = template.SamplerArguments[i];

                    Console.Write(string.Format("Please enter the {0} index: ", CacheContext.GetString(mapTemplate.Name)));

                    if (!CacheContext.TryGetTag(Console.ReadLine(), out var shaderMap))
                    {
                        Console.WriteLine($"ERROR: Invalid bitmap name, setting to null.");
                        shaderMaps[mapTemplate.Name] = null;
                    }

                    property.ShaderMaps[i].Bitmap = shaderMaps[mapTemplate.Name];
                }
            }

            foreach (var import in Definition.ImportData)
            {
                if (shaderMaps.ContainsKey(import.Name))
                {
                    import.Bitmap = shaderMaps[import.Name];
                }
            }

            using (var cacheStream = CacheContext.OpenTagCacheReadWrite())
                CacheContext.Serialize(cacheStream, Tag, Definition);

            Console.WriteLine("Done!");

            return(true);
        }
예제 #15
0
        private string SaveTagChanges(CachedTagInstance tag, object definition)
        {
            using (var stream = CacheContext.OpenTagCacheReadWrite())
            {
                var context = new TagSerializationContext(stream, CacheContext, tag);
                CacheContext.Serializer.Serialize(context, definition);
            }

            var tagName = tag.Name ?? $"0x{tag.Index:X4}";

            if (tagName.Contains('\\'))
            {
                var index = tagName.LastIndexOf('\\') + 1;
                tagName = tagName.Substring(index, tagName.Length - index);
            }

            return($"{tagName}.{ CacheContext.GetString(CurrentTag.Group.Name)}");
        }
예제 #16
0
        public override object Execute(List <string> args)
        {
            if (args.Count != 0)
            {
                return(false);
            }

            var variantNames = Definition.Variants.Select(v => CacheContext.GetString(v.Name) ?? v.Name.ToString()).OrderBy(n => n).ToList();

            if (variantNames.Count == 0)
            {
                Console.WriteLine("Model has no variants");
                return(true);
            }

            foreach (var name in variantNames)
            {
                Console.WriteLine(name);
            }

            return(true);
        }
예제 #17
0
        private void SetScenarioName(Stream stream, CachedTagInstance tag, ref Dictionary <int, string> tagNames)
        {
            var definition = GetTagDefinition <Scenario>(stream, tag);

            var tagName      = CacheContext.GetString(definition.ZoneSets[0].Name);
            var slashIndex   = tagName.LastIndexOf('\\');
            var scenarioName = tagName.Substring(slashIndex + 1);

            tagNames[tag.Index] = tagName;

            var bsp = definition.StructureBsps[0].StructureBsp;

            if (bsp != null)
            {
                tagNames[bsp.Index] = tagName;
            }

            var design = definition.StructureBsps[0].Design;

            if (design != null)
            {
                tagNames[design.Index] = $"{tagName}_design";
            }

            var cubemap = definition.StructureBsps[0].Cubemap;

            if (cubemap != null)
            {
                tagNames[cubemap.Index] = $"{tagName}_{scenarioName}_cubemaps";
            }

            var skyObject = definition.SkyReferences[0].SkyObject;

            if (skyObject != null)
            {
                tagNames[skyObject.Index] = $"{tagName.Substring(0, slashIndex)}\\sky\\sky";
            }
        }
예제 #18
0
        public override object Execute(List <string> args)
        {
            foreach (var property in Definition.ShaderProperties)
            {
                RenderMethodTemplate template = null;

                using (var cacheStream = CacheContext.OpenTagCacheRead())
                    template = CacheContext.Deserialize <RenderMethodTemplate>(cacheStream, property.Template);

                for (var i = 0; i < template.VectorArguments.Count; i++)
                {
                    Console.WriteLine("");

                    var argumentName  = CacheContext.GetString(template.VectorArguments[i].Name);
                    var argumentValue = new RealQuaternion(property.Arguments[i].Values);

                    Console.WriteLine(string.Format("{0}:", argumentName));

                    if (argumentName.EndsWith("_map"))
                    {
                        Console.WriteLine(string.Format("\tX Scale: {0}", argumentValue.I));
                        Console.WriteLine(string.Format("\tY Scale: {0}", argumentValue.J));
                        Console.WriteLine(string.Format("\tX Offset: {0}", argumentValue.K));
                        Console.WriteLine(string.Format("\tY Offset: {0}", argumentValue.W));
                    }
                    else
                    {
                        Console.WriteLine(string.Format("\tX: {0}", argumentValue.I));
                        Console.WriteLine(string.Format("\tY: {0}", argumentValue.J));
                        Console.WriteLine(string.Format("\tZ: {0}", argumentValue.K));
                        Console.WriteLine(string.Format("\tW: {0}", argumentValue.W));
                    }
                }
            }

            return(true);
        }
예제 #19
0
        public override object Execute(List <string> args)
        {
            if (args.Count != 0)
            {
                return(false);
            }

            foreach (var property in Definition.ShaderProperties)
            {
                RenderMethodTemplate template = null;

                using (var cacheStream = CacheContext.OpenTagCacheRead())
                    template = CacheContext.Deserialize <RenderMethodTemplate>(cacheStream, property.Template);

                for (var i = 0; i < template.SamplerArguments.Count; i++)
                {
                    var mapTemplate = template.SamplerArguments[i];

                    Console.WriteLine($"Bitmap {i} ({CacheContext.GetString(mapTemplate.Name)}): {property.ShaderMaps[i].Bitmap.Group.Tag} 0x{property.ShaderMaps[i].Bitmap.Index:X4}");
                }
            }

            return(true);
        }
예제 #20
0
        private string GetLabel(IList elements, int index)
        {
            if (index < 0 || index >= elements.Count)
            {
                return(null);
            }

            foreach (var info in TagStructure.GetTagFieldEnumerable(elements.GetType().GetGenericArguments()[0], CacheContext.Version))
            {
                if (info.Attribute == null || !info.Attribute.Flags.HasFlag(TagFieldFlags.Label))
                {
                    continue;
                }

                var value = info.FieldInfo.GetValue(elements[index]);

                if (info.FieldType == typeof(string))
                {
                    return((string)value);
                }
                else if (info.FieldType == typeof(StringId))
                {
                    return(CacheContext.GetString((StringId)value));
                }
                else if (info.FieldType.IsPrimitive && Tag.IsInGroup <Scenario>())
                {
                    return(GetLabel((IList)typeof(Scenario).GetField(nameof(Scenario.ObjectNames)).GetValue(Owner), Convert.ToInt32(value)));
                }
                else
                {
                    return(value.ToString());
                }
            }

            return(null);
        }
예제 #21
0
        public void GetFieldValue(object owner, object value = null, object definition = null)
        {
            if (value == null)
            {
                value = Field.GetValue(owner);
            }

            Owner   = owner;
            Loading = true;

            if (value == null)
            {
                textBox.Text = "";
                return;
            }

            var tag = (CachedTagInstance)value;

            var tagName = tag.Name ?? $"0x{tag.Index:X4}";

            textBox.Text = $"{tagName}.{CacheContext.GetString(tag.Group.Name)}";

            Loading = false;
        }
예제 #22
0
        public override object Execute(List <string> args)
        {
            if (args.Count != 1)
            {
                return(false);
            }

            if (!CacheContext.TryGetTag(args[0], out var tag))
            {
                return(false);
            }

            using (var stream = CacheContext.OpenTagCacheReadWrite())
            {
                var tagName = tag.Name ?? "<unnamed>";

                Console.Write($"Nulling {tagName}.{CacheContext.GetString(tag.Group.Name)}...");
                CacheContext.TagCache.Index[tag.Index] = null;
                CacheContext.TagCache.SetTagDataRaw(stream, tag, new byte[] { });
                Console.WriteLine("done.");
            }

            return(true);
        }
예제 #23
0
        public void Render()
        {
            var variantName = Object.DefaultModelVariant != StringId.Invalid ?
                              CacheContext.GetString(Object.DefaultModelVariant) :
                              "default";

            var modelVariant = Model.Variants.FirstOrDefault(v => (CacheContext.GetString(v.Name) ?? v.Name.ToString()) == variantName);

            if (modelVariant == null && Model.Variants.Count > 0)
            {
                modelVariant = Model.Variants.First();
            }

            UpdateTransform();
            Device.Transform.World = World;

            foreach (var region in modelVariant.Regions)
            {
                if (region.RenderModelRegionIndex >= RenderModel.Regions.Count)
                {
                    continue;
                }

                var renderModelRegion = RenderModel.Regions[region.RenderModelRegionIndex];

                if (region.Permutations.Count == 0)
                {
                    continue;
                }

                var permutation = region.Permutations[0];

                if (permutation.RenderModelPermutationIndex < 0 || permutation.RenderModelPermutationIndex >= renderModelRegion.Permutations.Count)
                {
                    continue;
                }

                var renderModelPermutation = renderModelRegion.Permutations[permutation.RenderModelPermutationIndex];

                var meshIndex       = renderModelPermutation.MeshIndex;
                var meshCount       = renderModelPermutation.MeshCount;
                var regionName      = CacheContext.GetString(region.Name) ?? region.Name.ToString();
                var permutationName = CacheContext.GetString(permutation.Name) ?? permutation.Name.ToString();

                for (var currentMeshIndex = 0; currentMeshIndex < meshCount; currentMeshIndex++)
                {
                    var mesh = RenderModel.Geometry.Meshes[meshIndex + currentMeshIndex];

                    var renderVertex  = VertexDefinition.Get(mesh.Type);
                    var streamTypes   = renderVertex.GetStreamTypes();
                    var streamIndex   = streamTypes.First().Key;
                    var primitiveType = D3DPrimitiveType.TriangleList;

                    switch (mesh.IndexBufferType)
                    {
                    case TagPrimitiveType.PointList:
                        primitiveType = D3DPrimitiveType.PointList;
                        break;

                    case TagPrimitiveType.LineList:
                        primitiveType = D3DPrimitiveType.LineList;
                        break;

                    case TagPrimitiveType.LineStrip:
                        primitiveType = D3DPrimitiveType.LineStrip;
                        break;

                    case TagPrimitiveType.TriangleList:
                        primitiveType = D3DPrimitiveType.TriangleList;
                        break;

                    case TagPrimitiveType.TriangleFan:
                        primitiveType = D3DPrimitiveType.TriangleFan;
                        break;

                    case TagPrimitiveType.TriangleStrip:
                        primitiveType = D3DPrimitiveType.TriangleStrip;
                        break;
                    }

                    Device.VertexDeclaration = renderVertex.GetDeclaration(Device);
                    Device.SetStreamSource(streamTypes.First().Key, VertexBuffers[mesh.VertexBufferIndices[streamIndex]], 0);
                    Device.Indices = IndexBuffers[mesh.IndexBufferIndices.Where(index => index != ushort.MaxValue).First()];

                    foreach (var part in mesh.Parts)
                    {
                        if (part.MaterialIndex != -1)
                        {
                            var material = Materials[part.MaterialIndex];

                            Device.RenderState.AlphaBlendEnable = (part.TypeNew == TagTool.Geometry.Mesh.Part.PartTypeNew.Transparent);

                            foreach (var entry in material.Textures)
                            {
                                var name = entry.Key;

                                if (name.StartsWith("diffuse_map") || name.StartsWith("base_map") || name == "foam_texture")
                                {
                                    Device.SetTexture(0, entry.Value.Texture);
                                    break;
                                }
                            }

                            Device.TextureState[0].ColorOperation = TextureOperation.Modulate;
                            Device.TextureState[0].ColorArgument1 = TextureArgument.TextureColor;
                            Device.TextureState[0].ColorArgument2 = TextureArgument.Current;
                            Device.RenderState.FillMode           = FillMode.Solid;
                        }

                        for (var currentSubPartIndex = 0; currentSubPartIndex < part.SubPartCount; currentSubPartIndex++)
                        {
                            var subPart = mesh.SubParts[part.FirstSubPartIndex + currentSubPartIndex];

                            Device.DrawIndexedPrimitives(primitiveType, 0, 0, subPart.VertexCount, subPart.FirstIndex, subPart.IndexCount - (primitiveType == D3DPrimitiveType.TriangleStrip ? 2 : 0));
                        }
                    }
                }
            }
        }
예제 #24
0
        public override object Execute(List <string> args)
        {
            if (args.Count < 2)
            {
                return(false);
            }

            var fieldName      = args[0];
            var fieldNameLow   = fieldName.ToLower();
            var fieldNameSnake = fieldName.ToSnakeCase();

            var previousContext   = ContextStack.Context;
            var previousOwner     = Owner;
            var previousStructure = Structure;

            if (fieldName.Contains("."))
            {
                var lastIndex = fieldName.LastIndexOf('.');
                var blockName = fieldName.Substring(0, lastIndex);
                fieldName      = fieldName.Substring(lastIndex + 1, (fieldName.Length - lastIndex) - 1);
                fieldNameLow   = fieldName.ToLower();
                fieldNameSnake = fieldName.ToSnakeCase();

                var command = new EditBlockCommand(ContextStack, CacheContext, Tag, Owner);

                if (command.Execute(new List <string> {
                    blockName
                }).Equals(false))
                {
                    while (ContextStack.Context != previousContext)
                    {
                        ContextStack.Pop();
                    }
                    Owner     = previousOwner;
                    Structure = previousStructure;
                    return(false);
                }

                command = (ContextStack.Context.GetCommand("EditBlock") as EditBlockCommand);

                Owner     = command.Owner;
                Structure = command.Structure;

                if (Owner == null)
                {
                    while (ContextStack.Context != previousContext)
                    {
                        ContextStack.Pop();
                    }
                    Owner     = previousOwner;
                    Structure = previousStructure;
                    return(false);
                }
            }

            var field = TagStructure.GetTagFieldEnumerable(Structure)
                        .Find(f =>
                              f.Name == fieldName ||
                              f.Name.ToLower() == fieldNameLow ||
                              f.Name.ToSnakeCase() == fieldNameSnake);

            if (field == null)
            {
                Console.WriteLine("ERROR: {0} does not contain a field named \"{1}\".", Structure.Types[0].Name, fieldName);
                while (ContextStack.Context != previousContext)
                {
                    ContextStack.Pop();
                }
                Owner     = previousOwner;
                Structure = previousStructure;
                return(false);
            }

            var fieldType  = field.FieldType;
            var fieldAttrs = field.GetCustomAttributes(typeof(TagFieldAttribute), false);
            var fieldAttr  = fieldAttrs?.Length < 1 ? new TagFieldAttribute() : (TagFieldAttribute)fieldAttrs[0];
            var fieldInfo  = new TagFieldInfo(field, fieldAttr, uint.MaxValue, uint.MaxValue);
            var fieldValue = ParseArgs(field.FieldType, fieldInfo, args.Skip(1).ToList());

            if (fieldValue != null && fieldValue.Equals(false))
            {
                while (ContextStack.Context != previousContext)
                {
                    ContextStack.Pop();
                }
                Owner     = previousOwner;
                Structure = previousStructure;
                return(false);
            }

            if (field.FieldType == typeof(PageableResource))
            {
                var ownerValue = field.GetValue(Owner);

                if (fieldValue == null)
                {
                    field.SetValue(Owner, null);
                }
                else if (ownerValue is PageableResource pageable)
                {
                    var newLocation = ResourceLocation.None;

                    FileInfo resourceFile = null;

                    switch (fieldValue)
                    {
                    case FileInfo file:
                        if (!pageable.GetLocation(out newLocation))
                        {
                            newLocation = ResourceLocation.ResourcesB;
                        }
                        resourceFile = file;
                        break;

                    case ValueTuple <ResourceLocation, FileInfo> tuple:
                        newLocation  = tuple.Item1;
                        resourceFile = tuple.Item2;
                        break;

                    default:
                        throw new FormatException(fieldValue.ToString());
                    }

                    ResourceCache oldCache = null;

                    if (pageable.GetLocation(out var oldLocation))
                    {
                        oldCache = CacheContext.GetResourceCache(oldLocation);
                    }

                    var newCache = CacheContext.GetResourceCache(newLocation);

                    var data = File.ReadAllBytes(resourceFile.FullName);

                    pageable.Page.UncompressedBlockSize = (uint)data.Length;

                    if (oldLocation == newLocation && pageable.Page.Index != -1)
                    {
                        using (var stream = CacheContext.OpenResourceCacheReadWrite(oldLocation))
                        {
                            pageable.Page.CompressedBlockSize = oldCache.Compress(stream, pageable.Page.Index, data);
                        }
                    }
                    else
                    {
                        using (var destStream = CacheContext.OpenResourceCacheReadWrite(newLocation))
                        {
                            pageable.Page.Index = newCache.Add(destStream, data, out pageable.Page.CompressedBlockSize);
                        }

                        pageable.ChangeLocation(newLocation);
                    }

                    pageable.DisableChecksum();

                    field.SetValue(Owner, fieldValue = pageable);
                }
            }
            else
            {
                field.SetValue(Owner, fieldValue);
            }

            var typeString =
                fieldType.IsGenericType ?
                $"{fieldType.Name}<{fieldType.GenericTypeArguments[0].Name}>" :
                fieldType.Name;

            string valueString;

#if !DEBUG
            try
            {
#endif
            if (fieldValue == null)
            {
                valueString = "null";
            }
            else if (fieldType == typeof(StringId))
            {
                valueString = CacheContext.GetString((StringId)fieldValue);
            }
            else if (fieldType == typeof(CachedTagInstance))
            {
                var instance = (CachedTagInstance)fieldValue;

                var tagName = instance?.Name ?? $"0x{instance.Index:X4}";

                valueString = $"[0x{instance.Index:X4}] {tagName}.{CacheContext.GetString(instance.Group.Name)}";
            }
            else if (fieldType == typeof(TagFunction))
            {
                var function = (TagFunction)fieldValue;
                valueString = "";
                foreach (var datum in function.Data)
                {
                    valueString += datum.ToString("X2");
                }
            }
            else if (fieldType == typeof(PageableResource))
            {
                var pageable = (PageableResource)fieldValue;
                pageable.GetLocation(out var location);
                valueString = pageable == null ? "null" : $"{{ Location: {location}, Index: 0x{pageable.Page.Index:X4}, CompressedSize: 0x{pageable.Page.CompressedBlockSize:X8} }}";
            }
            else if (fieldInfo.FieldType.IsArray && fieldInfo.Attribute.Length != 0)
            {
                valueString = fieldValue == null ? "null" : $"[{fieldInfo.Attribute.Length}] {{ ";
                var valueArray = (Array)fieldValue;

                if (fieldValue != null)
                {
                    for (var i = 0; i < fieldInfo.Attribute.Length; i++)
                    {
                        valueString += $"{valueArray.GetValue(i)}{((i + 1) < fieldInfo.Attribute.Length ? "," : "")} ";
                    }

                    valueString += "}";
                }
            }
            else if (fieldType.GetInterface(typeof(IList).Name) != null)
            {
                valueString =
                    ((IList)fieldValue).Count != 0 ?
                    $"{{...}}[{((IList)fieldValue).Count}]" :
                    "null";
            }
            else
            {
                valueString = fieldValue.ToString();
            }
#if !DEBUG
        }

        catch (Exception e)
        {
            valueString = $"<ERROR MESSAGE=\"{e.Message}\" />";
        }
#endif

            var fieldFullName     = $"{field.DeclaringType.FullName}.{field.Name}".Replace("+", ".");
            var documentationNode = EditTagContextFactory.Documentation.SelectSingleNode($"//member[starts-with(@name, 'F:{fieldFullName}')]");

            Console.WriteLine("{0}: {1} = {2} {3}", field.Name, typeString, valueString,
                              documentationNode != null ?
                              $":: {documentationNode.FirstChild.InnerText.Replace("\r\n", "").TrimStart().TrimEnd()}" :
                              "");

            while (ContextStack.Context != previousContext)
            {
                ContextStack.Pop();
            }
            Owner     = previousOwner;
            Structure = previousStructure;

            return(true);
        }
예제 #25
0
        private void WriteValueExpression(HsSyntaxNode expr, BinaryReader stringReader, StreamWriter scriptWriter)
        {
            var valueType = (HsType.Halo3ODSTValue)Enum.Parse(typeof(HsType.Halo3ODSTValue), expr.ValueType.HaloOnline.ToString());

            switch (valueType)
            {
            case HsType.Halo3ODSTValue.FunctionName:
                scriptWriter.Write(expr.StringAddress == 0 ? OpcodeLookup(expr.Opcode) : ReadScriptString(stringReader, expr.StringAddress));
                break;     //Trust the string table, its faster than going through the dictionary with OpcodeLookup.

            case HsType.Halo3ODSTValue.Boolean:
                scriptWriter.Write(expr.Data[0] == 0 ? "false" : "true");
                break;

            case HsType.Halo3ODSTValue.Real:
                scriptWriter.Write(BitConverter.ToSingle(new[] { expr.Data[0], expr.Data[1], expr.Data[2], expr.Data[3] }, 0));
                break;

            case HsType.Halo3ODSTValue.Short:
                scriptWriter.Write(BitConverter.ToInt16(new[] { expr.Data[0], expr.Data[1], }, 0));
                break;

            case HsType.Halo3ODSTValue.Long:
                scriptWriter.Write(BitConverter.ToInt32(new[] { expr.Data[0], expr.Data[1], expr.Data[2], expr.Data[3] }, 0));
                break;

            case HsType.Halo3ODSTValue.String:
                scriptWriter.Write(expr.StringAddress == 0 ? "none" : $"\"{ReadScriptString(stringReader, expr.StringAddress)}\"");
                break;

            case HsType.Halo3ODSTValue.Script:
                scriptWriter.Write(Definition.Scripts[BitConverter.ToInt16(new[] { expr.Data[0], expr.Data[1] }, 0)].ScriptName);
                break;

            case HsType.Halo3ODSTValue.StringId:
                scriptWriter.Write(CacheContext.GetString(new StringId(BitConverter.ToUInt32(new[] { expr.Data[0], expr.Data[1], expr.Data[2], expr.Data[3] }, 0))));
                break;

            case HsType.Halo3ODSTValue.GameDifficulty:
                switch (BitConverter.ToInt16(new[] { expr.Data[0], expr.Data[1] }, 0))
                {
                case 0: scriptWriter.Write("easy"); break;

                case 1: scriptWriter.Write("normal"); break;

                case 2: scriptWriter.Write("heroic"); break;

                case 3: scriptWriter.Write("legendary"); break;

                default: throw new NotImplementedException();
                }
                break;

            case HsType.Halo3ODSTValue.Object:
            case HsType.Halo3ODSTValue.Device:
            case HsType.Halo3ODSTValue.CutsceneCameraPoint:
            case HsType.Halo3ODSTValue.TriggerVolume:
            case HsType.Halo3ODSTValue.UnitSeatMapping:
            case HsType.Halo3ODSTValue.Vehicle:
            case HsType.Halo3ODSTValue.VehicleName:
                scriptWriter.Write(expr.StringAddress == 0 ? "none" : $"\"{ReadScriptString(stringReader, expr.StringAddress)}\"");
                break;

            default:
                scriptWriter.Write($"<UNIMPLEMENTED VALUE: {expr.Flags.ToString()} {expr.ValueType.ToString()}>");
                break;
            }
        }
예제 #26
0
        public override object Execute(List <string> args)
        {
            if (args.Count < 2)
            {
                return(false);
            }

            //
            // Verify Blam tag instance
            //

            var unitName = args[0].ToLower();

            if (unitName != "spartan" && unitName != "elite")
            {
                Console.WriteLine("ERROR: Only 'spartan' and 'elite' armor variants are allowed.");
                return(false);
            }

            args.RemoveAt(0);

            var blamTagName = unitName == "spartan" ?
                              @"objects\characters\masterchief\mp_masterchief\mp_masterchief" :
                              @"objects\characters\elite\mp_elite\mp_elite";

            Console.Write($"Verifying {blamTagName}.render_model...");

            CacheFile.IndexItem blamTag = null;

            foreach (var tag in BlamCache.IndexItems)
            {
                if ((tag.GroupTag == "mode") && (tag.Name == blamTagName))
                {
                    blamTag = tag;
                    break;
                }
            }

            if (blamTag == null)
            {
                Console.WriteLine($"ERROR: Blam tag does not exist: {blamTagName}.render_model");
                return(true);
            }

            Console.WriteLine("done.");

            //
            // Load the Blam tag definition
            //

            var variantName = args[0];

            args.RemoveAt(0);

            CachedTagInstance edModeTag = null;
            var isScenery   = false;
            var regionNames = new List <string>();

            while (args.Count != 0)
            {
                switch (args[0].ToLower())
                {
                case "scenery":
                    isScenery = true;
                    args.RemoveAt(0);
                    break;

                case "replace:":
                    edModeTag = CacheContext.GetTag(args[1]);
                    args.RemoveAt(1);
                    args.RemoveAt(0);
                    break;

                case "regions:":
                    regionNames.AddRange(args.Skip(1));
                    args.Clear();
                    break;

                default:
                    throw new InvalidDataException($"{args}");
                }
            }

            var blamContext      = new CacheSerializationContext(ref BlamCache, blamTag);
            var edModeDefinition = BlamCache.Deserializer.Deserialize <RenderModel>(blamContext);

            var materials = edModeDefinition.Materials.Select(i => new RenderMaterial
            {
                BreakableSurfaceIndex = i.BreakableSurfaceIndex,
                Properties            = i.Properties,
                RenderMethod          = i.RenderMethod,
                Skins    = i.Skins,
                Unknown  = i.Unknown,
                Unknown2 = i.Unknown2,
                Unknown3 = i.Unknown3,
                Unknown4 = i.Unknown4
            }).ToList();

            edModeDefinition = (RenderModel)ConvertData(null, edModeDefinition, false);

            var variantRegions = new List <RenderModel.Region>();

            foreach (var region in edModeDefinition.Regions)
            {
                if (regionNames.Count != 0 && !regionNames.Contains(CacheContext.GetString(region.Name)))
                {
                    continue;
                }

                var variantRegion = new RenderModel.Region
                {
                    Name         = region.Name,
                    Permutations = new List <RenderModel.Region.Permutation>()
                };

                foreach (var permutation in region.Permutations)
                {
                    if (variantName == CacheContext.GetString(permutation.Name))
                    {
                        variantRegion.Permutations.Add(permutation);
                    }
                }

                variantRegions.Add(variantRegion);
            }

            var variantMeshes        = new List <int>();
            var variantMaterials     = new List <int>();
            var variantVertexBuffers = new List <int>();
            var variantIndexBuffers  = new List <int>();

            foreach (var region in variantRegions)
            {
                foreach (var permutation in region.Permutations)
                {
                    for (var i = permutation.MeshIndex; i < (short)(permutation.MeshIndex + permutation.MeshCount); i++)
                    {
                        var mesh = edModeDefinition.Geometry.Meshes[i];

                        foreach (var part in mesh.Parts)
                        {
                            if (part.MaterialIndex != -1 && !variantMaterials.Contains(part.MaterialIndex))
                            {
                                variantMaterials.Add(part.MaterialIndex);
                            }
                        }

                        foreach (var vertexBuffer in mesh.VertexBufferIndices)
                        {
                            if (vertexBuffer != ushort.MaxValue && !variantVertexBuffers.Contains(vertexBuffer))
                            {
                                variantVertexBuffers.Add(vertexBuffer);
                            }
                        }

                        foreach (var indexBuffer in mesh.IndexBufferIndices)
                        {
                            if (indexBuffer != ushort.MaxValue && !variantIndexBuffers.Contains(indexBuffer))
                            {
                                variantIndexBuffers.Add(indexBuffer);
                            }
                        }

                        if (!variantMeshes.Contains(i))
                        {
                            variantMeshes.Add(i);
                        }
                    }
                }
            }

            variantMeshes.Sort();
            variantMaterials.Sort();
            variantVertexBuffers.Sort();
            variantIndexBuffers.Sort();

            foreach (var meshIndex in variantMeshes)
            {
                var mesh = edModeDefinition.Geometry.Meshes[meshIndex];

                foreach (var part in mesh.Parts)
                {
                    if (part.MaterialIndex != -1)
                    {
                        part.MaterialIndex = (short)variantMaterials.IndexOf(part.MaterialIndex);
                    }
                }
            }

            foreach (var region in variantRegions)
            {
                foreach (var permutation in region.Permutations)
                {
                    if (permutation.MeshIndex != -1)
                    {
                        permutation.MeshIndex = (short)variantMeshes.IndexOf(permutation.MeshIndex);
                    }
                }
            }

            foreach (var meshIndex in variantMeshes)
            {
                var mesh = edModeDefinition.Geometry.Meshes[meshIndex];

                for (var i = 0; i < mesh.VertexBufferIndices.Length; i++)
                {
                    if (!variantVertexBuffers.Contains(mesh.VertexBufferIndices[i]))
                    {
                        mesh.VertexBufferIndices[i] = ushort.MaxValue;
                    }
                    else
                    {
                        mesh.VertexBufferIndices[i] = (ushort)variantVertexBuffers.IndexOf(mesh.VertexBufferIndices[i]);
                    }
                }

                for (var i = 0; i < mesh.IndexBufferIndices.Length; i++)
                {
                    if (!variantIndexBuffers.Contains(mesh.IndexBufferIndices[i]))
                    {
                        mesh.IndexBufferIndices[i] = ushort.MaxValue;
                    }
                    else
                    {
                        mesh.IndexBufferIndices[i] = (ushort)variantIndexBuffers.IndexOf(mesh.IndexBufferIndices[i]);
                    }
                }
            }

            edModeDefinition.Regions         = variantRegions;
            edModeDefinition.Geometry.Meshes = edModeDefinition.Geometry.Meshes.Where(i => variantMeshes.Contains(edModeDefinition.Geometry.Meshes.IndexOf(i))).ToList();

            //
            // Port Blam render_model materials
            //

            materials = materials.Where(i => variantMaterials.Contains(materials.IndexOf(i))).ToList();

            using (var stream = CacheContext.OpenTagCacheReadWrite())
            {
                for (var i = 0; i < materials.Count; i++)
                {
                    var material = materials[i];

                    if (material.RenderMethod.Index == -1)
                    {
                        continue;
                    }

                    var blamRenderMethod    = materials[i].RenderMethod;
                    var blamRenderMethodTag = BlamCache.IndexItems.GetItemByID(blamRenderMethod.Index);

                    var renderMethodExists = false;

                    foreach (var instance in CacheContext.TagCache.Index.FindAllInGroup("rm  "))
                    {
                        if (instance?.Name == blamRenderMethodTag.Name)
                        {
                            renderMethodExists    = true;
                            material.RenderMethod = instance;
                            break;
                        }
                    }

                    if (!renderMethodExists)
                    {
                        material.RenderMethod = CacheContext.GetTag <Shader>(@"shaders\invalid");
                    }
                }
            }

            edModeDefinition.Materials = materials;

            //
            // Load Blam resource data
            //

            var resourceData = BlamCache.GetRawFromID(edModeDefinition.Geometry.ZoneAssetHandle);

            if (resourceData == null)
            {
                Console.WriteLine("Blam render_geometry resource contains no data.");
                return(true);
            }

            //
            // Load Blam resource definition
            //

            Console.Write("Loading Blam render_geometry resource definition...");

            var definitionEntry = BlamCache.ResourceGestalt.TagResources[edModeDefinition.Geometry.ZoneAssetHandle.Index];

            var resourceDefinition = new RenderGeometryApiResourceDefinition
            {
                VertexBuffers = new List <TagStructureReference <VertexBufferDefinition> >(),
                IndexBuffers  = new List <TagStructureReference <IndexBufferDefinition> >()
            };

            using (var definitionStream = new MemoryStream(BlamCache.ResourceGestalt.FixupInformation))
                using (var definitionReader = new EndianReader(definitionStream, EndianFormat.BigEndian))
                {
                    var dataContext = new DataSerializationContext(definitionReader, null, CacheResourceAddressType.Definition);

                    definitionReader.SeekTo(definitionEntry.FixupInformationOffset + (definitionEntry.FixupInformationLength - 24));

                    var vertexBufferCount = definitionReader.ReadInt32();
                    definitionReader.Skip(8);
                    var indexBufferCount = definitionReader.ReadInt32();

                    definitionReader.SeekTo(definitionEntry.FixupInformationOffset);

                    for (var i = 0; i < vertexBufferCount; i++)
                    {
                        resourceDefinition.VertexBuffers.Add(new TagStructureReference <VertexBufferDefinition>
                        {
                            Definition = new VertexBufferDefinition
                            {
                                Count      = definitionReader.ReadInt32(),
                                Format     = (VertexBufferFormat)definitionReader.ReadInt16(),
                                VertexSize = definitionReader.ReadInt16(),
                                Data       = new TagData
                                {
                                    Size     = definitionReader.ReadInt32(),
                                    Unused4  = definitionReader.ReadInt32(),
                                    Unused8  = definitionReader.ReadInt32(),
                                    Address  = new CacheResourceAddress(CacheResourceAddressType.Memory, definitionReader.ReadInt32()),
                                    Unused10 = definitionReader.ReadInt32()
                                }
                            }
                        });
                    }

                    definitionReader.Skip(vertexBufferCount * 12);

                    for (var i = 0; i < indexBufferCount; i++)
                    {
                        resourceDefinition.IndexBuffers.Add(new TagStructureReference <IndexBufferDefinition>
                        {
                            Definition = new IndexBufferDefinition
                            {
                                Format = (IndexBufferFormat)definitionReader.ReadInt32(),
                                Data   = new TagData
                                {
                                    Size     = definitionReader.ReadInt32(),
                                    Unused4  = definitionReader.ReadInt32(),
                                    Unused8  = definitionReader.ReadInt32(),
                                    Address  = new CacheResourceAddress(CacheResourceAddressType.Memory, definitionReader.ReadInt32()),
                                    Unused10 = definitionReader.ReadInt32()
                                }
                            }
                        });
                    }
                }

            Console.WriteLine("done.");

            //
            // Convert Blam resource data
            //

            using (var edResourceStream = new MemoryStream())
            {
                //
                // Convert Blam render_geometry_api_resource_definition
                //

                using (var blamResourceStream = new MemoryStream(resourceData))
                {
                    //
                    // Convert Blam vertex buffers
                    //

                    Console.Write("Converting vertex buffers...");

                    var previousVertexBufferCount = -1;

                    for (var i = 0; i < resourceDefinition.VertexBuffers.Count; i++)
                    {
                        if (!variantVertexBuffers.Contains(i))
                        {
                            continue;
                        }

                        blamResourceStream.Position = definitionEntry.ResourceFixups[i].Offset;
                        if (i > 0)
                        {
                            previousVertexBufferCount = resourceDefinition.VertexBuffers[i - 1].Definition.Count;
                        }
                        GeometryConverter.ConvertVertexBuffer(resourceDefinition, blamResourceStream, edResourceStream, i, previousVertexBufferCount);
                    }

                    Console.WriteLine("done.");

                    //
                    // Convert Blam index buffers
                    //

                    Console.Write("Converting index buffers...");

                    for (var i = 0; i < resourceDefinition.IndexBuffers.Count; i++)
                    {
                        if (!variantIndexBuffers.Contains(i))
                        {
                            continue;
                        }

                        blamResourceStream.Position = definitionEntry.ResourceFixups[resourceDefinition.VertexBuffers.Count * 2 + i].Offset;
                        GeometryConverter.ConvertIndexBuffer(resourceDefinition, blamResourceStream, edResourceStream, i);
                    }

                    Console.WriteLine("done.");
                }

                resourceDefinition.VertexBuffers = resourceDefinition.VertexBuffers.Where(i => variantVertexBuffers.Contains(resourceDefinition.VertexBuffers.IndexOf(i))).ToList();
                resourceDefinition.IndexBuffers  = resourceDefinition.IndexBuffers.Where(i => variantIndexBuffers.Contains(resourceDefinition.IndexBuffers.IndexOf(i))).ToList();

                //
                // Finalize the new ElDorado geometry resource
                //

                Console.Write("Writing resource data...");

                edModeDefinition.Geometry.Resource = new PageableResource
                {
                    Page     = new RawPage(),
                    Resource = new TagResourceGen3
                    {
                        ResourceType             = TagResourceTypeGen3.RenderGeometry,
                        ResourceFixups           = new List <TagResourceGen3.ResourceFixup>(),
                        ResourceDefinitionFixups = new List <TagResourceGen3.ResourceDefinitionFixup>(),
                        Unknown2 = 1
                    }
                };

                edResourceStream.Position = 0;

                var resourceContext = new ResourceSerializationContext(CacheContext, edModeDefinition.Geometry.Resource);
                CacheContext.Serializer.Serialize(resourceContext, resourceDefinition);
                edModeDefinition.Geometry.Resource.ChangeLocation(ResourceLocation.ResourcesB);
                CacheContext.AddResource(edModeDefinition.Geometry.Resource, edResourceStream);

                Console.WriteLine("done.");
            }

            edModeDefinition.Name = CacheContext.GetStringId(variantName);

            if (edModeTag == null)
            {
                for (var i = 0; i < CacheContext.TagCache.Index.Count; i++)
                {
                    if (CacheContext.TagCache.Index[i] == null)
                    {
                        CacheContext.TagCache.Index[i] = edModeTag = new CachedTagInstance(i, TagGroup.Instances[new Tag("mode")]);
                        break;
                    }
                }

                if (edModeTag == null)
                {
                    edModeTag = CacheContext.TagCache.AllocateTag(TagGroup.Instances[new Tag("mode")]);
                }
            }

            //
            // Create a new armor model tag
            //

            Model             edHlmtDefinition = null;
            CachedTagInstance edHlmtTag        = null;

            if (isScenery)
            {
                Console.Write($"Verifying {blamTagName}.model...");

                CacheFile.IndexItem blamHlmtTag = null;

                foreach (var tag in BlamCache.IndexItems)
                {
                    if ((tag.GroupTag == "hlmt") && (tag.Name == blamTagName))
                    {
                        blamHlmtTag = tag;
                        break;
                    }
                }

                if (blamHlmtTag == null)
                {
                    Console.WriteLine($"ERROR: Blam tag does not exist: {blamTagName}.model");
                    return(true);
                }

                Console.WriteLine("done.");

                blamContext      = new CacheSerializationContext(ref BlamCache, blamHlmtTag);
                edHlmtDefinition = (Model)ConvertData(null, BlamCache.Deserializer.Deserialize <Model>(blamContext), false);

                edHlmtDefinition.RenderModel        = edModeTag;
                edHlmtDefinition.ReduceToL1SuperLow = 36.38004f;
                edHlmtDefinition.ReduceToL2Low      = 27.28503f;
                edHlmtDefinition.Variants           = new List <Model.Variant>();
                edHlmtDefinition.Materials          = new List <Model.Material>();
                edHlmtDefinition.NewDamageInfo      = new List <Model.GlobalDamageInfoBlock>();
                edHlmtDefinition.Targets            = new List <Model.Target>();

                var collisionRegions = new List <Model.CollisionRegion>();

                foreach (var collisionRegion in edHlmtDefinition.CollisionRegions)
                {
                    var found = false;

                    foreach (var variantRegion in variantRegions)
                    {
                        if (collisionRegion.Name == variantRegion.Name)
                        {
                            found = true;
                            break;
                        }
                    }

                    if (!found)
                    {
                        continue;
                    }

                    found = false;

                    foreach (var permutation in collisionRegion.Permutations)
                    {
                        if (permutation.Name == CacheContext.GetStringId(variantName))
                        {
                            found = true;
                            break;
                        }
                    }

                    if (found)
                    {
                        collisionRegions.Add(collisionRegion);
                    }
                }

                foreach (var collisionRegion in collisionRegions)
                {
                    Model.CollisionRegion.Permutation permutation = null;

                    foreach (var collisionPermutation in collisionRegion.Permutations)
                    {
                        if (collisionPermutation.Name == CacheContext.GetStringId(variantName))
                        {
                            permutation = collisionPermutation;
                            break;
                        }
                    }

                    if (permutation == null)
                    {
                        throw new KeyNotFoundException();
                    }

                    collisionRegion.Permutations = new List <Model.CollisionRegion.Permutation> {
                        permutation
                    };
                }

                edHlmtDefinition.CollisionRegions = collisionRegions;

                for (var i = 0; i < CacheContext.TagCache.Index.Count; i++)
                {
                    if (CacheContext.TagCache.Index[i] == null)
                    {
                        CacheContext.TagCache.Index[i] = edHlmtTag = new CachedTagInstance(i, TagGroup.Instances[new Tag("hlmt")]);
                        break;
                    }
                }

                if (edHlmtTag == null)
                {
                    edHlmtTag = CacheContext.TagCache.AllocateTag(TagGroup.Instances[new Tag("hlmt")]);
                }
            }

            //
            // Create a new armor scenery tag
            //

            Scenery           edScenDefinition = null;
            CachedTagInstance edScenTag        = null;

            if (isScenery)
            {
                edScenDefinition = new Scenery
                {
                    ObjectType = new GameObjectType
                    {
                        Halo2       = GameObjectTypeHalo2.Scenery,
                        Halo3Retail = GameObjectTypeHalo3Retail.Scenery,
                        Halo3ODST   = GameObjectTypeHalo3ODST.Scenery,
                        HaloOnline  = GameObjectTypeHaloOnline.Scenery
                    },
                    BoundingRadius    = 0.44f,
                    BoundingOffset    = new RealPoint3d(-0.02f, 0.0f, 0.0f),
                    AccelerationScale = 1.2f,
                    SweetenerSize     = GameObject.SweetenerSizeValue.Medium,
                    Model             = edHlmtTag,
                    ChangeColors      = new List <GameObject.ChangeColor>
                    {
                        new GameObject.ChangeColor(),
                        new GameObject.ChangeColor(),
                        new GameObject.ChangeColor(),
                        new GameObject.ChangeColor(),
                        new GameObject.ChangeColor()
                    },
                    NodeMaps = new List <GameObject.NodeMap>()
                };

                for (sbyte i = 0; i < 51; i++)
                {
                    edScenDefinition.NodeMaps.Add(new GameObject.NodeMap {
                        TargetNode = i
                    });
                }

                for (var i = 0; i < CacheContext.TagCache.Index.Count; i++)
                {
                    if (CacheContext.TagCache.Index[i] == null)
                    {
                        CacheContext.TagCache.Index[i] = edScenTag = new CachedTagInstance(i, TagGroup.Instances[new Tag("scen")]);
                        break;
                    }
                }

                if (edScenTag == null)
                {
                    edScenTag = CacheContext.TagCache.AllocateTag(TagGroup.Instances[new Tag("scen")]);
                }
            }

            //
            // Serialize new ElDorado tag definitions
            //

            using (var cacheStream = CacheContext.OpenTagCacheReadWrite())
            {
                CacheContext.Serialize(cacheStream, edModeTag, edModeDefinition);
                edModeTag.Name = isScenery ?
                                 (unitName == "spartan" ?
                                  $@"objects\characters\masterchief\mp_masterchief\armor\{variantName}" :
                                  $@"objects\characters\elite\mp_elite\armor\{variantName}") :
                                 (unitName == "spartan" ?
                                  @"objects\characters\masterchief\mp_masterchief\mp_masterchief" :
                                  @"objects\characters\elite\mp_elite\mp_elite");

                if (isScenery)
                {
                    CacheContext.Serialize(cacheStream, edHlmtTag, edHlmtDefinition);
                    CacheContext.Serialize(cacheStream, edScenTag, edScenDefinition);
                    edScenTag.Name = unitName == "spartan" ?
                                     $@"objects\characters\masterchief\mp_masterchief\armor\{variantName}" :
                                     $@"objects\characters\elite\mp_elite\armor\{variantName}";
                }
            }

            return(true);
        }
예제 #27
0
        public void GetFieldValue(object owner, object value = null, object definition = null)
        {
            if (value == null)
            {
                value = Field.GetValue(owner);
            }

            if (value == null)
            {
                value = Activator.CreateInstance(Field.FieldType);
            }

            Owner = owner;
            elementsComboBox.Items.Clear();

            Definition = definition;

            var elements = value as IList;

            FieldInfo labelField = null;

            var enumerator = TagStructure.GetTagFieldEnumerable(new TagStructureInfo((Field?.FieldType ?? value.GetType()).GenericTypeArguments[0], Struct.CacheContext.Version));

            foreach (var fieldInfo in enumerator)
            {
                if (fieldInfo.Attribute.Flags.HasFlag(TagFieldFlags.Label))
                {
                    labelField = fieldInfo.FieldInfo;
                    break;
                }
            }

            for (var i = 0; i < elements.Count; i++)
            {
                var label = "";

                if (labelField != null)
                {
                    if (labelField.FieldType == typeof(string))
                    {
                        label = (string)labelField.GetValue(elements[i]);
                    }
                    else if (labelField.FieldType == typeof(StringId))
                    {
                        label = CacheContext.GetString((StringId)labelField.GetValue(elements[i]));
                    }
                    else if (labelField.FieldType.IsEnum)
                    {
                        label = labelField.GetValue(elements[i]).ToString().ToSnakeCase();
                    }
                    else if (labelField.FieldType == typeof(short))
                    {
                        if (definition != null)
                        {
                            if (definition.GetType() == typeof(Scenario))
                            {
                                var index = (short)labelField.GetValue(elements[i]);
                                var names = ((Scenario)definition).ObjectNames;

                                if (index >= 0 && index < names.Count)
                                {
                                    label = ((Scenario)definition).ObjectNames[index].Name;
                                }
                            }
                        }
                    }
                    else if (labelField.FieldType == typeof(CachedTagInstance))
                    {
                        var instance = (CachedTagInstance)labelField.GetValue(elements[i]);

                        if (instance != null)
                        {
                            var tagName = instance.Name ?? $"0x{instance.Index:X4}";

                            if (tagName.Contains("\\"))
                            {
                                var index = tagName.LastIndexOf('\\') + 1;
                                tagName = tagName.Substring(index, tagName.Length - index);
                            }

                            label = tagName;
                        }
                    }
                }

                elementsComboBox.Items.Add(new TagBlockElement(i, label, elements[i]));
            }

            if (elementsComboBox.Items.Count > 0)
            {
                elementsComboBox.SelectedIndex = 0;
            }
            else
            {
                Struct.Enabled = false;
            }
        }
예제 #28
0
        public override object Execute(List <string> args)
        {
            if (args.Count != 1)
            {
                return(false);
            }

            if (Definition.CollisionBspResource == null)
            {
                Console.WriteLine("ERROR: Collision geometry does not have a resource associated with it.");
                return(true);
            }

            var resourceContext    = new ResourceSerializationContext(CacheContext, Definition.CollisionBspResource);
            var resourceDefinition = CacheContext.Deserializer.Deserialize <StructureBspTagResources>(resourceContext);

            using (var resourceStream = new MemoryStream())
            {
                CacheContext.ExtractResource(Definition.CollisionBspResource, resourceStream);

                using (var reader = new EndianReader(resourceStream))
                {
                    foreach (var cbsp in resourceDefinition.CollisionBsps)
                    {
                        reader.BaseStream.Position = cbsp.Bsp3dNodes.Address.Offset;
                        for (var i = 0; i < cbsp.Bsp3dNodes.Count; i++)
                        {
                            var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Bsp3dNode));
                            cbsp.Bsp3dNodes.Add((CollisionGeometry.Bsp3dNode)element);
                        }

                        reader.BaseStream.Position = cbsp.Planes.Address.Offset;
                        for (var i = 0; i < cbsp.Planes.Count; i++)
                        {
                            var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Plane));
                            cbsp.Planes.Add((CollisionGeometry.Plane)element);
                        }

                        reader.BaseStream.Position = cbsp.Leaves.Address.Offset;
                        for (var i = 0; i < cbsp.Leaves.Count; i++)
                        {
                            var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Leaf));
                            cbsp.Leaves.Add((CollisionGeometry.Leaf)element);
                        }

                        reader.BaseStream.Position = cbsp.Bsp2dReferences.Address.Offset;
                        for (var i = 0; i < cbsp.Bsp2dReferences.Count; i++)
                        {
                            var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Bsp2dReference));
                            cbsp.Bsp2dReferences.Add((CollisionGeometry.Bsp2dReference)element);
                        }

                        reader.BaseStream.Position = cbsp.Bsp2dNodes.Address.Offset;
                        for (var i = 0; i < cbsp.Bsp2dNodes.Count; i++)
                        {
                            var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Bsp2dNode));
                            cbsp.Bsp2dNodes.Add((CollisionGeometry.Bsp2dNode)element);
                        }

                        reader.BaseStream.Position = cbsp.Surfaces.Address.Offset;
                        for (var i = 0; i < cbsp.Surfaces.Count; i++)
                        {
                            var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Surface));
                            cbsp.Surfaces.Add((CollisionGeometry.Surface)element);
                        }

                        reader.BaseStream.Position = cbsp.Edges.Address.Offset;
                        for (var i = 0; i < cbsp.Edges.Count; i++)
                        {
                            var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Edge));
                            cbsp.Edges.Add((CollisionGeometry.Edge)element);
                        }

                        reader.BaseStream.Position = cbsp.Vertices.Address.Offset;
                        for (var i = 0; i < cbsp.Vertices.Count; i++)
                        {
                            var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Vertex));
                            cbsp.Vertices.Add((CollisionGeometry.Vertex)element);
                        }
                    }

                    foreach (var cbsp in resourceDefinition.LargeCollisionBsps)
                    {
                        reader.BaseStream.Position = cbsp.Bsp3dNodes.Address.Offset;
                        for (var i = 0; i < cbsp.Bsp3dNodes.Count; i++)
                        {
                            var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(StructureBspTagResources.LargeCollisionBspBlock.Bsp3dNode));
                            cbsp.Bsp3dNodes.Add((StructureBspTagResources.LargeCollisionBspBlock.Bsp3dNode)element);
                        }

                        reader.BaseStream.Position = cbsp.Planes.Address.Offset;
                        for (var i = 0; i < cbsp.Planes.Count; i++)
                        {
                            var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Plane));
                            cbsp.Planes.Add((CollisionGeometry.Plane)element);
                        }

                        reader.BaseStream.Position = cbsp.Leaves.Address.Offset;
                        for (var i = 0; i < cbsp.Leaves.Count; i++)
                        {
                            var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Leaf));
                            cbsp.Leaves.Add((CollisionGeometry.Leaf)element);
                        }

                        reader.BaseStream.Position = cbsp.Bsp2dReferences.Address.Offset;
                        for (var i = 0; i < cbsp.Bsp2dReferences.Count; i++)
                        {
                            var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(StructureBspTagResources.LargeCollisionBspBlock.Bsp2dReference));
                            cbsp.Bsp2dReferences.Add((StructureBspTagResources.LargeCollisionBspBlock.Bsp2dReference)element);
                        }

                        reader.BaseStream.Position = cbsp.Bsp2dNodes.Address.Offset;
                        for (var i = 0; i < cbsp.Bsp2dNodes.Count; i++)
                        {
                            var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(StructureBspTagResources.LargeCollisionBspBlock.Bsp2dNode));
                            cbsp.Bsp2dNodes.Add((StructureBspTagResources.LargeCollisionBspBlock.Bsp2dNode)element);
                        }

                        reader.BaseStream.Position = cbsp.Surfaces.Address.Offset;
                        for (var i = 0; i < cbsp.Surfaces.Count; i++)
                        {
                            var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(StructureBspTagResources.LargeCollisionBspBlock.Surface));
                            cbsp.Surfaces.Add((StructureBspTagResources.LargeCollisionBspBlock.Surface)element);
                        }

                        reader.BaseStream.Position = cbsp.Edges.Address.Offset;
                        for (var i = 0; i < cbsp.Edges.Count; i++)
                        {
                            var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(StructureBspTagResources.LargeCollisionBspBlock.Edge));
                            cbsp.Edges.Add((StructureBspTagResources.LargeCollisionBspBlock.Edge)element);
                        }

                        reader.BaseStream.Position = cbsp.Vertices.Address.Offset;
                        for (var i = 0; i < cbsp.Vertices.Count; i++)
                        {
                            var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(StructureBspTagResources.LargeCollisionBspBlock.Vertex));
                            cbsp.Vertices.Add((StructureBspTagResources.LargeCollisionBspBlock.Vertex)element);
                        }
                    }

                    foreach (var instance in resourceDefinition.InstancedGeometry)
                    {
                        reader.BaseStream.Position = instance.CollisionInfo.Bsp3dNodes.Address.Offset;
                        for (var i = 0; i < instance.CollisionInfo.Bsp3dNodes.Count; i++)
                        {
                            var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Bsp3dNode));
                            instance.CollisionInfo.Bsp3dNodes.Add((CollisionGeometry.Bsp3dNode)element);
                        }

                        reader.BaseStream.Position = instance.CollisionInfo.Planes.Address.Offset;
                        for (var i = 0; i < instance.CollisionInfo.Planes.Count; i++)
                        {
                            var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Plane));
                            instance.CollisionInfo.Planes.Add((CollisionGeometry.Plane)element);
                        }

                        reader.BaseStream.Position = instance.CollisionInfo.Leaves.Address.Offset;
                        for (var i = 0; i < instance.CollisionInfo.Leaves.Count; i++)
                        {
                            var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Leaf));
                            instance.CollisionInfo.Leaves.Add((CollisionGeometry.Leaf)element);
                        }

                        reader.BaseStream.Position = instance.CollisionInfo.Bsp2dReferences.Address.Offset;
                        for (var i = 0; i < instance.CollisionInfo.Bsp2dReferences.Count; i++)
                        {
                            var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Bsp2dReference));
                            instance.CollisionInfo.Bsp2dReferences.Add((CollisionGeometry.Bsp2dReference)element);
                        }

                        reader.BaseStream.Position = instance.CollisionInfo.Bsp2dNodes.Address.Offset;
                        for (var i = 0; i < instance.CollisionInfo.Bsp2dNodes.Count; i++)
                        {
                            var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Bsp2dNode));
                            instance.CollisionInfo.Bsp2dNodes.Add((CollisionGeometry.Bsp2dNode)element);
                        }

                        reader.BaseStream.Position = instance.CollisionInfo.Surfaces.Address.Offset;
                        for (var i = 0; i < instance.CollisionInfo.Surfaces.Count; i++)
                        {
                            var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Surface));
                            instance.CollisionInfo.Surfaces.Add((CollisionGeometry.Surface)element);
                        }

                        reader.BaseStream.Position = instance.CollisionInfo.Edges.Address.Offset;
                        for (var i = 0; i < instance.CollisionInfo.Edges.Count; i++)
                        {
                            var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Edge));
                            instance.CollisionInfo.Edges.Add((CollisionGeometry.Edge)element);
                        }

                        reader.BaseStream.Position = instance.CollisionInfo.Vertices.Address.Offset;
                        for (var i = 0; i < instance.CollisionInfo.Vertices.Count; i++)
                        {
                            var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Vertex));
                            instance.CollisionInfo.Vertices.Add((CollisionGeometry.Vertex)element);
                        }

                        foreach (var cbsp in instance.CollisionGeometries)
                        {
                            reader.BaseStream.Position = cbsp.Bsp3dNodes.Address.Offset;
                            for (var i = 0; i < cbsp.Bsp3dNodes.Count; i++)
                            {
                                var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Bsp3dNode));
                                cbsp.Bsp3dNodes.Add((CollisionGeometry.Bsp3dNode)element);
                            }

                            reader.BaseStream.Position = cbsp.Planes.Address.Offset;
                            for (var i = 0; i < cbsp.Planes.Count; i++)
                            {
                                var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Plane));
                                cbsp.Planes.Add((CollisionGeometry.Plane)element);
                            }

                            reader.BaseStream.Position = cbsp.Leaves.Address.Offset;
                            for (var i = 0; i < cbsp.Leaves.Count; i++)
                            {
                                var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Leaf));
                                cbsp.Leaves.Add((CollisionGeometry.Leaf)element);
                            }

                            reader.BaseStream.Position = cbsp.Bsp2dReferences.Address.Offset;
                            for (var i = 0; i < cbsp.Bsp2dReferences.Count; i++)
                            {
                                var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Bsp2dReference));
                                cbsp.Bsp2dReferences.Add((CollisionGeometry.Bsp2dReference)element);
                            }

                            reader.BaseStream.Position = cbsp.Bsp2dNodes.Address.Offset;
                            for (var i = 0; i < cbsp.Bsp2dNodes.Count; i++)
                            {
                                var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Bsp2dNode));
                                cbsp.Bsp2dNodes.Add((CollisionGeometry.Bsp2dNode)element);
                            }

                            reader.BaseStream.Position = cbsp.Surfaces.Address.Offset;
                            for (var i = 0; i < cbsp.Surfaces.Count; i++)
                            {
                                var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Surface));
                                cbsp.Surfaces.Add((CollisionGeometry.Surface)element);
                            }

                            reader.BaseStream.Position = cbsp.Edges.Address.Offset;
                            for (var i = 0; i < cbsp.Edges.Count; i++)
                            {
                                var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Edge));
                                cbsp.Edges.Add((CollisionGeometry.Edge)element);
                            }

                            reader.BaseStream.Position = cbsp.Vertices.Address.Offset;
                            for (var i = 0; i < cbsp.Vertices.Count; i++)
                            {
                                var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Vertex));
                                cbsp.Vertices.Add((CollisionGeometry.Vertex)element);
                            }
                        }

                        for (var i = 0; i < instance.Unknown1.Count; i++)
                        {
                            var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(StructureBspTagResources.InstancedGeometryBlock.Unknown1Block));
                            instance.Unknown1.Add((StructureBspTagResources.InstancedGeometryBlock.Unknown1Block)element);
                        }

                        for (var i = 0; i < instance.Unknown2.Count; i++)
                        {
                            var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(StructureBspTagResources.InstancedGeometryBlock.Unknown2Block));
                            instance.Unknown2.Add((StructureBspTagResources.InstancedGeometryBlock.Unknown2Block)element);
                        }

                        for (var i = 0; i < instance.Unknown3.Count; i++)
                        {
                            var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(StructureBspTagResources.InstancedGeometryBlock.Unknown3Block));
                            instance.Unknown3.Add((StructureBspTagResources.InstancedGeometryBlock.Unknown3Block)element);
                        }

                        foreach (var collision in instance.BspPhysics)
                        {
                            for (var i = 0; i < collision.Data.Count; i++)
                            {
                                var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(byte));
                                collision.Data.Add(new StructureBspTagResources.CollisionBspPhysicsBlock.Datum {
                                    Value = (byte)element
                                });
                            }
                        }
                    }
                }

                var file = new FileInfo(args[0]);

                if (!file.Directory.Exists)
                {
                    file.Directory.Create();
                }

                using (var writer = new StreamWriter(file.Create()))
                {
                    var baseVertex = 0;

                    foreach (var bsp in resourceDefinition.CollisionBsps)
                    {
                        for (var i = 0; i < bsp.Vertices.Count; i++)
                        {
                            var vertex = bsp.Vertices[i];
                            writer.WriteLine($"v {vertex.Point.X} {vertex.Point.Z} {vertex.Point.Y}");
                        }

                        writer.WriteLine($"g bsp_surfaces_{resourceDefinition.CollisionBsps.IndexOf(bsp)}");

                        for (var i = 0; i < bsp.Surfaces.Count; i++)
                        {
                            var surface  = bsp.Surfaces[i];
                            var vertices = new HashSet <short>();
                            var edge     = bsp.Edges[surface.FirstEdge];

                            writer.Write("f");

                            while (true)
                            {
                                if (edge.LeftSurface == i)
                                {
                                    writer.Write($" {baseVertex + edge.StartVertex + 1}");

                                    if (edge.ForwardEdge == surface.FirstEdge)
                                    {
                                        break;
                                    }
                                    else
                                    {
                                        edge = bsp.Edges[edge.ForwardEdge];
                                    }
                                }
                                else if (edge.RightSurface == i)
                                {
                                    writer.Write($" {baseVertex + edge.EndVertex + 1}");

                                    if (edge.ReverseEdge == surface.FirstEdge)
                                    {
                                        break;
                                    }
                                    else
                                    {
                                        edge = bsp.Edges[edge.ReverseEdge];
                                    }
                                }
                            }

                            writer.WriteLine();
                        }

                        baseVertex += bsp.Vertices.Count;
                    }

                    foreach (var largeBsp in resourceDefinition.LargeCollisionBsps)
                    {
                        for (var i = 0; i < largeBsp.Vertices.Count; i++)
                        {
                            var vertex = largeBsp.Vertices[i];
                            writer.WriteLine($"v {vertex.Point.X} {vertex.Point.Z} {vertex.Point.Y}");
                        }

                        writer.WriteLine($"g large_bsp_surfaces_{resourceDefinition.LargeCollisionBsps.IndexOf(largeBsp)}");

                        for (var i = 0; i < largeBsp.Surfaces.Count; i++)
                        {
                            var surface  = largeBsp.Surfaces[i];
                            var vertices = new HashSet <short>();
                            var edge     = largeBsp.Edges[surface.FirstEdge];

                            writer.Write("f");

                            while (true)
                            {
                                if (edge.LeftSurface == i)
                                {
                                    writer.Write($" {baseVertex + edge.StartVertex + 1}");

                                    if (edge.ForwardEdge == surface.FirstEdge)
                                    {
                                        break;
                                    }
                                    else
                                    {
                                        edge = largeBsp.Edges[edge.ForwardEdge];
                                    }
                                }
                                else if (edge.RightSurface == i)
                                {
                                    writer.Write($" {baseVertex + edge.EndVertex + 1}");

                                    if (edge.ReverseEdge == surface.FirstEdge)
                                    {
                                        break;
                                    }
                                    else
                                    {
                                        edge = largeBsp.Edges[edge.ReverseEdge];
                                    }
                                }
                            }

                            writer.WriteLine();
                        }

                        baseVertex += largeBsp.Vertices.Count;
                    }

                    foreach (var instanceDef in Definition.InstancedGeometryInstances)
                    {
                        if (instanceDef.InstanceDefinition == -1)
                        {
                            continue;
                        }

                        var instance = resourceDefinition.InstancedGeometry[instanceDef.InstanceDefinition];

                        var instanceName = instanceDef.Name != StringId.Invalid ?
                                           CacheContext.GetString(instanceDef.Name) :
                                           $"instance_{instanceDef.InstanceDefinition}";

                        for (var i = 0; i < instance.CollisionInfo.Vertices.Count; i++)
                        {
                            var vertex = instance.CollisionInfo.Vertices[i];
                            var point  = Vector3.Transform(
                                new Vector3(vertex.Point.X, vertex.Point.Y, vertex.Point.Z),
                                new Matrix4x4(
                                    instanceDef.Matrix.m11, instanceDef.Matrix.m12, instanceDef.Matrix.m13, 0.0f,
                                    instanceDef.Matrix.m21, instanceDef.Matrix.m22, instanceDef.Matrix.m23, 0.0f,
                                    instanceDef.Matrix.m31, instanceDef.Matrix.m32, instanceDef.Matrix.m33, 0.0f,
                                    instanceDef.Matrix.m41, instanceDef.Matrix.m42, instanceDef.Matrix.m43, 0.0f));

                            writer.WriteLine($"v {point.X} {point.Z} {point.Y}");
                        }

                        writer.WriteLine($"g {instanceName}_main_surfaces");

                        for (var i = 0; i < instance.CollisionInfo.Surfaces.Count; i++)
                        {
                            var surface  = instance.CollisionInfo.Surfaces[i];
                            var vertices = new HashSet <short>();
                            var edge     = instance.CollisionInfo.Edges[surface.FirstEdge];

                            writer.Write("f");

                            while (true)
                            {
                                if (edge.LeftSurface == i)
                                {
                                    writer.Write($" {baseVertex + edge.StartVertex + 1}");

                                    if (edge.ForwardEdge == surface.FirstEdge)
                                    {
                                        break;
                                    }
                                    else
                                    {
                                        edge = instance.CollisionInfo.Edges[edge.ForwardEdge];
                                    }
                                }
                                else if (edge.RightSurface == i)
                                {
                                    writer.Write($" {baseVertex + edge.EndVertex + 1}");

                                    if (edge.ReverseEdge == surface.FirstEdge)
                                    {
                                        break;
                                    }
                                    else
                                    {
                                        edge = instance.CollisionInfo.Edges[edge.ReverseEdge];
                                    }
                                }
                            }

                            writer.WriteLine();
                        }

                        baseVertex += instance.CollisionInfo.Vertices.Count;

                        foreach (var bsp in instance.CollisionGeometries)
                        {
                            for (var i = 0; i < bsp.Vertices.Count; i++)
                            {
                                var vertex = bsp.Vertices[i];
                                writer.WriteLine($"v {vertex.Point.X} {vertex.Point.Z} {vertex.Point.Y}");
                            }

                            writer.WriteLine($"g {instanceName}_bsp_surfaces_{resourceDefinition.CollisionBsps.IndexOf(bsp)}");

                            for (var i = 0; i < bsp.Surfaces.Count; i++)
                            {
                                var surface  = bsp.Surfaces[i];
                                var vertices = new HashSet <short>();
                                var edge     = bsp.Edges[surface.FirstEdge];

                                writer.Write("f");

                                while (true)
                                {
                                    if (edge.LeftSurface == i)
                                    {
                                        writer.Write($" {baseVertex + edge.StartVertex + 1}");

                                        if (edge.ForwardEdge == surface.FirstEdge)
                                        {
                                            break;
                                        }
                                        else
                                        {
                                            edge = bsp.Edges[edge.ForwardEdge];
                                        }
                                    }
                                    else if (edge.RightSurface == i)
                                    {
                                        writer.Write($" {baseVertex + edge.EndVertex + 1}");

                                        if (edge.ReverseEdge == surface.FirstEdge)
                                        {
                                            break;
                                        }
                                        else
                                        {
                                            edge = bsp.Edges[edge.ReverseEdge];
                                        }
                                    }
                                }

                                writer.WriteLine();
                            }

                            baseVertex += bsp.Vertices.Count;
                        }
                    }
                }
            }

            return(true);
        }
        public override object Execute(List <string> args)
        {
            if (args.Count != 1)
            {
                return(false);
            }

            if (!CacheContext.TryGetTag <Shader>(@"shaders\invalid", out var defaultShaderTag))
            {
                Console.WriteLine("WARNING: 'shaders\\invalid.shader' not found!");
                Console.WriteLine("You will have to assign material shaders manually.");
            }

            var stringIdCount = CacheContext.StringIdCache.Strings.Count;

            var sceneFile = new FileInfo(args[0]);

            if (!sceneFile.Exists)
            {
                throw new FileNotFoundException(sceneFile.FullName);
            }

            if (sceneFile.Extension.ToLower() != ".dae")
            {
                throw new FormatException($"Input file is not COLLADA format: {sceneFile.FullName}");
            }

            Scene scene;

            using (var importer = new AssimpContext())
            {
                scene = importer.ImportFile(sceneFile.FullName,
                                            PostProcessSteps.CalculateTangentSpace |
                                            PostProcessSteps.GenerateNormals |
                                            PostProcessSteps.SortByPrimitiveType |
                                            PostProcessSteps.Triangulate);
            }

            var builder         = new RenderModelBuilder(CacheContext);
            var nodes           = new Dictionary <string, sbyte>();
            var materialIndices = new Dictionary <string, short>();

            foreach (var oldNode in Definition.Nodes)
            {
                var name = CacheContext.GetString(oldNode.Name);

                nodes[name] = builder.AddNode(oldNode);
            }

            foreach (var region in Definition.Regions)
            {
                builder.BeginRegion(region.Name);

                var regionName = CacheContext.GetString(region.Name);

                foreach (var permutation in region.Permutations)
                {
                    if (permutation.MeshCount > 1)
                    {
                        throw new NotSupportedException("multiple permutation meshes");
                    }

                    if (permutation.MeshIndex == -1)
                    {
                        continue;
                    }

                    var permName = CacheContext.GetString(permutation.Name);
                    var meshName = $"{regionName}FBXASC058{permName}Mesh";

                    var permMeshes = scene.Meshes.Where(i => i.Name == meshName).ToList();

                    if (permMeshes.Count == 0)
                    {
                        throw new Exception($"No mesh(es) found for region '{regionName}' permutation '{permName}'!");
                    }

                    permMeshes.Sort((a, b) => a.MaterialIndex.CompareTo(b.MaterialIndex));

                    // Build a multipart mesh from the model data,
                    // with each model mesh mapping to a part of one large mesh and having its own material
                    ushort partStartVertex = 0;
                    ushort partStartIndex  = 0;

                    var rigidVertices   = new List <RigidVertex>();
                    var skinnedVertices = new List <SkinnedVertex>();

                    var indices = new List <ushort>();

                    var vertexType = Definition.Geometry.Meshes[permutation.MeshIndex].Type;
                    var rigidNode  = Definition.Geometry.Meshes[permutation.MeshIndex].RigidNodeIndex;

                    builder.BeginPermutation(permutation.Name);
                    builder.BeginMesh();

                    foreach (var mesh in permMeshes)
                    {
                        for (var i = 0; i < mesh.VertexCount; i++)
                        {
                            var position = mesh.Vertices[i];
                            var normal   = mesh.Normals[i];

                            Vector3D uv;

                            try
                            {
                                uv = mesh.TextureCoordinateChannels[0][i];
                            }
                            catch
                            {
                                Console.WriteLine($"WARNING: Missing texture coordinate for vertex {i} in '{regionName}:{permName}'");
                                uv = new Vector3D();
                            }

                            var tangent   = mesh.Tangents.Count != 0 ? mesh.Tangents[i] : new Vector3D();
                            var bitangent = mesh.BiTangents.Count != 0 ? mesh.BiTangents[i] : new Vector3D();

                            if (vertexType == VertexType.Skinned)
                            {
                                var blendIndicesList = new List <byte>();
                                var blendWeightsList = new List <float>();

                                foreach (var bone in mesh.Bones)
                                {
                                    foreach (var vertexInfo in bone.VertexWeights)
                                    {
                                        if (vertexInfo.VertexID == i)
                                        {
                                            // HAX BELOW
                                            //if (bone.Name.StartsWith("_"))
                                            //bone.Name = bone.Name.Substring(4);
                                            //if (bone.Name.EndsWith("2"))
                                            //bone.Name = bone.Name.Replace("2", "_tip");
                                            //else if (bone.Name != "spine1" && bone.Name.EndsWith("1"))
                                            //bone.Name = bone.Name.Replace("1", "_low");
                                            blendIndicesList.Add((byte)nodes[bone.Name]);
                                            blendWeightsList.Add(vertexInfo.Weight);
                                        }
                                    }
                                }

                                var blendIndices = new byte[4];
                                var blendWeights = new float[4];

                                for (int j = 0; j < blendIndicesList.Count; j++)
                                {
                                    if (j < 4)
                                    {
                                        blendIndices[j] = blendIndicesList[j];
                                    }
                                }

                                for (int j = 0; j < blendWeightsList.Count; j++)
                                {
                                    if (j < 4)
                                    {
                                        blendWeights[j] = blendWeightsList[j];
                                    }
                                }

                                skinnedVertices.Add(new SkinnedVertex
                                {
                                    Position     = new RealQuaternion(position.X * 0.01f, position.Y * 0.01f, position.Z * 0.01f, 1),
                                    Texcoord     = new RealVector2d(uv.X, -uv.Y),
                                    Normal       = new RealVector3d(normal.X, normal.Y, normal.Z),
                                    Tangent      = new RealQuaternion(tangent.X, tangent.Y, tangent.Z, 1),
                                    Binormal     = new RealVector3d(bitangent.X, bitangent.Y, bitangent.Z),
                                    BlendIndices = blendIndices,
                                    BlendWeights = blendWeights
                                });
                            }
                            else
                            {
                                rigidVertices.Add(new RigidVertex
                                {
                                    Position = new RealQuaternion(position.X * 0.01f, position.Y * 0.01f, position.Z * 0.01f, 1),
                                    Texcoord = new RealVector2d(uv.X, -uv.Y),
                                    Normal   = new RealVector3d(normal.X, normal.Y, normal.Z),
                                    Tangent  = new RealQuaternion(tangent.X, tangent.Y, tangent.Z, 1),
                                    Binormal = new RealVector3d(bitangent.X, bitangent.Y, bitangent.Z),
                                });
                            }
                        }

                        // Build the index buffer
                        var meshIndices = mesh.GetIndices();
                        indices.AddRange(meshIndices.Select(i => (ushort)(i + partStartVertex)));

                        // Define a material and part for this mesh
                        var meshMaterial = scene.Materials[mesh.MaterialIndex];

                        short materialIndex = 0;

                        if (materialIndices.ContainsKey(meshMaterial.Name))
                        {
                            materialIndex = materialIndices[meshMaterial.Name];
                        }
                        else
                        {
                            materialIndex = materialIndices[meshMaterial.Name] = builder.AddMaterial(new RenderMaterial
                            {
                                RenderMethod = defaultShaderTag,
                            });
                        }

                        builder.BeginPart(materialIndex, partStartIndex, (ushort)meshIndices.Length, (ushort)mesh.VertexCount);
                        builder.DefineSubPart(partStartIndex, (ushort)meshIndices.Length, (ushort)mesh.VertexCount);
                        builder.EndPart();

                        // Move to the next part
                        partStartVertex += (ushort)mesh.VertexCount;
                        partStartIndex  += (ushort)meshIndices.Length;
                    }

                    // Bind the vertex and index buffers
                    if (vertexType == VertexType.Skinned)
                    {
                        builder.BindSkinnedVertexBuffer(skinnedVertices);
                    }
                    else
                    {
                        builder.BindRigidVertexBuffer(rigidVertices, rigidNode);
                    }

                    builder.BindIndexBuffer(indices, IndexBufferFormat.TriangleList);

                    builder.EndMesh();
                    builder.EndPermutation();
                }

                builder.EndRegion();
            }

            using (var resourceStream = new MemoryStream())
            {
                Console.Write("Building render_geometry...");

                var newDefinition = builder.Build(CacheContext.Serializer, resourceStream);
                Definition.Regions   = newDefinition.Regions;
                Definition.Geometry  = newDefinition.Geometry;
                Definition.Nodes     = newDefinition.Nodes;
                Definition.Materials = newDefinition.Materials;

                resourceStream.Position = 0;

                Definition.Geometry.Resource.ChangeLocation(ResourceLocation.ResourcesB);
                CacheContext.AddResource(Definition.Geometry.Resource, resourceStream);

                Console.WriteLine("done.");
            }

            //
            // TODO: Build the new render_model and update the original render_model here...
            //

            Console.Write("Writing render_model tag data...");

            using (var cacheStream = CacheContext.OpenTagCacheReadWrite())
                CacheContext.Serialize(cacheStream, Tag, Definition);

            Console.WriteLine("done.");

            if (stringIdCount != CacheContext.StringIdCache.Strings.Count)
            {
                Console.Write("Saving string ids...");

                using (var stream = CacheContext.OpenStringIdCacheReadWrite())
                    CacheContext.StringIdCache.Save(stream);

                Console.WriteLine("done");
            }

            Console.WriteLine("Replaced render_geometry successfully.");

            return(true);
        }
예제 #30
0
        public override object Execute(List<string> args)
        {
            if (args.Count > 1)
                return false;

            var match = (args.Count == 1);
            var token = match ? args[0].ToLower() : "";

			foreach (var tagFieldInfo in TagStructure.GetTagFieldEnumerable(Structure))
			{
				if (tagFieldInfo.Attribute != null && tagFieldInfo.Attribute.Flags.HasFlag(Padding))
					continue;

				var nameString = tagFieldInfo.Name;

				if (match && !nameString.ToLower().Contains(token))
					continue;

				var fieldType = tagFieldInfo.FieldType;
				var fieldValue = tagFieldInfo.GetValue(Value);

				var typeString =
					fieldType.IsGenericType ?
						$"{fieldType.Name}<{fieldType.GenericTypeArguments[0].Name}>" :
					fieldType.Name;

				string valueString;

#if !DEBUG
                try
                {
#endif
				if (fieldValue == null)
					valueString = "null";
				else if (fieldType == typeof(StringId))
					valueString = CacheContext.GetString((StringId)fieldValue);
				else if (fieldType == typeof(CachedTagInstance))
				{
					var instance = (CachedTagInstance)fieldValue;

					var tagName = instance?.Name ?? $"0x{instance.Index:X4}";

					valueString = $"[0x{instance.Index:X4}] {tagName}.{CacheContext.GetString(instance.Group.Name)}";
				}
				else if (fieldType == typeof(TagFunction))
				{
					var function = (TagFunction)fieldValue;
					valueString = "";
					foreach (var datum in function.Data)
						valueString += datum.ToString("X2");
				}
				else if (fieldType == typeof(PageableResource))
				{
					var pageable = (PageableResource)fieldValue;
					pageable.GetLocation(out var location);
					valueString = pageable == null ? "null" : $"{{ Location: {location}, Index: 0x{pageable.Page.Index:X4}, CompressedSize: 0x{pageable.Page.CompressedBlockSize:X8} }}";
				}
                else if (tagFieldInfo.FieldType.IsArray && tagFieldInfo.Attribute.Length != 0)
                {
                    valueString = fieldValue == null ? "null" : $"[{tagFieldInfo.Attribute.Length}] {{ ";
                    var valueArray = (Array)fieldValue;

                    if (fieldValue != null)
                    {
                        for (var i = 0; i < tagFieldInfo.Attribute.Length; i++)
                            valueString += $"{valueArray.GetValue(i)}{((i + 1) < tagFieldInfo.Attribute.Length ? "," : "")} ";

                        valueString += "}";
                    }
                }
                else if (fieldType.GetInterface(typeof(IList).Name) != null)
                    valueString =
                        ((IList)fieldValue).Count != 0 ?
                            $"{{...}}[{((IList)fieldValue).Count}]" :
                        "null";
                else
					valueString = fieldValue.ToString();
#if !DEBUG
                }
                catch (Exception e)
                {
                    valueString = $"<ERROR MESSAGE=\"{e.Message}\" />";
                }
#endif

				var fieldName = $"{tagFieldInfo.DeclaringType.FullName}.{tagFieldInfo.Name}".Replace("+", ".");
				var documentationNode = EditTagContextFactory.Documentation.SelectSingleNode($"//member[starts-with(@name, 'F:{fieldName}')]");

                Console.WriteLine("{0}: {1} = {2} {3}", nameString, typeString, valueString,
					documentationNode != null ?
						$":: {documentationNode.FirstChild.InnerText.Replace("\r\n", "").TrimStart().TrimEnd()}" :
						"");
			}

			return true;
        }