diff --git a/Quad64.csproj b/Quad64.csproj
index 4b2da88..a570548 100644
--- a/Quad64.csproj
+++ b/Quad64.csproj
@@ -302,6 +302,7 @@
Always
+
@@ -351,11 +352,11 @@
-
-
\ No newline at end of file
+
diff --git a/src/Forms/MainForm.cs b/src/Forms/MainForm.cs
index efd101a..c42a12e 100644
--- a/src/Forms/MainForm.cs
+++ b/src/Forms/MainForm.cs
@@ -13,6 +13,7 @@
using System.Runtime.InteropServices;
using Quad64.src.Forms.ToolStripRenderer;
using System.IO;
+using Newtonsoft.Json;
namespace Quad64
{
@@ -97,9 +98,26 @@ public MainForm()
myTimer.Enabled = false;
cameraMode.SelectedIndex = 0;
menuStrip1.Renderer = new ToolStripProfessionalRenderer(new CustomToolStripColorTable());
+
+ this.KeyDown += Handle_KeyDown;
}
// New functions for MainForm.cs
+ void Handle_KeyDown( object sender, KeyEventArgs e )
+ {
+ switch (e.KeyCode)
+ {
+ case Keys.F1: SaveSelectedObjectsToFile(1); break;
+ case Keys.F2: SaveSelectedObjectsToFile(2); break;
+ case Keys.F3: SaveSelectedObjectsToFile(3); break;
+ case Keys.F4: SaveSelectedObjectsToFile(4); break;
+ case Keys.F5: LoadObjectsFromFile(1); break;
+ case Keys.F6: LoadObjectsFromFile(2); break;
+ case Keys.F7: LoadObjectsFromFile(3); break;
+ case Keys.F8: LoadObjectsFromFile(4); break;
+ }
+ }
+
private void SetColorsForMenuStripItem(ref ToolStripItemCollection items)
{
for (int i = 0; i < items.Count; i++)
@@ -2290,7 +2308,89 @@ public static void forceGC()
{
GC.Collect();
GC.WaitForPendingFinalizers();
- SetProcessWorkingSetSize(System.Diagnostics.Process.GetCurrentProcess().Handle, -1, -1);
+ //SetProcessWorkingSetSize(System.Diagnostics.Process.GetCurrentProcess().Handle, -1, -1);
+ }
+
+ private void SaveSelectedObjectsToFile( int slot )
+ {
+ List selectedObjects = new List();
+
+ if( Globals.isMultiSelected )
+ {
+ if(
+ Globals.isMultiSelectedFromMultipleLists ||
+ Globals.multi_selected_nodes[0].Count < 1
+ ) return;
+
+ foreach( int index in Globals.multi_selected_nodes[0] )
+ {
+ selectedObjects.Add(level.getCurrentArea().Objects[index].Data);
+ }
+ } else
+ {
+ if ( Globals.list_selected != 0 || Globals.item_selected < 0 ) return;
+
+ selectedObjects.Add(level.getCurrentArea().Objects[Globals.item_selected].Data);
+ }
+
+ using( StreamWriter tempFile = new StreamWriter( "./data/profiles/default/saved-objects-" + slot.ToString() + ".json" ) )
+ {
+ tempFile.WriteLine(JsonConvert.SerializeObject(selectedObjects));
+ }
}
+
+ private void LoadObjectsFromFile( int slot )
+ {
+ ObjectData[] objectsToLoad;
+ try {
+ using( StreamReader tempFile = new StreamReader( "./data/profiles/default/saved-objects-" + slot.ToString() + ".json" ) )
+ {
+ string json = tempFile.ReadLine();
+ objectsToLoad = JsonConvert.DeserializeObject( json );
+ }
+ } catch( Exception ex )
+ {
+ Console.Error.WriteLine( ex );
+ return;
+ }
+
+ List objects = level.getCurrentArea().Objects;
+ if( Globals.isMultiSelected )
+ {
+ if ( Globals.isMultiSelectedFromMultipleLists ||
+ Globals.multi_selected_nodes[0].Count != objectsToLoad.Length
+ ) return;
+
+ for( int i = 0; i < objectsToLoad.Length; i++)
+ {
+ Object3D objectToUpdate = objects[Globals.multi_selected_nodes[0][i]];
+ objectToUpdate.ReplaceData(objectsToLoad[i]);
+ objectToUpdate.updateROMData();
+ }
+ } else
+ {
+ if (
+ Globals.list_selected != 0 ||
+ Globals.item_selected < 0 ||
+ objectsToLoad.Length < 1
+ ) return;
+
+ int j = 0;
+ for( int i = Globals.item_selected; i < level.getCurrentArea().Objects.Count && j < objectsToLoad.Length; i++ )
+ {
+ objects[i].ReplaceData(objectsToLoad[j]);
+ objects[i].updateROMData();
+ j++;
+ }
+
+ }
+ refreshObjectsInList();
+
+ glControl1.Invalidate();
+ propertyGrid1.Refresh();
+ glControl1.Update();
+ Globals.needToSave = true;
+ }
+
}
}
diff --git a/src/JSON/ObjectData.cs b/src/JSON/ObjectData.cs
new file mode 100644
index 0000000..ce6cb52
--- /dev/null
+++ b/src/JSON/ObjectData.cs
@@ -0,0 +1,26 @@
+using Newtonsoft.Json;
+
+namespace Quad64.src.JSON
+{
+ [JsonObject]
+ internal sealed class ObjectData
+ {
+
+ public byte ModelId { get; set; }
+ public uint Behaviour { get; set; }
+ public byte[] BehaviourArgs { get; set; } = new byte[4];
+
+ public bool AllActs { get; set; }
+ public bool[] Acts { get; set; } = new bool[6];
+
+ public short X { get; set; }
+ public short Y { get; set; }
+ public short Z { get; set; }
+
+ public short RX { get; set; }
+ public short RY { get; set; }
+ public short RZ { get; set; }
+
+ }
+
+}
diff --git a/src/LevelInfo/Object3D.cs b/src/LevelInfo/Object3D.cs
index dfd2afa..296d9fb 100644
--- a/src/LevelInfo/Object3D.cs
+++ b/src/LevelInfo/Object3D.cs
@@ -35,13 +35,38 @@ public enum FLAGS {
public enum FROM_LS_CMD {
CMD_24, CMD_39, CMD_2E_8, CMD_2E_10, CMD_2E_12
}
-
+
private const ushort NUM_OF_CATERGORIES = 7;
bool isBehaviorReadOnly = false;
bool isModelIDReadOnly = false;
bool isTempHidden = false;
+ public Object3D(){
+ m_data = new ObjectData();
+ }
+
+ public Object3D(
+ string address,
+ ObjectData objectData
+ )
+ {
+ m_data = objectData;
+ Address = address;
+ UpdateProperties();
+ }
+
+ public void ReplaceData( ObjectData newData )
+ {
+ m_data = newData;
+ UpdateProperties();
+ }
+
+ private ObjectData m_data = new ObjectData();
+
+ [Browsable(false)]
+ public ObjectData Data { get => m_data; }
+
[Browsable(false)]
public bool canEditModelID { get { return !isModelIDReadOnly; } }
[Browsable(false)]
@@ -63,14 +88,13 @@ public enum FROM_LS_CMD {
[DisplayName("Address")]
[ReadOnly(true)]
public string Address { get; set; }
-
- private byte modelID = 0;
+
[CustomSortedCategory("Model", 2, NUM_OF_CATERGORIES)]
[Browsable(true)]
[Description("Model identifer used by the object")]
[DisplayName("Model ID")]
[TypeConverter(typeof(HexNumberTypeConverter))]
- public byte ModelID { get { return modelID; } set { modelID = value; } }
+ public byte ModelID { get { return m_data.ModelId; } set { m_data.ModelId = value; } }
[CustomSortedCategory("Model", 2, NUM_OF_CATERGORIES)]
[Browsable(false)]
@@ -78,59 +102,59 @@ public enum FROM_LS_CMD {
[DisplayName("Model ID")]
[TypeConverter(typeof(HexNumberTypeConverter))]
[ReadOnly(true)]
- public byte ModelID_ReadOnly { get { return modelID; } }
+ public byte ModelID_ReadOnly { get { return m_data.ModelId; } }
- private short _xPos, _yPos, _zPos;
[CustomSortedCategory("Position", 3, NUM_OF_CATERGORIES)]
[Browsable(true)]
[DisplayName("X")]
[TypeConverter(typeof(HexNumberTypeConverter))]
- public short xPos { get { return _xPos; } set { _xPos = value; } }
+ public short xPos { get { return m_data.X; } set { m_data.X = value; } }
[CustomSortedCategory("Position", 3, NUM_OF_CATERGORIES)]
[Browsable(true)]
[DisplayName("Y")]
[TypeConverter(typeof(HexNumberTypeConverter))]
- public short yPos { get { return _yPos; } set { _yPos = value; } }
+ public short yPos { get { return m_data.Y; } set { m_data.Y = value; } }
[CustomSortedCategory("Position", 3, NUM_OF_CATERGORIES)]
[Browsable(true)]
[DisplayName("Z")]
[TypeConverter(typeof(HexNumberTypeConverter))]
- public short zPos { get { return _zPos; } set { _zPos = value; } }
-
- private short _xRot, _yRot, _zRot;
+ public short zPos { get { return m_data.Z; } set { m_data.Z = value; } }
+
[CustomSortedCategory("Rotation", 4, NUM_OF_CATERGORIES)]
[Browsable(true)]
[DisplayName("RX")]
[TypeConverter(typeof(HexNumberTypeConverter))]
- public short xRot { get { return _xRot; } set { _xRot = value; } }
+ public short xRot { get { return m_data.RX; } set { m_data.RX = value; } }
[CustomSortedCategory("Rotation", 4, NUM_OF_CATERGORIES)]
[Browsable(true)]
[DisplayName("RY")]
[TypeConverter(typeof(HexNumberTypeConverter))]
- public short yRot { get { return _yRot; } set { _yRot = value; } }
+ public short yRot { get { return m_data.RY; } set { m_data.RY = value; } }
[CustomSortedCategory("Rotation", 4, NUM_OF_CATERGORIES)]
[Browsable(true)]
[DisplayName("RZ")]
[TypeConverter(typeof(HexNumberTypeConverter))]
- public short zRot { get { return _zRot; } set { _zRot = value; } }
+ public short zRot { get { return m_data.RZ; } set { m_data.RZ = value; } }
[CustomSortedCategory("Behavior", 5, NUM_OF_CATERGORIES)]
[Browsable(true)]
[DisplayName("Behavior")]
- //[ReadOnly(true)]
- public string Behavior { get; set; }
+ public string Behavior {
+ get => "0x" + m_data.Behaviour.ToString("X8");
+ set { m_data.Behaviour = uint.Parse(value.Substring(2), NumberStyles.HexNumber); }
+ }
[CustomSortedCategory("Behavior", 5, NUM_OF_CATERGORIES)]
[Browsable(false)]
[DisplayName("Behavior")]
[ReadOnly(true)]
- public string Behavior_ReadOnly { get; set; }
-
+ public string Behavior_ReadOnly => this.Behavior;
+
[CustomSortedCategory("Behavior", 5, NUM_OF_CATERGORIES)]
[Browsable(true)]
[DisplayName("Beh. Name")]
[ReadOnly(true)]
- public string Behavior_Name { get; set; }
+ public string Behavior_Name => Globals.getBehaviorNameEntryFromSegAddress(m_data.Behaviour).Name;
// default names
private const string BP1DNAME = "B.Param 1";
@@ -143,57 +167,106 @@ public enum FROM_LS_CMD {
[DisplayName(BP1DNAME)]
[TypeConverter(typeof(HexNumberTypeConverter))]
[Description("")]
- public byte BehaviorParameter1 { get; set; }
+ public byte BehaviorParameter1
+ {
+ get { return m_data.BehaviourArgs[0]; }
+ set { m_data.BehaviourArgs[0] = value; }
+ }
[CustomSortedCategory("Behavior", 5, NUM_OF_CATERGORIES)]
[Browsable(true)]
[DisplayName(BP2DNAME)]
[TypeConverter(typeof(HexNumberTypeConverter))]
[Description("")]
- public byte BehaviorParameter2 { get; set; }
+ public byte BehaviorParameter2
+ {
+ get { return m_data.BehaviourArgs[1]; }
+ set { m_data.BehaviourArgs[1] = value; }
+ }
[CustomSortedCategory("Behavior", 5, NUM_OF_CATERGORIES)]
[Browsable(true)]
[DisplayName(BP3DNAME)]
[TypeConverter(typeof(HexNumberTypeConverter))]
[Description("")]
- public byte BehaviorParameter3 { get; set; }
+ public byte BehaviorParameter3
+ {
+ get { return m_data.BehaviourArgs[2]; }
+ set { m_data.BehaviourArgs[2] = value; }
+ }
[CustomSortedCategory("Behavior", 5, NUM_OF_CATERGORIES)]
[Browsable(true)]
[DisplayName(BP4DNAME)]
[TypeConverter(typeof(HexNumberTypeConverter))]
[Description("")]
- public byte BehaviorParameter4 { get; set; }
+ public byte BehaviorParameter4
+ {
+ get { return m_data.BehaviourArgs[3]; }
+ set { m_data.BehaviourArgs[3] = value; }
+ }
[CustomSortedCategory("Acts", 6, NUM_OF_CATERGORIES)]
[Browsable(true)]
[DisplayName("All Acts")]
- public bool AllActs { get; set; }
+ public bool AllActs
+ {
+ get { return m_data.AllActs; }
+ set { m_data.AllActs = value; }
+ }
[CustomSortedCategory("Acts", 6, NUM_OF_CATERGORIES)]
[Browsable(true)]
[DisplayName("Act 1")]
- public bool Act1 { get; set; }
+ public bool Act1
+ {
+ get { return m_data.Acts[0]; }
+ set { m_data.Acts[0] = value; }
+ }
+
[CustomSortedCategory("Acts", 6, NUM_OF_CATERGORIES)]
[Browsable(true)]
[DisplayName("Act 2")]
- public bool Act2 { get; set; }
+ public bool Act2
+ {
+ get { return m_data.Acts[1]; }
+ set { m_data.Acts[1] = value; }
+ }
+
[CustomSortedCategory("Acts", 6, NUM_OF_CATERGORIES)]
[Browsable(true)]
[DisplayName("Act 3")]
- public bool Act3 { get; set; }
+ public bool Act3
+ {
+ get { return m_data.Acts[2]; }
+ set { m_data.Acts[2] = value; }
+ }
+
[CustomSortedCategory("Acts", 6, NUM_OF_CATERGORIES)]
[Browsable(true)]
[DisplayName("Act 4")]
- public bool Act4 { get; set; }
+ public bool Act4
+ {
+ get { return m_data.Acts[3]; }
+ set { m_data.Acts[3] = value; }
+ }
+
[CustomSortedCategory("Acts", 6, NUM_OF_CATERGORIES)]
[Browsable(true)]
[DisplayName("Act 5")]
- public bool Act5 { get; set; }
+ public bool Act5
+ {
+ get { return m_data.Acts[4]; }
+ set { m_data.Acts[4] = value; }
+ }
+
[CustomSortedCategory("Acts", 6, NUM_OF_CATERGORIES)]
[Browsable(true)]
[DisplayName("Act 6")]
- public bool Act6 { get; set; }
+ public bool Act6
+ {
+ get { return m_data.Acts[5]; }
+ set { m_data.Acts[5] = value; }
+ }
private ulong Flags = 0;
@@ -239,27 +312,10 @@ public byte getActMask()
public void setBehaviorFromAddress(uint address)
{
- Behavior = "0x"+address.ToString("X8");
- Behavior_ReadOnly = Behavior;
- Behavior_Name = Globals.getBehaviorNameEntryFromSegAddress(address).Name;
+ m_data.Behaviour = address;
}
- public uint getBehaviorAddress()
- {
- uint value = 0;
- bool succeded = false;
- if(Behavior.ToUpper().StartsWith("0X"))
- succeded = uint.TryParse(Behavior.Substring(2), NumberStyles.HexNumber, new CultureInfo("en-US"), out value);
- else if (Behavior.ToUpper().StartsWith("$"))
- succeded = uint.TryParse(Behavior.Substring(1), NumberStyles.HexNumber, new CultureInfo("en-US"), out value);
- else
- succeded = uint.TryParse(Behavior, out value);
-
- if (succeded)
- return value;
- else
- return 0;
- }
+ public uint getBehaviorAddress() => m_data.Behaviour;
public void updateROMData()
{
@@ -619,7 +675,7 @@ public string getObjectComboName()
}
objectComboEntry = null;
- Title = "Undefined Combo (0x" + modelID.ToString("X2") + ", 0x" + behaviorAddr.ToString("X8") + ")";
+ Title = "Undefined Combo (0x" + m_data.ModelId.ToString("X2") + ", 0x" + behaviorAddr.ToString("X8") + ")";
return Title;
}