/// <summary> /// Serializes a tag reference. /// </summary> /// <param name="context">The serialization context to use.</param> /// <param name="writer">The writer to write to.</param> /// <param name="referencedTag">The referenced tag.</param> /// <param name="valueInfo">Information about the value. Can be <c>null</c>.</param> private void SerializeTagReference(ISerializationContext context, BinaryWriter writer, CachedTagInstance referencedTag, TagFieldAttribute valueInfo) { if ((referencedTag?.Index ?? 0) == -1) { referencedTag = context.GetTagByName(referencedTag.Group, referencedTag.Name); } if (referencedTag != null && valueInfo != null && valueInfo.ValidTags != null) { foreach (string tag in valueInfo.ValidTags) { if (!referencedTag.IsInGroup(tag)) { throw new Exception($"Invalid group for tag reference: {referencedTag.Group.Tag}"); } } } if (valueInfo == null || !valueInfo.Flags.HasFlag(TagFieldFlags.Short)) { writer.Write((referencedTag != null) ? referencedTag.Group.Tag.Value : -1); writer.Write(0); writer.Write(0); } writer.Write((referencedTag != null) ? referencedTag.Index : -1); }
public override object Execute(List <string> args) { //Arguments needed: filepath, <new>|<tagIndex> if (args.Count < 2) { return(false); } CachedTagInstance tag = null; bool b_duplicate; // optional argument: forces overwriting of tags that are not type: coll var b_force = (args.Count >= 3 && args[2].ToLower().Equals("force")); if (args[1].ToLower().Equals("new")) { b_duplicate = true; } else { if (!CacheContext.TryGetTag(args[1], out tag)) { return(false); } b_duplicate = false; } if (!b_force && !b_duplicate && !tag.IsInGroup("coll")) { Console.WriteLine("Tag to override was not of class- 'coll'. Use third argument- 'force' to inject into this tag."); return(false); } string filepath = args[0]; string[] fpaths = null; CollisionModel coll = null; bool b_singleFile = Path.GetExtension(filepath).Equals(".model_collision_geometry") && !Directory.Exists(filepath); var modelbuilder = new CollisionGeometryBuilder(); int n_objects = 1; if (!b_singleFile) { fpaths = Directory.GetFiles(filepath, "*.model_collision_geometry"); if (fpaths.Length == 0) { Console.WriteLine("No Halo 1 coll tags in directory: \"{0}\"", filepath); return(false); } filepath = fpaths[0]; n_objects = fpaths.Length; } Console.WriteLine( (n_objects == 1 ? "Loading coll tag..." : "Loading coll tags..."), n_objects); if (!modelbuilder.ParseFromFile(filepath)) { return(false); } coll = modelbuilder.Build(); if (coll == null) { Console.WriteLine("Builder produced null result."); return(false); } if (!b_singleFile) { for (int i = 1; i < fpaths.Length; ++i) { if (!modelbuilder.ParseFromFile(fpaths[i])) { return(false); } var coll2 = modelbuilder.Build(); if (coll2 == null) { Console.WriteLine("Builder produced null result."); return(false); } coll.Regions.Add(coll2.Regions[0]); } } using (var stream = CacheContext.OpenTagCacheReadWrite()) { if (b_duplicate) { //duplicate an existing tag, trashcan phmo tag = CacheContext.TagCache.DuplicateTag(stream, CacheContext.TagCache.Index[0x4436]); if (tag == null) { Console.WriteLine("Failed tag duplication."); return(false); } } CacheContext.Serialize(stream, tag, coll); } Console.WriteLine(n_objects == 1 ? "Added 1 collision." : "Added {0} collisions in one tag.", n_objects); Console.Write("Successfully imported coll to: "); TagPrinter.PrintTagShort(tag); return(true); }
public override object Execute(List <string> args) { //Arguments needed: filepath, <new>|<tagIndex> if (args.Count < 2) { return(false); } CachedTagInstance tag = null; bool b_duplicate; // optional argument: forces overwriting of tags that are not type: phmo bool b_force = (args.Count >= 3 && args[2].ToLower().Equals("force")); if (args[1].ToLower().Equals("new")) { b_duplicate = true; } else { if (!CacheContext.TryGetTag(args[1], out tag)) { return(false); } b_duplicate = false; } if (!b_force && !b_duplicate && !tag.IsInGroup("phmo")) { Console.WriteLine("Tag to override was not of class- 'phmo'. Use third argument- 'force' to inject."); return(false); } var filename = args[0]; var modelbuilder = new PhysicsModelBuilder(); if (!modelbuilder.ParseFromFile(filename)) { return(false); } //modelbuilder must also make a node for the physics model var phmo = modelbuilder.Build(); if (phmo == null) { return(false); } using (var stream = CacheContext.OpenTagCacheReadWrite()) { if (b_duplicate) { //duplicate an existing tag, trashcan phmo tag = CacheContext.TagCache.DuplicateTag(stream, CacheContext.TagCache.Index[0x4436]); if (tag == null) { Console.WriteLine("Failed tag duplication."); return(false); } } CacheContext.Serialize(stream, tag, phmo); } Console.Write("Successfully imported phmo to: "); TagPrinter.PrintTagShort(tag); return(true); }
public void LoadTagEditor(CachedTagInstance tag) { if (tag == null || (CurrentTag != null && CurrentTag.Index == tag.Index)) { return; } LoadingTag = true; object definition = null; if (CurrentTags.ContainsKey(tag.Index)) { definition = CurrentTags[tag.Index]; } tagTreeView.Enabled = false; tagEditorPanel.Controls.Clear(); var tagName = tag.Name ?? $"0x{tag.Index:X4}"; var groupName = CacheContext.GetString(tag.Group.Name); statusLabel.Text = $"Loading {tagName}.{ groupName}..."; progressBar.Style = ProgressBarStyle.Marquee; progressBar.MarqueeAnimationSpeed = 30; if (definition == null) { using (var stream = CacheContext.OpenTagCacheRead()) definition = CacheContext.Deserializer.Deserialize( new TagSerializationContext(stream, CacheContext, tag), TagDefinition.Find(tag.Group.Tag)); } if (tagName.Contains("\\")) { var index = tagName.LastIndexOf('\\') + 1; tagName = tagName.Substring(index, tagName.Length - index); } statusLabel.Text = $"Generating {groupName} interface..."; Application.DoEvents(); var point = new Point(); if (tag.IsInGroup("matg") || tag.IsInGroup("mulg") || tag.IsInGroup("scnr") || tag.IsInGroup("sbsp")) { var control = new StructMultiControl(this, CacheContext, tag, definition) { Dock = DockStyle.Fill }; control.GetFieldValue(null, definition, definition); tagEditorPanel.Controls.Add(control); } else if (tag.IsInGroup("bitm") || tag.IsInGroup("obje")) { var splitContainer = new SplitContainer { Dock = DockStyle.Fill, Orientation = Orientation.Horizontal }; splitContainer.FixedPanel = FixedPanel.Panel1; tagEditorPanel.Controls.Add(splitContainer); splitContainer.BringToFront(); if (tag.IsInGroup("bitm")) { splitContainer.SplitterDistance = Math.Min((short)512, Math.Max((short)16, ((TagTool.Tags.Definitions.Bitmap)definition).Images[0].Height)); } else if (tag.IsInGroup("obje")) { splitContainer.SplitterDistance = 384; } if (tag.IsInGroup("bitm")) { var bitmDefinition = (TagTool.Tags.Definitions.Bitmap)definition; var bitmapControl = new BitmapControl(CacheContext, bitmDefinition) { Dock = DockStyle.Fill }; splitContainer.Panel1.Controls.Add(bitmapControl); bitmapControl.BringToFront(); } else if (tag.IsInGroup("obje")) { var modelControl = new ObjectControl(CacheContext, (GameObject)definition) { Dock = DockStyle.Fill }; splitContainer.Panel1.Controls.Add(modelControl); modelControl.BringToFront(); } var control = tag.IsInGroup("obje") ? (Control) new StructMultiControl(this, CacheContext, tag, definition) { Dock = DockStyle.Fill } : new StructControl(this, CacheContext, definition.GetType(), null); ((IFieldControl)control).GetFieldValue(null, definition, definition); control.Location = point; splitContainer.Panel2.Controls.Add(control); splitContainer.Panel2.AutoScroll = true; } else { if (tag.IsInGroup("snd!")) { var soundControl = new SoundControl(CacheContext, tag, (TagTool.Tags.Definitions.Sound)definition) { Dock = DockStyle.Top }; tagEditorPanel.Controls.Add(soundControl); soundControl.BringToFront(); point.Y = soundControl.Bottom; } var control = new StructControl(this, CacheContext, definition.GetType(), null); control.GetFieldValue(null, definition, definition); control.Location = point; tagEditorPanel.Controls.Add(control); } statusLabel.Text = ""; progressBar.Style = ProgressBarStyle.Continuous; progressBar.MarqueeAnimationSpeed = 0; tagTreeView.Enabled = true; CurrentTag = tag; if (!CurrentTags.ContainsKey(tag.Index)) { CurrentTags[tag.Index] = definition; var item = new TagInstanceItem { CacheContext = CacheContext, Tag = tag }; currentTagsComboBox.Items.Add(item); currentTagsComboBox.SelectedItem = item; } else { for (var i = 0; i < currentTagsComboBox.Items.Count; i++) { var item = (TagInstanceItem)currentTagsComboBox.Items[i]; if (item.Tag.Index == tag.Index) { currentTagsComboBox.SelectedIndex = i; break; } } } LoadingTag = false; }
private string GetTagTreeNodeImageKey(CachedTagInstance tag) { if (tag.IsInGroup("cfgt") || tag.IsInGroup("matg") || tag.IsInGroup("mulg") || tag.IsInGroup("aigl") || tag.IsInGroup("smdt") || tag.IsInGroup("inpg") || tag.IsInGroup("rasg") || tag.IsInGroup("wezr") || tag.IsInGroup("wgtz") || tag.IsInGroup("wigl")) { return("file_settings"); } if (tag.IsInGroup("jmad")) { return("file_animation"); } else if (tag.IsInGroup("bitm")) { return("file_bitmap"); } else if (tag.IsInGroup("snd!") || tag.IsInGroup("lsnd")) { return("file_sound"); } else { return("file"); } }
private CachedTagInstance ConvertTag(CachedTagInstance srcTag, HaloOnlineCacheContext srcCacheContext, Stream srcStream, HaloOnlineCacheContext destCacheContext, Stream destStream, TagVersionMap tagMap) { TagPrinter.PrintTagShort(srcTag); // Uncomment this to use 0x101F for all shaders /*if (srcTag.IsClass("rm ")) * return destCacheContext.Cache.Tags[0x101F];*/ // Check if the tag is in the map, and just return the translated tag if so var destIndex = tagMap.Translate(srcCacheContext.Version, srcTag.Index, destCacheContext.Version); if (destIndex >= 0) { Console.WriteLine("- Using already-known index {0:X4}", destIndex); return(destCacheContext.TagCache.Index[destIndex]); } // Deserialize the tag from the source cache var tagData = srcCacheContext.Deserialize(srcStream, srcTag); // Uncomment this to use 0x101F in place of shaders that need conversion /*if (tagData is RenderMethod) * { * var rm = (RenderMethod)tagData; * foreach (var prop in rm.ShaderProperties) * { * if (tagMap.Translate(srcCacheContext.Version, prop.Template.Index, destCacheContext.Version) < 0) * return destCacheContext.Cache.Tags[0x101F]; * } * }*/ // Allocate a new tag and create a mapping for it CachedTagInstance instance = null; if (srcCacheContext.Version != destCacheContext.Version) { for (var i = 0; i < destCacheContext.TagCache.Index.Count; i++) { if (destCacheContext.TagCache.Index[i] == null) { destCacheContext.TagCache.Index[i] = instance = new CachedTagInstance(i, TagGroup.Instances[srcTag.Group.Tag]); break; } } } else { if (destCacheContext.TagCache.Index[srcTag.Index] != null) { if (destCacheContext.TagCache.Index[srcTag.Index].IsInGroup(srcTag.Group)) { return(destCacheContext.TagCache.Index[srcTag.Index]); } } else { destCacheContext.TagCache.Index[srcTag.Index] = instance = new CachedTagInstance(srcTag.Index, TagGroup.Instances[srcTag.Group.Tag], srcTag.Name); } } if (instance == null) { instance = destCacheContext.TagCache.AllocateTag(srcTag.Group); } tagMap.Add(srcCacheContext.Version, srcTag.Index, destCacheContext.Version, instance.Index); if (srcTag.IsInGroup("decs") || srcTag.IsInGroup("rmd ")) { IsDecalShader = true; } // Convert it tagData = Convert(tagData, srcCacheContext, srcStream, destCacheContext, destStream, tagMap); if (srcTag.IsInGroup("decs") || srcTag.IsInGroup("rmd ")) { IsDecalShader = false; } // Re-serialize into the destination cache destCacheContext.Serialize(destStream, instance, tagData); return(instance); }