/** * When selecting a node, ensure the variable containers are related to that node */ private void _treeView_AfterSelect(object sender, TreeViewEventArgs e) { GfxNode node = (GfxNode)e.Node.Tag; SelectedNode = node; UpdateSpecificVariables(SelectedNode); }
// The variables in the first 0x14 bytes in a GFX node are common, but after that there are type-specific variables void UpdateSpecificVariables(GfxNode node) { watchVariablePanelGfx.RemoveVariables(SpecificVariables); SpecificVariables.Clear(); if (node != null) { foreach (WatchVariableControlPrecursor precursor in node.GetTypeSpecificVariables()) { SpecificVariables.Add(precursor.CreateWatchVariableControl()); } } watchVariablePanelGfx.AddVariables(SpecificVariables); }
/* * Recursively converts a tree of GfxNodes to a tree of TreeNodes so that they can be displayed in the tree viewer */ public TreeNode GfxToTreeNode(GfxNode node) { // Should only happen when memory is invalid (for example when the US setting is used on a JP ROM) if (node == null) { return(new TreeNode("Invalid Gfx Node")); } TreeNode res = new TreeNode(node.Name, node.Children.Select(x => GfxToTreeNode(x)).ToArray()); res.Tag = node; return(res); }
public GfxTab() { InitializeComponent(); richTextBoxGfx.Font = new Font("Courier New", 8); richTextBoxGfx.ForeColor = Color.Black; treeViewGfx.AfterSelect += _treeView_AfterSelect; buttonGfxRefresh.Click += RefreshButton_Click; buttonGfxRefreshObject.Click += RefreshButtonObject_Click; buttonGfxDumpDisplayList.Click += DumpButton_Click; buttonGfxHitboxHack.Click += (sender, e) => InjectHitboxViewCode(); SuspendLayout(); foreach (WatchVariableControlPrecursor precursor in GfxNode.GetCommonVariables()) { watchVariablePanelGfx.AddVariable(precursor.CreateWatchVariableControl()); } ResumeLayout(); SpecificVariables = new List <WatchVariableControl>(); }
public void AddToTreeView(uint rootAddress) { GfxNode root = GfxNode.ReadGfxNode(rootAddress); treeViewGfx.Nodes.Add(GfxToTreeNode(root)); }
public static GfxNode ReadGfxNode(uint address) { if (address < 0x80000000u || address > 0x80800000u) { return(null); } ushort type = Config.Stream.GetUInt16(address + 0x00); GfxNode res; switch (type) { case 0x001: res = new GfxRootnode(); break; case 0x002: res = new GfxScreenSpace(); break; case 0x004: res = new GfxMasterList(); break; case 0x00A: res = new GfxGroupParent(); break; case 0x00B: res = new GfxLevelOfDetail(); break; case 0x015: res = new GfxDebugTransformation(); break; case 0x016: res = new GfxTranslatedModel(); break; case 0x017: res = new GfxRotationNode(); break; case 0x018: res = new GfxGameObject(); break; case 0x019: res = new GfxAnimationNode(); break; case 0x01A: res = new GfxBillboard(); break; case 0x01B: res = new GfxDisplayList(); break; case 0x01C: res = new GfxScalingNode(); break; case 0x028: res = new GfxShadowNode(); break; case 0x029: res = new GfxObjectParent(); break; //Todo: add 0x2F case 0x103: res = new GfxProjection3D(); break; case 0x10C: res = new GfxChildSelector(); break; case 0x114: res = new GfxCamera(); break; case 0x12A: res = new GfxGeoLayoutScript(); break; case 0x12C: res = new GfxBackgroundImage(); break; case 0x12E: res = new GfxHeldObject(); break; default: res = new GfxNode(); break; } res.Address = address; res.Children = new List <GfxNode>(); uint childAddress; if (type == 0x018 || type == 0x029) { // For some reason, the object parent has a null pointer as a child inbetween frames, // but during updatng it temporarily sets it to the pointer at offset 0x14 // Object nodes also do something like that childAddress = Config.Stream.GetUInt32(address + 0x14); } else { childAddress = Config.Stream.GetUInt32(address + 0x10); //offset 0x10 = child pointer } if (childAddress != 0) { //Traverse the circularly linked list of siblings until the first child is seen again uint currentAddress = childAddress; for (int i = 0; i < _maxSiblings; i++) { res.Children.Add(ReadGfxNode(currentAddress)); currentAddress = Config.Stream.GetUInt32(currentAddress + 0x08); //offset 0x08 = next pointer if (currentAddress == childAddress) { break; } } } return(res); }