diff --git a/Winch/Data/POI/Dock/CustomDockPOI.cs b/Winch/Data/POI/Dock/CustomDockPOI.cs index 81fb822a..5a7fd18b 100644 --- a/Winch/Data/POI/Dock/CustomDockPOI.cs +++ b/Winch/Data/POI/Dock/CustomDockPOI.cs @@ -97,4 +97,9 @@ public class CustomDockPOI : CustomPOI /// The dock's safe zone settings /// public DockSafeZone safeZone = new DockSafeZone(); + + /// + /// Cameras for any speakers in the dock data + /// + public Dictionary speakerVCams = new Dictionary(); } diff --git a/Winch/Data/POI/Dock/SpeakerVCam.cs b/Winch/Data/POI/Dock/SpeakerVCam.cs new file mode 100644 index 00000000..c45985c3 --- /dev/null +++ b/Winch/Data/POI/Dock/SpeakerVCam.cs @@ -0,0 +1,20 @@ +using System; +using UnityEngine; + +namespace Winch.Data.POI.Dock; + +[Serializable] +public class SpeakerVCam +{ + /// + /// Relative position of the camera from this speaker. + /// + [SerializeField] + public Vector3 vCam = new Vector3(13, 2.5f, 9); + + /// + /// The relative position for the camera look at target + /// + [SerializeField] + public Vector3 lookAtTarget = new Vector3(-0.7f, -2f, -0.25f); +} diff --git a/Winch/Serialization/DredgeTypeHelpers.cs b/Winch/Serialization/DredgeTypeHelpers.cs index 5a26428e..67dbed81 100644 --- a/Winch/Serialization/DredgeTypeHelpers.cs +++ b/Winch/Serialization/DredgeTypeHelpers.cs @@ -477,4 +477,30 @@ public static List ParseAudioReferenceOverrides(JArray o } return parsed; } + + public static Dictionary GetSpeakerVCamsFromJsonObject(object value) + { + var jsonDict = JsonConvert.DeserializeObject>(value.ToString()) ?? throw new InvalidOperationException("Unable to parse speaker cameras."); + return GetSpeakerVCamsDictionary(jsonDict); + } + + private static Dictionary GetSpeakerVCamsDictionary(Dictionary vcams) + { + var parsed = new Dictionary(); + foreach (var kvp in vcams) + { + parsed.Add(kvp.Key, ParseSpeakerVCam(kvp.Value)); + } + return parsed; + } + + private static SpeakerVCam ParseSpeakerVCam(object value) + { + var jsonDict = JsonConvert.DeserializeObject>(value.ToString()) ?? throw new InvalidOperationException("Unable to parse speaker camera."); + return new SpeakerVCam + { + vCam = jsonDict.TryGetValue("vCam", out object vCam) ? ParseVector3(vCam) : new Vector3(13, 2.5f, 9), + lookAtTarget = jsonDict.TryGetValue("lookAtTarget", out object lookAtTarget) ? ParseVector3(lookAtTarget) : new Vector3(-0.7f, -2f, -0.25f) + }; + } } diff --git a/Winch/Serialization/POI/Dock/CustomDockPOIConverter.cs b/Winch/Serialization/POI/Dock/CustomDockPOIConverter.cs index 654564ae..0e0a5134 100644 --- a/Winch/Serialization/POI/Dock/CustomDockPOIConverter.cs +++ b/Winch/Serialization/POI/Dock/CustomDockPOIConverter.cs @@ -21,6 +21,7 @@ public class CustomDockPOIConverter : CustomPOIConverter { "dockSlots", new(null, o=>DredgeTypeHelpers.ParseDockSlots((JArray)o) ) }, { "sanityModifier", new( new DockSanityModifier(), o=> DredgeTypeHelpers.ParseDockSanityModifier(o)) }, { "safeZone", new( new DockSafeZone(), o=> DredgeTypeHelpers.ParseDockSafeZone(o)) }, + { "speakerVCams", new( new Dictionary(), o=> DredgeTypeHelpers.GetSpeakerVCamsFromJsonObject(o)) }, }; private readonly Dictionary _reroutes = new() diff --git a/Winch/Util/DockUtil.cs b/Winch/Util/DockUtil.cs index 4857182e..3d84451c 100644 --- a/Winch/Util/DockUtil.cs +++ b/Winch/Util/DockUtil.cs @@ -443,9 +443,25 @@ public static DockPOI CreateDock(CustomDockPOI customDockPoi) dock.sanityModifier = CreateDockSanityModifier(customDockPoi.sanityModifier, dockObject.transform); dock.safeZone = CreateDockSafeZone(customDockPoi.safeZone, dockObject.transform); + Dictionary speakerVCams = new Dictionary(); + foreach (var speakerVCam in customDockPoi.speakerVCams) + { + speakerVCams.Add(speakerVCam.Key, CreateSpeakerVCam(speakerVCam.Key, speakerVCam.Value, dockObject.transform)); + } + dock.speakerVCams = speakerVCams; + return dockPoi; } + public static CinemachineVirtualCamera CreateSpeakerVCam(string speaker, SpeakerVCam settings, Transform parent) + { + var speakerObject = new GameObject(speaker); + speakerObject.transform.SetParent(parent, false); + speakerObject.transform.localPosition = Vector3.zero; + var lookAt = CreateLookAtTarget(settings.lookAtTarget, speakerObject.transform); + return CreateDockVirtualCamera(settings.vCam, lookAt, speakerObject.transform); + } + public static Transform CreateLookAtTarget(Vector3 position, Transform parent, string name = "LookAt") { var lookAt = new GameObject(name);