- 规范 UI 设计成为:

- UIForm 负责展示
    - Controller 负责控制
    - UseCase 负责业务逻辑
    - RawData 负责提供原始数据
    - Context 负责为 UIForm 提供数据
- 添加和补充一系列 UI 功能
This commit is contained in:
SepComet
2026-02-16 19:03:09 +08:00
parent d650dd63e7
commit 85b0205c73
251 changed files with 12705 additions and 5220 deletions
@@ -0,0 +1,40 @@
using CustomEvent;
using UnityEngine;
using UnityEngine.UI;
namespace UI
{
public class RoleItem : MonoBehaviour
{
[SerializeField] private Image _roleImage = null;
private RoleItemContext _context = null;
public void OnInit(RoleItemContext context)
{
_context = context;
if (_context == null || string.IsNullOrEmpty(_context.IconName))
{
return;
}
GameEntry.SpriteCache.GetSprite(_context.IconName, sprite => _roleImage.sprite = sprite);
}
public void OnReset()
{
_context = null;
}
public void UpdateShowRole()
{
int roleId = _context?.RoleId ?? -1;
GameEntry.Event.Fire(this, MenuSelectRoleSelectedEventArgs.Create(roleId));
}
public void OnConfirmRoleClick()
{
GameEntry.Event.Fire(this, MenuSelectRoleConfirmEventArgs.Create());
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 35de2974f065de547952f8d5cbb9f6fe
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,37 @@
using TMPro;
using UnityEngine;
using UnityEngine.UI;
namespace UI
{
public class RolePropertyArea : MonoBehaviour
{
[SerializeField] private TMP_Text _roleNameText;
[SerializeField] private RawImage _roleAvatar;
[SerializeField] private TMP_Text _roleInitialPropertyText;
[SerializeField] private Transform _roleInitialItemParent;
private RolePropertyAreaContext _context;
public void OnInit(RolePropertyAreaContext context)
{
_context = context;
if (_context == null)
{
OnReset();
return;
}
_roleNameText.text = _context.RoleName;
_roleInitialPropertyText.text = _context.InitialPropertyText;
}
public void OnReset(object userData = null)
{
_context = null;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e82dc413a4cd277429ec1e3f2de69434
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,100 @@
using System;
using CustomEvent;
using UnityEngine;
using UnityGameFramework.Runtime;
namespace UI
{
public class SelectRoleForm : UGuiForm
{
[SerializeField] private GameObject _randomRoleCard = null;
[SerializeField] private GameObject _roleCard = null;
[SerializeField] private RolePropertyArea _propertyArea = null;
private SelectRoleFormContext _context = null;
private RoleItem[] _roleItems = null;
public void RefreshUI(SelectRoleFormContext context)
{
_context = context;
int itemIndex = 1, roleIndex = 0;
while (itemIndex < _roleItems.Length)
{
if (roleIndex < _context.RoleItemContexts.Length)
{
_roleItems[itemIndex].OnInit(_context.RoleItemContexts[roleIndex]);
_roleItems[itemIndex].gameObject.SetActive(true);
}
else
{
_roleItems[itemIndex].gameObject.SetActive(false);
_roleItems[itemIndex].OnReset();
}
itemIndex++;
roleIndex++;
}
UpdateShowRole(_context.RolePropertyAreaContext);
}
#region FSM
protected override void OnInit(object userData)
{
base.OnInit(userData);
_roleItems = this.transform.GetComponentsInChildren<RoleItem>();
}
protected override void OnOpen(object userData)
{
base.OnOpen(userData);
if (userData is SelectRoleFormContext context)
{
RefreshUI(context);
return;
}
Log.Warning("SelectRoleForm requires SelectRoleFormContext as userData.");
}
protected override void OnClose(bool isShutdown, object userData)
{
base.OnClose(isShutdown, userData);
_context = null;
foreach (var item in _roleItems)
{
item.OnReset();
}
}
#endregion
public void UpdateShowRole(RolePropertyAreaContext propertyAreaContext)
{
if (propertyAreaContext == null)
{
_randomRoleCard.SetActive(true);
_roleCard.SetActive(false);
_propertyArea.OnReset();
}
else
{
_randomRoleCard.SetActive(false);
_propertyArea.OnInit(propertyAreaContext);
_roleCard.SetActive(true);
}
}
public void OnReturnButtonClick()
{
GameEntry.Event.Fire(this, MenuSelectRoleReturnEventArgs.Create());
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 665710bc9ed5c5547a40f0cc2d92ba2e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,189 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
using Definition;
using GameFramework.Localization;
using StarForce;
using UnityEngine;
using UnityEngine.UI;
using UnityGameFramework.Runtime;
namespace UI
{
public class SettingForm : UGuiForm
{
[SerializeField] private Toggle _musicMuteToggle = null;
[SerializeField] private Slider _musicVolumeSlider = null;
[SerializeField] private Toggle _soundMuteToggle = null;
[SerializeField] private Slider _soundVolumeSlider = null;
[SerializeField] private Toggle _uiSoundMuteToggle = null;
[SerializeField] private Slider _uiSoundVolumeSlider = null;
[SerializeField] private CanvasGroup _languageTipsCanvasGroup = null;
[SerializeField] private Toggle _englishToggle = null;
[SerializeField] private Toggle _chineseSimplifiedToggle = null;
[SerializeField] private Toggle _chineseTraditionalToggle = null;
[SerializeField] private Toggle _koreanToggle = null;
private Language _selectedLanguage = Language.Unspecified;
public void OnMusicMuteChanged(bool isOn)
{
GameEntry.Sound.Mute("Music", !isOn);
_musicVolumeSlider.gameObject.SetActive(isOn);
}
public void OnMusicVolumeChanged(float volume)
{
GameEntry.Sound.SetVolume("Music", volume);
}
public void OnSoundMuteChanged(bool isOn)
{
GameEntry.Sound.Mute("Sound", !isOn);
_soundVolumeSlider.gameObject.SetActive(isOn);
}
public void OnSoundVolumeChanged(float volume)
{
GameEntry.Sound.SetVolume("Sound", volume);
}
public void OnUISoundMuteChanged(bool isOn)
{
GameEntry.Sound.Mute("UISound", !isOn);
_uiSoundVolumeSlider.gameObject.SetActive(isOn);
}
public void OnUISoundVolumeChanged(float volume)
{
GameEntry.Sound.SetVolume("UISound", volume);
}
public void OnEnglishSelected(bool isOn)
{
if (!isOn)
{
return;
}
_selectedLanguage = Language.English;
RefreshLanguageTips();
}
public void OnChineseSimplifiedSelected(bool isOn)
{
if (!isOn)
{
return;
}
_selectedLanguage = Language.ChineseSimplified;
RefreshLanguageTips();
}
public void OnChineseTraditionalSelected(bool isOn)
{
if (!isOn)
{
return;
}
_selectedLanguage = Language.ChineseTraditional;
RefreshLanguageTips();
}
public void OnKoreanSelected(bool isOn)
{
if (!isOn)
{
return;
}
_selectedLanguage = Language.Korean;
RefreshLanguageTips();
}
public void OnSubmitButtonClick()
{
if (_selectedLanguage == GameEntry.Localization.Language)
{
Close();
return;
}
GameEntry.Setting.SetString(Constant.Setting.Language, _selectedLanguage.ToString());
GameEntry.Setting.Save();
GameEntry.Sound.StopMusic();
UnityGameFramework.Runtime.GameEntry.Shutdown(ShutdownType.Restart);
}
#if UNITY_2017_3_OR_NEWER
protected override void OnOpen(object userData)
#else
protected internal override void OnOpen(object userData)
#endif
{
base.OnOpen(userData);
_musicMuteToggle.isOn = !GameEntry.Sound.IsMuted("Music");
_musicVolumeSlider.value = GameEntry.Sound.GetVolume("Music");
_soundMuteToggle.isOn = !GameEntry.Sound.IsMuted("Sound");
_soundVolumeSlider.value = GameEntry.Sound.GetVolume("Sound");
_uiSoundMuteToggle.isOn = !GameEntry.Sound.IsMuted("UISound");
_uiSoundVolumeSlider.value = GameEntry.Sound.GetVolume("UISound");
_selectedLanguage = GameEntry.Localization.Language;
switch (_selectedLanguage)
{
case Language.English:
_englishToggle.isOn = true;
break;
case Language.ChineseSimplified:
_chineseSimplifiedToggle.isOn = true;
break;
case Language.ChineseTraditional:
_chineseTraditionalToggle.isOn = true;
break;
case Language.Korean:
_koreanToggle.isOn = true;
break;
default:
break;
}
}
#if UNITY_2017_3_OR_NEWER
protected override void OnUpdate(float elapseSeconds, float realElapseSeconds)
#else
protected internal override void OnUpdate(float elapseSeconds, float realElapseSeconds)
#endif
{
base.OnUpdate(elapseSeconds, realElapseSeconds);
if (_languageTipsCanvasGroup.gameObject.activeSelf)
{
_languageTipsCanvasGroup.alpha = 0.5f + 0.5f * Mathf.Sin(Mathf.PI * Time.time);
}
}
private void RefreshLanguageTips()
{
_languageTipsCanvasGroup.gameObject.SetActive(_selectedLanguage != GameEntry.Localization.Language);
}
}
}
@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 02bbd1c1f00c17842b1449ae2b66a932
timeCreated: 1528026161
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,64 @@
using CustomEvent;
using UnityGameFramework.Runtime;
namespace UI
{
public class StartMenuForm : UGuiForm
{
public void RefreshUI(StartMenuFormContext context)
{
}
#region Lifecycle
protected override void OnOpen(object userData)
{
base.OnOpen(userData);
if (userData is StartMenuFormContext context)
{
RefreshUI(context);
return;
}
Log.Warning("StartMenuForm requires StartMenuFormContext as userData.");
}
protected override void OnClose(bool isShutdown, object userData)
{
base.OnClose(isShutdown, userData);
}
#endregion
public void OnStartButtonClick()
{
GameEntry.Event.Fire(this, MenuStartGameEventArgs.Create());
}
public void OnFileButtonClick()
{
GameEntry.Event.Fire(this, MenuFileButtonClickEventArgs.Create());
}
public void OnGuideButtonClick()
{
GameEntry.Event.Fire(this, MenuGuideButtonClickEventArgs.Create());
}
public void OnSettingButtonClick()
{
GameEntry.Event.Fire(this, MenuSettingButtonClickEventArgs.Create());
}
public void OnQuitButtonClick()
{
GameEntry.Event.Fire(this, MenuQuitButtonClickEventArgs.Create());
}
public void OnAboutButtonClick()
{
GameEntry.Event.Fire(this, MenuAboutButtonClickEventArgs.Create());
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d448bbb919fe8454da81331191044ead
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: