feat: debug scene navigation system
This commit is contained in:
@@ -184,7 +184,14 @@ MonoBehaviour:
|
||||
SaveAudio: {fileID: 0}
|
||||
Overrides: []
|
||||
Scenes:
|
||||
SceneDatas: []
|
||||
SceneDatas:
|
||||
- {fileID: 11400000, guid: b09fa30cf6bafad46a041153b0bdb17e, type: 2}
|
||||
- {fileID: 11400000, guid: a996cfbfd3cdcf94fbcc944840699825, type: 2}
|
||||
- {fileID: 11400000, guid: b092f756642b19043bec9bab913906f9, type: 2}
|
||||
- {fileID: 11400000, guid: 95381629b7e563a45b923c8eca96a142, type: 2}
|
||||
- {fileID: 11400000, guid: eef5b93bc2c31ae48ac01a27f20884d5, type: 2}
|
||||
- {fileID: 11400000, guid: 23d4f22660e26344b8e2e2488c560c4c, type: 2}
|
||||
- {fileID: 11400000, guid: ecd5a6faaacb2244fa810987501a9b0b, type: 2}
|
||||
UseAddressables: 0
|
||||
FadeSettings:
|
||||
FadeInDuration: 0.5
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+484
-368
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -15,4 +15,4 @@ MonoBehaviour:
|
||||
objectName: Play_Amb_Scarecrowr_Placeholder
|
||||
id: 2236081422
|
||||
guid: 77D59EA9-AA28-4E2C-814C-DDD7A675CCBC
|
||||
IsInUserDefinedSoundBank: 0
|
||||
IsInUserDefinedSoundBank: 1
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 9089d8b7e41057e4cac3aad004af4b93, type: 3}
|
||||
m_Name: debug_navigation
|
||||
m_EditorClassIdentifier: Assembly-CSharp::Unheimlich.Navigation.Debug.DebugNavigation
|
||||
_scenes:
|
||||
- {fileID: 11400000, guid: a996cfbfd3cdcf94fbcc944840699825, type: 2}
|
||||
- {fileID: 11400000, guid: b092f756642b19043bec9bab913906f9, type: 2}
|
||||
- {fileID: 11400000, guid: 95381629b7e563a45b923c8eca96a142, type: 2}
|
||||
- {fileID: 11400000, guid: eef5b93bc2c31ae48ac01a27f20884d5, type: 2}
|
||||
- {fileID: 11400000, guid: 23d4f22660e26344b8e2e2488c560c4c, type: 2}
|
||||
- {fileID: 11400000, guid: ecd5a6faaacb2244fa810987501a9b0b, type: 2}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f20090b5a50ef084fa449b094cd9fa09
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,17 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: a1f04313388f6a846a9e2a6bfe6e985a, type: 3}
|
||||
m_Name: scene_Omnissiah
|
||||
m_EditorClassIdentifier: OctoCore.Runtime::OctoCore.Navigation.Data.OctoSceneData
|
||||
Id: scene_Omnissiah
|
||||
SceneName: Omnissiah
|
||||
UseFadeTransition: 1
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b092f756642b19043bec9bab913906f9
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,17 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: a1f04313388f6a846a9e2a6bfe6e985a, type: 3}
|
||||
m_Name: scene_titleScreen
|
||||
m_EditorClassIdentifier: OctoCore.Runtime::OctoCore.Navigation.Data.OctoSceneData
|
||||
Id: scene_titleScreen
|
||||
SceneName: TitleScreen
|
||||
UseFadeTransition: 1
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b09fa30cf6bafad46a041153b0bdb17e
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -2342,7 +2342,7 @@ MonoBehaviour:
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_text: => To the next scene
|
||||
m_text: To the next scene =>
|
||||
m_isRightToLeft: 0
|
||||
m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
|
||||
m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
|
||||
@@ -20848,7 +20848,7 @@ GameObject:
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &1962392721
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -21173,7 +21173,7 @@ MonoBehaviour:
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_text: 'R2 to the next scene '
|
||||
m_text: To the next scene R2
|
||||
m_isRightToLeft: 0
|
||||
m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
|
||||
m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
|
||||
|
||||
@@ -307,7 +307,7 @@ PrefabInstance:
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 5856627074613423090, guid: 10b589291a51b4a4f858c6c79ab6772a, type: 3}
|
||||
propertyPath: m_AnchoredPosition.x
|
||||
value: 240.00002
|
||||
value: 240
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 5856627074613423090, guid: 10b589291a51b4a4f858c6c79ab6772a, type: 3}
|
||||
propertyPath: m_AnchoredPosition.y
|
||||
@@ -1293,7 +1293,6 @@ RectTransform:
|
||||
- {fileID: 1869488458}
|
||||
- {fileID: 1841450551}
|
||||
- {fileID: 1903583299}
|
||||
- {fileID: 1880389255}
|
||||
m_Father: {fileID: 2109208143}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
@@ -1982,7 +1981,7 @@ PrefabInstance:
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 5856627074613423090, guid: 10b589291a51b4a4f858c6c79ab6772a, type: 3}
|
||||
propertyPath: m_AnchoredPosition.x
|
||||
value: 720.00006
|
||||
value: 960
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 5856627074613423090, guid: 10b589291a51b4a4f858c6c79ab6772a, type: 3}
|
||||
propertyPath: m_AnchoredPosition.y
|
||||
@@ -2229,7 +2228,7 @@ PrefabInstance:
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 5856627074613423090, guid: 10b589291a51b4a4f858c6c79ab6772a, type: 3}
|
||||
propertyPath: m_AnchoredPosition.x
|
||||
value: 240.00002
|
||||
value: 320
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 5856627074613423090, guid: 10b589291a51b4a4f858c6c79ab6772a, type: 3}
|
||||
propertyPath: m_AnchoredPosition.y
|
||||
@@ -2261,112 +2260,6 @@ RectTransform:
|
||||
m_CorrespondingSourceObject: {fileID: 5856627074613423090, guid: 10b589291a51b4a4f858c6c79ab6772a, type: 3}
|
||||
m_PrefabInstance: {fileID: 1869488457}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
--- !u!1001 &1880389254
|
||||
PrefabInstance:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 2
|
||||
m_Modification:
|
||||
serializedVersion: 3
|
||||
m_TransformParent: {fileID: 1354814231}
|
||||
m_Modifications:
|
||||
- target: {fileID: 148381449121762492, guid: 10b589291a51b4a4f858c6c79ab6772a, type: 3}
|
||||
propertyPath: m_Name
|
||||
value: Button Variant (3)
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 710399409615174608, guid: 10b589291a51b4a4f858c6c79ab6772a, type: 3}
|
||||
propertyPath: m_text
|
||||
value: 8
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 5856627074613423090, guid: 10b589291a51b4a4f858c6c79ab6772a, type: 3}
|
||||
propertyPath: m_Pivot.x
|
||||
value: 0.5
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 5856627074613423090, guid: 10b589291a51b4a4f858c6c79ab6772a, type: 3}
|
||||
propertyPath: m_Pivot.y
|
||||
value: 0.5
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 5856627074613423090, guid: 10b589291a51b4a4f858c6c79ab6772a, type: 3}
|
||||
propertyPath: m_AnchorMax.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 5856627074613423090, guid: 10b589291a51b4a4f858c6c79ab6772a, type: 3}
|
||||
propertyPath: m_AnchorMax.y
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 5856627074613423090, guid: 10b589291a51b4a4f858c6c79ab6772a, type: 3}
|
||||
propertyPath: m_AnchorMin.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 5856627074613423090, guid: 10b589291a51b4a4f858c6c79ab6772a, type: 3}
|
||||
propertyPath: m_AnchorMin.y
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 5856627074613423090, guid: 10b589291a51b4a4f858c6c79ab6772a, type: 3}
|
||||
propertyPath: m_SizeDelta.x
|
||||
value: 200
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 5856627074613423090, guid: 10b589291a51b4a4f858c6c79ab6772a, type: 3}
|
||||
propertyPath: m_SizeDelta.y
|
||||
value: 200
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 5856627074613423090, guid: 10b589291a51b4a4f858c6c79ab6772a, type: 3}
|
||||
propertyPath: m_LocalPosition.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 5856627074613423090, guid: 10b589291a51b4a4f858c6c79ab6772a, type: 3}
|
||||
propertyPath: m_LocalPosition.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 5856627074613423090, guid: 10b589291a51b4a4f858c6c79ab6772a, type: 3}
|
||||
propertyPath: m_LocalPosition.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 5856627074613423090, guid: 10b589291a51b4a4f858c6c79ab6772a, type: 3}
|
||||
propertyPath: m_LocalRotation.w
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 5856627074613423090, guid: 10b589291a51b4a4f858c6c79ab6772a, type: 3}
|
||||
propertyPath: m_LocalRotation.x
|
||||
value: -0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 5856627074613423090, guid: 10b589291a51b4a4f858c6c79ab6772a, type: 3}
|
||||
propertyPath: m_LocalRotation.y
|
||||
value: -0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 5856627074613423090, guid: 10b589291a51b4a4f858c6c79ab6772a, type: 3}
|
||||
propertyPath: m_LocalRotation.z
|
||||
value: -0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 5856627074613423090, guid: 10b589291a51b4a4f858c6c79ab6772a, type: 3}
|
||||
propertyPath: m_AnchoredPosition.x
|
||||
value: 1680.0001
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 5856627074613423090, guid: 10b589291a51b4a4f858c6c79ab6772a, type: 3}
|
||||
propertyPath: m_AnchoredPosition.y
|
||||
value: -690
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 5856627074613423090, guid: 10b589291a51b4a4f858c6c79ab6772a, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 5856627074613423090, guid: 10b589291a51b4a4f858c6c79ab6772a, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 5856627074613423090, guid: 10b589291a51b4a4f858c6c79ab6772a, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
m_RemovedComponents: []
|
||||
m_RemovedGameObjects: []
|
||||
m_AddedGameObjects: []
|
||||
m_AddedComponents: []
|
||||
m_SourcePrefab: {fileID: 100100000, guid: 10b589291a51b4a4f858c6c79ab6772a, type: 3}
|
||||
--- !u!224 &1880389255 stripped
|
||||
RectTransform:
|
||||
m_CorrespondingSourceObject: {fileID: 5856627074613423090, guid: 10b589291a51b4a4f858c6c79ab6772a, type: 3}
|
||||
m_PrefabInstance: {fileID: 1880389254}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
--- !u!1001 &1903583298
|
||||
PrefabInstance:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -2449,7 +2342,7 @@ PrefabInstance:
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 5856627074613423090, guid: 10b589291a51b4a4f858c6c79ab6772a, type: 3}
|
||||
propertyPath: m_AnchoredPosition.x
|
||||
value: 1200.0001
|
||||
value: 1600
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 5856627074613423090, guid: 10b589291a51b4a4f858c6c79ab6772a, type: 3}
|
||||
propertyPath: m_AnchoredPosition.y
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0412faee34f1f1e4a9163b338262c618
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: de5e8b6dd52514441b1115e22ce12f85
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,99 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using OctoCore.Navigation.Data;
|
||||
using OctoRef = OctoCore.OctoCore;
|
||||
|
||||
namespace Unheimlich.Navigation.Debuging
|
||||
{
|
||||
/// <summary>
|
||||
/// ScriptableObject holding the ordered list of debug scenes.
|
||||
/// Drag OctoSceneData assets in the desired order in the inspector.
|
||||
/// </summary>
|
||||
[CreateAssetMenu(fileName = "DebugNavigation", menuName = "Unheimlich/Debug/Debug Navigation")]
|
||||
public class DebugNavigation : ScriptableObject
|
||||
{
|
||||
[Tooltip("Ordered list of scenes available in debug mode.")]
|
||||
[SerializeField] private List<OctoSceneData> _scenes = new List<OctoSceneData>();
|
||||
|
||||
public IReadOnlyList<OctoSceneData> Scenes => _scenes;
|
||||
|
||||
/// <summary>Invoked when a debug scene change is requested.</summary>
|
||||
public Action<OctoSceneData> OnDebugSceneRequested;
|
||||
|
||||
private int _currentIndex = -1;
|
||||
public int CurrentIndex => _currentIndex;
|
||||
|
||||
/// <summary>
|
||||
/// Sync the current index with the active scene.
|
||||
/// If the active scene is not in the list, _currentIndex stays at -1
|
||||
/// so Next() will correctly start at index 0.
|
||||
/// </summary>
|
||||
public void SyncWithCurrentScene(OctoSceneData currentScene)
|
||||
{
|
||||
_currentIndex = currentScene != null ? _scenes.IndexOf(currentScene) : -1;
|
||||
|
||||
if (_currentIndex == -1)
|
||||
UnityEngine.Debug.Log("[DebugNavigation] Scene not found in debug list — Next() will start at index 0.");
|
||||
}
|
||||
|
||||
/// <summary>Load the previous scene in the list (wraps).</summary>
|
||||
public void Previous()
|
||||
{
|
||||
if (_scenes == null || _scenes.Count == 0) return;
|
||||
|
||||
// If not in list, go to last
|
||||
_currentIndex = (_currentIndex <= 0) ? _scenes.Count - 1 : _currentIndex - 1;
|
||||
RequestScene(_currentIndex);
|
||||
}
|
||||
|
||||
/// <summary>Load the next scene in the list (wraps).</summary>
|
||||
public void Next()
|
||||
{
|
||||
if (_scenes == null || _scenes.Count == 0) return;
|
||||
|
||||
// If not in list (-1), go to 0. Otherwise increment.
|
||||
_currentIndex = (_currentIndex >= _scenes.Count - 1) ? 0 : _currentIndex + 1;
|
||||
RequestScene(_currentIndex);
|
||||
}
|
||||
|
||||
/// <summary>Load a scene by index directly (called by Debug Menu UI buttons).</summary>
|
||||
public void LoadByIndex(int index)
|
||||
{
|
||||
if (index < 0 || index >= _scenes.Count)
|
||||
{
|
||||
UnityEngine.Debug.LogWarning($"[DebugNavigation] Index {index} out of range.");
|
||||
return;
|
||||
}
|
||||
|
||||
_currentIndex = index;
|
||||
RequestScene(_currentIndex);
|
||||
}
|
||||
|
||||
private void RequestScene(int index)
|
||||
{
|
||||
OctoSceneData scene = _scenes[index];
|
||||
|
||||
if (scene == null)
|
||||
{
|
||||
UnityEngine.Debug.LogWarning($"[DebugNavigation] Scene at index {index} is null.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't reload the scene that's already active
|
||||
if (OctoRef.Instance != null &&
|
||||
OctoRef.Instance.Navigation.CurrentScene == scene)
|
||||
{
|
||||
UnityEngine.Debug.Log($"[DebugNavigation] Scene '{scene.SceneName}' is already loaded, skipping.");
|
||||
return;
|
||||
}
|
||||
|
||||
OnDebugSceneRequested?.Invoke(scene);
|
||||
|
||||
if (OctoRef.Instance)
|
||||
OctoRef.Instance.Navigation.LoadScene(scene);
|
||||
else
|
||||
UnityEngine.Debug.LogError("[DebugNavigation] OctoCore instance not found.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9089d8b7e41057e4cac3aad004af4b93
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 767e525b8e268ce40b879a01f27987aa
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,320 @@
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
using UnityEngine.InputSystem;
|
||||
using OctoRef = OctoCore.OctoCore;
|
||||
|
||||
namespace Unheimlich.Navigation.Debuging
|
||||
{
|
||||
/// <summary>
|
||||
/// Listens for debug input combos and drives DebugNavigation.
|
||||
///
|
||||
/// — Gamepad : L2+R2 held 0.5s → unlock/lock. L2/R2 short press → prev/next (menu must be open).
|
||||
/// — Keyboard : backquote (² AZERTY / ~ QWERTY) → unlock/lock. ←/→ → prev/next.
|
||||
///
|
||||
/// Device display: switches based on last active input, not physical connection.
|
||||
/// </summary>
|
||||
public class DebugMenuUnlocker : MonoBehaviour
|
||||
{
|
||||
[Header("Data")]
|
||||
[SerializeField] private DebugNavigation _debugNavigation;
|
||||
|
||||
[Header("Timing")]
|
||||
[Tooltip("Duration in seconds L2+R2 must be held to toggle the debug menu.")]
|
||||
[SerializeField] private float _holdDuration = 0.5f;
|
||||
|
||||
[Header("Unlock Events")]
|
||||
public UnityEvent OnDebugMenuUnlockedGamepad;
|
||||
public UnityEvent OnDebugMenuUnlockedKeyboard;
|
||||
public UnityEvent OnDebugMenuLocked;
|
||||
|
||||
[Header("Navigation Events")]
|
||||
public UnityEvent OnPreviousScene;
|
||||
public UnityEvent OnNextScene;
|
||||
|
||||
[Header("Device Switch Events")]
|
||||
[Tooltip("Fired when gamepad input is detected and last input was keyboard/mouse.")]
|
||||
public UnityEvent OnSwitchedToGamepad;
|
||||
|
||||
[Tooltip("Fired when keyboard/mouse input is detected and last input was gamepad.")]
|
||||
public UnityEvent OnSwitchedToKeyboard;
|
||||
|
||||
// ── State ────────────────────────────────────────────────────────────
|
||||
|
||||
private bool _isUnlocked = false;
|
||||
private bool _isL2Held = false;
|
||||
private bool _isR2Held = false;
|
||||
private float _holdTimer = 0f;
|
||||
private bool _holdFired = false;
|
||||
private bool _lastWasGamepad = false;
|
||||
|
||||
// Input Actions
|
||||
private InputAction _keyboardUnlockAction;
|
||||
private InputAction _gamepadL2Action;
|
||||
private InputAction _gamepadR2Action;
|
||||
private InputAction _keyboardPreviousAction;
|
||||
private InputAction _keyboardNextAction;
|
||||
private InputAction _anyGamepadAction;
|
||||
private InputAction _anyKeyboardAction;
|
||||
|
||||
// ── Unity lifecycle ──────────────────────────────────────────────────
|
||||
|
||||
private void Awake() => BuildInputActions();
|
||||
private void OnEnable() => EnableActions();
|
||||
private void Start()
|
||||
{
|
||||
StartCoroutine(InitWhenReady());
|
||||
}
|
||||
|
||||
private IEnumerator InitWhenReady()
|
||||
{
|
||||
yield return new WaitUntil(() => OctoRef.Instance != null);
|
||||
yield return new WaitUntil(() => OctoRef.Instance.Navigation.CurrentScene != null);
|
||||
|
||||
SyncDebugNavigation();
|
||||
SubscribeToSceneEvents();
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
DisableActions();
|
||||
UnsubscribeFromSceneEvents();
|
||||
}
|
||||
private void OnDestroy() => DisposeActions();
|
||||
private void Update() => TickHoldTimer();
|
||||
|
||||
// ── Build ────────────────────────────────────────────────────────────
|
||||
|
||||
private void BuildInputActions()
|
||||
{
|
||||
// Keyboard unlock toggle
|
||||
_keyboardUnlockAction = new InputAction("DebugUnlockKeyboard", InputActionType.Button);
|
||||
_keyboardUnlockAction.AddBinding("<Keyboard>/backquote");
|
||||
_keyboardUnlockAction.performed += _ => ToggleDebugMenu(false);
|
||||
|
||||
// Gamepad L2 / R2
|
||||
_gamepadL2Action = new InputAction("DebugL2", InputActionType.Button);
|
||||
_gamepadL2Action.AddBinding("<Gamepad>/leftTrigger")
|
||||
.WithProcessor("AxisDeadzone(min=0.5,max=1)");
|
||||
_gamepadL2Action.performed += _ => OnL2Down();
|
||||
_gamepadL2Action.canceled += _ => OnL2Up();
|
||||
|
||||
_gamepadR2Action = new InputAction("DebugR2", InputActionType.Button);
|
||||
_gamepadR2Action.AddBinding("<Gamepad>/rightTrigger")
|
||||
.WithProcessor("AxisDeadzone(min=0.5,max=1)");
|
||||
_gamepadR2Action.performed += _ => OnR2Down();
|
||||
_gamepadR2Action.canceled += _ => OnR2Up();
|
||||
|
||||
// Keyboard navigation
|
||||
_keyboardPreviousAction = new InputAction("DebugPrevKeyboard", InputActionType.Button);
|
||||
_keyboardPreviousAction.AddBinding("<Keyboard>/leftArrow");
|
||||
_keyboardPreviousAction.performed += _ => TryPrevious();
|
||||
|
||||
_keyboardNextAction = new InputAction("DebugNextKeyboard", InputActionType.Button);
|
||||
_keyboardNextAction.AddBinding("<Keyboard>/rightArrow");
|
||||
_keyboardNextAction.performed += _ => TryNext();
|
||||
|
||||
// Device detection — wildcard bindings
|
||||
// Note: on exclut les triggers du anyGamepad pour éviter les faux positifs
|
||||
// lors du relâchement après un hold unlock
|
||||
_anyGamepadAction = new InputAction("AnyGamepad", InputActionType.PassThrough);
|
||||
_anyGamepadAction.AddBinding("<Gamepad>/leftStick");
|
||||
_anyGamepadAction.AddBinding("<Gamepad>/rightStick");
|
||||
_anyGamepadAction.AddBinding("<Gamepad>/buttonSouth");
|
||||
_anyGamepadAction.AddBinding("<Gamepad>/buttonNorth");
|
||||
_anyGamepadAction.AddBinding("<Gamepad>/buttonEast");
|
||||
_anyGamepadAction.AddBinding("<Gamepad>/buttonWest");
|
||||
_anyGamepadAction.AddBinding("<Gamepad>/leftShoulder");
|
||||
_anyGamepadAction.AddBinding("<Gamepad>/rightShoulder");
|
||||
_anyGamepadAction.AddBinding("<Gamepad>/start");
|
||||
_anyGamepadAction.AddBinding("<Gamepad>/select");
|
||||
_anyGamepadAction.AddBinding("<Gamepad>/dpad");
|
||||
_anyGamepadAction.performed += _ => OnAnyGamepadInput();
|
||||
|
||||
_anyKeyboardAction = new InputAction("AnyKeyboard", InputActionType.PassThrough);
|
||||
_anyKeyboardAction.AddBinding("<Keyboard>/anyKey");
|
||||
_anyKeyboardAction.AddBinding("<Mouse>/delta");
|
||||
_anyKeyboardAction.AddBinding("<Mouse>/leftButton");
|
||||
_anyKeyboardAction.AddBinding("<Mouse>/rightButton");
|
||||
_anyKeyboardAction.performed += _ => OnAnyKeyboardInput();
|
||||
}
|
||||
|
||||
private void EnableActions()
|
||||
{
|
||||
_keyboardUnlockAction?.Enable();
|
||||
_gamepadL2Action?.Enable();
|
||||
_gamepadR2Action?.Enable();
|
||||
_keyboardPreviousAction?.Enable();
|
||||
_keyboardNextAction?.Enable();
|
||||
_anyGamepadAction?.Enable();
|
||||
_anyKeyboardAction?.Enable();
|
||||
}
|
||||
|
||||
private void DisableActions()
|
||||
{
|
||||
_keyboardUnlockAction?.Disable();
|
||||
_gamepadL2Action?.Disable();
|
||||
_gamepadR2Action?.Disable();
|
||||
_keyboardPreviousAction?.Disable();
|
||||
_keyboardNextAction?.Disable();
|
||||
_anyGamepadAction?.Disable();
|
||||
_anyKeyboardAction?.Disable();
|
||||
}
|
||||
|
||||
private void DisposeActions()
|
||||
{
|
||||
_keyboardUnlockAction?.Dispose();
|
||||
_gamepadL2Action?.Dispose();
|
||||
_gamepadR2Action?.Dispose();
|
||||
_keyboardPreviousAction?.Dispose();
|
||||
_keyboardNextAction?.Dispose();
|
||||
_anyGamepadAction?.Dispose();
|
||||
_anyKeyboardAction?.Dispose();
|
||||
}
|
||||
|
||||
// ── L2 / R2 hold logic ───────────────────────────────────────────────
|
||||
|
||||
private void OnL2Down()
|
||||
{
|
||||
_isL2Held = true;
|
||||
if (_isR2Held) StartHold();
|
||||
}
|
||||
|
||||
private void OnL2Up()
|
||||
{
|
||||
// Short press navigation — only if hold didn't fire
|
||||
if (_isUnlocked && !_holdFired && !_isR2Held)
|
||||
TryPrevious();
|
||||
|
||||
_isL2Held = false;
|
||||
|
||||
// Reset hold only when both triggers are released
|
||||
if (!_isR2Held) ResetHold();
|
||||
}
|
||||
|
||||
private void OnR2Down()
|
||||
{
|
||||
_isR2Held = true;
|
||||
if (_isL2Held) StartHold();
|
||||
}
|
||||
|
||||
private void OnR2Up()
|
||||
{
|
||||
// Short press navigation — only if hold didn't fire
|
||||
if (_isUnlocked && !_holdFired && !_isL2Held)
|
||||
TryNext();
|
||||
|
||||
_isR2Held = false;
|
||||
|
||||
// Reset hold only when both triggers are released
|
||||
if (!_isL2Held) ResetHold();
|
||||
}
|
||||
|
||||
private void StartHold()
|
||||
{
|
||||
_holdTimer = 0f;
|
||||
_holdFired = false;
|
||||
}
|
||||
|
||||
private void ResetHold()
|
||||
{
|
||||
_holdTimer = 0f;
|
||||
_holdFired = false;
|
||||
}
|
||||
|
||||
private void TickHoldTimer()
|
||||
{
|
||||
if (!_isL2Held || !_isR2Held || _holdFired) return;
|
||||
|
||||
_holdTimer += Time.unscaledDeltaTime;
|
||||
|
||||
if (_holdTimer >= _holdDuration)
|
||||
{
|
||||
_holdFired = true; // marque comme fired AVANT le toggle pour bloquer OnR2Up/OnL2Up
|
||||
ToggleDebugMenu(true);
|
||||
}
|
||||
}
|
||||
|
||||
// ── Device switch ────────────────────────────────────────────────────
|
||||
|
||||
private void OnAnyGamepadInput()
|
||||
{
|
||||
if (_lastWasGamepad) return;
|
||||
_lastWasGamepad = true;
|
||||
OnSwitchedToGamepad?.Invoke();
|
||||
}
|
||||
|
||||
private void OnAnyKeyboardInput()
|
||||
{
|
||||
if (!_lastWasGamepad) return;
|
||||
_lastWasGamepad = false;
|
||||
OnSwitchedToKeyboard?.Invoke();
|
||||
}
|
||||
|
||||
// ── Logic ────────────────────────────────────────────────────────────
|
||||
|
||||
private void SubscribeToSceneEvents()
|
||||
{
|
||||
if (OctoRef.Instance == null) return;
|
||||
OctoRef.Instance.Navigation.OnSceneLoadCompleted += OnSceneLoadCompleted;
|
||||
}
|
||||
|
||||
private void UnsubscribeFromSceneEvents()
|
||||
{
|
||||
if (OctoRef.Instance == null) return;
|
||||
OctoRef.Instance.Navigation.OnSceneLoadCompleted -= OnSceneLoadCompleted;
|
||||
}
|
||||
|
||||
private void OnSceneLoadCompleted(OctoCore.Navigation.Data.OctoSceneData sceneData)
|
||||
{
|
||||
_debugNavigation?.SyncWithCurrentScene(sceneData);
|
||||
}
|
||||
|
||||
private void SyncDebugNavigation()
|
||||
{
|
||||
if (_debugNavigation == null || OctoRef.Instance == null) return;
|
||||
_debugNavigation.SyncWithCurrentScene(OctoRef.Instance.Navigation.CurrentScene);
|
||||
}
|
||||
|
||||
private void ToggleDebugMenu(bool isGamepad)
|
||||
{
|
||||
_isUnlocked = !_isUnlocked;
|
||||
|
||||
if (_isUnlocked)
|
||||
{
|
||||
SyncDebugNavigation();
|
||||
if (isGamepad) OnDebugMenuUnlockedGamepad?.Invoke();
|
||||
else OnDebugMenuUnlockedKeyboard?.Invoke();
|
||||
UnityEngine.Debug.Log($"[DebugMenuUnlocker] Unlocked ({(isGamepad ? "Gamepad" : "Keyboard")}).");
|
||||
}
|
||||
else
|
||||
{
|
||||
OnDebugMenuLocked?.Invoke();
|
||||
UnityEngine.Debug.Log("[DebugMenuUnlocker] Locked.");
|
||||
}
|
||||
}
|
||||
|
||||
private void TryPrevious()
|
||||
{
|
||||
if (!_isUnlocked || _debugNavigation == null) return;
|
||||
OnPreviousScene?.Invoke();
|
||||
_debugNavigation.Previous();
|
||||
}
|
||||
|
||||
private void TryNext()
|
||||
{
|
||||
if (!_isUnlocked || _debugNavigation == null) return;
|
||||
OnNextScene?.Invoke();
|
||||
_debugNavigation.Next();
|
||||
}
|
||||
|
||||
/// <summary>Called directly by Debug Menu UI buttons (0-based index).</summary>
|
||||
public void LoadSceneByIndex(int index)
|
||||
{
|
||||
if (_debugNavigation == null) return;
|
||||
_debugNavigation.LoadByIndex(index);
|
||||
}
|
||||
|
||||
public bool IsUnlocked => _isUnlocked;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e578ffb82b0e1c74bbb3a7e914b5b305
|
||||
@@ -5,9 +5,15 @@ EditorBuildSettings:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 2
|
||||
m_Scenes:
|
||||
- enabled: 1
|
||||
path: Assets/_Content/Scenes/TitleScreen.unity
|
||||
guid: 2b03899301d0b354382e3608b8ed52a8
|
||||
- enabled: 1
|
||||
path: Assets/_Content/Scenes/Theatre.unity
|
||||
guid: d8ad4f16aafb1e54cbd157a8059be2c5
|
||||
- enabled: 1
|
||||
path: Assets/_Content/Scenes/Omnissiah.unity
|
||||
guid: 78c6b217405801e40818f8e440fb7174
|
||||
- enabled: 1
|
||||
path: Assets/_Content/Scenes/HouseOfLeaves.unity
|
||||
guid: 05519f88e1cce5146843472b6b858607
|
||||
|
||||
Reference in New Issue
Block a user