Events and Scenes¶
MuseDashMirror exposes each supported callback in two forms:
- Add an attribute to a static method and let the source generator register it.
- Subscribe directly to the corresponding public event in
SceneInfoorPatchEvents.
Attributes are concise and do not perform runtime reflection. Direct subscriptions are useful when your mod needs explicit subscription lifetime or dynamic handlers.
Scene callbacks¶
A generated scene handler must return void, be static, belong to a partial class, and accept exactly object followed by SceneEventArgs:
using MuseDashMirror.Attributes.EventAttributes.SceneEvents;
using MuseDashMirror.EventArguments;
namespace ExampleMod;
internal static partial class SceneHooks
{
[EnterGameScene]
private static void OnEnterGame(object _, SceneEventArgs args)
{
// The GameMain scene has finished loading.
}
[ExitGameScene]
private static void OnExitGame(object _, SceneEventArgs args)
{
// The GameMain scene has been unloaded.
}
}
Use the unqualified SceneEventArgs name with the corresponding using directive as shown above. The current generator matches this declaration syntax directly.
The following attributes and events are available:
| Scene | Enter attribute / event | Exit attribute / event | Unity scene name |
|---|---|---|---|
| Any scene | EnterScene / SceneInfo.OnEnterScene |
ExitScene / SceneInfo.OnExitScene |
Any name |
| Main menu | EnterMainScene / SceneInfo.OnEnterMainScene |
ExitMainScene / SceneInfo.OnExitMainScene |
UISystem_PC |
| Gameplay | EnterGameScene / SceneInfo.OnEnterGameScene |
ExitGameScene / SceneInfo.OnExitGameScene |
GameMain |
| Loading | EnterLoadingScene / SceneInfo.OnEnterLoadingScene |
ExitLoadingScene / SceneInfo.OnExitLoadingScene |
Loading |
| Welcome | EnterWelcomeScene / SceneInfo.OnEnterWelcomeScene |
ExitWelcomeScene / SceneInfo.OnExitWelcomeScene |
Welcome |
SceneEventArgs.BuildIndex and SceneEventArgs.SceneName identify the scene. SceneInfo also exposes IsMainScene, IsGameScene, IsLoadingScene, and IsWelcomeScene for state checks.
Note
The general enter event runs before the matching specialized flag is set and before the specialized enter event. The general exit event runs before the matching flag is cleared and before the specialized exit event. In a specialized enter handler the flag is already true; in a specialized exit handler it is already false.
Game patch callbacks¶
Game patch events run from Harmony postfixes, after the corresponding game method. A generated patch handler follows the same rules as a scene handler but uses the event-specific argument type:
using MuseDashMirror.Attributes.EventAttributes.PatchEvents;
using MuseDashMirror.EventArguments;
namespace ExampleMod;
internal static partial class GameHooks
{
[GameStartPatch]
private static void OnGameStart(object _, GameStartEventArgs args)
{
var stageBattleComponent = args.StageBattleComponent;
}
[AddScorePatch]
private static void OnAddScore(object _, AddScoreEventArgs args)
{
var noteId = args.Id;
var scoreValue = args.Value;
}
}
Use the matching unqualified event-argument type with its using directive for generated patch handlers as well.
| Attribute | Public event | Runs after | Event arguments |
|---|---|---|---|
GameInitPatch |
PatchEvents.GameInitPatch |
GameInit.Awake |
GameInitEventArgs |
PnlMenuPatch |
PatchEvents.PnlMenuPatch |
PnlMenu.Awake |
PnlMenuEventArgs |
PnlStagePatch |
PatchEvents.PnlStagePatch |
PnlStage.Awake |
PnlStageEventArgs |
MenuSelectPatch |
PatchEvents.MenuSelectPatch |
MenuSelect.OnToggleChanged |
MenuSelectEventArgs |
PnlVictoryPatch |
PatchEvents.PnlVictoryPatch |
PnlVictory.OnVictory |
PnlVictoryEventArgs |
GameStartPatch |
PatchEvents.GameStartPatch |
StageBattleComponent.GameStart |
GameStartEventArgs |
AddScorePatch |
PatchEvents.AddScorePatch |
TaskStageTarget.AddScore |
AddScoreEventArgs |
SwitchLanguagesPatch |
PatchEvents.SwitchLanguagesPatch |
SwitchLanguages.OnClick |
SwitchLanguagesEventArgs |
All current event invocations pass null as sender; use the strongly typed event arguments instead of depending on sender.
Callback payloads¶
Each patch callback exposes either the patched game object, the original method values, or both:
| Event arguments | Available data |
|---|---|
GameInitEventArgs |
GameInit instance. |
PnlMenuEventArgs |
PnlMenu instance. |
PnlStageEventArgs |
PnlStage instance. |
MenuSelectEventArgs |
Raw ListIndex, item Index, and IsOn state supplied by the game. |
PnlVictoryEventArgs |
PnlVictory instance. |
GameStartEventArgs |
StageBattleComponent instance. |
AddScoreEventArgs |
TaskStageTarget, score Value, note Id, NoteType, IsAir, and Time. |
SwitchLanguagesEventArgs |
SwitchLanguages instance. |
Language-switch callback¶
The language callback supports the same generated-attribute form as the other patch events:
using MuseDashMirror.Attributes.EventAttributes.PatchEvents;
using MuseDashMirror.EventArguments;
namespace ExampleMod;
internal static partial class LanguageHooks
{
[SwitchLanguagesPatch]
private static void OnSwitchLanguages(object _, SwitchLanguagesEventArgs args)
{
var switchLanguages = args.SwitchLanguages;
}
}
Subscribe to PatchEvents.SwitchLanguagesPatch directly instead when explicit subscription lifetime is preferable.
Choosing the right callback¶
- Use
EnterMainSceneorPnlMenuPatchto build option-menu UI.PnlMenuPatchalso gives direct access to thePnlMenuinstance and runs after MuseDashMirror caches the menu objects used byToggleUtils. - Use
GameStartPatchfor chart-start logic and access toStageBattleComponent. - Use
AddScorePatchfor individual scoring calls. It supplies the note id, score value, note type, air-note flag, and time. - Use
EnterGameSceneandExitGameScenefor scene-level allocation and cleanup that is not tied to a patched game method. - Use
EnterSceneandExitSceneonly when the logic truly applies to every scene.
See Game data for the availability of BattleComponent values and Source generators for registration requirements and diagnostics.