HeavenStudioPlus/Assets/Scripts/LevelEditor/Timeline/TimelineBlockManager.cs
minenice55 fd1df6687e Auto-Swing (#827)
* BurstLinq

make BGM resync when changing pitch (to test)

* autoswing

some game implementations, most games already work fine

* more game tweaks

* 16th note swing

more game fixes
make pitch change resync optional in the API

* suppress some common warnings

* Update Credits.txt
2024-04-07 04:54:06 +00:00

209 lines
No EOL
6.2 KiB
C#

using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Pool;
using Jukebox;
using System.Linq;
using BurstLinq;
namespace HeavenStudio.Editor.Track
{
public class TimelineBlockManager : MonoBehaviour
{
public static TimelineBlockManager Instance { get; private set; }
public TimelineEventObj EntityTemplate;
public BlockDeleteFX BlockDeleteFXTemplate;
public Dictionary<Guid, TimelineEventObj> EntityMarkers = new();
public ObjectPool<TimelineEventObj> Pool { get; private set; }
private int firstMarkerToCareAbout = 0;
private int lastMarkerToCareAbout = 0;
private Timeline timeline;
private RiqEntity entityToSet;
public bool InteractingWithEvents { get; private set; } = false;
public bool MovingAnyEvents { get; private set; } = false;
public void SetEntityToSet(RiqEntity entity)
{
entityToSet = entity;
}
private void Awake()
{
Instance = this;
timeline = GetComponent<Timeline>();
Pool = new ObjectPool<TimelineEventObj>(CreateMarker, OnTakeMarkerFromPool, OnReturnMarkerToPool, OnDestroyMarker, true, 125, 1500);
}
public void Load()
{
var timeLeft = timeline.leftSide;
var timeRight = timeline.rightSide;
foreach (var marker in EntityMarkers)
{
Destroy(marker.Value.gameObject);
}
EntityMarkers.Clear();
Pool.Clear();
foreach (var entity in GameManager.instance.Beatmap.Entities)
{
var vLeft = entity.beat + entity.length >= timeLeft;
var vRight = entity.beat < timeRight;
var active = vLeft && vRight;
if (!active) continue;
entityToSet = entity;
Pool.Get();
Debug.Log(entity.datamodel);
}
}
public TimelineEventObj CreateEntity(RiqEntity entity)
{
entityToSet = entity;
var marker = Pool.Get();
marker.UpdateMarker();
return marker;
}
public void OnZoom()
{
foreach (var marker in EntityMarkers.Values)
{
marker.SetWidthHeight();
}
}
public void UpdateMarkers()
{
var timeLeft = timeline.leftSide;
var timeRight = timeline.rightSide;
var markersActiveBeats = new List<float>();
foreach (var marker in EntityMarkers.Values)
{
if (marker.selected || marker.moving)
{
markersActiveBeats.Add((float)marker.entity.beat);
}
}
for (var i = 0; i < GameManager.instance.Beatmap.Entities.Count; i++)
{
var entity = GameManager.instance.Beatmap.Entities[i];
var vLeft = entity.beat + entity.length >= timeLeft;
var vRight = entity.beat < timeRight;
var active = vLeft && vRight;
var containsMarker = EntityMarkers.ContainsKey(entity.guid);
if (containsMarker)
{
var marker = EntityMarkers[entity.guid];
if (marker.selected || marker.moving) active = true;
}
if (active)
{
if (!containsMarker)
{
entityToSet = entity;
Pool.Get();
}
EntityMarkers[entity.guid].UpdateMarker();
}
else
{
if (EntityMarkers.ContainsKey(entity.guid))
Pool.Release(EntityMarkers[entity.guid]);
}
}
InteractingWithEvents = false;
MovingAnyEvents = false;
foreach (var marker in EntityMarkers.Values)
{
if (marker.moving || marker.resizing || marker.mouseHovering)
InteractingWithEvents = true;
if (marker.moving)
MovingAnyEvents = true;
}
}
public void SortMarkers()
{
// Debug.Log("Sorted timeline blocks.");
var sortedBlocks = EntityMarkers.Values.OrderByDescending(c => c.entity.length).ToList();
var i = 0;
foreach (var block in EntityMarkers.Values)
{
var index = sortedBlocks.FindIndex(c => c.entity.guid == block.entity.guid);
block.transform.SetSiblingIndex(index + 1);
i++;
}
}
private TimelineEventObj CreateMarker()
{
TimelineEventObj marker = Instantiate(EntityTemplate.gameObject, Timeline.instance.TimelineEventsHolder).GetComponent<TimelineEventObj>();
return marker;
}
private void OnTakeMarkerFromPool(TimelineEventObj marker)
{
marker.SetEntity(entityToSet);
marker.SetMarkerInfo();
SortMarkers();
marker.gameObject.SetActive(true);
EntityMarkers.Add(entityToSet.guid, marker);
}
private void OnReturnMarkerToPool(TimelineEventObj marker)
{
EntityMarkers.Remove(marker.entity.guid);
marker.gameObject.SetActive(false);
}
private void OnDestroyMarker(TimelineEventObj marker)
{
Destroy(marker.gameObject);
}
// NOTE (PELLY): This should probably be pooled in the future.
public void CreateDestroyFX(RiqEntity entity)
{
var deleteFX = Instantiate(BlockDeleteFXTemplate, BlockDeleteFXTemplate.transform.parent);
deleteFX.gameObject.SetActive(true);
bool selected = false;
if (EntityMarkers.ContainsKey(entity.guid))
{
if (Selections.instance.eventsSelected.Contains(EntityMarkers[entity.guid]))
{
selected = true;
}
}
deleteFX.Create(entity.beat, entity.length, (int)entity["track"], selected);
}
}
}