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);