#if UNITY_EDITOR using BrewMonster; using BrewMonster.Scripts; using UnityEditor; using UnityEngine; namespace PerfectWorld.Scripts { [CustomEditor(typeof(AnimScenePlayerBootstrap))] internal sealed class AnimScenePlayerBootstrapEditor : UnityEditor.Editor { private Profession _editorSwitchProfession = Profession.PROF_MAGE; private Gender _editorSwitchGender = Gender.GENDER_FEMALE; private int _playActionIndex; private bool _playActionRestart = true; static AnimScenePlayerBootstrapEditor() { EditorApplication.playModeStateChanged += OnPlayModeStateChanged; } private static void OnPlayModeStateChanged(PlayModeStateChange state) { if (state != PlayModeStateChange.ExitingEditMode) { return; } var boots = Object.FindObjectsByType( FindObjectsInactive.Include, FindObjectsSortMode.None); foreach (AnimScenePlayerBootstrap boot in boots) { boot.ApplyPersistedEditorSwitchRole(); EditorUtility.SetDirty(boot); } } private void OnEnable() { _editorSwitchProfession = (Profession)EditorPrefs.GetInt( AnimScenePlayerBootstrap.EditorPrefsSwitchProfessionKey, (int)Profession.PROF_MAGE); _editorSwitchGender = (Gender)EditorPrefs.GetInt( AnimScenePlayerBootstrap.EditorPrefsSwitchGenderKey, (int)Gender.GENDER_FEMALE); } private void OnDisable() { SaveSwitchModelEditorPrefs(); } private static void SaveSwitchModelEditorPrefs(Profession profession, Gender gender) { EditorPrefs.SetInt(AnimScenePlayerBootstrap.EditorPrefsSwitchProfessionKey, (int)profession); EditorPrefs.SetInt(AnimScenePlayerBootstrap.EditorPrefsSwitchGenderKey, (int)gender); } private void SaveSwitchModelEditorPrefs() { SaveSwitchModelEditorPrefs(_editorSwitchProfession, _editorSwitchGender); } public override void OnInspectorGUI() { DrawDefaultInspector(); EditorGUILayout.Space(8f); EditorGUILayout.LabelField("Play Mode — switch model", EditorStyles.boldLabel); EditorGUILayout.HelpBox( "On Play Mode enter, the model loads from the profession / gender below (saved in EditorPrefs). " + "Use Switch model to change role while playing.", MessageType.Info); using (new EditorGUI.DisabledScope(!Application.isPlaying)) { Profession profession = (Profession)EditorGUILayout.EnumPopup( "Switch to profession", _editorSwitchProfession); if (profession != _editorSwitchProfession) { _editorSwitchProfession = profession; SaveSwitchModelEditorPrefs(); } Gender gender = (Gender)EditorGUILayout.EnumPopup("Switch to gender", _editorSwitchGender); if (gender != _editorSwitchGender) { _editorSwitchGender = gender; SaveSwitchModelEditorPrefs(); } } using (new EditorGUI.DisabledScope(!Application.isPlaying)) { if (GUILayout.Button("Switch model", GUILayout.Height(28f))) { var boot = (AnimScenePlayerBootstrap)target; boot.SwitchRole(_editorSwitchProfession, _editorSwitchGender); } } EditorGUILayout.Space(8f); EditorGUILayout.LabelField("Play Mode — play action", EditorStyles.boldLabel); EditorGUILayout.HelpBox( "Calls CECHostPlayer.PlayAction(index, restart). ACT_ATTACK_1..4 may still be blocked by design — " + "use combat/skill paths for those.", MessageType.Info); serializedObject.Update(); SerializedProperty playerProp = serializedObject.FindProperty("player"); var host = playerProp != null ? playerProp.objectReferenceValue as CECHostPlayer : null; using (new EditorGUI.DisabledScope(!Application.isPlaying)) { _playActionIndex = EditorGUILayout.IntField("Action index (PLAYER_ACTION_TYPE)", _playActionIndex); _playActionRestart = EditorGUILayout.Toggle("Restart", _playActionRestart); if (host != null && Application.isPlaying) { string preflight = host.AnimSceneTryExplainPlayActionFailure(_playActionIndex); if (!string.IsNullOrEmpty(preflight)) { EditorGUILayout.HelpBox(preflight, MessageType.Warning); } } EditorGUILayout.BeginHorizontal(); using (new EditorGUI.DisabledScope(!Application.isPlaying || host == null)) { if (GUILayout.Button("Stand (0)", GUILayout.Height(22f))) { _playActionIndex = (int)PLAYER_ACTION_TYPE.ACT_STAND; TryPlayActionOnHost((AnimScenePlayerBootstrap)target, host, _playActionIndex, _playActionRestart); } if (GUILayout.Button("Fight stand (1)", GUILayout.Height(22f))) { _playActionIndex = (int)PLAYER_ACTION_TYPE.ACT_FIGHTSTAND; TryPlayActionOnHost((AnimScenePlayerBootstrap)target, host, _playActionIndex, _playActionRestart); } if (GUILayout.Button("Run (3)", GUILayout.Height(22f))) { _playActionIndex = (int)PLAYER_ACTION_TYPE.ACT_RUN; TryPlayActionOnHost((AnimScenePlayerBootstrap)target, host, _playActionIndex, _playActionRestart); } } EditorGUILayout.EndHorizontal(); using (new EditorGUI.DisabledScope(host == null)) { if (GUILayout.Button("Play action", GUILayout.Height(28f))) { TryPlayActionOnHost((AnimScenePlayerBootstrap)target, host, _playActionIndex, _playActionRestart); } } } EditorGUILayout.Space(8f); EditorGUILayout.LabelField("Play Mode — weapon", EditorStyles.boldLabel); using (new EditorGUI.DisabledScope(!Application.isPlaying)) { if (GUILayout.Button("Re-apply active weapon slot", GUILayout.Height(28f))) { var boot = (AnimScenePlayerBootstrap)target; boot.ApplyWeaponForActiveSlot(); } } // EditorGUILayout.Space(8f); // EditorGUILayout.LabelField("Play Mode — skill grid", EditorStyles.boldLabel); // EditorGUILayout.HelpBox( // "Reset Skills (With Restrictions) re-applies the active weapon slot, rebuilds the skill catalog, " + // "and shows only skills that pass weapon / form / move-env checks.", // MessageType.Info); // using (new EditorGUI.DisabledScope(!Application.isPlaying)) // { // EditorGUILayout.BeginHorizontal(); // if (GUILayout.Button("Reset Skills", GUILayout.Height(28f))) // { // ((AnimScenePlayerBootstrap)target).ResetSkillsWithoutRestrictions(); // } // if (GUILayout.Button("Reset Skills (With Restrictions)", GUILayout.Height(28f))) // { // ((AnimScenePlayerBootstrap)target).ResetSkillsWithRestrictions(); // } // EditorGUILayout.EndHorizontal(); // } } private static void TryPlayActionOnHost( AnimScenePlayerBootstrap boot, CECHostPlayer host, int index, bool restart) { if (boot == null || host == null) { return; } boot.AnimSceneEnsureFashionPathSafeBeforePlayAction(host); string reason = host.AnimSceneTryExplainPlayActionFailure(index); if (reason != null && reason.IndexOf("m_PlayerActions is null", System.StringComparison.Ordinal) >= 0) { host.AnimSceneRebindPlayerActions(); reason = host.AnimSceneTryExplainPlayActionFailure(index); } if (!string.IsNullOrEmpty(reason)) { Debug.LogWarning("[AnimSceneBootstrap] Play action skipped: " + reason); return; } bool ok = host.PlayAction(index, restart); if (!ok) { Debug.LogWarning("[AnimSceneBootstrap] PlayAction(" + index + ") returned false."); } else { Debug.Log( "[AnimSceneBootstrap] PlayAction(" + index + ") called. If you see no motion, " + "CECModel.PlayActionByName may not have matched a clip on the loaded CombinedActionSO / Animancer."); } } } } #endif