diff --git a/fluXis.Import.osu/Storyboards/OsuStoryboardParser.cs b/fluXis.Import.osu/Storyboards/OsuStoryboardParser.cs index 0400d029a..3d8f54583 100644 --- a/fluXis.Import.osu/Storyboards/OsuStoryboardParser.cs +++ b/fluXis.Import.osu/Storyboards/OsuStoryboardParser.cs @@ -71,8 +71,8 @@ public Storyboard Parse(string data) toAdd.Add(new StoryboardAnimation(element) { Type = animation.Type, - ValueStart = animation.ValueStart, - ValueEnd = animation.ValueStart + StartValue = animation.StartValue, + ValueEnd = animation.StartValue }); } @@ -214,7 +214,7 @@ private void parseLine(string line) StartTime = startTime, Duration = duration, Easing = easing, - ValueStart = start.ToStringInvariant(), + StartValue = start.ToStringInvariant(), ValueEnd = end.ToStringInvariant() } }; @@ -235,7 +235,7 @@ private void parseLine(string line) StartTime = startTime, Duration = duration, Easing = easing, - ValueStart = start.ToStringInvariant(), + StartValue = start.ToStringInvariant(), ValueEnd = end.ToStringInvariant() } }; @@ -258,7 +258,7 @@ private void parseLine(string line) StartTime = startTime, Duration = duration, Easing = easing, - ValueStart = $"{startX},{startY}", + StartValue = $"{startX},{startY}", ValueEnd = $"{endX},{endY}" } }; @@ -282,7 +282,7 @@ private void parseLine(string line) StartTime = startTime, Duration = duration, Easing = easing, - ValueStart = startDeg.ToStringInvariant(), + StartValue = startDeg.ToStringInvariant(), ValueEnd = endDeg.ToStringInvariant() } }; @@ -305,7 +305,7 @@ private void parseLine(string line) StartTime = startTime, Duration = duration, Easing = easing, - ValueStart = startX.ToStringInvariant(), + StartValue = startX.ToStringInvariant(), ValueEnd = endX.ToStringInvariant() }, new StoryboardAnimation(currentElement) @@ -314,7 +314,7 @@ private void parseLine(string line) StartTime = startTime, Duration = duration, Easing = easing, - ValueStart = startY.ToStringInvariant(), + StartValue = startY.ToStringInvariant(), ValueEnd = endY.ToStringInvariant() } }; @@ -335,7 +335,7 @@ private void parseLine(string line) StartTime = startTime, Duration = duration, Easing = easing, - ValueStart = start.ToStringInvariant(), + StartValue = start.ToStringInvariant(), ValueEnd = end.ToStringInvariant() } }; @@ -356,7 +356,7 @@ private void parseLine(string line) StartTime = startTime, Duration = duration, Easing = easing, - ValueStart = start.ToStringInvariant(), + StartValue = start.ToStringInvariant(), ValueEnd = end.ToStringInvariant() } }; @@ -384,7 +384,7 @@ private void parseLine(string line) StartTime = startTime, Duration = duration, Easing = easing, - ValueStart = hexStart, + StartValue = hexStart, ValueEnd = hexEnd } }; diff --git a/fluXis/Map/Structures/Bases/IHasStartValue.cs b/fluXis/Map/Structures/Bases/IHasStartValue.cs new file mode 100644 index 000000000..6b8b5d91e --- /dev/null +++ b/fluXis/Map/Structures/Bases/IHasStartValue.cs @@ -0,0 +1,7 @@ +namespace fluXis.Map.Structures.Bases; + +public interface IHasStartValue +{ + T StartValue { get; set; } + bool UseStartValue { get; set; } +} diff --git a/fluXis/Map/Structures/Events/Scrolling/TimeOffsetEvent.cs b/fluXis/Map/Structures/Events/Scrolling/TimeOffsetEvent.cs index 696aac426..919b2e1b2 100644 --- a/fluXis/Map/Structures/Events/Scrolling/TimeOffsetEvent.cs +++ b/fluXis/Map/Structures/Events/Scrolling/TimeOffsetEvent.cs @@ -6,7 +6,7 @@ namespace fluXis.Map.Structures.Events.Scrolling; -public class TimeOffsetEvent : IMapEvent, IHasDuration, IHasEasing, IApplicableToHitManager +public class TimeOffsetEvent : IMapEvent, IHasDuration, IHasEasing, IHasStartValue, IApplicableToHitManager { [JsonProperty("time")] public double Time { get; set; } @@ -23,6 +23,12 @@ public class TimeOffsetEvent : IMapEvent, IHasDuration, IHasEasing, IApplicableT [JsonProperty("start-offset")] public double StartOffset { get; set; } + public double StartValue + { + get => StartOffset; + set => StartOffset = value; + } + [JsonProperty("offset")] public double TargetOffset { get; set; } diff --git a/fluXis/Map/Structures/Events/ShaderEvent.cs b/fluXis/Map/Structures/Events/ShaderEvent.cs index 5b49b241b..4970a3114 100644 --- a/fluXis/Map/Structures/Events/ShaderEvent.cs +++ b/fluXis/Map/Structures/Events/ShaderEvent.cs @@ -9,7 +9,7 @@ namespace fluXis.Map.Structures.Events; -public class ShaderEvent : IMapEvent, IHasDuration, IHasEasing +public class ShaderEvent : IMapEvent, IHasDuration, IHasEasing, IHasStartValue { [JsonProperty("time")] public double Time { get; set; } @@ -40,11 +40,17 @@ public string ShaderName public Easing Easing { get; set; } [JsonProperty("use-start")] - public bool UseStartParams { get; set; } + public bool UseStartValue { get; set; } [JsonProperty("start-params")] public ShaderParameters StartParameters { get; set; } = new(); + public ShaderParameters StartValue + { + get => StartParameters; + set => StartParameters = value; + } + [JsonProperty("end-params")] public ShaderParameters EndParameters { get; set; } = new(); @@ -97,7 +103,7 @@ public void Apply(ShaderTransformHandler shader) { using (shader.BeginAbsoluteSequence(Time)) { - if (UseStartParams) + if (UseStartValue) { shader.StrengthTo(StartParameters.Strength); shader.Strength2To(StartParameters.Strength2); diff --git a/fluXis/Screens/Edit/Tabs/Design/DesignShaderHandler.cs b/fluXis/Screens/Edit/Tabs/Design/DesignShaderHandler.cs index abbf230e3..b7ac1764c 100644 --- a/fluXis/Screens/Edit/Tabs/Design/DesignShaderHandler.cs +++ b/fluXis/Screens/Edit/Tabs/Design/DesignShaderHandler.cs @@ -62,9 +62,9 @@ private void handleGroup(ShaderType type, IEnumerable events) } var previous = events.LastOrDefault(e => e.Time < current.Time); - var startStrength = current.UseStartParams ? current.StartParameters.Strength : previous?.EndParameters.Strength ?? 0; - var startStrength2 = current.UseStartParams ? current.StartParameters.Strength2 : previous?.EndParameters.Strength2 ?? 0; - var startStrength3 = current.UseStartParams ? current.StartParameters.Strength3 : previous?.EndParameters.Strength3 ?? 0; + var startStrength = current.UseStartValue ? current.StartParameters.Strength : previous?.EndParameters.Strength ?? 0; + var startStrength2 = current.UseStartValue ? current.StartParameters.Strength2 : previous?.EndParameters.Strength2 ?? 0; + var startStrength3 = current.UseStartValue ? current.StartParameters.Strength3 : previous?.EndParameters.Strength3 ?? 0; if (progress < 0) { diff --git a/fluXis/Screens/Edit/Tabs/Design/Points/Entries/ShaderEntry.cs b/fluXis/Screens/Edit/Tabs/Design/Points/Entries/ShaderEntry.cs index e7635d18a..8d3a27853 100644 --- a/fluXis/Screens/Edit/Tabs/Design/Points/Entries/ShaderEntry.cs +++ b/fluXis/Screens/Edit/Tabs/Design/Points/Entries/ShaderEntry.cs @@ -33,7 +33,7 @@ protected override Drawable[] CreateValueContent() { var text = $"{shader.ShaderName} {(int)shader.Duration}ms ("; - if (shader.UseStartParams) + if (shader.UseStartValue) text += $"{shader.StartParameters.Strength} > "; text += $"{shader.EndParameters.Strength})"; @@ -54,10 +54,10 @@ protected override IEnumerable CreateSettings() { Text = "Use Start Value", TooltipText = "Enables whether start values should be used.", - Bindable = new Bindable(shader.UseStartParams), + Bindable = new Bindable(shader.UseStartValue), OnValueChanged = enabled => { - shader.UseStartParams = enabled; + shader.UseStartValue = enabled; Map.Update(shader); } }; diff --git a/fluXis/Screens/Edit/Tabs/Storyboarding/Animations/StoryboardAnimationEntry.cs b/fluXis/Screens/Edit/Tabs/Storyboarding/Animations/StoryboardAnimationEntry.cs index c349ca8d6..f55a524c0 100644 --- a/fluXis/Screens/Edit/Tabs/Storyboarding/Animations/StoryboardAnimationEntry.cs +++ b/fluXis/Screens/Edit/Tabs/Storyboarding/Animations/StoryboardAnimationEntry.cs @@ -44,11 +44,15 @@ public partial class StoryboardAnimationEntry : CompositeDrawable, IHasPopover private readonly OutlinedCircle outlineLength; private readonly FluXisSpriteIcon outlineDiamond; + protected Bindable UseStartValueBindable; + public StoryboardAnimationEntry(StoryboardAnimation animation, StoryboardAnimationRow row, Colour4 color) { Animation = animation; this.row = row; + UseStartValueBindable = new Bindable(Animation.UseStartValue); + Anchor = Anchor.CentreLeft; Origin = Anchor.Centre; @@ -140,20 +144,32 @@ protected override bool OnClick(ClickEvent e) new EditorVariableTitle(Animation.Type.GetDescription(), () => RequestRemove?.Invoke(Animation), false), new EditorVariableTime(map, Animation, () => row.Item.StartTime), new EditorVariableLength(map, Animation, beatLength), + new EditorVariableToggle() + { + Text = "Use Start Value", + TooltipText = "Enables whether start values should be used.", + Bindable = UseStartValueBindable, + OnValueChanged = enabled => + { + Animation.UseStartValue = enabled; + map.Update(Animation); + } + }, new EditorVariableTextBox { Text = "Start Value", - CurrentValue = Animation.ValueStart, + CurrentValue = Animation.StartValue, + Enabled = UseStartValueBindable, OnValueChanged = t => { - if (validate(t.Text, out var parsed)) Animation.ValueStart = parsed; + if (validate(t.Text, out var parsed)) Animation.StartValue = parsed; else t.NotifyError(); map.Update(Animation); }, OnCommit = t => { if (t is not null && validate(t.Text, out var parsed)) t.Text = parsed; - else { t.Text = Animation.ValueStart; t.NotifyError(); } + else { t.Text = Animation.StartValue; t.NotifyError(); } } }, new EditorVariableTextBox diff --git a/fluXis/Screens/Edit/Tabs/Storyboarding/Animations/StoryboardAnimationRow.cs b/fluXis/Screens/Edit/Tabs/Storyboarding/Animations/StoryboardAnimationRow.cs index 3400b3f9f..4f1bd902a 100644 --- a/fluXis/Screens/Edit/Tabs/Storyboarding/Animations/StoryboardAnimationRow.cs +++ b/fluXis/Screens/Edit/Tabs/Storyboarding/Animations/StoryboardAnimationRow.cs @@ -94,7 +94,8 @@ private void addNew() var animation = new StoryboardAnimation(Item) { StartTime = clock.CurrentTime - Item.StartTime, - ValueStart = getDefault(type), + UseStartValue = false, + StartValue = getDefault(type), ValueEnd = getDefault(type), Type = type }; diff --git a/fluXis/Scripting/Models/Storyboarding/LuaStoryboardAnimation.cs b/fluXis/Scripting/Models/Storyboarding/LuaStoryboardAnimation.cs index 4c6543fc7..2134b1868 100644 --- a/fluXis/Scripting/Models/Storyboarding/LuaStoryboardAnimation.cs +++ b/fluXis/Scripting/Models/Storyboarding/LuaStoryboardAnimation.cs @@ -23,6 +23,9 @@ public LuaStoryboardAnimation(LuaStoryboardElement parentElement) [LuaMember(Name = "type")] public StoryboardAnimationType Type { get; set; } + [LuaMember(Name = "useStartValue")] + public bool UseStartValue { get; set; } = true; + [LuaMember(Name = "start")] public string Start { get; set; } @@ -41,7 +44,8 @@ public LuaStoryboardAnimation(LuaStoryboardElement parentElement) Duration = Duration, Easing = Easing, Type = Type, - ValueStart = Start, + UseStartValue = UseStartValue, + StartValue = Start, ValueEnd = End }; } diff --git a/fluXis/Scripting/Models/Storyboarding/LuaStoryboardElement.cs b/fluXis/Scripting/Models/Storyboarding/LuaStoryboardElement.cs index f59de15e7..92c080e49 100644 --- a/fluXis/Scripting/Models/Storyboarding/LuaStoryboardElement.cs +++ b/fluXis/Scripting/Models/Storyboarding/LuaStoryboardElement.cs @@ -60,6 +60,7 @@ public class LuaStoryboardElement : ILuaModel [LuaHide] public Dictionary ExtraParameters { get; set; } = new(); +#nullable enable /// /// applies a new animation to this element /// @@ -70,16 +71,18 @@ public class LuaStoryboardElement : ILuaModel /// the value this animation ends with (input based on type) /// the easing function used for this animation [LuaMember(Name = "animate")] - public void AddAnimation([LuaCustomType(typeof(StoryboardAnimationType))] string type, float time, float len, string startVal, string endVal, [LuaCustomType(typeof(Easing))] string ease) => + public void AddAnimation([LuaCustomType(typeof(StoryboardAnimationType))] string type, float time, float len, string? startVal, string endVal, [LuaCustomType(typeof(Easing))] string ease) => Animations.Add(new LuaStoryboardAnimation(this) { StartTime = time, Duration = len, Easing = Enum.TryParse(ease, out var easing) ? easing : Easing.None, Type = Enum.Parse(type), - Start = startVal, - End = endVal + UseStartValue = startVal != null, + Start = startVal ?? "", + End = endVal, }); +#nullable restore [LuaMember(Name = "param")] public object GetParameter(string key, object fallback) diff --git a/fluXis/Storyboards/Drawables/DrawableStoryboardElement.cs b/fluXis/Storyboards/Drawables/DrawableStoryboardElement.cs index c0afc2b59..4c398771b 100644 --- a/fluXis/Storyboards/Drawables/DrawableStoryboardElement.cs +++ b/fluXis/Storyboards/Drawables/DrawableStoryboardElement.cs @@ -40,60 +40,58 @@ private void load() using (BeginAbsoluteSequence(Element.StartTime + animation.StartTime)) { var duration = Math.Max(animation.Duration, 0); + var useStart = animation.UseStartValue; switch (animation.Type) { case StoryboardAnimationType.MoveX: - this.MoveToX(animation.StartFloat).Then() - .MoveToX(animation.EndFloat, duration, animation.Easing); + if (useStart) this.MoveToX(animation.StartFloat); + this.MoveToX(animation.EndFloat, duration, animation.Easing); break; case StoryboardAnimationType.MoveY: - this.MoveToY(animation.StartFloat).Then() - .MoveToY(animation.EndFloat, duration, animation.Easing); + if (useStart) this.MoveToY(animation.StartFloat); + this.MoveToY(animation.EndFloat, duration, animation.Easing); break; case StoryboardAnimationType.Scale: - this.ScaleTo(animation.StartFloat).Then() - .ScaleTo(animation.EndFloat, duration, animation.Easing); + if (useStart) this.ScaleTo(animation.StartFloat); + this.ScaleTo(animation.EndFloat, duration, animation.Easing); break; case StoryboardAnimationType.ScaleVector: - this.ScaleTo(animation.StartVector).Then() - .ScaleTo(animation.EndVector, duration, animation.Easing); + if (useStart) this.ScaleTo(animation.StartVector); + this.ScaleTo(animation.EndVector, duration, animation.Easing); break; case StoryboardAnimationType.Width: - this.ResizeWidthTo(animation.StartFloat).Then() - .ResizeWidthTo(animation.EndFloat, duration, animation.Easing); + if (useStart) this.ResizeWidthTo(animation.StartFloat); + this.ResizeWidthTo(animation.EndFloat, duration, animation.Easing); break; case StoryboardAnimationType.Height: - this.ResizeHeightTo(animation.StartFloat).Then() - .ResizeHeightTo(animation.EndFloat, duration, animation.Easing); + if (useStart) this.ResizeHeightTo(animation.StartFloat); + this.ResizeHeightTo(animation.EndFloat, duration, animation.Easing); break; case StoryboardAnimationType.Rotate: - this.RotateTo(animation.StartFloat).Then() - .RotateTo(animation.EndFloat, duration, animation.Easing); + if (useStart) this.RotateTo(animation.StartFloat); + this.RotateTo(animation.EndFloat, duration, animation.Easing); break; case StoryboardAnimationType.Fade: - this.FadeTo(animation.StartFloat).Then() - .FadeTo(animation.EndFloat, duration, animation.Easing); + if (useStart) this.FadeTo(animation.StartFloat); + this.FadeTo(animation.EndFloat, duration, animation.Easing); break; case StoryboardAnimationType.Color: - var startColour = Colour4.FromHex(animation.ValueStart); - var endColour = Colour4.FromHex(animation.ValueEnd); - - this.FadeColour(startColour).Then() - .FadeColour(endColour, duration, animation.Easing); + if (useStart) this.FadeColour(Colour4.FromHex(animation.StartValue)); + this.FadeColour(Colour4.FromHex(animation.ValueEnd), duration, animation.Easing); break; case StoryboardAnimationType.Border when AllowBorder: - this.BorderTo(animation.StartFloat).Then() - .BorderTo(animation.EndFloat, duration, animation.Easing); + if (useStart) this.BorderTo(animation.StartFloat); + this.BorderTo(animation.EndFloat, duration, animation.Easing); break; } } diff --git a/fluXis/Storyboards/StoryboardAnimation.cs b/fluXis/Storyboards/StoryboardAnimation.cs index 754c96328..a2d006f77 100644 --- a/fluXis/Storyboards/StoryboardAnimation.cs +++ b/fluXis/Storyboards/StoryboardAnimation.cs @@ -8,7 +8,7 @@ namespace fluXis.Storyboards; -public class StoryboardAnimation : ITimedObject, IHasDuration, IHasEasing, IDeepCloneable +public class StoryboardAnimation : ITimedObject, IHasDuration, IHasEasing, IHasStartValue, IDeepCloneable { public StoryboardAnimation(StoryboardElement parentElement) { @@ -36,6 +36,12 @@ public StoryboardAnimation(StoryboardElement parentElement) [JsonProperty("easing")] public Easing Easing { get; set; } + /// + /// Whether to override the start value + /// + [JsonProperty("use-start", DefaultValueHandling = DefaultValueHandling.Ignore)] + public bool UseStartValue { get; set; } = true; + /// /// The type of the animation. /// @@ -46,7 +52,7 @@ public StoryboardAnimation(StoryboardElement parentElement) /// The start value of the animation. /// [JsonProperty("start-value")] - public string ValueStart { get; set; } + public string StartValue { get; set; } /// /// The end value of the animation. @@ -55,7 +61,7 @@ public StoryboardAnimation(StoryboardElement parentElement) public string ValueEnd { get; set; } [JsonIgnore] - public float StartFloat => ValueStart.ToFloatInvariant(); + public float StartFloat => StartValue.ToFloatInvariant(); [JsonIgnore] public float EndFloat => ValueEnd.ToFloatInvariant(); @@ -65,7 +71,7 @@ public Vector2 StartVector { get { - var xy = ValueStart.Split(','); + var xy = StartValue.Split(','); return new Vector2(xy[0].ToFloatInvariant(), xy[1].ToFloatInvariant()); } } @@ -89,7 +95,7 @@ public Vector2 EndVector Duration = Duration, Easing = Easing, Type = Type, - ValueStart = ValueStart, + StartValue = StartValue, ValueEnd = ValueEnd }; diff --git a/scripting/library/events.lua b/scripting/library/events.lua index 1a47dfa8e..778029775 100644 --- a/scripting/library/events.lua +++ b/scripting/library/events.lua @@ -75,7 +75,7 @@ PulseEvent = {} ---@field shaderName string ---@field duration number ---@field easing number ----@field useStartParams boolean +---@field useStartValue boolean ---@field startParameters string ---@field endParameters string ---@field parameters string