CarmenSandiego/Assets/UdonSharp/CaseVideoSyncPlayer.cs
Jamie Greunbaum 1bb921d8ed - Final round reworked to support map display.
- Removed Final Round host card, since it's a duplicate anyway.
2025-07-10 16:38:24 -04:00

246 lines
5.6 KiB
C#

using UdonSharp;
using UnityEngine;
using VRC.SDK3.Image;
using VRC.SDK3.Video.Components.Base;
using VRC.SDKBase;
using VRC.Udon.Common.Interfaces;
public enum ClueScreenType
{
Blank,
Video,
Map
}
public enum SubMap
{
NoLabels,
OneLabel,
TwoLabels,
ThreeLabels,
CorrectLit,
OnlyCorrect
}
[UdonBehaviourSyncMode(BehaviourSyncMode.Manual)]
public class CaseVideoSyncPlayer : UdonSharpBehaviour
{
[SerializeField] private GameManagerRound1 _GameManager;
[UdonSynced, FieldChangeCallback(nameof(SubMapIndex))] private SubMap _SubMapIndex = 0;
[FieldChangeCallback(nameof(FlashCorrectAnswer))] private bool _FlashCorrectAnswer = false;
[SerializeField] private BaseVRCVideoPlayer _VideoPlayer;
[UdonSynced, FieldChangeCallback(nameof(VideoURL))] private VRCUrl _VideoURL;
[UdonSynced, FieldChangeCallback(nameof(TimeAndOffset))] private Vector2 _TimeAndOffset;
public float SyncFrequency = 5.0f;
[SerializeField] private MeshRenderer _BlankScreenMesh;
[SerializeField] private MeshRenderer _VideoScreenMesh;
[SerializeField] private MeshRenderer _MapScreenMesh;
private VRCImageDownloader _MapDownloader;
private VRCUrl _CurrentMapURL;
void Start()
{
_MapDownloader = new VRCImageDownloader();
}
void OnDestroy()
{
_MapDownloader.Dispose();
}
public void LoadMap(int MapIndex)
{
VRCUrl MapURL = _GameManager.GetMapURL(MapIndex);
if (MapURL == _CurrentMapURL) return;
_CurrentMapURL = MapURL;
ShowScreen(ClueScreenType.Blank);
TextureInfo AdditionalTextureInfo = new TextureInfo();
AdditionalTextureInfo.WrapModeU = TextureWrapMode.Clamp;
AdditionalTextureInfo.WrapModeV = TextureWrapMode.Clamp;
AdditionalTextureInfo.GenerateMipMaps = false;
AdditionalTextureInfo.MaterialProperty = "_EmissionMap";
_MapDownloader.DownloadImage(
_CurrentMapURL,
_MapScreenMesh.sharedMaterial,
(IUdonEventReceiver)this,
AdditionalTextureInfo);
}
public override void OnImageLoadSuccess(IVRCImageDownload result)
{
base.OnImageLoadSuccess(result);
}
public override void OnImageLoadError(IVRCImageDownload result)
{
base.OnImageLoadError(result);
}
public void ShowSubMap(SubMap Index)
{
SubMapIndex = Index;
ShowScreen(ClueScreenType.Map);
}
public void NextCorrectAnswerFrame()
{
if (FlashCorrectAnswer)
{
SubMapIndex = (SubMapIndex == SubMap.CorrectLit) ? SubMap.ThreeLabels : SubMap.CorrectLit;
Debug.LogError("Switching to frame " + SubMapIndex + "...");
SendCustomEventDelayedSeconds(nameof(NextCorrectAnswerFrame), 0.2f);
}
else
{
_VideoPlayer.Stop();
SubMapIndex = 0;
ShowScreen(ClueScreenType.Blank);
}
}
private void UpdateMap()
{
switch (SubMapIndex)
{
case SubMap.NoLabels: _MapScreenMesh.sharedMaterial.SetVector("_MainTex_ST", new Vector4(0.5f, 0.33333333f, 0.0f, 0.66666666f)); break;
case SubMap.OneLabel: _MapScreenMesh.sharedMaterial.SetVector("_MainTex_ST", new Vector4(0.5f, 0.33333333f, 0.5f, 0.66666666f)); break;
case SubMap.TwoLabels: _MapScreenMesh.sharedMaterial.SetVector("_MainTex_ST", new Vector4(0.5f, 0.33333333f, 0.0f, 0.33333333f)); break;
case SubMap.ThreeLabels: _MapScreenMesh.sharedMaterial.SetVector("_MainTex_ST", new Vector4(0.5f, 0.33333333f, 0.5f, 0.33333333f)); break;
case SubMap.CorrectLit: _MapScreenMesh.sharedMaterial.SetVector("_MainTex_ST", new Vector4(0.5f, 0.33333333f, 0.0f, 0.0f)); break;
case SubMap.OnlyCorrect: _MapScreenMesh.sharedMaterial.SetVector("_MainTex_ST", new Vector4(0.5f, 0.33333333f, 0.5f, 0.0f)); break;
}
}
public void PlayVideo()
{
_VideoPlayer.PlayURL(VideoURL);
RequestSerialization();
}
public override void OnVideoStart()
{
Debug.LogError("Displaying video material...");
ShowScreen(ClueScreenType.Video);
UpdateTimeAndOffset();
base.OnVideoStart();
}
private void UpdateTimeAndOffset()
{
if (Networking.IsOwner(gameObject))
{
TimeAndOffset = new Vector2(_VideoPlayer.GetTime(), (float)Networking.GetServerTimeInSeconds());
RequestSerialization();
if (SyncFrequency > 0.0f)
{
SendCustomEventDelayedSeconds(nameof(UpdateTimeAndOffset), SyncFrequency);
}
}
else
{
SendCustomEvent(nameof(Resync));
}
}
public void Resync()
{
_VideoPlayer.SetTime(TimeAndOffset.x + ((float)Networking.GetServerTimeInSeconds() - TimeAndOffset.y));
}
public void ClearScreen()
{
ShowScreen(ClueScreenType.Blank);
FlashCorrectAnswer = false;
}
private void ShowScreen(ClueScreenType Screen)
{
switch (Screen)
{
case ClueScreenType.Blank:
{
_BlankScreenMesh.gameObject.SetActive(true);
_VideoScreenMesh.gameObject.SetActive(false);
_MapScreenMesh.gameObject.SetActive(false);
break;
}
case ClueScreenType.Video:
{
_BlankScreenMesh.gameObject.SetActive(false);
_VideoScreenMesh.gameObject.SetActive(true);
_MapScreenMesh.gameObject.SetActive(false);
break;
}
case ClueScreenType.Map:
{
_BlankScreenMesh.gameObject.SetActive(false);
_VideoScreenMesh.gameObject.SetActive(false);
_MapScreenMesh.gameObject.SetActive(true);
break;
}
}
}
public SubMap SubMapIndex
{
set
{
_SubMapIndex = value;
UpdateMap();
}
get => _SubMapIndex;
}
public bool FlashCorrectAnswer
{
set
{
_FlashCorrectAnswer = value;
NextCorrectAnswerFrame();
}
get => _FlashCorrectAnswer;
}
public VRCUrl VideoURL
{
set
{
if (_VideoURL != value)
{
_VideoURL = value;
PlayVideo();
}
}
get => _VideoURL;
}
public Vector2 TimeAndOffset
{
set
{
_TimeAndOffset = value;
if (!Networking.IsOwner(gameObject))
{
SendCustomEvent(nameof(Resync));
}
}
get => _TimeAndOffset;
}
}