Skip to content

Commit

Permalink
add InterpolatableSoflan
Browse files Browse the repository at this point in the history
  • Loading branch information
MikiraSora committed Dec 21, 2023
1 parent e90922a commit 4c19865
Show file tree
Hide file tree
Showing 19 changed files with 446 additions and 15 deletions.
14 changes: 14 additions & 0 deletions OngekiFumenEditor/AppBootstrapper.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using Caliburn.Micro;
using Gemini.Framework.Services;
using Gemini.Modules.Output;
using OngekiFumenEditor.Base;
using OngekiFumenEditor.Base.Collections;
using OngekiFumenEditor.Base.EditorObjects;
using OngekiFumenEditor.Base.OngekiObjects;
using OngekiFumenEditor.Kernel.ArgProcesser;
using OngekiFumenEditor.Kernel.Audio;
Expand Down Expand Up @@ -180,6 +182,18 @@ protected async override void OnStartup(object sender, StartupEventArgs e)
window.AllowDrop = true;
window.Drop += MainWindow_Drop;
}

var soflan = new InterpolatableSoflan()
{
Speed = 1,
TGrid = new TGrid(1, 0),
EndTGrid = new TGrid(2, 0),
};

(soflan.EndIndicator as InterpolatableSoflan.InterpolatableSoflanIndicator).Speed = 2;
soflan.Easing = EasingTypes.None;

var s = soflan.GetInterpolatedSoflans().ToArray();
}

private async void MainWindow_Drop(object sender, DragEventArgs e)
Expand Down
3 changes: 3 additions & 0 deletions OngekiFumenEditor/Base/Collections/SoflanList.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using OngekiFumenEditor.Base.Collections.Base;
using OngekiFumenEditor.Base.EditorObjects;
using OngekiFumenEditor.Base.OngekiObjects;
using System;
using System.Collections;
Expand Down Expand Up @@ -57,6 +58,8 @@ private void OnSoflanPropChanged(object sender, PropertyChangedEventArgs e)
case nameof(TGrid.Grid):
case nameof(TGrid.Unit):
case nameof(Soflan.ApplySpeedInDesignMode):
case nameof(InterpolatableSoflan.Easing):
case nameof(InterpolatableSoflan.InterpolateCountPerResT):
case nameof(Soflan.EndTGrid):
case nameof(Soflan.GridLength):
OnChangedEvent?.Invoke();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using IntervalTree;
using OngekiFumenEditor.Base.EditorObjects;
using OngekiFumenEditor.Base.OngekiObjects;
using OngekiFumenEditor.Utils;
using OngekiFumenEditor.Utils.ObjectPool;
Expand Down Expand Up @@ -73,7 +74,11 @@ public enum ChgEvt
break;
}
}
var r = this.AsEnumerable<ITimelineObject>().Concat(bpmList)
var r = this.SelectMany(x => x switch
{
InterpolatableSoflan s => s.GetInterpolatedSoflans(),
_ => new[] { x }
}).AsEnumerable<ITimelineObject>().Concat(bpmList)
.OrderBy(x => x.TGrid)
.SelectMany(GetEventTimings)
.GroupBy(x => x.TGrid)
Expand Down Expand Up @@ -496,6 +501,15 @@ 5. 完成
//尽量合并得到的VisibleTGridRange
return TryMerge(_internal());
}

public double CalculateSpeed(TGrid t)
{
var soflan = GetVisibleStartObjects(t, t).FirstOrDefault();

if (soflan is InterpolatableSoflan isf)
return isf.CalculateSpeed(t);
return soflan?.Speed ?? 1;
}
}

#endregion
Expand Down
170 changes: 170 additions & 0 deletions OngekiFumenEditor/Base/EditorObjects/InterpolatableSoflan.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
using OngekiFumenEditor.Base.OngekiObjects;
using OngekiFumenEditor.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;

namespace OngekiFumenEditor.Base.EditorObjects
{
public class InterpolatableSoflan : Soflan
{
public override string IDShortName => "[INTP_SFL]";

public class InterpolatableSoflanIndicator : SoflanEndIndicator
{
private float speed = 1;
public float Speed
{
get => speed;
set => Set(ref speed, value);
}

public override string IDShortName => "[INTP_SFL_End]";

public override void Copy(OngekiObjectBase from)
{
base.Copy(from);

if (from is not InterpolatableSoflanIndicator f)
return;
Speed = f.Speed;
}
}

public InterpolatableSoflan() : base()
{
EndIndicator = new InterpolatableSoflanIndicator() { RefSoflan = this };
EndIndicator.PropertyChanged += EndIndicator_PropertyChanged;
displayables = [this, EndIndicator];

Check failure on line 41 in OngekiFumenEditor/Base/EditorObjects/InterpolatableSoflan.cs

View workflow job for this annotation

GitHub Actions / build

Invalid expression term '['
}

private void EndIndicator_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
switch (e.PropertyName)
{
case nameof(Speed):
NotifyOfPropertyChange(nameof(Speed));
break;
case nameof(TGrid):
NotifyOfPropertyChange(nameof(EndTGrid));
break;
default:
NotifyOfPropertyChange(nameof(EndIndicator));
break;
}
}

public override void NotifyOfPropertyChange([CallerMemberName] string propertyName = null)
{
switch (propertyName)
{
case nameof(Speed):
case nameof(TGrid):
case nameof(InterpolateCountPerResT):
case nameof(EndTGrid):
case nameof(ApplySpeedInDesignMode):
case nameof(Easing):
cachedValid = false;
break;
default:
break;
}
base.NotifyOfPropertyChange(propertyName);
}

private EasingTypes easing = EasingTypes.None;
public EasingTypes Easing
{
get => easing;
set => Set(ref easing, value);
}

private int interpolateCountPerResT = 16;
public int InterpolateCountPerResT
{
get => interpolateCountPerResT;
set => Set(ref interpolateCountPerResT, value);
}

public override string ToString() => $"{base.ToString()} --> EndSpeed[{((InterpolatableSoflanIndicator)EndIndicator)?.Speed}x]";

public override void CopyEntire(Soflan from)
{
Copy(from);

Speed = from.Speed;
ApplySpeedInDesignMode = from.ApplySpeedInDesignMode;
EndIndicator.Copy(from.EndIndicator);

if (from is not InterpolatableSoflan s)
return;

Easing = s.Easing;
}

bool cachedValid = false;
List<Soflan> cachedInterpolatedSoflans = new();

public void UpdateCachedInterpolatedSoflans()
{
cachedInterpolatedSoflans.Clear();

var fromTotalGrid = TGrid.TotalGrid;
var toTotalGrid = EndTGrid.TotalGrid;

var fromSpeed = Speed;
var toSpeed = (EndIndicator as InterpolatableSoflanIndicator).Speed;

if (fromSpeed == toSpeed || fromTotalGrid == toTotalGrid)
{
cachedInterpolatedSoflans.Add(new Soflan()
{
EndTGrid = new TGrid(0, toTotalGrid),
TGrid = new TGrid(0, fromTotalGrid),
Speed = fromSpeed,
ApplySpeedInDesignMode = ApplySpeedInDesignMode
});
}
else
{
var stepGridLength = (int)(TGrid.DEFAULT_RES_T / InterpolateCountPerResT);

for (var curGrid = fromTotalGrid; curGrid < toTotalGrid; curGrid += stepGridLength)
{
var nextGrid = Math.Min(curGrid + stepGridLength, toTotalGrid);

var normalized = nextGrid == toTotalGrid ? 1 : (curGrid - fromTotalGrid) * 1.0d / (toTotalGrid - fromTotalGrid);
var transformed = (float)Interpolation.ApplyEasing(Easing, normalized);

var speed = fromSpeed + transformed * (toSpeed - fromSpeed);

cachedInterpolatedSoflans.Add(new Soflan()
{
EndTGrid = new TGrid(0, nextGrid),
TGrid = new TGrid(0, curGrid),
Speed = speed,
ApplySpeedInDesignMode = ApplySpeedInDesignMode
});
}
}
cachedValid = true;
}

public IReadOnlyList<Soflan> GetInterpolatedSoflans()
{
if (!cachedValid)
UpdateCachedInterpolatedSoflans();
return cachedInterpolatedSoflans;
}

public double CalculateSpeed(TGrid t)
{
var list = GetInterpolatedSoflans();
var r = list.LastOrDefaultByBinarySearch(t, x => x.TGrid);
return r.Speed;
}
}
}
8 changes: 4 additions & 4 deletions OngekiFumenEditor/Base/OngekiObjects/Soflan.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@ public override TGrid TGrid
public override string ToString() => $"{base.ToString()}";
}

private IDisplayableObject[] displayables;
protected IDisplayableObject[] displayables;

public Soflan()
{
EndIndicator = new SoflanEndIndicator() { RefSoflan = this };
EndIndicator.PropertyChanged += EndIndicator_PropertyChanged;
displayables = new IDisplayableObject[] { this, EndIndicator };
displayables = [this, EndIndicator];

Check failure on line 36 in OngekiFumenEditor/Base/OngekiObjects/Soflan.cs

View workflow job for this annotation

GitHub Actions / build

Invalid expression term '['
}

public override TGrid TGrid
Expand Down Expand Up @@ -62,7 +62,7 @@ private void EndIndicator_PropertyChanged(object sender, System.ComponentModel.P

public override string IDShortName => $"SFL";

public SoflanEndIndicator EndIndicator { get; }
public SoflanEndIndicator EndIndicator { get; protected set; }

public override IEnumerable<IDisplayableObject> GetDisplayableObjects() => displayables;

Expand Down Expand Up @@ -103,7 +103,7 @@ public override bool CheckVisiable(TGrid minVisibleTGrid, TGrid maxVisibleTGrid)
return true;
}

public void CopyEntire(Soflan from)
public virtual void CopyEntire(Soflan from)
{
Copy(from);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using OngekiFumenEditor.Base;
using OngekiFumenEditor.Base.EditorObjects;
using OngekiFumenEditor.Base.OngekiObjects;
using OngekiFumenEditor.Modules.FumenObjectPropertyBrowser.ViewModels;
using OngekiFumenEditor.UI.Controls.ObjectInspector.UIGenerator;
using OngekiFumenEditor.Utils;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Windows;

namespace OngekiFumenEditor.Modules.FumenObjectPropertyBrowser.UIGenerator.ObjectOperationImplement
{
[Export(typeof(IOngekiObjectOperationGenerator))]
public class InterpolatableSoflanOperationGenerator : IOngekiObjectOperationGenerator
{
public IEnumerable<Type> SupportOngekiTypes { get; } = new[] {
typeof(InterpolatableSoflan),
};

public UIElement Generate(OngekiObjectBase obj)
{
return ViewHelper.CreateViewByViewModelType(() => new InterpolatableSoflanOperationViewModel(obj as InterpolatableSoflan));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using Caliburn.Micro;
using Gemini.Modules.Toolbox;
using OngekiFumenEditor.Base.EditorObjects;
using OngekiFumenEditor.Base.OngekiObjects;
using OngekiFumenEditor.Modules.FumenVisualEditor.Base;
using OngekiFumenEditor.Modules.FumenVisualEditor.Base.DropActions;
using System;
using System.Linq;
using System.Windows;
using System.Windows.Input;

namespace OngekiFumenEditor.Modules.FumenObjectPropertyBrowser.ViewModels
{
public class InterpolatableSoflanOperationViewModel : PropertyChangedBase
{
private InterpolatableSoflan soflan;

public InterpolatableSoflanOperationViewModel(InterpolatableSoflan obj)
{
soflan = obj;
}

public void Interpolate(ActionExecutionContext e)
{
var list = soflan.GetInterpolatedSoflans().ToArray();
var editor = IoC.Get<IFumenObjectPropertyBrowser>().Editor;

if (editor == null)
return;

editor.UndoRedoManager.ExecuteAction(LambdaUndoAction.Create("插值生成Soflan物件", () =>
{
editor.Fumen.AddObjects(list);
editor.Fumen.RemoveObject(soflan);
}, () =>
{
editor.Fumen.AddObject(soflan);
editor.Fumen.RemoveObjects(list);
}));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
</UserControl.Resources>
<StackPanel Margin="21,5,0,0">
<ContentControl>
</ContentControl>
<controls:CommonOperationButton
Width="150"
HorizontalAlignment="Left"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<UserControl
x:Class="OngekiFumenEditor.Modules.FumenObjectPropertyBrowser.Views.InterpolatableSoflanOperationView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:cal="http://caliburnmicro.com"
xmlns:controls="clr-namespace:OngekiFumenEditor.Modules.FumenObjectPropertyBrowser.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
d:Background="White"
mc:Ignorable="d">
<StackPanel Margin="21,5,0,0">
<controls:CommonOperationButton
Width="150"
Margin="0,10,0,0"
HorizontalAlignment="Left"
cal:Message.Attach="[Event MouseLeftButtonDown] = [Action Interpolate($executionContext)];"
DecoratorBrush="DarkSalmon"
Text="插值生成Soflan物件"
ToolTip="生成已经插值好的一堆Soflan物件" />
</StackPanel>
</UserControl>
Loading

0 comments on commit 4c19865

Please sign in to comment.