diff --git a/Assets/Samples/XR Interaction Toolkit/2.4.3/Starter Assets/XRI Default Input Actions.inputactions b/Assets/Samples/XR Interaction Toolkit/2.4.3/Starter Assets/XRI Default Input Actions.inputactions index 7fecfee1f5c34b9b79f1d00015ec35091fa8006a..3251980096ec64765380bca12d0f1669d598c037 100644 --- a/Assets/Samples/XR Interaction Toolkit/2.4.3/Starter Assets/XRI Default Input Actions.inputactions +++ b/Assets/Samples/XR Interaction Toolkit/2.4.3/Starter Assets/XRI Default Input Actions.inputactions @@ -701,6 +701,24 @@ "processors": "", "interactions": "", "initialStateCheck": true + }, + { + "name": "save", + "type": "Button", + "id": "0031af44-5ced-4637-b320-dd79ef962b71", + "expectedControlType": "Button", + "processors": "", + "interactions": "", + "initialStateCheck": false + }, + { + "name": "load", + "type": "Button", + "id": "fe45058d-fbb0-4593-9fe2-d0a266c224a7", + "expectedControlType": "Button", + "processors": "", + "interactions": "", + "initialStateCheck": false } ], "bindings": [ @@ -846,6 +864,28 @@ "action": "UI Scroll", "isComposite": false, "isPartOfComposite": false + }, + { + "name": "", + "id": "20571414-9fa7-433d-89db-6df6c520f979", + "path": "<Keyboard>/#(S)", + "interactions": "", + "processors": "", + "groups": "", + "action": "save", + "isComposite": false, + "isPartOfComposite": false + }, + { + "name": "", + "id": "02fe76c0-36c4-4441-8b32-249460b6eb2f", + "path": "<Keyboard>/#(L)", + "interactions": "", + "processors": "", + "groups": "", + "action": "load", + "isComposite": false, + "isPartOfComposite": false } ] }, diff --git a/Assets/Scenes/SampleScene.unity b/Assets/Scenes/SampleScene.unity index 8a303a4b9bf9fb24dcd0520b2d5393e613377d5b..39efbdad3bb923eece8987b8616ca0c5ac45c23f 100644 --- a/Assets/Scenes/SampleScene.unity +++ b/Assets/Scenes/SampleScene.unity @@ -4472,8 +4472,9 @@ GameObject: - component: {fileID: 426651920} - component: {fileID: 426651919} - component: {fileID: 426651921} + - component: {fileID: 426651922} m_Layer: 0 - m_Name: Spawn Block Handler + m_Name: Program Controller m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 @@ -4522,6 +4523,18 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: editStateAction: {fileID: 2052445844685558139, guid: c348712bda248c246b8c49b3db54643f, type: 3} +--- !u!114 &426651922 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 426651918} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 3972891316024844e9f4db4ba6131e3b, type: 3} + m_Name: + m_EditorClassIdentifier: --- !u!1001 &427008753 PrefabInstance: m_ObjectHideFlags: 0 @@ -18754,7 +18767,7 @@ PrefabInstance: objectReference: {fileID: 0} - target: {fileID: 1984668758913251958, guid: 65eb6b98091a5734ba9d9ca871cef69a, type: 3} propertyPath: m_AnchoredPosition.x - value: 0 + value: 44.7 objectReference: {fileID: 0} - target: {fileID: 1984668758913251958, guid: 65eb6b98091a5734ba9d9ca871cef69a, type: 3} propertyPath: m_AnchoredPosition.y @@ -18782,7 +18795,7 @@ PrefabInstance: objectReference: {fileID: 0} - target: {fileID: 1984668759388320319, guid: 65eb6b98091a5734ba9d9ca871cef69a, type: 3} propertyPath: m_AnchoredPosition.x - value: 0 + value: 40 objectReference: {fileID: 0} - target: {fileID: 1984668759388320319, guid: 65eb6b98091a5734ba9d9ca871cef69a, type: 3} propertyPath: m_AnchoredPosition.y @@ -18818,7 +18831,7 @@ PrefabInstance: objectReference: {fileID: 0} - target: {fileID: 1984668759906836222, guid: 65eb6b98091a5734ba9d9ca871cef69a, type: 3} propertyPath: m_AnchoredPosition.x - value: 0 + value: 40 objectReference: {fileID: 0} - target: {fileID: 1984668759906836222, guid: 65eb6b98091a5734ba9d9ca871cef69a, type: 3} propertyPath: m_AnchoredPosition.y @@ -18838,7 +18851,7 @@ PrefabInstance: objectReference: {fileID: 0} - target: {fileID: 1984668759991436502, guid: 65eb6b98091a5734ba9d9ca871cef69a, type: 3} propertyPath: m_AnchoredPosition.x - value: 0 + value: 40 objectReference: {fileID: 0} - target: {fileID: 1984668759991436502, guid: 65eb6b98091a5734ba9d9ca871cef69a, type: 3} propertyPath: m_AnchoredPosition.y @@ -18874,7 +18887,7 @@ PrefabInstance: objectReference: {fileID: 0} - target: {fileID: 1984668760453204319, guid: 65eb6b98091a5734ba9d9ca871cef69a, type: 3} propertyPath: m_AnchoredPosition.x - value: 0 + value: 44.7 objectReference: {fileID: 0} - target: {fileID: 1984668760453204319, guid: 65eb6b98091a5734ba9d9ca871cef69a, type: 3} propertyPath: m_AnchoredPosition.y @@ -18894,7 +18907,7 @@ PrefabInstance: objectReference: {fileID: 0} - target: {fileID: 1984668760497519799, guid: 65eb6b98091a5734ba9d9ca871cef69a, type: 3} propertyPath: m_AnchoredPosition.x - value: 0 + value: 40 objectReference: {fileID: 0} - target: {fileID: 1984668760497519799, guid: 65eb6b98091a5734ba9d9ca871cef69a, type: 3} propertyPath: m_AnchoredPosition.y @@ -18922,7 +18935,7 @@ PrefabInstance: objectReference: {fileID: 0} - target: {fileID: 1984668760711245992, guid: 65eb6b98091a5734ba9d9ca871cef69a, type: 3} propertyPath: m_AnchoredPosition.x - value: 0 + value: 40 objectReference: {fileID: 0} - target: {fileID: 1984668760711245992, guid: 65eb6b98091a5734ba9d9ca871cef69a, type: 3} propertyPath: m_AnchoredPosition.y diff --git a/Assets/Scrips/Controllers.meta b/Assets/Scrips/Controllers.meta new file mode 100644 index 0000000000000000000000000000000000000000..0b7a1c0db089d98bb4decbe05718e0a298e7b1ee --- /dev/null +++ b/Assets/Scrips/Controllers.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f9874c2068d26194b9102aa670dcb6e6 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scrips/Controllers/ProgramController.cs b/Assets/Scrips/Controllers/ProgramController.cs new file mode 100644 index 0000000000000000000000000000000000000000..845ec377061cbcee93314d8edd19ec16ed47d41d --- /dev/null +++ b/Assets/Scrips/Controllers/ProgramController.cs @@ -0,0 +1,128 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Runtime.Serialization; +using System.Runtime.Serialization.Formatters.Binary; +using UnityEngine; +using UnityEngine.InputSystem; + +public class ProgramController : MonoBehaviour +{ + public SpawnBlockEvent spawnBlockEvent; + public Transform UserTransform; + + public InputActionReference saveEventAction; + public InputActionReference loadEventAction; + + + private List<GameObject> _spawnedBlocks = new(); + + private string _savePath; + + private void Awake() + { + this._savePath = Application.persistentDataPath + "/program.save"; + saveEventAction.action.Enable(); + saveEventAction.action.performed += SaveProgram; + + loadEventAction.action.Enable(); + loadEventAction.action.performed += LoadProgram; + + // InputSystem.onDeviceChange += OnDeviceChange; + } + + private void OnDestroy() + { + saveEventAction.action.Disable(); + saveEventAction.action.performed -= SaveProgram; + + loadEventAction.action.Disable(); + loadEventAction.action.performed -= LoadProgram; + + // InputSystem.onDeviceChange -= OnDeviceChange; + } + + private void OnDeviceChange(InputDevice device, InputDeviceChange change) + { + switch (change) + { + case InputDeviceChange.Disconnected: + saveEventAction.action.Disable(); + saveEventAction.action.performed -= SaveProgram; + break; + case InputDeviceChange.Reconnected: + saveEventAction.action.Enable(); + saveEventAction.action.performed += SaveProgram; + break; + } + } + + // Start is called before the first frame update + void Start() + { + + } + + // Update is called once per frame + void Update() + { + + } + + public void RegisterBlock(GameObject block) + { + _spawnedBlocks.Add(block); + } + + private Save CreateSave() + { + Save save = new(); + save.UserTransform = this.UserTransform.position; + + foreach (GameObject block in _spawnedBlocks) + { + save.Blocks.Add(block.transform.position); + } + + return save; + } + + public void SaveProgram(InputAction.CallbackContext context) + { + Debug.Log("saving"); + Save save = CreateSave(); + SurrogateSelector surrogateSelector = new(); + surrogateSelector.AddSurrogate(typeof(Vector3), new StreamingContext(StreamingContextStates.All), new Vector3SerializationSurrogate()); + + BinaryFormatter binaryFormatter = new(); + binaryFormatter.SurrogateSelector = surrogateSelector; + + FileStream fs = File.Create(this._savePath); + binaryFormatter.Serialize(fs, save); + fs.Close(); + Debug.Log("finished saving"); + } + + public void LoadProgram(InputAction.CallbackContext context) + { + Debug.Log("loading"); + if (File.Exists(this._savePath)) + { + if (_spawnedBlocks.Count > 0) _spawnedBlocks.Clear(); + + SurrogateSelector surrogateSelector = new(); + surrogateSelector.AddSurrogate(typeof(Vector3), new StreamingContext(StreamingContextStates.All), new Vector3SerializationSurrogate()); + + BinaryFormatter binaryFormatter = new(); + binaryFormatter.SurrogateSelector = surrogateSelector; + FileStream fs = File.Open(this._savePath, FileMode.Open); + + Save save = (Save)binaryFormatter.Deserialize(fs); + fs.Close(); + + spawnBlockEvent.LoadBlocks(save.Blocks); + } + } + +} diff --git a/Assets/Scrips/Controllers/ProgramController.cs.meta b/Assets/Scrips/Controllers/ProgramController.cs.meta new file mode 100644 index 0000000000000000000000000000000000000000..85b3b2fb91d28286deda5f16d58e26ee74c03bcb --- /dev/null +++ b/Assets/Scrips/Controllers/ProgramController.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3972891316024844e9f4db4ba6131e3b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scrips/Events/SpawnBlockEvent.cs b/Assets/Scrips/Events/SpawnBlockEvent.cs index a219c7cd59dc5f41e8aa30b85ea09d9d2a4b191b..87a69d15497cb232c226b16fa76bc97a88d080c1 100644 --- a/Assets/Scrips/Events/SpawnBlockEvent.cs +++ b/Assets/Scrips/Events/SpawnBlockEvent.cs @@ -11,6 +11,8 @@ public class SpawnBlockEvent : MonoBehaviour public Transform inputTransform; public InputActionReference triggerEventAction; + public ProgramController programController; + private void Awake() { spawnPrefab.GetComponent<BlockRotate>().inputTransform = this.inputTransform; @@ -40,10 +42,24 @@ public class SpawnBlockEvent : MonoBehaviour Vector3 adjustment = Vector3.Scale(hit.normal, objectCollider.bounds.size / 2); spawnedObject.transform.position += adjustment; spawnedObject.transform.parent = this.transform; + + programController.RegisterBlock(spawnedObject); } } } + public void LoadBlocks(List<Vector3> blocks) + { + foreach (Vector3 blockPosition in blocks) + { + GameObject spawnedObject = Instantiate(spawnPrefab, blockPosition, Quaternion.identity); + spawnedObject.transform.parent = this.transform; + + programController.RegisterBlock(spawnedObject); + + } + } + private void OnDeviceChange(InputDevice device, InputDeviceChange change) { switch (change) @@ -67,6 +83,8 @@ public class SpawnBlockEvent : MonoBehaviour Vector3 adjustment = Vector3.Scale(this.transform.up, objectCollider.bounds.size / 2); spawnedObject.transform.position += adjustment; spawnedObject.transform.parent = this.transform; + + programController.RegisterBlock(spawnedObject); } // Update is called once per frame diff --git a/Assets/Scrips/Utils.meta b/Assets/Scrips/Utils.meta new file mode 100644 index 0000000000000000000000000000000000000000..dba55af07b112089dc587e6b134ba114ccacb47d --- /dev/null +++ b/Assets/Scrips/Utils.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: da4de8fb2afe4654ea22f19e9ad20191 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scrips/Utils/MeshSerializationSurrogate.cs b/Assets/Scrips/Utils/MeshSerializationSurrogate.cs new file mode 100644 index 0000000000000000000000000000000000000000..a28d542ea885661e03ad31b3fbaac4854e1affd4 --- /dev/null +++ b/Assets/Scrips/Utils/MeshSerializationSurrogate.cs @@ -0,0 +1,31 @@ +using System.Collections; +using System.Collections.Generic; +using System.Runtime.Serialization; +using UnityEngine; + +public class MeshSerializationSurrogate : ISerializationSurrogate +{ + private float[] createFlattenedArray(Vector3[] vertices) + { + float[] flattenedVertices = new float[vertices.Length * 3]; + for (int i = 0; i < vertices.Length; i++) + { + flattenedVertices[i * 3] = vertices[i].x; + flattenedVertices[i * 3 + 1] = vertices[i].y; + flattenedVertices[i * 3 + 2] = vertices[i].z; + } + return flattenedVertices; + } + + + public void GetObjectData(object obj, SerializationInfo info, StreamingContext context) + { + Mesh _mesh = (Mesh)obj; + info.AddValue("vertices", createFlattenedArray(_mesh.vertices)); + } + + public object SetObjectData(object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector) + { + throw new System.NotImplementedException(); + } +} diff --git a/Assets/Scrips/Utils/MeshSerializationSurrogate.cs.meta b/Assets/Scrips/Utils/MeshSerializationSurrogate.cs.meta new file mode 100644 index 0000000000000000000000000000000000000000..e0bc1e39ba78524f9dcfac106702a1a9eb749a25 --- /dev/null +++ b/Assets/Scrips/Utils/MeshSerializationSurrogate.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 103fa22612a46bc4c9fef566e3dad455 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scrips/Utils/Save.cs b/Assets/Scrips/Utils/Save.cs new file mode 100644 index 0000000000000000000000000000000000000000..67fdb3526a6262457a15a355a61072e7ae61481f --- /dev/null +++ b/Assets/Scrips/Utils/Save.cs @@ -0,0 +1,10 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +[System.Serializable] +public class Save +{ + public Vector3 UserTransform; + public List<Vector3> Blocks = new(); +} diff --git a/Assets/Scrips/Utils/Save.cs.meta b/Assets/Scrips/Utils/Save.cs.meta new file mode 100644 index 0000000000000000000000000000000000000000..9527f58222960d935bfb83cd12c7b49ef1f4ef5e --- /dev/null +++ b/Assets/Scrips/Utils/Save.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: febfe6e3d5336ff49ade0c5698217ab4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scrips/Utils/TransformSerializationSurrogate.cs b/Assets/Scrips/Utils/TransformSerializationSurrogate.cs new file mode 100644 index 0000000000000000000000000000000000000000..40ecc8036392f43c32fb5ac43ac99a8fb8c87d3c --- /dev/null +++ b/Assets/Scrips/Utils/TransformSerializationSurrogate.cs @@ -0,0 +1,53 @@ +using System.Collections; +using System.Collections.Generic; +using System.Runtime.Serialization; +using UnityEngine; + +public class TransformSerializationSurrogate : ISerializationSurrogate +{ + public void GetObjectData(object obj, SerializationInfo info, StreamingContext context) + { + Transform _transform = (Transform)obj; + Vector3 pos = _transform.position; + info.AddValue("posX", pos.x); + info.AddValue("posY", pos.y); + info.AddValue("posZ", pos.z); + + Vector3 rot = _transform.eulerAngles; + info.AddValue("rotX", rot.x); + info.AddValue("rotY", rot.y); + info.AddValue("rotZ", rot.z); + + Vector3 scale = _transform.localScale; + info.AddValue("scaleX", scale.x); + info.AddValue("scaleY", scale.y); + info.AddValue("scaleZ", scale.z); + } + + public object SetObjectData(object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector) + { + GameObject _obj = (GameObject)obj; + Transform _transform = _obj.transform; + Vector3 pos = _transform.position; + + pos.x = (float)info.GetValue("posX", typeof(float)); + pos.y = (float)info.GetValue("posY", typeof(float)); + pos.z = (float)info.GetValue("posZ", typeof(float)); + _transform.position = pos; + Vector3 rot = new( + (float)info.GetValue("rotX", typeof(float)), + (float)info.GetValue("rotY", typeof(float)), + (float)info.GetValue("rotZ", typeof(float)) + ); + _transform.eulerAngles = rot; + Vector3 scale = new( + (float)info.GetValue("scaleX", typeof(float)), + (float)info.GetValue("scaleY", typeof(float)), + (float)info.GetValue("scaleZ", typeof(float)) + ); + _transform.localScale = scale; + + obj = _transform; + return obj; + } +} diff --git a/Assets/Scrips/Utils/TransformSerializationSurrogate.cs.meta b/Assets/Scrips/Utils/TransformSerializationSurrogate.cs.meta new file mode 100644 index 0000000000000000000000000000000000000000..040a429baa92c5ba127c52538844d82a58906b8f --- /dev/null +++ b/Assets/Scrips/Utils/TransformSerializationSurrogate.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 69acdbf0094ffc643aa7206dfc735da8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scrips/Utils/Vector3SerializationSurrogate.cs b/Assets/Scrips/Utils/Vector3SerializationSurrogate.cs new file mode 100644 index 0000000000000000000000000000000000000000..98d7a76b682f21ca6688fd67fa3d460749f46857 --- /dev/null +++ b/Assets/Scrips/Utils/Vector3SerializationSurrogate.cs @@ -0,0 +1,27 @@ +using System.Collections; +using System.Collections.Generic; +using System.Runtime.Serialization; +using UnityEngine; + +// source: https://raptorkwok.medium.com/unity-save-and-load-data-adf2c52f4de7 +sealed class Vector3SerializationSurrogate : ISerializationSurrogate +{ + // Method called to serialize a Vector3 object + public void GetObjectData(object obj, SerializationInfo info, StreamingContext context) + { + Vector3 v3 = (Vector3)obj; + info.AddValue("x", v3.x); + info.AddValue("y", v3.y); + info.AddValue("z", v3.z); + } + // Method called to deserialize a Vector3 object + public object SetObjectData(object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector) + { + Vector3 v3 = (Vector3)obj; + v3.x = (float)info.GetValue("x", typeof(float)); + v3.y = (float)info.GetValue("y", typeof(float)); + v3.z = (float)info.GetValue("z", typeof(float)); + obj = v3; + return obj; + } +} diff --git a/Assets/Scrips/Utils/Vector3SerializationSurrogate.cs.meta b/Assets/Scrips/Utils/Vector3SerializationSurrogate.cs.meta new file mode 100644 index 0000000000000000000000000000000000000000..9ce07a79e524c219ec6e090e231f55b3efd85e6f --- /dev/null +++ b/Assets/Scrips/Utils/Vector3SerializationSurrogate.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ece260a147b323e449a0519644b0ece7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: