mirror of https://github.com/hykilpikonna/AquaDX
[+] Slide related visual feature (#81)
New Features: 1. Invert the Slide hierarchy 2. Slide Track shrinking animation Changes: 1. Improve the visual effect of Break-Slide judge blink 2. `DisableTrackStartTabs` now also hide user's best achievementpull/84/head
parent
11beb6676e
commit
85dd8029af
|
@ -13,12 +13,11 @@ public class BreakSlideJudgeBlink
|
||||||
[HarmonyPostfix]
|
[HarmonyPostfix]
|
||||||
[HarmonyPatch(typeof(SlideJudge), "UpdateBreakEffectAdd")]
|
[HarmonyPatch(typeof(SlideJudge), "UpdateBreakEffectAdd")]
|
||||||
private static void FixBreakSlideJudgeBlink(
|
private static void FixBreakSlideJudgeBlink(
|
||||||
SpriteRenderer ___SpriteRenderAdd, SpriteRenderer ___SpriteRender,
|
SpriteRenderer ___SpriteRenderAdd, int ____addEffectCount
|
||||||
SlideJudge.SlideJudgeType ____judgeType, SlideJudge.SlideAngle ____angle
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (!___SpriteRenderAdd.gameObject.activeSelf) return;
|
if (!___SpriteRenderAdd.gameObject.activeSelf) return;
|
||||||
float num = ___SpriteRenderAdd.color.r;
|
float num = (____addEffectCount & 0b10) >> 1;
|
||||||
___SpriteRenderAdd.color = new Color(num, num, num, 1f);
|
___SpriteRenderAdd.color = new Color(num, num, num, 1f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,4 +84,24 @@ public class Config
|
||||||
推荐与自定义皮肤一起使用 (否则视觉效果可能并不好)
|
推荐与自定义皮肤一起使用 (否则视觉效果可能并不好)
|
||||||
""")]
|
""")]
|
||||||
public bool BreakSlideJudgeBlink { get; set; }
|
public bool BreakSlideJudgeBlink { get; set; }
|
||||||
|
|
||||||
|
[ConfigComment(
|
||||||
|
en: """
|
||||||
|
Make the Slide Track disappear with an inward-shrinking animation, similar to AstroDX
|
||||||
|
""",
|
||||||
|
zh: """
|
||||||
|
使 Slide Track 消失时有类似 AstroDX 一样的向内缩入的动画
|
||||||
|
""")]
|
||||||
|
public bool SlideArrowAnimation { get; set; }
|
||||||
|
|
||||||
|
[ConfigComment(
|
||||||
|
en: """
|
||||||
|
Invert the Slide hierarchy, so that the new Slide appears on top like Maimai classic
|
||||||
|
Enable to support color changing effects achieved by overlaying multiple stars
|
||||||
|
""",
|
||||||
|
zh: """
|
||||||
|
反转 Slide 层级, 使新出现的 Slide 像旧框一样显示在上层
|
||||||
|
启用以支持通过叠加多个星星达成的变色效果
|
||||||
|
""")]
|
||||||
|
public bool SlideLayerReverse { get; set; }
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
using Monitor;
|
using Monitor;
|
||||||
|
using TMPro;
|
||||||
using UI;
|
using UI;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
|
@ -13,7 +14,8 @@ public class DisableTrackStartTabs
|
||||||
[HarmonyPatch(typeof(TrackStartMonitor), "SetTrackStart")]
|
[HarmonyPatch(typeof(TrackStartMonitor), "SetTrackStart")]
|
||||||
private static void DisableTabs(
|
private static void DisableTabs(
|
||||||
SpriteCounter ____trackNumber, SpriteCounter ____bossTrackNumber, SpriteCounter ____utageTrackNumber,
|
SpriteCounter ____trackNumber, SpriteCounter ____bossTrackNumber, SpriteCounter ____utageTrackNumber,
|
||||||
MultipleImage ____musicTabImage, GameObject[] ____musicTabObj, GameObject ____derakkumaRoot
|
MultipleImage ____musicTabImage, GameObject[] ____musicTabObj, GameObject ____derakkumaRoot,
|
||||||
|
TimelineRoot ____musicDetail
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
____trackNumber.transform.parent.gameObject.SetActive(false);
|
____trackNumber.transform.parent.gameObject.SetActive(false);
|
||||||
|
@ -24,5 +26,15 @@ public class DisableTrackStartTabs
|
||||||
____musicTabObj[1].gameObject.SetActive(false);
|
____musicTabObj[1].gameObject.SetActive(false);
|
||||||
____musicTabObj[2].gameObject.SetActive(false);
|
____musicTabObj[2].gameObject.SetActive(false);
|
||||||
____derakkumaRoot.SetActive(false);
|
____derakkumaRoot.SetActive(false);
|
||||||
|
var traverse = Traverse.Create(____musicDetail);
|
||||||
|
traverse.Field<MultipleImage>("_achivement_Base").Value.ChangeSprite(1);
|
||||||
|
traverse.Field<MultipleImage>("_clearRank_Base").Value.ChangeSprite(1);
|
||||||
|
traverse.Field<TextMeshProUGUI>("_achivement_Text").Value.gameObject.SetActive(false);
|
||||||
|
traverse.Field<TextMeshProUGUI>("_achivement_decimal_Text").Value.gameObject.SetActive(false);
|
||||||
|
traverse.Field<TextMeshProUGUI>("_achivement_percent_Text").Value.gameObject.SetActive(false);
|
||||||
|
traverse.Field<MultipleImage>("_clearRank_Image").Value.gameObject.SetActive(false);
|
||||||
|
traverse.Field<GameObject>("_deluxScore_Obj").Value.SetActive(false);
|
||||||
|
traverse.Field<MultipleImage>("_comboRank_Image").Value.ChangeSprite(0);
|
||||||
|
traverse.Field<MultipleImage>("_syncRank_Image").Value.ChangeSprite(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,115 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using HarmonyLib;
|
||||||
|
using Manager;
|
||||||
|
using Monitor;
|
||||||
|
using Monitor.Game;
|
||||||
|
using Process;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace AquaMai.Visual;
|
||||||
|
|
||||||
|
public class SlideArrowAnimation
|
||||||
|
{
|
||||||
|
private static List<SpriteRenderer> _animatingSpriteRenderers = [];
|
||||||
|
|
||||||
|
[HarmonyTranspiler]
|
||||||
|
[HarmonyPatch(typeof(SlideRoot), "NoteCheck")]
|
||||||
|
private static IEnumerable<CodeInstruction> GetUnVisibleColorHook(IEnumerable<CodeInstruction> instructions)
|
||||||
|
{
|
||||||
|
var methodGetUnVisibleColor = AccessTools.Method(typeof(SlideRoot), "GetUnVisibleColor");
|
||||||
|
|
||||||
|
var oldInstList = new List<CodeInstruction>(instructions);
|
||||||
|
var newInstList = new List<CodeInstruction>();
|
||||||
|
|
||||||
|
for (var i = 0; i < oldInstList.Count; i++)
|
||||||
|
{
|
||||||
|
var inst = oldInstList[i];
|
||||||
|
if (inst.Calls(methodGetUnVisibleColor))
|
||||||
|
{
|
||||||
|
// 现在栈上应该有: SpriteRenderer, SlideRoot(this)
|
||||||
|
// 这一条 IL 会消耗 this, 调用 GetUnVisibleColor(), 推一个 Color 到栈上
|
||||||
|
// 然后接下来的一条 IL 是调用 SpriteRenderer.color 的 setter 把 SpriteRenderer 和 Color 一起消耗掉
|
||||||
|
// 我们现在直接用一个 static method 消耗掉 SpriteRenderer 和 this
|
||||||
|
// 所以要忽略当前 IL, 再忽略下一条 IL, 然后构造一个 Call
|
||||||
|
|
||||||
|
// ReSharper disable once ConvertClosureToMethodGroup
|
||||||
|
var redirect = CodeInstruction.Call((SpriteRenderer r, SlideRoot s) => OnSlideArrowDisable(r, s));
|
||||||
|
newInstList.Add(redirect);
|
||||||
|
i++; // 跳过下一条 IL
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
newInstList.Add(inst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newInstList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void OnSlideArrowDisable(SpriteRenderer renderer, SlideRoot slideRoot)
|
||||||
|
{
|
||||||
|
_animatingSpriteRenderers.Add(renderer);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPostfix]
|
||||||
|
[HarmonyPatch(typeof(SlideRoot), "SetArrowObject")]
|
||||||
|
private static void RemoveArrowAnimation(GameObject arrowobj)
|
||||||
|
{
|
||||||
|
var spriteRenderer = arrowobj.GetComponent<SpriteRenderer>();
|
||||||
|
spriteRenderer.transform.localScale = Vector3.one;
|
||||||
|
if (_animatingSpriteRenderers.Contains(spriteRenderer))
|
||||||
|
{
|
||||||
|
_animatingSpriteRenderers.Remove(spriteRenderer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPostfix]
|
||||||
|
[HarmonyPatch(typeof(SlideRoot), "SetBreakArrowObject")]
|
||||||
|
private static void RemoveBreakArrowAnimation(GameObject breakArrowobj)
|
||||||
|
{
|
||||||
|
var breakSlideObj = breakArrowobj.GetComponent<BreakSlide>();
|
||||||
|
breakSlideObj.SpriteRender.transform.localScale = Vector3.one;
|
||||||
|
if (_animatingSpriteRenderers.Contains(breakSlideObj.SpriteRender))
|
||||||
|
{
|
||||||
|
_animatingSpriteRenderers.Remove(breakSlideObj.SpriteRender);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPostfix]
|
||||||
|
[HarmonyPatch(typeof(GameCtrl), "UpdateNotes")]
|
||||||
|
private static void OnGameCtrlUpdateNotesLast()
|
||||||
|
{
|
||||||
|
for (var num = _animatingSpriteRenderers.Count - 1; num >= 0; num--)
|
||||||
|
{
|
||||||
|
var spriteRenderer = _animatingSpriteRenderers[num];
|
||||||
|
if (spriteRenderer == null)
|
||||||
|
{
|
||||||
|
_animatingSpriteRenderers.RemoveAt(num);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var localScale = spriteRenderer.transform.localScale;
|
||||||
|
var scale = localScale.y - NotesManager.GetAddMSec() / 150f;
|
||||||
|
if (scale <= 0)
|
||||||
|
{
|
||||||
|
spriteRenderer.transform.localScale = new Vector3(1f, 0f, 1f);
|
||||||
|
spriteRenderer.color = new Color(1f, 1f, 1f, 0f);
|
||||||
|
_animatingSpriteRenderers.RemoveAt(num);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
localScale.y = scale;
|
||||||
|
spriteRenderer.color = new Color(1f, 1f, 1f, Mathf.Sqrt(scale));
|
||||||
|
spriteRenderer.transform.localScale = localScale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPrefix]
|
||||||
|
[HarmonyPatch(typeof(GameProcess), "SetRelease")]
|
||||||
|
private static void OnBeforeGameProcessSetRelease()
|
||||||
|
{
|
||||||
|
_animatingSpriteRenderers.Clear();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using HarmonyLib;
|
||||||
|
using Monitor;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace AquaMai.Visual;
|
||||||
|
|
||||||
|
public class SlideLayerReverse
|
||||||
|
{
|
||||||
|
[HarmonyPostfix]
|
||||||
|
[HarmonyPatch(typeof(SlideRoot), "Initialize")]
|
||||||
|
private static void CalcArrowLayer(
|
||||||
|
bool ___BreakFlag, List<SpriteRenderer> ____spriteRenders, List<BreakSlide> ____breakSpriteRenders,
|
||||||
|
int ___SlideIndex, int ____baseArrowSortingOrder
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// 原本的 sortingOrder 是 -(SlideIndex + _baseArrowSortingOrder + index)
|
||||||
|
// 令 orderBase = SlideIndex + _baseArrowSortingOrder
|
||||||
|
// 分配给这条 slide 的 sortingOrder 范围是 -(orderBase + count - 1) ~ -(orderBase)
|
||||||
|
// 现在要保留 slide 内部箭头顺序, 但使得 slide 间次序反转
|
||||||
|
// 范围会变成 orderBase ~ orderBase + count - 1
|
||||||
|
// 其中原本是 -(orderBase) 的箭头应该调整为 orderBase + count - 1
|
||||||
|
|
||||||
|
var orderBase = ___SlideIndex + ____baseArrowSortingOrder; // SlideIndex + _baseArrowSortingOrder
|
||||||
|
if (!___BreakFlag)
|
||||||
|
{
|
||||||
|
var lastIdx = ____spriteRenders.Count - 1;
|
||||||
|
for (var index = 0; index < ____spriteRenders.Count; index++)
|
||||||
|
{
|
||||||
|
var renderer = ____spriteRenders[index];
|
||||||
|
renderer.sortingOrder = -32700 + orderBase + lastIdx - index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var lastIdx = ____breakSpriteRenders.Count - 1;
|
||||||
|
for (var index = 0; index < ____breakSpriteRenders.Count; index++)
|
||||||
|
{
|
||||||
|
var breakSlide = ____breakSpriteRenders[index];
|
||||||
|
breakSlide.SetSortingOrder(-32700 + orderBase + lastIdx - index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPostfix]
|
||||||
|
[HarmonyPatch(typeof(SlideFan), "Initialize")]
|
||||||
|
private static void CalcFanArrowLayer(
|
||||||
|
SpriteRenderer[] ____spriteLines, SpriteRenderer[] ____effectSprites,
|
||||||
|
int ___SlideIndex, int ____baseArrowSortingOrder
|
||||||
|
)
|
||||||
|
{
|
||||||
|
var orderBase = ___SlideIndex + ____baseArrowSortingOrder; // SlideIndex + _baseArrowSortingOrder
|
||||||
|
var lastIdx = ____spriteLines.Length - 1;
|
||||||
|
for (var index = 0; index < ____spriteLines.Length; index++)
|
||||||
|
{
|
||||||
|
var renderer = ____spriteLines[index];
|
||||||
|
renderer.sortingOrder = -32700 + orderBase + lastIdx - index;
|
||||||
|
}
|
||||||
|
lastIdx = ____effectSprites.Length - 1;
|
||||||
|
for (var index = 0; index < ____effectSprites.Length; index++)
|
||||||
|
{
|
||||||
|
var renderer = ____effectSprites[index];
|
||||||
|
renderer.sortingOrder = 1000 + orderBase + lastIdx - index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue