diff --git a/Quad64.csproj b/Quad64.csproj
index 1ecbc06..f38473a 100644
--- a/Quad64.csproj
+++ b/Quad64.csproj
@@ -41,7 +41,7 @@
true
- AnyCPU
+ x86
pdbonly
true
bin\Release\
@@ -81,6 +81,12 @@
+
+ Form
+
+
+ EditWarp.cs
+
Component
@@ -207,6 +213,9 @@
+
+ EditWarp.cs
+
MainForm.cs
diff --git a/src/Forms/EditWarp.Designer.cs b/src/Forms/EditWarp.Designer.cs
new file mode 100644
index 0000000..2ef8074
--- /dev/null
+++ b/src/Forms/EditWarp.Designer.cs
@@ -0,0 +1,395 @@
+namespace Quad64.src.Forms
+{
+ partial class EditWarp
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(EditWarp));
+ this.cancelButton = new System.Windows.Forms.Button();
+ this.selectButton = new System.Windows.Forms.Button();
+ this.panel_warp_controls = new System.Windows.Forms.Panel();
+ this.label7 = new System.Windows.Forms.Label();
+ this.w_warpToID = new System.Windows.Forms.NumericUpDown();
+ this.label6 = new System.Windows.Forms.Label();
+ this.w_selectLevel = new System.Windows.Forms.ComboBox();
+ this.label9 = new System.Windows.Forms.Label();
+ this.label10 = new System.Windows.Forms.Label();
+ this.w_areaID = new System.Windows.Forms.NumericUpDown();
+ this.w_warpFrom = new System.Windows.Forms.NumericUpDown();
+ this.panel_instWarp_controls = new System.Windows.Forms.Panel();
+ this.label5 = new System.Windows.Forms.Label();
+ this.label4 = new System.Windows.Forms.Label();
+ this.label3 = new System.Windows.Forms.Label();
+ this.label2 = new System.Windows.Forms.Label();
+ this.label1 = new System.Windows.Forms.Label();
+ this.iw_tz = new System.Windows.Forms.NumericUpDown();
+ this.iw_ty = new System.Windows.Forms.NumericUpDown();
+ this.iw_tx = new System.Windows.Forms.NumericUpDown();
+ this.iw_area = new System.Windows.Forms.NumericUpDown();
+ this.iw_trigger = new System.Windows.Forms.NumericUpDown();
+ this.panel_warp_controls.SuspendLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.w_warpToID)).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)(this.w_areaID)).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)(this.w_warpFrom)).BeginInit();
+ this.panel_instWarp_controls.SuspendLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.iw_tz)).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)(this.iw_ty)).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)(this.iw_tx)).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)(this.iw_area)).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)(this.iw_trigger)).BeginInit();
+ this.SuspendLayout();
+ //
+ // cancelButton
+ //
+ this.cancelButton.Font = new System.Drawing.Font("Courier New", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.cancelButton.Location = new System.Drawing.Point(225, 192);
+ this.cancelButton.Name = "cancelButton";
+ this.cancelButton.Size = new System.Drawing.Size(100, 27);
+ this.cancelButton.TabIndex = 4;
+ this.cancelButton.Text = "Cancel";
+ this.cancelButton.UseVisualStyleBackColor = true;
+ this.cancelButton.Click += new System.EventHandler(this.cancelButton_Click);
+ //
+ // selectButton
+ //
+ this.selectButton.Font = new System.Drawing.Font("Courier New", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.selectButton.Location = new System.Drawing.Point(82, 193);
+ this.selectButton.Name = "selectButton";
+ this.selectButton.Size = new System.Drawing.Size(100, 27);
+ this.selectButton.TabIndex = 3;
+ this.selectButton.Text = "Save";
+ this.selectButton.UseVisualStyleBackColor = true;
+ this.selectButton.Click += new System.EventHandler(this.selectButton_Click);
+ //
+ // panel_warp_controls
+ //
+ this.panel_warp_controls.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.panel_warp_controls.BackColor = System.Drawing.Color.DarkGray;
+ this.panel_warp_controls.Controls.Add(this.label7);
+ this.panel_warp_controls.Controls.Add(this.w_warpToID);
+ this.panel_warp_controls.Controls.Add(this.label6);
+ this.panel_warp_controls.Controls.Add(this.w_selectLevel);
+ this.panel_warp_controls.Controls.Add(this.label9);
+ this.panel_warp_controls.Controls.Add(this.label10);
+ this.panel_warp_controls.Controls.Add(this.w_areaID);
+ this.panel_warp_controls.Controls.Add(this.w_warpFrom);
+ this.panel_warp_controls.Location = new System.Drawing.Point(0, 0);
+ this.panel_warp_controls.Name = "panel_warp_controls";
+ this.panel_warp_controls.Size = new System.Drawing.Size(407, 183);
+ this.panel_warp_controls.TabIndex = 5;
+ this.panel_warp_controls.Visible = false;
+ //
+ // label7
+ //
+ this.label7.AutoSize = true;
+ this.label7.Font = new System.Drawing.Font("Consolas", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.label7.Location = new System.Drawing.Point(20, 118);
+ this.label7.Name = "label7";
+ this.label7.Size = new System.Drawing.Size(108, 19);
+ this.label7.TabIndex = 20;
+ this.label7.Text = "To Warp ID:";
+ //
+ // w_warpToID
+ //
+ this.w_warpToID.Location = new System.Drawing.Point(134, 117);
+ this.w_warpToID.Maximum = new decimal(new int[] {
+ 99999,
+ 0,
+ 0,
+ 0});
+ this.w_warpToID.Name = "w_warpToID";
+ this.w_warpToID.Size = new System.Drawing.Size(74, 20);
+ this.w_warpToID.TabIndex = 19;
+ //
+ // label6
+ //
+ this.label6.AutoSize = true;
+ this.label6.Font = new System.Drawing.Font("Consolas", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.label6.Location = new System.Drawing.Point(38, 64);
+ this.label6.Name = "label6";
+ this.label6.Size = new System.Drawing.Size(90, 19);
+ this.label6.TabIndex = 18;
+ this.label6.Text = "To Level:";
+ //
+ // w_selectLevel
+ //
+ this.w_selectLevel.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+ this.w_selectLevel.FormattingEnabled = true;
+ this.w_selectLevel.Location = new System.Drawing.Point(134, 63);
+ this.w_selectLevel.Name = "w_selectLevel";
+ this.w_selectLevel.Size = new System.Drawing.Size(261, 21);
+ this.w_selectLevel.TabIndex = 17;
+ //
+ // label9
+ //
+ this.label9.AutoSize = true;
+ this.label9.Font = new System.Drawing.Font("Consolas", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.label9.Location = new System.Drawing.Point(47, 91);
+ this.label9.Name = "label9";
+ this.label9.Size = new System.Drawing.Size(81, 19);
+ this.label9.TabIndex = 16;
+ this.label9.Text = "To Area:";
+ //
+ // label10
+ //
+ this.label10.AutoSize = true;
+ this.label10.Font = new System.Drawing.Font("Consolas", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.label10.Location = new System.Drawing.Point(103, 25);
+ this.label10.Name = "label10";
+ this.label10.Size = new System.Drawing.Size(90, 19);
+ this.label10.TabIndex = 15;
+ this.label10.Text = "Warp ID: ";
+ //
+ // w_areaID
+ //
+ this.w_areaID.Location = new System.Drawing.Point(134, 91);
+ this.w_areaID.Maximum = new decimal(new int[] {
+ 7,
+ 0,
+ 0,
+ 0});
+ this.w_areaID.Name = "w_areaID";
+ this.w_areaID.Size = new System.Drawing.Size(74, 20);
+ this.w_areaID.TabIndex = 11;
+ //
+ // w_warpFrom
+ //
+ this.w_warpFrom.Location = new System.Drawing.Point(199, 26);
+ this.w_warpFrom.Maximum = new decimal(new int[] {
+ 99999,
+ 0,
+ 0,
+ 0});
+ this.w_warpFrom.Name = "w_warpFrom";
+ this.w_warpFrom.Size = new System.Drawing.Size(99, 20);
+ this.w_warpFrom.TabIndex = 10;
+ //
+ // panel_instWarp_controls
+ //
+ this.panel_instWarp_controls.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.panel_instWarp_controls.BackColor = System.Drawing.Color.DarkGray;
+ this.panel_instWarp_controls.Controls.Add(this.label5);
+ this.panel_instWarp_controls.Controls.Add(this.label4);
+ this.panel_instWarp_controls.Controls.Add(this.label3);
+ this.panel_instWarp_controls.Controls.Add(this.label2);
+ this.panel_instWarp_controls.Controls.Add(this.label1);
+ this.panel_instWarp_controls.Controls.Add(this.iw_tz);
+ this.panel_instWarp_controls.Controls.Add(this.iw_ty);
+ this.panel_instWarp_controls.Controls.Add(this.iw_tx);
+ this.panel_instWarp_controls.Controls.Add(this.iw_area);
+ this.panel_instWarp_controls.Controls.Add(this.iw_trigger);
+ this.panel_instWarp_controls.Location = new System.Drawing.Point(0, 0);
+ this.panel_instWarp_controls.Name = "panel_instWarp_controls";
+ this.panel_instWarp_controls.Size = new System.Drawing.Size(407, 183);
+ this.panel_instWarp_controls.TabIndex = 6;
+ //
+ // label5
+ //
+ this.label5.AutoSize = true;
+ this.label5.Font = new System.Drawing.Font("Consolas", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.label5.Location = new System.Drawing.Point(31, 131);
+ this.label5.Name = "label5";
+ this.label5.Size = new System.Drawing.Size(189, 19);
+ this.label5.TabIndex = 9;
+ this.label5.Text = "Teleport on Z axis: ";
+ //
+ // label4
+ //
+ this.label4.AutoSize = true;
+ this.label4.Font = new System.Drawing.Font("Consolas", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.label4.Location = new System.Drawing.Point(31, 105);
+ this.label4.Name = "label4";
+ this.label4.Size = new System.Drawing.Size(189, 19);
+ this.label4.TabIndex = 8;
+ this.label4.Text = "Teleport on Y axis: ";
+ //
+ // label3
+ //
+ this.label3.AutoSize = true;
+ this.label3.Font = new System.Drawing.Font("Consolas", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.label3.Location = new System.Drawing.Point(31, 80);
+ this.label3.Name = "label3";
+ this.label3.Size = new System.Drawing.Size(189, 19);
+ this.label3.TabIndex = 7;
+ this.label3.Text = "Teleport on X axis: ";
+ //
+ // label2
+ //
+ this.label2.AutoSize = true;
+ this.label2.Font = new System.Drawing.Font("Consolas", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.label2.Location = new System.Drawing.Point(130, 54);
+ this.label2.Name = "label2";
+ this.label2.Size = new System.Drawing.Size(90, 19);
+ this.label2.TabIndex = 6;
+ this.label2.Text = "To Area: ";
+ //
+ // label1
+ //
+ this.label1.AutoSize = true;
+ this.label1.Font = new System.Drawing.Font("Consolas", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.label1.Location = new System.Drawing.Point(103, 28);
+ this.label1.Name = "label1";
+ this.label1.Size = new System.Drawing.Size(117, 19);
+ this.label1.TabIndex = 5;
+ this.label1.Text = "Trigger ID: ";
+ //
+ // wi_tz
+ //
+ this.iw_tz.Location = new System.Drawing.Point(226, 131);
+ this.iw_tz.Maximum = new decimal(new int[] {
+ 32767,
+ 0,
+ 0,
+ 0});
+ this.iw_tz.Minimum = new decimal(new int[] {
+ 32768,
+ 0,
+ 0,
+ -2147483648});
+ this.iw_tz.Name = "wi_tz";
+ this.iw_tz.Size = new System.Drawing.Size(99, 20);
+ this.iw_tz.TabIndex = 4;
+ //
+ // iw_ty
+ //
+ this.iw_ty.Location = new System.Drawing.Point(226, 105);
+ this.iw_ty.Maximum = new decimal(new int[] {
+ 32767,
+ 0,
+ 0,
+ 0});
+ this.iw_ty.Minimum = new decimal(new int[] {
+ 32768,
+ 0,
+ 0,
+ -2147483648});
+ this.iw_ty.Name = "iw_ty";
+ this.iw_ty.Size = new System.Drawing.Size(99, 20);
+ this.iw_ty.TabIndex = 3;
+ //
+ // iw_tx
+ //
+ this.iw_tx.Location = new System.Drawing.Point(226, 79);
+ this.iw_tx.Maximum = new decimal(new int[] {
+ 32767,
+ 0,
+ 0,
+ 0});
+ this.iw_tx.Minimum = new decimal(new int[] {
+ 32768,
+ 0,
+ 0,
+ -2147483648});
+ this.iw_tx.Name = "iw_tx";
+ this.iw_tx.Size = new System.Drawing.Size(99, 20);
+ this.iw_tx.TabIndex = 2;
+ //
+ // iw_area
+ //
+ this.iw_area.Location = new System.Drawing.Point(226, 53);
+ this.iw_area.Maximum = new decimal(new int[] {
+ 7,
+ 0,
+ 0,
+ 0});
+ this.iw_area.Name = "iw_area";
+ this.iw_area.Size = new System.Drawing.Size(99, 20);
+ this.iw_area.TabIndex = 1;
+ //
+ // iw_trigger
+ //
+ this.iw_trigger.Location = new System.Drawing.Point(226, 27);
+ this.iw_trigger.Maximum = new decimal(new int[] {
+ 3,
+ 0,
+ 0,
+ 0});
+ this.iw_trigger.Name = "iw_trigger";
+ this.iw_trigger.Size = new System.Drawing.Size(99, 20);
+ this.iw_trigger.TabIndex = 0;
+ //
+ // EditWarp
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(407, 228);
+ this.Controls.Add(this.panel_instWarp_controls);
+ this.Controls.Add(this.panel_warp_controls);
+ this.Controls.Add(this.cancelButton);
+ this.Controls.Add(this.selectButton);
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
+ this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
+ this.MaximizeBox = false;
+ this.MinimizeBox = false;
+ this.Name = "EditWarp";
+ this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
+ this.Text = "Edit Warp";
+ this.Load += new System.EventHandler(this.EditWarp_Load);
+ this.panel_warp_controls.ResumeLayout(false);
+ this.panel_warp_controls.PerformLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.w_warpToID)).EndInit();
+ ((System.ComponentModel.ISupportInitialize)(this.w_areaID)).EndInit();
+ ((System.ComponentModel.ISupportInitialize)(this.w_warpFrom)).EndInit();
+ this.panel_instWarp_controls.ResumeLayout(false);
+ this.panel_instWarp_controls.PerformLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.iw_tz)).EndInit();
+ ((System.ComponentModel.ISupportInitialize)(this.iw_ty)).EndInit();
+ ((System.ComponentModel.ISupportInitialize)(this.iw_tx)).EndInit();
+ ((System.ComponentModel.ISupportInitialize)(this.iw_area)).EndInit();
+ ((System.ComponentModel.ISupportInitialize)(this.iw_trigger)).EndInit();
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.Button cancelButton;
+ private System.Windows.Forms.Button selectButton;
+ private System.Windows.Forms.Panel panel_warp_controls;
+ private System.Windows.Forms.Panel panel_instWarp_controls;
+ private System.Windows.Forms.NumericUpDown iw_trigger;
+ private System.Windows.Forms.NumericUpDown iw_area;
+ private System.Windows.Forms.NumericUpDown iw_tz;
+ private System.Windows.Forms.NumericUpDown iw_ty;
+ private System.Windows.Forms.NumericUpDown iw_tx;
+ private System.Windows.Forms.Label label5;
+ private System.Windows.Forms.Label label4;
+ private System.Windows.Forms.Label label3;
+ private System.Windows.Forms.Label label2;
+ private System.Windows.Forms.Label label1;
+ private System.Windows.Forms.Label label9;
+ private System.Windows.Forms.Label label10;
+ private System.Windows.Forms.NumericUpDown w_areaID;
+ private System.Windows.Forms.NumericUpDown w_warpFrom;
+ private System.Windows.Forms.Label label6;
+ private System.Windows.Forms.ComboBox w_selectLevel;
+ private System.Windows.Forms.Label label7;
+ private System.Windows.Forms.NumericUpDown w_warpToID;
+ }
+}
\ No newline at end of file
diff --git a/src/Forms/EditWarp.cs b/src/Forms/EditWarp.cs
new file mode 100644
index 0000000..78a2a08
--- /dev/null
+++ b/src/Forms/EditWarp.cs
@@ -0,0 +1,118 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+
+namespace Quad64.src.Forms
+{
+ public partial class EditWarp : Form
+ {
+ public byte fromID, toLevel, toArea, toID, triggerID;
+ public short tX, tY, tZ;
+ public bool pressedSaved = false;
+ bool isInstantWarp = false;
+ List levelIds = new List();
+
+ public EditWarp(string title, byte fromID, byte toLevel, byte toArea, byte toID)
+ {
+ this.fromID = fromID;
+ this.toLevel = toLevel;
+ this.toArea = toArea;
+ this.toID = toID;
+ isInstantWarp = false;
+ InitializeComponent();
+ Text = title;
+ }
+
+ public EditWarp(byte triggerID, byte toArea, short teleX, short teleY, short teleZ)
+ {
+ this.triggerID = triggerID;
+ this.toArea = toArea;
+ tX = teleX;
+ tY = teleY;
+ tZ = teleZ;
+ isInstantWarp = true;
+ InitializeComponent();
+ Text = "Update Instant Warp";
+ }
+
+ private void EditWarp_Load(object sender, EventArgs e)
+ {
+ if (Globals.useHexadecimal)
+ {
+ iw_trigger.Hexadecimal = true;
+ iw_area.Hexadecimal = true;
+ iw_tx.Hexadecimal = true;
+ iw_ty.Hexadecimal = true;
+ iw_tz.Hexadecimal = true;
+
+ w_areaID.Hexadecimal = true;
+ w_warpFrom.Hexadecimal = true;
+ w_warpToID.Hexadecimal = true;
+ }
+
+
+ if (!isInstantWarp)
+ {
+ panel_instWarp_controls.Hide();
+ panel_warp_controls.Show();
+ w_warpFrom.Value = fromID;
+ w_warpToID.Value = toID;
+ w_areaID.Value = toArea;
+ levelIds.Clear();
+ foreach (KeyValuePair entry in ROM.Instance.levelIDs)
+ {
+ w_selectLevel.Items.Add(entry.Key + " (0x" + entry.Value.ToString("X2") + ")");
+ levelIds.Add(entry.Value);
+ if (entry.Value == toLevel)
+ {
+ w_selectLevel.SelectedIndex = w_selectLevel.Items.Count - 1;
+ }
+ }
+ }
+ else
+ {
+ panel_instWarp_controls.Show();
+ panel_warp_controls.Hide();
+ iw_trigger.Value = triggerID;
+ iw_area.Value = toArea;
+ iw_tx.Value = tX;
+ iw_ty.Value = tY;
+ iw_tz.Value = tZ;
+ }
+ }
+
+ private void cancelButton_Click(object sender, EventArgs e)
+ {
+ pressedSaved = false;
+ Hide();
+ }
+
+ private void selectButton_Click(object sender, EventArgs e)
+ {
+ if (!isInstantWarp)
+ {
+ fromID = (byte)w_warpFrom.Value;
+ toID = (byte)w_warpToID.Value;
+ toArea = (byte)w_areaID.Value;
+ toLevel = (byte)levelIds[w_selectLevel.SelectedIndex];
+ }
+ else
+ {
+ panel_instWarp_controls.Show();
+ panel_warp_controls.Hide();
+ iw_trigger.Value = triggerID;
+ iw_area.Value = toArea;
+ iw_tx.Value = tX;
+ iw_ty.Value = tY;
+ iw_tz.Value = tZ;
+ }
+ pressedSaved = true;
+ Hide();
+ }
+ }
+}
diff --git a/src/Forms/EditWarp.resx b/src/Forms/EditWarp.resx
new file mode 100644
index 0000000..4969adf
--- /dev/null
+++ b/src/Forms/EditWarp.resx
@@ -0,0 +1,635 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+
+
+ 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
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAA9rRcAOq0WGTuhA1TBPgtezjQNGc01DQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAHK0AAA2tAAQxrQw3L64IoDekAvHBPwz1zjUNoM0yCzfSIAAE0CgAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADR0dEA6tbvEp/Hk3BHtCXUJ68A/TSmAf/CPgv/zjML/c1L
+ KdTMmItwyt3kEsvHxwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB0uQAAAGkAAFWuMQWsw5891NLVp6/Kp+1Mtiz/KK8A/1Gv
+ J//FWzT/zjYO/81TMv/Nq6Ltzc/Pps2roizOJwACtAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB2pAAAZpwABKa4AFy6vB3Z0v13e0dHR/KO2
+ nf9KnDL/bLhW/7TLrP/Ntq7/yXRf/7JROP+6opz/zs7O/M58Zs/NOhRgzjMLC/8AAADcAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAztDOAP/b/wdYtzo8K68DtSyx
+ BPVptlL/nJ6b/0FIPP9baVX/wMa//9HR0P/Pzs3/x8C+/2pbWP9IQkH/op+f/8lxWv/POBHvzjcQms1i
+ RSrK+f8Fy8vLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALzLtQCpyJ0Cx8zEIdbQ
+ 2HZ5wGTcMLEJ/ySXAv8yaCH/KTob/xg1AP9qdGD/ucS2/5zCif/KnIn/x7q2/2hiYv8nAAD/RiIh/387
+ Kv+5MQ7/zz0X/c5+as3N1tldx9XVD/+amgCf//8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHawAAA6o
+ AAVEtCNPqsigtdXS1f1/uG7/IHoF/xJEAP8XMwD/J1IA/ylUAP9QdDz/YrNL/0CpD//CSBj/x2tT/21I
+ Qf9PAAD/bQAA/0kCAf9fEgT/ni8S/8uLev/Q1NTtzKeck8hkSDPFQh4Dx1k7AAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAorwEAKK8BISauAIY5sxXincaQ/6+vsP9IYj//FDUA/x9BAP8rWAD/MWMA/yxWAP8kbAX/JqgD/zOm
+ Af/CPQv/xzQO/20eDP9SAAD/igAA/4AAAP9bAAD/TAsF/3pZUv+7vr//z5iJ/s1JJsjOMwxa0CEDBtAa
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AACmyZ4A/+j/ANDR0gnJzMVaVrc4vyivAPgyqA//X4BV/ztFMv8fOgf/J04B/y5dAP8vXgD/MWMA/ytW
+ AP8fawD/J6gC/0asGf/ETyP/xzQO/24ZBv9SAAD/iQAA/40AAP+JAAD/bwAA/00NDf9aSUn/om1f/8s+
+ Gv7ONxDnzWFFkczV2CLCwcEAzc3NAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAALwAAC6sAAAARQABeL9lJL7NupTM0cvpXbdD/iGRAP8WTgL/HDYI/yJFAf8kTxn/IEky/ydS
+ GP8uWgT/MmMB/ytVAP8nbQr/YbRJ/6nInv/Nq5//x2dN/24gD/9RAAD/iQAA/40AAP+NAAD/jAAA/38A
+ AP9eBAP/SBMO/30hCv++NBD/zXRc+c/Q0cbOwr9QzFExCMAAAADLNwsAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAASa0iAD2tFxAlrQBSTbctyrHLqvq7v7v/RHc0/xA2AP8bOwH/JU0O/x1O
+ Qf8KXpL/A3Os/wxVfv8bRT7/LlwL/ylVAP9geVH/v8i8/9LS0//P0ND/x7y4/25STf9RAAD/iAAA/4IA
+ DP94ARj/iQAE/4UFDP92Bxn/bQEG/0sCAP9aFAb/pGJR/8nLzP7PopbuzVEwiMsyCiTJSCkBykAdAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOK0RAzatD4UsrgT1RLAk/omdgv9TWU7/HTQJ/yNK
+ AP8mVCL/ElJ9/wJ1vf8AqNP/ALDW/wCYzf8HT5n/KlUc/ypVAP90fWr/xsrF/7DIpP/LsaX/yMTD/25l
+ Zf9QAAD/iAAB/1cURf8iIYr/UgxI/2gWMv83P3j/UxtK/30BBf9dAAD/SR0b/4B7e/+6joL/zkgk/M04
+ EcLMPBk1zD0bAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALa4FBSyuBNQlqwD/JncO/yQ2
+ Gf8dPQH/KlYA/yxcDf8SYYX/C47W/yCw1v8TqNb/AqHX/wCX1f8MVJT/LVwS/ytVAP9feVD/fLxq/1Ct
+ JP/DWC7/yIRy/25UUP9QAAD/iAAB/2gkO/8fZrz/CU+5/yQ6jP8TfbL/FGqq/28PJv+KAAD/cAAA/00O
+ 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
+ AP8vXgD/L14A/zBfAf84ZhD/QnEk/zNpC/8xZAD/JlUA/yJVCv+KnoP/zMnM/5fFiv8xpR//HX1C/xMx
+ qv9AGaf/lihI/8VGL//No5j/wcPE/45tZ/9hGRH/fRIR/48JCf+SEBD/X0Nm/yUzoP9NDU7/hQAG/4wA
+ AP+VCgr/ZiUg/7eVjP/QxcPgz8/PMdDQ0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwvVoAbrxXiUKz
+ IPgggQP/FC4A/yxZAP8vXgD/L14A/y9eAP8xZAD/MWMA/y5aBP8gUwT/G3MA/zKmD/+qyaH/1NPT/6C+
+ pv8wXZb/CxLU/w0N4/8NDuP/IBHM/39Ejf/Iq63/z9DP/8yYiv+yNRT/dR0K/2wWEP+DEBD/jgwN/3sO
+ IP+FAwr/jAAA/4wAAP+WCgr/ZRMM/7Y+Hv/PdV7iypqNN8mdkQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAArrQQAK60DjSetAfkbeQD/FS4A/y1aAP8vXgD/MGEA/zNnAP8uWwP/QVom/1dySv83mRv/Jq8A/ze1
+ Dv+yzan/29zY/83N3/+PjuP/R0fi/xYWzv8aGtP/T0/j/5aX4v/Q0N3/2NfU/9Ofjf/SPRP/yDIK/5g/
+ Kf9uR0T/cRwd/4sLC/+TBQT/jAAA/4sAAP+XCQn/ZREL/7UuC//PNg/px0clUcdIJwAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAArrgMAK64DpzGuDP83eSL/FzEB/y5cAP8zZgD/MWEA/yVQAv9JaTb/oZ+h/6bD
+ nf9IuCb/I58T/yRxYP9zfcz/xsbh/+Pj4v/U1NT/d3eZ/x0da/8nJ3T/jY2p/9zc2//i4uL/wcDf/4Jq
+ vf+YLk3/yzEN/9BjRv+3qaX/h318/2onI/95Dg7/lAoK/44BAf+XCQn/ZBUR/7E3GP/PNQ3tzTQMXs00
+ DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABZuT0AW7o/tYzAfP9ufGj/GzgC/zNmAP8pVQH/HVQA/yN9
+ Bv95sWj/1NPU/6rJo/89iGH/ETqd/w8Y0v8aGuH/Skrb/3t7r/9ZWWb/HR1P/w0Ndf8gIJb/PT18/3Fx
+ gv9/f8L/RETf/xoa4v8nFMb/XxyE/7FcZf/Rv7n/ysfH/6hWQP95Hgz/ZxIO/4oPDv+dDQ3/Yxwb/66A
+ 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
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAmQA3MdQAJyPRAhgY4B1sa+F5z87g0N3d4fjDw9z/aWmw/xcXeP8+P5X/q6vQ/9nZ
+ 4P/Z2eHmlZXhrCoq4FAAANwIQji9AUE3vgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAM/DwAC+pZ4C4d3VLsbG4YhjY+HSGxvi+g4O
+ 4f8VFeL/SEjf8K2s36nk5OBT4ODeDeDg3wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADeAAAA
+ 3QgEBOE2FBPdkBAQ4NsXFdyxIB3UXh4Y0BgeGNEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAvLMwALSrNERIR3jMhHdUeKCPQAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAD///5///8AAP///D///wAA///wD///AAD//+AH//8AAP//gAH//wAA//4AAP//
+ AAD//AAAP/8AAP/wAAAf/wAA/+AAAAf/AAD/wAAAA/8AAP8AAAAB/wAA/AAAAAB/AAD4AAAAAB8AAPAA
+ AAAADwAA8AAAAAAPAADwAAAAAA8AAPAAAAAADwAA8AAAAAAPAADwAAAAAA8AAPAAAAAADwAA8AAAAAAP
+ AADwAAAAAA8AAPAAAAAADwAA8AAAAAAPAADwAAAAAA8AAPAAAAAADwAA8AAAAAAPAADwAAAAAA8AAPAA
+ AAAADwAA8AAAAAAPAADgAAAAAA8AAOAAAAAADwAA4AAAAAAPAADgAAAAAA8AAOAAAAAADwAA4AAAAAAP
+ AADgAAAAAA8AAPgAAAAAHwAA/gAAAAB/AAD/gAAAAf8AAP/gAAAH/wAA//AAAA//AAD//AAAP/8AAP//
+ AAD//wAA///AB///AAD///Af//8AAP///D///wAA////////AAAoAAAAOAAAAHAAAAABACAAAAAAAAAx
+ AADCDgAAwg4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAnrwAgzzUKMAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOa0TgCiuAO/ONQ3/zTUNgAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAP7QfMDOtDM8orwD/KK8A/841Df/ONQ3/zTQNz89FHzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANHR0YCCwW//KK8A/yiv
+ AP8orwD/zjUN/841Df/ONQ3/zX1o/8vHx4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAJu7h0DR0dHP0dHR/3/BbP8orwD/Kq8C/1i5O//OZkv/zjcP/841
+ Df/Of2r/zs7O/8zLys/Pj38gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ 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
+ Df/KPRi/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAL7EJ/3a/
+ Yf9gaF3/FS4A/y9eAP8vXgD/L14C/xZUc/8Aktf/EpTF/0B3Mf9OhVD/QKTP/wCH1/8FXLv/J1Eg/y9e
+ AP83bgD/GTgA/yOXAP8orwD/KK8A/841Df/ONQ3/rCwL/yUCAf92AAD/jAAA/4wCAv+Ci5z/B2XU/wBx
+ 1P8AhdT/AJHU/wCj1P8gOY//hgAH/4wAAP+MAAD/jgMD/1wVFf+fbWD/zkUh/841Db8AAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACsyqL/0dHR/2FiYP8YNQD/L14A/y9e
+ AP8nVib/A3HL/wCE1P8XfGz/L14A/ytiNf8OhNP/AGjS/xc6XP8vXgD/L14A/zdvAP8ZNwD/I5kA/yiv
+ AP8qsAP/zjcP/841Df+sLAv/JQIB/3YAAP+MAAD/jAAA/4osMP8sd87/AFrT/xdk0v8Sh9T/AJXU/wZD
+ qv97ABP/jAAA/4wAAP+PAwP/cBMT/5eXl//Ou7b/znJZvwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAx7+/QNHR0f/R0dH/UFVN/xo5AP8vXgD/Ll4D/w5OmP8Addf/A0q2/ylX
+ Fv8tWgb/CS6T/wBn1/8HNZv/LVkJ/y9eAP8vXgD/OHAA/xg1AP8jmgD/QLQe/5PFhP/OkoL/zkcj/6wt
+ C/8lAgH/dQAA/4wAAP+MAAD/jhYW/2SXxf8BTNP/KCmf/4+gtf8NitT/AV6+/zQIYv9/AA//jAAA/44C
+ Av95FBT/jo6O/87Ozv/Ozc2/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AADPz89Ayc/H/4HBbv8XPwr/HT0A/y9eAP8gZEP/AWfV/wBf1/8CMbj/EjFv/xApcf8APc7/ADq6/yFH
+ L/8vXgD/L14A/y9eAP84cAD/GTUC/2qqV//Azrz/0dHR/87Ozv/Ou7b/rWFN/yUDAf91AAD/jAAA/4wA
+ AP+MAQH/fVtp/xFb1P8HNL3/aWSc/xyB1P8AhdT/AHvH/xYdkv+AAA//jgIC/38UFP+DT0L/zr66/8nG
+ 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
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAADw/fIFBQ4p/MzOH/4eHh/+Hh4f/X19j/aGiL/wwMQP89PWr/wsLG/+Hh
+ 4f/h4eH/1NTh/3p64d8NDd9gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAM/ExDDh4eG/wMDh/15e4f8VFeH/Dg7d/xMT4f9LS+H/s7Ph/97e4d/f399gAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAfH99ADQ3hvw8P4f8PD+H/Dw/h/xgX2+80L9NwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJyXRYA4O
+ 4c8hHdWAr4+PEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////////8A////5////wD////D////AP///wD///8A///+AH//
+ /wD///gAH///AP//4AAP//8A///AAAP//wD//wAAAf//AP/+AAAAf/8A//gAAAA//wD/8AAAAA//AP/A
+ AAAAB/8A/4AAAAAB/wD+AAAAAAD/APwAAAAAAD8A/AAAAAAAPwD8AAAAAAA/APwAAAAAAD8A/AAAAAAA
+ PwD4AAAAAAA/APgAAAAAAD8A+AAAAAAAPwD4AAAAAAA/APgAAAAAAD8A+AAAAAAAHwD4AAAAAAAfAPgA
+ AAAAAB8A+AAAAAAAHwD4AAAAAAAfAPgAAAAAAB8A+AAAAAAAHwD4AAAAAAAfAPgAAAAAAB8A+AAAAAAA
+ HwDwAAAAAAAfAPAAAAAAAB8A8AAAAAAAHwDwAAAAAAAfAPAAAAAAAB8A8AAAAAAAHwDwAAAAAAAfAPgA
+ AAAAAB8A/gAAAAAAfwD/gAAAAAH/AP/gAAAAB/8A//gAAAAf/wD//gAAAH//AP//AAAB//8A///AAAf/
+ /wD///AAH///AP///AB///8A////Af///wD////D////AP////////8A/////////wA=
+
+
+
\ No newline at end of file
diff --git a/src/Forms/MainForm.Designer.cs b/src/Forms/MainForm.Designer.cs
index 0813eab..eaf091c 100644
--- a/src/Forms/MainForm.Designer.cs
+++ b/src/Forms/MainForm.Designer.cs
@@ -80,12 +80,16 @@ private void InitializeComponent()
this.splitContainer2 = new System.Windows.Forms.SplitContainer();
this.splitContainer3 = new System.Windows.Forms.SplitContainer();
this.panel3 = new System.Windows.Forms.Panel();
+ this.radioButton_front = new System.Windows.Forms.RadioButton();
+ this.radioButton_back = new System.Windows.Forms.RadioButton();
+ this.radioButton_top = new System.Windows.Forms.RadioButton();
+ this.radioButton_bottom = new System.Windows.Forms.RadioButton();
+ this.radioButton_left = new System.Windows.Forms.RadioButton();
+ this.radioButton_right = new System.Windows.Forms.RadioButton();
this.keepOnGround = new System.Windows.Forms.CheckBox();
this.dropToGround = new System.Windows.Forms.Button();
this.radioButton2 = new System.Windows.Forms.RadioButton();
this.radioButton1 = new System.Windows.Forms.RadioButton();
- this.fovText = new System.Windows.Forms.Label();
- this.trackBar_FOV = new System.Windows.Forms.TrackBar();
this.camSpeedLabel = new System.Windows.Forms.Label();
this.label6 = new System.Windows.Forms.Label();
this.trackBar_camSpeed = new System.Windows.Forms.TrackBar();
@@ -105,6 +109,7 @@ private void InitializeComponent()
this.moveObj = new System.Windows.Forms.PictureBox();
this.movObj_UpDown = new System.Windows.Forms.PictureBox();
this.glControl1 = new OpenTK.GLControl();
+ this.warpToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.menuStrip1.SuspendLayout();
this.statusStrip1.SuspendLayout();
this.panel1.SuspendLayout();
@@ -117,7 +122,6 @@ private void InitializeComponent()
this.splitContainer3.Panel2.SuspendLayout();
this.splitContainer3.SuspendLayout();
this.panel3.SuspendLayout();
- ((System.ComponentModel.ISupportInitialize)(this.trackBar_FOV)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.trackBar_camSpeed)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.trackBar_moveSpeed)).BeginInit();
this.moveCamPanel.SuspendLayout();
@@ -199,6 +203,7 @@ private void InitializeComponent()
this.modelIDToolStripMenuItem,
this.behaviorToolStripMenuItem,
this.behParametersToolStripMenuItem,
+ this.warpToolStripMenuItem,
this.toolStripSeparator5,
this.objectComboNameToolStripMenuItem});
this.editToolStripMenuItem.Name = "editToolStripMenuItem";
@@ -248,25 +253,25 @@ private void InitializeComponent()
// bParam1ToolStripMenuItem
//
this.bParam1ToolStripMenuItem.Name = "bParam1ToolStripMenuItem";
- this.bParam1ToolStripMenuItem.Size = new System.Drawing.Size(130, 22);
+ this.bParam1ToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
this.bParam1ToolStripMenuItem.Text = "B. Param 1";
//
// bParam2ToolStripMenuItem
//
this.bParam2ToolStripMenuItem.Name = "bParam2ToolStripMenuItem";
- this.bParam2ToolStripMenuItem.Size = new System.Drawing.Size(130, 22);
+ this.bParam2ToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
this.bParam2ToolStripMenuItem.Text = "B. Param 2";
//
// bParam3ToolStripMenuItem
//
this.bParam3ToolStripMenuItem.Name = "bParam3ToolStripMenuItem";
- this.bParam3ToolStripMenuItem.Size = new System.Drawing.Size(130, 22);
+ this.bParam3ToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
this.bParam3ToolStripMenuItem.Text = "B. Param 3";
//
// bParam4ToolStripMenuItem
//
this.bParam4ToolStripMenuItem.Name = "bParam4ToolStripMenuItem";
- this.bParam4ToolStripMenuItem.Size = new System.Drawing.Size(130, 22);
+ this.bParam4ToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
this.bParam4ToolStripMenuItem.Text = "B. Param 4";
//
// toolStripSeparator5
@@ -637,12 +642,16 @@ private void InitializeComponent()
this.panel3.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.panel3.BackColor = System.Drawing.Color.Gray;
+ this.panel3.Controls.Add(this.radioButton_front);
+ this.panel3.Controls.Add(this.radioButton_back);
+ this.panel3.Controls.Add(this.radioButton_top);
+ this.panel3.Controls.Add(this.radioButton_bottom);
+ this.panel3.Controls.Add(this.radioButton_left);
+ this.panel3.Controls.Add(this.radioButton_right);
this.panel3.Controls.Add(this.keepOnGround);
this.panel3.Controls.Add(this.dropToGround);
this.panel3.Controls.Add(this.radioButton2);
this.panel3.Controls.Add(this.radioButton1);
- this.panel3.Controls.Add(this.fovText);
- this.panel3.Controls.Add(this.trackBar_FOV);
this.panel3.Controls.Add(this.camSpeedLabel);
this.panel3.Controls.Add(this.label6);
this.panel3.Controls.Add(this.trackBar_camSpeed);
@@ -659,6 +668,96 @@ private void InitializeComponent()
this.panel3.Size = new System.Drawing.Size(649, 120);
this.panel3.TabIndex = 5;
//
+ // radioButton_front
+ //
+ this.radioButton_front.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.radioButton_front.Appearance = System.Windows.Forms.Appearance.Button;
+ this.radioButton_front.Font = new System.Drawing.Font("Corbel", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.radioButton_front.Location = new System.Drawing.Point(561, 99);
+ this.radioButton_front.Name = "radioButton_front";
+ this.radioButton_front.Size = new System.Drawing.Size(44, 20);
+ this.radioButton_front.TabIndex = 22;
+ this.radioButton_front.Text = "Front";
+ this.radioButton_front.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+ this.radioButton_front.UseVisualStyleBackColor = true;
+ this.radioButton_front.CheckedChanged += new System.EventHandler(this.radioButton_front_CheckedChanged);
+ //
+ // radioButton_back
+ //
+ this.radioButton_back.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.radioButton_back.Appearance = System.Windows.Forms.Appearance.Button;
+ this.radioButton_back.Font = new System.Drawing.Font("Corbel", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.radioButton_back.Location = new System.Drawing.Point(604, 99);
+ this.radioButton_back.Name = "radioButton_back";
+ this.radioButton_back.Size = new System.Drawing.Size(44, 20);
+ this.radioButton_back.TabIndex = 21;
+ this.radioButton_back.Text = "Back";
+ this.radioButton_back.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+ this.radioButton_back.UseVisualStyleBackColor = true;
+ this.radioButton_back.CheckedChanged += new System.EventHandler(this.radioButton_back_CheckedChanged);
+ //
+ // radioButton_top
+ //
+ this.radioButton_top.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.radioButton_top.Appearance = System.Windows.Forms.Appearance.Button;
+ this.radioButton_top.Font = new System.Drawing.Font("Corbel", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.radioButton_top.Location = new System.Drawing.Point(561, 61);
+ this.radioButton_top.Name = "radioButton_top";
+ this.radioButton_top.Size = new System.Drawing.Size(44, 20);
+ this.radioButton_top.TabIndex = 20;
+ this.radioButton_top.Text = "Top";
+ this.radioButton_top.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+ this.radioButton_top.UseVisualStyleBackColor = true;
+ this.radioButton_top.CheckedChanged += new System.EventHandler(this.radioButton5_CheckedChanged);
+ //
+ // radioButton_bottom
+ //
+ this.radioButton_bottom.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.radioButton_bottom.Appearance = System.Windows.Forms.Appearance.Button;
+ this.radioButton_bottom.Font = new System.Drawing.Font("Corbel", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.radioButton_bottom.Location = new System.Drawing.Point(604, 61);
+ this.radioButton_bottom.Name = "radioButton_bottom";
+ this.radioButton_bottom.Size = new System.Drawing.Size(44, 20);
+ this.radioButton_bottom.TabIndex = 19;
+ this.radioButton_bottom.Text = "Bttm";
+ this.radioButton_bottom.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+ this.radioButton_bottom.UseVisualStyleBackColor = true;
+ this.radioButton_bottom.CheckedChanged += new System.EventHandler(this.radioButton4_CheckedChanged);
+ //
+ // radioButton_left
+ //
+ this.radioButton_left.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.radioButton_left.Appearance = System.Windows.Forms.Appearance.Button;
+ this.radioButton_left.Font = new System.Drawing.Font("Corbel", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.radioButton_left.Location = new System.Drawing.Point(561, 80);
+ this.radioButton_left.Name = "radioButton_left";
+ this.radioButton_left.Size = new System.Drawing.Size(44, 20);
+ this.radioButton_left.TabIndex = 18;
+ this.radioButton_left.Text = "Left";
+ this.radioButton_left.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+ this.radioButton_left.UseVisualStyleBackColor = true;
+ this.radioButton_left.CheckedChanged += new System.EventHandler(this.radioButton_left_CheckedChanged);
+ //
+ // radioButton_right
+ //
+ this.radioButton_right.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.radioButton_right.Appearance = System.Windows.Forms.Appearance.Button;
+ this.radioButton_right.Font = new System.Drawing.Font("Corbel", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.radioButton_right.Location = new System.Drawing.Point(604, 80);
+ this.radioButton_right.Name = "radioButton_right";
+ this.radioButton_right.Size = new System.Drawing.Size(44, 20);
+ this.radioButton_right.TabIndex = 17;
+ this.radioButton_right.Text = "Right";
+ this.radioButton_right.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+ this.radioButton_right.UseVisualStyleBackColor = true;
+ this.radioButton_right.CheckedChanged += new System.EventHandler(this.radioButton_right_CheckedChanged);
+ //
// keepOnGround
//
this.keepOnGround.Appearance = System.Windows.Forms.Appearance.Button;
@@ -692,9 +791,9 @@ private void InitializeComponent()
| System.Windows.Forms.AnchorStyles.Right)));
this.radioButton2.Appearance = System.Windows.Forms.Appearance.Button;
this.radioButton2.Font = new System.Drawing.Font("Corbel", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
- this.radioButton2.Location = new System.Drawing.Point(605, 98);
+ this.radioButton2.Location = new System.Drawing.Point(604, 42);
this.radioButton2.Name = "radioButton2";
- this.radioButton2.Size = new System.Drawing.Size(40, 20);
+ this.radioButton2.Size = new System.Drawing.Size(44, 20);
this.radioButton2.TabIndex = 16;
this.radioButton2.Text = "Orbit";
this.radioButton2.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
@@ -708,9 +807,9 @@ private void InitializeComponent()
this.radioButton1.Appearance = System.Windows.Forms.Appearance.Button;
this.radioButton1.Checked = true;
this.radioButton1.Font = new System.Drawing.Font("Corbel", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
- this.radioButton1.Location = new System.Drawing.Point(569, 98);
+ this.radioButton1.Location = new System.Drawing.Point(561, 42);
this.radioButton1.Name = "radioButton1";
- this.radioButton1.Size = new System.Drawing.Size(38, 20);
+ this.radioButton1.Size = new System.Drawing.Size(44, 20);
this.radioButton1.TabIndex = 15;
this.radioButton1.TabStop = true;
this.radioButton1.Text = "Fly";
@@ -718,40 +817,13 @@ private void InitializeComponent()
this.radioButton1.UseVisualStyleBackColor = true;
this.radioButton1.CheckedChanged += new System.EventHandler(this.radioButton1_CheckedChanged);
//
- // fovText
- //
- this.fovText.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
- | System.Windows.Forms.AnchorStyles.Right)));
- this.fovText.AutoSize = true;
- this.fovText.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
- this.fovText.Location = new System.Drawing.Point(579, 54);
- this.fovText.Name = "fovText";
- this.fovText.Size = new System.Drawing.Size(63, 14);
- this.fovText.TabIndex = 14;
- this.fovText.Text = "FOV: 60°";
- //
- // trackBar_FOV
- //
- this.trackBar_FOV.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
- this.trackBar_FOV.Location = new System.Drawing.Point(565, 67);
- this.trackBar_FOV.Maximum = 120;
- this.trackBar_FOV.Minimum = 15;
- this.trackBar_FOV.Name = "trackBar_FOV";
- this.trackBar_FOV.Size = new System.Drawing.Size(86, 45);
- this.trackBar_FOV.SmallChange = 2;
- this.trackBar_FOV.TabIndex = 13;
- this.trackBar_FOV.TabStop = false;
- this.trackBar_FOV.TickFrequency = 15;
- this.trackBar_FOV.Value = 60;
- this.trackBar_FOV.ValueChanged += new System.EventHandler(this.trackBar1_ValueChanged);
- //
// camSpeedLabel
//
this.camSpeedLabel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Right)));
this.camSpeedLabel.AutoSize = true;
this.camSpeedLabel.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
- this.camSpeedLabel.Location = new System.Drawing.Point(592, 13);
+ this.camSpeedLabel.Location = new System.Drawing.Point(616, 2);
this.camSpeedLabel.Name = "camSpeedLabel";
this.camSpeedLabel.Size = new System.Drawing.Size(35, 14);
this.camSpeedLabel.TabIndex = 12;
@@ -764,11 +836,11 @@ private void InitializeComponent()
| System.Windows.Forms.AnchorStyles.Right)));
this.label6.AutoSize = true;
this.label6.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
- this.label6.Location = new System.Drawing.Point(569, 0);
+ this.label6.Location = new System.Drawing.Point(559, 2);
this.label6.Name = "label6";
- this.label6.Size = new System.Drawing.Size(77, 14);
+ this.label6.Size = new System.Drawing.Size(63, 14);
this.label6.TabIndex = 11;
- this.label6.Text = "Cam speed:";
+ this.label6.Text = "Cam spd:";
this.label6.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// trackBar_camSpeed
@@ -776,7 +848,7 @@ private void InitializeComponent()
this.trackBar_camSpeed.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Right)));
this.trackBar_camSpeed.LargeChange = 10;
- this.trackBar_camSpeed.Location = new System.Drawing.Point(565, 25);
+ this.trackBar_camSpeed.Location = new System.Drawing.Point(565, 14);
this.trackBar_camSpeed.Maximum = 100;
this.trackBar_camSpeed.Name = "trackBar_camSpeed";
this.trackBar_camSpeed.Size = new System.Drawing.Size(82, 45);
@@ -832,7 +904,7 @@ private void InitializeComponent()
this.moveCamPanel.Controls.Add(this.label2);
this.moveCamPanel.Controls.Add(this.moveCam_strafe);
this.moveCamPanel.Controls.Add(this.moveCam_InOut);
- this.moveCamPanel.Location = new System.Drawing.Point(436, 2);
+ this.moveCamPanel.Location = new System.Drawing.Point(434, 2);
this.moveCamPanel.Margin = new System.Windows.Forms.Padding(1);
this.moveCamPanel.Name = "moveCamPanel";
this.moveCamPanel.Size = new System.Drawing.Size(125, 120);
@@ -1001,6 +1073,14 @@ private void InitializeComponent()
this.glControl1.MouseUp += new System.Windows.Forms.MouseEventHandler(this.glControl1_MouseUp);
this.glControl1.Resize += new System.EventHandler(this.glControl1_Resize);
//
+ // warpToolStripMenuItem
+ //
+ this.warpToolStripMenuItem.Enabled = false;
+ this.warpToolStripMenuItem.Name = "warpToolStripMenuItem";
+ this.warpToolStripMenuItem.Size = new System.Drawing.Size(189, 22);
+ this.warpToolStripMenuItem.Text = "Warp";
+ this.warpToolStripMenuItem.Click += new System.EventHandler(this.warpToolStripMenuItem_Click);
+ //
// MainForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
@@ -1014,7 +1094,7 @@ private void InitializeComponent()
this.MinimumSize = new System.Drawing.Size(820, 522);
this.Name = "MainForm";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
- this.Text = "Quad64 v0.2 (Beta build 2)";
+ this.Text = "Quad64 v0.2 (Beta build 3)";
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing);
this.Shown += new System.EventHandler(this.Form1_Shown);
this.menuStrip1.ResumeLayout(false);
@@ -1033,7 +1113,6 @@ private void InitializeComponent()
this.splitContainer3.ResumeLayout(false);
this.panel3.ResumeLayout(false);
this.panel3.PerformLayout();
- ((System.ComponentModel.ISupportInitialize)(this.trackBar_FOV)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.trackBar_camSpeed)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.trackBar_moveSpeed)).EndInit();
this.moveCamPanel.ResumeLayout(false);
@@ -1087,8 +1166,6 @@ private void InitializeComponent()
private System.Windows.Forms.Label label3;
private System.Windows.Forms.TrackBar trackBar_moveSpeed;
private System.Windows.Forms.Label objSpeedLabel;
- private System.Windows.Forms.Label fovText;
- private System.Windows.Forms.TrackBar trackBar_FOV;
private System.Windows.Forms.Label camSpeedLabel;
private System.Windows.Forms.Label label6;
private System.Windows.Forms.TrackBar trackBar_camSpeed;
@@ -1130,6 +1207,13 @@ private void InitializeComponent()
private System.Windows.Forms.ToolStripMenuItem bParam4ToolStripMenuItem;
private System.Windows.Forms.ToolStripSeparator toolStripSeparator5;
private System.Windows.Forms.ToolStripMenuItem objectComboNameToolStripMenuItem;
+ private System.Windows.Forms.RadioButton radioButton_right;
+ private System.Windows.Forms.RadioButton radioButton_front;
+ private System.Windows.Forms.RadioButton radioButton_back;
+ private System.Windows.Forms.RadioButton radioButton_top;
+ private System.Windows.Forms.RadioButton radioButton_bottom;
+ private System.Windows.Forms.RadioButton radioButton_left;
+ private System.Windows.Forms.ToolStripMenuItem warpToolStripMenuItem;
}
}
diff --git a/src/Forms/MainForm.cs b/src/Forms/MainForm.cs
index be49bd7..53fd68e 100644
--- a/src/Forms/MainForm.cs
+++ b/src/Forms/MainForm.cs
@@ -58,7 +58,7 @@ private void initTreeView()
treeView1.Nodes.Add(makeTreeNode("Macro 3D Objects", Color.FromArgb(0, 0, 192)));
treeView1.Nodes.Add(makeTreeNode("Special 3D Objects", Color.FromArgb(0, 192, 0)));
treeView1.Nodes.Add(makeTreeNode("Warps", Color.FromArgb(0, 0, 0)));
- treeView1.Anchor = (AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left| AnchorStyles.Right );
+ treeView1.Anchor = (AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right);
treeView1.Size = new Size(217, 206);
treeView1.TabIndex = 0;
treeView1.TabStop = false;
@@ -80,7 +80,7 @@ public MainForm()
glControl1.CreateControl();
SettingsFile.LoadGlobalSettings("default");
glControl1.MouseWheel += new MouseEventHandler(glControl1_Wheel);
- ProjMatrix = Matrix4.CreatePerspectiveFieldOfView(FOV, (float)glControl1.Width/(float)glControl1.Height, 100f, 100000f);
+ ProjMatrix = Matrix4.CreatePerspectiveFieldOfView(FOV, (float)glControl1.Width / (float)glControl1.Height, 100f, 100000f);
glControl1.Enabled = false;
KeyPreview = true;
treeView1.HideSelection = false;
@@ -121,7 +121,7 @@ private void loadROM(bool startingUp)
BehaviorNameFile.parseBehaviorNames(Globals.getDefaultBehaviorNamesPath());
ModelComboFile.parseObjectCombos(Globals.getDefaultObjectComboPath());
rom.setSegment(0x15, Globals.seg15_location[0], Globals.seg15_location[1], false);
- rom.setSegment(0x02, Globals.seg02_location[0], Globals.seg02_location[1],
+ rom.setSegment(0x02, Globals.seg02_location[0], Globals.seg02_location[1],
rom.isSegmentMIO0(0x02), rom.Seg02_isFakeMIO0, rom.Seg02_uncompressedOffset);
level = new Level(0x10, 1);
LevelScripts.parse(ref level, 0x15, 0);
@@ -155,7 +155,7 @@ private void refreshObjectsInList()
{
obj.Title = obj.getObjectComboName();
objects.Nodes.Add(obj.Title);
- // objects.Nodes.Add("0x" + obj.Behavior.ToString("X8"));
+ // objects.Nodes.Add("0x" + obj.Behavior.ToString("X8"));
}
TreeNode macro_objects = treeView1.Nodes[1];
@@ -192,7 +192,7 @@ private void refreshObjectsInList()
}
EndUpdate(treeView1);
}
-
+
private void glControl1_Paint(object sender, PaintEventArgs e)
{
GL.ClearColor(bgColor);
@@ -237,7 +237,7 @@ private void selectObject(int mx, int my)
GL.ReadPixels(mx, h - my, 1, 1, PixelFormat.Rgba, PixelType.UnsignedByte, pixel);
if (pixel[0] == pixel[1] && pixel[1] == pixel[2])
{
- if(pixel[2] == 255 || pixel[2] == 0)
+ if (pixel[2] == 255 || pixel[2] == 0)
return; // If a pixel is fully white or fully black, then ignore picking.
}
if (pixel[2] > 0 && pixel[2] < 4)
@@ -249,7 +249,7 @@ private void selectObject(int mx, int my)
bool setSelected = !treeViewAlreadyHasNodeSelected(treeView1.Nodes[Globals.list_selected].Nodes[Globals.item_selected]);
treeView1.ToggleNode(treeView1.Nodes[Globals.list_selected].Nodes[Globals.item_selected],
setSelected);
- if(setSelected)
+ if (setSelected)
updateAfterSelect(treeView1.Nodes[Globals.list_selected].Nodes[Globals.item_selected]);
else
treeView1_updateMultiselection();
@@ -259,7 +259,7 @@ private void selectObject(int mx, int my)
treeView1.SelectSingleNode(treeView1.Nodes[Globals.list_selected].Nodes[Globals.item_selected]);
updateAfterSelect(treeView1.Nodes[Globals.list_selected].Nodes[Globals.item_selected]);
}
-
+
if (camera.isOrbitCamera())
{
camera.updateOrbitCamera(ref camMtx);
@@ -334,10 +334,10 @@ private void glControl1_KeyUp(object sender, KeyEventArgs e)
case Keys.A: isADown = false; break;
case Keys.D: isDDown = false; break;
}
- if(!isWDown && !isSDown && !isADown && !isDDown)
+ if (!isWDown && !isSDown && !isADown && !isDDown)
myTimer.Enabled = false;
}
-
+
private void glControl1_Leave(object sender, EventArgs e)
{
isWDown = false;
@@ -386,34 +386,6 @@ private void glControl1_KeyDown(object sender, KeyEventArgs e)
isControlDown = e.Control;
switch (e.KeyCode)
{
- case Keys.P:
- /*
- if (Globals.list_selected != -1 && Globals.item_selected != -1)
- {
- int listSel = Globals.list_selected;
- int objSel = Globals.item_selected;
- Object3D obj = getSelectedObject();
- if (obj == null) return;
- string newName = Prompts.ShowInputDialog("Type the new combo name", "New combo name");
- if (newName.Length > 0)
- {
- obj.Title = newName;
- uint segmentAddress = 0;
- if (level.ModelIDs.ContainsKey(obj.ModelID))
- segmentAddress = level.ModelIDs[obj.ModelID].GeoDataSegAddress;
- ObjectComboEntry oce = new ObjectComboEntry(newName, obj.ModelID,
- segmentAddress, obj.getBehaviorAddress());
- Globals.insertNewEntry(oce);
- refreshObjectsInList();
- treeView1.SelectedNode = treeView1.Nodes[listSel].Nodes[objSel];
- Globals.list_selected = listSel;
- Globals.item_selected = objSel;
- propertyGrid1.Refresh();
- }
- ModelComboFile.writeObjectCombosFile(Globals.getDefaultObjectComboPath());
- Console.WriteLine("Saved Object Combos!");
- }*/
- break;
case Keys.W:
isWDown = true;
myTimer.Enabled = true;
@@ -468,7 +440,7 @@ private void glControl1_Load(object sender, EventArgs e)
GL.Enable(EnableCap.Texture2D);
GL.Enable(EnableCap.AlphaTest);
GL.AlphaFunc(AlphaFunction.Gequal, 0.5f);
-
+
if (Globals.doBackfaceCulling)
GL.Enable(EnableCap.CullFace);
else
@@ -479,14 +451,14 @@ private void glControl1_Resize(object sender, EventArgs e)
{
glControl1.Context.Update(glControl1.WindowInfo);
GL.Viewport(0, 0, glControl1.Width, glControl1.Height);
- ProjMatrix = Matrix4.CreatePerspectiveFieldOfView(FOV, (float)glControl1.Width/(float)glControl1.Height, 100f, 100000f);
+ ProjMatrix = Matrix4.CreatePerspectiveFieldOfView(FOV, (float)glControl1.Width / (float)glControl1.Height, 100f, 100000f);
glControl1.Invalidate();
}
-
+
private void loadROMToolStripMenuItem_Click(object sender, EventArgs e)
{
DialogResult saveResult = Prompts.ShowShouldSaveDialog();
- if(saveResult != DialogResult.Cancel)
+ if (saveResult != DialogResult.Cancel)
loadROM(false);
}
@@ -497,7 +469,7 @@ private void saveROMAsToolStripMenuItem_Click(object sender, EventArgs e)
DialogResult result = saveFileDialog1.ShowDialog();
if (result == DialogResult.OK) // Test result.
{
- if(saveFileDialog1.FilterIndex == 1 || saveFileDialog1.FilterIndex == 4)
+ if (saveFileDialog1.FilterIndex == 1 || saveFileDialog1.FilterIndex == 4)
ROM.Instance.saveFileAs(saveFileDialog1.FileName, ROM_Endian.BIG);
else if (saveFileDialog1.FilterIndex == 2)
ROM.Instance.saveFileAs(saveFileDialog1.FileName, ROM_Endian.MIXED);
@@ -510,7 +482,7 @@ private void saveROMToolStripMenuItem_Click(object sender, EventArgs e)
{
ROM.Instance.saveFile();
}
-
+
private void settingsToolStripMenuItem_Click(object sender, EventArgs e)
{
SettingsForm settings = new SettingsForm();
@@ -578,7 +550,45 @@ private void replaceSpecialObject(int index, ref SelectComboPreset comboWindow)
= area.SpecialObjects[index].getObjectComboName();
area.SpecialObjects[index].UpdateProperties();
}
-
+
+ private void replaceWarp(int index, ref EditWarp editWarpWindow)
+ {
+ //Console.WriteLine(comboWindow.ReturnPresetMacro.PresetID);
+ Area area = level.getCurrentArea();
+ area.Warps[index].WarpFrom_ID = editWarpWindow.fromID;
+ area.Warps[index].WarpTo_AreaID = editWarpWindow.toArea;
+ area.Warps[index].WarpTo_LevelID = editWarpWindow.toLevel;
+ area.Warps[index].WarpTo_WarpID = editWarpWindow.toID;
+
+ treeView1.Nodes[3].Nodes[index].Text = area.Warps[index].ToString();
+ // area.SpecialObjects[index].UpdateProperties();
+ }
+
+ private void replacePaintingWarp(int index, ref EditWarp editWarpWindow)
+ {
+ //Console.WriteLine(comboWindow.ReturnPresetMacro.PresetID);
+ Area area = level.getCurrentArea();
+ area.PaintingWarps[index].WarpFrom_ID = editWarpWindow.fromID;
+ area.PaintingWarps[index].WarpTo_AreaID = editWarpWindow.toArea;
+ area.PaintingWarps[index].WarpTo_LevelID = editWarpWindow.toLevel;
+ area.PaintingWarps[index].WarpTo_WarpID = editWarpWindow.toID;
+
+ treeView1.Nodes[3].Nodes[index].Text = area.Warps[index].ToString();
+ // area.SpecialObjects[index].UpdateProperties();
+ }
+
+ private void replaceInstantWarp(int index, ref EditWarp editWarpWindow)
+ {
+ //Console.WriteLine(comboWindow.ReturnPresetMacro.PresetID);
+ Area area = level.getCurrentArea();
+ area.InstantWarps[index].AreaID = editWarpWindow.toArea;
+ area.InstantWarps[index].TriggerID = editWarpWindow.triggerID;
+ area.InstantWarps[index].TeleX = editWarpWindow.tX;
+ area.InstantWarps[index].TeleY = editWarpWindow.tY;
+ area.InstantWarps[index].TeleZ = editWarpWindow.tZ;
+ treeView1.Nodes[3].Nodes[index].Text = area.InstantWarps[index].ToString();
+ }
+
private void behaviorToolStripMenuItem_Click(object sender, EventArgs e)
{
SelectBehavior behWindow = new SelectBehavior();
@@ -597,7 +607,7 @@ private void behaviorToolStripMenuItem_Click(object sender, EventArgs e)
glControl1.Update(); // Needed after calling propertyGrid1.Refresh();
}
}
-
+
private void objectComboNameToolStripMenuItem_Click(object sender, EventArgs e)
{
RenameObjectCombo roc = new RenameObjectCombo(getSelectedObject().Title);
@@ -621,8 +631,8 @@ private void objectComboNameToolStripMenuItem_Click(object sender, EventArgs e)
area.SpecialObjects[node.Index].renameObjectCombo(roc.ReturnName);
}
}
- // Console.WriteLine("Changed object combo name to " + roc.ReturnName);
-
+ // Console.WriteLine("Changed object combo name to " + roc.ReturnName);
+
updateSelectedObjectsInROM();
glControl1.Invalidate();
propertyGrid1.Refresh();
@@ -641,7 +651,7 @@ private void objectComboPresetToolStripMenuItem_Click(object sender, EventArgs e
comboWindow =
new SelectComboPreset(level, 0, "Select Object Combos", Color.DarkRed);
comboWindow.ShowDialog();
- if(comboWindow.ClickedSelect)
+ if (comboWindow.ClickedSelect)
{
if (!Globals.isMultiSelected)
replaceObject(Globals.item_selected, ref comboWindow);
@@ -692,17 +702,66 @@ private void objectComboPresetToolStripMenuItem_Click(object sender, EventArgs e
Globals.needToSave = true;
}
+
+ private void warpToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ int warpIndex = 0;
+ bool isPaintingWarp = false;
+ object warp = getSelectedWarp(out warpIndex, out isPaintingWarp);
+ Area area = level.getCurrentArea();
+ if (warp is Warp)
+ {
+ Warp w = (Warp)warp;
+ string title = "Update Painting Warp";
+ if (w.ToString().StartsWith("Warp "))
+ title = "Update Warp";
+
+ EditWarp editWarpWindow = new EditWarp(title, w.WarpFrom_ID, w.WarpTo_LevelID, w.WarpTo_AreaID, w.WarpTo_WarpID);
+ editWarpWindow.ShowDialog();
+ if (editWarpWindow.pressedSaved)
+ {
+ if(isPaintingWarp)
+ replacePaintingWarp(warpIndex - area.Warps.Count, ref editWarpWindow);
+ else
+ replaceWarp(warpIndex, ref editWarpWindow);
+ updateSelectedWarpsInROM();
+ glControl1.Invalidate();
+ propertyGrid1.Refresh();
+ glControl1.Update(); // Needed after calling propertyGrid1.Refresh();
+ Globals.needToSave = true;
+ }
+ }
+ else if (warp is WarpInstant)
+ {
+ WarpInstant w = (WarpInstant)warp;
+ EditWarp editWarpWindow = new EditWarp(w.TriggerID, w.AreaID, w.TeleX, w.TeleY, w.TeleZ);
+ editWarpWindow.ShowDialog();
+ if (editWarpWindow.pressedSaved)
+ {
+ replaceInstantWarp(warpIndex - area.Warps.Count - area.PaintingWarps.Count, ref editWarpWindow);
+ updateSelectedWarpsInROM();
+ glControl1.Invalidate();
+ propertyGrid1.Refresh();
+ glControl1.Update(); // Needed after calling propertyGrid1.Refresh();
+ Globals.needToSave = true;
+ }
+ }
+
+ //EditWarp editWarpWindow = new EditWarp();
+ //editWarpWindow.ShowDialog();
+ }
+
private void Form1_Shown(object sender, EventArgs e)
{
string glString = GL.GetString(StringName.Version).Split(' ')[0];
if (glString.StartsWith("1."))
{
MessageBox.Show(
- "Error: You have an outdated version of OpenGL, which is not supported by this program."+
+ "Error: You have an outdated version of OpenGL, which is not supported by this program." +
" The program will now exit.\n\n" +
"OpenGL version: [" + GL.GetString(StringName.Version) + "]\n",
- "OpenGL version error",
- MessageBoxButtons.OK,
+ "OpenGL version error",
+ MessageBoxButtons.OK,
MessageBoxIcon.Error
);
Close();
@@ -741,7 +800,7 @@ private void trySwitchArea(ushort toArea)
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
-
+
}
private void resetObjectVariables()
@@ -792,8 +851,7 @@ private void selectLeveToolStripMenuItem_Click(object sender, EventArgs e)
switchLevel(newLevel.levelID);
}
}
-
-
+
private void testROMToolStripMenuItem_Click(object sender, EventArgs e)
{
LaunchROM.OpenEmulator();
@@ -838,12 +896,15 @@ private void updateAfterSelect(TreeNode node)
Globals.isMultiSelected = false;
Globals.isMultiSelectedFromMultipleLists = false;
+ Globals.isMultiSelectedFromSpecialObjects = false;
+ Globals.isMultiSelectedFromBothNormalWarpsAndInstantWarps = false;
propertyGrid1.SelectedObject = null;
Globals.list_selected = -1;
Globals.item_selected = -1;
objectComboPresetToolStripMenuItem.Enabled = false;
objectComboNameToolStripMenuItem.Enabled = false;
behaviorToolStripMenuItem.Enabled = false;
+ warpToolStripMenuItem.Enabled = false;
glControl1.Invalidate();
glControl1.Update();
@@ -853,24 +914,29 @@ private void updateAfterSelect(TreeNode node)
objectComboPresetToolStripMenuItem.Enabled = true;
objectComboNameToolStripMenuItem.Enabled = true;
behaviorToolStripMenuItem.Enabled = true;
+ warpToolStripMenuItem.Enabled = false;
if (treeView1.SelectedNodes.Count > 1)
{
Area area = level.getCurrentArea();
string parent_text = treeView1.SelectedNodes[0].Parent.Text;
-
+
if (parent_text.Equals("3D Objects"))
Globals.list_selected = 0;
else if (parent_text.Equals("Macro 3D Objects"))
Globals.list_selected = 1;
else if (parent_text.Equals("Special 3D Objects"))
Globals.list_selected = 2;
-
- if(Globals.list_selected != 0)
+ else if (parent_text.Equals("Warps"))
+ Globals.list_selected = 3;
+
+ if (Globals.list_selected != 0)
behaviorToolStripMenuItem.Enabled = false;
Globals.isMultiSelectedFromMultipleLists = false;
Globals.isMultiSelectedFromSpecialObjects = false;
bool hasSO_8 = false, hasSO_10 = false, hasSO_12 = false;
+ Globals.isMultiSelectedFromBothNormalWarpsAndInstantWarps = false;
+ bool hasRegularWarp = false, hasInstantWarp = false;
if (Globals.list_selected == 2)
{
Object3D obj3d_0 = area.SpecialObjects[treeView1.SelectedNodes[0].Index];
@@ -897,6 +963,7 @@ private void updateAfterSelect(TreeNode node)
objectComboPresetToolStripMenuItem.Enabled = false;
objectComboNameToolStripMenuItem.Enabled = false;
behaviorToolStripMenuItem.Enabled = false;
+ warpToolStripMenuItem.Enabled = false;
if (Globals.list_selected != 2 || (Globals.list_selected == 2 && Globals.isMultiSelectedFromSpecialObjects))
break;
}
@@ -918,22 +985,25 @@ private void updateAfterSelect(TreeNode node)
}
//Console.WriteLine(hasSO_8 + "/" + hasSO_10 + "/" + hasSO_12);
- if (atLeastTwoBools(hasSO_8, hasSO_10, hasSO_12)) {
+ if (atLeastTwoBools(hasSO_8, hasSO_10, hasSO_12))
+ {
Globals.isMultiSelectedFromSpecialObjects = true;
objectComboPresetToolStripMenuItem.Enabled = false;
objectComboNameToolStripMenuItem.Enabled = false;
behaviorToolStripMenuItem.Enabled = false;
+ warpToolStripMenuItem.Enabled = false;
if (Globals.isMultiSelectedFromMultipleLists)
break;
}
}
}
-
+
Object3D[] selectedObjs = new Object3D[treeView1.SelectedNodes.Count];
+ object[] selectedWarps = new object[treeView1.SelectedNodes.Count];
Object3D.FLAGS showFlags =
Object3D.FLAGS.POSITION_X | Object3D.FLAGS.POSITION_Y | Object3D.FLAGS.POSITION_Z |
- Object3D.FLAGS.ROTATION_Y | Object3D.FLAGS.BPARAM_1 | Object3D.FLAGS.BPARAM_2;
-
+ Object3D.FLAGS.ROTATION_Y | Object3D.FLAGS.BPARAM_1 | Object3D.FLAGS.BPARAM_2;;
+
for (int i = 0; i < treeView1.SelectedNodes.Count; i++)
{
string local_parent_text = treeView1.SelectedNodes[i].Parent.Text;
@@ -952,20 +1022,32 @@ private void updateAfterSelect(TreeNode node)
else if (selectedObjs[i].createdFromLevelScriptCommand == Object3D.FROM_LS_CMD.CMD_2E_10)
showFlags &= ~(Object3D.FLAGS.BPARAM_1 | Object3D.FLAGS.BPARAM_2);
}
+ else if (local_parent_text.Equals("Warps"))
+ {
+ if (treeView1.SelectedNodes[i].Index < area.Warps.Count)
+ selectedWarps[i] = area.Warps[treeView1.SelectedNodes[i].Index];
+ else if (treeView1.SelectedNodes[i].Index < area.Warps.Count + area.PaintingWarps.Count)
+ selectedWarps[i] = area.PaintingWarps[treeView1.SelectedNodes[i].Index - area.Warps.Count];
+ else
+ selectedWarps[i] = area.InstantWarps[treeView1.SelectedNodes[i].Index - area.Warps.Count - area.PaintingWarps.Count];
+ }
}
for (int i = 0; i < selectedObjs.Length; i++)
{
{
selectedObjs[i].RevealTemporaryHiddenFields();
- // Console.WriteLine(Globals.isMultiSelectedFromSpecialObjects);
+ // Console.WriteLine(Globals.isMultiSelectedFromSpecialObjects);
if (Globals.isMultiSelectedFromMultipleLists || Globals.isMultiSelectedFromSpecialObjects)
{
selectedObjs[i].HideFieldsTemporarly(showFlags);
}
}
}
-
- propertyGrid1.SelectedObjects = selectedObjs;
+
+ if(Globals.list_selected == 3)
+ propertyGrid1.SelectedObjects = selectedWarps;
+ else
+ propertyGrid1.SelectedObjects = selectedObjs;
treeView1_updateMultiselection();
Globals.isMultiSelected = true;
@@ -973,7 +1055,7 @@ private void updateAfterSelect(TreeNode node)
glControl1.Update();
return;
}
- // Console.WriteLine("Single Node!");
+ // Console.WriteLine("Single Node!");
Globals.isMultiSelected = false;
Globals.isMultiSelectedFromMultipleLists = false;
Globals.isMultiSelectedFromSpecialObjects = false;
@@ -981,6 +1063,7 @@ private void updateAfterSelect(TreeNode node)
if (node.Parent.Text.Equals("3D Objects"))
{
behaviorToolStripMenuItem.Enabled = true;
+ warpToolStripMenuItem.Enabled = false;
Globals.list_selected = 0;
Globals.item_selected = node.Index;
propertyGrid1.SelectedObject = level.getCurrentArea().Objects[node.Index];
@@ -995,6 +1078,7 @@ private void updateAfterSelect(TreeNode node)
else if (node.Parent.Text.Equals("Macro 3D Objects"))
{
behaviorToolStripMenuItem.Enabled = false;
+ warpToolStripMenuItem.Enabled = false;
Globals.list_selected = 1;
Globals.item_selected = node.Index;
propertyGrid1.SelectedObject = level.getCurrentArea().MacroObjects[node.Index];
@@ -1009,6 +1093,7 @@ private void updateAfterSelect(TreeNode node)
else if (node.Parent.Text.Equals("Special 3D Objects"))
{
behaviorToolStripMenuItem.Enabled = false;
+ warpToolStripMenuItem.Enabled = false;
Globals.list_selected = 2;
Globals.item_selected = node.Index;
propertyGrid1.SelectedObject = level.getCurrentArea().SpecialObjects[node.Index];
@@ -1023,6 +1108,8 @@ private void updateAfterSelect(TreeNode node)
else if (node.Parent.Text.Equals("Warps"))
{
behaviorToolStripMenuItem.Enabled = false;
+ objectComboNameToolStripMenuItem.Enabled = false;
+ warpToolStripMenuItem.Enabled = true;
Globals.list_selected = 3;
Globals.item_selected = node.Index;
Area area = level.getCurrentArea();
@@ -1034,7 +1121,7 @@ private void updateAfterSelect(TreeNode node)
propertyGrid1.SelectedObject = area.InstantWarps[node.Index - area.Warps.Count - area.PaintingWarps.Count];
}
}
-
+
Object3D obj = getSelectedObject();
if (obj != null)
{
@@ -1060,12 +1147,14 @@ private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
private void trackBar1_ValueChanged(object sender, EventArgs e)
{
+ /*
fovText.Text = "FOV: " + trackBar_FOV.Value + "°";
FOV = trackBar_FOV.Value * ((float)Math.PI/180.0f);
if (FOV < 0.1f)
FOV = 0.1f;
ProjMatrix = Matrix4.CreatePerspectiveFieldOfView(FOV, (float)glControl1.Width / (float)glControl1.Height, 100f, 100000f);
glControl1.Invalidate();
+ */
}
private void propertyGrid1_PropertyValueChanged(object s, PropertyValueChangedEventArgs e)
@@ -1120,7 +1209,7 @@ private void propertyGrid1_PropertyValueChanged(object s, PropertyValueChangedEv
if (obj == null)
continue;
-
+
Object3D.FLAGS flag = obj.getFlagFromDisplayName(e.ChangedItem.Label);
if (flag != 0)
if (!obj.isPropertyShown(flag))
@@ -1162,7 +1251,9 @@ private void propertyGrid1_PropertyValueChanged(object s, PropertyValueChangedEv
}
else if (Globals.list_selected == 3)
{
- object warp = getSelectedWarp();
+ int index = 0;
+ bool isPaintingWarp = false;
+ object warp = getSelectedWarp(out index, out isPaintingWarp);
string warpTypeName = warp.GetType().Name;
if (warpTypeName.Equals("Warp"))
{
@@ -1209,7 +1300,7 @@ private void treeView1_DrawNode(object sender, DrawTreeNodeEventArgs e)
e.DrawDefault = true;
}
}
-
+
private void radioButton2_CheckedChanged(object sender, EventArgs e)
{
if (radioButton2.Checked)
@@ -1231,6 +1322,66 @@ private void radioButton1_CheckedChanged(object sender, EventArgs e)
}
+ private void radioButton4_CheckedChanged(object sender, EventArgs e)
+ {
+ if (radioButton_bottom.Checked)
+ {
+ camera.setCameraMode_LookDirection(LookDirection.BOTTOM, ref camMtx);
+ camera.updateMatrix(ref camMtx);
+ glControl1.Invalidate();
+ }
+ }
+
+ private void radioButton5_CheckedChanged(object sender, EventArgs e)
+ {
+ if (radioButton_top.Checked)
+ {
+ camera.setCameraMode_LookDirection(LookDirection.TOP, ref camMtx);
+ camera.updateMatrix(ref camMtx);
+ glControl1.Invalidate();
+ }
+ }
+
+ private void radioButton_left_CheckedChanged(object sender, EventArgs e)
+ {
+ if (radioButton_left.Checked)
+ {
+ camera.setCameraMode_LookDirection(LookDirection.LEFT, ref camMtx);
+ camera.updateMatrix(ref camMtx);
+ glControl1.Invalidate();
+ }
+ }
+
+ private void radioButton_right_CheckedChanged(object sender, EventArgs e)
+ {
+ if (radioButton_right.Checked)
+ {
+ camera.setCameraMode_LookDirection(LookDirection.RIGHT, ref camMtx);
+ camera.updateMatrix(ref camMtx);
+ glControl1.Invalidate();
+ }
+ }
+
+ private void radioButton_front_CheckedChanged(object sender, EventArgs e)
+ {
+ if (radioButton_front.Checked)
+ {
+ camera.setCameraMode_LookDirection(LookDirection.FRONT, ref camMtx);
+ camera.updateMatrix(ref camMtx);
+ glControl1.Invalidate();
+ }
+ }
+
+ private void radioButton_back_CheckedChanged(object sender, EventArgs e)
+ {
+ if (radioButton_back.Checked)
+ {
+ camera.setCameraMode_LookDirection(LookDirection.BACK, ref camMtx);
+ camera.updateMatrix(ref camMtx);
+ glControl1.Invalidate();
+ }
+ }
+
private void starAct_CheckedChanged(object sender, EventArgs e)
{
RadioButton box = (RadioButton)sender;
@@ -1263,7 +1414,7 @@ private void moveCam_InOut_MouseMove(object sender, MouseEventArgs e)
glControl1.Invalidate();
}
}
-
+
bool moveCam_strafe_mouseDown = false;
private void moveCam_strafe_MouseDown(object sender, MouseEventArgs e)
{
@@ -1285,7 +1436,7 @@ private void moveCam_strafe_MouseMove(object sender, MouseEventArgs e)
glControl1.Invalidate();
}
}
-
+
private Object3D getSelectedObject()
{
if (Globals.list_selected == -1 || Globals.item_selected == -1)
@@ -1320,22 +1471,28 @@ private Object3D getSelectedObject()
}
}
- private object getSelectedWarp()
+ private object getSelectedWarp(out int warpIndex, out bool isPaintingWarp)
{
+ isPaintingWarp = false;
if (Globals.list_selected == -1 || Globals.item_selected == -1)
+ {
+ warpIndex = -1;
return null;
+ }
switch (Globals.list_selected)
{
case 3:
{
Area area = level.getCurrentArea();
int index = Globals.item_selected;
+ warpIndex = index;
if (index < area.Warps.Count)
{
propertyGrid1.SelectedObject = area.Warps[index];
}
else if (index < area.Warps.Count + area.PaintingWarps.Count)
{
+ isPaintingWarp = true;
propertyGrid1.SelectedObject = area.PaintingWarps[index - area.Warps.Count];
}
else
@@ -1345,7 +1502,37 @@ private object getSelectedWarp()
return propertyGrid1.SelectedObject;
}
default:
- return null;
+ {
+ warpIndex = -1;
+ return null;
+ }
+ }
+ }
+
+ void updateSelectedWarpsInROM()
+ {
+ if (!Globals.isMultiSelected)
+ {
+ int index = 0;
+ bool isPaintingWarp = false;
+ object warp = getSelectedWarp(out index, out isPaintingWarp);
+ if (warp is Warp)
+ ((Warp)warp).updateROMData();
+ else if (warp is WarpInstant)
+ ((WarpInstant)warp).updateROMData();
+ }
+ else
+ {
+ Area area = level.getCurrentArea();
+ foreach (int index in Globals.multi_selected_nodes[3])
+ {
+ if (index < area.Warps.Count)
+ area.Warps[index].updateROMData();
+ else if (index < area.Warps.Count + area.PaintingWarps.Count)
+ area.PaintingWarps[index - area.Warps.Count].updateROMData();
+ else
+ area.InstantWarps[index - area.Warps.Count - area.PaintingWarps.Count].updateROMData();
+ }
}
}
@@ -1949,6 +2136,7 @@ private void trackBar2_ValueChanged(object sender, EventArgs e)
Globals.objSpeedMultiplier = newValue / 100.0f;
}
+
private const int WM_USER = 0x0400;
private const int EM_SETEVENTMASK = (WM_USER + 69);
private const int WM_SETREDRAW = 0x0b;
diff --git a/src/Globals.cs b/src/Globals.cs
index ad7bdb9..c0890e5 100644
--- a/src/Globals.cs
+++ b/src/Globals.cs
@@ -43,6 +43,7 @@ class Globals
public static bool isMultiSelected = false;
public static bool isMultiSelectedFromMultipleLists = false;
public static bool isMultiSelectedFromSpecialObjects = false;
+ public static bool isMultiSelectedFromBothNormalWarpsAndInstantWarps = false;
public static List> multi_selected_nodes = new List>();
// Keeps track if the user needs to save their changes.
diff --git a/src/ROM.cs b/src/ROM.cs
index 7a012d5..8afab6a 100644
--- a/src/ROM.cs
+++ b/src/ROM.cs
@@ -239,7 +239,7 @@ public void WriteToFileEx()
}
stream.Close();
}
-
+
public void readFile(string filename)
{
filepath = filename;
diff --git a/src/Scripts/CollisionMap.cs b/src/Scripts/CollisionMap.cs
index d84e356..b6d0f48 100644
--- a/src/Scripts/CollisionMap.cs
+++ b/src/Scripts/CollisionMap.cs
@@ -135,15 +135,20 @@ public short dropToGround(Vector3 pos)
}
if (found.Count == 0)
return (short)pos.Y;
-
- float highestY = -0x2000;
+
+ int closest_index = 0;
+ float closest_abs = 9999999.0f;
// Console.WriteLine("Found " + found.Count + " triangles under position");
for (int i = 0; i < found.Count; i++)
{
- if (found[i] > highestY)
- highestY = found[i];
+ float abs = Math.Abs(pos.Y - found[i]);
+ if(abs < closest_abs)
+ {
+ closest_abs = abs;
+ closest_index = i;
+ }
}
- return (short)highestY;
+ return (short)found[closest_index];
}
public void buildCollisionMap()
diff --git a/src/Scripts/LevelScripts.cs b/src/Scripts/LevelScripts.cs
index e40c20f..92f1e9a 100644
--- a/src/Scripts/LevelScripts.cs
+++ b/src/Scripts/LevelScripts.cs
@@ -462,7 +462,6 @@ private static void CMD_22(ref Level lvl, ref string desc, byte[] cmd)
if (modelID == 0x7A)
Globals.DEBUG_PARSING_DL = true;
-
desc = "Define Model ID 0x" + modelID.ToString("X2") + "; Load Geometry layout from 0x" + seg.ToString("X2") + off.ToString("X6");
//Console.WriteLine("Size of seg 0x"+seg.ToString("X2")+" = " + rom.getSegment(seg).Length);
diff --git a/src/Viewer/Camera.cs b/src/Viewer/Camera.cs
index 897e3c5..462eb36 100644
--- a/src/Viewer/Camera.cs
+++ b/src/Viewer/Camera.cs
@@ -10,7 +10,15 @@ namespace Quad64
enum CameraMode
{
FLY = 0,
- ORBIT = 1
+ ORBIT = 1,
+ LOOK_DIRECTION = 2
+ }
+
+ enum LookDirection
+ {
+ TOP, BOTTOM,
+ LEFT, RIGHT,
+ FRONT, BACK
}
class Camera
@@ -44,6 +52,17 @@ class Camera
private float orbitDistance = 500.0f;
private float orbitTheta = 0.0f, orbitPhi = 0.0f;
+ private LookDirection currentLookDirection;
+ private Vector3[] lookPositions = new Vector3[]
+ {
+ new Vector3(0, 12500, 0), // top
+ new Vector3(0, -12500, 0), // bottom
+ new Vector3(-12500, 0, 0), // left
+ new Vector3(12500, 0, 0), // right
+ new Vector3(0, 0, 12500), // front
+ new Vector3(0, 0, -12500) // back
+ };
+
public Camera()
{
setRotationFromLookAt();
@@ -159,10 +178,57 @@ public void setCameraMode(CameraMode mode, ref Matrix4 cameraMatrix)
}
}
+ public void setCameraMode_LookDirection(LookDirection dir, ref Matrix4 cameraMatrix)
+ {
+ camMode = CameraMode.LOOK_DIRECTION;
+ currentLookDirection = dir;
+ switch (currentLookDirection)
+ {
+ case LookDirection.TOP:
+ pos = lookPositions[(int)LookDirection.TOP];
+ lookat = new Vector3(pos.X, -25000, pos.Z - 1);
+ cameraMatrix = Matrix4.LookAt(pos.X, pos.Y, pos.Z, lookat.X, lookat.Y, lookat.Z, 0, 1, 0);
+ setRotationFromLookAt();
+ break;
+ case LookDirection.BOTTOM:
+ pos = lookPositions[(int)LookDirection.BOTTOM];
+ lookat = new Vector3(pos.X, 25000, pos.Z + 1);
+ cameraMatrix = Matrix4.LookAt(pos.X, pos.Y, pos.Z, lookat.X, lookat.Y, lookat.Z, 0, 1, 0);
+ setRotationFromLookAt();
+ break;
+ case LookDirection.LEFT:
+ pos = lookPositions[(int)LookDirection.LEFT];
+ lookat = new Vector3(25000, pos.Y, pos.Z);
+ cameraMatrix = Matrix4.LookAt(pos.X, pos.Y, pos.Z, lookat.X, lookat.Y, lookat.Z, 0, 1, 0);
+ setRotationFromLookAt();
+ break;
+ case LookDirection.RIGHT:
+ pos = lookPositions[(int)LookDirection.RIGHT];
+ lookat = new Vector3(-25000, pos.Y, pos.Z);
+ cameraMatrix = Matrix4.LookAt(pos.X, pos.Y, pos.Z, lookat.X, lookat.Y, lookat.Z, 0, 1, 0);
+ setRotationFromLookAt();
+ break;
+ case LookDirection.FRONT:
+ pos = lookPositions[(int)LookDirection.FRONT];
+ lookat = new Vector3(pos.X, pos.Y, -25000);
+ cameraMatrix = Matrix4.LookAt(pos.X, pos.Y, pos.Z, lookat.X, lookat.Y, lookat.Z, 0, 1, 0);
+ setRotationFromLookAt();
+ break;
+ case LookDirection.BACK:
+ pos = lookPositions[(int)LookDirection.BACK];
+ lookat = new Vector3(pos.X, pos.Y, 25000);
+ cameraMatrix = Matrix4.LookAt(pos.X, pos.Y, pos.Z, lookat.X, lookat.Y, lookat.Z, 0, 1, 0);
+ setRotationFromLookAt();
+ break;
+ }
+ }
+
public void updateCameraMatrixWithMouse(int mouseX, int mouseY, ref Matrix4 cameraMatrix)
{
if (camMode == CameraMode.ORBIT && Globals.item_selected > -1)
updateCameraMatrixWithMouse_ORBIT(mouseX, mouseY, ref cameraMatrix);
+ else if (camMode == CameraMode.LOOK_DIRECTION)
+ updateCameraMatrixWithMouse_LOOK(pos, mouseX, mouseY, ref cameraMatrix);
else
updateCameraMatrixWithMouse_FLY(mouseX, mouseY, ref cameraMatrix);
}
@@ -171,6 +237,8 @@ public void updateCameraOffsetWithMouse(Vector3 orgPos, int mouseX, int mouseY,
{
if (camMode == CameraMode.ORBIT && Globals.item_selected > -1)
updateCameraOffsetWithMouse_ORBIT(mouseX, mouseY, ref cameraMatrix);
+ else if (camMode == CameraMode.LOOK_DIRECTION)
+ updateCameraMatrixWithMouse_LOOK(pos, mouseX, mouseY, ref cameraMatrix);
else
updateCameraOffsetWithMouse_FLY(orgPos, mouseX, mouseY, w, h, ref cameraMatrix);
}
@@ -179,6 +247,8 @@ public void updateCameraMatrixWithScrollWheel(int amt, ref Matrix4 cameraMatrix)
{
if (camMode == CameraMode.ORBIT && Globals.item_selected > -1)
updateCameraMatrixWithScrollWheel_ORBIT(amt, ref cameraMatrix);
+ else if (camMode == CameraMode.LOOK_DIRECTION)
+ updateCameraMatrixWithScrollWheel_LOOK(amt, ref cameraMatrix);
else
updateCameraMatrixWithScrollWheel_FLY(amt, ref cameraMatrix);
}
@@ -195,6 +265,97 @@ public void updateMatrix(ref Matrix4 cameraMatrix)
cameraMatrix = Matrix4.LookAt(pos.X, pos.Y, pos.Z, lookat.X, lookat.Y, lookat.Z, 0, 1, 0);
}
+ private void updateCameraMatrixWithScrollWheel_LOOK(int amt, ref Matrix4 cameraMatrix)
+ {
+ offsetCam(amt, amt, amt);
+ orientateCam(CamAngleX, CamAngleY);
+ switch (currentLookDirection)
+ {
+ case LookDirection.TOP:
+ cameraMatrix = Matrix4.LookAt(pos.X, pos.Y, pos.Z, lookat.X, lookat.Y, lookat.Z - 1, 0, 1, 0);
+ break;
+ case LookDirection.BOTTOM:
+ cameraMatrix = Matrix4.LookAt(pos.X, pos.Y, pos.Z, lookat.X, lookat.Y, lookat.Z + 1, 0, 1, 0);
+ break;
+ default:
+ cameraMatrix = Matrix4.LookAt(pos.X, pos.Y, pos.Z, lookat.X, lookat.Y, lookat.Z, 0, 1, 0);
+ break;
+ }
+ }
+
+ private void updateCameraMatrixWithMouse_LOOK(Vector3 orgPos, int mouseX, int mouseY, ref Matrix4 cameraMatrix)
+ {
+ if (resetMouse)
+ {
+ lastMouseX = mouseX;
+ lastMouseY = mouseY;
+ resetMouse = false;
+ }
+ int MousePosX = mouseX - lastMouseX;
+ int MousePosY = mouseY - lastMouseY;
+
+ double pitch = CamAngleY - (Math.PI / 2);
+ double yaw = CamAngleX - (Math.PI / 2);
+ float CamLX = (float)Math.Sin(yaw);
+ float CamLY = (float)Math.Cos(pitch);
+ float CamLZ = (float)-Math.Cos(yaw);
+
+ float m = 8f;
+
+ switch (currentLookDirection)
+ {
+ case LookDirection.TOP:
+ pos.X = orgPos.X - ((MousePosX * Globals.camSpeedMultiplier) * (CamLX) * m) -
+ ((MousePosY * Globals.camSpeedMultiplier) * (CamLZ) * m);
+ pos.Z = orgPos.Z - ((MousePosX * Globals.camSpeedMultiplier) * (CamLZ) * m) -
+ ((MousePosY * Globals.camSpeedMultiplier) * (CamLX) * m);
+ cameraMatrix = Matrix4.LookAt(pos.X, pos.Y, pos.Z, pos.X, pos.Y - 1000, pos.Z - 1, 0, 1, 0);
+ lookPositions[(int)currentLookDirection] = pos;
+ break;
+ case LookDirection.BOTTOM:
+ pos.X = orgPos.X - ((MousePosX * Globals.camSpeedMultiplier) * (CamLX) * m) +
+ ((MousePosY * Globals.camSpeedMultiplier) * (CamLZ) * m);
+ pos.Z = orgPos.Z - ((MousePosX * Globals.camSpeedMultiplier) * (CamLZ) * m) +
+ ((MousePosY * Globals.camSpeedMultiplier) * (CamLX) * m);
+ cameraMatrix = Matrix4.LookAt(pos.X, pos.Y, pos.Z, pos.X, pos.Y + 1000, pos.Z + 1, 0, 1, 0);
+ lookPositions[(int)currentLookDirection] = pos;
+ break;
+ case LookDirection.LEFT:
+ pos.X = orgPos.X - ((MousePosX * Globals.camSpeedMultiplier) * (CamLX) * m);
+ pos.Y = orgPos.Y - ((MousePosY * Globals.camSpeedMultiplier) * (-1f) * m);
+ pos.Z = orgPos.Z - ((MousePosX * Globals.camSpeedMultiplier) * (CamLZ) * m);
+ cameraMatrix = Matrix4.LookAt(pos.X, pos.Y, pos.Z, pos.X + 12500, pos.Y, pos.Z, 0, 1, 0);
+ lookPositions[(int)currentLookDirection] = pos;
+ break;
+ case LookDirection.RIGHT:
+ pos.X = orgPos.X - ((MousePosX * Globals.camSpeedMultiplier) * (CamLX) * m);
+ pos.Y = orgPos.Y - ((MousePosY * Globals.camSpeedMultiplier) * (-1f) * m);
+ pos.Z = orgPos.Z - ((MousePosX * Globals.camSpeedMultiplier) * (CamLZ) * m);
+ cameraMatrix = Matrix4.LookAt(pos.X, pos.Y, pos.Z, pos.X - 12500, pos.Y, pos.Z, 0, 1, 0);
+ lookPositions[(int)currentLookDirection] = pos;
+ break;
+ case LookDirection.FRONT:
+ pos.X = orgPos.X - ((MousePosX * Globals.camSpeedMultiplier) * (CamLX) * m);
+ pos.Y = orgPos.Y - ((MousePosY * Globals.camSpeedMultiplier) * (-1f) * m);
+ pos.Z = orgPos.Z - ((MousePosX * Globals.camSpeedMultiplier) * (CamLZ) * m);
+ cameraMatrix = Matrix4.LookAt(pos.X, pos.Y, pos.Z, pos.X, pos.Y, pos.Z - 12500, 0, 1, 0);
+ lookPositions[(int)currentLookDirection] = pos;
+ break;
+ case LookDirection.BACK:
+ pos.X = orgPos.X - ((MousePosX * Globals.camSpeedMultiplier) * (CamLX) * m);
+ pos.Y = orgPos.Y - ((MousePosY * Globals.camSpeedMultiplier) * (-1f) * m);
+ pos.Z = orgPos.Z - ((MousePosX * Globals.camSpeedMultiplier) * (CamLZ) * m);
+ cameraMatrix = Matrix4.LookAt(pos.X, pos.Y, pos.Z, pos.X, pos.Y, pos.Z + 12500, 0, 1, 0);
+ lookPositions[(int)currentLookDirection] = pos;
+ break;
+ }
+
+ lastMouseX = mouseX;
+ lastMouseY = mouseY;
+ //Console.WriteLine("CamAngleX = " + CamAngleX + ", CamAngleY = " + CamAngleY);
+ //setRotationFromLookAt();
+ }
+
private void updateCameraMatrixWithMouse_FLY(int mouseX, int mouseY, ref Matrix4 cameraMatrix)
{
if (resetMouse)