/** * Copyright 2019 The Knights Of Unity, created by Pawel Stolarczyk * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using System.Collections.Generic; using DemoGame.Scripts.Gameplay.Cards; using DemoGame.Scripts.Gameplay.NetworkCommunication; using DemoGame.Scripts.Gameplay.NetworkCommunication.MatchStates; using DemoGame.Scripts.Session; using UnityEngine; using UnityEngine.UI; namespace DemoGame.Scripts.Gameplay.Hands { /// /// Panel displaying all cards currently held by the local user. /// public class HandPanel : MonoBehaviour { #region Fields /// /// Parent transform all dragged cards are attached to during drag. /// This will ensure they will be always on top of other cards. /// [SerializeField] private Transform _dragParent = null; /// /// Point from which cards are being drawn. /// [SerializeField] private Transform _drawPosition = null; /// /// Reference to canvas scaler, used to calculate the real mouse position on canvas. /// [SerializeField] private CanvasScaler _canvasScaler = null; /// /// Card prefab displayed in user's hand. /// [SerializeField] private CardGrabber _inGameCardPrefab = null; /// /// List of available card slots in hand. /// [SerializeField] private List _cardSlots = null; #region Drop Regions [SerializeField] private RectTransform _handRegion = null; [SerializeField] private RectTransform _allyHalf = null; [SerializeField] private RectTransform _allySpawn = null; [SerializeField] private RectTransform _enemyHalf = null; [SerializeField] private RectTransform _enemySpawn = null; #endregion /// /// List of cards being currently in user's hand. /// private List _cardsInHand = new List(); #endregion #region Events /// /// Invoked whenever user plays a card. /// public event Action OnCardPlayed; /// /// Invoked whenever user clicks on a card in hand. /// public event Action OnCardGrabbed; /// /// Invoked whenever user returns grabbed card to their hand. /// public event Action OnCardReturned; #endregion #region Properties /// /// Reference to card being currently grabbed. /// public CardGrabber CurrentlyGrabbedCard { get; private set; } #endregion #region Mono /// /// Subscribes to event. /// private void Awake() { MatchCommunicationManager.Instance.OnCardCancelled += CancelPlay; } #endregion #region Methods /// /// Creates instance and initializes it. /// public CardGrabber DrawCard(Card card, int slotId) { Transform slot = _cardSlots[slotId]; RectTransform region = SelectRegion(card); CardGrabber cardGrabber = Instantiate(_inGameCardPrefab, slot, false); cardGrabber.transform.position = _drawPosition.position; cardGrabber.Initialize(card, slot, _handRegion, region, _canvasScaler); cardGrabber.OnCardPlayed += PlayCard; cardGrabber.OnDragStarted += StartCardDrag; cardGrabber.OnCardReturned += ReturnCard; _cardsInHand.Insert(slotId, cardGrabber); return cardGrabber; } /// /// Returns a region based on card info. /// private RectTransform SelectRegion(Card card) { DropRegion dropRegion = card.GetCardInfo().DropRegion; switch (dropRegion) { case DropRegion.WholeMap: return null; case DropRegion.EnemyHalf: return _enemyHalf; case DropRegion.EnemySpawn: return _enemySpawn; case DropRegion.AllyHalf: return _allyHalf; case DropRegion.AllySpawn: return _allySpawn; default: return null; } } /// /// Invoked on card grab. /// private void StartCardDrag(CardGrabber grabber) { grabber.transform.SetParent(_dragParent); CurrentlyGrabbedCard = grabber; OnCardGrabbed?.Invoke(grabber); } /// /// Invoked on card returning to hand. /// private void ReturnCard(CardGrabber grabber) { grabber.transform.SetParent(grabber.Slot); OnCardReturned?.Invoke(grabber); CurrentlyGrabbedCard = null; } /// /// Invoked on card played. /// Sends to host. /// private void PlayCard(CardGrabber grabber, Vector3 dropPosition) { grabber.OnDragStarted -= StartCardDrag; grabber.OnCardReturned -= ReturnCard; grabber.OnCardPlayed -= PlayCard; string id = NakamaSessionManager.Instance.Session.UserId; int index = _cardsInHand.IndexOf(grabber); //_cardsInHand.RemoveAt(index); MatchMessageCardPlayRequest message = new MatchMessageCardPlayRequest( id, grabber.Card, index, dropPosition.x, dropPosition.y, dropPosition.z); OnCardPlayed?.Invoke(message); CurrentlyGrabbedCard = null; //Destroy(grabber.gameObject); } /// /// Prevents given card from being played. /// Returns it to user's hand. /// private void CancelPlay(MatchMessageCardCanceled message) { CardGrabber grabber = _cardsInHand[message.CardSlotIndex]; grabber.OnDragStarted += StartCardDrag; grabber.OnCardReturned += ReturnCard; grabber.OnCardPlayed += PlayCard; grabber.CancelPlay(); } /// /// Removes played card grabber from the game. /// public void ResolveCardPlay(MatchMessageCardPlayed message) { CardGrabber grabber = _cardsInHand[message.CardSlotIndex]; grabber.Resolve(message); _cardsInHand.RemoveAt(message.CardSlotIndex); Destroy(grabber.gameObject); } #endregion } }