/**
* 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
}
}