ui: add inactive global setting panel
This commit is contained in:
parent
b8cb845245
commit
08a49c1df2
@ -0,0 +1,125 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1 &1000000000000000001
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 2000000000000000001}
|
||||
- component: {fileID: 3000000000000000001}
|
||||
- component: {fileID: 4000000000000000001}
|
||||
- component: {fileID: 5000000000000000001}
|
||||
- component: {fileID: 6000000000000000001}
|
||||
- component: {fileID: 7000000000000000001}
|
||||
m_Layer: 5
|
||||
m_Name: UIGlobalSetting
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &2000000000000000001
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1000000000000000001}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
||||
m_AnchorMax: {x: 0.5, y: 0.5}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 1180, y: 720}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!114 &3000000000000000001
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1000000000000000001}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 0ad50f81b1d25c441943c37a89ba23f6, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
_Animator: {fileID: 4000000000000000001}
|
||||
_ActionOnDisable: 0
|
||||
--- !u!95 &4000000000000000001
|
||||
Animator:
|
||||
serializedVersion: 5
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1000000000000000001}
|
||||
m_Enabled: 1
|
||||
m_Avatar: {fileID: 0}
|
||||
m_Controller: {fileID: 0}
|
||||
m_CullingMode: 0
|
||||
m_UpdateMode: 0
|
||||
m_ApplyRootMotion: 0
|
||||
m_LinearVelocityBlending: 0
|
||||
m_StabilizeFeet: 0
|
||||
m_WarningMessage:
|
||||
m_HasTransformHierarchy: 1
|
||||
m_AllowConstantClipSamplingOptimization: 1
|
||||
m_KeepAnimatorStateOnDisable: 0
|
||||
m_WriteDefaultValuesOnDisable: 0
|
||||
--- !u!225 &5000000000000000001
|
||||
CanvasGroup:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1000000000000000001}
|
||||
m_Enabled: 1
|
||||
m_Alpha: 1
|
||||
m_Interactable: 1
|
||||
m_BlocksRaycasts: 1
|
||||
m_IgnoreParentGroups: 0
|
||||
--- !u!114 &6000000000000000001
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1000000000000000001}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: e51b9280cf324acb9a977eb172eb62bc, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
_showAnimationClip: {fileID: 0}
|
||||
_hideAnimationClip: {fileID: 0}
|
||||
CloseButton: {fileID: 0}
|
||||
BlockerButton: {fileID: 0}
|
||||
TabRoot: {fileID: 0}
|
||||
PageRoot: {fileID: 0}
|
||||
TitleText: {fileID: 0}
|
||||
--- !u!114 &7000000000000000001
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1000000000000000001}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: dba07edb0e077114b8d1d67f0a1eaadd, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
GameObjectList: []
|
||||
GameObjectList2: []
|
||||
AutoGameObjectList: []
|
||||
ValueList: []
|
||||
ClassName:
|
||||
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5149219fee234dfaa8477edb443dfff1
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,69 @@
|
||||
using TH1_UI.Controller.Base;
|
||||
using TH1_UI.View.Global;
|
||||
|
||||
namespace TH1_UI.Controller.Global
|
||||
{
|
||||
public class UIGlobalSettingController : ViewController<UIGlobalSettingView>
|
||||
{
|
||||
public UIGlobalSettingController() { }
|
||||
|
||||
protected override void RegisterEventCallback()
|
||||
{
|
||||
base.RegisterEventCallback();
|
||||
if (WindowScript == null) return;
|
||||
|
||||
WindowScript.OnBtnCloseClick += _OnBtnCloseClick;
|
||||
WindowScript.OnBtnRepairRendererClick += _OnBtnRepairRendererClick;
|
||||
WindowScript.OnBtnBugReportClick += _OnBtnBugReportClick;
|
||||
WindowScript.OnBtnManageLanguageClick += _OnBtnManageLanguageClick;
|
||||
}
|
||||
|
||||
protected override void UnregisterEventCallback()
|
||||
{
|
||||
if (WindowScript != null)
|
||||
{
|
||||
WindowScript.OnBtnCloseClick = null;
|
||||
WindowScript.OnBtnRepairRendererClick = null;
|
||||
WindowScript.OnBtnBugReportClick = null;
|
||||
WindowScript.OnBtnManageLanguageClick = null;
|
||||
}
|
||||
|
||||
base.UnregisterEventCallback();
|
||||
}
|
||||
|
||||
protected override void OnOpen()
|
||||
{
|
||||
base.OnOpen();
|
||||
var context = _openParameter is UIGlobalSettingContext settingContext
|
||||
? settingContext
|
||||
: UIGlobalSettingContext.OutsideMenu;
|
||||
WindowScript?.SetContent(context);
|
||||
}
|
||||
|
||||
public override bool Close()
|
||||
{
|
||||
WindowScript?.CloseView();
|
||||
return base.Close();
|
||||
}
|
||||
|
||||
private void _OnBtnCloseClick()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
private void _OnBtnRepairRendererClick()
|
||||
{
|
||||
TH1Renderer.MapRenderer.Instance?.RepairAllRenderers();
|
||||
}
|
||||
|
||||
private void _OnBtnBugReportClick()
|
||||
{
|
||||
TH1_Core.Events.EventManager.Publish(new TH1_Core.Events.ShowUIGlobalBugReport());
|
||||
}
|
||||
|
||||
private void _OnBtnManageLanguageClick()
|
||||
{
|
||||
TH1_Core.Events.EventManager.Publish(new TH1_Core.Events.ShowUIOutsideMod());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6a351fd2294b4d729bec1d455a9cf8c0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,115 @@
|
||||
using System;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace TH1_UI.View.Global
|
||||
{
|
||||
public class UIGlobalSettingTabMono : MonoBehaviour
|
||||
{
|
||||
private UIGlobalSettingPage _page;
|
||||
private Button _button;
|
||||
private TMP_Text _label;
|
||||
private Action<UIGlobalSettingPage> _onSelected;
|
||||
|
||||
public void Init(UIGlobalSettingPage page, Button button, TMP_Text label, Action<UIGlobalSettingPage> onSelected)
|
||||
{
|
||||
_page = page;
|
||||
_button = button;
|
||||
_label = label;
|
||||
_onSelected = onSelected;
|
||||
|
||||
if (_button == null) return;
|
||||
_button.onClick.RemoveAllListeners();
|
||||
_button.onClick.AddListener(() => _onSelected?.Invoke(_page));
|
||||
}
|
||||
|
||||
public void SetSelected(bool selected)
|
||||
{
|
||||
if (_button != null && _button.targetGraphic != null)
|
||||
_button.targetGraphic.color = selected ? new Color32(97, 121, 155, 255) : new Color32(58, 66, 84, 255);
|
||||
|
||||
if (_label != null)
|
||||
_label.color = selected ? Color.white : new Color32(190, 197, 208, 255);
|
||||
}
|
||||
}
|
||||
|
||||
public class UIGlobalSettingToggleRowMono : MonoBehaviour
|
||||
{
|
||||
private TMP_Text _label;
|
||||
private Toggle _toggle;
|
||||
private Func<bool> _getter;
|
||||
private Action<bool> _setter;
|
||||
|
||||
public void Init(TMP_Text label, Toggle toggle, Func<bool> getter, Action<bool> setter)
|
||||
{
|
||||
_label = label;
|
||||
_toggle = toggle;
|
||||
_getter = getter;
|
||||
_setter = setter;
|
||||
|
||||
if (_toggle == null) return;
|
||||
_toggle.onValueChanged.RemoveAllListeners();
|
||||
_toggle.onValueChanged.AddListener(OnValueChanged);
|
||||
Refresh();
|
||||
}
|
||||
|
||||
public void Refresh()
|
||||
{
|
||||
if (_toggle == null || _getter == null) return;
|
||||
_toggle.SetIsOnWithoutNotify(_getter());
|
||||
}
|
||||
|
||||
private void OnValueChanged(bool value)
|
||||
{
|
||||
_setter?.Invoke(value);
|
||||
Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
public class UIGlobalSettingSliderRowMono : MonoBehaviour
|
||||
{
|
||||
private TMP_Text _label;
|
||||
private Slider _slider;
|
||||
private TMP_Text _valueText;
|
||||
private Func<float> _getter;
|
||||
private Action<float> _setter;
|
||||
|
||||
public void Init(TMP_Text label, Slider slider, TMP_Text valueText, Func<float> getter, Action<float> setter)
|
||||
{
|
||||
_label = label;
|
||||
_slider = slider;
|
||||
_valueText = valueText;
|
||||
_getter = getter;
|
||||
_setter = setter;
|
||||
|
||||
if (_slider == null) return;
|
||||
_slider.minValue = 0f;
|
||||
_slider.maxValue = 1f;
|
||||
_slider.onValueChanged.RemoveAllListeners();
|
||||
_slider.onValueChanged.AddListener(OnValueChanged);
|
||||
Refresh();
|
||||
}
|
||||
|
||||
public void Refresh()
|
||||
{
|
||||
if (_slider == null || _getter == null) return;
|
||||
float value = Mathf.Clamp01(_getter());
|
||||
_slider.SetValueWithoutNotify(value);
|
||||
RefreshValueText(value);
|
||||
}
|
||||
|
||||
private void OnValueChanged(float value)
|
||||
{
|
||||
value = Mathf.Clamp01(value);
|
||||
_setter?.Invoke(value);
|
||||
RefreshValueText(value);
|
||||
}
|
||||
|
||||
private void RefreshValueText(float value)
|
||||
{
|
||||
if (_valueText != null)
|
||||
_valueText.text = Mathf.RoundToInt(value * 100f).ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b0e6ccb7ff0f4a22a78dff270581981d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
670
Unity/Assets/Scripts/TH1_UI/View/Global/UIGlobalSettingView.cs
Normal file
670
Unity/Assets/Scripts/TH1_UI/View/Global/UIGlobalSettingView.cs
Normal file
@ -0,0 +1,670 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Logic.Multilingual;
|
||||
using TH1_Logic.Config;
|
||||
using TH1_UI.View.Base;
|
||||
using TH1_UI.View.Outside;
|
||||
using TH1Renderer;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace TH1_UI.View.Global
|
||||
{
|
||||
public enum UIGlobalSettingContext
|
||||
{
|
||||
OutsideMenu,
|
||||
InGame
|
||||
}
|
||||
|
||||
public enum UIGlobalSettingPage
|
||||
{
|
||||
Language,
|
||||
Audio,
|
||||
Display,
|
||||
Game,
|
||||
Support
|
||||
}
|
||||
|
||||
public class UIGlobalSettingView : View.Base.View
|
||||
{
|
||||
public Button CloseButton;
|
||||
public Button BlockerButton;
|
||||
public Transform TabRoot;
|
||||
public Transform PageRoot;
|
||||
public TMP_Text TitleText;
|
||||
|
||||
public ViDelegateAssisstant.Dele OnBtnCloseClick;
|
||||
public ViDelegateAssisstant.Dele OnBtnRepairRendererClick;
|
||||
public ViDelegateAssisstant.Dele OnBtnBugReportClick;
|
||||
public ViDelegateAssisstant.Dele OnBtnManageLanguageClick;
|
||||
|
||||
private readonly Dictionary<UIGlobalSettingPage, GameObject> _pages = new Dictionary<UIGlobalSettingPage, GameObject>();
|
||||
private readonly Dictionary<UIGlobalSettingPage, UIGlobalSettingTabMono> _tabs = new Dictionary<UIGlobalSettingPage, UIGlobalSettingTabMono>();
|
||||
private readonly List<UIGlobalSettingToggleRowMono> _toggleRows = new List<UIGlobalSettingToggleRowMono>();
|
||||
private readonly List<UIGlobalSettingSliderRowMono> _sliderRows = new List<UIGlobalSettingSliderRowMono>();
|
||||
|
||||
private UIOutsideSelectOptionGroupMono _languageOptionGroup;
|
||||
private GameObject _moreLanguageModule;
|
||||
private TMP_Text _nowUsingLanguageText;
|
||||
private Button _manageLanguageButton;
|
||||
private Button _repairRendererButton;
|
||||
private Button _bugReportButton;
|
||||
private UIGlobalSettingContext _context;
|
||||
private UIGlobalSettingPage _currentPage = UIGlobalSettingPage.Language;
|
||||
private bool _builtRuntimeLayout;
|
||||
|
||||
protected override void OnInit()
|
||||
{
|
||||
base.OnInit();
|
||||
EnsureLayout();
|
||||
BindCloseButtons();
|
||||
}
|
||||
|
||||
public void SetContent(UIGlobalSettingContext context)
|
||||
{
|
||||
EnsureLayout();
|
||||
_context = context;
|
||||
|
||||
RefreshLanguageOption();
|
||||
RefreshRows();
|
||||
RefreshContextVisibility();
|
||||
SelectPage(_currentPage);
|
||||
}
|
||||
|
||||
public void CloseView()
|
||||
{
|
||||
if (_moreLanguageModule != null) _moreLanguageModule.SetActive(false);
|
||||
}
|
||||
|
||||
private void BindCloseButtons()
|
||||
{
|
||||
if (CloseButton != null)
|
||||
{
|
||||
CloseButton.onClick.RemoveAllListeners();
|
||||
CloseButton.onClick.AddListener(() => OnBtnCloseClick?.Invoke());
|
||||
}
|
||||
|
||||
if (BlockerButton != null)
|
||||
{
|
||||
BlockerButton.onClick.RemoveAllListeners();
|
||||
BlockerButton.onClick.AddListener(() => OnBtnCloseClick?.Invoke());
|
||||
}
|
||||
}
|
||||
|
||||
private void RefreshRows()
|
||||
{
|
||||
foreach (var row in _toggleRows)
|
||||
{
|
||||
if (row == null) continue;
|
||||
row.Refresh();
|
||||
}
|
||||
|
||||
foreach (var row in _sliderRows)
|
||||
{
|
||||
if (row == null) continue;
|
||||
row.Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
private void RefreshContextVisibility()
|
||||
{
|
||||
SetPageVisible(UIGlobalSettingPage.Support, _context == UIGlobalSettingContext.InGame);
|
||||
if (_context != UIGlobalSettingContext.InGame && _currentPage == UIGlobalSettingPage.Support)
|
||||
_currentPage = UIGlobalSettingPage.Language;
|
||||
}
|
||||
|
||||
private void SetPageVisible(UIGlobalSettingPage page, bool visible)
|
||||
{
|
||||
if (_tabs.TryGetValue(page, out var tab) && tab != null)
|
||||
tab.gameObject.SetActive(visible);
|
||||
}
|
||||
|
||||
private void SelectPage(UIGlobalSettingPage page)
|
||||
{
|
||||
if (!_pages.ContainsKey(page))
|
||||
page = UIGlobalSettingPage.Language;
|
||||
|
||||
_currentPage = page;
|
||||
foreach (var kv in _pages)
|
||||
{
|
||||
if (kv.Value != null)
|
||||
kv.Value.SetActive(kv.Key == page);
|
||||
}
|
||||
|
||||
foreach (var kv in _tabs)
|
||||
{
|
||||
if (kv.Value != null)
|
||||
kv.Value.SetSelected(kv.Key == page);
|
||||
}
|
||||
}
|
||||
|
||||
private void RefreshLanguageOption()
|
||||
{
|
||||
if (_languageOptionGroup == null) return;
|
||||
|
||||
var lan = MultilingualManager.Instance.GetCurLanguage();
|
||||
bool useMore = !IsPrimaryLanguage(lan);
|
||||
uint idx;
|
||||
|
||||
if (useMore)
|
||||
{
|
||||
idx = 5;
|
||||
if (ConfigManager.Instance.Config.SecondaryLanguage != lan)
|
||||
ConfigManager.Instance.Config.SecondaryLanguage = lan;
|
||||
}
|
||||
else
|
||||
{
|
||||
idx = lan switch
|
||||
{
|
||||
MultilingualType.ZH => 0,
|
||||
MultilingualType.TDZH => 1,
|
||||
MultilingualType.JP => 2,
|
||||
MultilingualType.EN => 3,
|
||||
MultilingualType.KR => 4,
|
||||
_ => 3
|
||||
};
|
||||
}
|
||||
|
||||
_languageOptionGroup.Init(idx);
|
||||
_languageOptionGroup.OnOptionClicked = OnLanguageClicked;
|
||||
RefreshMoreLanguageModule(useMore);
|
||||
}
|
||||
|
||||
private static bool IsPrimaryLanguage(MultilingualType type)
|
||||
{
|
||||
return type == MultilingualType.ZH
|
||||
|| type == MultilingualType.TDZH
|
||||
|| type == MultilingualType.JP
|
||||
|| type == MultilingualType.EN
|
||||
|| type == MultilingualType.KR;
|
||||
}
|
||||
|
||||
private void RefreshMoreLanguageModule(bool show)
|
||||
{
|
||||
if (_moreLanguageModule != null)
|
||||
_moreLanguageModule.SetActive(show);
|
||||
|
||||
if (_nowUsingLanguageText != null)
|
||||
_nowUsingLanguageText.text = GetLanguageDisplayName(MultilingualManager.Instance.GetCurLanguage());
|
||||
}
|
||||
|
||||
private void OnLanguageClicked(uint idx)
|
||||
{
|
||||
if (idx == 5)
|
||||
{
|
||||
var secondary = ConfigManager.Instance.Config.SecondaryLanguage;
|
||||
if (secondary == MultilingualType.None) secondary = MultilingualType.EN;
|
||||
MultilingualManager.Instance.ChangedMultilingual(secondary);
|
||||
RefreshMoreLanguageModule(true);
|
||||
return;
|
||||
}
|
||||
|
||||
RefreshMoreLanguageModule(false);
|
||||
switch (idx)
|
||||
{
|
||||
case 0:
|
||||
MultilingualManager.Instance.ChangedMultilingual(MultilingualType.ZH);
|
||||
break;
|
||||
case 1:
|
||||
MultilingualManager.Instance.ChangedMultilingual(MultilingualType.TDZH);
|
||||
break;
|
||||
case 2:
|
||||
MultilingualManager.Instance.ChangedMultilingual(MultilingualType.JP);
|
||||
break;
|
||||
case 3:
|
||||
MultilingualManager.Instance.ChangedMultilingual(MultilingualType.EN);
|
||||
break;
|
||||
case 4:
|
||||
MultilingualManager.Instance.ChangedMultilingual(MultilingualType.KR);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetLanguageDisplayName(MultilingualType type)
|
||||
{
|
||||
return type switch
|
||||
{
|
||||
MultilingualType.ZH => "简体中文",
|
||||
MultilingualType.TDZH => "繁體中文",
|
||||
MultilingualType.EN => "English",
|
||||
MultilingualType.JP => "日本語",
|
||||
MultilingualType.KR => "한국어",
|
||||
MultilingualType.RU => "Русский",
|
||||
MultilingualType.ES => "Español",
|
||||
MultilingualType.PT => "Português",
|
||||
MultilingualType.FR => "Français",
|
||||
MultilingualType.DE => "Deutsch",
|
||||
MultilingualType.ID => "Bahasa Indonesia",
|
||||
MultilingualType.TH => "ไทย",
|
||||
MultilingualType.PL => "Polski",
|
||||
MultilingualType.VI => "Tiếng Việt",
|
||||
MultilingualType.MS => "Bahasa Melayu",
|
||||
MultilingualType.UK => "Українська",
|
||||
MultilingualType.KZ => "Қазақша",
|
||||
MultilingualType.TR => "Türkçe",
|
||||
MultilingualType.IT => "Italiano",
|
||||
MultilingualType.NL => "Nederlands",
|
||||
MultilingualType.FI => "Suomi",
|
||||
MultilingualType.SV => "Svenska",
|
||||
MultilingualType.NO => "Norsk",
|
||||
MultilingualType.CS => "Čeština",
|
||||
MultilingualType.HU => "Magyar",
|
||||
MultilingualType.EL => "Ελληνικά",
|
||||
MultilingualType.RO => "Română",
|
||||
MultilingualType.ET => "Eesti",
|
||||
MultilingualType.LT => "Lietuvių",
|
||||
MultilingualType.HR => "Hrvatski",
|
||||
MultilingualType.SR => "Српски",
|
||||
MultilingualType.SL => "Slovenščina",
|
||||
MultilingualType.SK => "Slovenčina",
|
||||
MultilingualType.BE => "Беларуская",
|
||||
MultilingualType.HE => "עברית",
|
||||
MultilingualType.BG => "Български",
|
||||
MultilingualType.UZ => "O'zbekcha",
|
||||
MultilingualType.KY => "Кыргызча",
|
||||
MultilingualType.MN => "Монгол",
|
||||
MultilingualType.AR => "العربية",
|
||||
MultilingualType.DA => "Dansk",
|
||||
MultilingualType.TL => "Filipino",
|
||||
MultilingualType.Custom => "Custom",
|
||||
_ => type.ToString()
|
||||
};
|
||||
}
|
||||
|
||||
private void EnsureLayout()
|
||||
{
|
||||
if (_builtRuntimeLayout) return;
|
||||
_builtRuntimeLayout = true;
|
||||
|
||||
EnsureRootComponents();
|
||||
BuildRuntimeLayout();
|
||||
BindCloseButtons();
|
||||
}
|
||||
|
||||
private void EnsureRootComponents()
|
||||
{
|
||||
if (GetComponent<RectTransform>() == null)
|
||||
gameObject.AddComponent<RectTransform>();
|
||||
|
||||
if (GetComponent<CanvasGroup>() == null)
|
||||
gameObject.AddComponent<CanvasGroup>();
|
||||
}
|
||||
|
||||
private void BuildRuntimeLayout()
|
||||
{
|
||||
var root = GetComponent<RectTransform>();
|
||||
root.anchorMin = new Vector2(0.5f, 0.5f);
|
||||
root.anchorMax = new Vector2(0.5f, 0.5f);
|
||||
root.sizeDelta = new Vector2(1180f, 720f);
|
||||
root.pivot = new Vector2(0.5f, 0.5f);
|
||||
|
||||
BlockerButton = CreateFullScreenBlocker();
|
||||
|
||||
var panel = CreatePanel(root);
|
||||
TitleText = CreateText(panel, "Title", "设置", 34, TextAlignmentOptions.Center, new RectSpec(0.5f, 0.5f, 1f, 1f, 0f, -36f, 260f, 52f));
|
||||
CloseButton = CreateTextButton(panel, "CloseButton", "×", new RectSpec(1f, 1f, 1f, 1f, -46f, -36f, 42f, 42f));
|
||||
|
||||
TabRoot = CreateRect(panel, "TabRoot", new RectSpec(0f, 0f, 0f, 1f, 118f, -92f, 180f, 44f));
|
||||
var tabLayout = TabRoot.gameObject.AddComponent<VerticalLayoutGroup>();
|
||||
tabLayout.spacing = 8f;
|
||||
tabLayout.childControlWidth = true;
|
||||
tabLayout.childControlHeight = false;
|
||||
tabLayout.childForceExpandWidth = true;
|
||||
tabLayout.childForceExpandHeight = false;
|
||||
|
||||
PageRoot = CreateRect(panel, "PageRoot", new RectSpec(0f, 1f, 0f, 1f, 230f, -96f, -32f, 44f));
|
||||
|
||||
AddPage(UIGlobalSettingPage.Language, "语言");
|
||||
AddPage(UIGlobalSettingPage.Audio, "音频");
|
||||
AddPage(UIGlobalSettingPage.Display, "显示");
|
||||
AddPage(UIGlobalSettingPage.Game, "游戏");
|
||||
AddPage(UIGlobalSettingPage.Support, "支持");
|
||||
|
||||
BuildLanguagePage(_pages[UIGlobalSettingPage.Language].transform);
|
||||
BuildAudioPage(_pages[UIGlobalSettingPage.Audio].transform);
|
||||
BuildDisplayPage(_pages[UIGlobalSettingPage.Display].transform);
|
||||
BuildGamePage(_pages[UIGlobalSettingPage.Game].transform);
|
||||
BuildSupportPage(_pages[UIGlobalSettingPage.Support].transform);
|
||||
|
||||
SelectPage(UIGlobalSettingPage.Language);
|
||||
}
|
||||
|
||||
private Button CreateFullScreenBlocker()
|
||||
{
|
||||
var go = new GameObject("Blocker", typeof(RectTransform), typeof(CanvasRenderer), typeof(Image), typeof(Button));
|
||||
go.layer = gameObject.layer;
|
||||
go.transform.SetParent(transform, false);
|
||||
var rect = go.GetComponent<RectTransform>();
|
||||
rect.anchorMin = Vector2.zero;
|
||||
rect.anchorMax = Vector2.one;
|
||||
rect.offsetMin = new Vector2(-2000f, -1200f);
|
||||
rect.offsetMax = new Vector2(2000f, 1200f);
|
||||
var image = go.GetComponent<Image>();
|
||||
image.color = new Color(0f, 0f, 0f, 0.48f);
|
||||
var button = go.GetComponent<Button>();
|
||||
button.transition = Selectable.Transition.None;
|
||||
button.targetGraphic = image;
|
||||
return button;
|
||||
}
|
||||
|
||||
private RectTransform CreatePanel(RectTransform parent)
|
||||
{
|
||||
var panel = CreateRect(parent, "Panel", new RectSpec(0.5f, 0.5f, 0.5f, 0.5f, 0f, 0f, 1120f, 640f));
|
||||
var image = panel.gameObject.AddComponent<Image>();
|
||||
image.color = new Color32(29, 34, 44, 245);
|
||||
return panel;
|
||||
}
|
||||
|
||||
private void AddPage(UIGlobalSettingPage page, string label)
|
||||
{
|
||||
var tabButton = CreateTextButton(TabRoot, page + "Tab", label, new RectSpec(0f, 1f, 1f, 1f, 0f, 0f, 0f, 48f));
|
||||
var layout = tabButton.gameObject.AddComponent<LayoutElement>();
|
||||
layout.minHeight = 48f;
|
||||
layout.preferredHeight = 48f;
|
||||
var tab = tabButton.gameObject.AddComponent<UIGlobalSettingTabMono>();
|
||||
tab.Init(page, tabButton, tabButton.GetComponentInChildren<TMP_Text>(true), SelectPage);
|
||||
_tabs[page] = tab;
|
||||
|
||||
var pageRect = CreateRect(PageRoot, page + "Page", new RectSpec(0f, 1f, 0f, 1f, 0f, 0f, 0f, 0f));
|
||||
var pageLayout = pageRect.gameObject.AddComponent<VerticalLayoutGroup>();
|
||||
pageLayout.padding = new RectOffset(0, 0, 0, 0);
|
||||
pageLayout.spacing = 10f;
|
||||
pageLayout.childControlWidth = true;
|
||||
pageLayout.childControlHeight = false;
|
||||
pageLayout.childForceExpandWidth = true;
|
||||
pageLayout.childForceExpandHeight = false;
|
||||
_pages[page] = pageRect.gameObject;
|
||||
}
|
||||
|
||||
private void BuildLanguagePage(Transform parent)
|
||||
{
|
||||
_languageOptionGroup = CreateLanguageOptionGroup(parent);
|
||||
|
||||
_moreLanguageModule = CreateRect(parent, "MoreLanguageModule", new RectSpec()).gameObject;
|
||||
var layout = _moreLanguageModule.AddComponent<HorizontalLayoutGroup>();
|
||||
layout.spacing = 12f;
|
||||
layout.childControlWidth = false;
|
||||
layout.childControlHeight = true;
|
||||
layout.childForceExpandWidth = false;
|
||||
layout.childForceExpandHeight = false;
|
||||
_moreLanguageModule.AddComponent<LayoutElement>().preferredHeight = 44f;
|
||||
|
||||
CreateText(_moreLanguageModule.transform, "NowUsingTitle", "当前语言", 20, TextAlignmentOptions.Left, new RectSpec())
|
||||
.gameObject.AddComponent<LayoutElement>().preferredWidth = 110f;
|
||||
_nowUsingLanguageText = CreateText(_moreLanguageModule.transform, "NowUsingLanguage", "", 20, TextAlignmentOptions.Left, new RectSpec());
|
||||
_nowUsingLanguageText.gameObject.AddComponent<LayoutElement>().preferredWidth = 220f;
|
||||
_manageLanguageButton = CreateTextButton(_moreLanguageModule.transform, "ManageLanguageButton", "管理", new RectSpec());
|
||||
_manageLanguageButton.gameObject.AddComponent<LayoutElement>().preferredWidth = 96f;
|
||||
_manageLanguageButton.onClick.AddListener(() => OnBtnManageLanguageClick?.Invoke());
|
||||
_moreLanguageModule.SetActive(false);
|
||||
}
|
||||
|
||||
private void BuildAudioPage(Transform parent)
|
||||
{
|
||||
AddSliderRow(parent, "音乐音量", () => ConfigManager.Instance.Config.MusicVolume,
|
||||
value => ConfigManager.Instance.Config.MusicVolume = value);
|
||||
AddSliderRow(parent, "音效音量", () => ConfigManager.Instance.Config.AudioVolume,
|
||||
value => ConfigManager.Instance.Config.AudioVolume = value);
|
||||
AddToggleRow(parent, "BGM连续播放", () => ConfigManager.Instance.Config.BgmContinuousPlay,
|
||||
value => ConfigManager.Instance.Config.BgmContinuousPlay = value);
|
||||
}
|
||||
|
||||
private void BuildDisplayPage(Transform parent)
|
||||
{
|
||||
AddToggleRow(parent, "护眼模式", () => ConfigManager.Instance.Config.EyeComfortModeEnabled,
|
||||
value =>
|
||||
{
|
||||
ConfigManager.Instance.Config.EyeComfortModeEnabled = value;
|
||||
VisualSpriteResolver.SetTheme(value ? VisualTheme.EyeComfort : VisualTheme.Default);
|
||||
MapRenderer.Instance?.RefreshVisualTheme();
|
||||
});
|
||||
AddToggleRow(parent, "详细移动提示", () => ConfigManager.Instance.Config.EnhancedMoveHighlightEnabled,
|
||||
value =>
|
||||
{
|
||||
ConfigManager.Instance.Config.EnhancedMoveHighlightEnabled = value;
|
||||
MapRenderer.Instance?.RefreshAllHighlights();
|
||||
});
|
||||
AddDisabledRow(parent, "快速动画", "预留");
|
||||
}
|
||||
|
||||
private void BuildGamePage(Transform parent)
|
||||
{
|
||||
AddToggleRow(parent, "关键时刻", () => ConfigManager.Instance.Config.KeyMomentEnabled,
|
||||
value => ConfigManager.Instance.Config.KeyMomentEnabled = value);
|
||||
AddToggleRow(parent, "下一回合二次确认", () => ConfigManager.Instance.Config.ConfirmBeforeNextTurn,
|
||||
value => ConfigManager.Instance.Config.ConfirmBeforeNextTurn = value);
|
||||
AddToggleRow(parent, "始终显示城市边界", () => ConfigManager.Instance.Config.AlwaysShowCityBorder,
|
||||
value => ConfigManager.Instance.Config.AlwaysShowCityBorder = value);
|
||||
AddDisabledRow(parent, "显示跳过行动", "预留");
|
||||
}
|
||||
|
||||
private void BuildSupportPage(Transform parent)
|
||||
{
|
||||
_bugReportButton = AddButtonRow(parent, "上传Bug报告", () => OnBtnBugReportClick?.Invoke());
|
||||
_repairRendererButton = AddButtonRow(parent, "修复画面错误", () => OnBtnRepairRendererClick?.Invoke());
|
||||
}
|
||||
|
||||
private void AddToggleRow(Transform parent, string label, Func<bool> getter, Action<bool> setter)
|
||||
{
|
||||
var row = CreateSettingRow(parent, "ToggleRow_" + label);
|
||||
var title = CreateText(row, "Label", label, 22, TextAlignmentOptions.Left, new RectSpec(0f, 0.6f, 0f, 1f, 16f, 0f, -8f, 0f));
|
||||
var toggle = CreateToggle(row, "Toggle", new RectSpec(1f, 1f, 0.5f, 0.5f, -86f, 0f, 58f, 34f));
|
||||
var mono = row.gameObject.AddComponent<UIGlobalSettingToggleRowMono>();
|
||||
mono.Init(title, toggle, getter, setter);
|
||||
_toggleRows.Add(mono);
|
||||
}
|
||||
|
||||
private void AddSliderRow(Transform parent, string label, Func<float> getter, Action<float> setter)
|
||||
{
|
||||
var row = CreateSettingRow(parent, "SliderRow_" + label);
|
||||
var title = CreateText(row, "Label", label, 22, TextAlignmentOptions.Left, new RectSpec(0f, 0.36f, 0f, 1f, 16f, 0f, -8f, 0f));
|
||||
var slider = CreateSlider(row, "Slider", new RectSpec(0.42f, 0.88f, 0.5f, 0.5f, 0f, 0f, 0f, 24f));
|
||||
var valueText = CreateText(row, "Value", "", 18, TextAlignmentOptions.Right, new RectSpec(0.89f, 1f, 0f, 1f, -8f, 0f, -16f, 0f));
|
||||
var mono = row.gameObject.AddComponent<UIGlobalSettingSliderRowMono>();
|
||||
mono.Init(title, slider, valueText, getter, setter);
|
||||
_sliderRows.Add(mono);
|
||||
}
|
||||
|
||||
private void AddDisabledRow(Transform parent, string label, string state)
|
||||
{
|
||||
var row = CreateSettingRow(parent, "DisabledRow_" + label);
|
||||
CreateText(row, "Label", label, 22, TextAlignmentOptions.Left, new RectSpec(0f, 0.65f, 0f, 1f, 16f, 0f, -8f, 0f));
|
||||
var stateText = CreateText(row, "State", state, 18, TextAlignmentOptions.Right, new RectSpec(0.66f, 1f, 0f, 1f, 0f, 0f, -16f, 0f));
|
||||
stateText.color = new Color32(170, 177, 188, 255);
|
||||
}
|
||||
|
||||
private Button AddButtonRow(Transform parent, string label, Action onClick)
|
||||
{
|
||||
var row = CreateSettingRow(parent, "ButtonRow_" + label);
|
||||
CreateText(row, "Label", label, 22, TextAlignmentOptions.Left, new RectSpec(0f, 0.6f, 0f, 1f, 16f, 0f, -8f, 0f));
|
||||
var button = CreateTextButton(row, "ActionButton", "执行", new RectSpec(1f, 1f, 0.5f, 0.5f, -108f, 0f, 92f, 38f));
|
||||
button.onClick.AddListener(() => onClick?.Invoke());
|
||||
return button;
|
||||
}
|
||||
|
||||
private UIOutsideSelectOptionGroupMono CreateLanguageOptionGroup(Transform parent)
|
||||
{
|
||||
var row = CreateSettingRow(parent, "LanguageOptionGroupRow");
|
||||
CreateText(row, "Label", "语言", 22, TextAlignmentOptions.Left, new RectSpec(0f, 0.18f, 0f, 1f, 16f, 0f, -8f, 0f));
|
||||
|
||||
var groupRect = CreateRect(row, "LanguageOptionGroup", new RectSpec(0.2f, 1f, 0.5f, 0.5f, 0f, 0f, -16f, 42f));
|
||||
var group = groupRect.gameObject.AddComponent<UIOutsideSelectOptionGroupMono>();
|
||||
var bg = CreateRect(groupRect, "SelectBG", new RectSpec(0f, 0f, 0.5f, 0.5f, 0f, 0f, 88f, 36f));
|
||||
bg.gameObject.AddComponent<Image>().color = new Color32(72, 91, 122, 255);
|
||||
group.SelectBG = bg;
|
||||
|
||||
string[] labels = { "简中", "繁中", "日本語", "English", "한국어", "更多" };
|
||||
for (int i = 0; i < labels.Length; i++)
|
||||
{
|
||||
var button = CreateTextButton(groupRect, "Option" + i, labels[i],
|
||||
new RectSpec(0f, 0f, 0.5f, 0.5f, 48f + i * 102f, 0f, 92f, 36f));
|
||||
group.options.Add(button);
|
||||
}
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
private RectTransform CreateSettingRow(Transform parent, string name)
|
||||
{
|
||||
var row = CreateRect(parent, name, new RectSpec());
|
||||
var image = row.gameObject.AddComponent<Image>();
|
||||
image.color = new Color32(43, 49, 63, 220);
|
||||
var layout = row.gameObject.AddComponent<LayoutElement>();
|
||||
layout.minHeight = 58f;
|
||||
layout.preferredHeight = 58f;
|
||||
return row;
|
||||
}
|
||||
|
||||
private Toggle CreateToggle(Transform parent, string name, RectSpec spec)
|
||||
{
|
||||
var root = CreateRect(parent, name, spec);
|
||||
var bg = root.gameObject.AddComponent<Image>();
|
||||
bg.color = new Color32(70, 76, 90, 255);
|
||||
var toggle = root.gameObject.AddComponent<Toggle>();
|
||||
toggle.targetGraphic = bg;
|
||||
|
||||
var checkmark = CreateRect(root, "Checkmark", new RectSpec(0f, 0f, 0.5f, 0.5f, 24f, 0f, 22f, 22f));
|
||||
checkmark.gameObject.AddComponent<Image>().color = new Color32(126, 187, 118, 255);
|
||||
toggle.graphic = checkmark.GetComponent<Image>();
|
||||
return toggle;
|
||||
}
|
||||
|
||||
private Slider CreateSlider(Transform parent, string name, RectSpec spec)
|
||||
{
|
||||
var root = CreateRect(parent, name, spec);
|
||||
var bg = root.gameObject.AddComponent<Image>();
|
||||
bg.color = new Color32(66, 72, 86, 255);
|
||||
|
||||
var fillArea = CreateRect(root, "Fill Area", new RectSpec(0f, 1f, 0f, 1f, 4f, 0f, -4f, 0f));
|
||||
var fill = CreateRect(fillArea, "Fill", new RectSpec(0f, 1f, 0f, 1f, 0f, 0f, 0f, 0f));
|
||||
fill.gameObject.AddComponent<Image>().color = new Color32(115, 151, 190, 255);
|
||||
|
||||
var handleArea = CreateRect(root, "Handle Slide Area", new RectSpec(0f, 1f, 0f, 1f, 4f, 0f, -4f, 0f));
|
||||
var handle = CreateRect(handleArea, "Handle", new RectSpec(0f, 0f, 0.5f, 0.5f, 0f, 0f, 18f, 32f));
|
||||
handle.gameObject.AddComponent<Image>().color = Color.white;
|
||||
|
||||
var slider = root.gameObject.AddComponent<Slider>();
|
||||
slider.minValue = 0f;
|
||||
slider.maxValue = 1f;
|
||||
slider.fillRect = fill;
|
||||
slider.handleRect = handle;
|
||||
slider.targetGraphic = handle.GetComponent<Image>();
|
||||
slider.direction = Slider.Direction.LeftToRight;
|
||||
return slider;
|
||||
}
|
||||
|
||||
private Button CreateTextButton(Transform parent, string name, string text, RectSpec spec)
|
||||
{
|
||||
var rect = CreateRect(parent, name, spec);
|
||||
var image = rect.gameObject.AddComponent<Image>();
|
||||
image.color = new Color32(68, 76, 98, 255);
|
||||
var button = rect.gameObject.AddComponent<Button>();
|
||||
button.targetGraphic = image;
|
||||
var label = CreateText(rect, "Text", text, 20, TextAlignmentOptions.Center, new RectSpec(0f, 1f, 0f, 1f, 0f, 0f, 0f, 0f));
|
||||
label.raycastTarget = false;
|
||||
return button;
|
||||
}
|
||||
|
||||
private TMP_Text CreateText(Transform parent, string name, string text, int fontSize, TextAlignmentOptions alignment, RectSpec spec)
|
||||
{
|
||||
var rect = CreateRect(parent, name, spec);
|
||||
var tmp = rect.gameObject.AddComponent<TextMeshProUGUI>();
|
||||
tmp.text = text;
|
||||
tmp.fontSize = fontSize;
|
||||
tmp.enableAutoSizing = true;
|
||||
tmp.fontSizeMin = 12;
|
||||
tmp.fontSizeMax = fontSize;
|
||||
tmp.color = Color.white;
|
||||
tmp.alignment = alignment;
|
||||
tmp.raycastTarget = false;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
private RectTransform CreateRect(Transform parent, string name, RectSpec spec)
|
||||
{
|
||||
var go = new GameObject(name, typeof(RectTransform));
|
||||
go.layer = gameObject.layer;
|
||||
go.transform.SetParent(parent, false);
|
||||
var rect = go.GetComponent<RectTransform>();
|
||||
spec.Apply(rect);
|
||||
return rect;
|
||||
}
|
||||
|
||||
private readonly struct RectSpec
|
||||
{
|
||||
private readonly bool _hasValue;
|
||||
private readonly float _anchorMinX;
|
||||
private readonly float _anchorMaxX;
|
||||
private readonly float _anchorMinY;
|
||||
private readonly float _anchorMaxY;
|
||||
private readonly float _x;
|
||||
private readonly float _y;
|
||||
private readonly float _w;
|
||||
private readonly float _h;
|
||||
|
||||
public RectSpec(float anchorMinX, float anchorMaxX, float anchorMinY, float anchorMaxY,
|
||||
float x, float y, float w, float h)
|
||||
{
|
||||
_hasValue = true;
|
||||
_anchorMinX = anchorMinX;
|
||||
_anchorMaxX = anchorMaxX;
|
||||
_anchorMinY = anchorMinY;
|
||||
_anchorMaxY = anchorMaxY;
|
||||
_x = x;
|
||||
_y = y;
|
||||
_w = w;
|
||||
_h = h;
|
||||
}
|
||||
|
||||
public void Apply(RectTransform rect)
|
||||
{
|
||||
if (!_hasValue)
|
||||
{
|
||||
rect.anchorMin = Vector2.zero;
|
||||
rect.anchorMax = Vector2.one;
|
||||
rect.offsetMin = Vector2.zero;
|
||||
rect.offsetMax = Vector2.zero;
|
||||
rect.pivot = new Vector2(0.5f, 0.5f);
|
||||
return;
|
||||
}
|
||||
|
||||
rect.anchorMin = new Vector2(_anchorMinX, _anchorMinY);
|
||||
rect.anchorMax = new Vector2(_anchorMaxX, _anchorMaxY);
|
||||
rect.pivot = new Vector2(0.5f, 0.5f);
|
||||
|
||||
var anchoredPosition = rect.anchoredPosition;
|
||||
var sizeDelta = rect.sizeDelta;
|
||||
var offsetMin = rect.offsetMin;
|
||||
var offsetMax = rect.offsetMax;
|
||||
|
||||
if (Mathf.Approximately(_anchorMinX, _anchorMaxX))
|
||||
{
|
||||
anchoredPosition.x = _x;
|
||||
sizeDelta.x = _w;
|
||||
}
|
||||
else
|
||||
{
|
||||
offsetMin.x = _x;
|
||||
offsetMax.x = _w;
|
||||
}
|
||||
|
||||
if (Mathf.Approximately(_anchorMinY, _anchorMaxY))
|
||||
{
|
||||
anchoredPosition.y = _y;
|
||||
sizeDelta.y = _h;
|
||||
}
|
||||
else
|
||||
{
|
||||
offsetMin.y = _h;
|
||||
offsetMax.y = _y;
|
||||
}
|
||||
|
||||
rect.anchoredPosition = anchoredPosition;
|
||||
rect.sizeDelta = sizeDelta;
|
||||
rect.offsetMin = offsetMin;
|
||||
rect.offsetMax = offsetMax;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e51b9280cf324acb9a977eb172eb62bc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Loading…
x
Reference in New Issue
Block a user