diff --git a/Assets/Resources/Prefabs/GameView/GameTex.renderTexture b/Assets/Resources/Prefabs/GameView/GameTex.renderTexture index ca194f82..2445acfb 100644 --- a/Assets/Resources/Prefabs/GameView/GameTex.renderTexture +++ b/Assets/Resources/Prefabs/GameView/GameTex.renderTexture @@ -14,8 +14,8 @@ RenderTexture: m_DownscaleFallback: 0 m_IsAlphaChannelOptional: 0 serializedVersion: 5 - m_Width: 1280 - m_Height: 720 + m_Width: 1600 + m_Height: 900 m_AntiAliasing: 2 m_MipCount: -1 m_DepthStencilFormat: 92 diff --git a/Assets/Resources/Prefabs/GameView/OverlayTex.renderTexture b/Assets/Resources/Prefabs/GameView/OverlayTex.renderTexture index d13320f7..116de67f 100644 --- a/Assets/Resources/Prefabs/GameView/OverlayTex.renderTexture +++ b/Assets/Resources/Prefabs/GameView/OverlayTex.renderTexture @@ -14,8 +14,8 @@ RenderTexture: m_DownscaleFallback: 0 m_IsAlphaChannelOptional: 0 serializedVersion: 5 - m_Width: 1920 - m_Height: 1080 + m_Width: 2400 + m_Height: 1350 m_AntiAliasing: 1 m_MipCount: -1 m_DepthStencilFormat: 92 diff --git a/Assets/Resources/Sprites/Editor/UI/Animations/Autoplay/Idle.anim b/Assets/Resources/Sprites/Editor/UI/Animations/Autoplay/Idle.anim index f2750ea2..61756227 100644 --- a/Assets/Resources/Sprites/Editor/UI/Animations/Autoplay/Idle.anim +++ b/Assets/Resources/Sprites/Editor/UI/Animations/Autoplay/Idle.anim @@ -16,7 +16,26 @@ AnimationClip: m_EulerCurves: [] m_PositionCurves: [] m_ScaleCurves: [] - m_FloatCurves: [] + m_FloatCurves: + - curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + attribute: m_AnchoredPosition.y + path: Graphic + classID: 224 + script: {fileID: 0} m_PPtrCurves: - curve: - time: 0 @@ -39,6 +58,13 @@ AnimationClip: typeID: 114 customType: 0 isPPtrCurve: 1 + - serializedVersion: 2 + path: 3003628726 + attribute: 538195251 + script: {fileID: 0} + typeID: 224 + customType: 28 + isPPtrCurve: 0 pptrCurveMapping: - {fileID: -1983818443, guid: 655fc978fc6e6ca41a3d3104b43298bd, type: 3} m_AnimationClipSettings: @@ -61,7 +87,26 @@ AnimationClip: m_KeepOriginalPositionXZ: 0 m_HeightFromFeet: 0 m_Mirror: 0 - m_EditorCurves: [] + m_EditorCurves: + - curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + attribute: m_AnchoredPosition.y + path: Graphic + classID: 224 + script: {fileID: 0} m_EulerEditorCurves: [] m_HasGenericRootTransform: 0 m_HasMotionFloatCurves: 0 diff --git a/Assets/Scenes/Editor.unity b/Assets/Scenes/Editor.unity index 56de6263..11eaddf0 100644 --- a/Assets/Scenes/Editor.unity +++ b/Assets/Scenes/Editor.unity @@ -10135,7 +10135,7 @@ RectTransform: m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 1} m_AnchorMax: {x: 0, y: 1} - m_AnchoredPosition: {x: 177.66986, y: -60.01} + m_AnchoredPosition: {x: 177.66988, y: -60.01} m_SizeDelta: {x: 42, y: 42} m_Pivot: {x: 0.5, y: 0.5} --- !u!114 &449176922 @@ -10986,7 +10986,7 @@ MonoBehaviour: m_TargetGraphic: {fileID: 171581557} m_HandleRect: {fileID: 171581556} m_Direction: 2 - m_Value: 1 + m_Value: 0 m_Size: 1 m_NumberOfSteps: 0 m_OnValueChanged: @@ -18620,8 +18620,8 @@ RectTransform: m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 1} m_AnchorMax: {x: 0, y: 1} - m_AnchoredPosition: {x: 29, y: -29} - m_SizeDelta: {x: 48, y: 48} + m_AnchoredPosition: {x: 29.3, y: -29.3} + m_SizeDelta: {x: 48.6, y: 48.6} m_Pivot: {x: 0.5, y: 0.5} --- !u!114 &781200687 MonoBehaviour: @@ -20896,8 +20896,8 @@ MonoBehaviour: m_TargetGraphic: {fileID: 1589389272} m_HandleRect: {fileID: 1589389271} m_Direction: 2 - m_Value: 0 - m_Size: 0.9999943 + m_Value: 1 + m_Size: 0.9999938 m_NumberOfSteps: 0 m_OnValueChanged: m_PersistentCalls: @@ -24751,6 +24751,82 @@ CanvasRenderer: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1128012797} m_CullTransparentMesh: 1 +--- !u!1 &1134629697 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1134629698} + - component: {fileID: 1134629700} + - component: {fileID: 1134629699} + m_Layer: 5 + m_Name: Image + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1134629698 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1134629697} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1806429019} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1134629699 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1134629697} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 21300000, guid: f9232c079e126cd48a7344b23eaf42a5, type: 3} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &1134629700 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1134629697} + m_CullTransparentMesh: 1 --- !u!1 &1144123704 GameObject: m_ObjectHideFlags: 0 @@ -25465,7 +25541,7 @@ RectTransform: m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0.5} m_AnchorMax: {x: 1, y: 0.5} - m_AnchoredPosition: {x: 0, y: 125.591866} + m_AnchoredPosition: {x: 0, y: 162.32596} m_SizeDelta: {x: 0, y: 0} m_Pivot: {x: 0.5, y: 1} --- !u!222 &1154875945 @@ -34511,8 +34587,8 @@ MonoBehaviour: m_TargetGraphic: {fileID: 1220118245} m_HandleRect: {fileID: 1220118244} m_Direction: 2 - m_Value: 1.0000002 - m_Size: 0.6423325 + m_Value: 1.0000017 + m_Size: 0.9467054 m_NumberOfSteps: 0 m_OnValueChanged: m_PersistentCalls: @@ -37731,6 +37807,57 @@ CanvasRenderer: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1800461596} m_CullTransparentMesh: 1 +--- !u!1 &1806429018 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1806429019} + - component: {fileID: 1806429020} + m_Layer: 5 + m_Name: BlockDeleteFXTemplate + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 0 +--- !u!224 &1806429019 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1806429018} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 1134629698} + m_Father: {fileID: 1838356727} + m_RootOrder: 3 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 91.4, y: 50.84} + m_Pivot: {x: 0, y: 1} +--- !u!114 &1806429020 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1806429018} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d7f2c4dbc99f13d4eac41ff79ee2844e, type: 3} + m_Name: + m_EditorClassIdentifier: + mainImage: {fileID: 1134629699} --- !u!1 &1813644963 GameObject: m_ObjectHideFlags: 0 @@ -38026,6 +38153,7 @@ RectTransform: - {fileID: 743531236} - {fileID: 2142375787} - {fileID: 1962968340} + - {fileID: 1806429019} m_Father: {fileID: 259713290} m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} @@ -38268,6 +38396,7 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: EntityTemplate: {fileID: 798021450} + BlockDeleteFXTemplate: {fileID: 1806429020} --- !u!1 &1863600390 GameObject: m_ObjectHideFlags: 0 diff --git a/Assets/Scripts/LevelEditor/BoxSelection.cs b/Assets/Scripts/LevelEditor/BoxSelection.cs index 1a336c96..f1c4fe65 100644 --- a/Assets/Scripts/LevelEditor/BoxSelection.cs +++ b/Assets/Scripts/LevelEditor/BoxSelection.cs @@ -107,6 +107,20 @@ namespace HeavenStudio.Editor else sizeText.text = string.Empty; + // Keeps the text always in view + var sizeTextLeft = Timeline.instance.leftSide - start.x; + sizeTextLeft = Mathf.Max(sizeTextLeft, 0); + var sizeTextRight = -(Timeline.instance.rightSide - end.x); + sizeTextRight = Mathf.Max(sizeTextRight, 0); + + var sizeTextTop = Timeline.instance.topSide - start.y; + sizeTextTop = Mathf.Max(sizeTextTop, 0); + var sizeTextBottom = -(Timeline.instance.bottomSide - end.y); + sizeTextBottom = Mathf.Max(sizeTextBottom, 0); + + 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); } diff --git a/Assets/Scripts/LevelEditor/Commands/Block.cs b/Assets/Scripts/LevelEditor/Commands/Block.cs index bd56facd..9d88673a 100644 --- a/Assets/Scripts/LevelEditor/Commands/Block.cs +++ b/Assets/Scripts/LevelEditor/Commands/Block.cs @@ -37,10 +37,11 @@ namespace HeavenStudio.Editor.Commands var marker = TimelineBlockManager.Instance.EntityMarkers[entity.guid]; var clonedEntity = entity.DeepCopy(); - clonedEntity.guid = entity.guid; // We have to do this because entities (as of when I'm typing this), do not have Guids. + clonedEntity.guid = entity.guid; deletedEntities.Add(new() { riqEntity = clonedEntity, selected = marker.selected }); + TimelineBlockManager.Instance.CreateDestroyFX(entity); Selections.instance.Deselect(marker); @@ -107,15 +108,16 @@ namespace HeavenStudio.Editor.Commands { placedEntityData = createdEntity.DeepCopy(); - var marker = TimelineBlockManager.Instance.EntityMarkers[createdEntity.guid]; + if (TimelineBlockManager.Instance.EntityMarkers.ContainsKey(createdEntity.guid)) + { + var marker = TimelineBlockManager.Instance.EntityMarkers[createdEntity.guid]; + Selections.instance.Deselect(marker); - Selections.instance.Deselect(marker); + TimelineBlockManager.Instance.EntityMarkers.Remove(createdEntity.guid); + GameObject.Destroy(marker.gameObject); + } GameManager.instance.Beatmap.Entities.Remove(createdEntity); - - TimelineBlockManager.Instance.EntityMarkers.Remove(createdEntity.guid); - GameObject.Destroy(marker.gameObject); - GameManager.instance.SortEventsList(); } } diff --git a/Assets/Scripts/LevelEditor/Theme.cs b/Assets/Scripts/LevelEditor/Theme.cs index 34b1c55e..f34d47d6 100644 --- a/Assets/Scripts/LevelEditor/Theme.cs +++ b/Assets/Scripts/LevelEditor/Theme.cs @@ -1,3 +1,4 @@ +using HeavenStudio.Editor.Track; using Newtonsoft.Json; using Starpelly; using System; @@ -55,5 +56,10 @@ namespace HeavenStudio.Editor LayersGradient.colorKeys = colorKeys.ToArray(); } + + public Color LayerGradientIndex(int layer) + { + return EditorTheme.theme.LayersGradient.Evaluate(layer / (float)(Timeline.instance.LayerCount - 1)); + } } } \ No newline at end of file diff --git a/Assets/Scripts/LevelEditor/Timeline/BlockDeleteFX.cs b/Assets/Scripts/LevelEditor/Timeline/BlockDeleteFX.cs new file mode 100644 index 00000000..fa48b85f --- /dev/null +++ b/Assets/Scripts/LevelEditor/Timeline/BlockDeleteFX.cs @@ -0,0 +1,62 @@ +using HeavenStudio.Util; +using UnityEngine; +using UnityEngine.UI; +using static UnityEditor.Experimental.GraphView.GraphView; + +namespace HeavenStudio.Editor.Track +{ + public class BlockDeleteFX : MonoBehaviour + { + private RectTransform rectTransform; + + [SerializeField] + private Image mainImage; + + private bool started = false; + private float deleteTime = 0.0f; + + private double eBeat; + private float eLength; + private int eLayer; + private bool wasESelected = false; + + public void Awake() + { + rectTransform = GetComponent(); + } + + public void Create(double beat, float length, int layer, bool selected) + { + started = true; + deleteTime = Time.time; + + eBeat = beat; + eLength = length; + eLayer = layer; + wasESelected = selected; + + Destroy(this.gameObject, 0.714f); + + Update(); + } + + private void Update() + { + 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)); + + var extrudeAnim = EasingFunction.EaseOutCirc(0.0f, 8.0f, norm); + mainImage.rectTransform.sizeDelta = new Vector2(extrudeAnim, extrudeAnim); + } + } +} \ No newline at end of file diff --git a/Assets/Scripts/LevelEditor/Timeline/BlockDeleteFX.cs.meta b/Assets/Scripts/LevelEditor/Timeline/BlockDeleteFX.cs.meta new file mode 100644 index 00000000..67f2af71 --- /dev/null +++ b/Assets/Scripts/LevelEditor/Timeline/BlockDeleteFX.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d7f2c4dbc99f13d4eac41ff79ee2844e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/LevelEditor/Timeline/Timeline.cs b/Assets/Scripts/LevelEditor/Timeline/Timeline.cs index 8cf32f91..5986c3db 100644 --- a/Assets/Scripts/LevelEditor/Timeline/Timeline.cs +++ b/Assets/Scripts/LevelEditor/Timeline/Timeline.cs @@ -182,9 +182,14 @@ namespace HeavenStudio.Editor.Track public Vector3[] LayerCorners = new Vector3[4]; + // Beats public float leftSide => (RealTimelineContent.anchoredPosition.x / PixelsPerBeat) * -1; public float rightSide => (TimelineScroll.viewport.rect.width / PixelsPerBeat) + leftSide; + // Layer Height + public float topSide => RealTimelineContent.anchoredPosition.y / LayerHeight(); + public float bottomSide => topSide + (TimelineScroll.viewport.rect.height / LayerHeight()); + private Vector2 lastScreenSize; public static Timeline instance { get; private set; } diff --git a/Assets/Scripts/LevelEditor/Timeline/TimelineBlockManager.cs b/Assets/Scripts/LevelEditor/Timeline/TimelineBlockManager.cs index 5b5afe74..023c9918 100644 --- a/Assets/Scripts/LevelEditor/Timeline/TimelineBlockManager.cs +++ b/Assets/Scripts/LevelEditor/Timeline/TimelineBlockManager.cs @@ -5,6 +5,7 @@ using UnityEngine.Pool; using Jukebox; using System.Linq; +using static Jukebox.Legacy.Beatmap; namespace HeavenStudio.Editor.Track { @@ -13,6 +14,7 @@ namespace HeavenStudio.Editor.Track public static TimelineBlockManager Instance { get; private set; } public TimelineEventObj EntityTemplate; + public BlockDeleteFX BlockDeleteFXTemplate; public Dictionary EntityMarkers = new(); public ObjectPool Pool { get; private set; } @@ -186,5 +188,22 @@ namespace HeavenStudio.Editor.Track { 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); + } } } \ No newline at end of file diff --git a/Assets/Scripts/LevelEditor/Timeline/TimelineEventObj.cs b/Assets/Scripts/LevelEditor/Timeline/TimelineEventObj.cs index 6065ff9c..028327f0 100644 --- a/Assets/Scripts/LevelEditor/Timeline/TimelineEventObj.cs +++ b/Assets/Scripts/LevelEditor/Timeline/TimelineEventObj.cs @@ -6,6 +6,7 @@ using Jukebox; using TMPro; using System.Linq; using System.Collections.Generic; +using UnityEngine.Timeline; namespace HeavenStudio.Editor.Track { @@ -148,8 +149,11 @@ namespace HeavenStudio.Editor.Track if (selected) { - if (moving) + if (TimelineBlockManager.Instance.MovingAnyEvents) + { outline.color = Color.magenta; + SetColor((int)entity["track"]); + } else outline.color = Color.cyan; } @@ -200,6 +204,7 @@ namespace HeavenStudio.Editor.Track if (!isCreating && movedEntity) { + // NOTE (PELLY): Replace with arrays soon List lastBeats = new(); List lastLayers = new(); foreach (var marker in Selections.instance.eventsSelected) @@ -318,7 +323,8 @@ namespace HeavenStudio.Editor.Track if (Input.GetMouseButton(1) || Input.GetMouseButton(2)) return; if (!moving) - altWhenClicked = Input.GetKey(KeyCode.LeftAlt); + if (!altWhenClicked) + altWhenClicked = Input.GetKey(KeyCode.LeftAlt); if (!altWhenClicked) { @@ -500,7 +506,7 @@ namespace HeavenStudio.Editor.Track public void SetColor(int type) { - var c = EditorTheme.theme.LayersGradient.Evaluate(type / (float)(Timeline.instance.LayerCount - 1)); + var c = EditorTheme.theme.LayerGradientIndex(type); transform.GetChild(0).GetComponent().color = c; if (resizable)