Fully working Replay in Observation Scene
This commit is contained in:
+3973
-162
File diff suppressed because it is too large
Load Diff
@@ -2,11 +2,10 @@ using System.Collections;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Reactive;
|
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using Postgrest;
|
using Postgrest;
|
||||||
|
using Cysharp.Threading.Tasks;
|
||||||
|
|
||||||
namespace GhostSystem
|
namespace GhostSystem
|
||||||
{
|
{
|
||||||
@@ -40,6 +39,8 @@ namespace GhostSystem
|
|||||||
private bool sceneIdReady = false;
|
private bool sceneIdReady = false;
|
||||||
private string loadedSceneId;
|
private string loadedSceneId;
|
||||||
|
|
||||||
|
private DateTime latestLoadedTimestamp;
|
||||||
|
|
||||||
[Serializable]
|
[Serializable]
|
||||||
public class TrackedObjectBinding
|
public class TrackedObjectBinding
|
||||||
{
|
{
|
||||||
@@ -72,59 +73,106 @@ namespace GhostSystem
|
|||||||
TryInitializeReplay();
|
TryInitializeReplay();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void TryInitializeReplay()
|
private async UniTaskVoid TryInitializeReplay()
|
||||||
{
|
{
|
||||||
if (!supabaseReady || !sceneIdReady) return;
|
if (!supabaseReady || !sceneIdReady) return;
|
||||||
|
|
||||||
SceneId = loadedSceneId;
|
SceneId = loadedSceneId;
|
||||||
|
|
||||||
await LoadFrames();
|
await LoadAllFrames();
|
||||||
StartReplay();
|
StartReplay();
|
||||||
|
_ = PeriodicUpdateFrames();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task LoadFrames()
|
public async UniTask LoadAllFrames()
|
||||||
{
|
{
|
||||||
Debug.Log("SceneId used in query: " + SceneId);
|
Debug.Log("SceneId used in query: " + SceneId);
|
||||||
Debug.Log("StartTime filter: " + dateSelector.selectedDateTime().ToString("o"));
|
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
|
var query = SupabaseManager.instance.supabase
|
||||||
.From<FrameModel>()
|
.From<FrameModel>()
|
||||||
.Filter("scene_id", Postgrest.Constants.Operator.Equals, SceneId)
|
.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);
|
.Order("timestamp", Postgrest.Constants.Ordering.Ascending);
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(UserFilter))
|
if (!string.IsNullOrEmpty(UserFilter))
|
||||||
query = query.Filter("user_id", Postgrest.Constants.Operator.Equals, UserFilter);
|
query = query.Filter("user_id", Postgrest.Constants.Operator.Equals, UserFilter);
|
||||||
|
|
||||||
var result = await query.Get();
|
var result = await query.Get();
|
||||||
var frames = result.Models;
|
var newFrames = result.Models;
|
||||||
Debug.LogError("Frames: " + frames.Count);
|
|
||||||
|
|
||||||
objectTracks.Clear();
|
foreach (var frame in newFrames)
|
||||||
foreach (var frame in frames)
|
|
||||||
{
|
{
|
||||||
if (!objectTracks.ContainsKey(frame.ObjectId))
|
if (!objectTracks.ContainsKey(frame.ObjectId))
|
||||||
objectTracks[frame.ObjectId] = new List<FrameModel>();
|
objectTracks[frame.ObjectId] = new List<FrameModel>();
|
||||||
|
|
||||||
objectTracks[frame.ObjectId].Add(frame);
|
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 (newFrames.Count > 0)
|
||||||
if (frames.Count > 1)
|
|
||||||
{
|
{
|
||||||
totalDuration = (float)(frames.Last().TimestampParsed - frames.First().TimestampParsed).TotalSeconds;
|
latestLoadedTimestamp = newFrames.Last().TimestampParsed;
|
||||||
firstTimestamp = frames.First().TimestampParsed.ToLongTimeString();
|
totalDuration = (float)(latestLoadedTimestamp - objectTracks.Values.SelectMany(f => f).First().TimestampParsed).TotalSeconds;
|
||||||
lastTimestamp = frames.Last().TimestampParsed.ToLongTimeString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Debug.Log($"Appended {newFrames.Count} new frames.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void StartReplay() // Für das Play UI-Element, um das Replay zu starten
|
public void StartReplay() // Für das Play UI-Element, um das Replay zu starten
|
||||||
{
|
{
|
||||||
isPlaying = true;
|
isPlaying = true;
|
||||||
@@ -147,8 +195,7 @@ namespace GhostSystem
|
|||||||
|
|
||||||
private void Update()
|
private void Update()
|
||||||
{
|
{
|
||||||
if (!isPlaying || objectTracks.Count == 0)
|
if (!isPlaying || objectTracks.Count == 0) return;
|
||||||
return;
|
|
||||||
|
|
||||||
playbackTime += Time.deltaTime * PlaybackSpeed;
|
playbackTime += Time.deltaTime * PlaybackSpeed;
|
||||||
|
|
||||||
@@ -166,12 +213,10 @@ namespace GhostSystem
|
|||||||
|
|
||||||
foreach (var binding in TrackedObjects)
|
foreach (var binding in TrackedObjects)
|
||||||
{
|
{
|
||||||
if (!objectTracks.ContainsKey(binding.objectId))
|
if (!objectTracks.ContainsKey(binding.objectId)) continue;
|
||||||
continue;
|
|
||||||
|
|
||||||
var frames = objectTracks[binding.objectId];
|
var frames = objectTracks[binding.objectId];
|
||||||
if (frames.Count < 2)
|
if (frames.Count < 2) continue;
|
||||||
continue;
|
|
||||||
|
|
||||||
FrameModel a = null, b = null;
|
FrameModel a = null, b = null;
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ public class DateSelector : MonoBehaviour
|
|||||||
|
|
||||||
public void SetYear(int yearIndex)
|
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)
|
public void SetMonth(int monthIndex)
|
||||||
@@ -33,7 +33,7 @@ public class DateSelector : MonoBehaviour
|
|||||||
|
|
||||||
public void SetMinute(int minuteIndex)
|
public void SetMinute(int minuteIndex)
|
||||||
{
|
{
|
||||||
selectedMinute = minuteIndex; // 0–59
|
selectedMinute = minuteIndex * 5; // 0–59
|
||||||
}
|
}
|
||||||
public DateTime selectedDateTime()
|
public DateTime selectedDateTime()
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user