优化+清理
This commit is contained in:
@@ -12,11 +12,14 @@ namespace GeometryTD.CustomComponent
|
||||
public class ResolutionAdapterComponent : GameFrameworkComponent
|
||||
{
|
||||
private const float DefaultCanvasPlaneDistance = 100f;
|
||||
private static ResolutionAdapterComponent s_Instance;
|
||||
|
||||
[SerializeField] private Vector2 _referenceResolution = new Vector2(2560f, 1600f);
|
||||
[SerializeField] private bool _adaptUiCanvasToViewport = true;
|
||||
[SerializeField] private bool _enableBlackMask = true;
|
||||
[SerializeField] private int _maskSortingOrder = short.MaxValue;
|
||||
[SerializeField] private bool _autoCollectSceneCanvases = true;
|
||||
[SerializeField] private float _canvasProbeInterval = 0.2f;
|
||||
[SerializeField] private List<Transform> _uiRoots = new List<Transform>();
|
||||
|
||||
private readonly List<Canvas> _canvasBuffer = new List<Canvas>(32);
|
||||
@@ -32,6 +35,7 @@ namespace GeometryTD.CustomComponent
|
||||
private bool _uiEventSubscribed;
|
||||
private bool _sceneEventSubscribed;
|
||||
private bool _missingRootWarned;
|
||||
private float _nextCanvasProbeTime;
|
||||
|
||||
private Canvas _maskCanvas;
|
||||
private RectTransform _leftMask;
|
||||
@@ -39,6 +43,23 @@ namespace GeometryTD.CustomComponent
|
||||
private RectTransform _topMask;
|
||||
private RectTransform _bottomMask;
|
||||
|
||||
public static bool TryGetTargetViewport(out Rect viewport)
|
||||
{
|
||||
if (s_Instance != null && s_Instance._cachedScreenWidth > 0 && s_Instance._cachedScreenHeight > 0)
|
||||
{
|
||||
viewport = s_Instance._targetViewport;
|
||||
return true;
|
||||
}
|
||||
|
||||
viewport = new Rect(0f, 0f, 1f, 1f);
|
||||
return false;
|
||||
}
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
s_Instance = this;
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
TryEnsureUiEventSubscribed();
|
||||
@@ -48,6 +69,10 @@ namespace GeometryTD.CustomComponent
|
||||
private void Update()
|
||||
{
|
||||
TryEnsureUiEventSubscribed();
|
||||
}
|
||||
|
||||
private void LateUpdate()
|
||||
{
|
||||
ApplyAdaptation(false);
|
||||
}
|
||||
|
||||
@@ -59,6 +84,11 @@ namespace GeometryTD.CustomComponent
|
||||
{
|
||||
_mainCamera.rect = new Rect(0f, 0f, 1f, 1f);
|
||||
}
|
||||
|
||||
if (s_Instance == this)
|
||||
{
|
||||
s_Instance = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyAdaptation(bool force)
|
||||
@@ -95,11 +125,7 @@ namespace GeometryTD.CustomComponent
|
||||
return;
|
||||
}
|
||||
|
||||
if (!needRecalculate && !_canvasCacheDirty)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
TryMarkCanvasCacheDirtyByProbe();
|
||||
ApplyCanvasAdaptation();
|
||||
}
|
||||
|
||||
@@ -308,6 +334,7 @@ namespace GeometryTD.CustomComponent
|
||||
if (!_uiEventSubscribed)
|
||||
{
|
||||
GameEntry.Event.Subscribe(OpenUIFormSuccessEventArgs.EventId, OnUIFormChanged);
|
||||
GameEntry.Event.Subscribe(OpenUIFormUpdateEventArgs.EventId, OnUIFormChanged);
|
||||
GameEntry.Event.Subscribe(CloseUIFormCompleteEventArgs.EventId, OnUIFormChanged);
|
||||
_uiEventSubscribed = true;
|
||||
_canvasCacheDirty = true;
|
||||
@@ -331,6 +358,7 @@ namespace GeometryTD.CustomComponent
|
||||
if (_uiEventSubscribed)
|
||||
{
|
||||
GameEntry.Event.Unsubscribe(OpenUIFormSuccessEventArgs.EventId, OnUIFormChanged);
|
||||
GameEntry.Event.Unsubscribe(OpenUIFormUpdateEventArgs.EventId, OnUIFormChanged);
|
||||
GameEntry.Event.Unsubscribe(CloseUIFormCompleteEventArgs.EventId, OnUIFormChanged);
|
||||
_uiEventSubscribed = false;
|
||||
}
|
||||
@@ -353,6 +381,47 @@ namespace GeometryTD.CustomComponent
|
||||
_missingRootWarned = false;
|
||||
}
|
||||
|
||||
private void TryMarkCanvasCacheDirtyByProbe()
|
||||
{
|
||||
if (_canvasCacheDirty)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_canvasProbeInterval > 0f && Time.unscaledTime < _nextCanvasProbeTime)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_nextCanvasProbeTime = Time.unscaledTime + Mathf.Max(0.01f, _canvasProbeInterval);
|
||||
Canvas[] canvases = Resources.FindObjectsOfTypeAll<Canvas>();
|
||||
foreach (Canvas canvas in canvases)
|
||||
{
|
||||
if (canvas == null || canvas == _maskCanvas || canvas.renderMode == RenderMode.WorldSpace)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
GameObject gameObject = canvas.gameObject;
|
||||
if (!gameObject.scene.IsValid() || !gameObject.scene.isLoaded)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!_trackedCanvasSet.Contains(canvas))
|
||||
{
|
||||
_canvasCacheDirty = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void CalculateViewportPadding(out float horizontalPadding, out float verticalPadding)
|
||||
{
|
||||
horizontalPadding = Mathf.Max(0f, (1f - _targetViewport.width) * 0.5f * _cachedScreenWidth);
|
||||
verticalPadding = Mathf.Max(0f, (1f - _targetViewport.height) * 0.5f * _cachedScreenHeight);
|
||||
}
|
||||
|
||||
private void UpdateMaskLayout()
|
||||
{
|
||||
if (!_enableBlackMask)
|
||||
@@ -367,8 +436,13 @@ namespace GeometryTD.CustomComponent
|
||||
return;
|
||||
}
|
||||
|
||||
float horizontalPadding = Mathf.Max(0f, (1f - _targetViewport.width) * 0.5f * _cachedScreenWidth);
|
||||
float verticalPadding = Mathf.Max(0f, (1f - _targetViewport.height) * 0.5f * _cachedScreenHeight);
|
||||
int maskSortingOrder = Mathf.Clamp(_maskSortingOrder, short.MinValue, short.MaxValue);
|
||||
if (_maskCanvas.sortingOrder != maskSortingOrder)
|
||||
{
|
||||
_maskCanvas.sortingOrder = maskSortingOrder;
|
||||
}
|
||||
|
||||
CalculateViewportPadding(out float horizontalPadding, out float verticalPadding);
|
||||
|
||||
bool showVerticalMask = horizontalPadding > 0.5f;
|
||||
bool showHorizontalMask = verticalPadding > 0.5f;
|
||||
@@ -405,7 +479,7 @@ namespace GeometryTD.CustomComponent
|
||||
_maskCanvas = maskRoot.GetComponent<Canvas>();
|
||||
_maskCanvas.renderMode = RenderMode.ScreenSpaceOverlay;
|
||||
_maskCanvas.overrideSorting = true;
|
||||
_maskCanvas.sortingOrder = short.MaxValue;
|
||||
_maskCanvas.sortingOrder = Mathf.Clamp(_maskSortingOrder, short.MinValue, short.MaxValue);
|
||||
|
||||
CanvasScaler scaler = maskRoot.GetComponent<CanvasScaler>();
|
||||
scaler.uiScaleMode = CanvasScaler.ScaleMode.ConstantPixelSize;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using DataTable;
|
||||
using Definition.Enum;
|
||||
using Event;
|
||||
using GameFramework.DataTable;
|
||||
using GameFramework.Event;
|
||||
@@ -16,6 +17,8 @@ namespace Procedure
|
||||
private const int DialogChapterDivisor = 1000;
|
||||
|
||||
private IDataTable<DRDialog> _dtDialog;
|
||||
private bool _pendingSceneChange;
|
||||
private int _pendingSceneId;
|
||||
|
||||
public override bool UseNativeDialog => false;
|
||||
|
||||
@@ -25,6 +28,8 @@ namespace Procedure
|
||||
AIChatEntryRuntime.EnsureOpen();
|
||||
|
||||
GameEntry.Event.Subscribe(StoryChapterEndedEventArgs.EventId, OnStoryChapterEnded);
|
||||
_pendingSceneChange = false;
|
||||
_pendingSceneId = 0;
|
||||
|
||||
GameEntry.Dialog.Init(InitialChapterId);
|
||||
GameEntry.Dialog.StartDialog(InitialDialogId);
|
||||
@@ -36,6 +41,21 @@ namespace Procedure
|
||||
base.OnLeave(procedureOwner, isShutdown);
|
||||
}
|
||||
|
||||
protected override void OnUpdate(IFsm<IProcedureManager> procedureOwner, float elapseSeconds,
|
||||
float realElapseSeconds)
|
||||
{
|
||||
base.OnUpdate(procedureOwner, elapseSeconds, realElapseSeconds);
|
||||
|
||||
if (!_pendingSceneChange)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_pendingSceneChange = false;
|
||||
procedureOwner.SetData<VarInt32>("NextSceneId", _pendingSceneId);
|
||||
ChangeState<ProcedureChangeScene>(procedureOwner);
|
||||
}
|
||||
|
||||
private void OnStoryChapterEnded(object sender, GameEventArgs e)
|
||||
{
|
||||
if (!(e is StoryChapterEndedEventArgs args))
|
||||
@@ -54,8 +74,12 @@ namespace Procedure
|
||||
|
||||
if (!TryResolveFirstDialogId(nextChapterId, out int nextDialogId))
|
||||
{
|
||||
Log.Info("ProcedureMain chapter switch stopped. No dialog found for chapter '{0}'.",
|
||||
nextChapterId.ToString());
|
||||
Log.Info(
|
||||
"ProcedureMain chapter '{0}' ended and no next chapter found. Return to menu scene.",
|
||||
currentChapterId.ToString());
|
||||
CloseBgFormIfOpened();
|
||||
_pendingSceneId = (int)SceneId.Menu;
|
||||
_pendingSceneChange = true;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -123,5 +147,19 @@ namespace Procedure
|
||||
{
|
||||
return dialogId / DialogChapterDivisor;
|
||||
}
|
||||
|
||||
private static void CloseBgFormIfOpened()
|
||||
{
|
||||
if (GameEntry.UI == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
UGuiForm bgForm = GameEntry.UI.GetUIForm(UIFormId.BgForm);
|
||||
if (bgForm != null)
|
||||
{
|
||||
GameEntry.UI.CloseUIForm(bgForm.UIForm);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,8 +69,7 @@ namespace Procedure
|
||||
e.Subscribe(MenuSettingEventArgs.EventId, MenuSetting);
|
||||
e.Subscribe(MenuExitEventArgs.EventId, MenuExit);
|
||||
e.Subscribe(SettingSaveEventArgs.EventId, SettingSave);
|
||||
|
||||
|
||||
|
||||
_menuFormController = new MenuFormController();
|
||||
_menuFormController.OpenUI(new MenuFormContext());
|
||||
|
||||
|
||||
@@ -8,18 +8,24 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityGameFramework.Runtime;
|
||||
using GeometryTD.CustomComponent;
|
||||
|
||||
namespace UI
|
||||
{
|
||||
/// <summary>
|
||||
/// uGUI 界面组辅助器。
|
||||
/// </summary>
|
||||
[DefaultExecutionOrder(200)]
|
||||
public class UGuiGroupHelper : UIGroupHelperBase
|
||||
{
|
||||
public const int DepthFactor = 10000;
|
||||
|
||||
private int m_Depth = 0;
|
||||
private Canvas m_CachedCanvas = null;
|
||||
private RectTransform m_RectTransform = null;
|
||||
private int m_LastScreenWidth = -1;
|
||||
private int m_LastScreenHeight = -1;
|
||||
private Rect m_LastViewport = new Rect(float.MinValue, float.MinValue, float.MinValue, float.MinValue);
|
||||
|
||||
/// <summary>
|
||||
/// 设置界面组深度。
|
||||
@@ -36,6 +42,7 @@ namespace UI
|
||||
{
|
||||
m_CachedCanvas = gameObject.GetOrAddComponent<Canvas>();
|
||||
gameObject.GetOrAddComponent<GraphicRaycaster>();
|
||||
m_RectTransform = GetComponent<RectTransform>();
|
||||
}
|
||||
|
||||
private void Start()
|
||||
@@ -43,11 +50,94 @@ namespace UI
|
||||
m_CachedCanvas.overrideSorting = true;
|
||||
m_CachedCanvas.sortingOrder = DepthFactor * m_Depth;
|
||||
|
||||
RectTransform transform = GetComponent<RectTransform>();
|
||||
transform.anchorMin = Vector2.zero;
|
||||
transform.anchorMax = Vector2.one;
|
||||
transform.anchoredPosition = Vector2.zero;
|
||||
transform.sizeDelta = Vector2.zero;
|
||||
if (m_RectTransform == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_RectTransform.anchorMin = Vector2.zero;
|
||||
m_RectTransform.anchorMax = Vector2.one;
|
||||
m_RectTransform.pivot = new Vector2(0.5f, 0.5f);
|
||||
m_RectTransform.anchoredPosition = Vector2.zero;
|
||||
m_RectTransform.sizeDelta = Vector2.zero;
|
||||
ApplyViewportClip(true);
|
||||
}
|
||||
|
||||
private void LateUpdate()
|
||||
{
|
||||
ApplyViewportClip(false);
|
||||
}
|
||||
|
||||
private void ApplyViewportClip(bool force)
|
||||
{
|
||||
if (m_RectTransform == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int screenWidth = Screen.width;
|
||||
int screenHeight = Screen.height;
|
||||
Rect viewport = ResolveViewportRect();
|
||||
if (!force
|
||||
&& screenWidth == m_LastScreenWidth
|
||||
&& screenHeight == m_LastScreenHeight
|
||||
&& Mathf.Approximately(viewport.x, m_LastViewport.x)
|
||||
&& Mathf.Approximately(viewport.y, m_LastViewport.y)
|
||||
&& Mathf.Approximately(viewport.width, m_LastViewport.width)
|
||||
&& Mathf.Approximately(viewport.height, m_LastViewport.height))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_LastScreenWidth = screenWidth;
|
||||
m_LastScreenHeight = screenHeight;
|
||||
m_LastViewport = viewport;
|
||||
|
||||
if (screenWidth <= 0 || screenHeight <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
float horizontalPadding = Mathf.Max(0f, (1f - viewport.width) * 0.5f * screenWidth);
|
||||
float verticalPadding = Mathf.Max(0f, (1f - viewport.height) * 0.5f * screenHeight);
|
||||
float canvasScale = ResolveCanvasScaleFactor();
|
||||
float horizontalPaddingInCanvasUnit = horizontalPadding / canvasScale;
|
||||
float verticalPaddingInCanvasUnit = verticalPadding / canvasScale;
|
||||
m_RectTransform.offsetMin = new Vector2(horizontalPaddingInCanvasUnit, verticalPaddingInCanvasUnit);
|
||||
m_RectTransform.offsetMax = new Vector2(-horizontalPaddingInCanvasUnit, -verticalPaddingInCanvasUnit);
|
||||
}
|
||||
|
||||
private Rect ResolveViewportRect()
|
||||
{
|
||||
if (ResolutionAdapterComponent.TryGetTargetViewport(out Rect adapterViewport))
|
||||
{
|
||||
return adapterViewport;
|
||||
}
|
||||
|
||||
Camera camera = m_CachedCanvas != null ? m_CachedCanvas.worldCamera : null;
|
||||
if (camera == null && m_CachedCanvas != null && m_CachedCanvas.rootCanvas != null)
|
||||
{
|
||||
camera = m_CachedCanvas.rootCanvas.worldCamera;
|
||||
}
|
||||
|
||||
if (camera == null && GameEntry.Scene != null)
|
||||
{
|
||||
camera = GameEntry.Scene.MainCamera;
|
||||
}
|
||||
|
||||
if (camera == null)
|
||||
{
|
||||
camera = Camera.main;
|
||||
}
|
||||
|
||||
return camera != null ? camera.rect : new Rect(0f, 0f, 1f, 1f);
|
||||
}
|
||||
|
||||
private float ResolveCanvasScaleFactor()
|
||||
{
|
||||
Canvas rootCanvas = m_CachedCanvas != null ? m_CachedCanvas.rootCanvas : null;
|
||||
float scale = rootCanvas != null ? rootCanvas.scaleFactor : (m_CachedCanvas != null ? m_CachedCanvas.scaleFactor : 1f);
|
||||
return scale > 0.0001f ? scale : 1f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,9 +49,7 @@ namespace UI
|
||||
{
|
||||
"Other",
|
||||
"Subtitle",
|
||||
"Time",
|
||||
"LiangSiCheng",
|
||||
"LinHuiYin"
|
||||
"Time"
|
||||
};
|
||||
|
||||
public override void StartDialog(DialogFormContext context)
|
||||
@@ -130,6 +128,13 @@ namespace UI
|
||||
return;
|
||||
}
|
||||
|
||||
if (!HasSpeakerPortrait(_context.SpeakerId))
|
||||
{
|
||||
ClearSpeakerState();
|
||||
ApplySpeakerLayout(false, false, true);
|
||||
return;
|
||||
}
|
||||
|
||||
bool isRightSpeaker = context.Direction > 0;
|
||||
if (isRightSpeaker)
|
||||
{
|
||||
@@ -381,13 +386,21 @@ namespace UI
|
||||
int requestVersion = isRightSpeaker ? ++_rightPortraitRequestVersion : ++_leftPortraitRequestVersion;
|
||||
if (string.IsNullOrWhiteSpace(speakerId) || NonPortraitSpeakerIds.Contains(speakerId))
|
||||
{
|
||||
portraitImage.sprite = null;
|
||||
return;
|
||||
}
|
||||
|
||||
int portraitCount = ResolveAvailablePortraitCount(speakerId);
|
||||
if (portraitCount <= 0)
|
||||
{
|
||||
portraitImage.sprite = null;
|
||||
return;
|
||||
}
|
||||
|
||||
string portraitAssetName = $"Characters/{speakerId}-{ResolvePortraitIndex(speakerId, lineId, portraitCount)}.png";
|
||||
if (GameEntry.SpriteCache == null)
|
||||
{
|
||||
portraitImage.sprite = null;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -400,10 +413,7 @@ namespace UI
|
||||
return;
|
||||
}
|
||||
|
||||
if (sprite != null)
|
||||
{
|
||||
_rightImage.sprite = sprite;
|
||||
}
|
||||
_rightImage.sprite = sprite;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -412,10 +422,7 @@ namespace UI
|
||||
return;
|
||||
}
|
||||
|
||||
if (sprite != null)
|
||||
{
|
||||
_leftImage.sprite = sprite;
|
||||
}
|
||||
_leftImage.sprite = sprite;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -449,6 +456,11 @@ namespace UI
|
||||
return GameEntry.Dialog.GetSpeakerPortraitCount(speakerId);
|
||||
}
|
||||
|
||||
private static bool HasSpeakerPortrait(string speakerId)
|
||||
{
|
||||
return ResolveAvailablePortraitCount(speakerId) > 0;
|
||||
}
|
||||
|
||||
private static bool IsHumanSpeaker(string speakerId)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(speakerId))
|
||||
|
||||
@@ -46,4 +46,4 @@ namespace UI
|
||||
GameEntry.Event.Fire(this, MenuExitEventArgs.Create());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,8 @@ namespace UI
|
||||
{
|
||||
public class SettingForm : UGuiForm
|
||||
{
|
||||
private static readonly string[] NavigateButtonNames = { "SoundButton", "GameButton", "ScreenButton" };
|
||||
|
||||
[SerializeField] private Transform _navigate;
|
||||
|
||||
[SerializeField] private Image[] _navigateButtonImages;
|
||||
@@ -95,20 +97,58 @@ namespace UI
|
||||
|
||||
public void OnNavigateButtonClick(int index)
|
||||
{
|
||||
RefreshNavigateButtonImages();
|
||||
|
||||
if (_navigateButtonImages == null || _navigateButtonImages.Length == 0)
|
||||
{
|
||||
Log.Error("Navigate button images are invalid.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (index < 0 || index >= _navigateButtonImages.Length)
|
||||
{
|
||||
Log.Error("NavigateButtonClick index is out of range.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (_navigateButtonImages[0] == null)
|
||||
_navigateButtonImages[0] = _navigate.Find("SoundButton")?.GetComponent<Image>();
|
||||
|
||||
for (int i = 0; i < _navigateButtonImages.Length; i++)
|
||||
{
|
||||
if (_navigateButtonImages[i] == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
_navigateButtonImages[i].enabled = i == index;
|
||||
}
|
||||
}
|
||||
|
||||
private void RefreshNavigateButtonImages()
|
||||
{
|
||||
if (_navigate == null)
|
||||
{
|
||||
Log.Error("Navigate transform is invalid.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (_navigateButtonImages == null || _navigateButtonImages.Length != NavigateButtonNames.Length)
|
||||
{
|
||||
_navigateButtonImages = new Image[NavigateButtonNames.Length];
|
||||
}
|
||||
|
||||
for (int i = 0; i < NavigateButtonNames.Length; i++)
|
||||
{
|
||||
var button = _navigate.Find(NavigateButtonNames[i]);
|
||||
if (button == null)
|
||||
{
|
||||
Log.Error($"Can not find navigate button '{NavigateButtonNames[i]}'.");
|
||||
_navigateButtonImages[i] = null;
|
||||
continue;
|
||||
}
|
||||
|
||||
_navigateButtonImages[i] = button.GetComponent<Image>();
|
||||
}
|
||||
}
|
||||
|
||||
public void OnReturnButtonClick()
|
||||
{
|
||||
var dialogParams = new DialogParams
|
||||
|
||||
Reference in New Issue
Block a user