Added all the other GhostSystem Scripts
This commit is contained in:
@@ -0,0 +1,231 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System;
|
||||
using System.Reactive;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace GhostSystem
|
||||
{
|
||||
public class GhostReplayManager : MonoBehaviour
|
||||
{
|
||||
[Header("Replay Settings")]
|
||||
public string SceneId;
|
||||
public string UserFilter = null; // optional: filtere nach User-ID
|
||||
public bool Loop = true;
|
||||
public DateTime selectedStartTime;
|
||||
public DateSelector dateSelector;
|
||||
|
||||
[Header("Target Objects")]
|
||||
public List<TrackedObjectBinding> TrackedObjects;
|
||||
|
||||
[Header("Playback")]
|
||||
public float PlaybackSpeed = 1f;
|
||||
public bool AutoStart = true;
|
||||
public Slider playbackSlider;
|
||||
private bool isScrubbing = false;
|
||||
|
||||
private bool isPlaying = false;
|
||||
private float playbackTime = 0f;
|
||||
private float totalDuration = 0f;
|
||||
|
||||
private Dictionary<string, List<FrameModel>> objectTracks = new();
|
||||
|
||||
private bool supabaseReady = false;
|
||||
private bool sceneIdReady = false;
|
||||
private string loadedSceneId;
|
||||
|
||||
[Serializable]
|
||||
public class TrackedObjectBinding
|
||||
{
|
||||
public string objectId;
|
||||
public GameObject targetObject;
|
||||
}
|
||||
|
||||
private async void OnEnable()
|
||||
{
|
||||
SupabaseManager.OnSuperbaseReady += HandleSupabaseReady;
|
||||
RoomManager.OnSceneIdReady += HandleSceneIdReady;
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
SupabaseManager.OnSuperbaseReady -= HandleSupabaseReady;
|
||||
RoomManager.OnSceneIdReady -= HandleSceneIdReady;
|
||||
}
|
||||
|
||||
private void HandleSupabaseReady()
|
||||
{
|
||||
supabaseReady = true;
|
||||
TryInitializeReplay();
|
||||
}
|
||||
|
||||
private void HandleSceneIdReady(string id)
|
||||
{
|
||||
sceneIdReady = true;
|
||||
loadedSceneId = id;
|
||||
TryInitializeReplay();
|
||||
}
|
||||
|
||||
private async void TryInitializeReplay()
|
||||
{
|
||||
if (!supabaseReady || !sceneIdReady) return;
|
||||
|
||||
SceneId = loadedSceneId;
|
||||
|
||||
await LoadFrames();
|
||||
StartReplay();
|
||||
}
|
||||
|
||||
public async Task LoadFrames()
|
||||
{
|
||||
Debug.Log("SceneId used in query: " + SceneId);
|
||||
|
||||
var query = SupabaseManager.instance.supabase
|
||||
.From<FrameModel>()
|
||||
.Filter("scene_id", Postgrest.Constants.Operator.Equals, SceneId)
|
||||
.Filter("timestamp", Postgrest.Constants.Operator.GreaterThanOrEqual, dateSelector.selectedDateTime().ToString("o"))
|
||||
.Order("timestamp", Postgrest.Constants.Ordering.Ascending);
|
||||
|
||||
if (!string.IsNullOrEmpty(UserFilter))
|
||||
query = query.Filter("user_id", Postgrest.Constants.Operator.Equals, UserFilter);
|
||||
|
||||
var result = await query.Get();
|
||||
var frames = result.Models;
|
||||
Debug.LogError("Frames: " + frames.Count);
|
||||
|
||||
objectTracks.Clear();
|
||||
foreach (var frame in frames)
|
||||
{
|
||||
if (!objectTracks.ContainsKey(frame.ObjectId))
|
||||
objectTracks[frame.ObjectId] = new List<FrameModel>();
|
||||
|
||||
objectTracks[frame.ObjectId].Add(frame);
|
||||
//Debug.Log($"Loaded frame: {frame.ObjectId} at {frame.Timestamp}");
|
||||
Debug.Log($"Loaded frame: {frame.ObjectId} at {frame.TimestampParsed} Pos: {frame.Position}");
|
||||
Debug.Log($"Parsed timestamp: {frame.Timestamp} -> {frame.TimestampParsed.ToString("o")}" + "Pos JSON: " + frame.PositionJson);
|
||||
|
||||
}
|
||||
Debug.LogWarning("Got the Data!");
|
||||
Debug.LogWarning(objectTracks.Count);
|
||||
|
||||
// Gesamtzeit berechnen (in Sekunden)
|
||||
if (frames.Count > 1)
|
||||
{
|
||||
totalDuration = (float)(frames.Last().TimestampParsed - frames.First().TimestampParsed).TotalSeconds;
|
||||
}
|
||||
}
|
||||
|
||||
public void StartReplay() // Für das Play UI-Element, um das Replay zu starten
|
||||
{
|
||||
isPlaying = true;
|
||||
playbackTime = 0f;
|
||||
Debug.LogError("Replay started: total duration = " + totalDuration);
|
||||
}
|
||||
|
||||
public void PauseReplay() => isPlaying = false; // Für das Pause UI-Element, um das Replay zu pausieren
|
||||
|
||||
public void StopReplay() // Für das Stop UI-Element, um das Replay zu beenden
|
||||
{
|
||||
isPlaying = false;
|
||||
playbackTime = 0f;
|
||||
}
|
||||
|
||||
public void SetPlaybackTime(float time) // Für das Slider UI-Element zum Scrubben
|
||||
{
|
||||
playbackTime = Mathf.Clamp(time, 0f, totalDuration);
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (!isPlaying || objectTracks.Count == 0)
|
||||
return;
|
||||
|
||||
playbackTime += Time.deltaTime * PlaybackSpeed;
|
||||
|
||||
if (playbackTime > totalDuration)
|
||||
{
|
||||
if (Loop)
|
||||
playbackTime = 0f;
|
||||
else
|
||||
isPlaying = false;
|
||||
}
|
||||
|
||||
DateTime currentTimestamp = objectTracks.Values
|
||||
.SelectMany(list => list)
|
||||
.First().TimestampParsed + TimeSpan.FromSeconds(playbackTime);
|
||||
|
||||
foreach (var binding in TrackedObjects)
|
||||
{
|
||||
if (!objectTracks.ContainsKey(binding.objectId))
|
||||
continue;
|
||||
|
||||
var frames = objectTracks[binding.objectId];
|
||||
if (frames.Count < 2)
|
||||
continue;
|
||||
|
||||
FrameModel a = null, b = null;
|
||||
|
||||
for (int i = 0; i < frames.Count - 1; i++)
|
||||
{
|
||||
var tA = frames[i].TimestampParsed;
|
||||
var tB = frames[i + 1].TimestampParsed;
|
||||
|
||||
if (tA <= currentTimestamp && tB >= currentTimestamp)
|
||||
{
|
||||
a = frames[i];
|
||||
b = frames[i + 1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (a != null && b != null)
|
||||
{
|
||||
double tA = a.TimestampParsed.Subtract(DateTime.UnixEpoch).TotalSeconds;
|
||||
double tB = b.TimestampParsed.Subtract(DateTime.UnixEpoch).TotalSeconds;
|
||||
double tCurrent = currentTimestamp.Subtract(DateTime.UnixEpoch).TotalSeconds;
|
||||
|
||||
float t = Mathf.Clamp01((float)((tCurrent - tA) / (tB - tA)));
|
||||
|
||||
Vector3 pos = Vector3.Lerp(a.Position, b.Position, t);
|
||||
Quaternion rot = Quaternion.Slerp(a.Rotation, b.Rotation, t);
|
||||
|
||||
binding.targetObject.transform.SetPositionAndRotation(pos, rot);
|
||||
}
|
||||
}
|
||||
|
||||
if (!isScrubbing && playbackSlider != null && totalDuration > 0f)
|
||||
{
|
||||
playbackSlider.value = playbackTime / totalDuration;
|
||||
}
|
||||
}
|
||||
|
||||
/*public void OnSliderValueChanged(float value)
|
||||
{
|
||||
if (totalDuration <= 0f) return;
|
||||
isScrubbing = true;
|
||||
SetPlaybackTime(value * totalDuration);
|
||||
}*/
|
||||
public void SetSliderScrubValue(float sliderValue)
|
||||
{
|
||||
if (isScrubbing)
|
||||
SetPlaybackTime(sliderValue * totalDuration);
|
||||
}
|
||||
|
||||
|
||||
public void OnSliderStartDrag()
|
||||
{
|
||||
isScrubbing = true;
|
||||
}
|
||||
|
||||
public void OnSliderEndDrag()
|
||||
{
|
||||
isScrubbing = false;
|
||||
SetPlaybackTime(playbackSlider.value * totalDuration);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user