This commit is contained in:
SoulliesOfficial
2026-06-09 11:21:59 -04:00
parent 7c60c40d6b
commit 021e76efe7
493 changed files with 50500 additions and 2211 deletions

View File

@@ -0,0 +1,171 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
#nullable enable
namespace Yarn.Unity
{
/// <summary>
/// Detects if no Input Module for the input system is present in the scene.
/// If there isn't one, creates an input module that's compatible with the
/// available input system - an InputSystemUIInputModule for the Input
/// System, and a StandaloneInputModule for the legacy Input Manager. If a
/// module is already present, no action is taken.
/// </summary>
internal sealed class EnsureInputModuleAvailable : MonoBehaviour
{
void OnValidate()
{
AddInputModule();
}
private void AddInputModule()
{
#if UNITY_EDITOR
if (UnityEditor.PrefabUtility.IsPartOfPrefabAsset(gameObject))
{
// Don't modify prefab assets themselves, only instances in the scene.
return;
}
UnityEditor.EditorApplication.delayCall += () =>
{
UnityEngine.EventSystems.BaseInputModule? inputModule = ActiveInputSystem;
if (inputModule != null)
{
// there is an input system in the scene now, but it might not be the right one
if (IsUsingCorrectInputSystem(inputModule))
{
// it is the right one, so we can just jump over this
// either there was always one in the scene or one was added in between this call being scheduled and run
return;
}
// the input system we have is the wrong type
// so we will need to destroy it and then make a new one
DestroyImmediate(inputModule);
}
// because we are doing this as a delayed action it's possible it will run after entering/exiting playback
// in which case the temporary version that unity makes for in-editor playing will be destroyed
// and we don't want that
if (this == null)
{
return;
}
#if USE_INPUTSYSTEM && ENABLE_INPUT_SYSTEM
// Create an input module that uses the Legacy Input Manager.
inputModule = this.gameObject.AddComponent<UnityEngine.InputSystem.UI.InputSystemUIInputModule>();
#elif ENABLE_LEGACY_INPUT_MANAGER
// Create an input module that uses the Input System.
inputModule = this.gameObject.AddComponent<UnityEngine.EventSystems.StandaloneInputModule>();
#endif
// Next, determine whether this change is something that should
// be written to disk. We don't want to accidentally commit a
// change that inserts a specific type of input module, so we'll
// prevent any changes that happen in scenes that are located in
// Packages from being saved. (If you DO want to commit a change
// that adds an input module to a scene in Packages/, delete
// this auto-added input module from the game object and add one
// manually.)
bool isInPackages = IsInPackages(this.gameObject);
if (isInPackages)
{
// This scene is in a package, and we should treat it as
// read-only. Mark this component as not saved in the
// editor.
inputModule.hideFlags |= HideFlags.DontSaveInEditor;
}
else
{
// Otherwise, we're free to save this change. Mark that the
// game object has been modified.
UnityEditor.EditorUtility.SetDirty(this.gameObject);
}
};
#endif
}
internal static bool IsInPackages(GameObject gameObject)
{
var scene = gameObject.scene;
bool isInPackages = scene.path.StartsWith("Packages");
return isInPackages;
}
// if we have an input system this will return it
private UnityEngine.EventSystems.BaseInputModule? ActiveInputSystem
{
get
{
// because we are doing this called as part of a delayed action it's possible it will run after entering/exiting playback
// in which case the temporary version that unity makes for in-editor playing will be destroyed
// and we don't want that
if (this == null)
{
return null;
}
if (this.TryGetComponent<UnityEngine.EventSystems.BaseInputModule>(out var inputSystem))
{
return inputSystem;
}
return FindAnyObjectByType<UnityEngine.EventSystems.BaseInputModule>(FindObjectsInactive.Include);
}
}
private bool IsUsingCorrectInputSystem(UnityEngine.EventSystems.BaseInputModule system)
{
#if USE_INPUTSYSTEM && ENABLE_INPUT_SYSTEM
return system is UnityEngine.InputSystem.UI.InputSystemUIInputModule;
#elif ENABLE_LEGACY_INPUT_MANAGER
return system is UnityEngine.EventSystems.StandaloneInputModule;
#else
return false;
#endif
}
}
#if UNITY_EDITOR
namespace Editor
{
using UnityEditor;
[CustomEditor(typeof(EnsureInputModuleAvailable))]
public class EnsureInputModuleAvailableEditor : UnityEditor.Editor
{
public override void OnInspectorGUI()
{
const string message = "This component checks to see if a UI Input Module exists in the scene. If one isn't available, it creates an input module on this object that's compatible with your current input system.";
EditorGUILayout.HelpBox(message, MessageType.Info);
if (target is not EnsureInputModuleAvailable module)
{
return;
}
if (module.TryGetComponent<UnityEngine.EventSystems.BaseInputModule>(out var existingInputModule))
{
if ((existingInputModule.hideFlags & HideFlags.DontSaveInEditor) != 0)
{
EditorGUILayout.Space();
EditorGUILayout.HelpBox("The " + existingInputModule.GetType().Name + " on this object is marked as temporary, and won't be saved in the scene. Click the button below if you'd like to include it in the saved scene.", MessageType.Info);
if (GUILayout.Button("Save in Scene"))
{
existingInputModule.hideFlags &= ~HideFlags.DontSaveInEditor;
UnityEditor.EditorUtility.SetDirty(existingInputModule.gameObject);
var scene = existingInputModule.gameObject.scene;
UnityEditor.SceneManagement.EditorSceneManager.SaveScene(scene);
}
}
}
}
}
}
#endif
}