diff --git a/.gitignore b/.gitignore index 46c0c15..7dcfacd 100644 --- a/.gitignore +++ b/.gitignore @@ -104,3 +104,4 @@ AGENTS.md /.dotnet-home /[Aa]ssets/RawResources /[Aa]ssets/RawResources.meta +/docs/TODO.md diff --git a/Assets/GameMain/DataTables/UIForm.txt b/Assets/GameMain/DataTables/UIForm.txt index ec55e18..969d161 100644 --- a/Assets/GameMain/DataTables/UIForm.txt +++ b/Assets/GameMain/DataTables/UIForm.txt @@ -6,6 +6,7 @@ 100 主菜单 MenuForm Default False True 101 设置 SettingForm Default False True 102 关于 AboutForm Default False True - 150 测试UI TestMenuForm Default False True - 200 事件UI EventForm Default False True + 103 主UI MainForm Default False True + 150 测试UI TestMenuForm Default False False + 200 事件UI EventForm Default False False 201 背包UI RepoForm Default False True diff --git a/Assets/GameMain/Scripts/Base/GameEntry.Custom.cs b/Assets/GameMain/Scripts/Base/GameEntry.Custom.cs index 1233e3c..c1bfed6 100644 --- a/Assets/GameMain/Scripts/Base/GameEntry.Custom.cs +++ b/Assets/GameMain/Scripts/Base/GameEntry.Custom.cs @@ -1,31 +1,25 @@ -//------------------------------------------------------------ -// Game Framework -// Copyright © 2013-2021 Jiang Yin. All rights reserved. -// Homepage: https://gameframework.cn/ -// Feedback: mailto:ellan@gameframework.cn -//------------------------------------------------------------ - -using CustomComponent; +using CustomComponent; using GeometryTD.CustomComponent; -using UnityEngine; /// /// 游戏入口。 /// -public partial class GameEntry : MonoBehaviour +public partial class GameEntry { public static BuiltinDataComponent BuiltinData { get; private set; } public static HPBarComponent HPBar { get; private set; } public static UIRouterComponent UIRouter { get; private set; } - + public static EventNodeComponent EventNode { get; private set; } public static CombatNodeComponent CombatNode { get; private set; } - + public static ShopNodeComponent ShopNode { get; private set; } + public static ResolutionAdapterComponent ResolutionAdapter { get; private set; } + private static void InitCustomComponents() { BuiltinData = UnityGameFramework.Runtime.GameEntry.GetComponent(); @@ -34,5 +28,11 @@ public partial class GameEntry : MonoBehaviour EventNode = UnityGameFramework.Runtime.GameEntry.GetComponent(); CombatNode = UnityGameFramework.Runtime.GameEntry.GetComponent(); ShopNode = UnityGameFramework.Runtime.GameEntry.GetComponent(); + ResolutionAdapter = UnityGameFramework.Runtime.GameEntry.GetComponent(); + if (ResolutionAdapter == null) + { + UnityGameFramework.Runtime.Log.Warning( + "ResolutionAdapterComponent is missing. Please add it in Launcher scene and inject UI roots."); + } } } diff --git a/Assets/GameMain/Scripts/CustomComponent/ResolutionAdapterComponent.cs b/Assets/GameMain/Scripts/CustomComponent/ResolutionAdapterComponent.cs new file mode 100644 index 0000000..3a39863 --- /dev/null +++ b/Assets/GameMain/Scripts/CustomComponent/ResolutionAdapterComponent.cs @@ -0,0 +1,445 @@ +using System.Collections.Generic; +using GameFramework.Event; +using UnityEngine; +using UnityEngine.UI; +using UnityGameFramework.Runtime; + +namespace GeometryTD.CustomComponent +{ + /// + /// Keeps gameplay camera and UI in a fixed design aspect, then fills extra area with black masks. + /// + public class ResolutionAdapterComponent : GameFrameworkComponent + { + private const float DefaultCanvasPlaneDistance = 100f; + + [SerializeField] private Vector2 _referenceResolution = new Vector2(2560f, 1600f); + [SerializeField] private bool _adaptUiCanvasToViewport = true; + [SerializeField] private bool _enableBlackMask = true; + [SerializeField] private List _uiRoots = new List(); + + private readonly List _canvasBuffer = new List(32); + private readonly List _trackedCanvases = new List(32); + private readonly HashSet _trackedCanvasSet = new HashSet(); + + private Camera _mainCamera; + private Rect _targetViewport = new Rect(0f, 0f, 1f, 1f); + private int _cachedScreenWidth = -1; + private int _cachedScreenHeight = -1; + + private bool _canvasCacheDirty = true; + private bool _uiEventSubscribed; + private bool _missingRootWarned; + + private Canvas _maskCanvas; + private RectTransform _leftMask; + private RectTransform _rightMask; + private RectTransform _topMask; + private RectTransform _bottomMask; + + private void Start() + { + TryEnsureUiEventSubscribed(); + ApplyAdaptation(true); + } + + private void Update() + { + TryEnsureUiEventSubscribed(); + ApplyAdaptation(false); + } + + private void OnDestroy() + { + UnsubscribeUiEvents(); + + if (_mainCamera != null) + { + _mainCamera.rect = new Rect(0f, 0f, 1f, 1f); + } + } + + private void ApplyAdaptation(bool force) + { + if (_referenceResolution.x <= 0f || _referenceResolution.y <= 0f) + { + return; + } + + Camera resolvedCamera = ResolveMainCamera(); + bool cameraChanged = resolvedCamera != _mainCamera; + bool screenChanged = Screen.width != _cachedScreenWidth || Screen.height != _cachedScreenHeight; + bool needRecalculate = force || cameraChanged || screenChanged; + + if (needRecalculate) + { + Camera lastCamera = _mainCamera; + if (lastCamera != null && lastCamera != resolvedCamera) + { + lastCamera.rect = new Rect(0f, 0f, 1f, 1f); + } + + _mainCamera = resolvedCamera; + _cachedScreenWidth = Screen.width; + _cachedScreenHeight = Screen.height; + _targetViewport = CalculateViewport(_cachedScreenWidth, _cachedScreenHeight); + + ApplyCameraViewport(); + UpdateMaskLayout(); + } + + if (!_adaptUiCanvasToViewport) + { + return; + } + + if (!needRecalculate && !_canvasCacheDirty) + { + return; + } + + ApplyCanvasAdaptation(); + } + + private Camera ResolveMainCamera() + { + if (GameEntry.Scene != null && GameEntry.Scene.MainCamera != null) + { + return GameEntry.Scene.MainCamera; + } + + if (Camera.main != null) + { + return Camera.main; + } + + if (_mainCamera != null && _mainCamera.isActiveAndEnabled) + { + return _mainCamera; + } + + return null; + } + + private Rect CalculateViewport(int width, int height) + { + if (width <= 0 || height <= 0) + { + return new Rect(0f, 0f, 1f, 1f); + } + + float referenceAspect = _referenceResolution.x / _referenceResolution.y; + float screenAspect = (float)width / height; + + if (Mathf.Approximately(referenceAspect, screenAspect)) + { + return new Rect(0f, 0f, 1f, 1f); + } + + if (screenAspect > referenceAspect) + { + float viewportWidth = referenceAspect / screenAspect; + return new Rect((1f - viewportWidth) * 0.5f, 0f, viewportWidth, 1f); + } + + float viewportHeight = screenAspect / referenceAspect; + return new Rect(0f, (1f - viewportHeight) * 0.5f, 1f, viewportHeight); + } + + private void ApplyCameraViewport() + { + if (_mainCamera == null) + { + return; + } + + _mainCamera.rect = _targetViewport; + } + + private void ApplyCanvasAdaptation() + { + if (_mainCamera == null) + { + return; + } + + if (_uiRoots == null || _uiRoots.Count == 0) + { + if (!_missingRootWarned) + { + _missingRootWarned = true; + Log.Warning( + "ResolutionAdapterComponent missing injected roots. Assign UI/HPBar root transforms in scene."); + } + + return; + } + + if (_canvasCacheDirty) + { + RebuildCanvasCache(); + } + + for (int i = _trackedCanvases.Count - 1; i >= 0; i--) + { + Canvas canvas = _trackedCanvases[i]; + if (canvas == null) + { + _trackedCanvases.RemoveAt(i); + _canvasCacheDirty = true; + continue; + } + + ApplyCanvasSettings(canvas); + } + } + + private void RebuildCanvasCache() + { + _canvasCacheDirty = false; + _trackedCanvases.Clear(); + _trackedCanvasSet.Clear(); + + foreach (var root in _uiRoots) + { + CollectCanvases(root); + } + } + + private void CollectCanvases(Transform root) + { + if (root == null) + { + return; + } + + root.GetComponentsInChildren(true, _canvasBuffer); + foreach (Canvas canvas in _canvasBuffer) + { + if (canvas == null || canvas == _maskCanvas || canvas.renderMode == RenderMode.WorldSpace) + { + continue; + } + + if (_trackedCanvasSet.Add(canvas)) + { + _trackedCanvases.Add(canvas); + } + } + + _canvasBuffer.Clear(); + } + + private void ApplyCanvasSettings(Canvas canvas) + { + if (canvas == _maskCanvas || canvas.renderMode == RenderMode.WorldSpace) + { + return; + } + + canvas.renderMode = RenderMode.ScreenSpaceCamera; + canvas.worldCamera = _mainCamera; + canvas.planeDistance = ResolveCanvasPlaneDistance(_mainCamera); + + CanvasScaler scaler = canvas.GetComponent(); + if (scaler != null) + { + scaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize; + scaler.referenceResolution = _referenceResolution; + scaler.screenMatchMode = CanvasScaler.ScreenMatchMode.MatchWidthOrHeight; + scaler.matchWidthOrHeight = 0f; + } + } + + private static float ResolveCanvasPlaneDistance(Camera camera) + { + if (camera == null) + { + return DefaultCanvasPlaneDistance; + } + + float minDistance = camera.nearClipPlane + 0.05f; + float maxDistance = camera.farClipPlane - 0.05f; + if (maxDistance <= minDistance) + { + return minDistance; + } + + return Mathf.Clamp(DefaultCanvasPlaneDistance, minDistance, maxDistance); + } + + private void TryEnsureUiEventSubscribed() + { + if (_uiEventSubscribed || GameEntry.Event == null) + { + return; + } + + GameEntry.Event.Subscribe(OpenUIFormSuccessEventArgs.EventId, OnUIFormChanged); + GameEntry.Event.Subscribe(CloseUIFormCompleteEventArgs.EventId, OnUIFormChanged); + _uiEventSubscribed = true; + _canvasCacheDirty = true; + } + + private void UnsubscribeUiEvents() + { + if (!_uiEventSubscribed || GameEntry.Event == null) + { + return; + } + + GameEntry.Event.Unsubscribe(OpenUIFormSuccessEventArgs.EventId, OnUIFormChanged); + GameEntry.Event.Unsubscribe(CloseUIFormCompleteEventArgs.EventId, OnUIFormChanged); + _uiEventSubscribed = false; + } + + private void OnUIFormChanged(object sender, GameEventArgs e) + { + _canvasCacheDirty = true; + } + + private void UpdateMaskLayout() + { + if (!_enableBlackMask) + { + SetMaskVisible(false, false); + return; + } + + EnsureMaskObjects(); + if (_maskCanvas == null) + { + return; + } + + float horizontalPadding = Mathf.Max(0f, (1f - _targetViewport.width) * 0.5f * _cachedScreenWidth); + float verticalPadding = Mathf.Max(0f, (1f - _targetViewport.height) * 0.5f * _cachedScreenHeight); + + bool showVerticalMask = horizontalPadding > 0.5f; + bool showHorizontalMask = verticalPadding > 0.5f; + + SetMaskVisible(showVerticalMask, showHorizontalMask); + if (showVerticalMask) + { + SetVerticalMaskRect(_leftMask, true, horizontalPadding); + SetVerticalMaskRect(_rightMask, false, horizontalPadding); + } + + if (showHorizontalMask) + { + SetHorizontalMaskRect(_topMask, true, verticalPadding); + SetHorizontalMaskRect(_bottomMask, false, verticalPadding); + } + } + + private void EnsureMaskObjects() + { + if (_maskCanvas != null) + { + return; + } + + GameObject maskRoot = new GameObject( + "ResolutionMask", + typeof(RectTransform), + typeof(Canvas), + typeof(CanvasScaler), + typeof(GraphicRaycaster)); + maskRoot.transform.SetParent(transform, false); + + _maskCanvas = maskRoot.GetComponent(); + _maskCanvas.renderMode = RenderMode.ScreenSpaceOverlay; + _maskCanvas.overrideSorting = true; + _maskCanvas.sortingOrder = short.MaxValue; + + CanvasScaler scaler = maskRoot.GetComponent(); + scaler.uiScaleMode = CanvasScaler.ScaleMode.ConstantPixelSize; + scaler.scaleFactor = 1f; + + GraphicRaycaster raycaster = maskRoot.GetComponent(); + raycaster.enabled = false; + + RectTransform rootRect = maskRoot.GetComponent(); + rootRect.anchorMin = Vector2.zero; + rootRect.anchorMax = Vector2.one; + rootRect.anchoredPosition = Vector2.zero; + rootRect.sizeDelta = Vector2.zero; + + _leftMask = CreateMaskRect("LeftMask", rootRect); + _rightMask = CreateMaskRect("RightMask", rootRect); + _topMask = CreateMaskRect("TopMask", rootRect); + _bottomMask = CreateMaskRect("BottomMask", rootRect); + } + + private static RectTransform CreateMaskRect(string maskName, Transform parent) + { + GameObject maskObject = new GameObject(maskName, typeof(RectTransform), typeof(Image)); + maskObject.transform.SetParent(parent, false); + + Image image = maskObject.GetComponent(); + image.color = Color.black; + image.raycastTarget = false; + + return maskObject.GetComponent(); + } + + private void SetMaskVisible(bool showVerticalMask, bool showHorizontalMask) + { + if (_maskCanvas == null) + { + return; + } + + bool visible = showVerticalMask || showHorizontalMask; + _maskCanvas.enabled = visible; + + if (_leftMask != null) + { + _leftMask.gameObject.SetActive(showVerticalMask); + } + + if (_rightMask != null) + { + _rightMask.gameObject.SetActive(showVerticalMask); + } + + if (_topMask != null) + { + _topMask.gameObject.SetActive(showHorizontalMask); + } + + if (_bottomMask != null) + { + _bottomMask.gameObject.SetActive(showHorizontalMask); + } + } + + private static void SetVerticalMaskRect(RectTransform maskRect, bool isLeft, float width) + { + if (maskRect == null) + { + return; + } + + maskRect.anchorMin = new Vector2(isLeft ? 0f : 1f, 0f); + maskRect.anchorMax = new Vector2(isLeft ? 0f : 1f, 1f); + maskRect.pivot = new Vector2(isLeft ? 0f : 1f, 0.5f); + maskRect.anchoredPosition = Vector2.zero; + maskRect.sizeDelta = new Vector2(width, 0f); + } + + private static void SetHorizontalMaskRect(RectTransform maskRect, bool isTop, float height) + { + if (maskRect == null) + { + return; + } + + maskRect.anchorMin = new Vector2(0f, isTop ? 1f : 0f); + maskRect.anchorMax = new Vector2(1f, isTop ? 1f : 0f); + maskRect.pivot = new Vector2(0.5f, isTop ? 1f : 0f); + maskRect.anchoredPosition = Vector2.zero; + maskRect.sizeDelta = new Vector2(0f, height); + } + } +} \ No newline at end of file diff --git a/Assets/GameMain/Scripts/CustomComponent/ResolutionAdapterComponent.cs.meta b/Assets/GameMain/Scripts/CustomComponent/ResolutionAdapterComponent.cs.meta new file mode 100644 index 0000000..8c75a3a --- /dev/null +++ b/Assets/GameMain/Scripts/CustomComponent/ResolutionAdapterComponent.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 10f174db309f41b9abaf60bc291fbb2c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Definition/Enum/UIFormType.cs b/Assets/GameMain/Scripts/Definition/Enum/UIFormType.cs index 64978a4..cc11d30 100644 --- a/Assets/GameMain/Scripts/Definition/Enum/UIFormType.cs +++ b/Assets/GameMain/Scripts/Definition/Enum/UIFormType.cs @@ -26,6 +26,11 @@ /// 关于。 /// AboutForm = 102, + + /// + /// 主界面。 + /// + MainForm = 103, /// /// 测试菜单。 diff --git a/Assets/GameMain/Scripts/Event/EventForm.meta b/Assets/GameMain/Scripts/Event/EventForm.meta new file mode 100644 index 0000000..f55caef --- /dev/null +++ b/Assets/GameMain/Scripts/Event/EventForm.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: e1274c270d074c23aaaa30b5397a006d +timeCreated: 1772270815 \ No newline at end of file diff --git a/Assets/GameMain/Scripts/Event/EventOptionItemSelectedEventArgs.cs b/Assets/GameMain/Scripts/Event/EventForm/EventOptionItemSelectedEventArgs.cs similarity index 100% rename from Assets/GameMain/Scripts/Event/EventOptionItemSelectedEventArgs.cs rename to Assets/GameMain/Scripts/Event/EventForm/EventOptionItemSelectedEventArgs.cs diff --git a/Assets/GameMain/Scripts/Event/EventOptionItemSelectedEventArgs.cs.meta b/Assets/GameMain/Scripts/Event/EventForm/EventOptionItemSelectedEventArgs.cs.meta similarity index 100% rename from Assets/GameMain/Scripts/Event/EventOptionItemSelectedEventArgs.cs.meta rename to Assets/GameMain/Scripts/Event/EventForm/EventOptionItemSelectedEventArgs.cs.meta diff --git a/Assets/GameMain/Scripts/Event/Game.meta b/Assets/GameMain/Scripts/Event/Game.meta new file mode 100644 index 0000000..9247579 --- /dev/null +++ b/Assets/GameMain/Scripts/Event/Game.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 35168ae7e80542e3a6b97a1607c21df5 +timeCreated: 1772270856 \ No newline at end of file diff --git a/Assets/GameMain/Scripts/Event/Game/NodeCompleteEventArgs.cs b/Assets/GameMain/Scripts/Event/Game/NodeCompleteEventArgs.cs new file mode 100644 index 0000000..485144c --- /dev/null +++ b/Assets/GameMain/Scripts/Event/Game/NodeCompleteEventArgs.cs @@ -0,0 +1,27 @@ +using GameFramework; +using GameFramework.Event; + +namespace GeometryTD.CustomEvent +{ + public class NodeCompleteEventArgs : GameEventArgs + { + public static int EventId = typeof(NodeCompleteEventArgs).GetHashCode(); + + public override int Id => EventId; + + public NodeCompleteEventArgs() + { + } + + public static NodeCompleteEventArgs Create() + { + var args = ReferencePool.Acquire(); + + return args; + } + + public override void Clear() + { + } + } +} \ No newline at end of file diff --git a/Assets/GameMain/Scripts/Event/Game/NodeCompleteEventArgs.cs.meta b/Assets/GameMain/Scripts/Event/Game/NodeCompleteEventArgs.cs.meta new file mode 100644 index 0000000..e80fc21 --- /dev/null +++ b/Assets/GameMain/Scripts/Event/Game/NodeCompleteEventArgs.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 3c8d1335edfb4fcd8b08279d3c254eff +timeCreated: 1772269787 \ No newline at end of file diff --git a/Assets/GameMain/Scripts/Event/Game/NodeEnterEventArgs.cs b/Assets/GameMain/Scripts/Event/Game/NodeEnterEventArgs.cs new file mode 100644 index 0000000..7cddf27 --- /dev/null +++ b/Assets/GameMain/Scripts/Event/Game/NodeEnterEventArgs.cs @@ -0,0 +1,27 @@ +using GameFramework; +using GameFramework.Event; + +namespace GeometryTD.CustomEvent +{ + public class NodeEnterEventArgs : GameEventArgs + { + public static int EventId = typeof(NodeEnterEventArgs).GetHashCode(); + + public override int Id => EventId; + + public NodeEnterEventArgs() + { + } + + public static NodeEnterEventArgs Create() + { + var args = ReferencePool.Acquire(); + + return args; + } + + public override void Clear() + { + } + } +} \ No newline at end of file diff --git a/Assets/GameMain/Scripts/Event/Game/NodeEnterEventArgs.cs.meta b/Assets/GameMain/Scripts/Event/Game/NodeEnterEventArgs.cs.meta new file mode 100644 index 0000000..645652c --- /dev/null +++ b/Assets/GameMain/Scripts/Event/Game/NodeEnterEventArgs.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 8a42a26567434ac194a89aa5c9ae6c5d +timeCreated: 1772270138 \ No newline at end of file diff --git a/Assets/GameMain/Scripts/Event/TestMenuNodeClickEventArgs.cs b/Assets/GameMain/Scripts/Event/Game/TestMenuNodeClickEventArgs.cs similarity index 100% rename from Assets/GameMain/Scripts/Event/TestMenuNodeClickEventArgs.cs rename to Assets/GameMain/Scripts/Event/Game/TestMenuNodeClickEventArgs.cs diff --git a/Assets/GameMain/Scripts/Event/TestMenuNodeClickEventArgs.cs.meta b/Assets/GameMain/Scripts/Event/Game/TestMenuNodeClickEventArgs.cs.meta similarity index 100% rename from Assets/GameMain/Scripts/Event/TestMenuNodeClickEventArgs.cs.meta rename to Assets/GameMain/Scripts/Event/Game/TestMenuNodeClickEventArgs.cs.meta diff --git a/Assets/GameMain/Scripts/Event/MainForm.meta b/Assets/GameMain/Scripts/Event/MainForm.meta new file mode 100644 index 0000000..4e9223e --- /dev/null +++ b/Assets/GameMain/Scripts/Event/MainForm.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 709fe1ffb5c64b7087ca303ece9dfbe3 +timeCreated: 1772270876 \ No newline at end of file diff --git a/Assets/GameMain/Scripts/Event/MainForm/RepoButtonClickedEventArgs.cs b/Assets/GameMain/Scripts/Event/MainForm/RepoButtonClickedEventArgs.cs new file mode 100644 index 0000000..9d57b2f --- /dev/null +++ b/Assets/GameMain/Scripts/Event/MainForm/RepoButtonClickedEventArgs.cs @@ -0,0 +1,27 @@ +using GameFramework; +using GameFramework.Event; + +namespace GeometryTD.CustomEvent +{ + public class RepoButtonClickedEventArgs : GameEventArgs + { + public static int EventId = typeof(RepoButtonClickedEventArgs).GetHashCode(); + + public override int Id => EventId; + + public RepoButtonClickedEventArgs() + { + } + + public static RepoButtonClickedEventArgs Create() + { + var args = ReferencePool.Acquire(); + + return args; + } + + public override void Clear() + { + } + } +} \ No newline at end of file diff --git a/Assets/GameMain/Scripts/Event/MainForm/RepoButtonClickedEventArgs.cs.meta b/Assets/GameMain/Scripts/Event/MainForm/RepoButtonClickedEventArgs.cs.meta new file mode 100644 index 0000000..5525d33 --- /dev/null +++ b/Assets/GameMain/Scripts/Event/MainForm/RepoButtonClickedEventArgs.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: cdad529781d948de8c745c9285a8dabf +timeCreated: 1772270941 \ No newline at end of file diff --git a/Assets/GameMain/Scripts/Event/MainForm/ReturnButtonClickedEventArgs.cs b/Assets/GameMain/Scripts/Event/MainForm/ReturnButtonClickedEventArgs.cs new file mode 100644 index 0000000..02ee195 --- /dev/null +++ b/Assets/GameMain/Scripts/Event/MainForm/ReturnButtonClickedEventArgs.cs @@ -0,0 +1,27 @@ +using GameFramework; +using GameFramework.Event; + +namespace GeometryTD.CustomEvent +{ + public class ReturnButtonClickedEventArgs : GameEventArgs + { + public static int EventId = typeof(ReturnButtonClickedEventArgs).GetHashCode(); + + public override int Id => EventId; + + public ReturnButtonClickedEventArgs() + { + } + + public static ReturnButtonClickedEventArgs Create() + { + var args = ReferencePool.Acquire(); + + return args; + } + + public override void Clear() + { + } + } +} \ No newline at end of file diff --git a/Assets/GameMain/Scripts/Event/MainForm/ReturnButtonClickedEventArgs.cs.meta b/Assets/GameMain/Scripts/Event/MainForm/ReturnButtonClickedEventArgs.cs.meta new file mode 100644 index 0000000..2f8116c --- /dev/null +++ b/Assets/GameMain/Scripts/Event/MainForm/ReturnButtonClickedEventArgs.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: fa47a9da112d431f866cb5f3309ad17a +timeCreated: 1772270885 \ No newline at end of file diff --git a/Assets/GameMain/Scripts/Event/RepoForm.meta b/Assets/GameMain/Scripts/Event/RepoForm.meta new file mode 100644 index 0000000..b913e07 --- /dev/null +++ b/Assets/GameMain/Scripts/Event/RepoForm.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 7775d869bf1a4026ae3bd5041db6cace +timeCreated: 1772270829 \ No newline at end of file diff --git a/Assets/GameMain/Scripts/Event/CombineSlotClickedEventArgs.cs b/Assets/GameMain/Scripts/Event/RepoForm/CombineSlotClickedEventArgs.cs similarity index 100% rename from Assets/GameMain/Scripts/Event/CombineSlotClickedEventArgs.cs rename to Assets/GameMain/Scripts/Event/RepoForm/CombineSlotClickedEventArgs.cs diff --git a/Assets/GameMain/Scripts/Event/CombineSlotClickedEventArgs.cs.meta b/Assets/GameMain/Scripts/Event/RepoForm/CombineSlotClickedEventArgs.cs.meta similarity index 100% rename from Assets/GameMain/Scripts/Event/CombineSlotClickedEventArgs.cs.meta rename to Assets/GameMain/Scripts/Event/RepoForm/CombineSlotClickedEventArgs.cs.meta diff --git a/Assets/GameMain/Scripts/Event/RepoItemSelectedEventArgs.cs b/Assets/GameMain/Scripts/Event/RepoForm/RepoItemSelectedEventArgs.cs similarity index 100% rename from Assets/GameMain/Scripts/Event/RepoItemSelectedEventArgs.cs rename to Assets/GameMain/Scripts/Event/RepoForm/RepoItemSelectedEventArgs.cs diff --git a/Assets/GameMain/Scripts/Event/RepoItemSelectedEventArgs.cs.meta b/Assets/GameMain/Scripts/Event/RepoForm/RepoItemSelectedEventArgs.cs.meta similarity index 100% rename from Assets/GameMain/Scripts/Event/RepoItemSelectedEventArgs.cs.meta rename to Assets/GameMain/Scripts/Event/RepoForm/RepoItemSelectedEventArgs.cs.meta diff --git a/Assets/GameMain/Scripts/Procedure/ProcedureMenu.cs b/Assets/GameMain/Scripts/Procedure/ProcedureMenu.cs index 9cc3946..2b8a130 100644 --- a/Assets/GameMain/Scripts/Procedure/ProcedureMenu.cs +++ b/Assets/GameMain/Scripts/Procedure/ProcedureMenu.cs @@ -1,6 +1,9 @@ +using GameFramework.Event; using GameFramework.Fsm; using GameFramework.Procedure; +using GeometryTD.CustomEvent; using GeometryTD.Definition; +using GeometryTD.UI; using UnityGameFramework.Runtime; namespace GeometryTD.Procedure @@ -11,6 +14,8 @@ namespace GeometryTD.Procedure public bool GameStart { get; set; } + private RepoFormUseCase _repoFormUseCase; + #region FSM protected override void OnInit(IFsm procedureOwner) @@ -22,11 +27,19 @@ namespace GeometryTD.Procedure { base.OnEnter(procedureOwner); + GameEntry.Event.Subscribe(NodeCompleteEventArgs.EventId, OnNodeComplete); + GameEntry.Event.Subscribe(NodeEnterEventArgs.EventId, OnNodeEnter); + GameStart = false; + GameEntry.EventNode.OnInit(); GameEntry.CombatNode.OnInit(LevelThemeType.Plain); GameEntry.ShopNode.OnInit(); + _repoFormUseCase = new RepoFormUseCase(); + GameEntry.UIRouter.BindUIUseCase(UIFormType.RepoForm, _repoFormUseCase); + + GameEntry.UIRouter.OpenUI(UIFormType.MainForm); GameEntry.UIRouter.OpenUI(UIFormType.TestMenuForm); } @@ -48,9 +61,26 @@ namespace GeometryTD.Procedure protected override void OnLeave(IFsm procedureOwner, bool isShutdown) { GameEntry.CombatNode.OnShutdown(); + GameEntry.Event.Unsubscribe(NodeEnterEventArgs.EventId, OnNodeEnter); + GameEntry.Event.Unsubscribe(NodeCompleteEventArgs.EventId, OnNodeComplete); + base.OnLeave(procedureOwner, isShutdown); } #endregion + + private void OnNodeEnter(object sender, GameEventArgs e) + { + if (!(e is NodeEnterEventArgs)) return; + + GameEntry.UIRouter.CloseUI(UIFormType.TestMenuForm); + } + + private void OnNodeComplete(object sender, GameEventArgs e) + { + if (!(e is NodeCompleteEventArgs)) return; + + GameEntry.UIRouter.OpenUI(UIFormType.TestMenuForm); + } } -} +} \ No newline at end of file diff --git a/Assets/GameMain/Scripts/UI/GameScene/Context/MainFormContext.cs b/Assets/GameMain/Scripts/UI/GameScene/Context/MainFormContext.cs new file mode 100644 index 0000000..b74efcc --- /dev/null +++ b/Assets/GameMain/Scripts/UI/GameScene/Context/MainFormContext.cs @@ -0,0 +1,6 @@ +namespace GeometryTD.UI +{ + public class MainFormContext : UIContext + { + } +} diff --git a/Assets/GameMain/Scripts/UI/GameScene/Context/MainFormContext.cs.meta b/Assets/GameMain/Scripts/UI/GameScene/Context/MainFormContext.cs.meta new file mode 100644 index 0000000..32d8220 --- /dev/null +++ b/Assets/GameMain/Scripts/UI/GameScene/Context/MainFormContext.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 50722ebad52b4f619bd33883598842ea +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameMain/Scripts/UI/GameScene/Controller/MainFormController.cs b/Assets/GameMain/Scripts/UI/GameScene/Controller/MainFormController.cs new file mode 100644 index 0000000..7ba1f4f --- /dev/null +++ b/Assets/GameMain/Scripts/UI/GameScene/Controller/MainFormController.cs @@ -0,0 +1,79 @@ +using GeometryTD.CustomEvent; +using GeometryTD.Definition; +using GameFramework.Event; +using UnityGameFramework.Runtime; + +namespace GeometryTD.UI +{ + public class MainFormController : UIFormControllerCommonBase + { + protected override UIFormType UIFormTypeId => UIFormType.MainForm; + + protected override void RefreshUI(MainForm form, MainFormContext context) + { + form.RefreshUI(context); + } + + protected override void SubscribeCustomEvents() + { + GameEntry.Event.Subscribe(ReturnButtonClickedEventArgs.EventId, OnReturnButtonClicked); + GameEntry.Event.Subscribe(RepoButtonClickedEventArgs.EventId, OnRepoButtonClicked); + } + + protected override void UnsubscribeCustomEvents() + { + GameEntry.Event.Unsubscribe(ReturnButtonClickedEventArgs.EventId, OnReturnButtonClicked); + GameEntry.Event.Unsubscribe(RepoButtonClickedEventArgs.EventId, OnRepoButtonClicked); + } + + public override int? OpenUI(object userData = null) + { + if (userData is MainFormContext context) + { + return OpenUIInternal(context); + } + + if (userData != null) + { + Log.Warning("MainFormController.OpenUI() userData type is invalid."); + return null; + } + + return OpenUIInternal(BuildDefaultContext()); + } + + public override void BindUseCase(IUIUseCase useCase) + { + if (useCase != null) + { + Log.Warning("MainFormController does not use a use case."); + } + } + + private static MainFormContext BuildDefaultContext() + { + return new MainFormContext(); + } + + private void OnReturnButtonClicked(object sender, GameEventArgs e) + { + if (!(sender is MainForm) || !(e is ReturnButtonClickedEventArgs)) + { + return; + } + + //TODO:游戏 UI 返回菜单 UI + //GameEntry.UIRouter.CloseUI(UIFormType.MainForm); + } + + private void OnRepoButtonClicked(object sender, GameEventArgs e) + { + if (!(sender is MainForm) || !(e is RepoButtonClickedEventArgs)) + { + return; + } + + GameEntry.UIRouter.OpenUI(UIFormType.RepoForm); + } + } +} \ No newline at end of file diff --git a/Assets/GameMain/Scripts/UI/GameScene/Controller/MainFormController.cs.meta b/Assets/GameMain/Scripts/UI/GameScene/Controller/MainFormController.cs.meta new file mode 100644 index 0000000..90006c2 --- /dev/null +++ b/Assets/GameMain/Scripts/UI/GameScene/Controller/MainFormController.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 88a17d9010c944a8a0123f31ed09f7d9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameMain/Scripts/UI/GameScene/UseCase/EventFormUseCase.cs b/Assets/GameMain/Scripts/UI/GameScene/UseCase/EventFormUseCase.cs index a789b03..2eb7b8e 100644 --- a/Assets/GameMain/Scripts/UI/GameScene/UseCase/EventFormUseCase.cs +++ b/Assets/GameMain/Scripts/UI/GameScene/UseCase/EventFormUseCase.cs @@ -1,5 +1,5 @@ +using GeometryTD.CustomEvent; using GeometryTD.Definition; -using GeometryTD.UI; using UnityGameFramework.Runtime; namespace GeometryTD.UI @@ -40,7 +40,8 @@ namespace GeometryTD.UI } // TODO: 执行 Requirements 校验、CostEffects/RewardEffects 结算与后续节点推进。 + GameEntry.Event.Fire(this, NodeCompleteEventArgs.Create()); return m_CurrentEvent.Options[optionIndex]; } } -} +} \ No newline at end of file diff --git a/Assets/GameMain/Scripts/UI/GameScene/View/MainForm.cs b/Assets/GameMain/Scripts/UI/GameScene/View/MainForm.cs new file mode 100644 index 0000000..e956e01 --- /dev/null +++ b/Assets/GameMain/Scripts/UI/GameScene/View/MainForm.cs @@ -0,0 +1,49 @@ +using GeometryTD.CustomEvent; +using UnityGameFramework.Runtime; + +namespace GeometryTD.UI +{ + public class MainForm : UGuiForm + { + private MainFormContext _context; + + public void RefreshUI(MainFormContext context) + { + _context = context; + if (_context == null) + { + return; + } + } + + public void OnReturnButtonClick() + { + GameEntry.Event.Fire(this, ReturnButtonClickedEventArgs.Create()); + } + + public void OnRepoButtonClick() + { + GameEntry.Event.Fire(this, RepoButtonClickedEventArgs.Create()); + } + + protected override void OnOpen(object userData) + { + base.OnOpen(userData); + + if (userData is MainFormContext context) + { + RefreshUI(context); + return; + } + + Log.Warning("MainForm requires MainFormContext as userData."); + } + + protected override void OnClose(bool isShutdown, object userData) + { + _context = null; + + base.OnClose(isShutdown, userData); + } + } +} \ No newline at end of file diff --git a/Assets/GameMain/Scripts/UI/GameScene/View/MainForm.cs.meta b/Assets/GameMain/Scripts/UI/GameScene/View/MainForm.cs.meta new file mode 100644 index 0000000..6513785 --- /dev/null +++ b/Assets/GameMain/Scripts/UI/GameScene/View/MainForm.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 838d81ed05914e248972f7ad7df7787d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameMain/UI/UIForms/MainForm.prefab b/Assets/GameMain/UI/UIForms/MainForm.prefab new file mode 100644 index 0000000..daba16e --- /dev/null +++ b/Assets/GameMain/UI/UIForms/MainForm.prefab @@ -0,0 +1,452 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &3784251474479012746 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 7992545098694047102} + m_Layer: 5 + m_Name: Top + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &7992545098694047102 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3784251474479012746} + 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: + - {fileID: 7300278248921280140} + m_Father: {fileID: 2576533646156518797} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: -150} + m_SizeDelta: {x: 0, y: 300} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &6196130353114318678 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4725840776031713869} + m_Layer: 5 + m_Name: Down + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &4725840776031713869 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6196130353114318678} + 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: + - {fileID: 2576324724784232350} + m_Father: {fileID: 2576533646156518797} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 0} + m_AnchoredPosition: {x: 0, y: 150} + m_SizeDelta: {x: 0, y: 300} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &6906491192444208336 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2576533646156518797} + - component: {fileID: 2488276356196385900} + m_Layer: 5 + m_Name: MainForm + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &2576533646156518797 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6906491192444208336} + 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: + - {fileID: 7992545098694047102} + - {fileID: 4725840776031713869} + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &2488276356196385900 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6906491192444208336} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 838d81ed05914e248972f7ad7df7787d, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!1001 &2131453811344650601 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + serializedVersion: 3 + m_TransformParent: {fileID: 4725840776031713869} + m_Modifications: + - target: {fileID: 770565994539545022, guid: 2307f223279813546a43b221ddd496cc, + type: 3} + propertyPath: m_Name + value: RepoButton + objectReference: {fileID: 0} + - target: {fileID: 1920576543566152029, guid: 2307f223279813546a43b221ddd496cc, + type: 3} + propertyPath: m_text + value: "\u80CC\u5305" + objectReference: {fileID: 0} + - target: {fileID: 4067353614215461310, guid: 2307f223279813546a43b221ddd496cc, + type: 3} + propertyPath: _onClick.m_PersistentCalls.m_Calls.Array.data[1].m_Mode + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 4067353614215461310, guid: 2307f223279813546a43b221ddd496cc, + type: 3} + propertyPath: _onClick.m_PersistentCalls.m_Calls.Array.data[0].m_Target + value: + objectReference: {fileID: 2488276356196385900} + - target: {fileID: 4067353614215461310, guid: 2307f223279813546a43b221ddd496cc, + type: 3} + propertyPath: _onClick.m_PersistentCalls.m_Calls.Array.data[1].m_Target + value: + objectReference: {fileID: 2488276356196385900} + - target: {fileID: 4067353614215461310, guid: 2307f223279813546a43b221ddd496cc, + type: 3} + propertyPath: _onHover.m_PersistentCalls.m_Calls.Array.data[0].m_Target + value: + objectReference: {fileID: 2488276356196385900} + - target: {fileID: 4067353614215461310, guid: 2307f223279813546a43b221ddd496cc, + type: 3} + propertyPath: _onClick.m_PersistentCalls.m_Calls.Array.data[1].m_MethodName + value: OnRepoButtonClick + objectReference: {fileID: 0} + - target: {fileID: 4067353614215461310, guid: 2307f223279813546a43b221ddd496cc, + type: 3} + propertyPath: _onClick.m_PersistentCalls.m_Calls.Array.data[1].m_TargetAssemblyTypeName + value: GeometryTD.UI.MainForm, Assembly-CSharp + objectReference: {fileID: 0} + - target: {fileID: 4067353614215461310, guid: 2307f223279813546a43b221ddd496cc, + type: 3} + propertyPath: _onClick.m_PersistentCalls.m_Calls.Array.data[1].m_Arguments.m_ObjectArgumentAssemblyTypeName + value: UnityEngine.Object, UnityEngine + objectReference: {fileID: 0} + - target: {fileID: 4491355866364659447, guid: 2307f223279813546a43b221ddd496cc, + type: 3} + propertyPath: m_Pivot.x + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 4491355866364659447, guid: 2307f223279813546a43b221ddd496cc, + type: 3} + propertyPath: m_Pivot.y + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 4491355866364659447, guid: 2307f223279813546a43b221ddd496cc, + type: 3} + propertyPath: m_AnchorMax.x + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 4491355866364659447, guid: 2307f223279813546a43b221ddd496cc, + type: 3} + propertyPath: m_AnchorMax.y + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 4491355866364659447, guid: 2307f223279813546a43b221ddd496cc, + type: 3} + propertyPath: m_AnchorMin.x + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 4491355866364659447, guid: 2307f223279813546a43b221ddd496cc, + type: 3} + propertyPath: m_AnchorMin.y + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 4491355866364659447, guid: 2307f223279813546a43b221ddd496cc, + type: 3} + propertyPath: m_SizeDelta.x + value: 200 + objectReference: {fileID: 0} + - target: {fileID: 4491355866364659447, guid: 2307f223279813546a43b221ddd496cc, + type: 3} + propertyPath: m_SizeDelta.y + value: 200 + objectReference: {fileID: 0} + - target: {fileID: 4491355866364659447, guid: 2307f223279813546a43b221ddd496cc, + type: 3} + propertyPath: m_LocalPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4491355866364659447, guid: 2307f223279813546a43b221ddd496cc, + type: 3} + propertyPath: m_LocalPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4491355866364659447, guid: 2307f223279813546a43b221ddd496cc, + type: 3} + propertyPath: m_LocalPosition.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4491355866364659447, guid: 2307f223279813546a43b221ddd496cc, + type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 4491355866364659447, guid: 2307f223279813546a43b221ddd496cc, + type: 3} + propertyPath: m_LocalRotation.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4491355866364659447, guid: 2307f223279813546a43b221ddd496cc, + type: 3} + propertyPath: m_LocalRotation.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4491355866364659447, guid: 2307f223279813546a43b221ddd496cc, + type: 3} + propertyPath: m_LocalRotation.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4491355866364659447, guid: 2307f223279813546a43b221ddd496cc, + type: 3} + propertyPath: m_AnchoredPosition.x + value: -200 + objectReference: {fileID: 0} + - target: {fileID: 4491355866364659447, guid: 2307f223279813546a43b221ddd496cc, + type: 3} + propertyPath: m_AnchoredPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4491355866364659447, guid: 2307f223279813546a43b221ddd496cc, + type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4491355866364659447, guid: 2307f223279813546a43b221ddd496cc, + type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4491355866364659447, guid: 2307f223279813546a43b221ddd496cc, + type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: 2307f223279813546a43b221ddd496cc, type: 3} +--- !u!224 &2576324724784232350 stripped +RectTransform: + m_CorrespondingSourceObject: {fileID: 4491355866364659447, guid: 2307f223279813546a43b221ddd496cc, + type: 3} + m_PrefabInstance: {fileID: 2131453811344650601} + m_PrefabAsset: {fileID: 0} +--- !u!1001 &6564924713997363323 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + serializedVersion: 3 + m_TransformParent: {fileID: 7992545098694047102} + m_Modifications: + - target: {fileID: 770565994539545022, guid: 2307f223279813546a43b221ddd496cc, + type: 3} + propertyPath: m_Name + value: ReturnButton + objectReference: {fileID: 0} + - target: {fileID: 1920576543566152029, guid: 2307f223279813546a43b221ddd496cc, + type: 3} + propertyPath: m_text + value: "\u8FD4\u56DE\u83DC\u5355" + objectReference: {fileID: 0} + - target: {fileID: 4067353614215461310, guid: 2307f223279813546a43b221ddd496cc, + type: 3} + propertyPath: _onClick.m_PersistentCalls.m_Calls.Array.data[1].m_Mode + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 4067353614215461310, guid: 2307f223279813546a43b221ddd496cc, + type: 3} + propertyPath: _onClick.m_PersistentCalls.m_Calls.Array.data[0].m_Target + value: + objectReference: {fileID: 2488276356196385900} + - target: {fileID: 4067353614215461310, guid: 2307f223279813546a43b221ddd496cc, + type: 3} + propertyPath: _onClick.m_PersistentCalls.m_Calls.Array.data[1].m_Target + value: + objectReference: {fileID: 2488276356196385900} + - target: {fileID: 4067353614215461310, guid: 2307f223279813546a43b221ddd496cc, + type: 3} + propertyPath: _onHover.m_PersistentCalls.m_Calls.Array.data[0].m_Target + value: + objectReference: {fileID: 2488276356196385900} + - target: {fileID: 4067353614215461310, guid: 2307f223279813546a43b221ddd496cc, + type: 3} + propertyPath: _onClick.m_PersistentCalls.m_Calls.Array.data[1].m_MethodName + value: OnReturnButtonClick + objectReference: {fileID: 0} + - target: {fileID: 4067353614215461310, guid: 2307f223279813546a43b221ddd496cc, + type: 3} + propertyPath: _onClick.m_PersistentCalls.m_Calls.Array.data[1].m_TargetAssemblyTypeName + value: GeometryTD.UI.MainForm, Assembly-CSharp + objectReference: {fileID: 0} + - target: {fileID: 4067353614215461310, guid: 2307f223279813546a43b221ddd496cc, + type: 3} + propertyPath: _onClick.m_PersistentCalls.m_Calls.Array.data[1].m_Arguments.m_ObjectArgumentAssemblyTypeName + value: UnityEngine.Object, UnityEngine + objectReference: {fileID: 0} + - target: {fileID: 4491355866364659447, guid: 2307f223279813546a43b221ddd496cc, + type: 3} + propertyPath: m_Pivot.x + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 4491355866364659447, guid: 2307f223279813546a43b221ddd496cc, + type: 3} + propertyPath: m_Pivot.y + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 4491355866364659447, guid: 2307f223279813546a43b221ddd496cc, + type: 3} + propertyPath: m_AnchorMax.x + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 4491355866364659447, guid: 2307f223279813546a43b221ddd496cc, + type: 3} + propertyPath: m_AnchorMax.y + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 4491355866364659447, guid: 2307f223279813546a43b221ddd496cc, + type: 3} + propertyPath: m_AnchorMin.x + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 4491355866364659447, guid: 2307f223279813546a43b221ddd496cc, + type: 3} + propertyPath: m_AnchorMin.y + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 4491355866364659447, guid: 2307f223279813546a43b221ddd496cc, + type: 3} + propertyPath: m_SizeDelta.x + value: 200 + objectReference: {fileID: 0} + - target: {fileID: 4491355866364659447, guid: 2307f223279813546a43b221ddd496cc, + type: 3} + propertyPath: m_SizeDelta.y + value: 200 + objectReference: {fileID: 0} + - target: {fileID: 4491355866364659447, guid: 2307f223279813546a43b221ddd496cc, + type: 3} + propertyPath: m_LocalPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4491355866364659447, guid: 2307f223279813546a43b221ddd496cc, + type: 3} + propertyPath: m_LocalPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4491355866364659447, guid: 2307f223279813546a43b221ddd496cc, + type: 3} + propertyPath: m_LocalPosition.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4491355866364659447, guid: 2307f223279813546a43b221ddd496cc, + type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 4491355866364659447, guid: 2307f223279813546a43b221ddd496cc, + type: 3} + propertyPath: m_LocalRotation.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4491355866364659447, guid: 2307f223279813546a43b221ddd496cc, + type: 3} + propertyPath: m_LocalRotation.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4491355866364659447, guid: 2307f223279813546a43b221ddd496cc, + type: 3} + propertyPath: m_LocalRotation.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4491355866364659447, guid: 2307f223279813546a43b221ddd496cc, + type: 3} + propertyPath: m_AnchoredPosition.x + value: -200 + objectReference: {fileID: 0} + - target: {fileID: 4491355866364659447, guid: 2307f223279813546a43b221ddd496cc, + type: 3} + propertyPath: m_AnchoredPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4491355866364659447, guid: 2307f223279813546a43b221ddd496cc, + type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4491355866364659447, guid: 2307f223279813546a43b221ddd496cc, + type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4491355866364659447, guid: 2307f223279813546a43b221ddd496cc, + type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: 2307f223279813546a43b221ddd496cc, type: 3} +--- !u!224 &7300278248921280140 stripped +RectTransform: + m_CorrespondingSourceObject: {fileID: 4491355866364659447, guid: 2307f223279813546a43b221ddd496cc, + type: 3} + m_PrefabInstance: {fileID: 6564924713997363323} + m_PrefabAsset: {fileID: 0} diff --git a/Assets/GameMain/UI/UIForms/MainForm.prefab.meta b/Assets/GameMain/UI/UIForms/MainForm.prefab.meta new file mode 100644 index 0000000..408da5c --- /dev/null +++ b/Assets/GameMain/UI/UIForms/MainForm.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: a78dfcd3d1efaa3409e9ef645f8d68c1 +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameMain/UI/UIItems/CommonButton.prefab b/Assets/GameMain/UI/UIItems/CommonButton.prefab index ded017f..acb61d7 100644 --- a/Assets/GameMain/UI/UIItems/CommonButton.prefab +++ b/Assets/GameMain/UI/UIItems/CommonButton.prefab @@ -52,10 +52,46 @@ MonoBehaviour: m_EditorClassIdentifier: _onHover: m_PersistentCalls: - m_Calls: [] + m_Calls: + - m_Target: {fileID: 0} + m_TargetAssemblyTypeName: GeometryTD.UI.UGuiForm, Assembly-CSharp + m_MethodName: PlayUISound + m_Mode: 3 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 10000 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 _onClick: m_PersistentCalls: - m_Calls: [] + m_Calls: + - m_Target: {fileID: 0} + m_TargetAssemblyTypeName: GeometryTD.UI.UGuiForm, Assembly-CSharp + m_MethodName: PlayUISound + m_Mode: 3 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 10001 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + - m_Target: {fileID: 0} + m_TargetAssemblyTypeName: + m_MethodName: + m_Mode: 0 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 _onHoverEnd: m_PersistentCalls: m_Calls: [] diff --git a/Assets/Launcher.unity b/Assets/Launcher.unity index a49f022..bbec1eb 100644 --- a/Assets/Launcher.unity +++ b/Assets/Launcher.unity @@ -157,6 +157,7 @@ Transform: - {fileID: 1549230541} - {fileID: 1758164286} - {fileID: 2007255511} + - {fileID: 428539048} m_Father: {fileID: 1852670053} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &120093239 @@ -706,6 +707,56 @@ Transform: type: 3} m_PrefabInstance: {fileID: 343730742} m_PrefabAsset: {fileID: 0} +--- !u!1 &428539047 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 428539048} + - component: {fileID: 428539049} + m_Layer: 0 + m_Name: ResolutionAdapter + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &428539048 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 428539047} + serializedVersion: 2 + 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: 119167776} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &428539049 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 428539047} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 10f174db309f41b9abaf60bc291fbb2c, type: 3} + m_Name: + m_EditorClassIdentifier: + _referenceResolution: {x: 2560, y: 1600} + _adaptUiCanvasToViewport: 1 + _enableBlackMask: 1 + _uiRoots: + - {fileID: 1576232203} + - {fileID: 1454214587} --- !u!4 &432952642 stripped Transform: m_CorrespondingSourceObject: {fileID: 430602, guid: adb3eb1c35fcff14f89fba7b05c9d71c, @@ -1022,7 +1073,7 @@ MonoBehaviour: m_UiScaleMode: 1 m_ReferencePixelsPerUnit: 100 m_ScaleFactor: 1 - m_ReferenceResolution: {x: 2560, y: 1600} + m_ReferenceResolution: {x: 2868, y: 1320} m_ScreenMatchMode: 0 m_MatchWidthOrHeight: 0 m_PhysicalUnit: 3 diff --git a/docs/TODO.md b/docs/TODO.md index 9e82dc6..7529ff7 100644 --- a/docs/TODO.md +++ b/docs/TODO.md @@ -71,3 +71,9 @@ | [ ] | D-06 | P1 | 事件池按期望值分层(高风险/低风险/功能型) | `docs/EventDesign.md`
`Assets/GameMain/DataTables/*.txt` | 三类事件都可稳定出现,且选择差异明显 | | [ ] | D-07 | P1 | 主题地图反制机制(每主题至少 2 个可用对策) | `Assets/GameMain/Scripts/Entity/`
`Assets/GameMain/Scripts/Scene/`
`Assets/GameMain/DataTables/*.txt` | 火山与山地都存在明确反制构筑,UI 有可读提示 | | [ ] | D-08 | P0 | 先定义数值预算(经济/敌强/掉落)再调参 | `docs/NumericBudget.md`
`Assets/GameMain/DataTables/*.txt` | 关键曲线有目标区间,3 局测试结果可与目标对比复盘 | + +## 小目标 +1. GameHud:游戏内的 UI,展示当前的金币数 +2. CombatHud:战斗场景的 UI,展示关卡相关信息 + - 硬币数:Coin + - 关卡当前波次与总波次(1/5 -> 12/无限) \ No newline at end of file