Update
This commit is contained in:
@@ -0,0 +1,143 @@
|
||||
using DA_Assets.DAI;
|
||||
using DA_Assets.Extensions;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
|
||||
namespace DA_Assets.Singleton
|
||||
{
|
||||
public class AssetConfig<T> : SingletonScriptableObject<T> where T : ScriptableObject
|
||||
{
|
||||
public string ProductVersion => productVersion;
|
||||
[SerializeField] string productVersion;
|
||||
|
||||
public InternalLocalizator Localizator => localizator.Init();
|
||||
[SerializeField] InternalLocalizator localizator;
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class InternalLocalizator
|
||||
{
|
||||
[SerializeField] TextAsset locFile;
|
||||
private List<LocItem> localizations = new List<LocItem>();
|
||||
|
||||
public InternalLocalizator Init()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
if (localizations.IsEmpty())
|
||||
{
|
||||
try
|
||||
{
|
||||
if (locFile == null)
|
||||
{
|
||||
throw new NullReferenceException("Localization file missing.");
|
||||
}
|
||||
|
||||
localizations = ConvertFileToLocItems(locFile.text);
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return this;
|
||||
}
|
||||
|
||||
private List<LocItem> ConvertFileToLocItems(string csvText)
|
||||
{
|
||||
List<LocItem> locItems = new List<LocItem>();
|
||||
|
||||
using (var reader = new StringReader(csvText))
|
||||
{
|
||||
string line;
|
||||
LocItem currentLocItem = default;
|
||||
StringBuilder currentText = null;
|
||||
|
||||
while ((line = reader.ReadLine()) != null)
|
||||
{
|
||||
if (currentLocItem.Equals(default(LocItem)))
|
||||
{
|
||||
string[] columns = line.Split(';');
|
||||
if (columns.Length >= 2)
|
||||
{
|
||||
currentLocItem = new LocItem
|
||||
{
|
||||
key = columns[0],
|
||||
en = columns[1]
|
||||
};
|
||||
|
||||
if (currentLocItem.en.StartsWith("\"") && !currentLocItem.en.EndsWith("\""))
|
||||
{
|
||||
currentText = new StringBuilder();
|
||||
currentText.AppendLine(currentLocItem.en.TrimStart('\"'));
|
||||
}
|
||||
else
|
||||
{
|
||||
locItems.Add(currentLocItem);
|
||||
currentLocItem = default;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (currentText != null)
|
||||
{
|
||||
if (line.EndsWith("\"") && !line.EndsWith(";\""))
|
||||
{
|
||||
currentText.AppendLine(line.TrimEnd('\"'));
|
||||
currentLocItem.en = currentText.ToString();
|
||||
locItems.Add(currentLocItem);
|
||||
currentLocItem = default;
|
||||
currentText = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
currentText.AppendLine(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return locItems;
|
||||
}
|
||||
|
||||
public string GetLocalizedText(Enum key, params object[] args)
|
||||
{
|
||||
return GetLocalizedText(key.ToString(), args);
|
||||
}
|
||||
|
||||
private string GetLocalizedText(string key, params object[] args)
|
||||
{
|
||||
foreach (LocItem item in localizations)
|
||||
{
|
||||
if (item.key == key)
|
||||
{
|
||||
string txt = item.en;
|
||||
|
||||
if (txt == "")
|
||||
{
|
||||
return key;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return string.Format(txt, args);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return txt;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
}
|
||||
|
||||
internal struct LocItem
|
||||
{
|
||||
internal string key { get; set; }
|
||||
internal string en { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f1d4a4f7829e18049831fcb1cb974278
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,156 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
|
||||
#pragma warning disable IDE1006
|
||||
#pragma warning disable CS1998
|
||||
|
||||
namespace DA_Assets.Singleton
|
||||
{
|
||||
/// <summary>
|
||||
/// An analogue of the <see href="https://docs.unity3d.com/6000.0/Documentation/ScriptReference/ScriptableSingleton_1.html">
|
||||
/// ScriptableSingleton<T></see> class, but works both in Playmode and in the Editor.
|
||||
/// <para>The asset is searched in the <see cref="Resources"/> folder by sequentially traversing the subfolders
|
||||
/// specified in the <see cref="ResourcePathAttribute"/> parameters. If the attribute is defined as
|
||||
/// <see cref="ResourcePathAttribute"/>(""), the search occurs in the root of the <see cref="Resources"/> folder,
|
||||
/// and each subsequent parameter indicates the corresponding subfolder.</para>
|
||||
/// <para>Inherits from <see cref="ScriptableObject"/>.</para>
|
||||
/// </summary>
|
||||
public class SingletonScriptableObject<T> : ScriptableObject where T : ScriptableObject
|
||||
{
|
||||
private static T _instance;
|
||||
|
||||
/// <summary>
|
||||
/// Called upon the first access to the object instance after script recompilation and when entering Playmode.
|
||||
/// </summary>
|
||||
protected virtual void OnCreateInstance() { }
|
||||
|
||||
public virtual async Task OnCreateInstanceAsync() { }
|
||||
|
||||
/// <summary>
|
||||
/// Called after exiting PlayMode.
|
||||
/// </summary>
|
||||
protected virtual void OnExitPlayMode() { }
|
||||
|
||||
private static SingletonScriptableObject<T> _genericInstance => _instance as SingletonScriptableObject<T>;
|
||||
|
||||
/// <summary>
|
||||
/// <para>Gets the instance of the Singleton. Unity creates the Singleton instance when this property is accessed for the first time.</para>
|
||||
/// </summary>
|
||||
public static T Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
CreateInstance();
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task<T> GetInstanceAsync()
|
||||
{
|
||||
await InitializeAsync();
|
||||
return _instance;
|
||||
}
|
||||
|
||||
public static void CreateInstance()
|
||||
{
|
||||
if (_instance == null)
|
||||
{
|
||||
_instance = LoadInstance();
|
||||
SetupPlayModeExitEvent();
|
||||
_genericInstance?.OnCreateInstance();
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task InitializeAsync()
|
||||
{
|
||||
if (_instance == null)
|
||||
{
|
||||
_instance = await LoadInstanceAsync();
|
||||
SetupPlayModeExitEvent();
|
||||
await _genericInstance?.OnCreateInstanceAsync();
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetAssetPath()
|
||||
{
|
||||
object[] attributes = typeof(T).GetCustomAttributes(typeof(ResourcePathAttribute), true);
|
||||
|
||||
if (attributes != null && attributes.Length > 0)
|
||||
{
|
||||
ResourcePathAttribute foldersAttribute = attributes[0] as ResourcePathAttribute;
|
||||
string path = Path.Combine(foldersAttribute.Path);
|
||||
path = Path.Combine(path, typeof(T).Name);
|
||||
return path;
|
||||
}
|
||||
|
||||
return typeof(T).Name;
|
||||
}
|
||||
|
||||
private static T LoadInstance()
|
||||
{
|
||||
string assetPath = GetAssetPath();
|
||||
|
||||
T instance = Resources.Load<T>(assetPath);
|
||||
|
||||
if (instance == null)
|
||||
{
|
||||
throw new NullReferenceException(_objectNotFoundErrorStr);
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
private static async Task<T> LoadInstanceAsync()
|
||||
{
|
||||
string assetPath = GetAssetPath();
|
||||
|
||||
ResourceRequest request = Resources.LoadAsync<T>(assetPath);
|
||||
|
||||
while (!request.isDone)
|
||||
await Task.Yield();
|
||||
|
||||
T instance = request.asset as T;
|
||||
|
||||
if (instance == null)
|
||||
{
|
||||
throw new NullReferenceException(_objectNotFoundErrorStr);
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
private static void SetupPlayModeExitEvent()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
UnityEditor.EditorApplication.playModeStateChanged -= PlayModeExitEvent;
|
||||
UnityEditor.EditorApplication.playModeStateChanged += PlayModeExitEvent;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private static void PlayModeExitEvent(UnityEditor.PlayModeStateChange change)
|
||||
{
|
||||
if (change == UnityEditor.PlayModeStateChange.EnteredEditMode)
|
||||
{
|
||||
_genericInstance?.OnExitPlayMode();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
private static string _missingAttributeErrorStr => $"Missing {nameof(ResourcePathAttribute)} in {typeof(T).Name}";
|
||||
private static string _objectNotFoundErrorStr => $"{nameof(ScriptableObject)} '{typeof(T).Name}' not found in the project.";
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public class ResourcePathAttribute : Attribute
|
||||
{
|
||||
public string[] Path { get; private set; }
|
||||
|
||||
public ResourcePathAttribute(params string[] path)
|
||||
{
|
||||
Path = path;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4839a49a0907ef644974b18b47da2fdb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
|
||||
namespace DA_Assets.Singleton
|
||||
{
|
||||
public class StaticSingleton<T>
|
||||
{
|
||||
private static T instance;
|
||||
public static T Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
instance = Activator.CreateInstance<T>();
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: afc81ce8e8e88024d9a377086dd52ee0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user