Jamie Greunbaum e485d0d992 - Modem camera transition now has zoom animations.
- Added a CameraAnchor and follower for the winning player in round 2.
- Round 2 now has a more reliable check for when the call ends.
- CameraAnchor can now follow different areas of a player's body.
- CameraTimedSwitcher can now choose to always reactivate when asked.
- Glass shatter effect now only works for hosts.
- CaseVideoSyncPlayer will no longer crash when skipping too fast in round 1.
- Fixed an erroneous camera switcher activation in round 3.
- Made a minor wording change to Eartha Brute's wanted poster.
2026-03-25 04:08:23 -04:00

127 lines
3.3 KiB
C#

using Newtonsoft.Json.Linq;
using UdonSharp;
using UnityEngine;
using VRC.Udon.Common;
[UdonBehaviourSyncMode(BehaviourSyncMode.Manual)]
public class CameraTimedSwitcher : UdonSharpBehaviour
{
[SerializeField] private CameraControllerBase _CameraController;
[SerializeField] private string[] _SwitchFunctions;
[SerializeField] private float[] _TimeBetweenCuts = { 5.0f };
[Space]
[SerializeField, Tooltip("When enabled, switcher will reset when activated, even if it wasn't deactivated first.")]
private bool _AlwaysReactivate = false;
[SerializeField] private bool _Loop = true;
[SerializeField, Tooltip("Loop to this point in the camera sequence. Default is index 0 (the beginning)")]
private int _LoopPoint = 0;
[Space]
[SerializeField, Tooltip("Set this to call a function on an UdonSharpBehaviour instead of looping the camera sequence")]
private UdonSharpBehaviour _FirstLoopCallbackObject = null;
[SerializeField] private string _FirstLoopCallbackFunction = "";
[UdonSynced] private bool _Active = false;
private float _Timer = 0.0f;
private bool _AwaitingNextSwitch = false;
private int _NextCameraIndex = 0;
private bool _LoopedOnce = false;
void Update()
{
if (_Active && _AwaitingNextSwitch)
{
_Timer -= Time.deltaTime;
if (_Timer <= 0.0f)
{
SwitchToNextCamera();
}
}
}
public override void OnDeserialization(DeserializationResult Result)
{
_Activate_Synced();
base.OnDeserialization(Result);
}
public void Activate(bool Activate)
{
if (_Active != Activate || _AlwaysReactivate)
{
_Active = Activate;
_Activate_Synced();
RequestSerialization();
}
}
private void _Activate_Synced()
{
_AwaitingNextSwitch = false;
if (_Active)
{
_NextCameraIndex = 0;
_LoopedOnce = false;
SwitchToNextCamera();
}
else
{
_Timer = 0.0f;
}
}
public void SwitchToNextCamera()
{
_AwaitingNextSwitch = false;
if (_Active)
{
int CurrentCameraIndex = _NextCameraIndex;
Debug.Log("[CameraTimedSwitcher] Current camera index: " + CurrentCameraIndex);
if (CurrentCameraIndex == _LoopPoint && _LoopedOnce)
{
if (_FirstLoopCallbackObject != null)
{
Debug.Log("[CameraTimedSwitcher] We're on a new loop and a callback is set; running function " + _FirstLoopCallbackFunction + " on object " + _FirstLoopCallbackObject.gameObject.name + " and deactivating");
_FirstLoopCallbackObject.SendCustomEvent(_FirstLoopCallbackFunction);
Activate(false);
return;
}
if (!_Loop)
{
Debug.Log("[CameraTimedSwitcher] On a second loop, but looping is disabled; deactivating");
Activate(false);
return;
}
}
string Function = _SwitchFunctions[_NextCameraIndex];
if (Function != "")
{
_CameraController.SendCustomEvent(Function);
Debug.Log("[CameraTimedSwitcher] Executing function " + Function);
}
_NextCameraIndex = (_NextCameraIndex + 1) % _SwitchFunctions.Length;
if (_NextCameraIndex == 0)
{
_LoopedOnce = true;
_NextCameraIndex = _LoopPoint;
Debug.Log("[CameraTimedSwitcher] Setting next camera index to loop point " + _LoopPoint);
}
_Timer = _TimeBetweenCuts[Mathf.Min(CurrentCameraIndex, _TimeBetweenCuts.Length - 1)];
_AwaitingNextSwitch = true;
Debug.Log("[CameraTimedSwitcher] Camera index " + _NextCameraIndex + " will be activated in " + _Timer + " seconds");
}
}
}