using asap.core; using cfg; using DG.Tweening; using GameCore; using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; namespace game { public class ScratchCard : MonoBehaviour, IBeginDragHandler, IDragHandler { [Header("Mask")] public List m_MaskList = new List(); [SerializeField] private int m_CDFrame = 5; [SerializeField] private string m_Ticket_Mask_Texture_Name = "sp_scratchticket_ticket_mask"; [Header("Brush")] [SerializeField] private EditablePolygon m_OperatingArea; [SerializeField] private GameObject m_BrushRoot; [SerializeField] private Image m_Brush; [SerializeField] private float m_BrushDurationTime = 1.0f; [SerializeField] private float m_BrushSpeed = 1000.0f; [SerializeField] private Material m_BrushMaterial; [SerializeField] private Vector2 m_BrushSize = new Vector2(50f, 50f); [SerializeField] private int m_InterpolationMaxCount = 4; [SerializeField] private int m_InterpolationMinDistance = 8; [SerializeField] private EventScratchTicketScratchType m_ScratchType = EventScratchTicketScratchType.TypeInvalid; [Header("Animation")] [SerializeField] private Animation m_Animation; [SerializeField] private string m_Anim_Ticket_Out = "ticket_out"; [SerializeField] private float m_Anim_Ticket_Out_DurationTime = 1.1f; [SerializeField] private CanvasGroup m_ShadowCanvasGroup; [SerializeField] private CanvasGroup m_TicketCanvasGroup; [Header("音效")] [SerializeField] private List m_ScratchOutPlaySoundList = new List(); [SerializeField] private List m_ScratchOutPlaySoundTimeList = new List(); [Header("Toast相关")] [SerializeField] private float m_ToastIntervalTime = 1.0f; private int m_CumulativeFrame = 0; private int m_MaskIndex = 0; private float m_BrushCumulativeTime = 0f; #region 音效相关 private bool m_IsPlayingSound = false; private float m_PlayingSoundTime = 0; private float m_PlayingSoundCumulativeTime = 0f; private void PlayScratchSound() { int count = m_ScratchOutPlaySoundList.Count; if (count < 1) return; foreach (var item in m_ScratchOutPlaySoundList) { if (item.gameObject.activeSelf) { item.gameObject.SetActive(false); } } int index = UnityEngine.Random.Range(0, count); m_IsPlayingSound = true; m_PlayingSoundTime = m_ScratchOutPlaySoundTimeList[index]; m_PlayingSoundCumulativeTime = 0f; m_ScratchOutPlaySoundList[index].gameObject.SetActive(true); } private void StopScratchSound() { foreach (var item in m_ScratchOutPlaySoundList) { item.gameObject.SetActive(false); } m_IsPlayingSound = false; m_PlayingSoundTime = float.MaxValue; m_PlayingSoundCumulativeTime = float.MinValue; } #endregion #region ScratchCardMask 相关 public void InitMaskList() { foreach (var item in m_MaskList) { item.InitMaskUGUI(m_BrushMaterial, m_BrushSize, m_InterpolationMaxCount, m_InterpolationMinDistance); //item.RevealProgressChanged = OnRevealProgressChangedCallback; } } private void OnRevealProgressChangedCallback(ScratchCardMask mask, float progress, bool isRevealed) { //Debug.LogError("--- ScratchCard OnRevealProgressChangedCallback mask:" + mask + ", progress:" + progress + ", isRevealed:" + isRevealed); bool flag = true; foreach (var item in m_MaskList) { if (!item.IsRevealed()) { flag = false; break; } } //if (flag) //{ // Debug.LogError("--- they have all revealed"); //} //else //{ // Debug.LogError("--- they have not all revealed"); //} } #endregion #region Brush 相关 private bool m_IsBrushPainting = false; public void SetBrushPosition(Vector2 screenPosition) { if (!m_OperatingArea.ContainsPoint(screenPosition)) { return; } RectTransformUtility.ScreenPointToLocalPointInRectangle( transform as RectTransform, screenPosition, UIManager.Instance.UICanvas.worldCamera, out Vector2 localPoint); if (!m_Brush.gameObject.activeSelf) { m_Brush.gameObject.SetActive(true); m_Brush.rectTransform.localPosition = localPoint; } float distance = Vector2.Distance(m_Brush.rectTransform.localPosition, localPoint); float time = distance / m_BrushSpeed; m_Brush.rectTransform.DOKill(); m_Brush.rectTransform.DOLocalMove(localPoint, time).SetEase(Ease.Linear); //m_BrushCumulativeTime = 0f; } private void OnMaskBeginDrag() { Vector2 screenPoint = RectTransformUtility.WorldToScreenPoint(UIManager.Instance.UICanvas.worldCamera, m_Brush.transform.position); foreach (var item in m_MaskList) { item.OnMaskBeginDrag(screenPoint); } } private void OnMaskDrag() { bool flag = false; Vector2 screenPoint = RectTransformUtility.WorldToScreenPoint(UIManager.Instance.UICanvas.worldCamera, m_Brush.transform.position); foreach (var item in m_MaskList) { if (item.OnMaskDrag(screenPoint)) { flag = true; } } //if (flag) //{ // bool isAllRevealed = true; // foreach (var item in m_MaskList) // { // if (!item.IsRevealed()) // { // isAllRevealed = false; // break; // } // } // if (isAllRevealed) // { // Debug.LogError("=== ok"); // } //} } #endregion #region IBeginDragHandler + IDragHandler 相关 public void OnBeginDrag(PointerEventData eventData) { if (m_ScratchType != EventScratchTicketScratchType.TypeScratch1) return; //Debug.LogWarning("---- ScratchCard OnBeginDrag"); SetBrushPosition(eventData.position); m_BrushCumulativeTime = 0f; //foreach (var item in m_MaskList) //{ // item.OnMaskBeginDrag(eventData.position); //} } public void OnDrag(PointerEventData eventData) { if (m_ScratchType != EventScratchTicketScratchType.TypeScratch1) return; //Debug.LogWarning("---- ScratchCard OnDrag"); SetBrushPosition(eventData.position); m_BrushCumulativeTime = 0f; //bool flag = false; //foreach (var item in m_MaskList) //{ // if (item.OnMaskDrag(eventData.position)) // { // flag = true; // } //} //if (flag) //{ // bool isAllRevealed = true; // foreach (var item in m_MaskList) // { // if (!item.IsRevealed()) // { // isAllRevealed = false; // break; // } // } // if (isAllRevealed) // { // Debug.LogError("=== ok"); // } //} } #endregion #region TypeScratch1 动画等相关 private IEnumerator PlayTicketOutAnim(EventScratchTicketScratchType scratchType) { // 播放 m_Anim_Ticket_Out m_Animation.Play(m_Anim_Ticket_Out); yield return new WaitForSeconds(m_Anim_Ticket_Out_DurationTime); // 重置 ScratchCard 图片资源,并将ticket和shadow的alpha设置为1(显示) foreach (var item in m_MaskList) { item.Restore(); //item.Reload(); } m_ShadowCanvasGroup.alpha = 1.0f; m_TicketCanvasGroup.alpha = 1.0f; if (scratchType == EventScratchTicketScratchType.TypeScratch1) { FishingScratchTicketAct.Publish(new EventScratchTicketPanelPlayEndAnimData() { ScratchType = scratchType }); } else if (scratchType == EventScratchTicketScratchType.TypeScratch5) { FishingScratchTicketAct.Publish(new EventScratchTicketPlayScratchType5()); } } private IEnumerator PlayCardRevealedAnimInScratch1(EventScratchTicketScratchType scratchType) { // 隐藏笔刷 m_Brush.gameObject.SetActive(false); // 确认奖励 EventScratchCard scratchCard = m_DataManager.GetCurrentEventScratchCard(); if (scratchCard.DropReward == 0) { // 空奖 FishingScratchTicketAct.Publish(new EventScratchTicketRewardEmptyData() { ScratchType = EventScratchTicketScratchType.TypeScratch1 }); } else { // 播放 m_Anim_Ticket_Out m_Animation.Play(m_Anim_Ticket_Out); yield return new WaitForSeconds(m_Anim_Ticket_Out_DurationTime); // 重置 ScratchCard 图片资源,并将ticket和shadow的alpha设置为1(显示) foreach (var item in m_MaskList) { item.Restore(); //item.Reload(); } m_ShadowCanvasGroup.alpha = 1.0f; m_TicketCanvasGroup.alpha = 1.0f; // RewardFly FishingScratchTicketAct.Publish(new EventScratchTicketStampRewardFlyData() { ScratchType = scratchType, SrcPosition = ticket_reward.transform.position, LocalScale = ticket_reward.transform.localScale, IconSize = ticket_reward.rectTransform.sizeDelta.x }); } } #endregion #region TypeScratch5 动画等相关 private IEnumerator PlayCardRevealedAnimInScratch5(EventScratchTicketScratchType scratchType) { // 隐藏笔刷 m_Brush.gameObject.SetActive(false); // 确认奖励 EventScratchCard scratchCard = m_DataManager.GetCurrentEventScratchCard(); if (scratchCard.DropReward == 0) { // 空奖 FishingScratchTicketAct.Publish(new EventScratchTicketRewardEmptyData() { ScratchType = scratchType }); } else { // 播放 m_Anim_Ticket_Out m_Animation.Play(m_Anim_Ticket_Out); yield return new WaitForSeconds(m_Anim_Ticket_Out_DurationTime); // 重置 ScratchCard 图片资源,并将ticket和shadow的alpha设置为1(显示) foreach (var item in m_MaskList) { item.Restore(); //item.Reload(); } m_ShadowCanvasGroup.alpha = 1.0f; m_TicketCanvasGroup.alpha = 1.0f; FishingScratchTicketAct.Publish(new EventScratchTicketPlayScratchType5()); } } #endregion #region 事件 private void InitEvent() { FishingScratchTicketAct.Subscribe(ChangeScratchType); FishingScratchTicketAct.Subscribe(OnScratchCardRevealedAll); FishingScratchTicketAct.Subscribe(UpdateEventScratchCardData); FishingScratchTicketAct.Subscribe(OnEventScratchTicketOutDataListener); } private void OnEventScratchTicketOutDataListener(EventScratchTicketOutData data) { StartCoroutine(PlayTicketOutAnim(data.ScratchType)); } private void UpdateEventScratchCardData(EventScratchTicketUpdateEventScratchCardData data) { var scratchCard = m_DataManager.GetCurrentEventScratchCard(); if (scratchCard == null) return; var sprite = m_DataManager.GetSprite(scratchCard.Card); ticket_reward.sprite = sprite; ticket_maskCore.UpdateScratchCardMask(sprite.texture); ticket_maskCore.Restore(); ticket_maskCore.SetThreshold(scratchCard.CorePercent); ticket_mask.Restore(); } private void OnScratchCardRevealedAll(EventScratchTicketRevealedAllData data) { StopScratchSound(); EventScratchCard scratchCard = m_DataManager.GetCurrentEventScratchCard(); if (scratchCard.DropReward > 0) { m_DataManager.AddScratchStamp(scratchCard.ID); } if (data.ScratchType == EventScratchTicketScratchType.TypeScratch1) { StartCoroutine(PlayCardRevealedAnimInScratch1(EventScratchTicketScratchType.TypeScratch1)); } else if (data.ScratchType == EventScratchTicketScratchType.TypeScratch5) { StartCoroutine(PlayCardRevealedAnimInScratch5(EventScratchTicketScratchType.TypeScratch5)); } } private void ChangeScratchType(EventScratchTicketChangeScratchTypeData data) { m_ScratchType = data.ScratchType; if (m_ScratchType != EventScratchTicketScratchType.TypeInvalid) { m_BrushRoot.SetActive(true); m_Brush.gameObject.SetActive(false); } } #endregion #region UI private Image ticket_reward; private ScratchCardMaskUGUI ticket_maskCore; private ScratchCardMaskUGUI ticket_mask; private void InitUI() { ticket_reward = transform.Find("ticket_reward").GetComponent(); ticket_maskCore = transform.Find("ticket_maskCore").GetComponent(); ticket_mask = transform.Find("ticket_mask").GetComponent(); } public void RefreshData() { UpdateEventScratchCardData(null); } #endregion #region 生命周期 private EventScratchTicketDataManager m_DataManager; // Start is called before the first frame update void Start() { m_DataManager = GContext.container.Resolve(); InitUI(); InitMaskList(); InitEvent(); RefreshData(); } private bool m_IsToasting = false; private float m_CumulativeToastIntervalTime = 0f; private void Update() { if (m_ScratchType == EventScratchTicketScratchType.TypeInvalid) { if (Input.GetMouseButtonDown(0) || Input.GetMouseButton(0)) { if (!m_IsToasting && m_OperatingArea.ContainsPoint(Input.mousePosition)) { ToastPanel.Show(LocalizationMgr.GetText("UI_EventScratchTicketPanel_9")); m_IsToasting = true; m_CumulativeToastIntervalTime = 0f; } } if (m_IsToasting) { if (m_CumulativeToastIntervalTime >= m_ToastIntervalTime) { m_CumulativeToastIntervalTime = 0f; m_IsToasting = false; } else { m_CumulativeToastIntervalTime += Time.deltaTime; } } } if (m_ScratchType == EventScratchTicketScratchType.TypeScratch1) { bool flag = false; if (!Input.GetMouseButtonDown(0) && !Input.GetMouseButton(0)) { flag = true; } else if (!m_OperatingArea.ContainsPoint(Input.mousePosition)) { flag = true; } if (flag) { if (m_BrushCumulativeTime >= m_BrushDurationTime) { if (m_Brush.gameObject.activeSelf) { m_Brush.gameObject.SetActive(false); m_IsBrushPainting = false; StopScratchSound(); } } else { m_BrushCumulativeTime += Time.deltaTime; } } } if (m_ScratchType != EventScratchTicketScratchType.TypeInvalid) { if (m_Brush.gameObject.activeSelf) { if (m_IsPlayingSound) { m_PlayingSoundCumulativeTime += Time.deltaTime; if (m_PlayingSoundCumulativeTime >= m_PlayingSoundTime) { PlayScratchSound(); } } else { PlayScratchSound(); } if (m_IsBrushPainting == false) { m_IsBrushPainting = true; OnMaskBeginDrag(); } else { OnMaskDrag(); } } } } private void LateUpdate() { if (m_ScratchType == EventScratchTicketScratchType.TypeInvalid || m_ScratchType == EventScratchTicketScratchType.TypeTemporary) return; if (m_BrushRoot.activeInHierarchy == false || m_Brush.gameObject.activeSelf == false) return; if (m_CumulativeFrame > m_CDFrame) { m_CumulativeFrame = 1; m_MaskIndex = 0; } else { ++m_CumulativeFrame; } int count = m_MaskList.Count; int step = Mathf.CeilToInt((float)count / m_CDFrame); int endIndex = m_MaskIndex + step; while (m_MaskIndex < count && m_MaskIndex < endIndex) { m_MaskList[m_MaskIndex].UpdateTempTexture(); ++m_MaskIndex; } bool flag = true; foreach (var mask in m_MaskList) { if (!mask.IsRevealed()) { flag = false; break; } } if (flag) { //Debug.LogError("--- all ok"); FishingScratchTicketAct.Publish(new EventScratchTicketRevealedAllData { ScratchType = m_ScratchType }); m_ScratchType = EventScratchTicketScratchType.TypeTemporary; } } #endregion } }