New Switch Game Look (#979)

* move prefabs and music out of resources

lower "real" audio cap
update some packages

* new game switch look

audio optimizations

* import SFB as package instead of plugin

use updated SFB fork

* fix game switch events

* delete effect for game switch

* new look for chart end

* update Jukebox to 0.2.4

* fix outline ordering

* re-isolated fan club sfx

* move more stuff out of resources

further reduce audiomanager virtual voices

* fix rendering of other GameManager blocks
This commit is contained in:
minenice55
2024-06-14 18:03:18 -04:00
committed by GitHub
parent 75cf2d46aa
commit 7abc15038c
1078 changed files with 7624 additions and 9390 deletions

View File

@ -1,6 +1,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
using BurstLinq;
using UnityEngine;
using Jukebox;

View File

@ -17,9 +17,15 @@ namespace HeavenStudio
{
public class GameManager : MonoBehaviour
{
const int SoundPoolSizeMin = 32;
const int SoundPoolSizeMin = 28;
const int SoundPoolSizeMax = 32;
[Header("Prefabs")]
[SerializeField] GameObject textboxPrefab;
[SerializeField] GameObject timingDispPrefab;
[SerializeField] GameObject skillStarDispPrefab;
[SerializeField] GameObject overlaysPrefab;
[Header("Lists")]
[NonSerialized] public RiqBeatmap Beatmap = new();
[NonSerialized] public ObjectPool<Sound> SoundObjects;
@ -88,7 +94,7 @@ namespace HeavenStudio
public static GameManager instance { get; private set; }
private EventCaller eventCaller;
public Conductor conductor;
[NonSerialized] public Conductor conductor;
// average input accuracy (msec)
List<int> inputOffsetSamples = new List<int>();
@ -144,21 +150,23 @@ namespace HeavenStudio
canInput = true;
// note: serialize this shit in the inspector //
GameObject textbox = Instantiate(Resources.Load<GameObject>("Prefabs/Common/Textbox"));
// GameObject textbox = Instantiate(Resources.Load<GameObject>("Prefabs/Common/Textbox"));
GameObject textbox = Instantiate(textboxPrefab);
textbox.name = "Textbox";
GameObject timingDisp = Instantiate(Resources.Load<GameObject>("Prefabs/Common/Overlays/TimingAccuracy"));
// GameObject timingDisp = Instantiate(Resources.Load<GameObject>("Prefabs/Common/Overlays/TimingAccuracy"));
GameObject timingDisp = Instantiate(timingDispPrefab);
timingDisp.name = "TimingDisplay";
GameObject skillStarDisp = Instantiate(Resources.Load<GameObject>("Prefabs/Common/Overlays/SkillStar"));
// GameObject skillStarDisp = Instantiate(Resources.Load<GameObject>("Prefabs/Common/Overlays/SkillStar"));
GameObject skillStarDisp = Instantiate(skillStarDispPrefab);
skillStarDisp.name = "SkillStar";
GameObject overlays = Instantiate(Resources.Load<GameObject>("Prefabs/Common/Overlays"));
// GameObject overlays = Instantiate(Resources.Load<GameObject>("Prefabs/Common/Overlays"));
GameObject overlays = Instantiate(overlaysPrefab);
overlays.name = "Overlays";
GoForAPerfect.instance.Disable();
/////
SoundByte.BasicCheck();
SoundObjects = new ObjectPool<Sound>(CreatePooledSound, OnTakePooledSound, OnReturnPooledSound, OnDestroyPooledSound, true, SoundPoolSizeMin, SoundPoolSizeMax);

View File

@ -3,7 +3,20 @@ guid: fd86589935fb46c4db0d3d23d52743a9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
defaultReferences:
- textboxPrefab: {fileID: 2987735714244475933, guid: 8e18884075612184aaff6ef8d3db8839, type: 3}
- timingDispPrefab: {fileID: 6450655676217413848, guid: 5fc25fa6546364c42a43c2323fca4c01, type: 3}
- skillStarDispPrefab: {fileID: 3811612147158016040, guid: 2777c2b8273631d45abc37febc4cb2e7, type: 3}
- overlaysPrefab: {fileID: 162471444277636096, guid: 4d9453ade5932194bae17fced9de7093, type: 3}
- GameCamera: {instanceID: 0}
- CursorCam: {instanceID: 0}
- OverlayCamera: {instanceID: 0}
- StaticCamera: {instanceID: 0}
- CircleCursor: {instanceID: 0}
- GamesHolder: {instanceID: 0}
- fade: {instanceID: 0}
- filter: {instanceID: 0}
- conductor: {instanceID: 0}
executionOrder: -44
icon: {instanceID: 0}
userData:

View File

@ -5,6 +5,7 @@ using HeavenStudio.Util;
using HeavenStudio.Editor.Track;
using DG.Tweening;
using System;
namespace HeavenStudio.Editor
{
@ -15,8 +16,10 @@ namespace HeavenStudio.Editor
/// </summary>
public bool ActivelySelecting { get; private set; } = false;
private Vector2 startPosition = Vector2.zero;
private Vector2 endPosition = Vector2.zero;
// private Vector2 startPosition = Vector2.zero;
// private Vector2 endPosition = Vector2.zero;
private double startBeat, endBeat;
private int startTrack, endTrack;
private bool validClick = false;
[SerializeField] private RectTransform boxVisual;
@ -49,7 +52,8 @@ namespace HeavenStudio.Editor
}
validClick = true;
startPosition = new Vector2(Timeline.instance.MousePos2Beat, Timeline.instance.MousePos2Layer);
startBeat = Math.Max(Timeline.instance.MousePos2Beat, 0);
startTrack = Mathf.RoundToInt(Timeline.instance.MousePos2Layer);
boxGroup.DOKill();
boxGroup.alpha = 1.0f;
@ -57,19 +61,16 @@ namespace HeavenStudio.Editor
if (!validClick) return;
var startPos = startPosition;
var endPos = endPosition;
Vector2 startPos = new Vector2((float)startBeat, startTrack);
Vector2 endPos = Vector2.zero;
if (Input.GetMouseButton(0))
{
endPos = new Vector2(Timeline.instance.MousePos2Beat,
Timeline.instance.MousePos2Layer +
(Timeline.instance.MousePos2Layer < startPosition.y ? 0 : 1));
startPos = new Vector2(startPos.x,
startPos.y + ((Timeline.instance.MousePos2Layer < startPosition.y) ? 1 : 0));
endBeat = Math.Max(Timeline.instance.MousePos2Beat, 0);
endTrack = Mathf.RoundToInt(Timeline.instance.MousePos2Layer);
startPos = new Vector2(startPos.x, Mathf.Clamp(startPos.y, 0, Timeline.instance.LayerCount));
endPos = new Vector2(endPos.x, Mathf.Clamp(endPos.y, 0, Timeline.instance.LayerCount));
startPos = new Vector2((float)startBeat, Mathf.Clamp(startTrack, 0, Timeline.instance.LayerCount) + (endTrack >= startTrack ? 0 : 1));
endPos = new Vector2((float)endBeat, Mathf.Clamp(endTrack, 0, Timeline.instance.LayerCount) + (endTrack >= startTrack ? 1 : 0));
ActivelySelecting = true;
@ -121,20 +122,37 @@ namespace HeavenStudio.Editor
sizeText.rectTransform.offsetMin = new Vector2(sizeTextLeft * Timeline.instance.PixelsPerBeat, -sizeTextTop * Timeline.instance.LayerHeight());
sizeText.rectTransform.offsetMax = new Vector2(-sizeTextRight * Timeline.instance.PixelsPerBeat, sizeTextBottom * Timeline.instance.LayerHeight());
Select(start, end);
double finalStartBeat = startBeat, finalEndBeat = endBeat;
int finalStartTrack = startTrack, finalEndTrack = endTrack;
if (finalEndBeat < finalStartBeat)
{
var temp = finalStartBeat;
finalStartBeat = finalEndBeat;
finalEndBeat = temp;
}
if (finalEndTrack < finalStartTrack)
{
var temp = finalStartTrack;
finalStartTrack = finalEndTrack;
finalEndTrack = temp;
}
Select(finalStartBeat, finalEndBeat, finalStartTrack, finalEndTrack);
}
private void Select(Vector2 start, Vector2 end)
/// <summary>
/// Selects the entity markers within the specified range.
/// </summary>
/// <param name="startBeat">The starting beat of the selection range.</param>
/// <param name="endBeat">The ending beat of the selection range.</param>
/// <param name="startTrack">The starting track of the selection range.</param>
/// <param name="endTrack">The ending track of the selection range.</param>
private void Select(double startBeat, double endBeat, int startTrack, int endTrack)
{
var boxRect = new Rect(start.x, start.y, end.x - start.x, end.y - start.y);
// This doesn't take into account blocks the user cannot see, this is intentional.
// minenice: not ideal though, eventually make this select riq entities instead of timeline objects
foreach (var marker in TimelineBlockManager.Instance.EntityMarkers.Values)
{
var markerRect = new Rect((float)marker.entity.beat, (int)marker.entity["track"], marker.entity.length, 1);
var boxOverMarker = boxRect.Overlaps(markerRect);
if (boxOverMarker)
if (marker.BoxSelectOverlapping(startBeat, endBeat, startTrack, endTrack))
{
if (!marker.selected)
Selections.instance.DragSelect(marker);

View File

@ -39,7 +39,7 @@ namespace HeavenStudio.Editor.Commands
var clonedEntity = entity.DeepCopy();
clonedEntity.guid = entity.guid;
deletedEntities.Add(new() { riqEntity = clonedEntity, selected = marker.selected });
deletedEntities.Add(new() { riqEntity = clonedEntity, selected = marker.selected });
TimelineBlockManager.Instance.CreateDestroyFX(entity);
@ -61,7 +61,10 @@ namespace HeavenStudio.Editor.Commands
{
var deletedEntity = deletedEntities[i];
GameManager.instance.Beatmap.Entities.Add(deletedEntity.riqEntity);
var marker = TimelineBlockManager.Instance.CreateEntity(deletedEntity.riqEntity);
string[] split = deletedEntity.riqEntity.datamodel.Split('/');
bool longMarker = (split[0] == "gameManager" && (split[1] == "switchGame" || split[1] == "end"));
var marker = TimelineBlockManager.Instance.CreateEntity(deletedEntity.riqEntity, longMarker);
/*if (deletedEntities[i].selected)
Selections.instance.ShiftClickSelect(marker);*/
@ -94,7 +97,9 @@ namespace HeavenStudio.Editor.Commands
GameManager.instance.Beatmap.Entities.Add(entity);
var marker = TimelineBlockManager.Instance.CreateEntity(entity);
string[] split = entity.datamodel.Split('/');
bool longMarker = (split[0] == "gameManager" && (split[1] == "switchGame" || split[1] == "end"));
var marker = TimelineBlockManager.Instance.CreateEntity(entity, longMarker);
GameManager.instance.SortEventsList();
}
@ -136,8 +141,10 @@ namespace HeavenStudio.Editor.Commands
{
var newEntity = entity.DeepCopy();
// there's gotta be a better way to do this. i just don't know how... -AJ
foreach ((var key, var value) in new Dictionary<string, dynamic>(newEntity.dynamicData)) {
if (value is EntityTypes.DropdownObj dd) {
foreach ((var key, var value) in new Dictionary<string, dynamic>(newEntity.dynamicData))
{
if (value is EntityTypes.DropdownObj dd)
{
newEntity[key] = new EntityTypes.DropdownObj(dd.value, dd.Values);
}
}
@ -166,7 +173,10 @@ namespace HeavenStudio.Editor.Commands
entity.guid = placedEntityIDs[i];
GameManager.instance.Beatmap.Entities.Add(entity);
var marker = TimelineBlockManager.Instance.CreateEntity(entity);
string[] split = entity.datamodel.Split('/');
bool longMarker = (split[0] == "gameManager" && (split[1] == "switchGame" || split[1] == "end"));
var marker = TimelineBlockManager.Instance.CreateEntity(entity, longMarker);
Selections.instance.DragSelect(marker);
if (i == entities.Count - 1)
@ -242,7 +252,10 @@ namespace HeavenStudio.Editor.Commands
entity.guid = entityIds[i];
GameManager.instance.Beatmap.Entities.Add(entity);
var marker = TimelineBlockManager.Instance.CreateEntity(entity);
string[] split = entity.datamodel.Split('/');
bool longMarker = (split[0] == "gameManager" && (split[1] == "switchGame" || split[1] == "end"));
var marker = TimelineBlockManager.Instance.CreateEntity(entity, longMarker);
Selections.instance.DragSelect(marker);
}

View File

@ -1,3 +1,4 @@
using HeavenStudio.Games;
using HeavenStudio.Util;
using UnityEngine;
using UnityEngine.UI;
@ -14,6 +15,8 @@ namespace HeavenStudio.Editor.Track
private bool started = false;
private float deleteTime = 0.0f;
private Color color;
private double eBeat;
private float eLength;
private int eLayer;
@ -34,6 +37,26 @@ namespace HeavenStudio.Editor.Track
eLayer = layer;
wasESelected = selected;
rectTransform.anchoredPosition = new Vector2((float)eBeat * Timeline.instance.PixelsPerBeat, -eLayer * Timeline.instance.LayerHeight());
rectTransform.sizeDelta = new Vector2(eLength * Timeline.instance.PixelsPerBeat, Timeline.instance.LayerHeight());
color = EditorTheme.theme.LayerGradientIndex(eLayer);
Destroy(this.gameObject, 0.714f);
Update();
}
public void Create(double beat, Color color)
{
started = true;
deleteTime = Time.time;
eBeat = beat;
rectTransform.anchoredPosition = new Vector2((float)eBeat * Timeline.instance.PixelsPerBeat, 0);
rectTransform.sizeDelta = new Vector2(0.25f * Timeline.instance.PixelsPerBeat, Timeline.instance.LayerCount * Timeline.instance.LayerHeight());
this.color = color;
Destroy(this.gameObject, 0.714f);
Update();
@ -43,14 +66,9 @@ namespace HeavenStudio.Editor.Track
{
if (!started) return;
rectTransform.anchoredPosition = new Vector2((float)eBeat * Timeline.instance.PixelsPerBeat, -eLayer * Timeline.instance.LayerHeight());
rectTransform.sizeDelta = new Vector2(eLength * Timeline.instance.PixelsPerBeat, Timeline.instance.LayerHeight());
// I added this because I was going to use the effect when you undo a place as well, but I didn't like it.
// var color = (wasESelected) ? Color.cyan : EditorTheme.theme.LayerGradientIndex(eLayer);
var color = EditorTheme.theme.LayerGradientIndex(eLayer);
var norm = (Time.time - deleteTime) * 1.4f;
mainImage.color = Color.Lerp(color, new Color(color.r, color.g, color.b, 0.0f), EasingFunction.EaseOutCirc(0, 1, norm));

View File

@ -149,14 +149,12 @@ namespace HeavenStudio.Editor.Track
[Header("Timeline Components")]
[SerializeField] private RectTransform TimelineSlider;
[SerializeField] private RectTransform TimelineGridSelect;
[SerializeField] private RectTransform TimelineEventGrid;
[SerializeField] private TMP_Text TimelinePlaybackBeat;
public ScrollRect TimelineScroll;
[SerializeField] private RectTransform RealTimelineContent;
[SerializeField] private RectTransform TimelineContent;
public RectTransform EventContent;
[SerializeField] private RectTransform TimelineSongPosLineRef;
[SerializeField] private RectTransform TimelineEventObjRef;
public RectTransform TimelineEventsHolder;
[SerializeField] private RectTransform LayersRect;
@ -846,6 +844,7 @@ namespace HeavenStudio.Editor.Track
{
string[] split = eventName.Split('/');
var action = EventCaller.instance.GetGameAction(split[0], split[1]);
bool longMarker = split[0] == "gameManager" && (split[1] == "switchGame" || split[1] == "end");
if (addEvent)
{
@ -899,7 +898,7 @@ namespace HeavenStudio.Editor.Track
TimelineBlockManager.Instance.SetEntityToSet(entity);
}
var marker = TimelineBlockManager.Instance.Pool.Get();
var marker = longMarker ? TimelineBlockManager.Instance.LongEventsPool.Get() : TimelineBlockManager.Instance.EventPool.Get();
marker.SetMarkerInfo();

View File

@ -4,6 +4,7 @@ using UnityEngine;
using UnityEngine.Pool;
using Jukebox;
using HeavenStudio.Util;
using System.Linq;
using BurstLinq;
@ -13,16 +14,15 @@ namespace HeavenStudio.Editor.Track
{
public static TimelineBlockManager Instance { get; private set; }
public TimelineEventObj EntityTemplate;
public BlockDeleteFX BlockDeleteFXTemplate;
[SerializeField] private TimelineEventObj EntityTemplate;
[SerializeField] private TimelineEventObj GameSwitchTemplate;
[SerializeField] private BlockDeleteFX BlockDeleteFXTemplate;
public Dictionary<Guid, TimelineEventObj> EntityMarkers = new();
public ObjectPool<TimelineEventObj> Pool { get; private set; }
public ObjectPool<TimelineEventObj> EventPool { get; private set; }
public ObjectPool<TimelineGameSwitch> LongEventsPool { get; private set; }
//private int firstMarkerToCareAbout = 0; Unused value - Marc
//private int lastMarkerToCareAbout = 0; Unused value - Marc
private Timeline timeline;
private RiqEntity entityToSet;
public bool InteractingWithEvents { get; private set; } = false;
@ -39,7 +39,8 @@ namespace HeavenStudio.Editor.Track
timeline = GetComponent<Timeline>();
Pool = new ObjectPool<TimelineEventObj>(CreateMarker, OnTakeMarkerFromPool, OnReturnMarkerToPool, OnDestroyMarker, true, 125, 1500);
EventPool = new ObjectPool<TimelineEventObj>(CreateMarker, OnTakeMarkerFromPool, OnReturnMarkerToPool, OnDestroyMarker, true, 125, 1500);
LongEventsPool = new ObjectPool<TimelineGameSwitch>(CreateLongMarker, OnTakeLongMarkerFromPool, OnReturnMarkerToPool, OnDestroyMarker, true, 10, 150);
}
public void Load()
@ -53,7 +54,8 @@ namespace HeavenStudio.Editor.Track
}
EntityMarkers.Clear();
Pool.Clear();
EventPool.Clear();
LongEventsPool.Clear();
foreach (var entity in GameManager.instance.Beatmap.Entities)
{
@ -64,16 +66,24 @@ namespace HeavenStudio.Editor.Track
if (!active) continue;
entityToSet = entity;
Pool.Get();
string[] split = entity.datamodel.Split('/');
if (split[0] == "gameManager" && (split[1] == "switchGame" || split[1] == "end"))
{
LongEventsPool.Get();
}
else
{
EventPool.Get();
}
Debug.Log(entity.datamodel);
}
}
public TimelineEventObj CreateEntity(RiqEntity entity)
public TimelineEventObj CreateEntity(RiqEntity entity, bool longMarker = false)
{
entityToSet = entity;
var marker = Pool.Get();
var marker = longMarker ? LongEventsPool.Get() : EventPool.Get();
marker.UpdateMarker();
return marker;
@ -118,19 +128,36 @@ namespace HeavenStudio.Editor.Track
if (marker.selected || marker.moving) active = true;
}
string[] split = entity.datamodel.Split('/');
if (active)
{
if (!containsMarker)
{
entityToSet = entity;
Pool.Get();
if (split[0] == "gameManager" && (split[1] == "switchGame" || split[1] == "end"))
{
LongEventsPool.Get();
}
else
{
EventPool.Get();
}
}
EntityMarkers[entity.guid].UpdateMarker();
}
else
{
if (EntityMarkers.ContainsKey(entity.guid))
Pool.Release(EntityMarkers[entity.guid]);
{
if (split[0] == "gameManager" && (split[1] == "switchGame" || split[1] == "end"))
{
LongEventsPool.Release(EntityMarkers[entity.guid] as TimelineGameSwitch);
}
else
{
EventPool.Release(EntityMarkers[entity.guid]);
}
}
}
}
@ -167,6 +194,12 @@ namespace HeavenStudio.Editor.Track
return marker;
}
private TimelineGameSwitch CreateLongMarker()
{
TimelineGameSwitch marker = Instantiate(GameSwitchTemplate.gameObject, Timeline.instance.TimelineEventsHolder).GetComponent<TimelineGameSwitch>();
return marker;
}
private void OnTakeMarkerFromPool(TimelineEventObj marker)
{
marker.SetEntity(entityToSet);
@ -178,6 +211,17 @@ namespace HeavenStudio.Editor.Track
EntityMarkers.Add(entityToSet.guid, marker);
}
private void OnTakeLongMarkerFromPool(TimelineGameSwitch 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);
@ -203,7 +247,27 @@ namespace HeavenStudio.Editor.Track
selected = true;
}
}
deleteFX.Create(entity.beat, entity.length, (int)entity["track"], selected);
string[] split = entity.datamodel.Split('/');
if (split[0] == "gameManager")
{
if (split[1] == "switchGame")
{
deleteFX.Create(entity.beat, StringUtils.Hex2RGB(EventCaller.instance.GetMinigame(split[2]).color));
}
else if (split[1] == "end")
{
deleteFX.Create(entity.beat, Color.white);
}
else
{
deleteFX.Create(entity.beat, entity.length, (int)entity["track"], selected);
}
}
else
{
deleteFX.Create(entity.beat, entity.length, (int)entity["track"], selected);
}
}
}
}

View File

@ -1,9 +1,10 @@
using UnityEngine;
using UnityEngine.UI;
using Jukebox;
using HeavenStudio.Util;
using TMPro;
using System;
using System.Linq;
using System.Collections.Generic;
@ -11,40 +12,29 @@ namespace HeavenStudio.Editor.Track
{
public class TimelineEventObj : MonoBehaviour
{
public bool interacting;
private Vector3 lastPos;
public Vector2 moveStartPos;
private RectTransform rectTransform;
protected RectTransform rectTransform;
[Header("Components")]
[SerializeField] private RectTransform PosPreview;
[SerializeField] private RectTransform PosPreviewRef;
[SerializeField] public Image Icon;
[SerializeField] private Image selectedImage;
[SerializeField] public TMP_Text eventLabel;
[SerializeField] protected Image[] recolourables;
[SerializeField] protected Image Icon;
[SerializeField] protected Image selectedImage;
[SerializeField] protected TMP_Text eventLabel;
[SerializeField] private Image resizeGraphic;
[SerializeField] protected Image resizeGraphic;
[SerializeField] private RectTransform leftDrag;
[SerializeField] private RectTransform rightDrag;
[SerializeField] protected Image outline;
[SerializeField] protected Image hasPropertiesIcon;
[SerializeField] private Image outline;
[SerializeField] private Image hasPropertiesIcon;
[SerializeField] private RectTransform visibleRegion;
// private GameObject moveTemp;
[SerializeField] protected RectTransform visibleRegion;
[Header("Properties")]
public RiqEntity entity;
public float length;
private bool lastVisible;
public bool selected;
public bool mouseHovering;
public bool resizable;
public bool moving;
public bool wasDuplicated;
[NonSerialized] public float length;
[NonSerialized] public bool selected;
[NonSerialized] public bool mouseHovering;
[NonSerialized] public bool resizable;
[NonSerialized] public bool moving;
[NonSerialized] public bool isCreating;
public bool resizing => resizingLeft || resizingRight;
private bool resizingLeft;
@ -55,36 +45,31 @@ namespace HeavenStudio.Editor.Track
private double lastResizeBeat = 0;
private float lastResizeLength = 0;
public bool isCreating;
private bool altWhenClicked = false;
private bool dragging = false;
private double initMoveX = 0;
private float initMoveY = 0;
private double selectedMinInitMoveX, selectedMaxInitMoveX;
private float selectedMinInitMoveY, selectedMaxInitMoveY;
protected double initMoveX = 0;
protected float initMoveY = 0;
protected double selectedMinInitMoveX, selectedMaxInitMoveX;
protected float selectedMinInitMoveY, selectedMaxInitMoveY;
private bool movedEntity = false;
private double lastBeat = 0;
private int lastLayer = 0;
protected double lastBeat = 0;
protected int lastLayer = 0;
private int lastSiblingIndex;
private bool changedSiblingIndex;
public float zPriority { get; private set; }
public float zPriority { get; protected set; }
// Difference between mouseHovering is this is regardless if the user can see it.
private bool mouseOver;
private float clickTimer = 0.0f;
[Header("Colors")]
public Color NormalCol;
public void SetMarkerInfo()
{
moveStartPos = transform.localPosition;
rectTransform = GetComponent<RectTransform>();
var eventName = entity.datamodel;
@ -92,37 +77,67 @@ namespace HeavenStudio.Editor.Track
string[] split = eventName.Split('/');
var action = EventCaller.instance.GetGameAction(split[0], split[1]);
if (split[1] == "switchGame")
Icon.sprite = Editor.GameIcon(split[2]);
else
Icon.sprite = Editor.GameIcon(split[0]);
if (action != null)
if (split[0] == "gameManager")
{
this.resizable = action.resizable;
if (action.resizable == false)
if (split[1] == "switchGame")
{
rectTransform.sizeDelta = new Vector2(action.defaultLength * Timeline.instance.PixelsPerBeat, Timeline.instance.LayerHeight());
this.length = action.defaultLength;
entity["track"] = 0;
Icon.gameObject.SetActive(true);
Icon.sprite = Editor.GameIcon(split[2]);
eventLabel.text = EventCaller.instance.GetMinigame(split[2]).displayName;
}
else if (split[1] == "end")
{
entity["track"] = 0;
Icon.gameObject.SetActive(false);
eventLabel.text = action.displayName;
}
else
{
if (entity != null && action.defaultLength != entity.length)
Icon.sprite = Editor.GameIcon(split[0]);
eventLabel.text = action.displayName;
}
}
else
{
Icon.sprite = Editor.GameIcon(split[0]);
eventLabel.text = action.displayName;
}
if (action != null)
{
resizable = action.resizable;
if (action.resizable)
{
if (entity != null)
{
length = entity.length;
rectTransform.sizeDelta = new Vector2(entity.length * Timeline.instance.PixelsPerBeat, Timeline.instance.LayerHeight());
}
else
{
length = action.defaultLength;
rectTransform.sizeDelta = new Vector2(action.defaultLength * Timeline.instance.PixelsPerBeat, Timeline.instance.LayerHeight());
}
}
else
{
entity.length = action.defaultLength;
length = action.defaultLength;
rectTransform.sizeDelta = new Vector2(action.defaultLength * Timeline.instance.PixelsPerBeat, Timeline.instance.LayerHeight());
}
}
rectTransform.anchoredPosition = new Vector2((float)entity.beat * Timeline.instance.PixelsPerBeat, (int)-entity["track"] * Timeline.instance.LayerHeight());
resizeGraphic.gameObject.SetActive(resizable);
eventLabel.text = action.displayName;
if (resizeGraphic != null)
{
resizeGraphic.gameObject.SetActive(resizable);
}
hasPropertiesIcon.enabled = action.actionName != "switchGame" && action.parameters != null && action.parameters.Count > 0;
if (hasPropertiesIcon != null)
{
hasPropertiesIcon.enabled = action.actionName != "switchGame" && action.parameters != null && action.parameters.Count > 0;
}
SetColor((int)entity["track"]);
SetWidthHeight();
@ -140,7 +155,7 @@ namespace HeavenStudio.Editor.Track
this.entity = entity;
}
public void Update()
protected void Update()
{
clickTimer += Time.deltaTime;
}
@ -291,11 +306,7 @@ namespace HeavenStudio.Editor.Track
foreach (var marker in Selections.instance.eventsSelected)
{
if (setMovedEntity) marker.movedEntity = true;
marker.lastBeat = marker.entity.beat;
marker.lastLayer = (int)marker.entity["track"];
marker.initMoveX = Timeline.instance.MousePos2BeatSnap - marker.entity.beat;
marker.initMoveY = Timeline.instance.MousePos2Layer - (int)marker.entity["track"];
marker.SetInitialMove();
}
selectedMinInitMoveX = Selections.instance.eventsSelected.Min(marker => marker.initMoveX);
selectedMaxInitMoveX = Selections.instance.eventsSelected.Max(marker => marker.initMoveX);
@ -303,6 +314,15 @@ namespace HeavenStudio.Editor.Track
selectedMaxInitMoveY = Selections.instance.eventsSelected.Max(marker => marker.initMoveY);
}
public void SetInitialMove()
{
lastBeat = entity.beat;
lastLayer = (int)entity["track"];
initMoveX = Timeline.instance.MousePos2BeatSnap - entity.beat;
initMoveY = Timeline.instance.MousePos2Layer - (int)entity["track"];
}
#region ClickEvents
public void HoverEnter()
@ -408,7 +428,7 @@ namespace HeavenStudio.Editor.Track
// hardcoded stuff
// needs to happen because hidden blocks technically change the event index
if (game.fxOnly) block--;
if (datamodels[0] == "gameManager") block --;
if (datamodels[0] == "gameManager") block--;
}
GridGameSelector.instance.SelectGame(datamodels[isSwitchGame ? 2 : 0], block);
@ -515,12 +535,15 @@ namespace HeavenStudio.Editor.Track
#region Extra
public void SetColor(int type)
public virtual void SetColor(int type)
{
var c = EditorTheme.theme.LayerGradientIndex(type);
transform.GetChild(0).GetComponent<Image>().color = c;
foreach (var r in recolourables)
{
r.color = c;
}
if (resizable)
if (resizable && resizeGraphic != null)
{
c = new Color(0, 0, 0, 0.35f);
resizeGraphic.color = c;
@ -539,23 +562,19 @@ namespace HeavenStudio.Editor.Track
return (int)Mathf.Round(this.transform.localPosition.y / Timeline.instance.LayerHeight()) * -1;
}
private void OnDestroy()
public virtual bool BoxSelectOverlapping(double startBeat, double endBeat, int startTrack, int endTrack)
{
// better safety net than canada's healthcare system
// this is still hilarious
// GameManager.instance.Beatmap.Entities.Remove(GameManager.instance.Beatmap.Entities.Find(c => c.eventObj = this));
return (entity.beat.IsBetween(startBeat, endBeat) || (entity.beat + entity.length).IsBetween(startBeat, endBeat)) &&
((int)entity["track"]).IsBetween(startTrack, endTrack);
}
#endregion
public void OnSelect()
public virtual void OnSelect()
{
// selectedImage.gameObject.SetActive(true);
}
public void OnDeselect()
public virtual void OnDeselect()
{
// selectedImage.gameObject.SetActive(false);
}
}
}

View File

@ -0,0 +1,110 @@
using UnityEngine;
using UnityEngine.UI;
using Jukebox;
using HeavenStudio.Util;
using TMPro;
using System.Linq;
using System.Collections.Generic;
namespace HeavenStudio.Editor.Track
{
public class TimelineGameSwitch : TimelineEventObj
{
[SerializeField] RectTransform contentPanel;
[SerializeField] Image fadeEffect;
[SerializeField] Image leftLine;
[SerializeField] GameObject arrow;
new public void SetEntity(RiqEntity entity)
{
this.entity = entity;
}
new public void SetMarkerInfo()
{
base.SetMarkerInfo();
// SetColor(0);
}
new public void UpdateMarker()
{
base.UpdateMarker();
entity["track"] = 0;
entity.length = 0.5f;
// SetColor(0);
}
new public int GetTrack()
{
return 0;
}
new public void LateUpdate()
{
entity["track"] = 0;
entity.length = 0.5f;
rectTransform.anchoredPosition = new Vector2((float)entity.beat * Timeline.instance.PixelsPerBeat, -contentPanel.anchoredPosition.y);
SetWidthHeight();
}
new public void SetWidthHeight()
{
rectTransform.sizeDelta = new Vector2(entity.length * Timeline.instance.PixelsPerBeat, 0);
if (Icon.gameObject.activeSelf)
{
Icon.rectTransform.sizeDelta = new Vector2(24, 24);
eventLabel.rectTransform.offsetMin = new Vector2(Icon.rectTransform.anchoredPosition.x + Icon.rectTransform.sizeDelta.x + 4, eventLabel.rectTransform.offsetMin.y);
}
else
{
eventLabel.rectTransform.offsetMin = new Vector2(0, eventLabel.rectTransform.offsetMin.y);
}
}
public override void SetColor(int _)
{
Color c;
var eventName = entity.datamodel;
string[] split = eventName.Split('/');
if (split[0] == "gameManager")
{
if (split[1] == "switchGame")
{
c = StringUtils.Hex2RGB(EventCaller.instance.GetMinigame(split[2]).color);
foreach (var r in recolourables)
{
r.color = c;
}
c.a = 0.05f;
fadeEffect.color = c;
c.a = 0.15f;
leftLine.color = c;
arrow.SetActive(true);
}
else if (split[1] == "end")
{
c = Color.white;
foreach (var r in recolourables)
{
r.color = c;
}
leftLine.color = c;
c.a = 0.25f;
fadeEffect.color = c;
arrow.SetActive(false);
}
}
}
public override bool BoxSelectOverlapping(double startBeat, double endBeat, int startTrack, int endTrack)
{
return entity.beat.IsBetween(startBeat, endBeat) || (entity.beat + 0.25).IsBetween(startBeat, endBeat);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ae2e37747bf39ba4485b51d25a825fe0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -779,7 +779,7 @@ namespace HeavenStudio
},
inactiveFunction: delegate { var e = eventCaller.currentEntity; GameManager.instance.SwitchGame(eventCaller.currentSwitchGame, eventCaller.currentEntity.beat, e["toggle"]); }
),
new GameAction("end", "End Remix", "",
new GameAction("end", "End Remix", "", 0.5f,
function: delegate {
Debug.Log("end");
if (Timeline.instance != null)

View File

@ -14,9 +14,19 @@ namespace HeavenStudio.Util
return (value - min) / (max - min);
}
public static bool IsBetween(this int value, int min, int max)
{
return value >= min && value <= max;
}
public static bool IsBetween(this float value, float min, float max)
{
return value >= min && value <= max;
}
public static bool IsBetween(this double value, double min, double max)
{
return value >= min && value <= max;
}
}
}

View File

@ -70,7 +70,7 @@ namespace HeavenStudio.Util
GameManager.instance.SoundObjects.Release(this);
return;
}
CancelFadeRoutine();
audioSource = GetComponent<AudioSource>();
@ -92,6 +92,7 @@ namespace HeavenStudio.Util
playInstant = true;
played = true;
startTime = dspTime;
audioSource.enabled = true;
audioSource.Play();
}
else
@ -105,10 +106,15 @@ namespace HeavenStudio.Util
if (scheduledPitch != 0 && dspTime >= startTime)
{
audioSource.enabled = true;
audioSource.PlayScheduled(startTime);
played = true;
queued = true;
}
else
{
audioSource.enabled = false;
}
}
Update();
}
@ -128,6 +134,7 @@ namespace HeavenStudio.Util
{
if (!queued && dspTime > scheduledTime - PREBAKE_TIME)
{
audioSource.enabled = true;
audioSource.PlayScheduled(scheduledTime);
queued = true;
}
@ -141,6 +148,7 @@ namespace HeavenStudio.Util
if (!queued && dspTime > startTime - PREBAKE_TIME)
{
startTime = (dspTime + (cond.GetSongPosFromBeat(beat) - cond.songPositionAsDouble) / (double)scheduledPitch) - offset;
audioSource.enabled = true;
audioSource.PlayScheduled(startTime);
queued = true;
}
@ -156,12 +164,16 @@ namespace HeavenStudio.Util
{
scheduledPitch = cond.SongPitch;
if (queued)
{
audioSource.Pause();
audioSource.enabled = false;
}
}
else
{
if (scheduledPitch == 0)
{
audioSource.enabled = true;
audioSource.UnPause();
}
scheduledPitch = cond.SongPitch;
@ -193,6 +205,7 @@ namespace HeavenStudio.Util
{
// Debug.Log($"Pausing {gameObject.name}");
audioSource.Pause();
audioSource.enabled = false;
paused = true;
}
}
@ -201,6 +214,7 @@ namespace HeavenStudio.Util
if (paused)
{
// Debug.Log($"Unpausing {gameObject.name}");
audioSource.enabled = true;
audioSource.UnPause();
paused = false;
}
@ -247,6 +261,7 @@ namespace HeavenStudio.Util
public void Stop()
{
CancelFadeRoutine();
audioSource.Stop();
available = true;
played = false;
@ -262,7 +277,6 @@ namespace HeavenStudio.Util
ignoreConductorPause = false;
audioSource.loop = false;
audioSource.Stop();
gameObject.SetActive(false);
}
@ -335,13 +349,14 @@ namespace HeavenStudio.Util
if (!gameObject.activeSelf) return;
CancelFadeRoutine();
if (fadeTime == 0)
{
audioSource.Stop();
GameManager.instance.SoundObjects.Release(this);
return;
}
fadeRoutine = StartCoroutine(FadeLoop(fadeTime));
}
@ -358,12 +373,13 @@ namespace HeavenStudio.Util
}
yield return null;
audioSource.Stop();
GameManager.instance.SoundObjects.Release(this);
}
private void CancelFadeRoutine()
{
if(fadeRoutine != null) StopCoroutine(fadeRoutine);
if (fadeRoutine != null) StopCoroutine(fadeRoutine);
}
}
}

View File

@ -112,6 +112,7 @@ namespace HeavenStudio.Util
var clips = Resources.LoadAll<AudioClip>(path);
foreach (var clip in clips)
{
clip.LoadAudioData();
OnResourceLoaded(clip, $"games/{inf.name}/{clip.name}");
}
}