Files
Fishing2/Assets/ThirdParty/Rewired/Extras/Glyphs/Scripts/GlyphProvider.cs
2025-05-10 12:49:47 +08:00

223 lines
9.0 KiB
C#

// Copyright (c) 2024 Augie R. Maddox, Guavaman Enterprises. All rights reserved.
#pragma warning disable 0649
namespace Rewired.Glyphs {
using Rewired;
using Interfaces;
using System;
using System.Collections.Generic;
/// <summary>
/// Manages glyphs.
/// </summary>
public class GlyphProvider : UnityEngine.MonoBehaviour, IGlyphProvider {
[UnityEngine.SerializeField]
[UnityEngine.Tooltip("Determines if glyphs should be fetched immediately in bulk when available. If false, glyphs will be fetched when queried.")]
private bool _prefetch;
[UnityEngine.SerializeField]
[UnityEngine.Tooltip("A list of glyph set collections. At least one collection must be assigned.")]
private List<GlyphSetCollection> _glyphSetCollections;
[NonSerialized]
private readonly Dictionary<string, object> _glyphs = new Dictionary<string, object>();
[NonSerialized]
private bool _initialized;
/// <summary>
/// Determines if glyphs should be fetched immediately in bulk when available.
/// If false, glyphs will be fetched when queried.
/// </summary>
public bool prefetch {
get {
return _prefetch;
}
set {
_prefetch = value;
if (isActiveAndEnabled && ReInput.isReady && ReInput.glyphs.glyphProvider == (IGlyphProvider)this) {
ReInput.glyphs.prefetch = value;
}
}
}
/// <summary>
/// The list of glyph set collections.
/// You should not make changes to the list directly, but instead set the list.
/// Otherwise, the changes will not be reflected in Rewired for glyphs that
/// have already been cached. If you do modify the list directly, call <see cref="Reload"/> after making changes.
/// When setting the array, <see cref="Reload"/> will be called automatically.
/// </summary>
public List<GlyphSetCollection> glyphSetCollections {
get {
return _glyphSetCollections;
}
set {
_glyphSetCollections = value;
Reload();
}
}
/// <summary>
/// The cached glyphs.
/// </summary>
protected Dictionary<string, object> glyphs {
get {
return _glyphs;
}
}
protected virtual void OnEnable() {
if (!_initialized) Initialize(); // only init if needed to avoid reloading everything if re-enabled
TrySetGlyphProvider();
}
protected virtual void OnDisable() {
if (ReInput.isReady && ReInput.glyphs.glyphProvider == (IGlyphProvider)this) {
ReInput.glyphs.glyphProvider = null;
}
ReInput.InitializedEvent -= TrySetGlyphProvider;
}
protected virtual void Update() {
#if UNITY_EDITOR
HandleInspectorValueChanges();
#endif
}
/// <summary>
/// Sets this as the Glyph Provider in Rewired.
/// </summary>
protected virtual void TrySetGlyphProvider() {
// Workaround to handle OnEnable script execution order bugs in various versions of Unity.
// When recompiling in the editor in Play mode, OnEnable can be called on this script
// before it is called on Rewired, so Rewired is not initialized by the time this runs.
// This also has the side benefit of allowing the user to instantiate this object
// before Rewired for whatever reason, and it will set itself as the provider
// when Rewired initalizes.
// This will also set the glyph provider again after calling ReInput.Reset or changing
// some configuration setting that causes Rewired to reset.
ReInput.InitializedEvent -= TrySetGlyphProvider;
ReInput.InitializedEvent += TrySetGlyphProvider;
if (!ReInput.isReady) return;
if (!Utils.UnityTools.IsNullOrDestroyed(ReInput.glyphs.glyphProvider)) {
UnityEngine.Debug.LogWarning("Rewired: A glyph provider is already set. Only one glyph provider can exist at a time.");
return;
}
ReInput.glyphs.glyphProvider = this;
ReInput.glyphs.prefetch = _prefetch;
}
/// <summary>
/// Called when initialized.
/// Will be initialized on enable and when localized strings are set.
/// </summary>
/// <returns>True if initialized, false if initialization failed.</returns>
protected virtual bool Initialize() {
_initialized = false;
if (_glyphSetCollections == null) return false;
// Create a dictionary of all glyhps in all collections
_glyphs.Clear();
const char keyPathSeparator = '/';
System.Text.StringBuilder sb = new System.Text.StringBuilder();
string key;
GlyphSetCollection collection;
GlyphSet.EntryBase entry;
int baseKeysCount;
int entryCount;
int i, j, k;
for (i = 0; i < _glyphSetCollections.Count; i++) {
collection = _glyphSetCollections[i];
if (collection == null) continue;
foreach(var set in collection.IterateSetsRecursively()) {
if (set == null) continue;
if (set.baseKeys != null) {
baseKeysCount = set.baseKeys.Length;
for (j = 0; j < baseKeysCount; j++) {
if (string.IsNullOrEmpty(set.baseKeys[j])) continue;
entryCount = set.glyphCount;
for (k = 0; k < entryCount; k++) {
entry = set.GetEntry(k);
if (entry == null) continue;
if (string.IsNullOrEmpty(entry.key)) continue;
if (entry.GetValue() == null) continue;
// Concatenate base key and glyph key
sb.Append(set.baseKeys[j]);
sb.Append(keyPathSeparator);
sb.Append(entry.key);
key = sb.ToString();
sb.Length = 0;
if (_glyphs.ContainsKey(key)) {
UnityEngine.Debug.LogError("Rewired: Duplicate glyph key found: " + key);
continue;
}
_glyphs.Add(key, entry.GetValue());
}
}
}
}
}
_initialized = true;
return true;
}
/// <summary>
/// Clears glyph cache so all glyhps are reloaded.
/// Subclasses should call this after making changes to the glyph collection.
/// </summary>
public void Reload() {
Initialize();
if (isActiveAndEnabled && ReInput.isReady && ReInput.glyphs.glyphProvider == (IGlyphProvider)this) {
ReInput.glyphs.Reload();
}
}
/// <summary>
/// Try to get the glyph for the specified key.
/// </summary>
/// <param name="key">The key.</param>
/// <param name="result">The localized string.</param>
/// <returns>True if the glyph was found, false if not.</returns>
bool IGlyphProvider.TryGetGlyph(string key, out object result) {
if (!_initialized) {
result = null;
return false;
}
return _glyphs.TryGetValue(key, out result);
}
#if UNITY_EDITOR
[NonSerialized]
private Action _inspectorActions;
private Rewired.Utils.Classes.Data.InspectorValue<bool>_inspector_prefetch = new Rewired.Utils.Classes.Data.InspectorValue<bool>();
private Rewired.Utils.Classes.Data.InspectorListValue<GlyphSetCollection> _inspector_glyphSetCollections = new Rewired.Utils.Classes.Data.InspectorListValue<GlyphSetCollection>();
protected virtual void OnValidate() {
_inspectorActions = null; // prevent buffering of actions in edit mode
CheckInspectorValues(ref _inspectorActions);
}
protected virtual void CheckInspectorValues(ref Action actions) {
if(_inspector_prefetch.SetIfChanged(_prefetch)) {
actions += () => prefetch = _prefetch;
}
if (_inspector_glyphSetCollections.SetIfChanged(_glyphSetCollections)) {
actions += () => glyphSetCollections = _glyphSetCollections;
}
}
protected virtual void HandleInspectorValueChanges() {
Action actions = _inspectorActions;
_inspectorActions = null;
if (actions != null) actions();
}
#endif
}
}