diff --git a/FDK/src/04.Graphics/TextRenderer/CSkiaSharpTextRenderer.cs b/FDK/src/04.Graphics/TextRenderer/CSkiaSharpTextRenderer.cs index d99b31e4..59553a59 100644 --- a/FDK/src/04.Graphics/TextRenderer/CSkiaSharpTextRenderer.cs +++ b/FDK/src/04.Graphics/TextRenderer/CSkiaSharpTextRenderer.cs @@ -91,15 +91,12 @@ namespace FDK public bool UseGradiant; public Color GradiantTop; public Color GradiantBottom; - - public override string ToString() - { - if (UseGradiant == false) - return $"{s} (TextColor: {TextColor})"; - return $"{s} (TextColor: {TextColor}, GradiantTop: {GradiantTop}, GradiantBottom: {GradiantBottom})"; - } + public bool UseOutline; + public Color OutlineColor; } + // Purify is equivalent to RemoveTags on ObjectExtensions.cs, update both if changing TagRegex + private const string TagRegex = @"<(/?)([gc](?:\.#[0-9a-fA-F]{6})*?)>"; private string Purify(string input) @@ -132,7 +129,8 @@ namespace FDK GradiantTop = (tokenStack.Count == 0) ? gradationTopColor : tokenStack.Peek().GradiantTop, GradiantBottom = (tokenStack.Count == 0) ? gradationBottomColor : tokenStack.Peek().GradiantBottom, TextColor = (tokenStack.Count == 0) ? fontColor : tokenStack.Peek().TextColor, - + UseOutline = tokenStack.Count > 0 && tokenStack.Peek().UseOutline, + OutlineColor = (tokenStack.Count == 0) ? edgeColor : tokenStack.Peek().OutlineColor, }; tokens.Add(token); } @@ -153,6 +151,8 @@ namespace FDK GradiantTop = (tokenStack.Count == 0) ? gradationTopColor : tokenStack.Peek().GradiantTop, GradiantBottom = (tokenStack.Count == 0) ? gradationBottomColor : tokenStack.Peek().GradiantBottom, TextColor = (tokenStack.Count == 0) ? fontColor : tokenStack.Peek().TextColor, + UseOutline = tokenStack.Count > 0 ? tokenStack.Peek().UseOutline : false, + OutlineColor = (tokenStack.Count == 0) ? edgeColor : tokenStack.Peek().OutlineColor, }; string[] _varSplit = match.Groups[2].Value.Split("."); @@ -177,6 +177,11 @@ namespace FDK { newToken.TextColor = ColorTranslator.FromHtml(_varSplit[1]); } + if (_varSplit.Length > 2) + { + newToken.UseOutline = true; + newToken.OutlineColor = ColorTranslator.FromHtml(_varSplit[2]); + } break; } @@ -197,6 +202,8 @@ namespace FDK GradiantTop = (tokenStack.Count == 0) ? gradationTopColor : tokenStack.Peek().GradiantTop, GradiantBottom = (tokenStack.Count == 0) ? gradationBottomColor : tokenStack.Peek().GradiantBottom, TextColor = (tokenStack.Count == 0) ? fontColor : tokenStack.Peek().TextColor, + UseOutline = tokenStack.Count > 0 && tokenStack.Peek().UseOutline, + OutlineColor = (tokenStack.Count == 0) ? edgeColor : tokenStack.Peek().OutlineColor, }; tokens.Add(token); } @@ -238,7 +245,7 @@ namespace FDK { int token_width = (int)Math.Ceiling(paint.MeasureText(tok.s, ref bounds)); - if (drawMode.HasFlag(CFontRenderer.DrawMode.Edge)) + if (drawMode.HasFlag(CFontRenderer.DrawMode.Edge) || tok.UseOutline) { SKPath path = paint.GetTextPath(tok.s, 25 + x_offset, -paint.FontMetrics.Ascent + 25); @@ -257,7 +264,7 @@ namespace FDK SKPaint edgePaint = new SKPaint(); edgePaint.StrokeWidth = paint.TextSize * (secondEdgeColor == null ? 8 : 4) / edge_Ratio; edgePaint.StrokeJoin = SKStrokeJoin.Round; - edgePaint.Color = new SKColor(edgeColor.R, edgeColor.G, edgeColor.B, edgeColor.A); + edgePaint.Color = new SKColor(tok.OutlineColor.R, tok.OutlineColor.G, tok.OutlineColor.B, tok.OutlineColor.A); edgePaint.Style = SKPaintStyle.Stroke; edgePaint.IsAntialias = true; canvas.DrawPath(path, edgePaint); diff --git a/OpenTaiko/Databases/NameplateUnlockables.db3 b/OpenTaiko/Databases/NameplateUnlockables.db3 index b7429287..2e315228 100644 Binary files a/OpenTaiko/Databases/NameplateUnlockables.db3 and b/OpenTaiko/Databases/NameplateUnlockables.db3 differ diff --git a/OpenTaiko/System/Open-World Memories/Graphics/10_Heya/Center_Menu_Background.png b/OpenTaiko/System/Open-World Memories/Graphics/10_Heya/Center_Menu_Background.png new file mode 100644 index 00000000..b732850a Binary files /dev/null and b/OpenTaiko/System/Open-World Memories/Graphics/10_Heya/Center_Menu_Background.png differ diff --git a/OpenTaiko/System/Open-World Memories/Graphics/10_Heya/Description_Panel.png b/OpenTaiko/System/Open-World Memories/Graphics/10_Heya/Description_Panel.png new file mode 100644 index 00000000..2b403b77 Binary files /dev/null and b/OpenTaiko/System/Open-World Memories/Graphics/10_Heya/Description_Panel.png differ diff --git a/OpenTaiko/System/Open-World Memories/Graphics/9_NamePlateEffect/Title/31/0.png b/OpenTaiko/System/Open-World Memories/Graphics/9_NamePlateEffect/Title/31/0.png new file mode 100644 index 00000000..27ef731c Binary files /dev/null and b/OpenTaiko/System/Open-World Memories/Graphics/9_NamePlateEffect/Title/31/0.png differ diff --git a/OpenTaiko/System/Open-World Memories/HeyaConfig.ini b/OpenTaiko/System/Open-World Memories/HeyaConfig.ini index a9d3a595..9b70f5da 100644 --- a/OpenTaiko/System/Open-World Memories/HeyaConfig.ini +++ b/OpenTaiko/System/Open-World Memories/HeyaConfig.ini @@ -25,6 +25,6 @@ Heya_Side_Menu_Font_Offset=0,21 Heya_InfoSection=930,240 - +Heya_DescriptionTextOrigin=60,60 Heya_Font_Scale=21 \ No newline at end of file diff --git a/OpenTaiko/src/Common/Modal.cs b/OpenTaiko/src/Common/Modal.cs index 92d0ba01..6415c080 100644 --- a/OpenTaiko/src/Common/Modal.cs +++ b/OpenTaiko/src/Common/Modal.cs @@ -243,19 +243,19 @@ namespace TJAPlayer3 } else if (modalType == EModalType.Title) { - content = (string)reference[0]; + content = ((string)reference[0]).RemoveTags(); } else if (modalType == EModalType.Character) { - content = (string)reference[0]; + content = ((string)reference[0]).RemoveTags(); } else if (modalType == EModalType.Puchichara) { - content = (string)reference[0]; + content = ((string)reference[0]).RemoveTags(); } else if (modalType == EModalType.Song) { - content = (string)reference[0]; + content = ((string)reference[0]).RemoveTags(); } TitleTextureKey _content = new TitleTextureKey( diff --git a/OpenTaiko/src/Helpers/ObjectExtensions.cs b/OpenTaiko/src/Helpers/ObjectExtensions.cs index 26d490a0..25493549 100644 --- a/OpenTaiko/src/Helpers/ObjectExtensions.cs +++ b/OpenTaiko/src/Helpers/ObjectExtensions.cs @@ -1,6 +1,8 @@ using System.Collections.Generic; using System.Reflection; using System.ArrayExtensions; +using System.Globalization; +using System.Text.RegularExpressions; // https://github.com/Burtsev-Alexey/net-object-deep-copy/blob/master/ObjectExtensions.cs @@ -135,6 +137,15 @@ namespace System public static class StringExtensions { + // TagRegex and RemoveTags are copies of TagRegex and Purify from the CSkiaSharpTextRenderer class (Have two instances because of both being in 2 different projects) + + private const string TagRegex = @"<(/?)([gc](?:\.#[0-9a-fA-F]{6})*?)>"; + + public static string RemoveTags(this string input) + { + return Regex.Replace(input, TagRegex, ""); + } + public static string SafeFormat(this string format, params object?[] args) { try @@ -146,5 +157,79 @@ namespace System return format; } } + + public static double[] ParseComplex(this string input) + { + try + { + // Removing all spaces from the input for easier processing + input = input.Replace(" ", "").ToLower(); + + double real = 0; + double imaginary = 0; + + // If the input contains 'i', we need to handle the imaginary part + if (input.Contains("i")) + { + // Special cases for 'i', '-i', '1+i', '1-i' + if (input == "i") + { + imaginary = 1; + } + else if (input == "-i") + { + imaginary = -1; + } + else + { + // Remove 'i' for further processing + input = input.Replace("i", ""); + + // Check if input ends with '+' or '-', meaning it was something like '1+i' or '1-i' + if (input.EndsWith("+") || input.EndsWith("-")) + { + real = double.Parse(input.TrimEnd('+', '-'), CultureInfo.InvariantCulture); + imaginary = input.EndsWith("+") ? 1 : -1; + } + else + { + // Split the input into real and imaginary parts + string[] parts = input.Split(new[] { '+', '-' }, StringSplitOptions.RemoveEmptyEntries); + + if (input.Contains("+")) + { + real = double.Parse(parts[0], CultureInfo.InvariantCulture); + imaginary = double.Parse(parts[1], CultureInfo.InvariantCulture); + } + else if (input.LastIndexOf('-') > 0) // handling cases like "1-2i" + { + real = double.Parse(parts[0], CultureInfo.InvariantCulture); + imaginary = -double.Parse(parts[1], CultureInfo.InvariantCulture); + } + else if (input.StartsWith("-")) + { + imaginary = -double.Parse(parts[0], CultureInfo.InvariantCulture); + } + else + { + imaginary = double.Parse(parts[0], CultureInfo.InvariantCulture); + } + } + } + } + else + { + // If there is no 'i', it is purely a real number + real = double.Parse(input, CultureInfo.InvariantCulture); + } + + return new double[] { real, imaginary }; + } + catch (Exception ex) + { + // Log Error + return new double[] { 0, 0 }; // Return default value in case of error + } + } } } \ No newline at end of file diff --git a/OpenTaiko/src/Songs/CDTX.cs b/OpenTaiko/src/Songs/CDTX.cs index b7a47ea1..7b64120a 100644 --- a/OpenTaiko/src/Songs/CDTX.cs +++ b/OpenTaiko/src/Songs/CDTX.cs @@ -7930,6 +7930,7 @@ namespace TJAPlayer3 /// private void tParsedComplexNumber(string strScroll, ref double[] dbScroll) { + /* bool bFirst = true; //最初の数値か bool bUse = false; //数値扱い中 string[] arScroll = new string[2]; @@ -7949,9 +7950,13 @@ namespace TJAPlayer3 bFirst = false; } - dbScroll[0] = Convert.ToDouble(arScroll[0]); dbScroll[1] = Convert.ToDouble(arScroll[1]); + */ + + var cpx = strScroll.ParseComplex(); + dbScroll[0] = cpx[0]; + dbScroll[1] = cpx[1]; return; } diff --git a/OpenTaiko/src/Stages/01.StartUp/TextureLoader.cs b/OpenTaiko/src/Stages/01.StartUp/TextureLoader.cs index ad326e74..f4a690ae 100644 --- a/OpenTaiko/src/Stages/01.StartUp/TextureLoader.cs +++ b/OpenTaiko/src/Stages/01.StartUp/TextureLoader.cs @@ -1128,6 +1128,8 @@ namespace TJAPlayer3 Heya_Center_Menu_Box_Slot = TxC(HEYA + @$"Center_Menu_Box_Slot.png"); Heya_Side_Menu = TxC(HEYA + @$"Side_Menu.png"); Heya_Render_Field = TxC(HEYA + @$"Render_Field.png"); + Heya_Center_Menu_Background = TxC(HEYA + @$"Center_Menu_Background.png"); + Heya_Description_Panel = TxC(HEYA + @$"Description_Panel.png"); Heya_Box = TxC(HEYA + @$"Box.png"); Heya_Lock = TxC(HEYA + @$"Lock.png"); @@ -3036,6 +3038,8 @@ Result_Mountain = new CTexture[4]*/; Heya_Side_Menu, Heya_Box, Heya_Render_Field, + Heya_Center_Menu_Background, + Heya_Description_Panel, Heya_Lock; #endregion diff --git a/OpenTaiko/src/Stages/11.Heya/CHeyaDisplayAssetInformations.cs b/OpenTaiko/src/Stages/11.Heya/CHeyaDisplayAssetInformations.cs index 88712ce4..cccdda05 100644 --- a/OpenTaiko/src/Stages/11.Heya/CHeyaDisplayAssetInformations.cs +++ b/OpenTaiko/src/Stages/11.Heya/CHeyaDisplayAssetInformations.cs @@ -52,8 +52,8 @@ namespace TJAPlayer3 } else if (gaugeType == "Extreme") { - description += "Gauge Type: Extreme\n"; - description += "The gauge starts full and sharply depletes at each miss!\nA strange power seems to reduce the margin of error progressively through the song...\n"; + description += "Gauge Type: Extreme\n"; + description += "The gauge starts full and sharply depletes at each miss!\nA strange power seems to reduce the margin of error through the song...\n"; } var bombFactor = character.effect.BombFactor; @@ -73,8 +73,8 @@ namespace TJAPlayer3 ttkDescription = new TitleTextureKey(description, pf, Color.White, Color.Black, 1000); } + TJAPlayer3.Tx.Heya_Description_Panel?.t2D描画(0, 0); TJAPlayer3.stageSongSelect.actSongList.ResolveTitleTexture(ttkDescription).t2D描画(XOrigin, YOrigin); - } public static void DisplayPuchicharaInfo(CCachedFontRenderer pf, CPuchichara puchi) @@ -96,6 +96,7 @@ namespace TJAPlayer3 ttkDescription = new TitleTextureKey(description, pf, Color.White, Color.Black, 1000); } + TJAPlayer3.Tx.Heya_Description_Panel?.t2D描画(0, 0); TJAPlayer3.stageSongSelect.actSongList.ResolveTitleTexture(ttkDescription).t2D描画(XOrigin, YOrigin); } diff --git a/OpenTaiko/src/Stages/11.Heya/CStageHeya.cs b/OpenTaiko/src/Stages/11.Heya/CStageHeya.cs index 4a6abb3b..1fea0be5 100644 --- a/OpenTaiko/src/Stages/11.Heya/CStageHeya.cs +++ b/OpenTaiko/src/Stages/11.Heya/CStageHeya.cs @@ -196,6 +196,38 @@ namespace TJAPlayer3 Background.Draw(); //Heya_Background.t2D描画(0, 0); + #region [Main menu (Side bar)] + + for (int i = 0; i < this.ttkMainMenuOpt.Length; i++) + { + CTexture tmpTex = TJAPlayer3.stageSongSelect.actSongList.ResolveTitleTexture(this.ttkMainMenuOpt[i]); + + if (iCurrentMenu != -1 || iMainMenuCurrent != i) + { + tmpTex.color4 = CConversion.ColorToColor4(Color.DarkGray); + TJAPlayer3.Tx.Heya_Side_Menu?.tUpdateColor4(CConversion.ColorToColor4(Color.DarkGray)); + } + else + { + tmpTex.color4 = CConversion.ColorToColor4(Color.White); + TJAPlayer3.Tx.Heya_Side_Menu?.tUpdateColor4(CConversion.ColorToColor4(Color.White)); + } + + TJAPlayer3.Tx.Heya_Side_Menu?.t2D拡大率考慮上中央基準描画(TJAPlayer3.Skin.Heya_Main_Menu_X[i], TJAPlayer3.Skin.Heya_Main_Menu_Y[i]); + tmpTex.t2D拡大率考慮上中央基準描画(TJAPlayer3.Skin.Heya_Main_Menu_X[i] + TJAPlayer3.Skin.Heya_Main_Menu_Font_Offset[0], TJAPlayer3.Skin.Heya_Main_Menu_Y[i] + TJAPlayer3.Skin.Heya_Main_Menu_Font_Offset[1]); + } + + #endregion + + #region [Background center] + + if (iCurrentMenu >= 0) + { + TJAPlayer3.Tx.Heya_Center_Menu_Background?.t2D描画(0, 0); + } + + #endregion + #region [Render field] float renderRatioX = 1.0f; @@ -220,29 +252,6 @@ namespace TJAPlayer3 #region [Menus display] - #region [Main menu (Side bar)] - - for (int i = 0; i < this.ttkMainMenuOpt.Length; i++) - { - CTexture tmpTex = TJAPlayer3.stageSongSelect.actSongList.ResolveTitleTexture(this.ttkMainMenuOpt[i]); - - if (iCurrentMenu != -1 || iMainMenuCurrent != i) - { - tmpTex.color4 = CConversion.ColorToColor4(Color.DarkGray); - TJAPlayer3.Tx.Heya_Side_Menu?.tUpdateColor4(CConversion.ColorToColor4(Color.DarkGray)); - } - else - { - tmpTex.color4 = CConversion.ColorToColor4(Color.White); - TJAPlayer3.Tx.Heya_Side_Menu?.tUpdateColor4(CConversion.ColorToColor4(Color.White)); - } - - TJAPlayer3.Tx.Heya_Side_Menu?.t2D拡大率考慮上中央基準描画(TJAPlayer3.Skin.Heya_Main_Menu_X[i], TJAPlayer3.Skin.Heya_Main_Menu_Y[i]); - tmpTex.t2D拡大率考慮上中央基準描画(TJAPlayer3.Skin.Heya_Main_Menu_X[i] + TJAPlayer3.Skin.Heya_Main_Menu_Font_Offset[0], TJAPlayer3.Skin.Heya_Main_Menu_Y[i] + TJAPlayer3.Skin.Heya_Main_Menu_Font_Offset[1]); - } - - #endregion - #region [Petit chara] if (iCurrentMenu == 0) @@ -481,7 +490,6 @@ namespace TJAPlayer3 #endregion - #endregion #region [Description area]