diff --git a/Assets/Scripts/Utils/UITools.meta b/Assets/Scripts/Utils/UITools.meta new file mode 100644 index 00000000..ed07315a --- /dev/null +++ b/Assets/Scripts/Utils/UITools.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d1d32f0cf350541f7be719b30527a629 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Utils/UITools/HUDBase.cs b/Assets/Scripts/Utils/UITools/HUDBase.cs new file mode 100644 index 00000000..d66cd0d7 --- /dev/null +++ b/Assets/Scripts/Utils/UITools/HUDBase.cs @@ -0,0 +1,106 @@ +using System; +using System.Collections; +using UnityEngine; +using UnityEngine.UI; + +public class HUDBase : MonoBehaviour +{ + public Action DelDestroy; + + public bool HasTarget => mTargetTrans != null; + public Transform TargetTrans => mTargetTrans; + + protected RectTransform mRectTrans = null; + + protected Transform mTargetTrans = null; + protected Canvas mRootCanvas = null; + protected Camera mCamera = null; + protected float mHOffset; + protected bool mIsActive = false; + + private void Awake() + { + mRectTrans = GetComponent(); + if (mRectTrans == null) + { + Debug.LogError("RectTransform is invalid."); + return; + } + + OnAwake(); + } + + public void Init(Transform pTargetTrans, Canvas pRootCanvas, Camera pCamera, float pHOffset) + { + if (pTargetTrans == null) + { + Debug.LogError("Target is invalid."); + return; + } + + mTargetTrans = pTargetTrans; + mRootCanvas = pRootCanvas; + mCamera = pCamera; + mHOffset = pHOffset; + mIsActive = true; + + Refresh(); + + OnInit(); + } + + public void Refresh() + { + if (!HasTarget || mCamera == null) + return; + + Vector3 worldPosition = mTargetTrans.position + Vector3.up * mHOffset; + Vector3 screenPosition = mCamera.WorldToScreenPoint(worldPosition); + + Vector2 position; + if (RectTransformUtility.ScreenPointToLocalPointInRectangle((RectTransform)mRootCanvas.transform, screenPosition, mRootCanvas.worldCamera, out position)) + { + mRectTrans.localPosition = position; + } + } + + public void RefreshHeight(float pHeight) + { + mHOffset = pHeight; + Refresh(); + } + + public void Destroy() + { + if (!mIsActive) + return; + + mIsActive = false; + + ResetTarget(null); + OnDestroy(); + + DelDestroy?.Invoke(this); + DelDestroy = null; + } + + public virtual void ResetTarget(Transform pTargetTrans) + { + mTargetTrans = pTargetTrans; + } + + protected virtual void OnAwake() + { + + } + + protected virtual void OnInit() + { + + } + + protected virtual void OnDestroy() + { + + } +} \ No newline at end of file diff --git a/Assets/Scripts/Utils/UITools/HUDBase.cs.meta b/Assets/Scripts/Utils/UITools/HUDBase.cs.meta new file mode 100644 index 00000000..210b52bf --- /dev/null +++ b/Assets/Scripts/Utils/UITools/HUDBase.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 767f12cfc20d24c03969e6b6aea03249 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Utils/UITools/Hole.meta b/Assets/Scripts/Utils/UITools/Hole.meta new file mode 100644 index 00000000..2dc7fde2 --- /dev/null +++ b/Assets/Scripts/Utils/UITools/Hole.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d07c34a5adc0c4328bdaba04738ca8d5 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Utils/UITools/Hole/Hole.cs b/Assets/Scripts/Utils/UITools/Hole/Hole.cs new file mode 100644 index 00000000..2beeb4ec --- /dev/null +++ b/Assets/Scripts/Utils/UITools/Hole/Hole.cs @@ -0,0 +1,16 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.UI; + +public class Hole : Mask +{ + public override bool IsRaycastLocationValid(Vector2 sp, Camera eventCamera) + { + return false; + if (!isActiveAndEnabled) + return true; + + //return !RectTransformUtility.RectangleContainsScreenPoint(rectTransform, sp, eventCamera); + } +} \ No newline at end of file diff --git a/Assets/Scripts/Utils/UITools/Hole/Hole.cs.meta b/Assets/Scripts/Utils/UITools/Hole/Hole.cs.meta new file mode 100644 index 00000000..725e3d22 --- /dev/null +++ b/Assets/Scripts/Utils/UITools/Hole/Hole.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1fe0f1b949e1542b0ab856e2389d3d08 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Utils/UITools/Hole/HoleImage.cs b/Assets/Scripts/Utils/UITools/Hole/HoleImage.cs new file mode 100644 index 00000000..50966785 --- /dev/null +++ b/Assets/Scripts/Utils/UITools/Hole/HoleImage.cs @@ -0,0 +1,32 @@ +using UnityEngine; +using UnityEngine.Rendering; +using UnityEngine.UI; + +public class HoleImage : Image +{ + public override Material GetModifiedMaterial(Material baseMaterial) + { + var toUse = baseMaterial; + + if (m_ShouldRecalculateStencil) + { + var rootCanvas = MaskUtilities.FindRootSortOverrideCanvas(transform); + m_StencilValue = maskable ? MaskUtilities.GetStencilDepth(transform, rootCanvas) : 0; + m_ShouldRecalculateStencil = false; + } + + // if we have a enabled Mask component then it will + // generate the mask material. This is an optimisation + // it adds some coupling between components though :( + + Mask maskComponent = GetComponent(); + if (m_StencilValue > 0 && (maskComponent == null || !maskComponent.IsActive())) + { + var maskMat = StencilMaterial.Add(toUse, (1 << m_StencilValue) - 1, StencilOp.Keep, CompareFunction.NotEqual, ColorWriteMask.All, (1 << m_StencilValue) - 1, 0); + StencilMaterial.Remove(m_MaskMaterial); + m_MaskMaterial = maskMat; + toUse = m_MaskMaterial; + } + return toUse; + } +} \ No newline at end of file diff --git a/Assets/Scripts/Utils/UITools/Hole/HoleImage.cs.meta b/Assets/Scripts/Utils/UITools/Hole/HoleImage.cs.meta new file mode 100644 index 00000000..9976100c --- /dev/null +++ b/Assets/Scripts/Utils/UITools/Hole/HoleImage.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 018dc5431b7d44eacb0409152897f33c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Utils/UITools/ResShower.cs b/Assets/Scripts/Utils/UITools/ResShower.cs new file mode 100644 index 00000000..1287a6d2 --- /dev/null +++ b/Assets/Scripts/Utils/UITools/ResShower.cs @@ -0,0 +1,152 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.UI; +using DG.Tweening; + +public class ResShower : MonoBehaviour +{ + [SerializeField] GameObject mTplCurrency; + [SerializeField] RectTransform mRctCurrencyIcon; + [SerializeField] Text mTxtCurrency; + [SerializeField] Text mTxtCurrencyChange; + + Sequence mPopTweenSequence; + Sequence mFadeTweenSequence; + + private Camera mMainCam; + private Camera mUICam; + + private int mFinalCount; + + public void SetCamera(Camera pMainCam, Camera pUICam = null) + { + mMainCam = pMainCam; + mUICam = pUICam; + } + + public void FlyCoins(Vector3 pWorldPos, int pFlyCount, int pCoinCount, int pFinalCount) + { + mFinalCount = pFinalCount; + float tFlyDelta = 0.05f; + + for (int i = 0; i < pFlyCount; i++) + { + FlyOneCoin(pWorldPos, tFlyDelta * i); + } + + PopCoinChange(pCoinCount); + StartCoroutine(SeperatlyAddCoin(tFlyDelta, pFlyCount, pCoinCount)); + } + + private void FlyOneCoin(Vector3 pWorldPos, float pDelay) + { + Vector2 tStartPos = GetLocalPosInRect(pWorldPos, mRctCurrencyIcon, mMainCam, mUICam); + RectTransform tFlyCoin = Instantiate(mTplCurrency).GetComponent(); + tFlyCoin.gameObject.SetActive(true); + tFlyCoin.SetParent(mRctCurrencyIcon, false); + tFlyCoin.localScale = Vector3.one; + tFlyCoin.anchoredPosition = tStartPos; + + Vector3 tJumpPos = tStartPos + new Vector2(UnityEngine.Random.Range(-150f, 150f), UnityEngine.Random.Range(-80f, -120f)); + tFlyCoin.DOJumpAnchorPos(tJumpPos, 300, 1, 0.5f); + + tFlyCoin.DOAnchorPos(Vector2.zero, 0.5f).SetDelay(0.5f + pDelay).SetEase(Ease.Linear).onComplete = () => + { + Destroy(tFlyCoin.gameObject); + }; + } + + private IEnumerator SeperatlyAddCoin(float pFlyDelta, int pFlyCount, int pCoinCount) + { + int tCoinPerFly = 1, tCoinLastFly = 1; + if (pCoinCount > pFlyCount) + { + tCoinPerFly = pCoinCount / pFlyCount; + tCoinLastFly = pCoinCount - tCoinPerFly * pFlyCount; + if (tCoinLastFly == 0) + tCoinLastFly = tCoinPerFly; + } + + yield return new WaitForSeconds(1f); + + for (int i = 0; i < pFlyCount; i++) + { + int tAddCount = i < pFlyCount - 1 ? tCoinPerFly : tCoinLastFly; + RefreshCoins(tAddCount); + if (i == pFlyCount - 1) + { + RefreshCoinsWithoutAni(); + } + yield return new WaitForSeconds(pFlyDelta); + } + } + + public void RefreshCoins(int pAddCount) + { + int tCurrentNum = int.Parse(mTxtCurrency.text); + tCurrentNum += pAddCount; + mTxtCurrency.text = tCurrentNum.ToString(); + + } + + public void RefreshCoinsWithoutAni() + { + mTxtCurrency.text = mFinalCount.ToString(); + //mRectCoinIcon.anchoredPosition = new Vector2(-(mTxtCoin.preferredWidth), mRectCoinIcon.anchoredPosition.y); + } + + public void PopCoinChange(int pChangedNum) + { + mTxtCurrencyChange.text = pChangedNum >= 0 ? "+" + pChangedNum.ToString() : pChangedNum.ToString(); + Color tColor = pChangedNum > 0 ? Color.green : Color.red; + tColor.a = 0; + mTxtCurrencyChange.color = tColor; + mTxtCurrencyChange.rectTransform.anchoredPosition = new Vector2(32, 0); + + mTxtCurrencyChange.rectTransform.DOKill(); + mPopTweenSequence = DOTween.Sequence(); + mPopTweenSequence.Append(mTxtCurrencyChange.rectTransform.DOAnchorPosY(-100, 0.3f).SetEase(Ease.OutBounce)); + mPopTweenSequence.AppendInterval(0.8f); + mPopTweenSequence.Append(mTxtCurrencyChange.rectTransform.DOAnchorPosY(0, 0.3f).SetEase(Ease.InBounce)); + + mTxtCurrencyChange.DOKill(); + mFadeTweenSequence = DOTween.Sequence(); + mFadeTweenSequence.Append(mTxtCurrencyChange.DOFade(1, 0.3f)); + mFadeTweenSequence.AppendInterval(0.8f); + mFadeTweenSequence.Append(mTxtCurrencyChange.DOFade(0, 0.3f)); + + mPopTweenSequence.Restart(); + mFadeTweenSequence.Restart(); + } + + private void PunchIcon(RectTransform pRect) + { + pRect.localScale = Vector3.one; + pRect.DOKill(); + pRect.DOPunchScale(Vector3.one * 1.2f, 0.3f); + } + + public void ShowNotEnoughCoin() + { + mTxtCurrency.color = Color.white; + mTxtCurrency.rectTransform.anchoredPosition = new Vector2(32, 0); + + mTxtCurrency.color = Color.red; + mTxtCurrency.rectTransform.DOKill(); + mTxtCurrency.rectTransform.DOPunchAnchorPos(new Vector2(0, 15), 0.5f).onComplete = () => + { + mTxtCurrency.color = Color.white; + mTxtCurrency.rectTransform.anchoredPosition = new Vector2(32, 0); + }; + } + + public Vector2 GetLocalPosInRect(Vector3 pWorldPos, RectTransform pRect, Camera pMainCam, Camera pUICam = null) + { + Vector2 tScreenPos = RectTransformUtility.WorldToScreenPoint(pMainCam, pWorldPos); + Vector2 tLocalPos = Vector2.zero; + RectTransformUtility.ScreenPointToLocalPointInRectangle(pRect, tScreenPos, pUICam, out tLocalPos); + + return tLocalPos; + } +} diff --git a/Assets/Scripts/Utils/UITools/ResShower.cs.meta b/Assets/Scripts/Utils/UITools/ResShower.cs.meta new file mode 100644 index 00000000..d555b761 --- /dev/null +++ b/Assets/Scripts/Utils/UITools/ResShower.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bfbba84a4acd64888a1567f9e154f372 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Utils/UITools/UIToggleSwap.cs b/Assets/Scripts/Utils/UITools/UIToggleSwap.cs new file mode 100644 index 00000000..43bd1977 --- /dev/null +++ b/Assets/Scripts/Utils/UITools/UIToggleSwap.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.UI; + +[RequireComponent(typeof(Button))] +public class UIToggleSwap : MonoBehaviour +{ + public event Action OnSwitch; + + public bool IsOn + { + get + { + return mIsOn; + } + set + { + mIsOn = value; + if (mSignOn != null) mSignOn.SetActive(mIsOn); + if (mSignOff != null) mSignOff.SetActive(!mIsOn); + + OnSwitch?.Invoke(mIsOn); + } + } + + [SerializeField] GameObject mSignOn; + [SerializeField] GameObject mSignOff; + + private Button mBtnClick; + private bool mIsOn; + + private void Awake() + { + mBtnClick = GetComponent