Fully working Replay in Observation Scene

This commit is contained in:
Thorbjoern
2025-05-26 20:31:19 +02:00
parent c304bc0e10
commit f47331ef81
3 changed files with 4048 additions and 192 deletions
@@ -2,11 +2,10 @@ using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;
using System.Threading.Tasks;
using System;
using System.Reactive;
using UnityEngine.UI;
using Postgrest;
using Cysharp.Threading.Tasks;
namespace GhostSystem
{
@@ -40,6 +39,8 @@ namespace GhostSystem
private bool sceneIdReady = false;
private string loadedSceneId;
private DateTime latestLoadedTimestamp;
[Serializable]
public class TrackedObjectBinding
{
@@ -72,59 +73,106 @@ namespace GhostSystem
TryInitializeReplay();
}
private async void TryInitializeReplay()
private async UniTaskVoid TryInitializeReplay()
{
if (!supabaseReady || !sceneIdReady) return;
SceneId = loadedSceneId;
await LoadFrames();
await LoadAllFrames();
StartReplay();
_ = PeriodicUpdateFrames();
}
public async Task LoadFrames()
public async UniTask LoadAllFrames()
{
Debug.Log("SceneId used in query: " + SceneId);
Debug.Log("StartTime filter: " + dateSelector.selectedDateTime().ToString("o"));
objectTracks.Clear();
int batchSize = 1000;
int offset = 0;
bool more = true;
List<FrameModel> allFrames = new();
while (more)
{
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)
.Limit(batchSize) // Limit, wie viele Frames in einem Batch geladen werden. (Standardmäßig 1000)
.Offset(offset); // Um zu wissen, wo der nçhste Batch anfängt
if (!string.IsNullOrEmpty(UserFilter))
query = query.Filter("user_id", Postgrest.Constants.Operator.Equals, UserFilter);
var result = await query.Get();
if (result.Models.Count == 0) break;
allFrames.AddRange(result.Models);
offset += batchSize;
more = result.Models.Count == batchSize;
}
foreach (var frame in allFrames)
{
if (!objectTracks.ContainsKey(frame.ObjectId))
objectTracks[frame.ObjectId] = new List<FrameModel>();
objectTracks[frame.ObjectId].Add(frame);
}
if (allFrames.Count > 1)
{
latestLoadedTimestamp = allFrames.Last().TimestampParsed;
totalDuration = (float)(latestLoadedTimestamp - allFrames.First().TimestampParsed).TotalSeconds;
firstTimestamp = allFrames.First().TimestampParsed.ToLongTimeString();
lastTimestamp = latestLoadedTimestamp.ToLongTimeString();
}
Debug.LogWarning($"Loaded {allFrames.Count} frames across {objectTracks.Count} objects.");
}
private async UniTaskVoid PeriodicUpdateFrames() // lädt alle 10 s neue Frames nach, falls verfügbar
{
while (true)
{
await UniTask.Delay(TimeSpan.FromSeconds(10));
await LoadNewFramesAfter(latestLoadedTimestamp);
}
}
private async UniTask LoadNewFramesAfter(DateTime afterTime) // lädt einen neuen Batch nach.
{
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"))
.Filter("timestamp", Postgrest.Constants.Operator.GreaterThan, afterTime.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);
var newFrames = result.Models;
objectTracks.Clear();
foreach (var frame in frames)
foreach (var frame in newFrames)
{
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)
if (newFrames.Count > 0)
{
totalDuration = (float)(frames.Last().TimestampParsed - frames.First().TimestampParsed).TotalSeconds;
firstTimestamp = frames.First().TimestampParsed.ToLongTimeString();
lastTimestamp = frames.Last().TimestampParsed.ToLongTimeString();
latestLoadedTimestamp = newFrames.Last().TimestampParsed;
totalDuration = (float)(latestLoadedTimestamp - objectTracks.Values.SelectMany(f => f).First().TimestampParsed).TotalSeconds;
}
Debug.Log($"Appended {newFrames.Count} new frames.");
}
public void StartReplay() // Für das Play UI-Element, um das Replay zu starten
{
isPlaying = true;
@@ -147,8 +195,7 @@ namespace GhostSystem
private void Update()
{
if (!isPlaying || objectTracks.Count == 0)
return;
if (!isPlaying || objectTracks.Count == 0) return;
playbackTime += Time.deltaTime * PlaybackSpeed;
@@ -166,12 +213,10 @@ namespace GhostSystem
foreach (var binding in TrackedObjects)
{
if (!objectTracks.ContainsKey(binding.objectId))
continue;
if (!objectTracks.ContainsKey(binding.objectId)) continue;
var frames = objectTracks[binding.objectId];
if (frames.Count < 2)
continue;
if (frames.Count < 2) continue;
FrameModel a = null, b = null;
+2 -2
View File
@@ -13,7 +13,7 @@ public class DateSelector : MonoBehaviour
public void SetYear(int yearIndex)
{
selectedYear = yearIndex; // Achtung: ggf. +Offset je nach Dropdown-Inhalt
selectedYear = yearIndex + 2025; // Achtung: ggf. +Offset je nach Dropdown-Inhalt
}
public void SetMonth(int monthIndex)
@@ -33,7 +33,7 @@ public class DateSelector : MonoBehaviour
public void SetMinute(int minuteIndex)
{
selectedMinute = minuteIndex; // 059
selectedMinute = minuteIndex * 5; // 059
}
public DateTime selectedDateTime()
{