diff --git a/OngekiFumenEditor/App.config b/OngekiFumenEditor/App.config
index ffc24a55..92e5f623 100644
--- a/OngekiFumenEditor/App.config
+++ b/OngekiFumenEditor/App.config
@@ -152,6 +152,9 @@
False
+
+ False
+
diff --git a/OngekiFumenEditor/App.xaml b/OngekiFumenEditor/App.xaml
index 7770166a..92b421c9 100644
--- a/OngekiFumenEditor/App.xaml
+++ b/OngekiFumenEditor/App.xaml
@@ -31,7 +31,7 @@
-
+
diff --git a/OngekiFumenEditor/Kernel/SettingPages/FumenVisualEditor/Views/FumenVisualEditorGlobalSettingView.xaml b/OngekiFumenEditor/Kernel/SettingPages/FumenVisualEditor/Views/FumenVisualEditorGlobalSettingView.xaml
index ce80b4fc..c71fe90d 100644
--- a/OngekiFumenEditor/Kernel/SettingPages/FumenVisualEditor/Views/FumenVisualEditorGlobalSettingView.xaml
+++ b/OngekiFumenEditor/Kernel/SettingPages/FumenVisualEditor/Views/FumenVisualEditorGlobalSettingView.xaml
@@ -7,14 +7,15 @@
xmlns:markup="clr-namespace:OngekiFumenEditor.UI.Markup"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:res="clr-namespace:OngekiFumenEditor.Properties"
- xmlns:vm="clr-namespace:OngekiFumenEditor.Kernel.SettingPages.FumenVisualEditor.ViewModels" xmlns:valueconverters="clr-namespace:OngekiFumenEditor.Kernel.SettingPages.FumenVisualEditor.ValueConverters"
+ xmlns:valueconverters="clr-namespace:OngekiFumenEditor.Kernel.SettingPages.FumenVisualEditor.ValueConverters"
+ xmlns:vm="clr-namespace:OngekiFumenEditor.Kernel.SettingPages.FumenVisualEditor.ViewModels"
d:Background="White"
d:DataContext="{d:DesignInstance IsDesignTimeCreatable=True,
Type=vm:FumenVisualEditorGlobalSettingViewModel}"
d:DesignWidth="800"
mc:Ignorable="d">
-
+
@@ -99,30 +100,54 @@
-
+
+ Width="50"
+ Margin="5,0,5,0"
+ Text="{Binding Setting.ParallelCountLimit}">
-
-
+
+
-
+
-
-
-
+
+
+
+
+
+
diff --git a/OngekiFumenEditor/Modules/FumenVisualEditor/Graphics/Drawing/Editors/DrawPlayerLocationHelper.cs b/OngekiFumenEditor/Modules/FumenVisualEditor/Graphics/Drawing/Editors/DrawPlayerLocationHelper.cs
new file mode 100644
index 00000000..50aa1165
--- /dev/null
+++ b/OngekiFumenEditor/Modules/FumenVisualEditor/Graphics/Drawing/Editors/DrawPlayerLocationHelper.cs
@@ -0,0 +1,69 @@
+using System;
+using System.ComponentModel;
+using System.Linq;
+using System.Numerics;
+using Caliburn.Micro;
+using OngekiFumenEditor.Base;
+using OngekiFumenEditor.Base.EditorObjects;
+using OngekiFumenEditor.Kernel.Graphics;
+using OngekiFumenEditor.Kernel.Graphics.Base;
+using OngekiFumenEditor.Utils;
+
+namespace OngekiFumenEditor.Modules.FumenVisualEditor.Graphics.Drawing.Editors;
+
+public class DrawPlayerLocationHelper
+{
+ private readonly (Vector2 size, Vector2 position, float rotation)[] arr = { default };
+ private readonly Texture texture;
+ private readonly ITextureDrawing textureDrawing;
+ private bool enableShowPlayerLocation;
+
+ public DrawPlayerLocationHelper()
+ {
+ textureDrawing = IoC.Get();
+ arr[0].size = new Vector2(48, 48);
+ arr[0].rotation = 0f;
+
+ texture = ResourceUtils.OpenReadTextureFromResource(@"Modules\FumenVisualEditor\Views\OngekiObjects\playerLoc.png");
+
+ UpdateProps();
+ Properties.EditorGlobalSetting.Default.PropertyChanged += Default_PropertyChanged;
+ }
+
+ private void UpdateProps()
+ {
+ enableShowPlayerLocation = Properties.EditorGlobalSetting.Default.EnableShowPlayerLocation;
+ }
+
+ private void Default_PropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ switch (e.PropertyName)
+ {
+ case nameof(Properties.EditorGlobalSetting.EnableShowPlayerLocation):
+ UpdateProps();
+ break;
+ default:
+ break;
+ }
+ }
+
+ public void Draw(IFumenEditorDrawingContext target)
+ {
+ if (target.Editor.IsDesignMode)
+ return;
+ if (!enableShowPlayerLocation)
+ return;
+
+ var tGrid = TGridCalculator.ConvertAudioTimeToTGrid(target.CurrentPlayTime, target.Editor);
+ var apfLane = target.Editor.Fumen.Lanes.GetVisibleStartObjects(tGrid, tGrid).OfType()
+ .LastOrDefault();
+ var xGrid = apfLane?.CalulateXGrid(tGrid) ?? XGrid.Zero;
+
+ var x = XGridCalculator.ConvertXGridToX(xGrid, target.Editor);
+ var y = target.ConvertToY(tGrid);
+
+ arr[0].position = new Vector2((float)x, (float)y);
+
+ textureDrawing.Draw(target, texture, arr);
+ }
+}
\ No newline at end of file
diff --git a/OngekiFumenEditor/Modules/FumenVisualEditor/ViewModels/FumenVisualEditorViewModel.Drawing.cs b/OngekiFumenEditor/Modules/FumenVisualEditor/ViewModels/FumenVisualEditorViewModel.Drawing.cs
index 46ae5caf..a7ee96b2 100644
--- a/OngekiFumenEditor/Modules/FumenVisualEditor/ViewModels/FumenVisualEditorViewModel.Drawing.cs
+++ b/OngekiFumenEditor/Modules/FumenVisualEditor/ViewModels/FumenVisualEditorViewModel.Drawing.cs
@@ -1,7 +1,14 @@
-using Caliburn.Micro;
-using Gemini.Framework;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Media;
+using Caliburn.Micro;
+using Gemini.Framework;
using OngekiFumenEditor.Base;
-using OngekiFumenEditor.Base.Collections;
using OngekiFumenEditor.Base.OngekiObjects;
using OngekiFumenEditor.Base.OngekiObjects.Beam;
using OngekiFumenEditor.Kernel.Graphics;
@@ -10,490 +17,505 @@
using OngekiFumenEditor.Modules.FumenVisualEditor.Graphics;
using OngekiFumenEditor.Modules.FumenVisualEditor.Graphics.Drawing;
using OngekiFumenEditor.Modules.FumenVisualEditor.Graphics.Drawing.Editors;
+using OngekiFumenEditor.Properties;
using OngekiFumenEditor.UI.Controls;
-using OngekiFumenEditor.Utils;
-using OngekiFumenEditor.Utils.ObjectPool;
+using OngekiFumenEditor.Utils;
using OpenTK.Graphics.OpenGL;
using OpenTK.Mathematics;
using OpenTK.Wpf;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading;
-using System.Threading.Tasks;
-using System.Windows;
-using System.Windows.Media;
using static OngekiFumenEditor.Kernel.Graphics.IDrawingContext;
using static OngekiFumenEditor.Modules.FumenVisualEditor.Graphics.Drawing.Editors.DrawXGridHelper;
+using Color = System.Drawing.Color;
+using Vector4 = System.Numerics.Vector4;
+
+namespace OngekiFumenEditor.Modules.FumenVisualEditor.ViewModels;
-namespace OngekiFumenEditor.Modules.FumenVisualEditor.ViewModels
+public partial class FumenVisualEditorViewModel : PersistedDocument, ISchedulable, IFumenEditorDrawingContext
{
- public partial class FumenVisualEditorViewModel : PersistedDocument, ISchedulable, IFumenEditorDrawingContext
- {
- private IPerfomenceMonitor dummyPerformenceMonitor = new DummyPerformenceMonitor();
- private IPerfomenceMonitor actualPerformenceMonitor;
+ private static Dictionary drawTargets = new();
+ private IPerfomenceMonitor actualPerformenceMonitor;
+
+ private readonly List cachedMagneticXGridLines = new();
+
+ private Func
+ convertToY = TGridCalculator.ConvertTGridUnitToY_DesignMode;
- private DrawTimeSignatureHelper timeSignatureHelper;
- private DrawXGridHelper xGridHelper;
- private DrawJudgeLineHelper judgeLineHelper;
- private DrawSelectingRangeHelper selectingRangeHelper;
- private DrawPlayableAreaHelper playableAreaHelper;
+ private string displayFPS = "";
+ private readonly Dictionary> drawMap = new();
+ private IFumenEditorDrawingTarget[] drawTargetOrder;
+ private readonly IPerfomenceMonitor dummyPerformenceMonitor = new DummyPerformenceMonitor();
+ private bool enablePlayFieldDrawing;
- private Func convertToY = TGridCalculator.ConvertTGridUnitToY_DesignMode;
+ private bool isDisplayFPS;
+ private DrawJudgeLineHelper judgeLineHelper;
+ private DrawPlayableAreaHelper playableAreaHelper;
+ private DrawPlayerLocationHelper playerLocationHelper;
+ private Vector4 playFieldBackgroundColor;
+ private int renderViewHeight;
- private StringBuilder stringBuilder = new StringBuilder(2048);
+ private int renderViewWidth;
+ private DrawSelectingRangeHelper selectingRangeHelper;
- private List cachedMagneticXGridLines = new();
- public IEnumerable CachedMagneticXGridLines => cachedMagneticXGridLines;
+ private readonly StringBuilder stringBuilder = new(2048);
- private int renderViewWidth;
- private int renderViewHeight;
- private System.Numerics.Vector4 playFieldBackgroundColor;
- private bool enablePlayFieldDrawing;
- private float viewWidth = 0;
- public float ViewWidth
+ private DrawTimeSignatureHelper timeSignatureHelper;
+
+ private float viewHeight;
+ private float viewWidth;
+
+ private readonly List<(TGrid minTGrid, TGrid maxTGrid)> visibleTGridRanges = new();
+ private DrawXGridHelper xGridHelper;
+ public IEnumerable CachedMagneticXGridLines => cachedMagneticXGridLines;
+
+ public bool IsDisplayFPS
+ {
+ get => isDisplayFPS;
+ set
{
- get => viewWidth;
- set
- {
- Set(ref viewWidth, value);
- RecalcViewProjectionMatrix();
- }
+ Set(ref isDisplayFPS, value);
+ PerfomenceMonitor = value ? actualPerformenceMonitor : dummyPerformenceMonitor;
}
+ }
- private float viewHeight = 0;
- public float ViewHeight
+ public string DisplayFPS
+ {
+ get => displayFPS;
+ set
{
- get => viewHeight;
- set
- {
- Set(ref viewHeight, value);
- RecalcViewProjectionMatrix();
- }
+ displayFPS = value;
+ NotifyOfPropertyChange(() => DisplayFPS);
}
+ }
- public TimeSpan CurrentPlayTime { get; private set; } = TimeSpan.FromSeconds(0);
-
- private bool isDisplayFPS = false;
- public bool IsDisplayFPS
+ public float ViewWidth
+ {
+ get => viewWidth;
+ set
{
- get => isDisplayFPS;
- set
- {
- Set(ref isDisplayFPS, value);
- PerfomenceMonitor = value ? actualPerformenceMonitor : dummyPerformenceMonitor;
- }
+ Set(ref viewWidth, value);
+ RecalcViewProjectionMatrix();
}
+ }
- private string displayFPS = "";
- public string DisplayFPS
+ public float ViewHeight
+ {
+ get => viewHeight;
+ set
{
- get => displayFPS;
- set
- {
- displayFPS = value;
- NotifyOfPropertyChange(() => DisplayFPS);
- }
+ Set(ref viewHeight, value);
+ RecalcViewProjectionMatrix();
}
+ }
- public Matrix4 ViewMatrix { get; private set; }
- public Matrix4 ProjectionMatrix { get; private set; }
- public Matrix4 ViewProjectionMatrix { get; private set; }
+ public TimeSpan CurrentPlayTime { get; private set; } = TimeSpan.FromSeconds(0);
- public string SchedulerName => "Fumen Previewer Performance Statictis";
+ public Matrix4 ViewMatrix { get; private set; }
+ public Matrix4 ProjectionMatrix { get; private set; }
+ public Matrix4 ViewProjectionMatrix { get; private set; }
- public TimeSpan ScheduleCallLoopInterval => TimeSpan.FromSeconds(1);
+ public FumenVisualEditorViewModel Editor => this;
- public FumenVisualEditorViewModel Editor => this;
+ public VisibleRect Rect { get; set; }
- public VisibleRect Rect { get; set; } = default;
+ public IPerfomenceMonitor PerfomenceMonitor { get; private set; } = new DummyPerformenceMonitor();
- public IPerfomenceMonitor PerfomenceMonitor { get; private set; } = new DummyPerformenceMonitor();
+ public void OnRenderSizeChanged(GLWpfControl glView, SizeChangedEventArgs sizeArg)
+ {
+ Log.LogDebug($"new size: {sizeArg.NewSize} , glView.RenderSize = {glView.RenderSize}");
- private static Dictionary drawTargets = new();
- private IFumenEditorDrawingTarget[] drawTargetOrder;
- private Dictionary> drawMap = new();
+ var dpiX = VisualTreeHelper.GetDpi(Application.Current.MainWindow).DpiScaleX;
+ var dpiY = VisualTreeHelper.GetDpi(Application.Current.MainWindow).DpiScaleY;
- protected override void OnViewLoaded(object v)
- {
- base.OnViewLoaded(v);
- InitExtraMenuItems();
- }
+ ViewWidth = (float) sizeArg.NewSize.Width;
+ ViewHeight = (float) sizeArg.NewSize.Height;
+ renderViewWidth = (int) (sizeArg.NewSize.Width * dpiX);
+ renderViewHeight = (int) (sizeArg.NewSize.Height * dpiY);
+ }
- private void RecalcViewProjectionMatrix()
- {
- var xOffset = 0;
+ public async void PrepareRender(GLWpfControl openGLView)
+ {
+ Log.LogDebug("ready.");
+ await IoC.Get().CheckOrInitGraphics();
- var y = (float)convertToY(GetCurrentTGrid().TotalUnit, this);
+ var dpiX = VisualTreeHelper.GetDpi(Application.Current.MainWindow).DpiScaleX;
+ var dpiY = VisualTreeHelper.GetDpi(Application.Current.MainWindow).DpiScaleY;
- ProjectionMatrix =
- Matrix4.CreateOrthographic(ViewWidth, ViewHeight, -1, 1);
- ViewMatrix =
- Matrix4.CreateTranslation(new Vector3(-ViewWidth / 2 + xOffset, -y - ViewHeight / 2 + (float)Setting.JudgeLineOffsetY, 0));
+ ViewWidth = (float) openGLView.ActualWidth;
+ ViewHeight = (float) openGLView.ActualHeight;
- ViewProjectionMatrix = ViewMatrix * ProjectionMatrix;
- }
+ renderViewWidth = (int) (openGLView.ActualWidth * dpiX);
+ renderViewHeight = (int) (openGLView.ActualHeight * dpiY);
- public void OnRenderSizeChanged(GLWpfControl glView, SizeChangedEventArgs sizeArg)
- {
- Log.LogDebug($"new size: {sizeArg.NewSize} , glView.RenderSize = {glView.RenderSize}");
+ playFieldBackgroundColor = Color.FromArgb(EditorGlobalSetting.Default.PlayFieldBackgroundColor).ToVector4();
+ enablePlayFieldDrawing = EditorGlobalSetting.Default.EnablePlayFieldDrawing;
- var dpiX = VisualTreeHelper.GetDpi(Application.Current.MainWindow).DpiScaleX;
- var dpiY = VisualTreeHelper.GetDpi(Application.Current.MainWindow).DpiScaleY;
+ drawTargets = IoC.GetAll()
+ .SelectMany(target => target.DrawTargetID.Select(supportId => (supportId, target)))
+ .GroupBy(x => x.supportId).ToDictionary(x => x.Key, x => x.Select(x => x.target).ToArray());
- ViewWidth = (float)sizeArg.NewSize.Width;
- ViewHeight = (float)sizeArg.NewSize.Height;
- renderViewWidth = (int)(sizeArg.NewSize.Width * dpiX);
- renderViewHeight = (int)(sizeArg.NewSize.Height * dpiY);
- }
+ ResortRenderOrder();
- public async void PrepareRender(GLWpfControl openGLView)
- {
- Log.LogDebug($"ready.");
- await IoC.Get().CheckOrInitGraphics();
+ timeSignatureHelper = new DrawTimeSignatureHelper();
+ xGridHelper = new DrawXGridHelper();
+ judgeLineHelper = new DrawJudgeLineHelper();
+ selectingRangeHelper = new DrawSelectingRangeHelper();
+ playableAreaHelper = new DrawPlayableAreaHelper();
+ playerLocationHelper = new DrawPlayerLocationHelper();
- var dpiX = VisualTreeHelper.GetDpi(Application.Current.MainWindow).DpiScaleX;
- var dpiY = VisualTreeHelper.GetDpi(Application.Current.MainWindow).DpiScaleY;
+ actualPerformenceMonitor = IoC.Get();
+ IsDisplayFPS = IsDisplayFPS;
- ViewWidth = (float)openGLView.ActualWidth;
- ViewHeight = (float)openGLView.ActualHeight;
+ openGLView.Render += Render;
+ }
- renderViewWidth = (int)(openGLView.ActualWidth * dpiX);
- renderViewHeight = (int)(openGLView.ActualHeight * dpiY);
+ public void Render(TimeSpan ts)
+ {
+ PerfomenceMonitor.PostUIRenderTime(ts);
+ PerfomenceMonitor.OnBeforeRender();
- playFieldBackgroundColor = System.Drawing.Color.FromArgb(Properties.EditorGlobalSetting.Default.PlayFieldBackgroundColor).ToVector4();
- enablePlayFieldDrawing = Properties.EditorGlobalSetting.Default.EnablePlayFieldDrawing;
+#if DEBUG
+ GLUtility.CheckError();
+#endif
- drawTargets = IoC.GetAll()
- .SelectMany(target => target.DrawTargetID.Select(supportId => (supportId, target)))
- .GroupBy(x => x.supportId).ToDictionary(x => x.Key, x => x.Select(x => x.target).ToArray());
+ CleanRender();
+ GL.Viewport(0, 0, renderViewWidth, renderViewHeight);
- ResortRenderOrder();
+ hits.Clear();
- timeSignatureHelper = new DrawTimeSignatureHelper();
- xGridHelper = new DrawXGridHelper();
- judgeLineHelper = new DrawJudgeLineHelper();
- selectingRangeHelper = new DrawSelectingRangeHelper();
- playableAreaHelper = new DrawPlayableAreaHelper();
+ var fumen = Fumen;
+ if (fumen is null)
+ return;
- actualPerformenceMonitor = IoC.Get();
- IsDisplayFPS = IsDisplayFPS;
+ var tGrid = GetCurrentTGrid();
- openGLView.Render += Render;
- }
+ var curY = ConvertToY(tGrid.TotalUnit);
+ var minY = (float) (curY - Setting.JudgeLineOffsetY);
+ var maxY = minY + ViewHeight;
- private void ResortRenderOrder()
+ //计算可以显示的TGrid范围以及像素范围
+ visibleTGridRanges.Clear();
+ if (IsDesignMode)
{
- drawTargetOrder = drawTargets.Values.SelectMany(x => x).OrderBy(x => x.CurrentRenderOrder).Distinct().ToArray();
- }
-
- public IFumenEditorDrawingTarget[] GetDrawingTarget(string name) => drawTargets.TryGetValue(name, out var drawingTarget) ? drawingTarget : default;
+ var minTGrid = TGridCalculator.ConvertYToTGrid_DesignMode(minY, this) ?? TGrid.Zero;
+ var maxTGrid = TGridCalculator.ConvertYToTGrid_DesignMode(maxY, this);
- private IEnumerable GetDisplayableObjects(OngekiFumen fumen, IEnumerable<(TGrid min, TGrid max)> visibleRanges)
+ if (maxTGrid is null || minTGrid is null)
+ return;
+ visibleTGridRanges.Add((minTGrid, maxTGrid));
+ }
+ else
{
- var containBeams = fumen.Beams.Any();
+ var scale = Setting.VerticalDisplayScale;
+ var ranges =
+ Fumen.Soflans.GetVisibleRanges_PreviewMode(curY, ViewHeight, Setting.JudgeLineOffsetY, Fumen.BpmList,
+ scale);
- var objects = visibleRanges.SelectMany(x =>
+ foreach (var x in ranges)
{
- (var min, var max) = x;
- var r = Enumerable.Empty()
- .Concat(fumen.Flicks.BinaryFindRange(min, max))
- .Concat(fumen.MeterChanges.Skip(1)) //not show first meter
- .Concat(fumen.BpmList.Skip(1)) //not show first bpm
- .Concat(fumen.ClickSEs.BinaryFindRange(min, max))
- .Concat(fumen.LaneBlocks.GetVisibleStartObjects(min, max))
- .Concat(fumen.Comments.BinaryFindRange(min, max))
- .Concat(fumen.Soflans.GetVisibleStartObjects(min, max))
- .Concat(fumen.EnemySets.BinaryFindRange(min, max))
- .Concat(fumen.Lanes.GetVisibleStartObjects(min, max))
- .Concat(fumen.Taps.BinaryFindRange(min, max))
- .Concat(fumen.Holds.GetVisibleStartObjects(min, max))
- .Concat(fumen.SvgPrefabs);
-
- if (containBeams)
- {
- var leadInTGrid = TGridCalculator.ConvertAudioTimeToTGrid(TGridCalculator.ConvertTGridToAudioTime(min, this) - TGridCalculator.ConvertFrameToAudioTime(BeamStart.LEAD_IN_DURATION_FRAME), this);
- var leadOutTGrid = TGridCalculator.ConvertAudioTimeToTGrid(TGridCalculator.ConvertTGridToAudioTime(max, this) + TimeSpan.FromMilliseconds(BeamStart.LEAD_OUT_DURATION), this);
-
- r = r.Concat(fumen.Beams.GetVisibleStartObjects(leadInTGrid, leadOutTGrid));
- }
-
- return r;
- });
+ if (x.maxTGrid is null || x.minTGrid is null)
+ return;
+ visibleTGridRanges.Add((x.minTGrid, x.maxTGrid));
+ }
+ }
- /*
- * 这里考虑到有spd<1的子弹/Bell会提前出现的情况,因此得分状态分别去选择
- */
- var objs = Enumerable.Empty();
- if (Editor.IsPreviewMode)
- {
- /*
- var r = fumen.Bells
- .AsEnumerable()
- .Concat(fumen.Bullets);
+ Rect = new VisibleRect(new Vector2(ViewWidth, minY), new Vector2(0, minY + ViewHeight));
- objs = objs.Concat(r);
- */
- }
- else
- {
- foreach (var item in visibleRanges)
- {
- (var min, var max) = item;
- var blts = fumen.Bullets.BinaryFindRange(min, max);
- var bels = fumen.Bells.BinaryFindRange(min, max);
-
- objs = objs.Concat(bels);
- objs = objs.Concat(blts);
- }
- }
+ RecalculateMagaticXGridLines();
- return objects.Concat(objs).SelectMany(x => x.GetDisplayableObjects());
- }
+ foreach (var (minTGrid, maxTGrid) in visibleTGridRanges)
+ playableAreaHelper.DrawPlayField(this, minTGrid, maxTGrid);
+ playableAreaHelper.Draw(this);
+ timeSignatureHelper.DrawLines(this);
- private void CleanRender()
+ xGridHelper.DrawLines(this, CachedMagneticXGridLines);
+
+ //todo 可以把GroupBy()给优化掉
+ var renderObjects =
+ GetDisplayableObjects(fumen, visibleTGridRanges)
+ .Distinct()
+ .OfType()
+ .GroupBy(x => x.IDShortName);
+
+ foreach (var objGroup in renderObjects)
{
- if (IsDesignMode || !enablePlayFieldDrawing)
- GL.ClearColor(16 / 255.0f, 16 / 255.0f, 16 / 255.0f, 1);
- else
- GL.ClearColor(playFieldBackgroundColor.X, playFieldBackgroundColor.Y, playFieldBackgroundColor.Z, playFieldBackgroundColor.W);
- GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
+ if (GetDrawingTarget(objGroup.Key) is not IFumenEditorDrawingTarget[] drawingTargets)
+ continue;
+
+ foreach (var drawingTarget in drawingTargets)
+ if (!drawMap.TryGetValue(drawingTarget, out var enums))
+ drawMap[drawingTarget] = objGroup;
+ else
+ drawMap[drawingTarget] = enums.Concat(objGroup);
}
- private List<(TGrid minTGrid, TGrid maxTGrid)> visibleTGridRanges = new List<(TGrid minTGrid, TGrid maxTGrid)>();
+ if (IsPreviewMode)
+ {
+ //特殊处理:子弹和Bell
+ foreach (var drawingTarget in GetDrawingTarget(Bullet.CommandName))
+ drawMap[drawingTarget] = Fumen.Bullets;
+ foreach (var drawingTarget in GetDrawingTarget(Bell.CommandName))
+ drawMap[drawingTarget] = Fumen.Bells;
+ }
- public void Render(TimeSpan ts)
+ var prevOrder = int.MinValue;
+ foreach (var drawingTarget in drawTargetOrder.Where(x => CheckDrawingVisible(x.Visible)))
{
- PerfomenceMonitor.PostUIRenderTime(ts);
- PerfomenceMonitor.OnBeforeRender();
+ //check render order
+ var order = drawingTarget.CurrentRenderOrder;
+ if (prevOrder > order)
+ {
+ ResortRenderOrder();
+ CleanRender();
+ break;
+ }
-#if DEBUG
- GLUtility.CheckError();
-#endif
+ prevOrder = order;
- CleanRender();
- GL.Viewport(0, 0, renderViewWidth, renderViewHeight);
+ if (drawMap.TryGetValue(drawingTarget, out var drawingObjs))
+ {
+ drawingTarget.Begin(this);
+ foreach (var obj in drawingObjs.OrderBy(x => x.TGrid))
+ drawingTarget.Post(obj);
+ drawingTarget.End();
+ }
+ }
- hits.Clear();
+ drawMap.Clear();
- var fumen = Fumen;
- if (fumen is null)
- return;
+ timeSignatureHelper.DrawTimeSigntureText(this);
+ xGridHelper.DrawXGridText(this, CachedMagneticXGridLines);
+ judgeLineHelper.Draw(this);
+ playerLocationHelper.Draw(this);
+ selectingRangeHelper.Draw(this);
- var tGrid = GetCurrentTGrid();
- var curY = ConvertToY(tGrid.TotalUnit);
- var minY = (float)(curY - Setting.JudgeLineOffsetY);
- var maxY = (float)(minY + ViewHeight);
+ PerfomenceMonitor.OnAfterRender();
+ }
- //计算可以显示的TGrid范围以及像素范围
- visibleTGridRanges.Clear();
- if (IsDesignMode)
- {
- var minTGrid = TGridCalculator.ConvertYToTGrid_DesignMode(minY, this) ?? TGrid.Zero;
- var maxTGrid = TGridCalculator.ConvertYToTGrid_DesignMode(maxY, this);
+ public bool CheckDrawingVisible(DrawingVisible visible)
+ {
+ return visible.HasFlag(EditorObjectVisibility == Visibility.Visible
+ ? DrawingVisible.Design
+ : DrawingVisible.Preview);
+ }
- if (maxTGrid is null || minTGrid is null)
- return;
- visibleTGridRanges.Add((minTGrid, maxTGrid));
- }
- else
- {
- var scale = Setting.VerticalDisplayScale;
- var ranges = Fumen.Soflans.GetVisibleRanges_PreviewMode(curY, ViewHeight, Setting.JudgeLineOffsetY, Fumen.BpmList, scale);
-
- foreach (var x in ranges)
- {
- if (x.maxTGrid is null || x.minTGrid is null)
- return;
- visibleTGridRanges.Add((x.minTGrid, x.maxTGrid));
- }
- }
- Rect = new VisibleRect(new(ViewWidth, minY), new(0, minY + ViewHeight));
+ public double ConvertToY(double tGridUnit)
+ {
+ return convertToY(tGridUnit, this);
+ }
- RecalculateMagaticXGridLines();
+ public bool CheckVisible(TGrid tGrid)
+ {
+ foreach (var (minTGrid, maxTGrid) in visibleTGridRanges)
+ if (minTGrid <= tGrid && tGrid <= maxTGrid)
+ return true;
+ return false;
+ }
- foreach ((var minTGrid, var maxTGrid) in visibleTGridRanges)
- playableAreaHelper.DrawPlayField(this, minTGrid, maxTGrid);
- playableAreaHelper.Draw(this);
- timeSignatureHelper.DrawLines(this);
+ public bool CheckRangeVisible(TGrid minTGrid, TGrid maxTGrid)
+ {
+ foreach (var visibleRange in visibleTGridRanges)
+ {
+ var result = !(minTGrid > visibleRange.maxTGrid || maxTGrid < visibleRange.minTGrid);
+ if (result)
+ return true;
+ }
- xGridHelper.DrawLines(this, CachedMagneticXGridLines);
+ return false;
+ }
- //todo 可以把GroupBy()给优化掉
- var renderObjects =
- GetDisplayableObjects(fumen, visibleTGridRanges)
- .Distinct()
- .OfType()
- .GroupBy(x => x.IDShortName);
+ public string SchedulerName => "Fumen Previewer Performance Statictis";
- foreach (var objGroup in renderObjects)
- {
- if (GetDrawingTarget(objGroup.Key) is not IFumenEditorDrawingTarget[] drawingTargets)
- continue;
-
- foreach (var drawingTarget in drawingTargets)
- {
- if (!drawMap.TryGetValue(drawingTarget, out var enums))
- drawMap[drawingTarget] = objGroup;
- else
- drawMap[drawingTarget] = enums.Concat(objGroup);
- }
- }
+ public TimeSpan ScheduleCallLoopInterval => TimeSpan.FromSeconds(1);
- if (IsPreviewMode)
- {
- //特殊处理:子弹和Bell
- foreach (var drawingTarget in GetDrawingTarget(Bullet.CommandName))
- drawMap[drawingTarget] = Fumen.Bullets;
- foreach (var drawingTarget in GetDrawingTarget(Bell.CommandName))
- drawMap[drawingTarget] = Fumen.Bells;
- }
+ public void OnSchedulerTerm()
+ {
+ }
- var prevOrder = int.MinValue;
- foreach (var drawingTarget in drawTargetOrder.Where(x => CheckDrawingVisible(x.Visible)))
- {
- //check render order
- var order = drawingTarget.CurrentRenderOrder;
- if (prevOrder > order)
- {
- ResortRenderOrder();
- CleanRender();
- break;
- }
- prevOrder = order;
-
- if (drawMap.TryGetValue(drawingTarget, out var drawingObjs))
- {
- drawingTarget.Begin(this);
- foreach (var obj in drawingObjs.OrderBy(x => x.TGrid))
- drawingTarget.Post(obj);
- drawingTarget.End();
- }
- }
+ public Task OnScheduleCall(CancellationToken cancellationToken)
+ {
+ if (IsDisplayFPS)
+ {
+ stringBuilder.Clear();
- drawMap.Clear();
+ PerfomenceMonitor?.FormatStatistics(stringBuilder);
+#if DEBUG
+ stringBuilder.AppendLine();
+ stringBuilder.AppendLine($"View: {ViewWidth}x{ViewHeight}");
+ stringBuilder.AppendLine($"VisibleYRange: [{Rect.MinY}, {Rect.MaxY}]");
+ stringBuilder.AppendLine("VisibleTGridRanges:");
+ foreach (var tGridRange in visibleTGridRanges.ToArray())
+ stringBuilder.AppendLine($"* {tGridRange.minTGrid} - {tGridRange.maxTGrid}");
+#endif
- timeSignatureHelper.DrawTimeSigntureText(this);
- xGridHelper.DrawXGridText(this, CachedMagneticXGridLines);
- judgeLineHelper.Draw(this);
- selectingRangeHelper.Draw(this);
+ DisplayFPS = stringBuilder.ToString();
- PerfomenceMonitor.OnAfterRender();
+ PerfomenceMonitor?.Clear();
}
- public void OnLoaded(ActionExecutionContext e)
- {
+ return Task.CompletedTask;
+ }
- }
+ protected override void OnViewLoaded(object v)
+ {
+ base.OnViewLoaded(v);
+ InitExtraMenuItems();
+ }
- private void RecalculateMagaticXGridLines()
- {
- //todo 可以优化
- cachedMagneticXGridLines.Clear();
+ private void RecalcViewProjectionMatrix()
+ {
+ var xOffset = 0;
- var xOffset = (float)Setting.XOffset;
- var width = ViewWidth;
- if (width == 0)
- return;
- var xUnitSpace = (float)Setting.XGridUnitSpace;
- var maxDisplayXUnit = Setting.XGridDisplayMaxUnit;
+ var y = (float) convertToY(GetCurrentTGrid().TotalUnit, this);
- var unitSize = (float)XGridCalculator.CalculateXUnitSize(maxDisplayXUnit, width, xUnitSpace);
- var totalUnitValue = 0f;
+ ProjectionMatrix =
+ Matrix4.CreateOrthographic(ViewWidth, ViewHeight, -1, 1);
+ ViewMatrix =
+ Matrix4.CreateTranslation(new Vector3(-ViewWidth / 2 + xOffset,
+ -y - ViewHeight / 2 + (float) Setting.JudgeLineOffsetY, 0));
- var baseX = width / 2 + xOffset;
+ ViewProjectionMatrix = ViewMatrix * ProjectionMatrix;
+ }
- var limitLength = width + Math.Abs(xOffset);
+ private void ResortRenderOrder()
+ {
+ drawTargetOrder = drawTargets.Values.SelectMany(x => x).OrderBy(x => x.CurrentRenderOrder).Distinct().ToArray();
+ }
+
+ public IFumenEditorDrawingTarget[] GetDrawingTarget(string name)
+ {
+ return drawTargets.TryGetValue(name, out var drawingTarget) ? drawingTarget : default;
+ }
- for (float totalLength = baseX + unitSize; totalLength - xOffset < limitLength; totalLength += unitSize)
+ private IEnumerable GetDisplayableObjects(OngekiFumen fumen,
+ IEnumerable<(TGrid min, TGrid max)> visibleRanges)
+ {
+ var containBeams = fumen.Beams.Any();
+
+ var objects = visibleRanges.SelectMany(x =>
+ {
+ var (min, max) = x;
+ var r = Enumerable.Empty()
+ .Concat(fumen.Flicks.BinaryFindRange(min, max))
+ .Concat(fumen.MeterChanges.Skip(1)) //not show first meter
+ .Concat(fumen.BpmList.Skip(1)) //not show first bpm
+ .Concat(fumen.ClickSEs.BinaryFindRange(min, max))
+ .Concat(fumen.LaneBlocks.GetVisibleStartObjects(min, max))
+ .Concat(fumen.Comments.BinaryFindRange(min, max))
+ .Concat(fumen.Soflans.GetVisibleStartObjects(min, max))
+ .Concat(fumen.EnemySets.BinaryFindRange(min, max))
+ .Concat(fumen.Lanes.GetVisibleStartObjects(min, max))
+ .Concat(fumen.Taps.BinaryFindRange(min, max))
+ .Concat(fumen.Holds.GetVisibleStartObjects(min, max))
+ .Concat(fumen.SvgPrefabs);
+
+ if (containBeams)
{
- totalUnitValue += xUnitSpace;
-
- cachedMagneticXGridLines.Add(new()
- {
- X = totalLength,
- XGridTotalUnit = totalUnitValue,
- XGridTotalUnitDisplay = totalUnitValue.ToString()
- });
-
- cachedMagneticXGridLines.Add(new()
- {
- X = baseX - (totalLength - baseX),
- XGridTotalUnit = -totalUnitValue,
- XGridTotalUnitDisplay = (-totalUnitValue).ToString()
- });
+ var leadInTGrid = TGridCalculator.ConvertAudioTimeToTGrid(
+ TGridCalculator.ConvertTGridToAudioTime(min, this) -
+ TGridCalculator.ConvertFrameToAudioTime(BeamStart.LEAD_IN_DURATION_FRAME), this);
+ var leadOutTGrid = TGridCalculator.ConvertAudioTimeToTGrid(
+ TGridCalculator.ConvertTGridToAudioTime(max, this) +
+ TimeSpan.FromMilliseconds(BeamStart.LEAD_OUT_DURATION), this);
+
+ r = r.Concat(fumen.Beams.GetVisibleStartObjects(leadInTGrid, leadOutTGrid));
}
- cachedMagneticXGridLines.Add(new()
- {
- X = baseX,
- XGridTotalUnit = 0f,
- });
- }
- public void OnSizeChanged(ActionExecutionContext e)
- {
- var scrollViewer = e.Source as AnimatedScrollViewer;
- scrollViewer?.InvalidateMeasure();
- }
+ return r;
+ });
- public void OnSchedulerTerm()
+ /*
+ * 这里考虑到有spd<1的子弹/Bell会提前出现的情况,因此得分状态分别去选择
+ */
+ var objs = Enumerable.Empty();
+ if (Editor.IsPreviewMode)
{
+ /*
+ var r = fumen.Bells
+ .AsEnumerable()
+ .Concat(fumen.Bullets);
+ objs = objs.Concat(r);
+ */
}
-
- public Task OnScheduleCall(CancellationToken cancellationToken)
+ else
{
- if (IsDisplayFPS)
+ foreach (var item in visibleRanges)
{
- stringBuilder.Clear();
+ var (min, max) = item;
+ var blts = fumen.Bullets.BinaryFindRange(min, max);
+ var bels = fumen.Bells.BinaryFindRange(min, max);
- PerfomenceMonitor?.FormatStatistics(stringBuilder);
-#if DEBUG
- stringBuilder.AppendLine();
- stringBuilder.AppendLine($"View: {ViewWidth}x{ViewHeight}");
- stringBuilder.AppendLine($"VisibleYRange: [{Rect.MinY}, {Rect.MaxY}]");
- stringBuilder.AppendLine($"VisibleTGridRanges:");
- foreach (var tGridRange in visibleTGridRanges.ToArray())
- stringBuilder.AppendLine($"* {tGridRange.minTGrid} - {tGridRange.maxTGrid}");
-#endif
+ objs = objs.Concat(bels);
+ objs = objs.Concat(blts);
+ }
+ }
- DisplayFPS = stringBuilder.ToString();
+ return objects.Concat(objs).SelectMany(x => x.GetDisplayableObjects());
+ }
- PerfomenceMonitor?.Clear();
+ private void CleanRender()
+ {
+ if (IsDesignMode || !enablePlayFieldDrawing)
+ GL.ClearColor(16 / 255.0f, 16 / 255.0f, 16 / 255.0f, 1);
+ else
+ GL.ClearColor(playFieldBackgroundColor.X, playFieldBackgroundColor.Y, playFieldBackgroundColor.Z,
+ playFieldBackgroundColor.W);
+ GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
+ }
+
+ public void OnLoaded(ActionExecutionContext e)
+ {
+ }
- }
- return Task.CompletedTask;
- }
+ private void RecalculateMagaticXGridLines()
+ {
+ //todo 可以优化
+ cachedMagneticXGridLines.Clear();
- public bool CheckDrawingVisible(DrawingVisible visible)
- {
- return visible.HasFlag(EditorObjectVisibility == Visibility.Visible ? DrawingVisible.Design : DrawingVisible.Preview);
- }
+ var xOffset = (float) Setting.XOffset;
+ var width = ViewWidth;
+ if (width == 0)
+ return;
+ var xUnitSpace = (float) Setting.XGridUnitSpace;
+ var maxDisplayXUnit = Setting.XGridDisplayMaxUnit;
- public double ConvertToY(double tGridUnit)
- {
- return convertToY(tGridUnit, this);
- }
+ var unitSize = (float) XGridCalculator.CalculateXUnitSize(maxDisplayXUnit, width, xUnitSpace);
+ var totalUnitValue = 0f;
- public bool CheckVisible(TGrid tGrid)
- {
- foreach ((var minTGrid, var maxTGrid) in visibleTGridRanges)
- if (minTGrid <= tGrid && tGrid <= maxTGrid)
- return true;
- return false;
- }
+ var baseX = width / 2 + xOffset;
+
+ var limitLength = width + Math.Abs(xOffset);
- public bool CheckRangeVisible(TGrid minTGrid, TGrid maxTGrid)
+ for (var totalLength = baseX + unitSize; totalLength - xOffset < limitLength; totalLength += unitSize)
{
- foreach (var visibleRange in visibleTGridRanges)
+ totalUnitValue += xUnitSpace;
+
+ cachedMagneticXGridLines.Add(new CacheDrawXLineResult
{
- var result = !(minTGrid > visibleRange.maxTGrid || maxTGrid < visibleRange.minTGrid);
- if (result)
- return true;
- }
- return false;
+ X = totalLength,
+ XGridTotalUnit = totalUnitValue,
+ XGridTotalUnitDisplay = totalUnitValue.ToString()
+ });
+
+ cachedMagneticXGridLines.Add(new CacheDrawXLineResult
+ {
+ X = baseX - (totalLength - baseX),
+ XGridTotalUnit = -totalUnitValue,
+ XGridTotalUnitDisplay = (-totalUnitValue).ToString()
+ });
}
- }
-}
+
+ cachedMagneticXGridLines.Add(new CacheDrawXLineResult
+ {
+ X = baseX,
+ XGridTotalUnit = 0f
+ });
+ }
+
+ public void OnSizeChanged(ActionExecutionContext e)
+ {
+ var scrollViewer = e.Source as AnimatedScrollViewer;
+ scrollViewer?.InvalidateMeasure();
+ }
+}
\ No newline at end of file
diff --git a/OngekiFumenEditor/Modules/FumenVisualEditor/Views/OngekiObjects/playerLoc.png b/OngekiFumenEditor/Modules/FumenVisualEditor/Views/OngekiObjects/playerLoc.png
new file mode 100644
index 00000000..bc02bdd8
Binary files /dev/null and b/OngekiFumenEditor/Modules/FumenVisualEditor/Views/OngekiObjects/playerLoc.png differ
diff --git a/OngekiFumenEditor/OngekiFumenEditor.csproj b/OngekiFumenEditor/OngekiFumenEditor.csproj
index cc10815d..32d1c35c 100644
--- a/OngekiFumenEditor/OngekiFumenEditor.csproj
+++ b/OngekiFumenEditor/OngekiFumenEditor.csproj
@@ -25,6 +25,8 @@
+
+
@@ -179,10 +181,10 @@
-
+
all
-
+
all
diff --git a/OngekiFumenEditor/Properties/EditorGlobalSetting.Designer.cs b/OngekiFumenEditor/Properties/EditorGlobalSetting.Designer.cs
index 4fdb3dee..965d0e58 100644
--- a/OngekiFumenEditor/Properties/EditorGlobalSetting.Designer.cs
+++ b/OngekiFumenEditor/Properties/EditorGlobalSetting.Designer.cs
@@ -12,7 +12,7 @@ namespace OngekiFumenEditor.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.8.0.0")]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.11.0.0")]
public sealed partial class EditorGlobalSetting : global::System.Configuration.ApplicationSettingsBase {
private static EditorGlobalSetting defaultInstance = ((EditorGlobalSetting)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new EditorGlobalSetting())));
@@ -382,5 +382,17 @@ public bool EnablePlayFieldDrawing {
this["EnablePlayFieldDrawing"] = value;
}
}
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("False")]
+ public bool EnableShowPlayerLocation {
+ get {
+ return ((bool)(this["EnableShowPlayerLocation"]));
+ }
+ set {
+ this["EnableShowPlayerLocation"] = value;
+ }
+ }
}
}
diff --git a/OngekiFumenEditor/Properties/EditorGlobalSetting.settings b/OngekiFumenEditor/Properties/EditorGlobalSetting.settings
index b993c659..92d8a4c6 100644
--- a/OngekiFumenEditor/Properties/EditorGlobalSetting.settings
+++ b/OngekiFumenEditor/Properties/EditorGlobalSetting.settings
@@ -92,5 +92,8 @@
False
+
+ False
+
\ No newline at end of file
diff --git a/OngekiFumenEditor/Properties/Resources.Designer.cs b/OngekiFumenEditor/Properties/Resources.Designer.cs
index 5b4437fa..6c26ab57 100644
--- a/OngekiFumenEditor/Properties/Resources.Designer.cs
+++ b/OngekiFumenEditor/Properties/Resources.Designer.cs
@@ -1563,6 +1563,15 @@ public static string EnablePlayFieldDrawing {
}
}
+ ///
+ /// 查找类似 Display the player's current position (if there is no AutoPlayFaderLane, it defaults to the center) 的本地化字符串。
+ ///
+ public static string EnableShowPlayerLocation {
+ get {
+ return ResourceManager.GetString("EnableShowPlayerLocation", resourceCulture);
+ }
+ }
+
///
/// 查找类似 Enable display visualizer 的本地化字符串。
///
diff --git a/OngekiFumenEditor/Properties/Resources.ja.resx b/OngekiFumenEditor/Properties/Resources.ja.resx
index cf93ca10..3d27c60d 100644
--- a/OngekiFumenEditor/Properties/Resources.ja.resx
+++ b/OngekiFumenEditor/Properties/Resources.ja.resx
@@ -147,6 +147,9 @@
サポートされている全ファイル形式
+
+ アプリケーションバージョン
+
音源位置を補正する
@@ -207,6 +210,9 @@
現在オブジェクトの時刻を自動更新
+
+ 背景色:
+
一括でクリティカル設定
@@ -261,6 +267,9 @@
AcbGeneratorFuck.Generator.Generate() の呼び出しに失敗しました
+
+ GenerateSvgAsync() の呼び出しに失敗しました
+
キャンセル
@@ -270,6 +279,9 @@
選択解除
+
+ 新しいプロジェクトを作成できません:
+
譜面をクイックオープンできませんでした:
@@ -336,6 +348,9 @@
ユーザは新規プロジェクトウィザードを完了できません。このエディタを閉じてください。
+
+ プログラムを終了
+
レーンを結合
@@ -345,6 +360,9 @@
確認
+
+ 確認したため閉じることができます
+
コンパイルに成功しました。実行しますか?
@@ -438,6 +456,12 @@
作成
+
+ プロジェクトを作成
+
+
+ 新しくプロジェクトを作成します
+
タイムラインのオフセット
@@ -531,6 +555,12 @@
レーンの途中でレーンを2つに分岐します
+
+ .dmpファイル:
+
+
+ 以前
+
エディタは指定されたTGridに移動します
@@ -576,9 +606,18 @@
メトロノームを有効化(デザインモードのみ)
+
+ 複数起動を許可
+
通知ダイアログを表示
+
+ オーディオ時間(末尾の赤い線)の外側にオブジェクトを配置できるようにする
+
+
+ 渲染可击打区域(実験的機能)
+
スペクトル表示
@@ -615,6 +654,9 @@
音源フォルダが存在しません
+
+ 有栖がエディタを食べてしまいました
+
実行
@@ -630,6 +672,12 @@
クイックオープン
+
+ クイックオープン
+
+
+ 既存の譜面ファイルを開く
+
譜面をクイックオープン
@@ -645,6 +693,18 @@
クイック再生/一時停止
+
+ ファイルの関連付け
+
+
+ 選択したファイル形式を関連付ける
+
+
+ ファイルの関連付け(要管理者権限)
+
+
+ すべての関連付けを解除
+
フィルタ
@@ -750,6 +810,9 @@
スクリプトプロジェクトファイルの生成に失敗しました
+
+ 生成铺面预览.svg文件
+
ジャンル:
@@ -765,6 +828,9 @@
画面描画
+
+ 30分前
+
譜面ヘッダー情報
@@ -780,6 +846,9 @@
画像ファイル:
+
+ 内部例外メッセージ:
+
生成する画像ファイルが存在しません
@@ -825,12 +894,18 @@
判定ラインオフセット:
+
+ 今
+
キーワード並び替え
このレーンは不正なセグメントを含んでいます
+
+ 言語
+
元に戻せる回数を制限する
@@ -846,6 +921,12 @@
既存のMusic.xmlを読み込む
+
+ プロジェクトと譜面は正常に読み込まれました
+
+
+ 現在のログファイルの保存先:
+
ロガー
@@ -924,6 +1005,9 @@
(非表示)
+
+ 再度表示しない
+
{0} はブラシモードでサポートされていません
@@ -981,6 +1065,12 @@
エディタを開いてください
+
+ プロジェクトを開く
+
+
+ 既存のプロジェクトを開く
+
オプション
@@ -1023,9 +1113,15 @@
X[0, 0]を基準として水平方向にミラーリングして貼り付け
+
+ マウスポインタ位置に貼り付け
+
音声/譜面を一時停止してください
+
+ 可击打区域颜色:
+
編集の競合を避けるため,一時的にこのエディタを使用できなくなります
@@ -1053,6 +1149,18 @@
プロパティのバッチ割り当て:
+
+ ランダムオフセット範囲
+
+
+ 再計算に成功しました
+
+
+ エディタの全長の再計算
+
+
+ 最近使用したファイル
+
音源時刻に復元
@@ -1065,6 +1173,15 @@
更新
+
+ 登録に失敗しました
+
+
+ 一つ以上のファイル種別について登録に失敗しました
+
+
+ 登録に成功しました
+
音源ファイルを再読込
@@ -1086,9 +1203,21 @@
描画順
+
+ 権限がありません。管理者として実行してください。
+
+
+ プログラムの再起動が必要です
+
リサンプリング
+
+ 譜面・プロジェクトファイルは一時的に以下の場所に保存されています:
+
+
+ リセット
+
オブジェクトの選択を反転
@@ -1218,6 +1347,9 @@
標準オンゲキ譜面を生成
+
+ 開始
+
外部エディタの使用を停止
@@ -1281,15 +1413,24 @@
コピーされたオブジェクト…
+
+ 今日
+
貼り付け…
選択されたオブジェクト…
+
+ チュートリアル
+
チュートリアル・文書
+
+ 譜面とエディタの使用方法についてチュートリアルで学習する
+
出力トラックをプレビューするにはShowOriginColorのチェックを外してください
@@ -1299,6 +1440,12 @@
元に戻す/やり直し(要再起動)
+
+ 登録解除に失敗しました
+
+
+ 登録解除に成功しました
+
assets.bytesを更新(存在する場合):
@@ -1345,11 +1492,17 @@
同じ方向のWALLノーツ(id:{0},id:{1})が同じ時間に存在しています
- WALLノーツ(id:{0})の中間点/終点オブジェクトのTGrid({1})が始点({1})よりも小さくなっています
+ WALLノーツ(id:{0})の中間点/終点オブジェクトのTGrid({1})が始点({2})よりも小さくなっています
いくつかの効果音の読み込みに失敗しました。詳細についてはログを確認してください。
+
+ 1ヶ月以内
+
+
+ 1週間以内
+
{0}オブジェクトが正しいレーン(id:{1})上に配置されていません
@@ -1365,154 +1518,4 @@
水平スクロールオフセット
-
- アプリケーションバージョン
-
-
- 新しいプロジェクトを作成できません:
-
-
- プログラムを終了
-
-
- 確認したため閉じることができます
-
-
- プロジェクトを作成
-
-
- 新しくプロジェクトを作成します
-
-
- .dmpファイル:
-
-
- 以前
-
-
- 複数起動を許可
-
-
- 有栖がエディタを食べてしまいました
-
-
- クイックオープン
-
-
- 既存の譜面ファイルを開く
-
-
- ファイルの関連付け
-
-
- 選択したファイル形式を関連付ける
-
-
- ファイルの関連付け(要管理者権限)
-
-
- すべての関連付けを解除
-
-
- 30分前
-
-
- 内部例外メッセージ:
-
-
- 今
-
-
- 言語
-
-
- プロジェクトと譜面は正常に読み込まれました
-
-
- 現在のログファイルの保存先:
-
-
- 再度表示しない
-
-
- プロジェクトを開く
-
-
- 既存のプロジェクトを開く
-
-
- マウスポインタ位置に貼り付け
-
-
- 最近使用したファイル
-
-
- 登録に失敗しました
-
-
- 一つ以上のファイル種別について登録に失敗しました
-
-
- 登録に成功しました
-
-
- 権限がありません。管理者として実行してください。
-
-
- プログラムの再起動が必要です
-
-
- 譜面・プロジェクトファイルは一時的に以下の場所に保存されています:
-
-
- リセット
-
-
- 開始
-
-
- 今日
-
-
- チュートリアル
-
-
- 譜面とエディタの使用方法についてチュートリアルで学習する
-
-
- 登録解除に失敗しました
-
-
- 登録解除に成功しました
-
-
- 1ヶ月以内
-
-
- 1週間以内
-
-
- オーディオ時間(末尾の赤い線)の外側にオブジェクトを配置できるようにする
-
-
- エディタの全長の再計算
-
-
- 再計算に成功しました
-
-
- 背景色:
-
-
- 渲染可击打区域(実験的機能)
-
-
- 生成铺面预览.svg文件
-
-
- 可击打区域颜色:
-
-
- ランダムオフセット範囲
-
\ No newline at end of file
diff --git a/OngekiFumenEditor/Properties/Resources.resx b/OngekiFumenEditor/Properties/Resources.resx
index d5b67472..182ada92 100644
--- a/OngekiFumenEditor/Properties/Resources.resx
+++ b/OngekiFumenEditor/Properties/Resources.resx
@@ -1524,4 +1524,7 @@
Horizontal scroll offset:
+
+ Display the player's current position (if there is no AutoPlayFaderLane, it defaults to the center)
+
\ No newline at end of file
diff --git a/OngekiFumenEditor/Properties/Resources.zh-Hans.resx b/OngekiFumenEditor/Properties/Resources.zh-Hans.resx
index bd730455..4afda4cf 100644
--- a/OngekiFumenEditor/Properties/Resources.zh-Hans.resx
+++ b/OngekiFumenEditor/Properties/Resources.zh-Hans.resx
@@ -1524,4 +1524,7 @@
水平轴偏移:
+
+ 显示玩家当前位置 (若没AutoPlayFaderLane轨道则默认在中心)
+
\ No newline at end of file