-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
fa4976c
commit b792aa4
Showing
8 changed files
with
288 additions
and
40 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
using System; | ||
using System.Diagnostics.CodeAnalysis; | ||
using System.Linq; | ||
using System.Reflection; | ||
using HarmonyLib; | ||
using JetBrains.Annotations; | ||
|
@@ -10,6 +11,7 @@ namespace Osu.Patcher.Hook.Patches.LivePerformance; | |
/// <summary> | ||
/// Hooks the constructor of <c>ScoreDisplay</c> to add our own <c>pTextSprite</c> for displaying | ||
/// the performance counter to the ScoreDisplay's sprite manager. | ||
/// This needs [email protected] or score-p.png in your skin's score font assets! | ||
/// </summary> | ||
[HarmonyPatch] | ||
[UsedImplicitly] | ||
|
@@ -27,32 +29,39 @@ private static void After( | |
[HarmonyArgument(0)] object spriteManager, // SpriteManager | ||
[HarmonyArgument(1)] object position, // Vector2 | ||
[HarmonyArgument(2)] bool alignRight, | ||
[HarmonyArgument(3)] float scale, | ||
[HarmonyArgument(4)] bool showScore, | ||
[HarmonyArgument(5)] bool showAccuracy | ||
[HarmonyArgument(3)] float scale | ||
) | ||
{ | ||
var positionX = Vector2.X.Get(position); | ||
|
||
// TODO: use correct position | ||
var startPosition = ((ConstructorInfo)Vector2.Constructor.Reference).Invoke([positionX, 0f]); | ||
var currentSkin = SkinManager.Current.Get(); | ||
var scoreFont = SkinOsu.FontScore.Get(currentSkin); | ||
var scoreFontOverlap = SkinOsu.FontScoreOverlap.Get(currentSkin); | ||
|
||
var performanceSprite = ((ConstructorInfo)pSpriteText.Constructor.Reference).Invoke( | ||
[ | ||
/* text: */ "0000.0", | ||
/* fontName: */ "Assets/score/score", | ||
/* spacingOverlap: */ 10f, | ||
/* text: */ "00.0pp", | ||
/* fontName: */ scoreFont, | ||
/* spacingOverlap: */ (float)scoreFontOverlap, | ||
/* fieldType: */ alignRight ? Fields.TopRight : Fields.TopLeft, | ||
/* origin: */ alignRight ? Origins.TopRight : Origins.TopLeft, | ||
/* clock: */ Clocks.Game, | ||
/* startPosition: */ startPosition, | ||
/* startPosition: */ ((ConstructorInfo)Vector2.Constructor.Reference).Invoke([0f, 0f]), | ||
/* drawDepth: */ 0.95f, | ||
/* alwaysDraw: */ true, | ||
/* color: */ Color.White, // TODO: try GhostWhite | ||
/* color: */ Color.White, | ||
/* precache: */ true, | ||
/* source: */ SkinSource.All, | ||
/* source: */ SkinSource.ExceptBeatmap, | ||
]); | ||
|
||
// Cannot be startPosition directly | ||
var positionX = Vector2.X.Get(position) + 8f; | ||
var positionY = GetYOffset(Vector2.Y.Get(position), scale, __instance); | ||
var newPosition = ((ConstructorInfo)Vector2.Constructor.Reference).Invoke([positionX, positionY]); | ||
pDrawable.Position.Set(performanceSprite, newPosition); | ||
|
||
pDrawable.Scale.Set(performanceSprite, 0.50f); | ||
pSpriteText.TextConstantSpacing.Set(performanceSprite, true); | ||
pSpriteText.MeasureText.Invoke(performanceSprite); | ||
|
||
SpriteManager.Add.Invoke(spriteManager, [performanceSprite]); | ||
PerformanceDisplay.SetPerformanceCounter(performanceSprite); | ||
} | ||
|
@@ -67,4 +76,22 @@ private static void Finalizer(Exception? __exception) | |
Console.WriteLine($"Exception due to {nameof(PatchAddPerformanceToScoreDisplay)}: {__exception}"); | ||
} | ||
} | ||
|
||
private static float GetYOffset(float baseYPosition, float scale, object scoreDisplay) | ||
{ | ||
// Read the heights of both pSpriteTexts: s_Score, s_Accuracy | ||
var sprites = ScoreDisplay.RuntimeType | ||
.GetDeclaredFields() | ||
.Where(f => f.FieldType == pSpriteText.RuntimeType) | ||
.Select(f => f.GetValue(scoreDisplay)); | ||
var spriteSizes = sprites | ||
.Where(s => s != null) | ||
.Select(s => pSpriteText.MeasureText.Invoke(s)); | ||
var totalSpriteHeight = spriteSizes.Sum(v => Vector2.Y.Get(v)) * 0.58f * scale; | ||
|
||
// Preserve additional spacing between s_Score and s_Accuracy | ||
var additionalOffset = SkinManager.GetUseNewLayout.Invoke() ? 3f : 0f; | ||
|
||
return baseYPosition + totalSpriteHeight + additionalOffset; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
using System; | ||
using System.Linq; | ||
using HarmonyLib; | ||
using JetBrains.Annotations; | ||
using Osu.Stubs.Opcode; | ||
using static System.Reflection.Emit.OpCodes; | ||
|
||
namespace Osu.Stubs; | ||
|
||
/// <summary> | ||
/// Original: <c>osu.Graphics.Skinning.SkinManager</c> | ||
/// b20240123: <c>#=zdwZLyAQXwqtPhTfOQ$e2PRLm39DcCX13EA==</c> | ||
/// </summary> | ||
[UsedImplicitly] | ||
public static class SkinManager | ||
{ | ||
/// <summary> | ||
/// Original: <c>get_UseNewLayout()</c> | ||
/// b20240123: <c>#=zOwgqVurLFLwR</c> | ||
/// </summary> | ||
[UsedImplicitly] | ||
public static readonly LazyMethod<bool> GetUseNewLayout = new( | ||
"SkinManager#get_UseNewLayout()", | ||
new[] | ||
{ | ||
Ldsfld, | ||
Brfalse_S, | ||
Call, | ||
Brtrue_S, | ||
Ldsfld, | ||
Brfalse_S, | ||
Ldsfld, | ||
Ldfld, | ||
} | ||
); | ||
|
||
/// <summary> | ||
/// Original: <c>Current</c> | ||
/// b20240123: <c>#=zUzFTHbU=</c> | ||
/// </summary> | ||
[UsedImplicitly] | ||
public static readonly LazyField<object> Current = new( | ||
"SkinManager#Current", | ||
// There is two fields with type SkinOsu; Current and CurrentUserSkin in that order | ||
() => RuntimeType.GetDeclaredFields() | ||
.First(f => f.FieldType == SkinOsu.RuntimeType) | ||
); | ||
|
||
[UsedImplicitly] | ||
public static Type RuntimeType = GetUseNewLayout.Reference.DeclaringType!; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
using System; | ||
using HarmonyLib; | ||
using JetBrains.Annotations; | ||
using Osu.Stubs.Opcode; | ||
|
||
namespace Osu.Stubs; | ||
|
||
/// <summary> | ||
/// Original: <c>osu.Graphics.Skinning.OsuSkin</c> | ||
/// b20240123: <c>osu.Graphics.Skinning.OsuSkin</c> | ||
/// Most names are present because of this class is [Serializable]. | ||
/// </summary> | ||
[UsedImplicitly] | ||
public static class SkinOsu | ||
{ | ||
/// <summary> | ||
/// Original: <c>FontScoreOverlap</c> | ||
/// b20240123: <c>FontScoreOverlap</c> | ||
/// </summary> | ||
[UsedImplicitly] | ||
public static readonly LazyField<int> FontScoreOverlap = new( | ||
"OsuSkin#FontScoreOverlap", | ||
() => RuntimeType.GetDeclaredFields() | ||
.Find(f => f.Name == "FontScoreOverlap") | ||
); | ||
|
||
/// <summary> | ||
/// Original: <c>FontScore</c> | ||
/// b20240123: <c>FontScore</c> | ||
/// </summary> | ||
[UsedImplicitly] | ||
public static readonly LazyField<string> FontScore = new( | ||
"OsuSkin#FontScore", | ||
() => RuntimeType.GetDeclaredFields() | ||
.Find(f => f.Name == "FontScore") | ||
); | ||
|
||
[UsedImplicitly] | ||
public static Type RuntimeType => OsuAssembly.GetType("osu.Graphics.Skinning.SkinOsu"); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
using System; | ||
using System.Diagnostics.CodeAnalysis; | ||
using System.Linq; | ||
using System.Reflection; | ||
using HarmonyLib; | ||
using JetBrains.Annotations; | ||
using Osu.Stubs.Opcode; | ||
using static System.Reflection.Emit.OpCodes; | ||
|
||
namespace Osu.Stubs; | ||
|
||
/// <summary> | ||
/// Original: <c>osu.Graphics.pDrawable</c> | ||
/// b20240123: <c>#=zB63SnFDTnRqYMKLlscCRpu_ww$IG</c> | ||
/// </summary> | ||
[UsedImplicitly] | ||
[SuppressMessage("ReSharper", "InconsistentNaming")] | ||
public static class pDrawable | ||
{ | ||
/// <summary> | ||
/// Original: <c>Click(bool confirmed)</c> | ||
/// b20240123: <c>#=zcJ6mazw=</c> | ||
/// </summary> | ||
[UsedImplicitly] | ||
public static readonly LazyMethod<bool> Click = new( | ||
"pDrawable#Click(...)", | ||
new[] | ||
{ | ||
Ret, | ||
Ldarg_0, | ||
Ldfld, | ||
Ldnull, | ||
Cgt_Un, | ||
Dup, | ||
Brfalse_S, | ||
Ldarg_0, | ||
Ldfld, | ||
} | ||
); | ||
|
||
/// <summary> | ||
/// Original: <c>ScaleTo(float final, int duration, EasingTypes easing)</c> | ||
/// b20240123: <c>#=zVyF2njk=</c> | ||
/// </summary> | ||
[UsedImplicitly] | ||
public static readonly LazyMethod<object> ScaleTo = new( | ||
"pDrawable#ScaleTo(...)", | ||
new[] | ||
{ | ||
Ldc_I4_4, // TransformationType.Scale | ||
Ldarg_0, | ||
Ldfld, // this.Scale | ||
Conv_R4, | ||
Ldarg_1, | ||
Ldarg_0, | ||
Ldfld, | ||
Call, | ||
Ldsfld, | ||
Conv_I4, | ||
Sub, | ||
} | ||
); | ||
|
||
/// <summary> | ||
/// Original: <c>Position</c> | ||
/// b20240123: <c>#=ztOn8vDI=</c> | ||
/// </summary> | ||
[UsedImplicitly] | ||
public static readonly LazyField<object> Position = new( | ||
"pDrawable#Position", | ||
// There is 3 fields with a type of <c>Vector2</c> on this class. The middle one is <c>Position</c>. | ||
() => RuntimeType.GetDeclaredFields().AsEnumerable() | ||
.Reverse() | ||
.Where(field => field.FieldType == Vector2.RuntimeType) | ||
.Skip(1) | ||
.First() | ||
); | ||
|
||
/// <summary> | ||
/// Original: <c>Scale</c> | ||
/// b20240123: <c>#=zmbpQ79A=</c> | ||
/// </summary> | ||
[UsedImplicitly] | ||
public static readonly LazyField<float> Scale = new( | ||
"pDrawable#Scale", | ||
() => | ||
{ | ||
// The last "ldsfld float" in the ScaleTo method is a reference to this.Scale | ||
var instruction = MethodReader.GetInstructions(ScaleTo.Reference) | ||
.Reverse() | ||
.Where(inst => inst.Opcode == Ldfld) | ||
.First(inst => ((FieldInfo)inst.Operand).FieldType == typeof(float)); | ||
|
||
return (FieldInfo)instruction.Operand; | ||
} | ||
); | ||
|
||
[UsedImplicitly] | ||
public static Type RuntimeType => ScaleTo.Reference.DeclaringType!; | ||
} |
Oops, something went wrong.