public GfxManager(Control tabControl, WatchVariableFlowLayoutPanel watchVariablePanel) : base(null, watchVariablePanel) { SplitContainer left = tabControl.Controls["splitContainerGfxLeft"] as SplitContainer; SplitContainer right = left.Panel2.Controls["splitContainerGfxright"] as SplitContainer; SplitContainer middle = right.Panel1.Controls["splitContainerGfxmiddle"] as SplitContainer; Button refreshButtonRoot = middle.Panel1.Controls["buttonGfxRefresh"] as Button; Button refreshButtonObject = middle.Panel1.Controls["buttonGfxRefreshObject"] as Button; Button dumpButton = middle.Panel1.Controls["buttonGfxDumpDisplayList"] as Button; Button hitboxViewButton = middle.Panel1.Controls["buttonGfxHitboxHack"] as Button; _outputTextBox = right.Panel2.Controls["richTextBoxGfx"] as RichTextBox; _outputTextBox.Font = new System.Drawing.Font("Courier New", 8); _outputTextBox.ForeColor = System.Drawing.Color.Black; _watchVariablePanel = watchVariablePanel; _treeView = left.Panel1.Controls["treeViewGfx"] as TreeView; _treeView.AfterSelect += _treeView_AfterSelect; refreshButtonRoot.Click += RefreshButton_Click; refreshButtonObject.Click += RefreshButtonObject_Click; dumpButton.Click += DumpButton_Click; hitboxViewButton.Click += (sender, e) => InjectHitboxViewCode(); _tabControl = tabControl; foreach (WatchVariableControlPrecursor precursor in GfxNode.GetCommonVariables()) { watchVariablePanel.AddVariable(precursor.CreateWatchVariableControl()); } SpecificVariables = new List <WatchVariableControl>(); }
/** * 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); }
/* * 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); }
// 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) { _watchVariablePanel.RemoveVariables(SpecificVariables); SpecificVariables.Clear(); if (node != null) { foreach (WatchVariableControlPrecursor precursor in node.GetTypeSpecificVariables()) { SpecificVariables.Add(precursor.CreateWatchVariableControl()); } } _watchVariablePanel.AddVariables(SpecificVariables); }
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); }
public void AddToTreeView(uint rootAddress) { GfxNode root = GfxNode.ReadGfxNode(rootAddress); _treeView.Nodes.Add(GfxToTreeNode(root)); }