using Ionic.Zip; using Microsoft.Graphics.Canvas; using Microsoft.Graphics.Canvas.Brushes; using Microsoft.Graphics.Canvas.Text; using Microsoft.UI; using MoonSharp.Interpreter; using Qwilight.Note; using Qwilight.PaintComponent; using Qwilight.UIComponent; using Qwilight.Utilities; using Qwilight.ViewModel; using System.Collections.Concurrent; using System.Collections.ObjectModel; using System.IO; using System.Text; using Windows.UI; using YamlDotNet.Core; using YamlDotNet.RepresentationModel; namespace Qwilight { public sealed class UI : Model, IDrawingContainer, IAudioContainer { public const int HighestUIConfigure = 16; public const int HighestNoteID = 64; public const int HighestPaintPropertyID = 256; public static readonly UI Instance = QwilightComponent.GetBuiltInData<UI>(nameof(UI)); public static void ZipUIFile(ZipFile zipFile, UIItem value, string entryPath) { var yamlFilePath = value.GetYamlFilePath(); if (File.Exists(yamlFilePath)) { zipFile.AddFile(yamlFilePath, Path.Combine(entryPath, Path.GetRelativePath(QwilightComponent.UIEntryPath, Path.GetDirectoryName(yamlFilePath)))); var ys = new YamlStream(); using (var sr = File.OpenText(yamlFilePath)) { ys.Load(sr); } var formatNode = ys.Documents[0].RootNode[new YamlScalarNode("format")]; var zipFilePath = Path.Combine(QwilightComponent.UIEntryPath, value.UIEntry, Path.ChangeExtension(Utility.GetText(formatNode, "zip", value.YamlName), "zip")); if (File.Exists(zipFilePath)) { zipFile.AddFile(zipFilePath, Path.Combine(entryPath, Path.GetRelativePath(QwilightComponent.UIEntryPath, Path.GetDirectoryName(zipFilePath)))); } var luaFilePath = Path.Combine(QwilightComponent.UIEntryPath, value.UIEntry, Path.ChangeExtension(Utility.GetText(formatNode, "lua", value.YamlName), "lua")); if (File.Exists(luaFilePath)) { zipFile.AddFile(luaFilePath, Path.Combine(entryPath, Path.GetRelativePath(QwilightComponent.UIEntryPath, Path.GetDirectoryName(luaFilePath)))); } } } readonly Dictionary<string, AudioItem?> _audioItemMap = new(); /// <summary> /// UI, BaseUI가 로드됨을 보장하는 락 /// </summary> public object LoadedCSX { get; } = new(); public XamlUIConfigure[] XamlUIConfigures { get; set; } = Array.Empty<XamlUIConfigure>(); public string[] LoadedConfigures { get; } = new string[8]; public bool HasMain => PaintPipelineValues.Contains(PaintPipelineID.Main); public bool HasJudgmentMain => PaintPipelineValues.Contains(PaintPipelineID.JudgmentMain); public bool HasJudgmentCount => PaintPipelineValues.Contains(PaintPipelineID.HighestJudgment) || PaintPipelineValues.Contains(PaintPipelineID.HigherJudgment) || PaintPipelineValues.Contains(PaintPipelineID.HighJudgment) || PaintPipelineValues.Contains(PaintPipelineID.LowJudgment) || PaintPipelineValues.Contains(PaintPipelineID.LowerJudgment) || PaintPipelineValues.Contains(PaintPipelineID.LowestJudgment); public bool HasJudgmentMeter => PaintPipelineValues.Contains(PaintPipelineID.JudgmentMeter); public bool HasJudgmentVisualizer => PaintPipelineValues.Contains(PaintPipelineID.JudgmentVisualizer); public bool HasJudgmentPaint => PaintPipelineValues.Contains(PaintPipelineID.JudgmentPaint); public bool HasHitNotePaint => PaintPipelineValues.Contains(PaintPipelineID.HitNotePaint); public bool HasBPM => PaintPipelineValues.Contains(PaintPipelineID.BPM); public bool HasNet => PaintPipelineValues.Contains(PaintPipelineID.Net); public bool HasJudgmentInputVisualizer => PaintPipelineValues.Contains(PaintPipelineID.JudgmentInputVisualizer); public bool HasHunter => PaintPipelineValues.Contains(PaintPipelineID.Hunter); public bool HasMediaInput => PaintPipelineValues.Contains(PaintPipelineID.MediaInput); public bool HasMainJudgmentMeter => PaintPipelineValues.Contains(PaintPipelineID.MainJudgmentMeter); public double DefaultLength { get; set; } public double DefaultHeight { get; set; } public ObservableCollection<UIItem> UIItems { get; } = new(); public Dictionary<string, string[]> IntCallMap { get; } = new(); public Dictionary<string, string[]> ValueCallMap { get; } = new(); public Dictionary<string, string[]> AltCallMap { get; } = new(); public Dictionary<string, double> ValueMap { get; } = new(); public Dictionary<string, int> IntMap { get; } = new(); public Dictionary<string, int> AltMap { get; } = new(); public List<PaintPipelineID> PaintPipelineValues { get; } = new(); public Color TitleColor { get; set; } public Color ArtistColor { get; set; } public Color GenreColor { get; set; } public Color WantLevelIDColor { get; set; } public ICanvasBrush[] NetTextPaints { get; } = new ICanvasBrush[101]; public ICanvasBrush[] NetWallPaints { get; } = new ICanvasBrush[101]; public List<int> DrawingPipeline { get; } = new(); public int[][] DrawingInputModeMap { get; } = new int[17][]; public DrawingItem?[][] PauseDrawings { get; } = new DrawingItem?[3][]; public DrawingItem?[][][][][] NoteDrawings { get; } = new DrawingItem?[17][][][][]; public DrawingItem?[][][] NoteHitDrawings { get; } = new DrawingItem?[17][][]; public DrawingItem?[][][] LongNoteHitDrawings { get; } = new DrawingItem?[17][][]; public DrawingItem?[][][] MainDrawings { get; } = new DrawingItem?[17][][]; public DrawingItem?[][][] JudgmentMainDrawings { get; } = new DrawingItem?[17][][]; public DrawingItem?[][][] InputDrawings { get; } = new DrawingItem?[17][][]; public DrawingItem?[] MainWalls { get; } = new DrawingItem?[2]; public DrawingItem?[][] AutoInputDrawings { get; } = new DrawingItem?[17][]; public DrawingItem?[] BinStandMap { get; } = new DrawingItem?[10]; public DrawingItem?[] BinPointMap { get; } = new DrawingItem?[10]; public DrawingItem?[] BinHitPointsVisualizerMap { get; } = new DrawingItem?[10]; public DrawingItem?[] BinHmsMap { get; } = new DrawingItem?[10]; public DrawingItem?[] BinAudioMultiplierMap { get; } = new DrawingItem?[10]; public DrawingItem?[][] BinJudgmentValueMap { get; } = new DrawingItem?[6][]; public DrawingItem?[] BinBPMMap { get; } = new DrawingItem?[10]; public DrawingItem?[] BinMultiplierMap { get; } = new DrawingItem?[10]; public DrawingItem?[] BinHighestBandMap { get; } = new DrawingItem?[10]; public DrawingItem?[] BinInputVisualizerMap { get; } = new DrawingItem?[10]; public DrawingItem?[] BinJudgmentMeterMap { get; } = new DrawingItem?[10]; public DrawingItem?[] BinHunterMap { get; } = new DrawingItem?[10]; public DrawingItem?[] BinEarlyValueMap { get; } = new DrawingItem?[10]; public DrawingItem?[] BinLateValueMap { get; } = new DrawingItem?[10]; public DrawingItem?[] BinJudgmentVSVisualizerMap { get; } = new DrawingItem?[10]; public DrawingItem?[] JudgmentPointsDrawings { get; } = new DrawingItem?[6]; public DrawingItem?[] JudgmentInputDrawings { get; } = new DrawingItem?[6]; public PaintProperty[] PaintPropertyValues { get; } = new PaintProperty[HighestPaintPropertyID]; public DrawingItem?[][] JudgmentDrawings { get; } = new DrawingItem?[11][]; public DrawingItem?[][] LevelDrawings { get; } = new DrawingItem?[6][]; public DrawingItem?[] AutoMainDrawings { get; set; } public Dictionary<int, DrawingItem?>[][] MainJudgmentMeterDrawings { get; } = new Dictionary<int, DrawingItem?>[17][]; public CanvasTextFormat TitleFont { get; } = DrawingSystem.Instance.GetFont(); public CanvasTextFormat ArtistFont { get; } = DrawingSystem.Instance.GetFont(); public CanvasTextFormat GenreFont { get; } = DrawingSystem.Instance.GetFont(); public CanvasTextFormat LevelTextFont { get; } = DrawingSystem.Instance.GetFont(); public CanvasTextFormat WantLevelFont { get; } = DrawingSystem.Instance.GetFont(); public string UILS { get; set; } = string.Empty; public bool MaintainLongNoteFrontEdge { get; set; } public bool MaintainAutoInput { get; set; } public int LoopingMain { get; set; } public int LoopingInput { get; set; } public bool SetJudgmentMainPosition { get; set; } public bool SetMainPosition { get; set; } public bool SetNoteLength { get; set; } public bool SetNoteHeight { get; set; } public bool SetBandPosition { get; set; } public bool SetJudgmentPaintPosition { get; set; } public bool SetHitNotePaintArea { get; set; } public DrawingItem?[] HitPointsDrawings { get; } = new DrawingItem?[8]; public HandledDrawingItem? VeilDrawing { get; set; } public DrawingItem? StatusDrawing { get; set; } public DrawingItem? StatusSliderDrawing { get; set; } public DrawingItem? CommaDrawing { get; set; } public DrawingItem? SlashDrawing { get; set; } public DrawingItem? ColonDrawing { get; set; } public DrawingItem? AudioMultiplierStopPointDrawing { get; set; } public DrawingItem? MultiplierStopPointDrawing { get; set; } public DrawingItem? PointStopPointDrawing { get; set; } public DrawingItem? JudgmentVSVisualizerStopPointDrawing { get; set; } public DrawingItem? PointUnitDrawing { get; set; } public DrawingItem? HitPointsVisualizerUnitDrawing { get; set; } public DrawingItem? BPMUnitDrawing { get; set; } public DrawingItem? JudgmentMererHigherDrawing { get; set; } public DrawingItem? JudgmentMeterLowerDrawing { get; set; } public DrawingItem? HunterHigherDrawing { get; set; } public DrawingItem? HunterLowerDrawing { get; set; } public DrawingItem? JudgmentMeterUnitDrawing { get; set; } public DrawingItem? AudioMultiplierUnitDrawing { get; set; } public DrawingItem? MultiplierUnitDrawing { get; set; } public DrawingItem?[,] BinBandMap { get; set; } public DrawingItem?[] PausedUnpauseDrawings { get; } = new DrawingItem?[2]; public DrawingItem?[] PausedStopDrawings { get; } = new DrawingItem?[2]; public DrawingItem?[] PausedUndoDrawings { get; } = new DrawingItem?[2]; public DrawingItem?[] PausedConfigureDrawings { get; } = new DrawingItem?[2]; public bool HandleAudio(string audioFileName, string defaultFileName, PausableAudioHandler pausableAudioHandler, double fadeInLength) { lock (LoadedCSX) { if (!_audioItemMap.TryGetValue(audioFileName, out var audioItem) && defaultFileName != null) { _audioItemMap.TryGetValue(defaultFileName, out audioItem); } if (audioItem != null) { AudioSystem.Instance.Handle(new AudioNote { AudioLevyingPosition = pausableAudioHandler?.GetAudioPosition() ?? 0U, AudioItem = audioItem }, AudioSystem.SEAudio, 1.0, false, pausableAudioHandler, fadeInLength); return true; } return false; } } public string FaultText { get; set; } public UI() => Init(); void LoadUIImpl(UIItem src, UIItem target) { #region COMPATIBLE Compatible.Compatible.UI(QwilightComponent.UIEntryPath, target.GetYamlFilePath(), target.YamlName, target.UIEntry); #endregion Init(); var drawingMap = new int[HighestNoteID + 1][]; drawingMap[0] = new int[] { 0 }; var noteHitDrawings = new DrawingItem?[HighestNoteID + 1][]; var longNoteHitDrawings = new DrawingItem?[HighestNoteID + 1][]; var inputDrawings = new DrawingItem?[HighestNoteID + 1][]; var noteDrawings = new DrawingItem?[HighestNoteID + 1][][][]; var mainDrawings = new DrawingItem?[HighestNoteID + 1][]; var autoInputDrawings = new DrawingItem?[HighestNoteID + 1]; var judgmentMainDrawings = new DrawingItem?[HighestNoteID + 1][]; var mainJudgmentMeterDrawings = new Dictionary<int, DrawingItem?>[HighestNoteID + 1]; string zipName; var lsCaller = new Script(); var parallelItems = new ConcurrentBag<Action>(); var ys = new YamlStream(); using (var sr = File.OpenText(target.GetYamlFilePath())) { ys.Load(sr); var valueNode = ys.Documents[0].RootNode; var formatNode = valueNode[new YamlScalarNode("format")]; var lambdaNode = valueNode[new YamlScalarNode("lambda")]; var frameNode = valueNode[new YamlScalarNode("frame")]; var pointNode = valueNode[new YamlScalarNode("point")]; (valueNode as YamlMappingNode).Children.TryGetValue(new YamlScalarNode("paint"), out var paintNode); (valueNode as YamlMappingNode).Children.TryGetValue(new YamlScalarNode("font"), out var fontNode); zipName = Utility.GetText(formatNode, "zip", target.YamlName); XamlUIConfigures = Enumerable.Range(0, HighestUIConfigure).Select(i => { var configures = (Utility.GetText(lambdaNode, $"configure-{i}-{Utility.GetLCID(Configure.Instance.Language)}") ?? Utility.GetText(lambdaNode, $"configure-{i}"))?.Split(',')?.Select(configure => configure.Trim())?.ToArray(); if (configures != null) { LoadedConfigures[i] = Configure.Instance.UIConfigureValue.UIConfiguresV2[i] ??= configures.FirstOrDefault(); return new XamlUIConfigure { Position = i, Configures = configures, ConfigureComment = Utility.GetText(lambdaNode, $"configure-comment-{i}-{Utility.GetLCID(Configure.Instance.Language)}") ?? Utility.GetText(lambdaNode, $"configure-comment-{i}") }; } else { return null; } }).Where(value => value != null).ToArray(); SetConfigures(lsCaller); UILS = File.ReadAllText(Path.Combine(QwilightComponent.UIEntryPath, target.UIEntry, Path.ChangeExtension(Utility.GetText(formatNode, "lua", target.YamlName), "lua")), Encoding.UTF8); Script.RunString(UILS); lsCaller.DoString(UILS); DefaultLength = GetCalledValue(formatNode, "defaultLength", Component.StandardLength.ToString()); DefaultHeight = GetCalledValue(formatNode, "defaultHeight", Component.StandardHeight.ToString()); var setPaintPipelines = Utility.ToBool(Utility.GetText(lambdaNode, "set-paint-pinelines", bool.FalseString)); foreach (var pipeline in GetCalledText(Utility.GetText(lambdaNode, "pipeline")).Split(',').Select(value => Utility.ToInt32(value.Trim(), out var pipeline) ? pipeline : 0)) { var paintPipeline = (PaintPipelineID)pipeline; PaintPipelineValues.Add(paintPipeline); if (paintPipeline == PaintPipelineID.JudgmentPaint && !setPaintPipelines) { PaintPipelineValues.Add(PaintPipelineID.HitNotePaint); } } if (!PaintPipelineValues.Contains(PaintPipelineID.Media)) { PaintPipelineValues.Insert(0, PaintPipelineID.Media); } if (!PaintPipelineValues.Contains(PaintPipelineID.MainAreaFaint)) { var mainPosition = PaintPipelineValues.IndexOf(PaintPipelineID.Main); if (mainPosition >= 0) { PaintPipelineValues.Insert(mainPosition, PaintPipelineID.MainAreaFaint); } } if (!PaintPipelineValues.Contains(PaintPipelineID.Limiter)) { var mainPosition = PaintPipelineValues.IndexOf(PaintPipelineID.Main); if (mainPosition >= 0) { PaintPipelineValues.Insert(mainPosition + 1, PaintPipelineID.Limiter); } } if (!PaintPipelineValues.Contains(PaintPipelineID.VeilDrawing)) { var notePosition = PaintPipelineValues.IndexOf(PaintPipelineID.Note); if (notePosition >= 0) { PaintPipelineValues.Insert(notePosition + 1, PaintPipelineID.VeilDrawing); } } PaintPipelineValues.Add(PaintPipelineID.MediaInput); SaveInt(lambdaNode, "drawingInputModeSystem", 0); TitleColor = Utility.GetText(paintNode, "title", nameof(Colors.White)).GetColor(); ArtistColor = Utility.GetText(paintNode, "artist", nameof(Colors.White)).GetColor(); GenreColor = Utility.GetText(paintNode, "genre", nameof(Colors.White)).GetColor(); WantLevelIDColor = Utility.GetText(paintNode, "wantLevelID", nameof(Colors.White)).GetColor(); parallelItems.Add(() => DrawingSystem.Instance.SetFaintPaints(this, NetTextPaints, Utility.GetText(paintNode, "netText", nameof(Colors.White)).GetColor())); parallelItems.Add(() => DrawingSystem.Instance.SetFaintPaints(this, NetWallPaints, Utility.GetText(paintNode, "netWall", nameof(Colors.Black)).GetColor())); SaveValueMap(pointNode, "mainPosition"); SaveValueMap(pointNode, "p2Position"); SaveValueMap(pointNode, "binLength"); SaveValueMap(pointNode, "binHeight"); SaveValueMapAsDefaultID("stopPointDrawingLength", "binLength"); SaveSplitValueMap("floatingNotePosition0", 0.0); SaveSplitValueMap("floatingNoteLength", 0.0); SaveSplitValueMap("slashNotePosition0", 0.0); SaveValueMap(pointNode, "judgmentMainPosition"); SaveValueMap(pointNode, "mediaPosition0", 0.0); SaveValueMap(pointNode, "mediaPosition1", 0.0); SaveValueMap(pointNode, "mediaLength", Component.StandardLength); SaveValueMap(pointNode, "mediaHeight", Component.StandardHeight); SaveAltMap("alt-media", 0); SaveValueMap(pointNode, "titlePosition0"); SaveValueMap(pointNode, "titlePosition1"); SaveValueMap(pointNode, "titleLength"); SaveValueMap(pointNode, "titleHeight"); SaveIntMap(pointNode, "titleSystem0"); SaveIntMap(pointNode, "titleSystem1", 2); SaveAltMap("alt-title", 0); SaveValueMap(pointNode, "artistPosition0"); SaveValueMap(pointNode, "artistPosition1"); SaveValueMap(pointNode, "artistLength"); SaveValueMap(pointNode, "artistHeight"); SaveIntMap(pointNode, "artistSystem0"); SaveIntMap(pointNode, "artistSystem1", 2); SaveAltMap("alt-artist", 0); SaveValueMap(pointNode, "genrePosition0"); SaveValueMap(pointNode, "genrePosition1"); SaveValueMap(pointNode, "genreLength"); SaveValueMap(pointNode, "genreHeight"); SaveIntMap(pointNode, "genreSystem0"); SaveIntMap(pointNode, "genreSystem1"); SaveAltMap("alt-genre", 0); SaveValueMap(pointNode, "levelTextPosition0"); SaveValueMap(pointNode, "levelTextPosition1"); SaveValueMap(pointNode, "levelTextLength"); SaveValueMap(pointNode, "levelTextHeight"); SaveIntMap(pointNode, "levelTextSystem0"); SaveIntMap(pointNode, "levelTextSystem1"); SaveAltMap("alt-level-text", 0); SaveValueMap(pointNode, "wantLevelPosition0"); SaveValueMap(pointNode, "wantLevelPosition1"); SaveValueMap(pointNode, "wantLevelLength"); SaveValueMap(pointNode, "wantLevelHeight"); SaveIntMap(pointNode, "wantLevelSystem0"); SaveIntMap(pointNode, "wantLevelSystem1"); SaveAltMap("alt-want-level", 0); SaveValueMap(pointNode, "audioVisualizerPosition0", 0.0); SaveValueMap(pointNode, "audioVisualizerPosition1", 0.0); SaveValueMap(pointNode, "audioVisualizerLength", Component.StandardLength); SaveValueMap(pointNode, "audioVisualizerHeight", Component.StandardHeight); DrawingSystem.Instance.SetFontLevel(TitleFont, Utility.ToFloat32(Utility.GetText(fontNode, "titleLevel", QwilightComponent.GetBuiltInFloat64As("FontLevel0")))); DrawingSystem.Instance.SetFontLevel(ArtistFont, Utility.ToFloat32(Utility.GetText(fontNode, "artistLevel", QwilightComponent.GetBuiltInFloat64As("FontLevel0")))); DrawingSystem.Instance.SetFontLevel(GenreFont, Utility.ToFloat32(Utility.GetText(fontNode, "genreLevel", QwilightComponent.GetBuiltInFloat64As("FontLevel0")))); DrawingSystem.Instance.SetFontLevel(LevelTextFont, Utility.ToFloat32(Utility.GetText(fontNode, "levelTextLevel", QwilightComponent.GetBuiltInFloat64As("FontLevel0")))); DrawingSystem.Instance.SetFontLevel(WantLevelFont, Utility.ToFloat32(Utility.GetText(fontNode, "wantLevelLevel", QwilightComponent.GetBuiltInFloat64As("FontLevel0")))); SaveValueMap(pointNode, "mainWall0Length"); SaveValueMap(pointNode, "mainWall1Length"); SaveValueMap(pointNode, "mainWall0Position1"); SaveValueMap(pointNode, "mainWall0Height", 720.0); SaveValueMap(pointNode, "mainWall1Position1"); SaveValueMap(pointNode, "mainWall1Height", 720.0); SaveAltMap("alt-wall-0", 2); SaveAltMap("alt-wall-1", 2); SaveIntMap(frameNode, "main-frame"); SaveValueMap(frameNode, "main-framerate"); SaveValueMap(pointNode, "mainPosition1"); SaveValueMap(pointNode, "mainHeight", 720.0); SaveSplitValueMap("autoInputPosition1"); SaveSplitValueMap("autoInputHeight", 720.0); SaveIntMap(pointNode, "hitPointsSystem"); SaveValueMap(pointNode, "hitPointsPosition0"); SaveValueMap(pointNode, "hitPointsPosition1"); SaveValueMap(pointNode, "hitPointsLength"); SaveValueMap(pointNode, "hitPointsHeight"); SaveAltMap("alt-hit-points", 2); SaveIntMap(frameNode, "note-frame"); SaveValueMap(frameNode, "note-framerate"); SaveSplitValueMap("noteLength"); SaveSplitValueMap("noteHeight"); SaveSplitValueMap("noteHeightJudgment"); SaveSplitValueMap("longNoteTailEdgeHeight"); SaveSplitValueMap("longNoteFrontEdgeHeight"); SaveSplitValueMap("longNoteTailEdgePosition"); SaveSplitValueMap("longNoteFrontEdgePosition"); SaveSplitValueMap("longNoteTailContentsHeight"); SaveSplitValueMap("longNoteFrontContentsHeight"); MaintainLongNoteFrontEdge = Utility.ToBool(Utility.GetText(lambdaNode, "maintainLongNoteFrontEdge", bool.FalseString)); MaintainAutoInput = Utility.ToBool(Utility.GetText(lambdaNode, "maintainAutoInput", bool.TrueString)); LoopingMain = Utility.ToInt32(Utility.GetText(lambdaNode, "loopingMain", 0.ToString())); LoopingInput = Utility.ToInt32(Utility.GetText(lambdaNode, "loopingInput", 0.ToString())); SetJudgmentMainPosition = Utility.ToBool(Utility.GetText(lambdaNode, "setJudgmentMainPosition", bool.FalseString)); SetMainPosition = Utility.ToBool(Utility.GetText(lambdaNode, "setMainPosition", bool.FalseString)); SetNoteLength = Utility.ToBool(Utility.GetText(lambdaNode, "setNoteLength", bool.FalseString)); SetNoteHeight = Utility.ToBool(Utility.GetText(lambdaNode, "setNoteHeight", bool.FalseString)); SetBandPosition = Utility.ToBool(Utility.GetText(lambdaNode, "setBandPosition", bool.FalseString)); SetJudgmentPaintPosition = Utility.ToBool(Utility.GetText(lambdaNode, "setJudgmentPaintPosition", bool.FalseString)); SetHitNotePaintArea = Utility.ToBool(Utility.GetText(lambdaNode, "setHitNotePaintArea", bool.FalseString)); SaveIntMap(lambdaNode, "judgmentPaintComposition"); SaveIntMap(lambdaNode, "hitNotePaintComposition", (int)CanvasComposite.Add); SaveIntMap(frameNode, "input-frame"); SaveValueMap(frameNode, "input-framerate"); SaveSplitValueMap("inputPosition0"); SaveSplitValueMapAsDefaultID("inputPosition1", "judgmentMainPosition"); SaveSplitValueMap("inputLength"); SaveSplitValueMapAsDefaultID("inputHeight", "judgmentMainPosition", value => 720.0 - value); SaveIntMap(frameNode, "level-frame"); SaveValueMap(frameNode, "level-framerate"); SaveValueMap(pointNode, "levelPosition0"); SaveValueMap(pointNode, "levelPosition1"); SaveValueMap(pointNode, "levelLength"); SaveValueMap(pointNode, "levelHeight"); SaveAltMap("alt-level"); SaveIntMap(pointNode, "bandSystem"); SaveValueMap(pointNode, "bandPosition0"); SaveValueMap(pointNode, "bandPosition1"); SaveIntMap(frameNode, "band-frame"); SaveValueMap(frameNode, "band-framerate"); SaveValueMapAsDefaultID("binBandLength", "binLength"); SaveValueMapAsDefaultID("binBandHeight", "binHeight"); SaveValueMap(pointNode, "enlargeBand"); SaveAltMap("alt-band", 2); SaveIntMap(pointNode, "judgmentMeterSystem"); SaveValueMap(pointNode, "judgmentMeterPosition0"); SaveValueMap(pointNode, "judgmentMeterPosition1"); SaveValueMapAsDefaultID("binJudgmentMeterLength", "binLength"); SaveValueMapAsDefaultID("binJudgmentMeterHeight", "binHeight"); SaveValueMapAsDefaultID("judgmentMeterFrontDrawingLength", "binJudgmentMeterLength"); SaveValueMapAsDefaultID("judgmentMeterUnitDrawingLength", "binJudgmentMeterLength"); SaveAltMap("alt-judgment-meter", 3); SaveIntMap(pointNode, "standSystem"); SaveValueMap(pointNode, "standPosition0"); SaveValueMap(pointNode, "standPosition1"); SaveValueMapAsDefaultID("binStandLength", "binLength"); SaveValueMapAsDefaultID("binStandHeight", "binHeight"); SaveValueMapAsDefaultID("standCommaDrawingLength", "binLength"); SaveAltMap("alt-stand"); SaveIntMap(pointNode, "pointSystem"); SaveValueMap(pointNode, "pointPosition0"); SaveValueMap(pointNode, "pointPosition1"); SaveValueMapAsDefaultID("binPointLength", "binLength"); SaveValueMapAsDefaultID("binPointHeight", "binHeight"); SaveValueMapAsDefaultID("pointStopPointDrawingLength", "stopPointDrawingLength"); SaveValueMapAsDefaultID("pointUnitDrawingLength", "binPointLength"); SaveAltMap("alt-point"); SaveIntMap(pointNode, "bpmSystem"); SaveValueMap(pointNode, "bpmPosition0"); SaveValueMap(pointNode, "bpmPosition1"); SaveValueMapAsDefaultID("binBPMLength", "binLength"); SaveValueMapAsDefaultID("binBPMHeight", "binHeight"); SaveValueMapAsDefaultID("bpmUnitDrawingLength", "binBPMLength"); SaveAltMap("alt-bpm"); SaveIntMap(pointNode, "multiplierSystem"); SaveValueMap(pointNode, "multiplierPosition0"); SaveValueMap(pointNode, "multiplierPosition1"); SaveValueMapAsDefaultID("binMultiplierLength", "binLength"); SaveValueMapAsDefaultID("binMultiplierHeight", "binHeight"); SaveValueMapAsDefaultID("multiplierStopPointDrawingLength", "stopPointDrawingLength"); SaveValueMapAsDefaultID("multiplierUnitDrawingLength", "binMultiplierLength"); SaveAltMap("alt-multiplier"); SaveIntMap(frameNode, "note-hit-frame"); SaveValueMap(frameNode, "note-hit-framerate"); SaveIntMap(frameNode, "long-note-hit-frame"); SaveValueMap(frameNode, "long-note-hit-framerate"); SaveIntMap(frameNode, "judgment-frame"); SaveValueMap(frameNode, "judgment-framerate"); SaveIntMap(pointNode, "judgmentPaintSystem"); SaveValueMap(pointNode, "judgmentPaintPosition0"); SaveValueMap(pointNode, "judgmentPaintPosition1"); SaveValueMap(pointNode, "judgmentPaintLength"); SaveValueMap(pointNode, "judgmentPaintHeight"); SaveSplitValueMap("hitNotePaintLength"); SaveSplitValueMap("hitNotePaintHeight"); SaveSplitValueMap("hitLongNotePaintLength"); SaveSplitValueMap("hitLongNotePaintHeight"); SaveSplitValueMapAsDefaultID("hitNotePaintPosition0", "hitNotePaintLength1", value => -value / 2); SaveSplitValueMapAsDefaultID("hitNotePaintPosition1", "hitNotePaintHeight1", value => -value / 2); SaveSplitValueMapAsDefaultID("hitLongNotePaintPosition0", "hitLongNotePaintLength1", value => -value / 2); SaveSplitValueMapAsDefaultID("hitLongNotePaintPosition1", "hitLongNotePaintHeight1", value => -value / 2); SaveIntMap(frameNode, "hit-input-paint-frame"); SaveValueMap(frameNode, "hit-input-paint-framerate"); SaveSplitValueMap("hitInputPaintPosition0"); SaveSplitValueMap("hitInputPaintPosition1"); SaveSplitValueMap("hitInputPaintLength"); SaveSplitValueMap("hitInputPaintHeight"); SaveIntMap(frameNode, "long-note-hit-loop-frame"); SaveIntMap(frameNode, "last-enlarged-band-loop-frame"); SaveIntMap(frameNode, "last-frame"); SaveValueMap(frameNode, "last-framerate"); SaveIntMap(pointNode, "lastSystem"); SaveValueMap(pointNode, "lastPosition0"); SaveValueMap(pointNode, "lastPosition1"); SaveValueMap(pointNode, "lastLength"); SaveValueMap(pointNode, "lastHeight"); SaveAltMap("alt-last", 2); SaveIntMap(frameNode, "band!-frame"); SaveValueMap(frameNode, "band!-framerate"); SaveIntMap(pointNode, "band!System"); SaveValueMap(pointNode, "band!Position0"); SaveValueMap(pointNode, "band!Position1"); SaveValueMap(pointNode, "band!Length"); SaveValueMap(pointNode, "band!Height"); SaveAltMap("alt-band!", 2); SaveIntMap(pointNode, "netSystem"); SaveValueMap(pointNode, "netPosition0"); SaveValueMap(pointNode, "netPosition1"); SaveAltMap("alt-net"); SaveIntMap(frameNode, "auto-main-frame"); SaveValueMap(frameNode, "auto-main-framerate"); SaveIntMap(pointNode, "autoMainSystem"); SaveValueMap(pointNode, "autoMainPosition0"); SaveValueMap(pointNode, "autoMainPosition1"); SaveValueMap(pointNode, "autoMainLength"); SaveValueMap(pointNode, "autoMainHeight"); SaveAltMap("alt-auto-main"); SaveIntMap(frameNode, "pause-frame", 1); SaveIntMap(pointNode, "pauseSystem"); SaveValueMap(pointNode, "pausePosition0"); SaveValueMap(pointNode, "pausePosition1"); SaveValueMap(pointNode, "pauseLength"); SaveValueMap(pointNode, "pauseHeight"); SaveAltMap("alt-pause", 2); SaveIntMap(pointNode, "statusSystem"); SaveValueMap(pointNode, "statusPosition0"); SaveValueMap(pointNode, "statusPosition1"); SaveValueMap(pointNode, "statusLength"); SaveValueMap(pointNode, "statusHeight"); SaveAltMap("alt-status"); SaveIntMap(pointNode, "statusSliderSystem"); SaveValueMap(pointNode, "statusSliderPosition0"); SaveValueMap(pointNode, "statusSliderPosition1"); SaveValueMap(pointNode, "statusSliderLength"); SaveValueMap(pointNode, "statusSliderHeight"); SaveValueMap(pointNode, "statusSliderContentsLength"); SaveValueMap(pointNode, "statusSliderContentsHeight"); SaveAltMap("alt-status-slider"); SaveIntMap(pointNode, "hmsSystem"); SaveValueMap(pointNode, "hmsPosition0"); SaveValueMap(pointNode, "hmsPosition1"); SaveValueMapAsDefaultID("binHmsLength", "binLength"); SaveValueMapAsDefaultID("binHmsHeight", "binHeight"); SaveValueMapAsDefaultID("hmsColonDrawingLength", "binLength"); SaveValueMapAsDefaultID("hmsSlashDrawingLength", "binLength"); SaveAltMap("alt-hms"); SaveIntMap(pointNode, "judgmentPointsSystem"); SaveValueMap(pointNode, "judgmentPointsPosition0"); SaveValueMap(pointNode, "judgmentPointsPosition1"); SaveValueMap(pointNode, "judgmentPointsLength"); SaveValueMap(pointNode, "judgmentPointsHeight"); SaveAltMap("alt-judgment-points"); SaveIntMap(frameNode, "judgment-main-frame"); SaveValueMap(frameNode, "judgment-main-framerate"); SaveSplitValueMap("judgmentMainPosition1"); SaveSplitValueMap("judgmentMainHeight"); SaveIntMap(frameNode, "main-judgment-meter-frame"); SaveValueMap(frameNode, "main-judgment-meter-framerate"); SaveSplitValueMap("mainJudgmentMeterPosition1"); SaveSplitValueMap("mainJudgmentMeterHeight"); SaveIntMap(pointNode, "audioMultiplierSystem"); SaveValueMap(pointNode, "audioMultiplierPosition0"); SaveValueMap(pointNode, "audioMultiplierPosition1"); SaveValueMapAsDefaultID("binAudioMultiplierLength", "binLength"); SaveValueMapAsDefaultID("binAudioMultiplierHeight", "binHeight"); SaveValueMapAsDefaultID("audioMultiplierStopPointDrawingLength", "stopPointDrawingLength"); SaveValueMapAsDefaultID("audioMultiplierUnitDrawingLength", "binAudioMultiplierLength"); SaveAltMap("alt-audio-multiplier"); SaveIntMap(pointNode, "hitPointsVisualizerSystem"); SaveValueMap(pointNode, "hitPointsVisualizerPosition0"); SaveValueMap(pointNode, "hitPointsVisualizerPosition1"); SaveValueMapAsDefaultID("binHitPointsVisualizerLength", "binLength"); SaveValueMapAsDefaultID("binHitPointsVisualizerHeight", "binHeight"); SaveValueMap(pointNode, "hitPointsVisualizerUnitDrawingLength"); SaveAltMap("alt-hit-points-visualizer"); SaveIntMap(pointNode, "highestJudgmentValueSystem"); SaveValueMap(pointNode, "highestJudgmentValuePosition0"); SaveValueMap(pointNode, "highestJudgmentValuePosition1"); SaveValueMapAsDefaultID("binHighestJudgmentValueLength", "binLength"); SaveValueMapAsDefaultID("binHighestJudgmentValueHeight", "binHeight"); SaveAltMap("alt-highest-judgment-value"); SaveIntMap(pointNode, "higherJudgmentValueSystem"); SaveValueMap(pointNode, "higherJudgmentValuePosition0"); SaveValueMap(pointNode, "higherJudgmentValuePosition1"); SaveValueMapAsDefaultID("binHigherJudgmentValueLength", "binLength"); SaveValueMapAsDefaultID("binHigherJudgmentValueHeight", "binHeight"); SaveAltMap("alt-higher-judgment-value"); SaveIntMap(pointNode, "highJudgmentValueSystem"); SaveValueMap(pointNode, "highJudgmentValuePosition0"); SaveValueMap(pointNode, "highJudgmentValuePosition1"); SaveValueMapAsDefaultID("binHighJudgmentValueLength", "binLength"); SaveValueMapAsDefaultID("binHighJudgmentValueHeight", "binHeight"); SaveAltMap("alt-high-judgment-value"); SaveIntMap(pointNode, "lowJudgmentValueSystem"); SaveValueMap(pointNode, "lowJudgmentValuePosition0"); SaveValueMap(pointNode, "lowJudgmentValuePosition1"); SaveValueMapAsDefaultID("binLowJudgmentValueLength", "binLength"); SaveValueMapAsDefaultID("binLowJudgmentValueHeight", "binHeight"); SaveAltMap("alt-low-judgment-value"); SaveIntMap(pointNode, "lowerJudgmentValueSystem"); SaveValueMap(pointNode, "lowerJudgmentValuePosition0"); SaveValueMap(pointNode, "lowerJudgmentValuePosition1"); SaveValueMapAsDefaultID("binLowerJudgmentValueLength", "binLength"); SaveValueMapAsDefaultID("binLowerJudgmentValueHeight", "binHeight"); SaveAltMap("alt-lower-judgment-value"); SaveIntMap(pointNode, "lowestJudgmentValueSystem"); SaveValueMap(pointNode, "lowestJudgmentValuePosition0"); SaveValueMap(pointNode, "lowestJudgmentValuePosition1"); SaveValueMapAsDefaultID("binLowestJudgmentValueLength", "binLength"); SaveValueMapAsDefaultID("binLowestJudgmentValueHeight", "binHeight"); SaveAltMap("alt-lowest-judgment-value"); SaveIntMap(pointNode, "highestBandSystem"); SaveValueMap(pointNode, "highestBandPosition0"); SaveValueMap(pointNode, "highestBandPosition1"); SaveValueMapAsDefaultID("binHighestBandLength", "binLength"); SaveValueMapAsDefaultID("binHighestBandHeight", "binHeight"); SaveAltMap("alt-highest-band"); SaveValueMapAsDefaultID("limiterPosition1", "mainPosition1"); SaveValueMap(pointNode, "limiterLength", 1.0); SaveValueMapAsDefaultID("limiterHeight", "mainHeight"); SaveIntMap(pointNode, "judgmentVisualizerSystem"); SaveValueMap(pointNode, "judgmentVisualizerPosition0"); SaveValueMap(pointNode, "judgmentVisualizerPosition1"); SaveValueMap(pointNode, "judgmentVisualizerLength"); SaveValueMap(pointNode, "judgmentVisualizerHeight"); SaveValueMap(pointNode, "judgmentVisualizerContentsLength"); SaveValueMap(pointNode, "judgmentVisualizerContentsHeight"); SaveAltMap("alt-judgment-visualizer"); SaveIntMap(pointNode, "hunterSystem"); SaveValueMap(pointNode, "hunterPosition0"); SaveValueMap(pointNode, "hunterPosition1"); SaveValueMapAsDefaultID("binHunterLength", "binLength"); SaveValueMapAsDefaultID("binHunterHeight", "binHeight"); SaveValueMapAsDefaultID("hunterFrontDrawingLength", "binHunterLength"); SaveAltMap("alt-hunter"); SaveIntMap(pointNode, "inputVisualizerSystem"); SaveValueMap(pointNode, "inputVisualizerPosition0"); SaveValueMap(pointNode, "inputVisualizerPosition1"); SaveValueMapAsDefaultID("binInputVisualizerLength", "binLength"); SaveValueMapAsDefaultID("binInputVisualizerHeight", "binHeight"); SaveAltMap("alt-input-visualizer"); SaveIntMap(pointNode, "earlyValueSystem"); SaveValueMap(pointNode, "earlyValuePosition0"); SaveValueMap(pointNode, "earlyValuePosition1"); SaveValueMapAsDefaultID("binEarlyValueLength", "binLength"); SaveValueMapAsDefaultID("binEarlyValueHeight", "binHeight"); SaveAltMap("alt-early-value"); SaveIntMap(pointNode, "lateValueSystem"); SaveValueMap(pointNode, "lateValuePosition0"); SaveValueMap(pointNode, "lateValuePosition1"); SaveValueMapAsDefaultID("binLateValueLength", "binLength"); SaveValueMapAsDefaultID("binLateValueHeight", "binHeight"); SaveAltMap("alt-late-value"); SaveIntMap(pointNode, "judgmentVSVisualizerSystem"); SaveValueMap(pointNode, "judgmentVSVisualizerPosition0"); SaveValueMap(pointNode, "judgmentVSVisualizerPosition1"); SaveValueMapAsDefaultID("binJudgmentVSVisualizerLength", "binLength"); SaveValueMapAsDefaultID("binJudgmentVSVisualizerHeight", "binHeight"); SaveValueMapAsDefaultID("judgmentVSVisualizerStopPointDrawingLength", "stopPointDrawingLength"); SaveAltMap("alt-judgment-vs-visualizer"); SaveValueMap(pointNode, "judgmentInputVisualizerPosition0"); SaveValueMap(pointNode, "judgmentInputVisualizerPosition1"); SaveValueMap(pointNode, "judgmentInputVisualizerLength"); SaveValueMap(pointNode, "judgmentInputVisualizerHeight"); SaveAltMap("alt-judgment-input-visualizer"); SaveValueMap(pointNode, "pausedUnpausePosition0", 539); SaveValueMap(pointNode, "pausedUnpausePosition1", 239); SaveValueMap(pointNode, "pausedUnpauseLength", 202); SaveValueMap(pointNode, "pausedUnpauseHeight", 53); SaveValueMap(pointNode, "pausedConfigurePosition0", 539); SaveValueMap(pointNode, "pausedConfigurePosition1", 302); SaveValueMap(pointNode, "pausedConfigureLength", 202); SaveValueMap(pointNode, "pausedConfigureHeight", 53); SaveValueMap(pointNode, "pausedUndoPosition0", 539); SaveValueMap(pointNode, "pausedUndoPosition1", 365); SaveValueMap(pointNode, "pausedUndoLength", 202); SaveValueMap(pointNode, "pausedUndoHeight", 53); SaveValueMap(pointNode, "pausedStopPosition0", 539); SaveValueMap(pointNode, "pausedStopPosition1", 428); SaveValueMap(pointNode, "pausedStopLength", 202); SaveValueMap(pointNode, "pausedStopHeight", 53); SaveValueMap(pointNode, "assistTextPosition1", 360.0); SaveValueMap(pointNode, "inputAssistTextPosition1", 480.0); for (var i = HighestNoteID; i > 0; --i) { drawingMap[i] = GetCalledText(Utility.GetText(lambdaNode, $"drawing{i}", i.ToString())).Split(',').Select(value => Utility.ToInt32(value, out var drawingPipeline) ? drawingPipeline : 0).Where(drawingPipeline => 0 < drawingPipeline && drawingPipeline < HighestNoteID).ToArray(); } DrawingInputModeMap[(int)Component.InputMode.InputMode4] = GetDrawingInputMode((int)Component.InputMode.InputMode4, "2, 3, 3, 2"); DrawingInputModeMap[(int)Component.InputMode.InputMode5] = GetDrawingInputMode((int)Component.InputMode.InputMode5, "2, 3, 4, 3, 2"); DrawingInputModeMap[(int)Component.InputMode.InputMode6] = GetDrawingInputMode((int)Component.InputMode.InputMode6, "2, 3, 2, 2, 3, 2"); DrawingInputModeMap[(int)Component.InputMode.InputMode7] = GetDrawingInputMode((int)Component.InputMode.InputMode7, "2, 3, 2, 5, 2, 3, 2"); DrawingInputModeMap[(int)Component.InputMode.InputMode8] = GetDrawingInputMode((int)Component.InputMode.InputMode8, "2, 3, 2, 3, 3, 2, 3, 2"); DrawingInputModeMap[(int)Component.InputMode.InputMode9] = GetDrawingInputMode((int)Component.InputMode.InputMode9, "2, 3, 2, 3, 4, 3, 2, 3, 2"); DrawingInputModeMap[(int)Component.InputMode.InputMode51] = GetDrawingInputMode((int)Component.InputMode.InputMode51, "1, 2, 3, 4, 3, 2"); DrawingInputModeMap[(int)Component.InputMode.InputMode71] = GetDrawingInputMode((int)Component.InputMode.InputMode71, "1, 2, 3, 2, 5, 2, 3, 2"); DrawingInputModeMap[(int)Component.InputMode.InputMode102] = GetDrawingInputMode2P((int)Component.InputMode.InputMode102, "1, 2, 3, 4, 3, 2, 2, 3, 4, 3, 2, 10"); DrawingInputModeMap[(int)Component.InputMode.InputMode142] = GetDrawingInputMode2P((int)Component.InputMode.InputMode142, "1, 2, 3, 2, 5, 2, 3, 2, 2, 3, 2, 5, 2, 3, 2, 10"); DrawingInputModeMap[(int)Component.InputMode.InputMode10] = GetDrawingInputMode((int)Component.InputMode.InputMode10, "2, 3, 2, 3, 2, 2, 3, 2, 3, 2"); DrawingInputModeMap[(int)Component.InputMode.InputMode242] = GetDrawingInputMode((int)Component.InputMode.InputMode242, "6, 9, 8, 7, 8, 7, 9, 8, 7, 8, 7, 8, 7, 9, 8, 7, 8, 7, 9, 8, 7, 8, 7, 8, 7, 11"); DrawingInputModeMap[(int)Component.InputMode.InputMode484] = GetDrawingInputMode((int)Component.InputMode.InputMode484, "6, 6, 9, 8, 7, 8, 7, 9, 8, 7, 8, 7, 8, 7, 9, 8, 7, 8, 7, 9, 8, 7, 8, 7, 8, 7, 9, 8, 7, 8, 7, 9, 8, 7, 8, 7, 8, 7, 9, 8, 7, 8, 7, 9, 8, 7, 8, 7, 8, 7, 11, 11"); if (DrawingInputModeMap[(int)Component.InputMode.InputMode484].Length == 51) { DrawingInputModeMap[(int)Component.InputMode.InputMode484] = new int[] { default }.Append(DrawingInputModeMap[(int)Component.InputMode.InputMode484][1]).Concat(DrawingInputModeMap[(int)Component.InputMode.InputMode484].Skip(1)).Append(DrawingInputModeMap[(int)Component.InputMode.InputMode484][50]).ToArray(); } DrawingPipeline.AddRange(GetCalledText(Utility.GetText(lambdaNode, "drawingPipeline", string.Join(", ", Enumerable.Range(0, HighestNoteID)))).Split(',').Select(value => Utility.ToInt32(value.Trim(), out var drawingPipeline) ? drawingPipeline : 0).Where(drawingPipeline => drawingPipeline < HighestNoteID)); int[] GetDrawingInputMode(int mode, string defaultValue) { return new int[] { default }.Concat(GetCalledText(Utility.GetText(lambdaNode, $"drawingInputMode{mode}", defaultValue)).Split(',').Select(value => Utility.ToInt32(value.Trim(), out var drawingPipeline) ? drawingPipeline : 0).Where(drawingPipeline => 0 < drawingPipeline && drawingPipeline < HighestNoteID)).ToArray(); } int[] GetDrawingInputMode2P(int mode, string defaultValue) { var drawingInputModeMap = GetDrawingInputMode(mode, defaultValue).Skip(1).ToArray(); return IntMap["drawingInputModeSystem"] switch { 0 => new int[] { default }.Concat(drawingInputModeMap).Concat(drawingInputModeMap.Skip(1)).Append(drawingInputModeMap.First()).ToArray(), 1 => new int[] { default }.Concat(drawingInputModeMap).Concat(drawingInputModeMap.Reverse()).ToArray(), 2 => new int[] { default }.Concat(drawingInputModeMap).ToArray(), _ => throw new ArgumentException("drawingInputModeSystem") }; } double GetCalledValue(YamlNode yamlNode, string target, string defaultValue = null) { var text = Utility.GetText(yamlNode, target, defaultValue); if (Utility.ToFloat64(text, out var r)) { return r; } else if (QwilightComponent.GetCallComputer().IsMatch(text)) { var values = text.Split("(").Select(value => value.Trim()).ToArray(); return lsCaller.Call(lsCaller.Globals[values[0]], values[1][0..^1].Split(',').Where(value => !string.IsNullOrEmpty(value)).Select(value => Utility.ToFloat64(value) as object).ToArray()).Number; } else { throw new ArgumentException(target.ToString()); } } string GetCalledText(string text) { if (QwilightComponent.GetCallComputer().IsMatch(text)) { var values = text.Split("("); text = lsCaller.Call(lsCaller.Globals[values[0]], values[1][0..^1].Split(',').Where(value => !string.IsNullOrEmpty(value)).Select(value => Utility.ToInt32(value.Trim(), out var arg) ? (object)arg : value as object).ToArray()).String; } return text; } static string[] GetCalledData(YamlNode yamlNode, string target, string[] defaultValues = null) { var text = Utility.GetText(yamlNode, target); if (string.IsNullOrEmpty(text)) { return defaultValues; } else { return text.Split(',').Select(value => value.Trim()).ToArray(); } } void SaveInt(YamlNode yamlNode, string target, int defaultValue = default) { var text = Utility.GetText(yamlNode, target); if (!string.IsNullOrEmpty(text) && Utility.ToInt32(text, out var value)) { IntMap[target] = value; } else { IntMap[target] = defaultValue; } } void SaveIntMap(YamlNode yamlNode, string target, int defaultValue = default) { var text = Utility.GetText(yamlNode, target); if (string.IsNullOrEmpty(text)) { IntMap[target] = defaultValue; } else { SaveIntMapImpl(text, target, IntMap, IntCallMap); } } void SaveSplitValueMap(string target, double defaultValue = default) { var data = GetCalledData(pointNode, target); if (data != null) { string lastData = null; for (var i = 0; i < HighestNoteID; ++i) { var t = data.ElementAtOrDefault(i) ?? "~"; var s = t != "~" ? t : lastData; SaveValueMapImpl(s, $"{target}{i + 1}", ValueMap, ValueCallMap); lastData = s; } } else { for (var i = HighestNoteID - 1; i >= 0; --i) { ValueMap[$"{target}{i + 1}"] = defaultValue; } } } void SaveSplitValueMapAsDefaultID(string target, string defaultValueID = null, Func<double, double> valueMapping = null) { var data = GetCalledData(pointNode, target); if (data != null) { string lastData = null; for (var i = 0; i < HighestNoteID; ++i) { var t = data.ElementAtOrDefault(i) ?? "~"; var s = t != "~" ? t : lastData; SaveValueMapImpl(s, $"{target}{i + 1}", ValueMap, ValueCallMap); lastData = s; } } else { for (var i = HighestNoteID - 1; i >= 0; --i) { if (ValueMap.TryGetValue(defaultValueID, out var defaultValue)) { ValueMap[$"{target}{i + 1}"] = valueMapping?.Invoke(defaultValue) ?? defaultValue; } } } } void SaveValueMap(YamlNode yamlNode, string target, double defaultValue = default) { var text = Utility.GetText(yamlNode, target); if (string.IsNullOrEmpty(text)) { ValueMap[target] = defaultValue; } else { SaveValueMapImpl(text, target, ValueMap, ValueCallMap); } } void SaveValueMapAsDefaultID(string target, string defaultValueID, Func<double, double> valueMapping = null) { var text = Utility.GetText(pointNode, target); if (string.IsNullOrEmpty(text)) { if (ValueMap.TryGetValue(defaultValueID, out var defaultValue)) { ValueMap[target] = valueMapping?.Invoke(defaultValue) ?? defaultValue; } } else { SaveValueMapImpl(text, target, ValueMap, ValueCallMap); } } void SaveAltMap(string target, int defaultValue = default) { var text = Utility.GetText(lambdaNode, target); if (string.IsNullOrEmpty(text)) { AltMap[target] = defaultValue; } else { SaveAltImpl(text, target, AltMap, AltCallMap); } } for (var i = PaintPropertyValues.Length - 1; i >= 0; --i) { var data = GetCalledData(pointNode, $"paintProperty{i}"); if (data?.Length > 4) { var paintProperty = new PaintProperty(); SavePaintMap(PaintProperty.ID.Position0, 0); SavePaintMap(PaintProperty.ID.Position1, 1); SavePaintMap(PaintProperty.ID.Length, 2); SavePaintMap(PaintProperty.ID.Height, 3); SavePaintAlt(PaintProperty.ID.Alt, 4); SavePaintInt(PaintProperty.ID.Frame, 5, 1); SavePaintValue(PaintProperty.ID.Framerate, 6); SavePaintInt(PaintProperty.ID.Mode, 7); SavePaintInt(PaintProperty.ID.Pipeline, 8, -1); SavePaintInt(PaintProperty.ID.Composition, 9); PaintPropertyValues[i] = paintProperty; void SavePaintMap(PaintProperty.ID target, int paintPosition, double defaultValue = default) { if (paintPosition < data.Length) { SaveValueMapImpl(data[paintPosition], target, paintProperty.ValueMap, paintProperty.ValueCallMap); } else { paintProperty.ValueMap[target] = defaultValue; } } void SavePaintAlt(PaintProperty.ID target, int paintPosition, int defaultValue = default) { if (paintPosition < data.Length) { SaveAltImpl(data[paintPosition], target, paintProperty.AltMap, paintProperty.AltCallMap); } else { paintProperty.AltMap[target] = defaultValue; } } void SavePaintValue(PaintProperty.ID target, int paintPosition, double defaultValue = default) { var text = data.ElementAtOrDefault(paintPosition); if (!string.IsNullOrEmpty(text) && Utility.ToFloat64(data[paintPosition], out var value)) { paintProperty.ValueMap[target] = value; } else { paintProperty.ValueMap[target] = defaultValue; } } void SavePaintInt(PaintProperty.ID target, int paintPosition, int defaultValue = default) { if (paintPosition < data.Length) { SaveIntMapImpl(data[paintPosition], target, paintProperty.IntMap, paintProperty.IntCallMap); } else { paintProperty.IntMap[target] = defaultValue; } } } } static void SaveIntMapImpl<T>(string text, T target, Dictionary<T, int> toIntMap, Dictionary<T, string[]> toCallMap) { if (Utility.ToInt32(text, out var r)) { toIntMap[target] = r; } else if (QwilightComponent.GetCallComputer().IsMatch(text)) { var data = new List<string>(); var values = text.Split("("); data.Add(values[0]); data.AddRange(values[1][0..^1].Split(',').Where(value => !string.IsNullOrEmpty(value)).Select(value => value.Trim())); toCallMap[target] = data.ToArray(); } else { throw new ArgumentException(target.ToString()); } } static void SaveValueMapImpl<T>(string text, T target, Dictionary<T, double> toValueMap, Dictionary<T, string[]> toCallMap) { if (Utility.ToFloat64(text, out var r)) { toValueMap[target] = r; } else if (QwilightComponent.GetCallComputer().IsMatch(text)) { var data = new List<string>(); var values = text.Split("("); data.Add(values[0]); data.AddRange(values[1][0..^1].Split(',').Where(value => !string.IsNullOrEmpty(value)).Select(value => value.Trim())); toCallMap[target] = data.ToArray(); } else { throw new ArgumentException(target.ToString()); } } static void SaveAltImpl<T>(string text, T target, Dictionary<T, int> altMap, Dictionary<T, string[]> toCallMap) { switch (text) { case "0": altMap[target] = 0; break; case "1": altMap[target] = 3; break; case "2": altMap[target] = 2; break; default: if (QwilightComponent.GetCallComputer().IsMatch(text)) { var data = new List<string>(); var values = text.Split("("); data.Add(values[0]); data.AddRange(values[1][0..^1].Split(',').Where(value => !string.IsNullOrEmpty(value)).Select(value => value.Trim())); toCallMap[target] = data.ToArray(); } else { throw new ArgumentException(target.ToString()); } break; } } } var getNote = new Func<int[], string>(args => "N"); var getHitNotePaint = new Func<int[], string>(args => "N"); var getHitLongNotePaint = new Func<int[], string>(args => "L"); var getJudgmentPaint = new Func<int[], string>(args => "J"); var getMain = new Func<int[], string>(args => "M"); var getWall = new Func<int[], string>(args => "W"); var get = new Func<int[], string>(args => "W"); var getAutoInput = new Func<int[], string>(args => "A"); var getAutoMain = new Func<int[], string>(args => "AM"); var getPause = new Func<int[], string>(args => "PS"); var getJudgmentMain = new Func<int[], string>(args => "J"); var getMainJudgmentMeter = new Func<int[], string>(args => "JM"); var getInput = new Func<int[], string>(args => "I"); var getLevel = new Func<int[], string>(args => "L"); var getPaintProperty = new Func<int[], string>(args => "P"); var getHighestBandBin = new Func<int[], string>(args => "HC"); var getStandBin = new Func<int[], string>(args => "S"); var getBandBin = new Func<int[], string>(args => "C"); SetLambda("_GetNote", ref getNote); SetLambda("_GetHitNotePaint", ref getHitNotePaint); SetLambda("_GetHitLongNotePaint", ref getHitLongNotePaint); SetLambda("_GetJudgmentPaint", ref getJudgmentPaint); SetLambda("_GetMain", ref getMain); SetLambda("_GetWall", ref getWall); SetLambda("_GetAutoInput", ref getAutoInput); SetLambda("_GetAutoMain", ref getAutoMain); SetLambda("_GetJudgmentMain", ref getJudgmentMain); SetLambda("_GetMainJudgmentMeter", ref getMainJudgmentMeter); SetLambda("_GetInput", ref getInput); SetLambda("_GetPaintProperty", ref getPaintProperty); SetLambda("_GetHighestBandBin", ref getHighestBandBin); SetLambda("_GetStandBin", ref getStandBin); SetLambda("_GetBandBin", ref getBandBin); void SetLambda(string lambdaName, ref Func<int[], string> lambda) { var value = lsCaller.Globals[lambdaName]; if (value != null) { lambda = new Func<int[], string>(args => { try { return lsCaller.Call(value, args).String; } catch { throw new ArgumentException($"{lambdaName}([{string.Join(", ", args)}])"); } }); } } foreach (var (toCallID, values) in IntCallMap) { if (!IntMap.ContainsKey(toCallID)) { var lambdaName = values[0]; var value = lsCaller.Globals[lambdaName]; if (value != null) { try { IntMap[toCallID] = (int)lsCaller.Call(value, values.Skip(1).Select(value => Utility.ToFloat64(value) as object).ToArray()).Number; } catch { // 여기서는 불가능한 연산들 } } else { throw new ArgumentException($"{lambdaName}({string.Join(", ", values.Skip(1))})"); } } } foreach (var paintPropertyValue in PaintPropertyValues.Where(paintPropertyValue => paintPropertyValue != null)) { foreach (var (toCallID, values) in paintPropertyValue.IntCallMap) { if (!paintPropertyValue.IntMap.ContainsKey(toCallID)) { var lambdaName = values[0]; var lambdaValue = lsCaller.Globals[lambdaName]; if (lambdaValue != null) { try { paintPropertyValue.IntMap[toCallID] = (int)lsCaller.Call(lsCaller.Globals[values[0]], values.Skip(1).Select(value => Utility.ToFloat64(value) as object).ToArray()).Number; } catch { // 여기서는 불가능한 연산들 } } else { throw new ArgumentException($"{lambdaName}({string.Join(", ", values.Skip(1))})"); } } } switch (paintPropertyValue.IntMap[PaintProperty.ID.Mode]) { case 0: case 2: paintPropertyValue.Drawings = new DrawingItem?[paintPropertyValue.IntMap[PaintProperty.ID.Frame]]; break; case 1: paintPropertyValue.Drawings = new DrawingItem?[paintPropertyValue.IntMap[PaintProperty.ID.Frame] + 1]; break; } } for (var i = BinJudgmentValueMap.Length - 1; i >= 0; --i) { BinJudgmentValueMap[i] = new DrawingItem?[10]; } IntMap.TryGetValue("judgment-frame", out var judgmentFrame); for (var i = JudgmentDrawings.Length - 1; i >= 0; --i) { JudgmentDrawings[i] = new DrawingItem?[judgmentFrame]; } IntMap.TryGetValue("band!-frame", out var band1Frame); JudgmentDrawings[JudgmentPaint.Band1] = new DrawingItem?[band1Frame]; IntMap.TryGetValue("last-frame", out var lastFrame); JudgmentDrawings[JudgmentPaint.Last] = new DrawingItem?[lastFrame]; if (!IntMap.TryGetValue("band-frame", out var bandFrame)) { bandFrame = 1; IntMap["band-frame"] = bandFrame; } BinBandMap = new DrawingItem?[10, bandFrame]; IntMap.TryGetValue("note-hit-frame", out var noteHitFrame); for (var i = noteHitDrawings.Length - 1; i > 0; --i) { noteHitDrawings[i] = new DrawingItem?[noteHitFrame]; } IntMap.TryGetValue("long-note-hit-frame", out var longNoteHitFrame); for (var i = longNoteHitDrawings.Length - 1; i > 0; --i) { longNoteHitDrawings[i] = new DrawingItem?[longNoteHitFrame]; } if (!IntMap.TryGetValue("long-note-hit-loop-frame", out var longNoteHitLoopFrame)) { longNoteHitLoopFrame = longNoteHitFrame; IntMap["long-note-hit-loop-frame"] = longNoteHitLoopFrame; } if (!IntMap.TryGetValue("last-enlarged-band-loop-frame", out var lastEnlargedBandLoopFrame)) { lastEnlargedBandLoopFrame = longNoteHitLoopFrame; IntMap["last-enlarged-band-loop-frame"] = lastEnlargedBandLoopFrame; } IntMap.TryGetValue("main-frame", out var mainFrame); for (var i = mainDrawings.Length - 1; i > 0; --i) { mainDrawings[i] = new DrawingItem?[mainFrame + 1]; } IntMap.TryGetValue("judgment-main-frame", out var judgmentMainFrame); for (var i = judgmentMainDrawings.Length - 1; i > 0; --i) { judgmentMainDrawings[i] = new DrawingItem?[judgmentMainFrame + 1]; } IntMap.TryGetValue("input-frame", out var inputFrame); for (var i = inputDrawings.Length - 1; i > 0; --i) { inputDrawings[i] = new DrawingItem?[inputFrame + 1]; } IntMap.TryGetValue("level-frame", out var levelFrame); for (var i = LevelDrawings.Length - 1; i >= 0; --i) { LevelDrawings[i] = new DrawingItem?[levelFrame]; } IntMap.TryGetValue("note-frame", out var noteFrame); for (var i = noteDrawings.Length - 1; i >= 0; --i) { noteDrawings[i] = new DrawingItem?[noteFrame][][]; for (var j = noteDrawings[i].Length - 1; j >= 0; --j) { noteDrawings[i][j] = new DrawingItem?[18][]; for (var m = noteDrawings[i][j].Length - 1; m >= 0; --m) { noteDrawings[i][j][m] = new DrawingItem?[3]; } } } IntMap.TryGetValue("auto-main-frame", out var autoMainFrame); AutoMainDrawings = new DrawingItem?[autoMainFrame]; IntMap.TryGetValue("pause-frame", out var pauseFrame); for (var i = PauseDrawings.Length - 1; i >= 0; --i) { PauseDrawings[i] = new DrawingItem?[pauseFrame]; } IntMap.TryGetValue("main-judgment-meter-frame", out var mainJudgmentMeterFrame); for (var i = mainJudgmentMeterDrawings.Length - 1; i > 0; --i) { mainJudgmentMeterDrawings[i] = new Dictionary<int, DrawingItem?>(); } DrawingItem? pointUnitDrawing = null; DrawingItem? multiplierUnitDrawing = null; DrawingItem? stopPointDrawing = null; DrawingItem? lowerDrawing = null; DrawingItem? higherDrawing = null; var binMap = new DrawingItem?[10]; var audioValues = new ConcurrentDictionary<string, AudioItem>(); var drawingValues = new ConcurrentDictionary<string, DrawingItem>(); var handledDrawingValues = new ConcurrentDictionary<string, HandledDrawingItem>(); var zipFilePath = Path.Combine(QwilightComponent.UIEntryPath, target.UIEntry, Path.ChangeExtension(zipName, "zip")); var fileNames = new HashSet<string>(); if (File.Exists(zipFilePath)) { using var zipFile = new ZipFile(zipFilePath); foreach (var zipEntry in zipFile) { if (!zipEntry.IsDirectory) { var rms = PoolSystem.Instance.GetDataFlow((int)zipEntry.UncompressedSize); zipEntry.Extract(rms); SetDrawing(zipEntry.FileName, rms); } } } foreach (var pausedFileName in new[] { "Configure 0.png", "Configure 1.png", "Stop 0.png", "Stop 1.png", "Undo 0.png", "Undo 1.png", "Unpause 0.png", "Unpause 1.png" }) { if (!fileNames.Contains($"Paused/{pausedFileName}")) { SetDrawing($"Paused/{pausedFileName}", File.OpenRead(Path.Combine(QwilightComponent.AssetsEntryPath, "Paused", pausedFileName))); } } void SetDrawing(string fileName, Stream s) { var justFileName = Path.GetFileNameWithoutExtension(fileName); fileNames.Add(fileName); switch (Path.GetDirectoryName(fileName)) { case "Audio": parallelItems.Add(() => { try { using (s) { audioValues[fileName] = AudioSystem.Instance.Load(s, this, 1F, null, QwilightComponent.GetLoopingAudioComputer().IsMatch(justFileName)); } } catch { } }); break; case "Note": case "Main": NewDrawing(s, true); break; case "Drawing": switch (justFileName) { case "Veil": NewHandledDrawing(s); break; default: NewDrawing(s); break; } break; default: NewDrawing(s); break; } void NewDrawing(Stream s, bool setAverage = false) => parallelItems.Add(() => { try { using (s) { drawingValues[fileName] = DrawingSystem.Instance.Load(s, this, setAverage); } } catch { } }); void NewHandledDrawing(Stream s) { parallelItems.Add(() => { using (s) { try { handledDrawingValues[fileName] = new HandledDrawingItem { Drawing = DrawingSystem.Instance.Load(s, this), DefaultDrawing = DrawingSystem.Instance.LoadDefault(s, this) }; } catch { } } }); } } if (src != target) { AudioSystem.Instance.Close(this); DrawingSystem.Instance.Close(this); } Utility.HandleLowlyParallelly(parallelItems, Configure.Instance.UIBin, parallelItem => parallelItem()); foreach (var fileName in audioValues.Keys) { var justFileName = Path.GetFileNameWithoutExtension(fileName); var audioItem = audioValues[fileName]; if (Path.GetDirectoryName(fileName) == "Audio") { _audioItemMap[justFileName] = audioItem; } } foreach (var (fileName, drawingItem) in drawingValues.OrderBy(drawingValue => drawingValue.Key)) { var justFileName = Path.GetFileNameWithoutExtension(fileName); switch (Path.GetDirectoryName(fileName)) { case "Paint": var fileNameContents = justFileName.Split(' '); var main = Utility.ToInt32(fileNameContents.ElementAtOrDefault(1)); var frame = Utility.ToInt32(fileNameContents.ElementAtOrDefault(2)); if (fileNameContents[0] == getHitNotePaint(new[] { main, frame })) { switch (fileNameContents.Length) { case 2: for (var i = HighestNoteID; i > 0; --i) { noteHitDrawings.SetValue(i, main, drawingItem); } break; case 3: foreach (var drawingMapValue in drawingMap[main]) { noteHitDrawings.SetValue(drawingMapValue, frame, drawingItem); } break; } } else if (fileNameContents[0] == getHitLongNotePaint(new[] { main, frame })) { switch (fileNameContents.Length) { case 2: for (var i = HighestNoteID; i > 0; --i) { longNoteHitDrawings.SetValue(i, main, drawingItem); } break; case 3: foreach (var drawingMapValue in drawingMap[main]) { longNoteHitDrawings.SetValue(drawingMapValue, frame, drawingItem); } break; } } else if (fileNameContents[0] == getJudgmentPaint(new[] { main, frame })) { JudgmentDrawings.SetValue(main, frame, drawingItem); } break; case "Drawing": fileNameContents = justFileName.Split(' '); Utility.ToInt32(fileNameContents.ElementAtOrDefault(1), out var value1); Utility.ToInt32(fileNameContents.ElementAtOrDefault(2), out var value2); if (fileNameContents[0] == getPaintProperty(new[] { value1, value2 })) { Utility.GetValue(PaintPropertyValues, value1)?.Drawings?.SetValue(fileNameContents.Length >= 3 ? value2 : 0, drawingItem); } else if (fileNameContents[0] == getAutoMain(new[] { value1 })) { AutoMainDrawings[value1] = drawingItem; } else if (fileNameContents[0] == getPause(new[] { value1, value2 })) { PauseDrawings.SetValue(value1, value2, drawingItem); } else if (justFileName.IsFrontCaselsss("JI")) { if (Utility.ToInt32(justFileName.Split(' ')[1], out var i)) { JudgmentInputDrawings.SetValue(i, drawingItem); } } else if (justFileName.IsFrontCaselsss("J")) { if (Utility.ToInt32(justFileName.Split(' ')[1], out var i)) { JudgmentPointsDrawings.SetValue(i, drawingItem); } } else if (justFileName.IsFrontCaselsss("HP")) { if (Utility.ToInt32(justFileName.Split(' ')[1], out var i)) { HitPointsDrawings.SetValue(i, drawingItem); } } else { switch (justFileName) { case "Status": StatusDrawing = drawingItem; break; case "Status Slider": StatusSliderDrawing = drawingItem; break; } } break; case "Note": fileNameContents = justFileName.Split(' '); main = Utility.ToInt32(fileNameContents.ElementAtOrDefault(1)); frame = Utility.ToInt32(fileNameContents.ElementAtOrDefault(2)); var text = Utility.ToInt32(fileNameContents.ElementAtOrDefault(3)); var longNoteContents = Utility.ToInt32(fileNameContents.ElementAtOrDefault(4)); if (fileNameContents[0] == getNote(new[] { main, frame, text, longNoteContents })) { var status = fileNameContents.Length > 4 ? longNoteContents : LongNote.LongNoteBefore; foreach (var drawingMapValue in drawingMap[main]) { noteDrawings.SetValue(drawingMapValue, frame, text, status, drawingItem); } } break; case "Main": fileNameContents = justFileName.Split(' '); main = Utility.ToInt32(fileNameContents.ElementAtOrDefault(1)); frame = Utility.ToInt32(fileNameContents.ElementAtOrDefault(2)); if (fileNameContents[0] == getMain(new[] { main, frame })) { foreach (var drawingMapValue in drawingMap[main]) { mainDrawings.SetValue(drawingMapValue, frame, drawingItem); } } else if (fileNameContents[0] == getWall(new[] { main, frame })) { MainWalls.SetValue(main, drawingItem); } else if (fileNameContents[0] == getAutoInput(new[] { main, frame })) { foreach (var drawingMapValue in drawingMap[main]) { autoInputDrawings.SetValue(drawingMapValue, drawingItem); } } else if (fileNameContents[0] == getJudgmentMain(new[] { main, frame })) { foreach (var drawingMapValue in drawingMap[main]) { judgmentMainDrawings.SetValue(drawingMapValue, frame, drawingItem); } } else if (fileNameContents[0] == getMainJudgmentMeter(new[] { main, frame })) { if (main > 0) { foreach (var drawingMapValue in drawingMap[main]) { mainJudgmentMeterDrawings[drawingMapValue][frame] = drawingItem; } } else { for (var i = drawingMap.Length - 1; i > 0; --i) { mainJudgmentMeterDrawings[i][frame] = drawingItem; } } } break; case "Input": fileNameContents = justFileName.Split(' '); main = Utility.ToInt32(fileNameContents[1]); frame = Utility.ToInt32(fileNameContents[2]); if (fileNameContents[0] == getInput(new[] { main, frame })) { foreach (var drawingMapValue in drawingMap[main]) { if (drawingMapValue > 0) { inputDrawings.SetValue(drawingMapValue, frame, drawingItem); } } } break; case "Level": fileNameContents = justFileName.Split(' '); main = Utility.ToInt32(fileNameContents[1]); frame = Utility.ToInt32(fileNameContents[2]); if (fileNameContents[0] == getLevel(new[] { main, frame })) { LevelDrawings.SetValue(main, frame, drawingItem); } break; case "Paused": fileNameContents = justFileName.Split(' '); switch (fileNameContents[0]) { case "Unpause": PausedUnpauseDrawings[Utility.ToInt32(fileNameContents[1])] = drawingItem; break; case "Stop": PausedStopDrawings[Utility.ToInt32(fileNameContents[1])] = drawingItem; break; case "Undo": PausedUndoDrawings[Utility.ToInt32(fileNameContents[1])] = drawingItem; break; case "Configure": PausedConfigureDrawings[Utility.ToInt32(fileNameContents[1])] = drawingItem; break; } break; case "Bin": switch (justFileName) { case "%": pointUnitDrawing = drawingItem; break; case ",": CommaDrawing = drawingItem; break; case ".": stopPointDrawing = drawingItem; break; case "..": ColonDrawing = drawingItem; break; case "+": higherDrawing = drawingItem; break; case "-": lowerDrawing = drawingItem; break; case "BPM": BPMUnitDrawing = drawingItem; break; case "Millis": JudgmentMeterUnitDrawing = drawingItem; break; case "Slash": SlashDrawing = drawingItem; break; case "X": multiplierUnitDrawing = drawingItem; break; default: fileNameContents = justFileName.Split(' '); Utility.ToInt32(fileNameContents.ElementAtOrDefault(1), out value1); Utility.ToInt32(fileNameContents.ElementAtOrDefault(2), out value2); if (Utility.ToInt32(justFileName, out var bin)) { binMap.SetValue(bin, drawingItem); } else if (fileNameContents[0].IsFrontCaselsss("A")) { switch (justFileName) { case "AW": AudioMultiplierUnitDrawing = drawingItem; break; case "A .": AudioMultiplierStopPointDrawing = drawingItem; break; default: BinAudioMultiplierMap.SetValue(value1, drawingItem); break; } } else if (fileNameContents[0] == "B") { BinBPMMap.SetValue(value1, drawingItem); } else if (fileNameContents[0] == getBandBin(new[] { value1, value2 })) { switch (fileNameContents.Length) { case 2: BinBandMap.SetValue(value1, 0, drawingItem); break; case 3: BinBandMap.SetValue(value1, value2, drawingItem); break; } } else if (fileNameContents[0] == "E") { BinEarlyValueMap.SetValue(value1, drawingItem); } else if (fileNameContents[0] == getHighestBandBin(new[] { value1 })) { BinHighestBandMap.SetValue(value1, drawingItem); } else if (fileNameContents[0] == "HU") { switch (justFileName) { case "HU +": HunterHigherDrawing = drawingItem; break; case "HU -": HunterLowerDrawing = drawingItem; break; default: BinHunterMap.SetValue(value1, drawingItem); break; } } else if (fileNameContents[0] == "HH") { switch (justFileName) { case "HH .": JudgmentVSVisualizerStopPointDrawing = drawingItem; break; default: BinJudgmentVSVisualizerMap.SetValue(value1, drawingItem); break; } } else if (fileNameContents[0] == "HP") { switch (justFileName) { case "HP %": HitPointsVisualizerUnitDrawing = drawingItem; break; default: BinHitPointsVisualizerMap.SetValue(value1, drawingItem); break; } } else if (fileNameContents[0] == "IS") { BinInputVisualizerMap.SetValue(value1, drawingItem); } else if (fileNameContents[0] == "JM") { switch (justFileName) { case "JM -": JudgmentMeterLowerDrawing = drawingItem; break; case "JM +": JudgmentMererHigherDrawing = drawingItem; break; default: BinJudgmentMeterMap.SetValue(value1, drawingItem); break; } } else if (fileNameContents[0] == "J") { BinJudgmentValueMap.SetValue(value1, value2, drawingItem); } else if (fileNameContents[0] == "L") { BinLateValueMap.SetValue(value1, drawingItem); } else if (fileNameContents[0].IsFrontCaselsss("M")) { switch (justFileName) { case "MW": MultiplierUnitDrawing = drawingItem; break; case "M .": MultiplierStopPointDrawing = drawingItem; break; default: BinMultiplierMap.SetValue(value1, drawingItem); break; } } else if (fileNameContents[0] == "P") { switch (justFileName) { case "P %": PointUnitDrawing = drawingItem; break; case "P .": PointStopPointDrawing = drawingItem; break; default: BinPointMap.SetValue(value1, drawingItem); break; } } else if (fileNameContents[0] == getStandBin(new[] { value1 })) { BinStandMap.SetValue(value1, drawingItem); } else if (fileNameContents[0] == "W") { BinHmsMap.SetValue(value1, drawingItem); } break; } break; } } foreach (var (fileName, handledDrawingItem) in handledDrawingValues.OrderBy(handledDrawingValue => handledDrawingValue.Key)) { var justFileName = Path.GetFileNameWithoutExtension(fileName); switch (Path.GetDirectoryName(fileName)) { case "Drawing": switch (justFileName) { case "Veil": VeilDrawing = handledDrawingItem; break; } break; } } for (var i = (int)Component.Judged.Lowest; i >= (int)Component.Judged.Highest; --i) { for (var j = 1; j < judgmentFrame; ++j) { JudgmentDrawings[i][j] ??= JudgmentDrawings[i][j - 1]; } } for (var i = 1; i < band1Frame; ++i) { JudgmentDrawings[JudgmentPaint.Band1][i] ??= JudgmentDrawings[JudgmentPaint.Band1][i - 1]; } for (var i = 1; i < lastFrame; ++i) { JudgmentDrawings[JudgmentPaint.Last][i] ??= JudgmentDrawings[JudgmentPaint.Last][i - 1]; } for (var i = noteDrawings.Length - 1; i > 0; --i) { for (var j = noteFrame - 1; j >= 0; --j) { noteDrawings[i][j][TrapNote.TrapNoteContents][LongNote.LongNoteBefore] ??= noteDrawings[0][j][InputNote.InputNoteContents][LongNote.LongNoteBefore]; for (var m = InputNote.NeutralPostableItemNoteContents; m >= TrapNote.TrapNoteContents; --m) { noteDrawings[i][j][m][LongNote.LongNoteBefore] ??= noteDrawings[0][j][m][LongNote.LongNoteBefore]; } } } for (var i = noteDrawings.Length - 1; i > 0; --i) { for (var j = noteFrame - 1; j >= 0; --j) { for (var m = InputNote.NeutralPostableItemNoteContents; m >= InputNote.InputNoteContents; --m) { for (var o = LongNote.LongNoteFailed; o > LongNote.LongNoteBefore; --o) { noteDrawings[i][j][m][o] ??= noteDrawings[i][j][m][LongNote.LongNoteBefore]; } } } } for (var i = noteDrawings.Length - 1; i >= 0; --i) { for (var j = noteFrame - 1; j >= 0; --j) { for (var m = LongNote.LongNoteFailed; m >= LongNote.LongNoteBefore; --m) { noteDrawings[i][j][VoidNote.VoidNoteContents][m] ??= noteDrawings[i][j][TrapNote.TrapNoteContents][m]; } } } for (var i = noteDrawings.Length - 1; i >= 0; --i) { for (var j = 1; j < noteFrame; ++j) { for (var m = InputNote.NeutralPostableItemNoteContents; m >= InputNote.InputNoteContents; --m) { for (var o = LongNote.LongNoteFailed; o >= LongNote.LongNoteBefore; --o) { noteDrawings[i][j][m][o] ??= noteDrawings[i][j - 1][m][o]; } } } } var lowestHitFrame = Math.Min(longNoteHitFrame, noteHitFrame); if (lowestHitFrame > 0) { for (var i = longNoteHitDrawings.Length - 1; i > 0; --i) { for (var j = lowestHitFrame - 1; j >= 0; --j) { longNoteHitDrawings[i][j] ??= noteHitDrawings[i][j]; } } } if (mainFrame > 0) { for (var i = mainDrawings.Length - 1; i > 0; --i) { for (var j = 1; j <= mainFrame; ++j) { mainDrawings[i][j] ??= mainDrawings[i][j - 1]; } } } if (judgmentMainFrame > 0) { for (var i = judgmentMainDrawings.Length - 1; i > 0; --i) { for (var j = 1; j <= judgmentMainFrame; ++j) { judgmentMainDrawings[i][j] ??= judgmentMainDrawings[i][j - 1]; } } } if (mainJudgmentMeterFrame > 0) { for (var i = mainJudgmentMeterDrawings.Length - 1; i > 0; --i) { for (var j = 1; j <= mainJudgmentMeterFrame; ++j) { if (mainJudgmentMeterDrawings[i].ContainsKey(j - 1)) { mainJudgmentMeterDrawings[i][j] ??= mainJudgmentMeterDrawings[i][j - 1]; } } for (var j = -1; j >= -mainJudgmentMeterFrame; --j) { if (mainJudgmentMeterDrawings[i].ContainsKey(j + 1)) { mainJudgmentMeterDrawings[i][j] ??= mainJudgmentMeterDrawings[i][j + 1]; } } } } if (inputFrame > 0) { for (var i = inputDrawings.Length - 1; i > 0; --i) { for (var j = 1; j <= inputFrame; ++j) { inputDrawings[i][j] ??= inputDrawings[i][j - 1]; } } } if (levelFrame > 0) { for (var i = LevelDrawings.Length - 1; i >= 0; --i) { for (var j = 1; j < levelFrame; ++j) { LevelDrawings[i][j] ??= LevelDrawings[i][j - 1]; } } } if (autoMainFrame > 0) { for (var i = 1; i < autoMainFrame; ++i) { AutoMainDrawings[i] ??= AutoMainDrawings[i - 1]; } } if (pauseFrame > 0) { for (var i = PauseDrawings.Length - 1; i > 0; --i) { for (var j = 1; j < pauseFrame; ++j) { PauseDrawings[i][j] ??= PauseDrawings[i][j - 1]; } } } for (var i = 9; i >= 0; --i) { BinBandMap[i, 0] ??= binMap[i]; for (var j = 0; j < bandFrame; ++j) { if (BinBandMap[i, j] == null) { for (var m = j - 1; m >= 0; --m) { if (BinBandMap[i, m] != null) { BinBandMap[i, j] ??= BinBandMap[i, m]; break; } } } } for (var j = (int)Component.Judged.Lowest; j >= (int)Component.Judged.Highest; --j) { BinJudgmentValueMap[j][i] ??= binMap[i]; } BinStandMap[i] ??= binMap[i]; BinPointMap[i] ??= binMap[i]; BinHmsMap[i] ??= binMap[i]; BinHitPointsVisualizerMap[i] ??= binMap[i]; BinJudgmentMeterMap[i] ??= binMap[i]; BinHighestBandMap[i] ??= binMap[i]; BinInputVisualizerMap[i] ??= binMap[i]; BinAudioMultiplierMap[i] ??= binMap[i]; BinMultiplierMap[i] ??= binMap[i]; BinBPMMap[i] ??= binMap[i]; BinHunterMap[i] ??= binMap[i]; BinEarlyValueMap[i] ??= binMap[i]; BinLateValueMap[i] ??= binMap[i]; BinJudgmentVSVisualizerMap[i] ??= binMap[i]; } HitPointsVisualizerUnitDrawing ??= pointUnitDrawing; PointUnitDrawing ??= pointUnitDrawing; PointStopPointDrawing ??= stopPointDrawing; MultiplierStopPointDrawing ??= stopPointDrawing; AudioMultiplierStopPointDrawing ??= stopPointDrawing; JudgmentVSVisualizerStopPointDrawing ??= stopPointDrawing; MultiplierUnitDrawing ??= multiplierUnitDrawing; AudioMultiplierUnitDrawing ??= multiplierUnitDrawing; JudgmentMeterLowerDrawing ??= lowerDrawing; JudgmentMererHigherDrawing ??= higherDrawing; HunterLowerDrawing ??= lowerDrawing; HunterHigherDrawing ??= higherDrawing; for (var i = HitPointsDrawings.Length - 1; i >= 0; --i) { HitPointsDrawings[i] ??= HitPointsDrawings[(int)ModeComponent.HitPointsMode.Default]; } for (var i = (int)Component.InputMode.InputMode484; i >= (int)Component.InputMode.InputMode4; --i) { var inputCount = Component.InputCounts[i]; AutoInputDrawings[i] = new DrawingItem?[inputCount + 1]; NoteHitDrawings[i] = new DrawingItem?[inputCount + 1][]; LongNoteHitDrawings[i] = new DrawingItem?[inputCount + 1][]; MainDrawings[i] = new DrawingItem?[inputCount + 1][]; JudgmentMainDrawings[i] = new DrawingItem?[inputCount + 1][]; InputDrawings[i] = new DrawingItem?[inputCount + 1][]; NoteDrawings[i] = new DrawingItem?[inputCount + 1][][][]; MainJudgmentMeterDrawings[i] = new Dictionary<int, DrawingItem?>[inputCount + 1]; for (var j = inputCount; j > 0; --j) { AutoInputDrawings[i][j] = autoInputDrawings[DrawingInputModeMap[i][j]]; NoteHitDrawings[i][j] = noteHitDrawings[DrawingInputModeMap[i][j]]; LongNoteHitDrawings[i][j] = longNoteHitDrawings[DrawingInputModeMap[i][j]]; MainDrawings[i][j] = mainDrawings[DrawingInputModeMap[i][j]]; JudgmentMainDrawings[i][j] = judgmentMainDrawings[DrawingInputModeMap[i][j]]; InputDrawings[i][j] = inputDrawings[DrawingInputModeMap[i][j]]; NoteDrawings[i][j] = noteDrawings[DrawingInputModeMap[i][j]]; MainJudgmentMeterDrawings[i][j] = mainJudgmentMeterDrawings[DrawingInputModeMap[i][j]]; } } FaultText = null; } public void SetFontFamily() { DrawingSystem.Instance.SetFontFamily(TitleFont); DrawingSystem.Instance.SetFontFamily(ArtistFont); DrawingSystem.Instance.SetFontFamily(GenreFont); DrawingSystem.Instance.SetFontFamily(LevelTextFont); DrawingSystem.Instance.SetFontFamily(WantLevelFont); } public void LoadUIFiles() => Utility.SetUICollection(UIItems, Utility.GetEntry(QwilightComponent.UIEntryPath).Prepend(QwilightComponent.UIEntryPath).SelectMany(targetEntryPath => Utility.GetFiles(targetEntryPath).Where(targetFilePath => !Path.GetFileName(targetFilePath).StartsWith('@') && targetFilePath.IsTailCaselsss(".yaml")).Select(yamlFilePath => new UIItem { UIEntry = Path.GetRelativePath(QwilightComponent.UIEntryPath, targetEntryPath), YamlName = Path.GetFileNameWithoutExtension(yamlFilePath) })).ToArray()); void Init() { foreach (var value in typeof(UI).GetProperties()) { if (value.CanWrite) { value.SetValue(this, default); } else if (value.PropertyType.IsArray) { var data = value.GetValue(this) as Array; Array.Clear(data, 0, data.Length); } } DefaultLength = Component.StandardLength; DefaultHeight = Component.StandardHeight; _audioItemMap.Clear(); ValueCallMap.Clear(); ValueMap.Clear(); IntMap.Clear(); IntCallMap.Clear(); AltMap.Clear(); PaintPipelineValues.Clear(); DrawingPipeline.Clear(); DrawingSystem.Instance.SetFontLevel(TitleFont, Levels.FontLevel0Float32); DrawingSystem.Instance.SetFontLevel(ArtistFont, Levels.FontLevel0Float32); DrawingSystem.Instance.SetFontLevel(GenreFont, Levels.FontLevel0Float32); DrawingSystem.Instance.SetFontLevel(LevelTextFont, Levels.FontLevel0Float32); DrawingSystem.Instance.SetFontLevel(WantLevelFont, Levels.FontLevel0Float32); } public void SetConfigures(Script lsCaller) { lsCaller.Globals["configures"] = Enumerable.Range(0, HighestUIConfigure).Select(i => { return Math.Max(0, Array.IndexOf(XamlUIConfigures.SingleOrDefault(value => value.Position == i)?.Configures ?? Array.Empty<string>(), Configure.Instance.UIConfigureValue.UIConfiguresV2[i])); }).ToArray(); } public void LoadUI(UIItem src, UIItem target, bool isParallel = true) { var mainViewModel = ViewModels.Instance.MainValue; if (!mainViewModel.IsUILoading) { mainViewModel.IsUILoading = true; if (isParallel) { NotifySystem.Instance.Notify(NotifySystem.NotifyVariety.Info, NotifySystem.NotifyConfigure.Default, LanguageSystem.Instance.OpeningUIFileContents); Task.Run(() => { try { lock (LoadedCSX) { LoadUIImpl(src, target); } OnLoaded(); NotifySystem.Instance.Notify(NotifySystem.NotifyVariety.OK, NotifySystem.NotifyConfigure.Default, LanguageSystem.Instance.OpenedUIFileContents); } catch (YamlException e) { FaultText = string.Format(LanguageSystem.Instance.YAMLCompileFault, e.Message); NotifySystem.Instance.Notify(NotifySystem.NotifyVariety.Warning, NotifySystem.NotifyConfigure.Default, FaultText); } catch (InterpreterException e) { FaultText = string.Format(LanguageSystem.Instance.LSCompileFault, e.Message); NotifySystem.Instance.Notify(NotifySystem.NotifyVariety.Warning, NotifySystem.NotifyConfigure.Default, FaultText); } catch (Exception e) { FaultText = string.Format(LanguageSystem.Instance.UIFaultText, e.Message); NotifySystem.Instance.Notify(NotifySystem.NotifyVariety.Warning, NotifySystem.NotifyConfigure.Default, FaultText); } finally { mainViewModel.IsUILoading = false; } }); } else { try { lock (LoadedCSX) { LoadUIImpl(src, target); } OnLoaded(); } catch (YamlException e) { FaultText = string.Format(LanguageSystem.Instance.YAMLCompileFault, e.Message, true); } catch (InterpreterException e) { FaultText = string.Format(LanguageSystem.Instance.LSCompileFault, e.Message, true); } catch (Exception e) { FaultText = string.Format(LanguageSystem.Instance.UIFaultText, e.Message, true); } finally { mainViewModel.IsUILoading = false; } } void OnLoaded() { mainViewModel.GetHandlingComputer()?.SetUIMap(); DrawingSystem.Instance.LoadVeilDrawing(); ViewModels.Instance.NotifyWindowViewModels(); mainViewModel.NotifyModel(); } } } } }