本地化
This commit is contained in:
@@ -10,6 +10,7 @@ namespace AibisDream
|
||||
public class DialogController : Singleton<DialogController>
|
||||
{
|
||||
private DialogueRunner _dialogueRunner;
|
||||
private LocalisedLineProvider _lineProvider;
|
||||
|
||||
# region controller状态标识
|
||||
|
||||
@@ -45,6 +46,7 @@ namespace AibisDream
|
||||
private void Start()
|
||||
{
|
||||
_dialogueRunner = GetComponentInChildren<DialogueRunner>();
|
||||
_lineProvider = GetComponentInChildren<LocalisedLineProvider>();
|
||||
|
||||
_dialogueRunner.onDialogueStart.AddListener(() =>
|
||||
{
|
||||
@@ -58,7 +60,6 @@ namespace AibisDream
|
||||
OnDialogueComplete?.Invoke();
|
||||
IsTalking = false;
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -68,6 +69,7 @@ namespace AibisDream
|
||||
public void StartDialog(YarnProject yarnProject)
|
||||
{
|
||||
_dialogueRunner.SetProject(yarnProject);
|
||||
_lineProvider.InitStringTable(yarnProject.name);
|
||||
_dialogueRunner.StartDialogue("Start");
|
||||
}
|
||||
|
||||
@@ -82,6 +84,7 @@ namespace AibisDream
|
||||
public void LoadDialog(YarnProject yarnProject)
|
||||
{
|
||||
_dialogueRunner.SetProject(yarnProject);
|
||||
_lineProvider.InitStringTable(yarnProject.name);
|
||||
_dialogueRunner.StartDialogue("Center");
|
||||
}
|
||||
|
||||
@@ -93,7 +96,7 @@ namespace AibisDream
|
||||
}
|
||||
}
|
||||
|
||||
public bool CheckIfNodeExistInCurrentYarnProject(string nodeName)
|
||||
private bool CheckIfNodeExistInCurrentYarnProject(string nodeName)
|
||||
{
|
||||
YarnProject currentProject = _dialogueRunner.yarnProject;
|
||||
string[] nodeNames = currentProject.NodeNames;
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
using System.Linq;
|
||||
using UnityEngine.Localization.Settings;
|
||||
using Yarn.Unity;
|
||||
using AibisDream.Framework;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AibisDream
|
||||
{
|
||||
public class LocalisedLineProvider : LineProviderBehaviour
|
||||
{
|
||||
private LocalizationTable _localizationTable;
|
||||
|
||||
public override string LocaleCode => LocalizationSettings.SelectedLocale.Identifier.Code;
|
||||
|
||||
// 本地化表存在即可用
|
||||
public override bool LinesAvailable => _localizationTable != null;
|
||||
|
||||
// We're good to go!
|
||||
public override LocalizedLine GetLocalizedLine(Yarn.Line line)
|
||||
{
|
||||
var text = line.ID;
|
||||
if (_localizationTable != null)
|
||||
{
|
||||
text = _localizationTable[line.ID]?.LocalizedValue ??
|
||||
$"Error: Missing localisation for line {line.ID} in string table {_localizationTable.LocaleIdentifier}";
|
||||
}
|
||||
|
||||
// Construct the localized line
|
||||
LocalizedLine localizedLine = new LocalizedLine
|
||||
{
|
||||
TextID = line.ID,
|
||||
RawText = text,
|
||||
Substitutions = line.Substitutions,
|
||||
Metadata = YarnProject.lineMetadata.GetMetadata(line.ID)
|
||||
};
|
||||
|
||||
// Attempt to fetch metadata tags for this line from the string
|
||||
// table
|
||||
if (_localizationTable == null) return localizedLine;
|
||||
|
||||
var metadata = _localizationTable[line.ID]?.SharedEntry.Metadata
|
||||
.GetMetadata<Yarn.Unity.UnityLocalization.LineMetadata>();
|
||||
|
||||
if (metadata != null && localizedLine.Metadata != null)
|
||||
{
|
||||
localizedLine.Metadata = localizedLine.Metadata.Concat(metadata.tags).ToArray();
|
||||
}
|
||||
else if (localizedLine.Metadata == null && metadata != null)
|
||||
{
|
||||
localizedLine.Metadata = metadata.tags;
|
||||
}
|
||||
|
||||
return localizedLine;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 初始化StringTable
|
||||
/// </summary>
|
||||
/// <param name="tableName">本地化表名称</param>
|
||||
/// <returns>协程</returns>
|
||||
public void InitStringTable(string tableName)
|
||||
{
|
||||
Debug.Log(tableName + "Init");
|
||||
// 释放
|
||||
_localizationTable?.Dispose();
|
||||
// 加载
|
||||
_localizationTable = new LocalizationTable(tableName);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8d3a78e02d644e96a9e0caa46f1e442b
|
||||
timeCreated: 1745489761
|
||||
@@ -47,7 +47,8 @@ namespace AibisDream.Kit
|
||||
{
|
||||
IsFinalized = true;
|
||||
_callback = null;
|
||||
ActionQueue.AddCallback(new ActionQueueRecycleCallback<Callback>(SimpleObjectPool,this));
|
||||
ActionKitMonoBehaviourEvents.AddCallback(
|
||||
new ActionQueueRecycleCallback<Callback>(SimpleObjectPool, this));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,8 +7,10 @@ namespace AibisDream.Kit
|
||||
private Func<bool> _condition;
|
||||
|
||||
private static readonly SimpleObjectPool<Condition> SimpleObjectPool = new(() => new Condition(), null, 10);
|
||||
|
||||
private Condition(){}
|
||||
|
||||
private Condition()
|
||||
{
|
||||
}
|
||||
|
||||
public static Condition Allocate(Func<bool> condition)
|
||||
{
|
||||
@@ -24,6 +26,7 @@ namespace AibisDream.Kit
|
||||
public bool IsFinalized { get; set; }
|
||||
public ulong ActionID { get; set; }
|
||||
public ActionStatus Status { get; set; }
|
||||
|
||||
public void OnStart()
|
||||
{
|
||||
}
|
||||
@@ -46,7 +49,8 @@ namespace AibisDream.Kit
|
||||
{
|
||||
IsFinalized = true;
|
||||
_condition = null;
|
||||
ActionQueue.AddCallback(new ActionQueueRecycleCallback<Condition>(SimpleObjectPool,this));
|
||||
ActionKitMonoBehaviourEvents.AddCallback(
|
||||
new ActionQueueRecycleCallback<Condition>(SimpleObjectPool, this));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,7 +60,7 @@ namespace AibisDream.Kit
|
||||
Status = ActionStatus.NotStart;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class ConditionExtension
|
||||
{
|
||||
public static ISequence Condition(this ISequence self, Func<bool> condition)
|
||||
|
||||
@@ -9,8 +9,10 @@ namespace AibisDream.Kit
|
||||
|
||||
private Func<IEnumerator> _coroutineGetter;
|
||||
|
||||
private CoroutineAction(){}
|
||||
|
||||
private CoroutineAction()
|
||||
{
|
||||
}
|
||||
|
||||
public static CoroutineAction Allocate(Func<IEnumerator> coroutineGetter)
|
||||
{
|
||||
var coroutineAction = Pool.Allocate();
|
||||
@@ -22,6 +24,7 @@ namespace AibisDream.Kit
|
||||
}
|
||||
|
||||
public bool Paused { get; set; }
|
||||
|
||||
public void Deinit()
|
||||
{
|
||||
if (!IsFinalized)
|
||||
@@ -29,7 +32,7 @@ namespace AibisDream.Kit
|
||||
IsFinalized = true;
|
||||
_coroutineGetter = null;
|
||||
|
||||
ActionQueue.AddCallback(new ActionQueueRecycleCallback<CoroutineAction>(Pool,this));
|
||||
ActionKitMonoBehaviourEvents.AddCallback(new ActionQueueRecycleCallback<CoroutineAction>(Pool, this));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,12 +45,11 @@ namespace AibisDream.Kit
|
||||
public bool IsFinalized { get; set; }
|
||||
public ulong ActionID { get; set; }
|
||||
public ActionStatus Status { get; set; }
|
||||
|
||||
public void OnStart()
|
||||
{
|
||||
ActionKitMonoBehaviourEvents.Instance.ExecuteCoroutine(_coroutineGetter(), () =>
|
||||
{
|
||||
Status = ActionStatus.Finished;
|
||||
});
|
||||
ActionKitMonoBehaviourEvents.Instance.ExecuteCoroutine(_coroutineGetter(),
|
||||
() => { Status = ActionStatus.Finished; });
|
||||
}
|
||||
|
||||
public void OnExecute(float dt)
|
||||
@@ -58,14 +60,14 @@ namespace AibisDream.Kit
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class CoroutineExtension
|
||||
{
|
||||
public static ISequence Coroutine(this ISequence self, Func<IEnumerator> coroutineGetter)
|
||||
{
|
||||
return self.Append(CoroutineAction.Allocate(coroutineGetter));
|
||||
}
|
||||
|
||||
|
||||
public static IAction ToAction(this IEnumerator self)
|
||||
{
|
||||
return CoroutineAction.Allocate(() => self);
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace AibisDream.Kit
|
||||
retNode.CurrentSeconds = 0.0f;
|
||||
return retNode;
|
||||
}
|
||||
|
||||
|
||||
public static Delay Allocate(Func<float> delayTimeFactory, Action onDelayFinish = null)
|
||||
{
|
||||
var retNode = Pool.Allocate();
|
||||
@@ -60,7 +60,7 @@ namespace AibisDream.Kit
|
||||
this.Finish();
|
||||
OnDelayFinish?.Invoke();
|
||||
}
|
||||
|
||||
|
||||
CurrentSeconds += dt;
|
||||
}
|
||||
|
||||
@@ -83,23 +83,23 @@ namespace AibisDream.Kit
|
||||
{
|
||||
OnDelayFinish = null;
|
||||
IsFinalized = true;
|
||||
ActionQueue.AddCallback(new ActionQueueRecycleCallback<Delay>(Pool,this));
|
||||
ActionKitMonoBehaviourEvents.AddCallback(new ActionQueueRecycleCallback<Delay>(Pool, this));
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsFinalized { get; set; }
|
||||
}
|
||||
|
||||
|
||||
public static class DelayExtension
|
||||
{
|
||||
public static ISequence Delay(this ISequence self, float seconds,Action onDelayFinish = null)
|
||||
public static ISequence Delay(this ISequence self, float seconds, Action onDelayFinish = null)
|
||||
{
|
||||
return self.Append(Kit.Delay.Allocate(seconds,onDelayFinish));
|
||||
return self.Append(Kit.Delay.Allocate(seconds, onDelayFinish));
|
||||
}
|
||||
|
||||
public static ISequence Delay(this ISequence self,Func<float> delayTimeFactory,Action onDelayFinish = null)
|
||||
|
||||
public static ISequence Delay(this ISequence self, Func<float> delayTimeFactory, Action onDelayFinish = null)
|
||||
{
|
||||
return self.Append(Kit.Delay.Allocate(delayTimeFactory,onDelayFinish));
|
||||
return self.Append(Kit.Delay.Allocate(delayTimeFactory, onDelayFinish));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -53,7 +53,8 @@ namespace AibisDream.Kit
|
||||
{
|
||||
IsFinalized = true;
|
||||
_onDelayFinish = null;
|
||||
ActionQueue.AddCallback(new ActionQueueRecycleCallback<DelayFrame>(_simpleObjectPool, this));
|
||||
ActionKitMonoBehaviourEvents.AddCallback(
|
||||
new ActionQueueRecycleCallback<DelayFrame>(_simpleObjectPool, this));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ namespace AibisDream.Kit
|
||||
IsFinalized = true;
|
||||
_onLerp = null;
|
||||
_onLerpFinish = null;
|
||||
ActionQueue.AddCallback(new ActionQueueRecycleCallback<Lerp>(Pool, this));
|
||||
ActionKitMonoBehaviourEvents.AddCallback(new ActionQueueRecycleCallback<Lerp>(Pool, this));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/****************************************************************************
|
||||
* Copyright (c) 2015 - 2024 liangxiegame UNDER MIT License
|
||||
*
|
||||
*
|
||||
* https://qframework.cn
|
||||
* https://github.com/liangxiegame/QFramework
|
||||
* https://gitee.com/liangxiegame/QFramework
|
||||
@@ -13,18 +13,20 @@ namespace AibisDream.Kit
|
||||
{
|
||||
public interface IParallel : ISequence
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
internal class Parallel : IParallel
|
||||
{
|
||||
private Parallel(){}
|
||||
private Parallel()
|
||||
{
|
||||
}
|
||||
|
||||
private static readonly SimpleObjectPool<Parallel> SimpleObjectPool = new(() => new Parallel(), null, 5);
|
||||
|
||||
private readonly List<IAction> _actions = ListPool<IAction>.Get();
|
||||
|
||||
private int _finishedCount;
|
||||
|
||||
|
||||
public static Parallel Allocate()
|
||||
{
|
||||
var parallel = SimpleObjectPool.Allocate();
|
||||
@@ -33,10 +35,12 @@ namespace AibisDream.Kit
|
||||
parallel.Reset();
|
||||
return parallel;
|
||||
}
|
||||
|
||||
public bool Paused { get; set; }
|
||||
public bool IsFinalized { get; set; }
|
||||
public ulong ActionID { get; set; }
|
||||
public ActionStatus Status { get; set; }
|
||||
|
||||
public void OnStart()
|
||||
{
|
||||
}
|
||||
@@ -46,7 +50,7 @@ namespace AibisDream.Kit
|
||||
for (var i = _finishedCount; i < _actions.Count; i++)
|
||||
{
|
||||
if (!_actions[i].Execute(dt)) continue;
|
||||
|
||||
|
||||
_finishedCount++;
|
||||
|
||||
if (_finishedCount >= _actions.Count)
|
||||
@@ -58,7 +62,6 @@ namespace AibisDream.Kit
|
||||
// swap
|
||||
(_actions[i], _actions[_finishedCount - 1]) = (_actions[_finishedCount - 1], _actions[i]);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,7 +77,6 @@ namespace AibisDream.Kit
|
||||
|
||||
public void Deinit()
|
||||
{
|
||||
|
||||
if (!IsFinalized)
|
||||
{
|
||||
IsFinalized = true;
|
||||
@@ -83,13 +85,13 @@ namespace AibisDream.Kit
|
||||
{
|
||||
action.Deinit();
|
||||
}
|
||||
|
||||
|
||||
_actions.Clear();
|
||||
|
||||
ActionQueue.AddCallback(new ActionQueueRecycleCallback<Parallel>(SimpleObjectPool,this));
|
||||
}
|
||||
|
||||
|
||||
_actions.Clear();
|
||||
|
||||
ActionKitMonoBehaviourEvents.AddCallback(
|
||||
new ActionQueueRecycleCallback<Parallel>(SimpleObjectPool, this));
|
||||
}
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
@@ -101,10 +103,9 @@ namespace AibisDream.Kit
|
||||
{
|
||||
action.Reset();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class ParallelExtension
|
||||
{
|
||||
public static ISequence Parallel(this ISequence self, Action<ISequence> parallelSetting)
|
||||
|
||||
@@ -82,10 +82,11 @@ namespace AibisDream.Kit
|
||||
if (!IsFinalized)
|
||||
{
|
||||
IsFinalized = true;
|
||||
|
||||
|
||||
_sequence.Deinit();
|
||||
|
||||
ActionQueue.AddCallback(new ActionQueueRecycleCallback<Repeat>(SimpleObjectPool,this));
|
||||
|
||||
ActionKitMonoBehaviourEvents.AddCallback(
|
||||
new ActionQueueRecycleCallback<Repeat>(SimpleObjectPool, this));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,17 +98,17 @@ namespace AibisDream.Kit
|
||||
_sequence.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class RepeatExtension
|
||||
{
|
||||
public static ISequence Repeat(this ISequence self,Action<IRepeat> repeatSetting)
|
||||
public static ISequence Repeat(this ISequence self, Action<IRepeat> repeatSetting)
|
||||
{
|
||||
var repeat = Kit.Repeat.Allocate();
|
||||
repeatSetting(repeat);
|
||||
return self.Append(repeat);
|
||||
}
|
||||
|
||||
public static ISequence Repeat(this ISequence self,int repeatCount, Action<IRepeat> repeatSetting)
|
||||
|
||||
public static ISequence Repeat(this ISequence self, int repeatCount, Action<IRepeat> repeatSetting)
|
||||
{
|
||||
var repeat = Kit.Repeat.Allocate(repeatCount);
|
||||
repeatSetting(repeat);
|
||||
|
||||
@@ -112,15 +112,16 @@ namespace AibisDream.Kit
|
||||
if (!IsFinalized)
|
||||
{
|
||||
IsFinalized = true;
|
||||
|
||||
|
||||
foreach (var action in _actions)
|
||||
{
|
||||
action.Deinit();
|
||||
}
|
||||
|
||||
_actions.Clear();
|
||||
|
||||
ActionQueue.AddCallback(new ActionQueueRecycleCallback<Sequence>(SimpleObjectPool,this));
|
||||
|
||||
ActionKitMonoBehaviourEvents.AddCallback(
|
||||
new ActionQueueRecycleCallback<Sequence>(SimpleObjectPool, this));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,7 +136,7 @@ namespace AibisDream.Kit
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class SequenceExtension
|
||||
{
|
||||
public static ISequence Sequence(this ISequence self, Action<ISequence> sequenceSetting)
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace AibisDream.Kit
|
||||
_executingTask = null;
|
||||
}
|
||||
|
||||
ActionQueue.AddCallback(new ActionQueueRecycleCallback<TaskAction>(Pool, this));
|
||||
ActionKitMonoBehaviourEvents.AddCallback(new ActionQueueRecycleCallback<TaskAction>(Pool, this));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using AibisDream.Framework;
|
||||
using UnityEngine;
|
||||
|
||||
@@ -23,6 +24,8 @@ namespace AibisDream.Kit
|
||||
private void Update()
|
||||
{
|
||||
_onUpdate?.Trigger();
|
||||
|
||||
QueueUpdate();
|
||||
}
|
||||
|
||||
private void OnGUI()
|
||||
@@ -66,5 +69,30 @@ namespace AibisDream.Kit
|
||||
yield return coroutine;
|
||||
onFinish?.Invoke();
|
||||
}
|
||||
|
||||
#region ActionQueue移植
|
||||
|
||||
private readonly List<IActionQueueCallback> _actionQueueCallbacks = new();
|
||||
|
||||
public static void AddCallback(IActionQueueCallback actionQueueCallback)
|
||||
{
|
||||
Instance._actionQueueCallbacks.Add(actionQueueCallback);
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
private void QueueUpdate()
|
||||
{
|
||||
if (_actionQueueCallbacks.Count > 0)
|
||||
{
|
||||
foreach (var actionQueueCallback in _actionQueueCallbacks)
|
||||
{
|
||||
actionQueueCallback.Call();
|
||||
}
|
||||
|
||||
_actionQueueCallbacks.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -28,25 +28,6 @@ namespace AibisDream.Kit
|
||||
|
||||
internal class ActionQueue : Singleton<ActionQueue>
|
||||
{
|
||||
private readonly List<IActionQueueCallback> _actionQueueCallbacks = new();
|
||||
|
||||
public static void AddCallback(IActionQueueCallback actionQueueCallback)
|
||||
{
|
||||
Instance._actionQueueCallbacks.Add(actionQueueCallback);
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
private void Update()
|
||||
{
|
||||
if (_actionQueueCallbacks.Count > 0)
|
||||
{
|
||||
foreach (var actionQueueCallback in _actionQueueCallbacks)
|
||||
{
|
||||
actionQueueCallback.Call();
|
||||
}
|
||||
|
||||
_actionQueueCallbacks.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,6 @@
|
||||
using AibisDream.Framework;
|
||||
using UnityEngine.Localization.Settings;
|
||||
|
||||
namespace AibisDream.Kit
|
||||
{
|
||||
public class Character
|
||||
@@ -47,7 +50,20 @@ namespace AibisDream.Kit
|
||||
/// <returns></returns>
|
||||
public string GetActorName()
|
||||
{
|
||||
return string.IsNullOrEmpty(nameColor) ? cn : $"<color={nameColor}>{cn}</color>";
|
||||
string rawName;
|
||||
// 人名部分直接为空
|
||||
if (string.IsNullOrWhiteSpace(key))
|
||||
{
|
||||
rawName = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
// 人名能找到
|
||||
var entry = LocalizationKit.ActorTableName[key];
|
||||
rawName = entry == null ? key : entry.LocalizedValue;
|
||||
}
|
||||
|
||||
return string.IsNullOrEmpty(nameColor) ? rawName : $"<color={nameColor}>{rawName}</color>";
|
||||
}
|
||||
|
||||
public string VoicePath
|
||||
|
||||
@@ -133,7 +133,6 @@ namespace AibisDream.Framework
|
||||
|
||||
public IEnumerator LoadByJson(JObject dataJson)
|
||||
{
|
||||
Debug.Log(_instances.Count);
|
||||
// 从加载序号1到10加载数据
|
||||
for (var i = 1; i <= 10; i++)
|
||||
{
|
||||
|
||||
@@ -1,14 +1,21 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.Localization;
|
||||
using UnityEngine.Localization.Settings;
|
||||
using UnityEngine.Localization.Tables;
|
||||
|
||||
namespace AibisDream.Framework
|
||||
{
|
||||
public static class LocalizationKit
|
||||
{
|
||||
private static LocalizationTable _actorTableName;
|
||||
|
||||
public static LocalizationTable ActorTableName => _actorTableName ??= new LocalizationTable("ActorName");
|
||||
|
||||
public static void SwitchLanguage(string localeCode)
|
||||
{
|
||||
var selectedLocale = LocalizationSettings.AvailableLocales.Locales.Find(locale => locale.Identifier.Code == localeCode);
|
||||
|
||||
var selectedLocale =
|
||||
LocalizationSettings.AvailableLocales.Locales.Find(locale => locale.Identifier.Code == localeCode);
|
||||
|
||||
if (selectedLocale)
|
||||
{
|
||||
LocalizationSettings.SelectedLocale = selectedLocale;
|
||||
@@ -19,4 +26,35 @@ namespace AibisDream.Framework
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class LocalizationTable
|
||||
{
|
||||
private readonly string _tableName;
|
||||
|
||||
private StringTable _stringTable;
|
||||
|
||||
public LocalizationTable(string tableName)
|
||||
{
|
||||
_tableName = tableName;
|
||||
_stringTable = LocalizationSettings.StringDatabase.GetTable(_tableName);
|
||||
LocalizationSettings.SelectedLocaleChanged += OnLocaleChanged;
|
||||
|
||||
Debug.Log($"表格{_tableName}已加载");
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
LocalizationSettings.SelectedLocaleChanged -= OnLocaleChanged;
|
||||
_stringTable = null;
|
||||
}
|
||||
|
||||
private void OnLocaleChanged(Locale locale)
|
||||
{
|
||||
_stringTable = LocalizationSettings.StringDatabase.GetTable(_tableName);
|
||||
}
|
||||
|
||||
public StringTableEntry this[string key] => _stringTable[key];
|
||||
|
||||
public LocaleIdentifier LocaleIdentifier => _stringTable.LocaleIdentifier;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,9 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.AddressableAssets;
|
||||
using UnityEngine.ResourceManagement.AsyncOperations;
|
||||
|
||||
namespace AibisDream.Framework
|
||||
{
|
||||
@@ -69,5 +72,39 @@ namespace AibisDream.Framework
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static T LoadAddressableSync<T>(string key)
|
||||
{
|
||||
T result = default;
|
||||
var operation = Addressables.LoadAssetAsync<T>(key);
|
||||
|
||||
// 运行协程等待加载完成
|
||||
GameManager.Instance.StartCoroutine(LoadCoroutine(operation, loadedObject => result = loadedObject));
|
||||
|
||||
// 等待协程完成(阻塞主线程)
|
||||
while (!operation.IsDone)
|
||||
{
|
||||
// 主动让出一帧
|
||||
System.Threading.Thread.Sleep(1);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static IEnumerator LoadCoroutine<T>(AsyncOperationHandle<T> operation, Action<T> onComplete)
|
||||
{
|
||||
yield return operation;
|
||||
|
||||
if (operation.Status == AsyncOperationStatus.Succeeded)
|
||||
{
|
||||
onComplete?.Invoke(operation.Result);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("Failed to load addressable");
|
||||
}
|
||||
|
||||
Addressables.Release(operation);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,16 +12,16 @@ namespace AibisDream
|
||||
OpenScreen,
|
||||
CloseScreen,
|
||||
SceneLoad,
|
||||
SceneUnload,
|
||||
FixStateSwitch,
|
||||
Menu
|
||||
FixStateSwitch
|
||||
}
|
||||
|
||||
public enum GameLoopEnum
|
||||
{
|
||||
AppStart,
|
||||
GameStart,
|
||||
GameQuit
|
||||
GameQuit,
|
||||
PauseGame,
|
||||
UnPauseGame
|
||||
}
|
||||
|
||||
public enum DialogEventEnum
|
||||
|
||||
@@ -94,10 +94,12 @@ namespace AibisDream
|
||||
{
|
||||
// 系统暂停
|
||||
Time.timeScale = 0;
|
||||
// 交互暂停
|
||||
CursorManager.Instance.isPaused = true;
|
||||
// 交互继续
|
||||
EnumEventSystem.Global.Send(GameLoopEnum.PauseGame);
|
||||
// 音频全部暂停
|
||||
AudioManager.Instance.PauseAll();
|
||||
// 关闭Dialog
|
||||
DialogCanvasManager.Instance.CloseCanvas();
|
||||
}
|
||||
|
||||
public void ContinueGame()
|
||||
@@ -105,9 +107,11 @@ namespace AibisDream
|
||||
// 系统继续
|
||||
Time.timeScale = 1;
|
||||
// 交互继续
|
||||
CursorManager.Instance.isPaused = false;
|
||||
EnumEventSystem.Global.Send(GameLoopEnum.UnPauseGame);
|
||||
// 音频继续
|
||||
AudioManager.Instance.UnPauseAll();
|
||||
// 打开Dialog
|
||||
DialogCanvasManager.Instance.OpenCanvas();
|
||||
}
|
||||
|
||||
public void QuitGame()
|
||||
@@ -115,11 +119,13 @@ namespace AibisDream
|
||||
// 系统继续
|
||||
Time.timeScale = 1;
|
||||
// 交互继续
|
||||
CursorManager.Instance.isPaused = true;
|
||||
EnumEventSystem.Global.Send(GameLoopEnum.GameQuit);
|
||||
// 卸载当前场景
|
||||
StartCoroutine(RestartCoroutine());
|
||||
// 音频继续
|
||||
AudioManager.Instance.UnPauseAll();
|
||||
// 打开Dialog
|
||||
DialogCanvasManager.Instance.OpenCanvas();
|
||||
}
|
||||
|
||||
public void QuitApp()
|
||||
|
||||
@@ -78,17 +78,11 @@ namespace AibisDream
|
||||
{
|
||||
yield return Addressables.UnloadSceneAsync(_loadHandle);
|
||||
_data.sceneName = null;
|
||||
EnumEventSystem.Global.Send(EventEnum.SceneUnload);
|
||||
}
|
||||
|
||||
_isLoading = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void UnloadScene()
|
||||
{
|
||||
StartCoroutine(UnloadSceneAsync());
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
|
||||
@@ -13,17 +13,19 @@ namespace AibisDream
|
||||
private const float DelayTime = 0.1f;
|
||||
|
||||
[Header("指针图片")] public Sprite defaultCursor;
|
||||
public Sprite nextTalk, talking, option, interactive, holding, disable, eye;
|
||||
public Sprite nextTalk, talking, option, interactive, holding, disable;
|
||||
|
||||
private Image _cursor;
|
||||
|
||||
private Sprite _cursorCache;
|
||||
private CursorState _stateCache;
|
||||
|
||||
#region 状态相关
|
||||
|
||||
private Coroutine _switchCoroutine;
|
||||
private CursorState _curState = CursorState.Default;
|
||||
private bool _isTalking;
|
||||
[HideInInspector] public bool isInMenu;
|
||||
[HideInInspector] public bool isPaused;
|
||||
private bool _isPaused;
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -66,9 +68,49 @@ namespace AibisDream
|
||||
private void RegisterEvent()
|
||||
{
|
||||
// 此处监听所有可能对鼠标状态产生影响的事件
|
||||
RegisterGameEvent();
|
||||
RegisterDialogEvent();
|
||||
RegisterTriggerEvent();
|
||||
RegisterMenu();
|
||||
}
|
||||
|
||||
private void RegisterGameEvent()
|
||||
{
|
||||
_unRegisters.Add(EnumEventSystem.Global.Register(GameLoopEnum.GameQuit, OnGameQuit));
|
||||
_unRegisters.Add(EnumEventSystem.Global.Register(GameLoopEnum.PauseGame, OnPauseGame));
|
||||
_unRegisters.Add(EnumEventSystem.Global.Register(GameLoopEnum.UnPauseGame, OnUnPauseGame));
|
||||
}
|
||||
|
||||
private void OnUnPauseGame()
|
||||
{
|
||||
_cursor.sprite = _cursorCache;
|
||||
_cursorCache = null;
|
||||
|
||||
_curState = _stateCache;
|
||||
_stateCache = CursorState.Default;
|
||||
|
||||
_isPaused = false;
|
||||
}
|
||||
|
||||
private void OnPauseGame()
|
||||
{
|
||||
_cursorCache = _cursor.sprite;
|
||||
_cursor.sprite = defaultCursor;
|
||||
|
||||
_stateCache = _curState;
|
||||
_curState = CursorState.Default;
|
||||
|
||||
_isPaused = true;
|
||||
}
|
||||
|
||||
private void OnGameQuit()
|
||||
{
|
||||
_cursor.sprite = defaultCursor;
|
||||
_cursorCache = null;
|
||||
|
||||
_curState = CursorState.Default;
|
||||
_stateCache = CursorState.Default;
|
||||
|
||||
_isPaused = false;
|
||||
}
|
||||
|
||||
private void RegisterDialogEvent()
|
||||
@@ -100,16 +142,16 @@ namespace AibisDream
|
||||
EnumEventSystem.Global.Register<TriggerEnum, IInteraction>(TriggerEnum.PointerUp, OnPointerUp));
|
||||
}
|
||||
|
||||
private void RegisterMenu()
|
||||
{
|
||||
_unRegisters.Add(EnumEventSystem.Global.Register<EventEnum, bool>(EventEnum.Menu, OnMenuChange));
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (_isPaused)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (Input.GetMouseButtonDown(0) || Input.GetKeyDown(KeyCode.Space))
|
||||
{
|
||||
if (_isTalking && !isInMenu)
|
||||
if (_isTalking)
|
||||
{
|
||||
DialogController.Instance.JumpLine();
|
||||
}
|
||||
@@ -214,17 +256,6 @@ namespace AibisDream
|
||||
SwitchCursor(EventSystemEx.Instance.holdingObj == target.GetGameObject() ? interactive : defaultCursor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region 菜单打开
|
||||
|
||||
private void OnMenuChange(bool isMenuOpen)
|
||||
{
|
||||
isInMenu = isMenuOpen;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -262,6 +293,7 @@ namespace AibisDream
|
||||
{
|
||||
Default,
|
||||
Interactive,
|
||||
Eye
|
||||
Dialog,
|
||||
Menu
|
||||
}
|
||||
}
|
||||
@@ -61,7 +61,7 @@ namespace AibisDream
|
||||
_dialogText = transform.Find(DialogText)?.gameObject.GetComponent<TypewriterByCharacter>();
|
||||
_nextArray = transform.Find(NextArray)?.gameObject;
|
||||
_choiceBox = transform.Find(ChoiceBox)?.gameObject;
|
||||
|
||||
|
||||
OnAwake();
|
||||
}
|
||||
|
||||
@@ -85,7 +85,6 @@ namespace AibisDream
|
||||
/// <param name="dialogLine">对话内容</param>
|
||||
/// <param name="character">角色内容</param>
|
||||
/// <param name="nextStep">下一步</param>
|
||||
/// <param name="onTextShowed">文字展示结束后触发</param>
|
||||
/// <param name="isAutoSkip">是否自动跳过,默认为false</param>
|
||||
public virtual void ShowLine(string dialogLine, CharacterVo character, Action nextStep, bool isAutoSkip = false)
|
||||
{
|
||||
@@ -196,7 +195,7 @@ namespace AibisDream
|
||||
{
|
||||
if (!_actorName) return;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(character.GetActorName()))
|
||||
if (string.IsNullOrWhiteSpace(character.key))
|
||||
{
|
||||
_actorName.transform.parent.gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
@@ -3,22 +3,17 @@ using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using AibisDream.Framework;
|
||||
using AibisDream.Kit;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace AibisDream
|
||||
{
|
||||
public class DialogCanvasManager : Singleton<DialogCanvasManager>, IDialogView
|
||||
{
|
||||
private const string QuickTalk = "Quick Talk";
|
||||
|
||||
#region 引用
|
||||
|
||||
private readonly Dictionary<DialogViewType, IDialogView> _dialogViewDict = new();
|
||||
private IDialogView _curView;
|
||||
private IDialogView _lastShowView;
|
||||
private GameObject _quickTalkButton;
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -26,7 +21,6 @@ namespace AibisDream
|
||||
|
||||
public override void OnSingletonInit()
|
||||
{
|
||||
InitQuickTalkButton();
|
||||
InitEvent();
|
||||
|
||||
// 默认对话框直接加载
|
||||
@@ -74,29 +68,8 @@ namespace AibisDream
|
||||
|
||||
#endregion
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (Input.GetKeyDown(KeyCode.Q) && Input.GetKey(KeyCode.P))
|
||||
{
|
||||
_quickTalkButton.SetActive(!_quickTalkButton.activeSelf);
|
||||
}
|
||||
}
|
||||
|
||||
#region 对话框相关处理
|
||||
|
||||
private void InitQuickTalkButton()
|
||||
{
|
||||
_quickTalkButton = transform.Find(QuickTalk).gameObject;
|
||||
_quickTalkButton.GetComponent<Button>().onClick.AddListener(SwitchQuickTalkMode);
|
||||
}
|
||||
|
||||
private void SwitchQuickTalkMode()
|
||||
{
|
||||
DialogController.Instance.quickRunMode = !DialogController.Instance.quickRunMode;
|
||||
_quickTalkButton.GetComponent<Image>().color =
|
||||
DialogController.Instance.quickRunMode ? Color.gray : Color.white;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 注册对话框
|
||||
/// </summary>
|
||||
@@ -215,14 +188,14 @@ namespace AibisDream
|
||||
DialogRecord.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 切换对话回顾展示状态
|
||||
/// </summary>
|
||||
public void ControlDialogHistory()
|
||||
public void CloseCanvas()
|
||||
{
|
||||
var logObj = transform.Find("Dialogue Log").gameObject;
|
||||
logObj.SetActive(!logObj.activeSelf);
|
||||
EnumEventSystem.Global.Send(EventEnum.Menu, logObj.activeSelf);
|
||||
gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
public void OpenCanvas()
|
||||
{
|
||||
gameObject.SetActive(true);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -48,5 +48,10 @@ namespace AibisDream.Framework
|
||||
{
|
||||
gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
public void SetMaxCharNum(string value)
|
||||
{
|
||||
maxCharNum = int.Parse(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,7 @@ namespace AibisDream
|
||||
GameManager.Instance.PauseGame();
|
||||
gameObject.SetActive(true);
|
||||
|
||||
var btn = transform.Find("Return").GetComponent<Button>();
|
||||
var btn = transform.Find("Title").Find("Return").GetComponent<Button>();
|
||||
btn.onClick.AddListener(ReturnGame);
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace AibisDream
|
||||
GameManager.Instance.ContinueGame();
|
||||
// 关闭时停止渲染
|
||||
ClearText();
|
||||
var btn = transform.Find("Return").GetComponent<Button>();
|
||||
var btn = transform.Find("Title").Find("Return").GetComponent<Button>();
|
||||
btn.onClick.RemoveAllListeners();
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace AibisDream
|
||||
{
|
||||
public class SavesPanel : MonoBehaviour, IUIPanel
|
||||
{
|
||||
public bool IsOpen => gameObject.activeSelf;
|
||||
|
||||
private static readonly string SaveFilePath = Application.streamingAssetsPath + "/SaveFiles";
|
||||
|
||||
#region 索引
|
||||
public Button buttonPrefab;
|
||||
public Transform buttonParent;
|
||||
#endregion
|
||||
|
||||
#region 打开和关闭
|
||||
|
||||
public void Show()
|
||||
{
|
||||
InitLevelBtn();
|
||||
gameObject.SetActive(true);
|
||||
RegisterButton();
|
||||
}
|
||||
|
||||
public void Hide()
|
||||
{
|
||||
gameObject.SetActive(false);
|
||||
UnRegisterButton();
|
||||
}
|
||||
|
||||
private void RegisterButton()
|
||||
{
|
||||
var returnBtn = transform.Find("Return").GetComponent<Button>();
|
||||
returnBtn.onClick.AddListener(() => UIManager.Instance.HidePanel<SavesPanel>());
|
||||
}
|
||||
|
||||
private void UnRegisterButton()
|
||||
{
|
||||
var returnBtn = transform.Find("Return").GetComponent<Button>();
|
||||
returnBtn.onClick.RemoveAllListeners();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private void InitLevelBtn()
|
||||
{
|
||||
// 清空旧按钮
|
||||
foreach (Transform child in buttonParent)
|
||||
{
|
||||
Destroy(child.gameObject);
|
||||
}
|
||||
|
||||
// 加载存档文件
|
||||
string[] saveFiles = Directory.GetFiles(SaveFilePath, "*.json");
|
||||
var orderedSaveFiles = saveFiles.OrderByDescending(item => item).ToArray();
|
||||
foreach (var saveFile in orderedSaveFiles)
|
||||
{
|
||||
var button = Instantiate(buttonPrefab, buttonParent);
|
||||
button.GetComponentInChildren<TMP_Text>().text = Path.GetFileNameWithoutExtension(saveFile);
|
||||
button.onClick.AddListener(() => OnSaveFileSelected(saveFile));
|
||||
}
|
||||
}
|
||||
|
||||
private void OnSaveFileSelected(string saveFileName)
|
||||
{
|
||||
// 隐藏UI
|
||||
gameObject.SetActive(false);
|
||||
// 开始游戏
|
||||
GameManager.Instance.StartWithSaveFile(saveFileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bdd86c19be1449ca9e2783eb714fb8ff
|
||||
timeCreated: 1745572533
|
||||
@@ -34,6 +34,7 @@ namespace AibisDream
|
||||
tabs.Find("Start").GetComponent<Button>().onClick.AddListener(StartNewGame);
|
||||
tabs.Find("Select Level").GetComponent<Button>().onClick.AddListener(OpenLevelPanel);
|
||||
tabs.Find("Load Save File").GetComponent<Button>().onClick.AddListener(OpenSaveFilePanel);
|
||||
tabs.Find("Setting").GetComponent<Button>().onClick.AddListener(OpenSetting);
|
||||
tabs.Find("Quit").GetComponent<Button>().onClick.AddListener(QuitApp);
|
||||
// 打开链接
|
||||
transform.Find("问卷").GetComponent<Button>().onClick.AddListener(() => Application.OpenURL(ConstRef.SurveyURL));
|
||||
@@ -55,7 +56,12 @@ namespace AibisDream
|
||||
|
||||
private void OpenSaveFilePanel()
|
||||
{
|
||||
// TODO 打开存档面板
|
||||
UIManager.Instance.ShowPanel<SavesPanel>();
|
||||
}
|
||||
|
||||
private void OpenSetting()
|
||||
{
|
||||
UIManager.Instance.ShowPanel<SettingPanel>();
|
||||
}
|
||||
|
||||
private void QuitApp()
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using TMPro;
|
||||
@@ -52,7 +50,7 @@ namespace AibisDream
|
||||
// GameLoopManager.Instance.StartWithSaveFile(saveFileName);
|
||||
}
|
||||
|
||||
public void HideSaveFileUI()
|
||||
private void HideSaveFileUI()
|
||||
{
|
||||
gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user