This commit is contained in:
yaoyanwei
2025-08-04 16:45:48 +08:00
parent 565aa16389
commit 2f2a601227
2296 changed files with 522745 additions and 93 deletions

View File

@@ -0,0 +1,152 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TcgEngine.Client;
namespace TcgEngine.UI
{
/// <summary>
/// Ability button on a BoardCard, let you activate abilities
/// </summary>
public class AbilityButton : MonoBehaviour
{
public Text text;
public Image focus_highlight;
private Card card;
private AbilityData iability;
private CanvasGroup canvas_group;
private float target_alpha = 0f;
private bool focus = false;
private bool nextfocus = false;
private bool interactable = false;
private static List<AbilityButton> button_list = new List<AbilityButton>();
void Awake()
{
button_list.Add(this);
canvas_group = GetComponent<CanvasGroup>();
canvas_group.alpha = 0f;
if (focus_highlight != null)
focus_highlight.enabled = false;
}
private void OnDestroy()
{
button_list.Remove(this);
}
void Update()
{
canvas_group.alpha = Mathf.MoveTowards(canvas_group.alpha, target_alpha, 5f * Time.deltaTime);
focus = nextfocus;
if (focus_highlight != null && IsVisible())
focus_highlight.enabled = focus && interactable;
}
public void SetAbility(Card card, AbilityData iability)
{
this.card = card;
this.iability = iability;
text.text = iability.title;
if (this.iability.mana_cost > 0)
text.text += " (" + this.iability.mana_cost + ")";
canvas_group.interactable = true;
canvas_group.blocksRaycasts = true;
target_alpha = 1f;
}
public void SetInteractable(bool interact)
{
interactable = interact;
}
public void Hide()
{
if (canvas_group == null)
canvas_group = GetComponent<CanvasGroup>();
this.card = null;
this.iability = null;
canvas_group.interactable = false;
canvas_group.blocksRaycasts = false;
target_alpha = 0f;
}
public void OnClick()
{
if (card != null && iability != null)
{
if (!Tutorial.Get().CanDo(TutoEndTrigger.CastAbility, card))
return;
GameClient.Get().CastAbility(card, iability);
PlayerControls.Get().UnselectAll();
}
}
public AbilityData GetAbility()
{
return iability;
}
public bool IsVisible()
{
return canvas_group.alpha > 0.5f;
}
public bool IsInteractable()
{
return interactable && IsVisible();
}
public void MouseEnter()
{
focus = true;
nextfocus = true;
}
public void MouseExit()
{
nextfocus = false; //Keep it focused 1 more frame to work on mobile
}
public static AbilityButton GetFocus(Vector3 pos, float range = 999f)
{
AbilityButton nearest = null;
float min_dist = range;
foreach (AbilityButton button in button_list)
{
float dist = (button.transform.position - pos).magnitude;
if (button.focus && button.IsVisible() && dist < min_dist)
{
min_dist = dist;
nearest = button;
}
}
return nearest;
}
public static AbilityButton GetNearest(Vector3 pos, float range = 999f)
{
AbilityButton nearest = null;
float min_dist = range;
foreach (AbilityButton button in button_list)
{
float dist = (button.transform.position - pos).magnitude;
if (dist < min_dist)
{
min_dist = dist;
nearest = button;
}
}
return nearest;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4584e4c98c0662b42a3aabdae6d9a1af
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,74 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
using TcgEngine;
namespace TcgEngine.UI
{
/// <summary>
/// Displays an avatar
/// </summary>
public class AvatarUI : MonoBehaviour
{
public UnityAction<AvatarData> onClick;
private Image avatar_img;
private Button avatar_button;
private Sprite default_icon;
private AvatarData avatar;
void Awake()
{
avatar_img = GetComponent<Image>();
avatar_button = GetComponent<Button>();
default_icon = avatar_img.sprite;
if (avatar_button != null)
avatar_button.onClick.AddListener(OnClick);
}
public void SetAvatar(AvatarData avatar)
{
this.avatar = avatar;
avatar_img.enabled = true;
avatar_img.sprite = default_icon;
if (avatar != null)
{
avatar_img.sprite = avatar.avatar;
}
}
public void SetDefaultAvatar()
{
this.avatar = null;
avatar_img.enabled = true;
avatar_img.sprite = default_icon;
}
public void SetImage(Sprite sprite)
{
avatar_img.sprite = sprite;
}
public void Hide()
{
this.avatar = null;
avatar_img.enabled = false;
}
public AvatarData GetAvatar()
{
return avatar;
}
private void OnClick()
{
onClick?.Invoke(avatar);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 81dc47f13cc20f34ca6c7249e36b2206
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,23 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace TcgEngine.UI
{
public class BlackPanel : UIPanel
{
private static BlackPanel instance;
protected override void Awake()
{
base.Awake();
instance = this;
}
public static BlackPanel Get()
{
return instance;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 99a75e5cfba2ed24aa1cc9b9e1ae886f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,28 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
namespace TcgEngine.UI
{
/// <summary>
/// Add sound when clicking on a button
/// </summary>
public class ButtonAudio : MonoBehaviour
{
public AudioClip click_audio;
void Start()
{
Button button = GetComponent<Button>();
if (button != null)
button.onClick.AddListener(OnClick);
}
void OnClick()
{
AudioTool.Get().PlaySFX("ui", click_audio);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c65cf51b063a92646b38136a42dcbed9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,75 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TcgEngine;
namespace TcgEngine.UI
{
/// <summary>
/// Grid of cards in the collection panel
/// </summary>
public class CardGrid : MonoBehaviour
{
private GridLayoutGroup grid;
private RectTransform rect;
void Awake()
{
grid = GetComponent<GridLayoutGroup>();
rect = GetComponent<RectTransform>();
}
public void GetColumnAndRow(out int rows, out int columns)
{
rows = 0;
columns = 0;
if (grid.transform.childCount == 0)
return;
//Get the first child GameObject of the GridLayoutGroup
RectTransform firstChildObj = grid.transform.GetChild(0).GetComponent<RectTransform>();
Vector2 firstChildPos = firstChildObj.anchoredPosition;
bool stopCountingCol = false;
if (firstChildPos.x == 0 && firstChildPos.y == 0)
return;
//Column and row are now 1
rows = 1;
columns = 1;
//Loop through the rest of the child object
for (int i = 1; i < grid.transform.childCount; i++)
{
//Get the next child
RectTransform currentChildObj = grid.transform.GetChild(i).GetComponent<RectTransform>();
Vector2 currentChildPos = currentChildObj.anchoredPosition;
//check if column or row
if (Mathf.Abs(firstChildPos.x - currentChildPos.x) < 0.1f)
{
rows++;
stopCountingCol = true;
}
else
{
if (!stopCountingCol)
columns++;
}
}
}
public GridLayoutGroup GetGrid()
{
return grid;
}
public RectTransform GetRect()
{
return rect;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: edae855830c948f49ade8fe11c1274ed
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,62 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
namespace TcgEngine.UI
{
public class CardMulligan : MonoBehaviour
{
public CardUI card_ui;
public Image x_img;
private Card card;
public UnityAction<CardMulligan> onClick;
private void Awake()
{
if (x_img != null)
x_img.enabled = false;
card_ui.onClick += OnClick;
}
public void SetCard(Card card)
{
this.card = card;
card_ui.SetCard(card.CardData, card.VariantData);
gameObject.SetActive(true);
}
public void SetSelected(bool discard)
{
if (x_img != null)
x_img.enabled = discard;
}
public void Hide()
{
gameObject.SetActive(false);
}
public bool IsSelected()
{
if (x_img != null)
return x_img.enabled;
return false;
}
public Card GetCard()
{
return card;
}
private void OnClick(CardUI card_ui)
{
onClick?.Invoke(this);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 929e92b16c599754f987b3021561b6c4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,121 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TcgEngine.Client;
using TcgEngine;
namespace TcgEngine.UI
{
/// <summary>
/// In the game scene, the CardPreviewUI is what shows the card in big with extra info when hovering a card
/// </summary>
public class CardPreviewUI : MonoBehaviour
{
public UIPanel ui_panel;
public CardUI card_ui;
public Text desc;
public float hover_delay_board = 0.7f;
public float hover_delay_hand = 0.4f;
public float hover_delay_mobile = 0.1f;
public RectTransform[] side_rows;
public StatusLine[] status_lines;
private float preview_timer = 0f;
private Vector2[] start_pos;
private void Start()
{
start_pos = new Vector2[side_rows.Length];
for (int i = 0; i < side_rows.Length; i++)
{
start_pos[i] = side_rows[i].anchoredPosition;
}
}
void Update()
{
if (!GameClient.Get().IsReady())
return;
foreach (StatusLine line in status_lines)
line.Hide();
PlayerControls controls = PlayerControls.Get();
HandCard hcard = HandCard.GetFocus();
BoardCard bcard = BoardCard.GetFocus();
HeroUI hero_ui = HeroUI.GetFocus();
Card histcard = TurnHistoryLine.GetHoverCard();
Card secret_card = SecretIconUI.GetHoverCard();
float delay = hcard != null ? hover_delay_hand : hover_delay_board;
if (GameTool.IsMobile())
delay = hover_delay_mobile;
Card pcard = hcard != null ? hcard?.GetCard() : bcard?.GetFocusCard();
if (pcard == null)
pcard = histcard;
if (pcard == null)
pcard = secret_card;
if (pcard == null)
pcard = hero_ui?.GetCard();
bool hover_only = !Input.GetMouseButton(0) && !HandCardArea.Get().IsDragging();
bool should_show_preview = hover_only && pcard != null && !GameUI.IsUIOpened();
if (should_show_preview)
preview_timer += Time.deltaTime;
else
preview_timer = 0f;
bool show_preview = should_show_preview && preview_timer >= delay;
ui_panel.SetVisible(show_preview);
if (show_preview)
{
CardData icard = pcard.CardData;
card_ui.SetCard(icard, pcard.VariantData);
string cdesc = icard.GetDesc();
string adesc = icard.GetAbilitiesDesc();
if (!string.IsNullOrWhiteSpace(cdesc))
this.desc.text = cdesc + "\n\n" + adesc;
else
this.desc.text = adesc;
//Abilities
int index = 0;
foreach (AbilityData ability in pcard.GetAbilities())
{
if (index < status_lines.Length)
{
//Dont display default ability (GetAbilitiesDesc does that already)
if (!pcard.CardData.HasAbility(ability) && !string.IsNullOrWhiteSpace(ability.desc))
{
status_lines[index].SetLine(pcard.CardData, ability);
index++;
}
}
}
//Status
foreach (CardStatus status in pcard.GetAllStatus())
{
if (index < status_lines.Length)
{
StatusData istatus = StatusData.Get(status.type);
if (istatus != null && !string.IsNullOrWhiteSpace(istatus.desc))
{
int ival = Mathf.Max(status.value, Mathf.CeilToInt(status.duration / 2f));
status_lines[index].SetLine(istatus, ival);
index++;
}
}
}
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7975a0a610dfda94eb5a9c87cf1a8c6e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,261 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TcgEngine.Client;
using TcgEngine;
namespace TcgEngine.UI
{
/// <summary>
/// The UI for card selector, appears when an ability with CardSelector target is triggered
/// </summary>
public class CardSelector : SelectorPanel
{
public GameObject card_prefab;
public RectTransform content;
public Text title;
public Text subtitle;
public Button select_button;
public Text select_button_text;
public float card_spacing = 100f;
private AbilityData iability;
private List<Card> card_list = new List<Card>();
private List<CardSelectorCard> selector_list = new List<CardSelectorCard>();
private Vector2 mouse_start;
private int mouse_start_index;
private int selection_index = 0;
private bool drag = false;
private bool force_show = false;
private float mouse_scroll = 0f;
private float timer = 0f;
private static CardSelector instance;
protected override void Awake()
{
base.Awake();
instance = this;
Hide();
}
protected override void Update()
{
base.Update();
timer += Time.deltaTime;
//Drag cards
Vector2 mouse_pos = GetMouseRectPosition();
Vector2 move = mouse_pos - mouse_start;
if (drag && move.magnitude > 0.1f)
{
selection_index = mouse_start_index - Mathf.RoundToInt(move.x / card_spacing);
selection_index = Mathf.Clamp(selection_index, 0, selector_list.Count - 1);
}
//Mouse scroll
mouse_scroll += -Input.mouseScrollDelta.y;
if (mouse_scroll > 0.5f)
{
OnClickNext();
mouse_scroll -= 1f;
}
else if (mouse_scroll < -0.5f)
{
OnClickPrev();
mouse_scroll += 1f;
}
//Refresh cards
foreach (CardSelectorCard card in selector_list)
{
bool is_selected = card.GetIndex() == selection_index;
Vector3 pos = GetCardPosition(card);
Vector3 scale = is_selected ? Vector3.one : Vector3.one / 2f;
card.SetTargetPos(pos);
card.SetTargetScale(scale);
}
//Close on right click if not a selection
if (iability == null && Input.GetMouseButtonDown(1) && timer > 1f)
Hide();
Game game = GameClient.Get().GetGameData();
if (game != null && iability != null && game.selector == SelectorType.None)
Hide(); //Ability was selected already, close panel
}
public void RefreshPanel()
{
foreach (CardSelectorCard card in selector_list)
Destroy(card.gameObject);
selector_list.Clear();
drag = false;
mouse_scroll = 0f;
select_button_text.text = (iability != null) ? "Select" : "OK";
select_button.gameObject.SetActive(iability != null);
int index = 0;
foreach (Card card in card_list)
{
CardData icard = CardData.Get(card.card_id);
if (icard != null)
{
GameObject obj = Instantiate(card_prefab, content.transform);
RectTransform rect = obj.GetComponent<RectTransform>();
CardSelectorCard selector_card = obj.GetComponent<CardSelectorCard>();
selector_card.SetCard(card);
selector_card.SetIndex(index);
Vector3 pos = GetCardPosition(selector_card);
Vector3 scale = (index == selection_index ? 1 : 0.5f) * Vector3.one;
selector_card.SetTargetPos(pos);
selector_card.SetTargetScale(scale);
rect.anchoredPosition = pos;
selector_list.Add(selector_card);
index++;
}
}
}
//Show ability
public override void Show(AbilityData iability, Card caster)
{
Game data = GameClient.Get().GetGameData();
this.card_list = iability.GetCardTargets(data, caster);
this.iability = iability;
force_show = false;
title.text = iability.title;
subtitle.text = iability.desc;
selection_index = 0;
timer = 0f;
Show();
}
//Show deck/discard
public void Show(List<Card> card_list, string title)
{
this.card_list.Clear();
this.card_list.AddRange(card_list);
this.card_list.Sort((Card a, Card b) => { return a.CardData.title.CompareTo(b.CardData.title); }); //Reorder to not show the deck order
this.iability = null;
force_show = true;
this.title.text = title;
subtitle.text = "";
selection_index = 0;
timer = 0f;
Show();
}
public void OnClickOK()
{
Game data = GameClient.Get().GetGameData();
if (iability != null && data.selector == SelectorType.SelectorCard)
{
CardSelectorCard selector_card = null;
if (selection_index >= 0 && selection_index < selector_list.Count)
selector_card = selector_list[selection_index];
if (selector_card != null)
{
Card selected_card = selector_card.GetCard();
Card caster = data.GetCard(data.selector_caster_uid);
if (selected_card != null && iability.AreTargetConditionsMet(data, caster, selected_card))
{
GameClient.Get().SelectCard(selected_card);
Hide();
}
}
}
else
{
Hide();
}
}
public void OnClickMouseDown()
{
mouse_start = GetMouseRectPosition();
mouse_start_index = selection_index;
drag = true;
}
public void OnClickMouseUp()
{
drag = false;
}
public void OnClickCancel()
{
GameClient.Get().CancelSelection();
Hide();
}
public void OnClickNext()
{
selection_index += 1;
selection_index = Mathf.Clamp(selection_index, 0, selector_list.Count - 1);
}
public void OnClickPrev()
{
selection_index -= 1;
selection_index = Mathf.Clamp(selection_index, 0, selector_list.Count - 1);
}
private Vector2 GetCardPosition(CardSelectorCard card)
{
int index_offset = card.GetIndex() - selection_index;
Vector2 pos = new Vector2(index_offset * card_spacing, (index_offset != 0) ? 50f : 0f);
float center_offset = (index_offset != 0) ? (Mathf.Sign(index_offset) * 140f) : 0;
pos += Vector2.right * center_offset;
return pos;
}
private Vector2 GetMouseRectPosition()
{
Vector2 localpoint;
RectTransformUtility.ScreenPointToLocalPointInRectangle(content, Input.mousePosition, GetComponentInParent<Canvas>().worldCamera, out localpoint);
return localpoint;
}
public bool IsAbility()
{
return IsVisible() && iability != null;
}
public override void Show(bool instant = false)
{
base.Show(instant);
RefreshPanel();
}
public override void Hide(bool instant = false)
{
base.Hide(instant);
force_show = false;
}
public override bool ShouldShow()
{
Game data = GameClient.Get().GetGameData();
int player_id = GameClient.Get().GetPlayerID();
return force_show || (data.selector == SelectorType.SelectorCard && data.selector_player_id == player_id);
}
public static CardSelector Get()
{
return instance;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ae52c06bf4bbc3f4e99b89e89911c445
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,83 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TcgEngine;
namespace TcgEngine.UI
{
/// <summary>
/// One card in the CardSelector
/// </summary>
public class CardSelectorCard : MonoBehaviour
{
public CardUI card_ui;
private int index;
private Vector2 target_pos;
private Vector3 target_scale;
private Card card;
private RectTransform rect;
private void Awake()
{
rect = GetComponent<RectTransform>();
}
private void Start()
{
transform.localScale = target_scale;
}
private void Update()
{
rect.anchoredPosition = Vector2.Lerp(rect.anchoredPosition, target_pos, 5f * Time.deltaTime);
transform.localScale = Vector2.Lerp(transform.localScale, target_scale, 2f * Time.deltaTime);
}
public void SetCard(Card card)
{
this.card = card;
CardData icard = CardData.Get(card.card_id);
card_ui.SetCard(icard, card.VariantData);
}
public void SetIndex(int index)
{
this.index = index;
}
public void SetTargetPos(Vector3 pos)
{
target_pos = pos;
}
public void SetTargetScale(Vector3 scale)
{
target_scale = scale;
}
public Card GetCard()
{
return card;
}
public int GetIndex()
{
return index;
}
public Vector3 GetTargetPos()
{
return target_pos;
}
public Vector3 GetTargetScale()
{
return target_scale;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 975a16df86691a94997c5e4bbb3522ef
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,207 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TcgEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using TcgEngine.Client;
namespace TcgEngine.UI
{
/// <summary>
/// Scripts to display all stats of a card,
/// is used by other script that display cards like BoardCard, and HandCard, CollectionCard..
/// </summary>
public class CardUI : MonoBehaviour, IPointerClickHandler
{
public Image card_image;
public Image frame_image;
public Image team_icon;
public Image rarity_icon;
public Image attack_icon;
public Image hp_icon;
public Image cost_icon;
public Text attack;
public Text hp;
public Text cost;
public Text card_title;
public Text card_text;
public TraitUI[] stats;
public UnityAction<CardUI> onClick;
public UnityAction<CardUI> onClickRight;
private CardData card;
private VariantData variant;
void Awake()
{
}
public void SetCard(Card card)
{
if (card == null)
return;
SetCard(card.CardData, card.VariantData);
if (cost != null)
cost.text = card.GetMana().ToString();
if (cost != null && card.CardData.IsDynamicManaCost())
cost.text = "X";
if (attack != null)
attack.text = card.GetAttack().ToString();
if (hp != null)
hp.text = card.GetHP().ToString();
foreach (TraitUI stat in stats)
stat.SetCard(card);
}
public void SetCard(CardData card, VariantData variant)
{
if (card == null)
return;
this.card = card;
this.variant = variant;
if(card_image != null)
card_image.sprite = card.GetFullArt(variant);
if (frame_image != null)
frame_image.sprite = variant.frame;
if (card_title != null)
card_title.text = card.GetTitle().ToUpper();
if (card_text != null)
card_text.text = card.GetText();
if (attack_icon != null)
attack_icon.enabled = card.IsCharacter();
if (attack != null)
attack.enabled = card.IsCharacter();
if (hp_icon != null)
hp_icon.enabled = card.IsBoardCard() || card.IsEquipment();
if (hp != null)
hp.enabled = card.IsBoardCard() || card.IsEquipment();
if (cost_icon != null)
cost_icon.enabled = card.type != CardType.Hero;
if (cost != null)
cost.enabled = card.type != CardType.Hero;
if (cost != null)
cost.text = card.mana.ToString();
if (cost != null && card.IsDynamicManaCost())
cost.text = "X";
if (attack != null)
attack.text = card.attack.ToString();
if (hp != null)
hp.text = card.hp.ToString();
if (team_icon != null)
{
team_icon.sprite = card.team.icon;
team_icon.enabled = team_icon.sprite != null;
}
if (rarity_icon != null)
{
rarity_icon.sprite = card.rarity.icon;
rarity_icon.enabled = rarity_icon.sprite != null && card.type != CardType.Hero;
}
foreach (TraitUI stat in stats)
stat.SetCard(card);
if (!gameObject.activeSelf)
gameObject.SetActive(true);
}
public void SetHP(int hp_value)
{
if (hp != null)
hp.text = hp_value.ToString();
}
public void SetMaterial(Material mat)
{
if (card_image != null)
card_image.material = mat;
if (frame_image != null)
frame_image.material = mat;
if (team_icon != null)
team_icon.material = mat;
if (rarity_icon != null)
rarity_icon.material = mat;
if (attack_icon != null)
attack_icon.material = mat;
if (hp_icon != null)
hp_icon.material = mat;
if (cost_icon != null)
cost_icon.material = mat;
}
public void SetOpacity(float opacity)
{
if (card_image != null)
card_image.color = new Color(card_image.color.r, card_image.color.g, card_image.color.b, opacity);
if (frame_image != null)
frame_image.color = new Color(frame_image.color.r, frame_image.color.g, frame_image.color.b, opacity);
if (team_icon != null)
team_icon.color = new Color(team_icon.color.r, team_icon.color.g, team_icon.color.b, opacity);
if (rarity_icon != null)
rarity_icon.color = new Color(rarity_icon.color.r, rarity_icon.color.g, rarity_icon.color.b, opacity);
if (attack_icon != null)
attack_icon.color = new Color(attack_icon.color.r, attack_icon.color.g, attack_icon.color.b, opacity);
if (hp_icon != null)
hp_icon.color = new Color(hp_icon.color.r, hp_icon.color.g, hp_icon.color.b, opacity);
if (cost_icon != null)
cost_icon.color = new Color(cost_icon.color.r, cost_icon.color.g, cost_icon.color.b, opacity);
if (attack != null)
attack.color = new Color(attack.color.r, attack.color.g, attack.color.b, opacity);
if (hp != null)
hp.color = new Color(hp.color.r, hp.color.g, hp.color.b, opacity);
if (cost != null)
cost.color = new Color(cost.color.r, cost.color.g, cost.color.b, opacity);
if (card_title != null)
card_title.color = new Color(card_title.color.r, card_title.color.g, card_title.color.b, opacity);
if (card_text != null)
card_text.color = new Color(card_text.color.r, card_text.color.g, card_text.color.b, opacity);
}
public void Hide()
{
if (gameObject.activeSelf)
gameObject.SetActive(false);
}
public void OnPointerClick(PointerEventData eventData)
{
if (eventData.button == PointerEventData.InputButton.Left)
{
if (onClick != null)
onClick.Invoke(this);
}
if (eventData.button == PointerEventData.InputButton.Right)
{
if (onClickRight != null)
onClickRight.Invoke(this);
}
}
public CardData GetCard()
{
return card;
}
public VariantData GetVariant()
{
return variant;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 943be08264f3555448cac48ac16c1e8c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,70 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
using TcgEngine;
namespace TcgEngine.UI
{
/// <summary>
/// Displays a cardback
/// </summary>
public class CardbackUI : MonoBehaviour
{
public UnityAction<CardbackData> onClick;
private Image cardback_img;
private Button cardback_button;
private Sprite default_icon;
private CardbackData cardback;
void Awake()
{
cardback_img = GetComponent<Image>();
cardback_button = GetComponent<Button>();
default_icon = cardback_img.sprite;
if (cardback_button != null)
cardback_button.onClick.AddListener(OnClick);
}
public void SetCardback(CardbackData cardback)
{
this.cardback = cardback;
cardback_img.enabled = true;
cardback_img.sprite = default_icon;
if (cardback != null)
{
cardback_img.sprite = cardback.cardback;
}
}
public void SetDefaultCardback()
{
this.cardback = null;
cardback_img.enabled = true;
cardback_img.sprite = default_icon;
}
public void Hide()
{
this.cardback = null;
cardback_img.enabled = false;
}
public CardbackData GetCardback()
{
return cardback;
}
private void OnClick()
{
if (cardback != null)
onClick?.Invoke(cardback);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a33bcce692d0d9946b177fddc34a1c9f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,47 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TcgEngine;
namespace TcgEngine.UI
{
/// <summary>
/// UI that appears when sending a chat message
/// </summary>
public class ChatBubble : MonoBehaviour
{
public Text msg_txt;
public Image bubble;
public CanvasGroup group;
private float timer = 0f;
void Start()
{
}
private void Update()
{
timer -= Time.deltaTime;
group.alpha = timer;
if (timer < 0f)
Hide();
}
public void SetLine(string msg, float duration)
{
msg_txt.text = msg;
timer = duration;
gameObject.SetActive(true);
}
public void Hide()
{
gameObject.SetActive(false);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 11f21e03097150c429fb4d1c89e4f487
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,133 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TcgEngine.Client;
using TcgEngine;
namespace TcgEngine.UI
{
/// <summary>
/// Chat area in the UI,
/// its where you can write chat msg and will display chat message received from the server
/// </summary>
public class ChatUI : MonoBehaviour
{
public bool is_opponent;
[Header("Display Box")]
public ChatBubble chat_bubble;
public AudioClip chat_audio;
[Header("Write Box")]
public UIPanel chat_field_area;
public InputField chat_field;
private string chat_msg;
private float chat_timer = 0f;
private static List<ChatUI> ui_list = new List<ChatUI>();
private void Awake()
{
ui_list.Add(this);
}
private void OnDestroy()
{
ui_list.Remove(this);
}
void Start()
{
GameClient.Get().onChatMsg += OnChat;
RefreshChat();
}
void Update()
{
if (!GameClient.Get().IsReady())
return;
int player_id = is_opponent ? GameClient.Get().GetOpponentPlayerID() : GameClient.Get().GetPlayerID();
Game data = GameClient.Get().GetGameData();
Player player = data.GetPlayer(player_id);
if (player != null)
{
//Chat
if (chat_field_area != null && !is_opponent && Input.GetKeyDown(KeyCode.Return))
{
if (chat_field_area.IsVisible())
{
if (!string.IsNullOrWhiteSpace(chat_field.text))
SendChat(chat_field.text);
chat_field.text = "";
chat_field_area.Hide();
GUI.FocusControl(null);
}
else
{
chat_field_area.Show();
}
chat_field.ActivateInputField();
chat_field.Select();
}
//Chat remove
chat_timer += Time.deltaTime;
if (chat_timer > 5f)
chat_msg = null;
}
}
private void SendChat(string msg)
{
GameClient.Get().SendChatMsg(msg);
}
private void RefreshChat()
{
chat_bubble.Hide();
if(!string.IsNullOrWhiteSpace(chat_msg))
chat_bubble.SetLine(chat_msg, 5f);
}
private void OnChat(int chat_player_id, string msg)
{
int player_id = is_opponent ? GameClient.Get().GetOpponentPlayerID() : GameClient.Get().GetPlayerID();
if (player_id == chat_player_id)
{
chat_msg = msg;
chat_timer = 0f;
AudioTool.Get().PlaySFX("chat", chat_audio);
RefreshChat();
}
}
public void OnClickSend()
{
if (chat_field_area != null && !string.IsNullOrWhiteSpace(chat_field.text))
{
SendChat(chat_field.text);
chat_field.text = "";
chat_field_area.Hide();
GUI.FocusControl(null);
}
}
public static ChatUI Get(bool opponent)
{
foreach (ChatUI ui in ui_list)
{
if (ui.is_opponent == opponent)
return ui;
}
return null;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 17739ec646c11c846bffa5b5bb551734
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,115 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TcgEngine.Client;
namespace TcgEngine.UI
{
/// <summary>
/// The choice selector is a box that appears when using an ability with ChoiceSelector as target
/// it let you choose between different abilities
/// </summary>
public class ChoiceSelector : SelectorPanel
{
public ChoiceSelectorChoice[] choices;
private Card caster;
private AbilityData ability;
private static ChoiceSelector instance;
protected override void Awake()
{
base.Awake();
instance = this;
}
protected override void Start()
{
base.Start();
foreach (ChoiceSelectorChoice choice in choices)
choice.onClick += OnClickChoice;
}
protected override void Update()
{
base.Update();
Game game = GameClient.Get().GetGameData();
if (game != null && game.selector == SelectorType.None)
Hide();
}
public void RefreshPanel()
{
if (ability == null)
return;
foreach (ChoiceSelectorChoice choice in choices)
choice.Hide();
Game gdata = GameClient.Get().GetGameData();
Player player = GameClient.Get().GetPlayer();
int index = 0;
foreach (AbilityData choice in ability.chain_abilities)
{
if (choice != null && index < choices.Length)
{
ChoiceSelectorChoice achoice = choices[index];
achoice.SetChoice(index, choice);
achoice.SetInteractable(gdata.CanSelectAbility(caster, choice));
index++;
}
}
}
public void OnClickChoice(int index)
{
Game data = GameClient.Get().GetGameData();
if (data.selector == SelectorType.SelectorChoice)
{
GameClient.Get().SelectChoice(index);
Hide();
}
else
{
Hide();
}
}
public void OnClickCancel()
{
GameClient.Get().CancelSelection();
Hide();
}
public override void Show(AbilityData iability, Card caster)
{
this.caster = caster;
this.ability = iability;
Show();
}
public override void Show(bool instant = false)
{
base.Show(instant);
RefreshPanel();
}
public override bool ShouldShow()
{
Game data = GameClient.Get().GetGameData();
int player_id = GameClient.Get().GetPlayerID();
return data.selector == SelectorType.SelectorChoice && data.selector_player_id == player_id;
}
public static ChoiceSelector Get()
{
return instance;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: abc22584ecc915948863236a61201c25
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,76 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
namespace TcgEngine.UI
{
/// <summary>
/// One choice in the choice selector
/// Its a button you can click
/// </summary>
public class ChoiceSelectorChoice : MonoBehaviour
{
public Text title;
public Text subtitle;
public Image highlight;
public UnityAction<int> onClick;
private Button button;
private int choice;
private bool focus = false;
private void Awake()
{
button = GetComponent<Button>();
button.onClick.AddListener(OnClick);
}
private void Update()
{
if (highlight != null)
highlight.enabled = focus;
}
public void SetChoice(int choice, AbilityData ability)
{
this.choice = choice;
this.title.text = ability.title;
this.subtitle.text = ability.desc;
button.interactable = true;
gameObject.SetActive(true);
if (ability.mana_cost > 0)
this.title.text += " (" + ability.mana_cost + ")";
}
public void SetInteractable(bool interact)
{
button.interactable = interact;
}
public void Hide()
{
gameObject.SetActive(false);
}
public void OnClick()
{
onClick?.Invoke(choice);
}
public void MouseEnter()
{
if (button.interactable)
focus = true;
}
public void MouseExit()
{
focus = false;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 17b5ac0995e578c42ae7eac8a25193b2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,33 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TcgEngine.Client;
namespace TcgEngine.UI
{
/// <summary>
/// Panel that appears when internet connection is lost
/// </summary>
public class ConnectionPanel : UIPanel
{
private static ConnectionPanel instance;
protected override void Awake()
{
base.Awake();
instance = this;
}
public void OnClickQuit()
{
GameClient.Get()?.Disconnect();
SceneNav.GoTo("LoginMenu");
}
public static ConnectionPanel Get()
{
return instance;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1d1274fe633fcc845a1b41ea4b5a85dd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,95 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TcgEngine.Client;
namespace TcgEngine.UI
{
/// <summary>
/// The choice selector is a box that appears when using an ability with ChoiceSelector as target
/// it let you choose between different abilities
/// </summary>
public class CostSelector : SelectorPanel
{
public NumberSelector selector;
private Card caster;
private static CostSelector instance;
protected override void Awake()
{
base.Awake();
instance = this;
}
protected override void Start()
{
base.Start();
}
protected override void Update()
{
base.Update();
Game game = GameClient.Get().GetGameData();
if (game != null && game.selector == SelectorType.None)
Hide();
}
public void RefreshPanel()
{
if (caster == null)
return;
Game game = GameClient.Get().GetGameData();
Player player = game.GetPlayer(caster.player_id);
selector.SetMax(player.mana);
selector.SetValue(0);
}
public void OnClickOK()
{
Game data = GameClient.Get().GetGameData();
if (data.selector == SelectorType.SelectorCost)
{
GameClient.Get().SelectCost(selector.value);
}
Hide();
}
public void OnClickCancel()
{
GameClient.Get().CancelSelection();
Hide();
}
public override void Show(AbilityData iability, Card caster)
{
this.caster = caster;
Show();
}
public override void Show(bool instant = false)
{
base.Show(instant);
RefreshPanel();
}
public override bool ShouldShow()
{
Game data = GameClient.Get().GetGameData();
int player_id = GameClient.Get().GetPlayerID();
return data.selector == SelectorType.SelectorCost && data.selector_player_id == player_id;
}
public static CostSelector Get()
{
return instance;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 837d2b512cb0e9040be455798ce3dce5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,171 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
namespace TcgEngine.UI
{
/// <summary>
/// Can display a deck in the UI
/// Only shows a few cards and the total amount of cards
/// </summary>
public class DeckDisplay : MonoBehaviour
{
public Text deck_title;
public Text card_count;
public CardUI[] ui_cards;
private string deck_id;
void Awake()
{
Clear();
}
void Update()
{
}
public void Clear()
{
if (deck_title != null)
deck_title.text = "";
if (card_count != null)
card_count.text = "";
foreach (CardUI card in ui_cards)
card.Hide();
}
public void SetDeck(string tid)
{
UserData user = Authenticator.Get().UserData;
UserDeckData udeck = user.GetDeck(tid);
DeckData ddeck = DeckData.Get(tid);
if (udeck != null)
SetDeck(udeck);
else if (ddeck != null)
SetDeck(ddeck);
else
Clear();
}
public void SetDeck(UserDeckData deck)
{
Clear();
if (deck != null)
{
deck_id = deck.tid;
if (deck_title != null)
deck_title.text = deck.title;
if (card_count != null)
{
card_count.text = deck.GetQuantity().ToString() + " / " + GameplayData.Get().deck_size.ToString();
card_count.color = deck.GetQuantity() >= GameplayData.Get().deck_size ? Color.white : Color.red;
}
List<CardDataQ> cards = new List<CardDataQ>();
foreach (UserCardData ucard in deck.cards)
{
CardDataQ card = new CardDataQ();
card.card = CardData.Get(ucard.tid);
card.variant = VariantData.Get(ucard.variant);
card.quantity = ucard.quantity;
if (card.card != null)
cards.Add(card);
}
ShowCards(cards);
}
gameObject.SetActive(deck != null);
}
public void SetDeck(DeckData deck)
{
Clear();
if (deck != null)
{
deck_id = deck.id;
if (deck_title != null)
deck_title.text = deck.title;
if (card_count != null)
{
card_count.text = deck.GetQuantity().ToString() + " / " + GameplayData.Get().deck_size.ToString();
card_count.color = deck.GetQuantity() >= GameplayData.Get().deck_size ? Color.white : Color.red;
}
List<CardDataQ> dcards = new List<CardDataQ>();
VariantData variant = VariantData.GetDefault();
foreach (CardData icard in deck.cards)
{
if (icard != null)
{
CardDataQ card = new CardDataQ();
card.card = icard;
card.variant = variant;
card.quantity = 1;
dcards.Add(card);
}
}
if (deck is DeckPuzzleData)
{
DeckPuzzleData pdeck = (DeckPuzzleData)deck;
foreach (DeckCardSlot slot in pdeck.board_cards)
{
if (slot.card != null)
{
CardDataQ card = new CardDataQ();
card.card = slot.card;
card.variant = variant;
card.quantity = 1;
dcards.Add(card);
}
}
}
ShowCards(dcards);
}
gameObject.SetActive(deck != null);
}
public void ShowCards(List<CardDataQ> cards)
{
cards.Sort((CardDataQ a, CardDataQ b) => { return b.card.mana.CompareTo(a.card.mana); });
int index = 0;
foreach (CardDataQ icard in cards)
{
for (int i = 0; i < icard.quantity; i++)
{
if (index < ui_cards.Length)
{
CardUI card_ui = ui_cards[index];
card_ui.SetCard(icard.card, icard.variant);
index++;
}
}
}
}
public void Hide()
{
gameObject.SetActive(false);
}
public string GetDeck()
{
return deck_id;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 20cb804e9da996c40bfa27b9a70bd519
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,197 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
using TcgEngine;
namespace TcgEngine.UI
{
/// <summary>
/// Deck selector is a dropdown that let the player select a deck before a match
/// </summary>
public class DeckSelector : MonoBehaviour
{
public DropdownValue deck_dropdown;
public UnityAction<string> onChange;
void Start()
{
deck_dropdown.onValueChanged += OnChange;
}
void Update()
{
}
public void SetupUserDeckList()
{
deck_dropdown.ClearOptions();
deck_dropdown.AddOption("random", "Random");
//Add standard decks
foreach (DeckData deck in GameplayData.Get().free_decks)
{
deck_dropdown.AddOption(deck.id, deck.title);
}
UserData udata = Authenticator.Get().UserData;
if (udata != null)
{
foreach (UserDeckData deck in udata.decks)
{
if (udata.IsDeckValid(deck))
{
deck_dropdown.AddOption(deck.tid, deck.title);
}
}
}
}
public void SetupAIDeckList()
{
deck_dropdown.ClearOptions();
deck_dropdown.AddOption("random_ai", "Random");
//Add standard decks
foreach (DeckData deck in GameplayData.Get().ai_decks)
{
deck_dropdown.AddOption(deck.id, deck.title);
}
//Also add user made decks
UserData udata = Authenticator.Get().UserData;
if (udata != null)
{
foreach (UserDeckData deck in udata.decks)
{
if (udata.IsDeckValid(deck))
{
deck_dropdown.AddOption(deck.tid, deck.title);
}
}
}
}
private void SelectDeck(UserDeckData deck)
{
if (deck != null)
{
deck_dropdown.SetValue(deck.tid);
}
}
private void SelectDeck(DeckData deck)
{
if (deck != null)
{
deck_dropdown.SetValue(deck.id);
}
}
public void SelectDeck(string deck)
{
//Make sure deck exists, to prevent assigning invalid deck
UserData udata = Authenticator.Get().UserData;
UserDeckData udeck = udata?.GetDeck(deck);
if (udeck != null)
{
SelectDeck(udeck);
return;
}
DeckData adeck = DeckData.Get(deck);
if(adeck != null)
SelectDeck(adeck);
}
public void SelectDeck(int index)
{
deck_dropdown.SetValue(index);
}
public void Lock()
{
deck_dropdown.interactable = false;
}
public void Unlock()
{
deck_dropdown.interactable = true;
}
public void SetLocked(bool locked)
{
deck_dropdown.interactable = !locked;
}
private void OnChange(int i, string val)
{
string value = deck_dropdown.GetSelectedValue();
onChange?.Invoke(value);
}
public string GetDeckID()
{
return deck_dropdown.GetSelectedValue();
}
public string GetDeckTitle()
{
return deck_dropdown.GetSelectedText();
}
public UserDeckData GetDeckById(string deck_id)
{
UserData user = Authenticator.Get().UserData;
UserDeckData udeck = user.GetDeck(deck_id); //Check for user custom deck
DeckData deck = DeckData.Get(deck_id); //Check for deck presets
//User custom deck
if (udeck != null)
return udeck;
//Premade deck
else if (deck != null)
return new UserDeckData(deck);
return null;
}
public UserDeckData GetDeck()
{
string deck_id = GetDeckID();
//Random Reck
if (deck_id == "random")
return GetRandomDeck();
if (deck_id == "random_ai")
return GetRandomDeckAI();
return GetDeckById(deck_id);
}
public UserDeckData GetRandomDeck()
{
List<UserDeckData> random_decks = new List<UserDeckData>();
foreach (DropdownValueItem item in deck_dropdown.Items)
{
UserDeckData deck = GetDeckById(item.id);
if (deck != null)
random_decks.Add(deck);
}
if (random_decks.Count > 0)
return random_decks[Random.Range(0, random_decks.Count)];
return null;
}
public UserDeckData GetRandomDeckAI()
{
return new UserDeckData(GameplayData.Get().GetRandomAIDeck());
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4daa8faeec7ed4b47b929070d37c732e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,137 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
namespace TcgEngine.UI
{
/// <summary>
/// Class that let you store a ID with each element of a Dropdown
/// </summary>
[System.Serializable]
public class DropdownValueItem
{
public string id;
public string text;
}
[RequireComponent(typeof(Dropdown))]
public class DropdownValue : MonoBehaviour
{
public UnityAction<int, string> onValueChanged;
private List<DropdownValueItem> values = new List<DropdownValueItem>();
private Dropdown dropdown;
void Awake()
{
dropdown = GetComponent<Dropdown>();
dropdown.onValueChanged.AddListener(OnChangeValue);
}
private void Start()
{
}
public void AddOption(string id, string text)
{
Dropdown.OptionData option = new Dropdown.OptionData(text);
dropdown.options.Add(option);
DropdownValueItem item = new DropdownValueItem();
item.id = id;
item.text = text;
values.Add(item);
dropdown.RefreshShownValue();
}
public void ClearOptions()
{
values.Clear();
dropdown.ClearOptions();
}
public void SetValue(string value)
{
int index = 0;
foreach (DropdownValueItem item in values)
{
if (item.id == value)
dropdown.value = index;
index++;
}
}
public void SetValue(int index)
{
if (index >= 0 && index < dropdown.options.Count)
dropdown.value = index;
}
private void OnChangeValue(int selected_index)
{
if (selected_index >= 0 && selected_index < values.Count)
{
DropdownValueItem value = values[selected_index];
if (onValueChanged != null)
onValueChanged.Invoke(selected_index, value.id);
}
}
public DropdownValueItem GetSelected()
{
if (dropdown.value >= 0 && dropdown.value < values.Count)
{
DropdownValueItem item = values[dropdown.value];
return item;
}
return null;
}
public string GetSelectedValue()
{
DropdownValueItem item = GetSelected();
if (item != null)
return item.id;
return "";
}
public string GetSelectedText()
{
DropdownValueItem item = GetSelected();
if (item != null)
return item.text;
return "";
}
public int GetSelectedIndex()
{
return dropdown.value;
}
public int Count
{
get { return dropdown.options.Count; }
}
public bool interactable
{
get { return dropdown.interactable; }
set { dropdown.interactable = value; }
}
public int value
{
get { return dropdown.value; }
set { dropdown.value = value; dropdown.RefreshShownValue(); }
}
public List<DropdownValueItem> Items
{
get { return values; }
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0657b564c5827e148bfa6e2fb4ad96cd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,164 @@
using TcgEngine.Client;
using UnityEngine;
using UnityEngine.UI;
namespace TcgEngine.UI
{
/// <summary>
/// Endgame panel is shown when a game end
/// Showing winner and rewards obtained
/// </summary>
public class EndGamePanel : UIPanel
{
public Text winner_text;
public Image winner_glow;
public Text player_name;
public Text other_name;
public Image player_avatar;
public Image other_avatar;
public Text coins_text;
public Text xp_text;
private bool reward_loaded = false;
private float timer = 0f;
private int target_coins = 0;
private int target_xp = 0;
private float coins = 0;
private float xp = 0;
private static EndGamePanel _instance;
protected override void Awake()
{
base.Awake();
_instance = this;
}
protected override void Start()
{
base.Start();
coins_text.text = "";
xp_text.text = "";
}
protected override void Update()
{
base.Update();
if (!reward_loaded && IsVisible())
{
timer += Time.deltaTime;
if (timer > 1f)
{
timer = 0f;
RefreshRewards();
}
}
if (reward_loaded)
{
coins = Mathf.MoveTowards(coins, target_coins, 2000f * Time.deltaTime);
xp = Mathf.MoveTowards(xp, target_xp, 500f * Time.deltaTime);
coins_text.text = "+ " + Mathf.RoundToInt(coins) + " coins";
xp_text.text = "+ " + Mathf.RoundToInt(xp) + " xp";
if (Mathf.RoundToInt(coins) == 0)
coins_text.text = "";
if (Mathf.RoundToInt(xp) == 0)
xp_text.text = "";
}
}
private void RefreshPanel(int winner)
{
Game data = GameClient.Get().GetGameData();
Player pwinner = data.GetPlayer(winner);
Player player = GameClient.Get().GetPlayer();
Player oplayer = GameClient.Get().GetOpponentPlayer();
player_name.text = player.username;
other_name.text = oplayer.username;
AvatarData avat1 = AvatarData.Get(player.avatar);
AvatarData avat2 = AvatarData.Get(oplayer.avatar);
if(avat1 != null)
player_avatar.sprite = avat1.avatar;
if (avat2 != null)
other_avatar.sprite = avat2.avatar;
if (pwinner != null && pwinner == player)
winner_text.text = "Victory";
else if (pwinner != null)
winner_text.text = "Defeat";
else
winner_text.text = "Tie";
if (pwinner == player)
winner_glow.rectTransform.anchoredPosition = player_avatar.rectTransform.anchoredPosition;
if (pwinner == oplayer)
winner_glow.rectTransform.anchoredPosition = other_avatar.rectTransform.anchoredPosition;
winner_glow.gameObject.SetActive(pwinner != null);
}
private async void RefreshRewards()
{
//Online rewards
if (GameClient.game_settings.IsOnline())
{
string url = ApiClient.ServerURL + "/matches/" + GameClient.game_settings.game_uid;
WebResponse res = await ApiClient.Get().SendGetRequest(url);
if (res.success)
{
reward_loaded = true;
MatchResponse match = ApiTool.JsonToObject<MatchResponse>(res.data);
string username = ApiClient.Get().Username.ToLower();
foreach (MatchDataResponse data in match.udata)
{
if (data.username.ToLower() == username)
{
target_coins = data.reward.coins;
target_xp = data.reward.xp;
}
}
}
}
//Adventure Rewards
if (GameClient.game_settings.game_type == GameType.Adventure)
{
LevelData lvl = LevelData.Get(GameClient.game_settings.level);
if (lvl != null && RewardManager.Get().IsRewardGained())
{
target_coins = lvl.reward_coins;
target_xp = lvl.reward_xp;
reward_loaded = true;
}
}
}
public void ShowEnd(int winner)
{
reward_loaded = false;
RefreshPanel(winner);
RefreshRewards();
Show();
}
public void OnClickQuit()
{
GameUI.Get().OnClickQuit();
}
public static EndGamePanel Get()
{
return _instance;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1afae4aac668abe449f2a87f21167b69
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,283 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TcgEngine.Client;
using UnityEngine.SceneManagement;
using UnityEngine.EventSystems;
namespace TcgEngine.UI
{
/// <summary>
/// Main UI script for all the game scene UI
/// </summary>
public class GameUI : MonoBehaviour
{
public Canvas game_canvas;
public Canvas panel_canvas;
public Canvas top_canvas;
public UIPanel menu_panel;
public Text quit_btn;
[Header("Turn Area")]
public Text turn_count;
public Text turn_timer;
public Button end_turn_button;
public Animator timeout_animator;
public AudioClip timeout_audio;
private float selector_timer = 0f;
private float end_turn_timer = 0f;
private int prev_time_val = 0;
private static GameUI instance;
void Awake()
{
instance = this;
if (game_canvas.worldCamera == null)
game_canvas.worldCamera = Camera.main;
if (panel_canvas.worldCamera == null)
panel_canvas.worldCamera = Camera.main;
if (top_canvas.worldCamera == null)
top_canvas.worldCamera = Camera.main;
}
private void Start()
{
GameClient.Get().onGameStart += OnGameStart;
GameClient.Get().onNewTurn += OnNewTurn;
LoadPanel.Get().Show(true);
BlackPanel.Get().Show(true);
BlackPanel.Get().Hide();
if (quit_btn != null)
quit_btn.text = GameClient.game_settings.IsOnlinePlayer() ? "Resign" : "Quit";
}
void Update()
{
Game data = GameClient.Get().GetGameData();
bool is_connecting = data == null || data.state == GameState.Connecting;
bool connection_lost = !is_connecting && !GameClient.Get().IsReady();
ConnectionPanel.Get().SetVisible(connection_lost);
//Menu
if (Input.GetKeyDown(KeyCode.Escape))
menu_panel.Toggle();
if (!GameClient.Get().IsReady())
return;
bool yourturn = GameClient.Get().IsYourTurn();
LoadPanel.Get().SetVisible(is_connecting && !data.HasStarted());
end_turn_button.interactable = yourturn && end_turn_timer > 1f;
end_turn_timer += Time.deltaTime;
selector_timer += Time.deltaTime;
//Timer
turn_count.text = "Turn " + data.turn_count.ToString();
turn_timer.enabled = data.turn_timer > 0f;
turn_timer.text = Mathf.RoundToInt(data.turn_timer).ToString();
turn_timer.enabled = data.turn_timer < 999f;
//Simulate timer
if (data.state == GameState.Play && data.turn_timer > 0f)
data.turn_timer -= Time.deltaTime;
//Timer warning
if (data.state == GameState.Play)
{
int val = Mathf.RoundToInt(data.turn_timer);
int tick_val = 10;
if (val < prev_time_val && val <= tick_val)
PulseFX();
prev_time_val = val;
}
//Show selector panels
foreach (SelectorPanel panel in SelectorPanel.GetAll())
{
bool should_show = panel.ShouldShow();
if (should_show != panel.IsVisible() && selector_timer > 1f)
{
selector_timer = 0f;
panel.SetVisible(should_show);
if (should_show)
{
AbilityData ability = AbilityData.Get(data.selector_ability_id);
Card caster = data.GetCard(data.selector_caster_uid);
panel.Show(ability, caster);
}
}
}
//Hide
if (!yourturn && data.phase != GamePhase.Mulligan)
{
SelectorPanel.HideAll();
}
}
private void PulseFX()
{
timeout_animator?.SetTrigger("pulse");
AudioTool.Get().PlaySFX("time", timeout_audio, 1f);
}
private void OnGameStart()
{
}
private void OnNewTurn(int player_id)
{
CardSelector.Get().Hide();
SelectTargetUI.Get().Hide();
}
public void OnClickNextTurn()
{
if (!Tutorial.Get().CanDo(TutoEndTrigger.EndTurn))
return;
GameClient.Get().EndTurn();
end_turn_timer = 0f; //Disable button immediately (dont wait for refresh)
}
public void OnClickRestart()
{
SceneManager.LoadScene(SceneManager.GetActiveScene().name);
}
public void OnClickMenu()
{
menu_panel.Show();
}
public void OnClickBack()
{
menu_panel.Hide();
}
public void OnClickQuit()
{
bool online = GameClient.game_settings.IsOnlinePlayer();
bool ended = GameClient.Get().HasEnded();
if (online && !ended)
GameClient.Get().Resign();
else
StartCoroutine(QuitRoutine("Menu"));
menu_panel.Hide();
}
private IEnumerator QuitRoutine(string scene)
{
BlackPanel.Get().Show();
AudioTool.Get().FadeOutMusic("music");
AudioTool.Get().FadeOutSFX("ambience");
AudioTool.Get().FadeOutSFX("ending_sfx");
yield return new WaitForSeconds(1f);
GameClient.Get().Disconnect();
SceneNav.GoTo(scene);
}
public void OnClickSwapObserve()
{
int other = GameClient.Get().GetPlayerID() == 0 ? 1 : 0;
GameClient.Get().SetObserverMode(other);
}
public static bool IsUIOpened()
{
return CardSelector.Get().IsVisible() || EndGamePanel.Get().IsVisible();
}
public static bool IsOverUI()
{
//return UnityEngine.EventSystems.EventSystem.current.IsPointerOverGameObject();
PointerEventData eventDataCurrentPosition = new PointerEventData(EventSystem.current);
eventDataCurrentPosition.position = new Vector2(Input.mousePosition.x, Input.mousePosition.y);
List<RaycastResult> results = new List<RaycastResult>();
EventSystem.current.RaycastAll(eventDataCurrentPosition, results);
return results.Count > 0;
}
public static bool IsOverUILayer(string sorting_layer)
{
return IsOverUILayer(SortingLayer.NameToID(sorting_layer));
}
public static bool IsOverUILayer(int sorting_layer)
{
//return UnityEngine.EventSystems.EventSystem.current.IsPointerOverGameObject();
PointerEventData eventDataCurrentPosition = new PointerEventData(EventSystem.current);
eventDataCurrentPosition.position = new Vector2(Input.mousePosition.x, Input.mousePosition.y);
List<RaycastResult> results = new List<RaycastResult>();
EventSystem.current.RaycastAll(eventDataCurrentPosition, results);
int count = 0;
foreach (RaycastResult result in results)
{
if (result.sortingLayer == sorting_layer)
count++;
}
return count > 0;
}
public static bool IsOverRectTransform(Canvas canvas, RectTransform rect)
{
PointerEventData pevent = new PointerEventData(EventSystem.current);
pevent.position = Input.mousePosition;
List<RaycastResult> results = new List<RaycastResult>();
GraphicRaycaster raycaster = canvas.GetComponent<GraphicRaycaster>();
raycaster.Raycast(pevent, results);
foreach (RaycastResult result in results)
{
if (result.gameObject.transform == rect || result.gameObject.transform.IsChildOf(rect))
return true;
}
return false;
}
public static Vector2 MouseToRectPos(Canvas canvas, RectTransform rect, Vector2 screen_pos)
{
if (canvas.renderMode != RenderMode.ScreenSpaceOverlay && canvas.worldCamera != null)
{
Vector2 anchor_pos;
RectTransformUtility.ScreenPointToLocalPointInRectangle(rect, screen_pos, canvas.worldCamera, out anchor_pos);
return anchor_pos;
}
else
{
Vector2 anchor_pos = screen_pos - new Vector2(rect.position.x, rect.position.y);
anchor_pos = new Vector2(anchor_pos.x / rect.lossyScale.x, anchor_pos.y / rect.lossyScale.y);
return anchor_pos;
}
}
public static Vector3 MouseToWorld(Vector2 mouse_pos, float distance = 10f)
{
Camera cam = GameCamera.Get() != null ? GameCamera.GetCamera() : Camera.main;
Vector3 wpos = cam.ScreenToWorldPoint(new Vector3(mouse_pos.x, mouse_pos.y, distance));
return wpos;
}
public static string FormatNumber(int value)
{
return string.Format("{0:#,0}", value);
}
public static GameUI Get()
{
return instance;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 61d11954e9747ce43a0a9c63b8388916
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,169 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TcgEngine.Client;
using UnityEngine.EventSystems;
namespace TcgEngine.UI
{
public class HeroUI : MonoBehaviour
{
public bool opponent;
public GameObject power_area;
public Button power_button;
public Image power_image;
public GameObject power_mana_slot;
public Text power_mana;
public Material active_mat;
public Material inactive_mat;
private bool focus = false;
private static List<HeroUI> ui_list = new List<HeroUI>();
private void Awake()
{
ui_list.Add(this);
}
private void OnDestroy()
{
ui_list.Remove(this);
}
void Start()
{
power_area.SetActive(false);
if (power_button != null)
power_button.onClick.AddListener(OnClickPower);
EventTrigger trigger = power_area.GetComponent<EventTrigger>();
EventTrigger.Entry entry = new EventTrigger.Entry();
entry.eventID = EventTriggerType.PointerEnter;
entry.callback.AddListener((eventData) => { OnEnterMouse(); });
EventTrigger.Entry exit = new EventTrigger.Entry();
exit.eventID = EventTriggerType.PointerExit;
exit.callback.AddListener((eventData) => { OnExitMouse(); });
trigger.triggers.Add(entry);
trigger.triggers.Add(exit);
}
private void Update()
{
if (!GameClient.Get().IsReady())
return;
Game gdata = GameClient.Get().GetGameData();
Player player = GetPlayer();
Card hero = player.hero;
if (hero == null)
return;
AbilityData ability = hero.GetAbility(AbilityTrigger.Activate);
if (ability != null)
{
power_image.sprite = hero.CardData.GetBoardArt(hero.VariantData);
power_image.material = !hero.exhausted ? active_mat : inactive_mat;
power_mana_slot?.SetActive(gdata.IsPlayerTurn(player) && !hero.exhausted);
power_mana.text = ability.mana_cost.ToString();
}
if (power_button != null)
power_button.interactable = ability != null && !hero.exhausted && gdata.IsPlayerTurn(player);
if (hero != null && !power_area.activeSelf)
power_area.SetActive(true);
}
public void OnClickPower()
{
Game gdata = GameClient.Get().GetGameData();
Player player = GameClient.Get().GetPlayer();
Card hero = player.hero;
AbilityData ability = hero?.GetAbility(AbilityTrigger.Activate);
if (ability != null && !opponent)
{
if (!hero.exhausted && !player.CanPayAbility(hero, ability))
{
WarningText.ShowNoMana();
return;
}
if (!Tutorial.Get().CanDo(TutoEndTrigger.CastAbility, hero))
return;
bool valid = gdata.IsPlayerActionTurn(player) && gdata.CanCastAbility(hero, ability);
if (valid)
{
GameClient.Get().CastAbility(hero, ability);
}
}
}
private void OnEnterMouse()
{
focus = true;
}
private void OnExitMouse()
{
focus = false;
}
private void OnDisable()
{
focus = false;
}
public bool IsFocus()
{
return focus;
}
public int GetPlayerID()
{
return opponent ? GameClient.Get().GetOpponentPlayerID() : GameClient.Get().GetPlayerID();
}
public Player GetPlayer()
{
Game gdata = GameClient.Get().GetGameData();
return gdata.GetPlayer(GetPlayerID());
}
public Card GetCard()
{
Player player = GetPlayer();
return player.hero;
}
public static HeroUI GetFocus()
{
foreach (HeroUI ui in ui_list)
{
if (ui.IsFocus())
return ui;
}
return null;
}
public static HeroUI Get(bool opponent)
{
foreach (HeroUI ui in ui_list)
{
if (ui.opponent == opponent)
return ui;
}
return null;
}
public static HeroUI Get(int player_id)
{
bool opponent = player_id != GameClient.Get().GetPlayerID();
return Get(opponent);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 388b3a721fb8b1a4d84475dbddbb1563
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,83 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
namespace TcgEngine.UI
{
/// <summary>
/// Target in the scene that can be hovered (and text will appear)
/// </summary>
public class HoverTarget : MonoBehaviour
{
[TextArea(5, 7)]
public string text;
public float delay = 0.5f;
public int text_size = 22;
public int width = 350;
public int height = 140;
//private LangTableText ltable;
private float timer = 0f;
private bool hover = false;
void Awake()
{
//ltable = GetComponent<LangTableText>();
}
void Start()
{
if (HoverTextBox.Get() == null)
{
Instantiate(AssetData.Get().hover_text_box, Vector3.zero, Quaternion.identity);
}
}
void Update()
{
if (hover)
{
timer += Time.deltaTime;
if (timer > delay)
{
HoverTextBox.Get().Show(this);
}
}
}
public string GetText()
{
//if (ltable != null)
// return ltable.GetTranslation(text);
return text;
}
private void OnMouseEnter()
{
if (GameUI.IsOverUI())
return;
timer = 0f;
hover = true;
}
private void OnMouseExit()
{
timer = 0f;
hover = false;
}
void OnDisable()
{
hover = false;
}
public bool IsHover()
{
return hover;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 41327cc8bd9b00544a3e6de2b2168f0b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,94 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
namespace TcgEngine.UI
{
/// <summary>
/// Target in the UI that can be hovered (and text will appear)
/// </summary>
public class HoverTargetUI : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler
{
[TextArea(5, 7)]
public string text;
public float delay = 0.5f;
public int text_size = 22;
public int width = 350;
public int height = 140;
private Canvas canvas;
private RectTransform rect;
//private LangTableText ltable;
private float timer = 0f;
private bool hover = false;
void Awake()
{
canvas = GetComponentInParent<Canvas>();
//ltable = GetComponent<LangTableText>();
rect = canvas?.GetComponent<RectTransform>();
}
void Start()
{
if (HoverTextBox.Get() == null)
{
Instantiate(AssetData.Get().hover_text_box, Vector3.zero, Quaternion.identity);
}
}
void Update()
{
if (hover)
{
timer += Time.deltaTime;
if (timer > delay)
{
HoverTextBox.Get().Show(this);
}
}
}
public string GetText()
{
//if (ltable != null)
// return ltable.GetTranslation(text);
return text;
}
public void OnPointerEnter(PointerEventData eventData)
{
timer = 0f;
hover = true;
}
public void OnPointerExit(PointerEventData eventData)
{
timer = 0f;
hover = false;
}
void OnDisable()
{
hover = false;
}
public Canvas GetCanvas()
{
return canvas;
}
public RectTransform GetRect()
{
return rect;
}
public bool IsHover()
{
return hover;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 48f1c6105a2efd946b431664eef2f58c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,87 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
namespace TcgEngine.UI
{
/// <summary>
/// Box that appears when hovering a HoverTarget
/// </summary>
public class HoverTextBox : MonoBehaviour
{
public UIPanel panel_left;
public UIPanel panel_right;
public Text text1;
public Text text2;
private HoverTarget current;
private HoverTargetUI current_ui;
private RectTransform rect_left;
private RectTransform rect_right;
private static HoverTextBox instance;
void Awake()
{
instance = this;
rect_left = panel_left.GetComponent<RectTransform>();
rect_right = panel_right.GetComponent<RectTransform>();
}
void Update()
{
if (current != null || current_ui != null)
{
transform.position = GameUI.MouseToWorld(Input.mousePosition);
transform.rotation = Quaternion.LookRotation(Camera.main.transform.forward, Vector2.up);
panel_left.SetVisible(transform.position.x > 0f);
panel_right.SetVisible(transform.position.x <= 0f);
if (current != null && !current.IsHover())
Hide();
if (current_ui != null && !current_ui.IsHover())
Hide();
}
}
public void Show(HoverTarget hover)
{
current = hover;
current_ui = null;
text1.text = hover.GetText();
text2.text = hover.GetText();
text1.fontSize = hover.text_size;
text2.fontSize = hover.text_size;
rect_left.sizeDelta = new Vector2(hover.width, hover.height);
rect_right.sizeDelta = new Vector2(hover.width, hover.height);
}
public void Show(HoverTargetUI hover)
{
current = null;
current_ui = hover;
text1.text = hover.GetText();
text2.text = hover.GetText();
text1.fontSize = hover.text_size;
text2.fontSize = hover.text_size;
rect_left.sizeDelta = new Vector2(hover.width, hover.height);
rect_right.sizeDelta = new Vector2(hover.width, hover.height);
}
public void Hide()
{
current = null;
current_ui = null;
panel_left.Hide();
panel_right.Hide();
}
public static HoverTextBox Get()
{
return instance;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b1601e2e0f0e4424798c1aad5e56d4ca
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,53 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
namespace TcgEngine.UI
{
/// <summary>
/// Bar that contain multiple icons to represent a value
/// Such as the mana bar during the game
/// </summary>
public class IconBar : MonoBehaviour
{
public int value = 0;
public int max_value = 4;
public bool auto_refresh = true;
public Image[] icons;
public Sprite sprite_full;
public Sprite sprite_empty;
void Awake()
{
}
void Update()
{
if (auto_refresh)
Refresh();
}
public void Refresh()
{
int index = 0;
foreach (Image icon in icons)
{
icon.gameObject.SetActive(index < value || index < max_value);
icon.sprite = (index < value) ? sprite_full : sprite_empty;
index++;
}
}
public void SetMat(Material mat)
{
foreach (Image icon in icons)
{
icon.material = mat;
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: bf1498eac12d8c14e98918e5ac2baf2c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,128 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Events;
namespace TcgEngine.UI
{
/// <summary>
/// A toggle button that will disable other buttons in same group when clicked
/// </summary>
public class IconButton : MonoBehaviour
{
public string group;
public string value;
public Image active_img;
public Image disabled_img;
public bool on_if_all_off;
public UnityAction<IconButton> onClick;
private bool active = false;
private Button button;
private static List<IconButton> toggle_list = new List<IconButton>();
void Awake()
{
toggle_list.Add(this);
button = GetComponent<Button>();
button.onClick.AddListener(OnClick);
if(!on_if_all_off && active_img != null)
active_img.enabled = false;
}
private void OnDestroy()
{
toggle_list.Remove(this);
}
void Start()
{
}
private void Update()
{
if (on_if_all_off)
{
if (active_img != null && IsAllOff(group))
{
active_img.enabled = true;
}
}
}
void OnClick()
{
bool was_active = active;
DeactivateAll(group);
if (!was_active)
Activate();
if (onClick != null)
onClick.Invoke(this);
}
public void SetActive(bool act)
{
if (act) Activate();
else Deactivate();
}
public void Activate()
{
active = true;
if (active_img != null)
active_img.enabled = true;
}
public void Deactivate()
{
active = false;
if (active_img != null)
active_img.enabled = false;
}
public bool IsActive()
{
return active;
}
public static bool IsAllOff(string group)
{
bool all_off = true;
foreach (IconButton toggle in toggle_list)
{
if (toggle.group == group && toggle.IsActive())
all_off = false;
}
return all_off;
}
public static void DeactivateAll(string group)
{
foreach (IconButton toggle in toggle_list)
{
if (toggle.group == group)
toggle.Deactivate();
}
}
public static List<IconButton> GetAll(string group)
{
List<IconButton> toggles = new List<IconButton>();
foreach (IconButton toggle in toggle_list)
{
if (toggle.group == group)
toggles.Add(toggle);
}
return toggles;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e783a0cc445432e4d8f1e46ae30ac0c1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,52 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
namespace TcgEngine.UI
{
/// <summary>
/// Icon that changes based on the value assigned
/// </summary>
public class IconValue : MonoBehaviour
{
public int value;
public bool auto_refresh = true;
public Sprite[] values;
private Image image;
void Awake()
{
image = GetComponent<Image>();
}
void Update()
{
if (auto_refresh)
Refresh();
}
public void Refresh()
{
if (image == null)
image = GetComponent<Image>();
if (value >= 0 && value < values.Length)
{
image.sprite = values[value];
image.enabled = image.sprite != null;
}
}
public void SetMat(Material mat)
{
if (image == null)
image = GetComponent<Image>();
image.material = mat;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0f3556e0fcd278b4aa88039d6386e1dc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,75 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TcgEngine.Client;
namespace TcgEngine.UI
{
/// <summary>
/// Loading panel that appears at the begining of a match, waiting for players to connect
/// </summary>
public class LoadPanel : UIPanel
{
public Text load_txt;
private static LoadPanel instance;
protected override void Awake()
{
base.Awake();
instance = this;
if (load_txt != null)
load_txt.text = "";
}
protected override void Start()
{
base.Start();
GameClient.Get().onConnectGame += OnConnect;
GameClient.Get().onPlayerReady += OnReady;
GameClient.Get().onGameStart += OnStart;
SetLoadText("Connecting to server...");
}
private void OnConnect()
{
SetLoadText("Sending player data...");
}
private void OnStart()
{
SetLoadText("");
}
private void OnReady(int player_id)
{
if (player_id == GameClient.Get().GetPlayerID())
{
SetLoadText("Waiting for other player...");
}
}
private void SetLoadText(string text)
{
if (IsOnline())
{
if (load_txt != null)
load_txt.text = text;
}
}
public bool IsOnline()
{
return GameClient.game_settings.IsOnline();
}
public static LoadPanel Get()
{
return instance;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2daa79dc6f4e7fd4584da92c14550c10
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,80 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TcgEngine.Client;
namespace TcgEngine.UI
{
public class MulliganSelector : SelectorPanel
{
public CardMulligan[] cards;
private static MulliganSelector instance;
protected override void Awake()
{
base.Awake();
instance = this;
foreach (CardMulligan card in cards)
{
card.onClick += OnClickCard;
}
}
private void RefreshMulligan()
{
Player player = GameClient.Get().GetPlayer();
int index = 0;
foreach (Card card in player.cards_hand)
{
string bonus_id = GameplayData.Get().second_bonus != null ? GameplayData.Get().second_bonus.id : "";
if (index < cards.Length && card.card_id != bonus_id)
{
CardMulligan card_ui = cards[index];
card_ui.SetCard(card);
index++;
}
}
}
private void OnClickCard(CardMulligan card_ui)
{
card_ui.SetSelected(!card_ui.IsSelected());
}
public void OnClickOK()
{
List<string> selected_cards = new List<string>();
foreach (CardMulligan acard in cards)
{
if (acard.IsSelected())
selected_cards.Add(acard.GetCard().uid);
}
GameClient.Get().Mulligan(selected_cards.ToArray());
Hide();
}
public override void Show(bool instant = false)
{
base.Show(instant);
RefreshMulligan();
}
public override bool ShouldShow()
{
Game gdata = GameClient.Get().GetGameData();
Player player = GameClient.Get().GetPlayer();
return gdata.IsPlayerMulliganTurn(player);
}
public static MulliganSelector Get()
{
return instance;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 89c8af25f735377459c5579bb720e1c8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,89 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
using TcgEngine;
namespace TcgEngine.UI
{
/// <summary>
/// Select a value between min and max
/// </summary>
public class NumberSelector : MonoBehaviour
{
[Header("Options")]
public int value;
public int value_min;
public int value_max;
[Header("Display")]
public Text select_text;
public UnityAction onChange;
private bool is_locked = false;
void Start()
{
SetValue(0);
}
void Update()
{
}
private void AfterChangeOption()
{
if (select_text != null)
select_text.text = value.ToString();
onChange?.Invoke();
}
public void OnClickLeft()
{
if (is_locked)
return;
value--;
value = Mathf.Clamp(value, value_min, value_max);
AfterChangeOption();
}
public void OnClickRight()
{
if (is_locked)
return;
value++;
value = Mathf.Clamp(value, value_min, value_max);
AfterChangeOption();
}
public void SetValue(int val)
{
value = Mathf.Clamp(val, value_min, value_max);
if (select_text != null)
select_text.text = value.ToString();
}
public void SetMin(int min)
{
value_min = min;
}
public void SetMax(int max)
{
value_max = max;
}
public void SetLocked(bool locked)
{
is_locked = locked;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b5fba4a554f29ee4fbd74a069788475c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,80 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TcgEngine;
namespace TcgEngine.UI
{
[System.Serializable]
public class OptionString
{
public string value;
public string title;
}
/// <summary>
/// Option selector is a UI element with 2 arrows (left/right) to select an option among preset values
/// This one let you select a string
/// </summary>
public class OptionSelector : MonoBehaviour
{
[Header("Options")]
public OptionString[] options;
[Header("Display")]
public Text select_text;
private int position = 0;
void Start()
{
SetIndex(0);
}
void Update()
{
}
private void AfterChangeOption()
{
if (select_text != null)
select_text.text = GetSelectedTitle();
}
public void OnClickLeft()
{
position = (position + options.Length - 1) % options.Length;
AfterChangeOption();
}
public void OnClickRight()
{
position = (position + options.Length + 1) % options.Length;
AfterChangeOption();
}
public void SetIndex(int index)
{
position = index;
AfterChangeOption();
}
public OptionString GetSelected()
{
return options[position];
}
public string GetSelectedValue()
{
return options[position].value;
}
public string GetSelectedTitle()
{
return options[position].title;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 46b952ba1cd24b24cade92a18835b10e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,96 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
using TcgEngine;
namespace TcgEngine.UI
{
[System.Serializable]
public class OptionImage
{
public string value;
public Sprite image;
}
/// <summary>
/// Option selector is a UI element with 2 arrows (left/right) to select an option among preset values
/// This one let you select a sprite
/// </summary>
public class OptionSelectorImage : MonoBehaviour
{
[Header("Options")]
public OptionImage[] options;
[Header("Display")]
public Image select_img;
public UnityAction onChange;
private int position = 0;
void Start()
{
SetIndex(0);
}
void Update()
{
}
private void AfterChangeOption()
{
if (select_img != null)
select_img.sprite = GetSelectedImage();
onChange?.Invoke();
}
public void OnClickLeft()
{
position = (position + options.Length - 1) % options.Length;
AfterChangeOption();
}
public void OnClickRight()
{
position = (position + options.Length + 1) % options.Length;
AfterChangeOption();
}
public void SetIndex(int index)
{
position = index;
AfterChangeOption();
}
public void SetValue(string value)
{
for (int i = 0; i < options.Length; i++)
{
if (options[i].value == value)
position = i;
}
if (select_img != null)
select_img.sprite = GetSelectedImage();
}
public OptionImage GetSelected()
{
return options[position];
}
public string GetSelectedValue()
{
return options[position].value;
}
public Sprite GetSelectedImage()
{
return options[position].image;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c0c37f030b61e07419f316a4c49d4207
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,111 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
using TcgEngine;
namespace TcgEngine.UI
{
[System.Serializable]
public class OptionInt
{
public int value;
public string title;
}
/// <summary>
/// Option selector is a UI element with 2 arrows (left/right) to select an option among preset values
/// This one let you select a int
/// </summary>
public class OptionSelectorInt : MonoBehaviour
{
[Header("Options")]
public OptionInt[] options;
[Header("Display")]
public Text select_text;
public UnityAction onChange;
private int position = 0;
private bool is_locked = false;
void Start()
{
SetIndex(0);
}
void Update()
{
}
private void AfterChangeOption()
{
if (select_text != null)
select_text.text = GetSelectedTitle();
onChange?.Invoke();
}
public void OnClickLeft()
{
if (is_locked)
return;
position = (position + options.Length - 1) % options.Length;
AfterChangeOption();
}
public void OnClickRight()
{
if (is_locked)
return;
position = (position + options.Length + 1) % options.Length;
AfterChangeOption();
}
public void SetIndex(int index)
{
position = index;
if (select_text != null)
select_text.text = GetSelectedTitle();
}
public void SetValue(int value)
{
for (int i = 0; i < options.Length; i++)
{
if (options[i].value == value)
position = i;
}
if (select_text != null)
select_text.text = GetSelectedTitle();
}
public void SetLocked(bool locked)
{
is_locked = locked;
}
public OptionInt GetSelected()
{
return options[position];
}
public int GetSelectedValue()
{
return options[position].value;
}
public string GetSelectedTitle()
{
if (!string.IsNullOrWhiteSpace(options[position].title))
return options[position].title;
return options[position].value.ToString();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9da7ea7a061605c4a84fbe7db8ce19c5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,99 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
using TcgEngine;
using UnityEngine.EventSystems;
namespace TcgEngine.UI
{
/// <summary>
/// Display a pack and all its information
/// </summary>
public class PackUI : MonoBehaviour, IPointerClickHandler
{
public Image pack_img;
public Text pack_title;
public Text pack_quantity;
public Image quantity_bar;
public UnityAction<PackUI> onClick;
public UnityAction<PackUI> onClickRight;
private PackData pack;
void Awake()
{
}
public void SetPack(PackData pack)
{
this.pack = pack;
if (pack != null)
{
if (pack_title != null)
{
pack_title.enabled = true;
pack_title.text = pack.title;
}
pack_img.enabled = true;
pack_img.sprite = pack.pack_img;
}
if (pack_quantity != null)
pack_quantity.enabled = false;
if (quantity_bar != null)
quantity_bar.enabled = false;
}
public void SetPack(PackData pack, int quantity)
{
SetPack(pack);
if (pack_quantity != null)
{
pack_quantity.enabled = quantity > 0;
pack_quantity.text = quantity.ToString();
}
if (quantity_bar != null)
quantity_bar.enabled = quantity > 0;
}
public void Hide()
{
this.pack = null;
pack_img.enabled = false;
if(pack_title != null)
pack_title.enabled = false;
if (pack_quantity != null)
pack_quantity.enabled = false;
if (quantity_bar != null)
quantity_bar.enabled = false;
}
public void OnPointerClick(PointerEventData eventData)
{
if (eventData.button == PointerEventData.InputButton.Left)
{
if (onClick != null)
onClick.Invoke(this);
}
if (eventData.button == PointerEventData.InputButton.Right)
{
if (onClickRight != null)
onClickRight.Invoke(this);
}
}
public PackData GetPack()
{
return pack;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 33d1c4562ea83df49b2152ce40d46b33
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,174 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TcgEngine.Client;
using TcgEngine;
namespace TcgEngine.UI
{
/// <summary>
/// Main player UI inside the GameUI, inside the game scene
/// there is one for each player
/// </summary>
public class PlayerUI : MonoBehaviour
{
public bool is_opponent;
public Text pname;
public AvatarUI avatar;
public IconBar mana_bar;
public Text hp_txt;
public Text hp_max_txt;
public Animator[] secrets;
public GameObject dead_fx;
public AudioClip dead_audio;
public Sprite avatar_dead;
private bool killed = false;
private float timer = 0f;
private int prev_hp = 0;
private float delayed_damage_timer = 0f;
private static List<PlayerUI> ui_list = new List<PlayerUI>();
private void Awake()
{
ui_list.Add(this);
}
private void OnDestroy()
{
ui_list.Remove(this);
}
void Start()
{
pname.text = "";
hp_txt.text = "";
hp_max_txt.text = "";
for (int i = 0; i < secrets.Length; i++)
secrets[i].gameObject.SetActive(false);
avatar.onClick += OnClickAvatar;
GameClient.Get().onSecretTrigger += OnSecretTrigger;
}
void Update()
{
if (!GameClient.Get().IsReady())
return;
Player player = GetPlayer();
if (player != null)
{
pname.text = player.username;
mana_bar.value = player.mana;
mana_bar.max_value = player.mana_max;
hp_txt.text = prev_hp.ToString();
hp_max_txt.text = "/" + player.hp_max.ToString();
AvatarData adata = AvatarData.Get(player.avatar);
if (avatar != null && adata != null && !killed)
avatar.SetAvatar(adata);
delayed_damage_timer -= Time.deltaTime;
if (!IsDamagedDelayed())
prev_hp = player.hp;
}
timer += Time.deltaTime;
if (timer > 0.4f)
{
timer = 0f;
SlowUpdate();
}
}
void SlowUpdate()
{
Player player = GetPlayer();
if (player == null)
return;
for (int i = 0; i < secrets.Length; i++)
{
bool active = i < player.cards_secret.Count;
bool was_active = secrets[i].gameObject.activeSelf;
if (active != was_active)
secrets[i].gameObject.SetActive(active);
if (active && !was_active)
secrets[i].SetTrigger("appear");
if (active && !was_active && !is_opponent)
secrets[i].GetComponent<SecretIconUI>().SetCard(player.cards_secret[i]);
if (!active && was_active)
secrets[i].Rebind();
}
}
public void Kill()
{
killed = true;
avatar.SetImage(avatar_dead);
AudioTool.Get().PlaySFX("fx", dead_audio);
FXTool.DoFX(dead_fx, avatar.transform.position);
}
public void DelayDamage(int damage, float duration = 1f)
{
if (damage != 0)
{
delayed_damage_timer = duration;
}
}
public bool IsDamagedDelayed()
{
return delayed_damage_timer > 0f;
}
private void OnClickAvatar(AvatarData avatar)
{
Game gdata = GameClient.Get().GetGameData();
int player_id = GameClient.Get().GetPlayerID();
if (gdata.selector == SelectorType.SelectTarget && player_id == gdata.selector_player_id)
{
GameClient.Get().SelectPlayer(GetPlayer());
}
}
private void OnSecretTrigger(Card secret, Card triggerer)
{
Player player = GetPlayer();
int index = player.cards_secret.Count - 1;
if (player.player_id == secret.player_id && index >= 0 && index < secrets.Length)
{
secrets[index].SetTrigger("reveal");
}
}
public Player GetPlayer()
{
int player_id = is_opponent ? GameClient.Get().GetOpponentPlayerID() : GameClient.Get().GetPlayerID();
Game data = GameClient.Get().GetGameData();
return data.GetPlayer(player_id);
}
public static PlayerUI Get(bool opponent)
{
foreach (PlayerUI ui in ui_list)
{
if (ui.is_opponent == opponent)
return ui;
}
return null;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 424cb2a085f4507429325fe86087b8d0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,31 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TcgEngine;
namespace TcgEngine.UI
{
/// <summary>
/// UI element that shows a value with a progress bar
/// </summary>
public class ProgressBar : MonoBehaviour
{
public float value;
public float value_max;
public Image fill;
void Start()
{
}
void Update()
{
float ratio = value / Mathf.Max(value_max, 0.01f);
fill.fillAmount = ratio;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 228b238dd8f215b4b929e770061027a0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,63 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
namespace TcgEngine.UI
{
public class SecretIconUI : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler
{
private Card card = null;
private bool is_hover = false;
private static List<SecretIconUI> icon_list = new List<SecretIconUI>();
void Awake()
{
icon_list.Add(this);
}
void OnDestroy()
{
icon_list.Remove(this);
}
public void SetCard(Card card)
{
this.card = card;
}
public void OnPointerEnter(PointerEventData eventData)
{
is_hover = true;
}
public void OnPointerExit(PointerEventData eventData)
{
is_hover = false;
}
void OnDisable()
{
is_hover = false;
}
public Card GetCard()
{
return card;
}
public static Card GetHoverCard()
{
foreach (SecretIconUI line in icon_list)
{
if (line.card != null && line.is_hover)
return line.card;
}
return null;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8efc5ab4c29d95347aa53b7ff7b914d3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,60 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TcgEngine.Client;
using TcgEngine;
namespace TcgEngine.UI
{
/// <summary>
/// Box that appears when using the SelectTarget ability target
/// </summary>
public class SelectTargetUI : SelectorPanel
{
public Text title;
public Text desc;
private static SelectTargetUI _instance;
protected override void Awake()
{
_instance = this;
base.Awake();
}
protected override void Update()
{
base.Update();
Game game = GameClient.Get().GetGameData();
if (game != null && game.selector == SelectorType.None)
Hide();
}
public override void Show(AbilityData ability, Card caster)
{
this.title.text = ability.title;
//this.desc.text = ability.desc;
Show();
}
public void OnClickClose()
{
GameClient.Get().CancelSelection();
}
public override bool ShouldShow()
{
Game data = GameClient.Get().GetGameData();
int player_id = GameClient.Get().GetPlayerID();
return data.selector == SelectorType.SelectTarget && data.selector_player_id == player_id;
}
public static SelectTargetUI Get()
{
return _instance;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 200c15f6bde861a43b0c4704ebbd9df2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,46 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace TcgEngine.UI
{
public class SelectorPanel : UIPanel
{
private static List<SelectorPanel> panel_list = new List<SelectorPanel>();
protected override void Awake()
{
base.Awake();
panel_list.Add(this);
}
protected virtual void OnDestroy()
{
panel_list.Remove(this);
}
public virtual void Show(AbilityData ability, Card card)
{
//Override this to show panel
}
public virtual bool ShouldShow()
{
return false; //Override this function, when this panel should show
}
public static List<SelectorPanel> GetAll()
{
return panel_list;
}
public static void HideAll()
{
foreach (SelectorPanel panel in panel_list)
{
if(panel.IsVisible())
panel.Hide();
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8f86f694ec3015a408102200f23b6bcf
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,52 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
namespace TcgEngine.UI
{
public class SellDuplicatePanel : UIPanel
{
public Text error;
private static SellDuplicatePanel instance;
protected override void Awake()
{
base.Awake();
instance = this;
}
public async void OnClickSell()
{
SellDuplicateRequest req = new SellDuplicateRequest();
req.keep = 2;
string url = ApiClient.ServerURL + "/users/cards/sell/duplicate";
string jdata = ApiTool.ToJson(req);
error.text = "";
WebResponse res = await ApiClient.Get().SendPostRequest(url, jdata);
if (res.success)
{
CollectionPanel.Get().ReloadUser();
Hide();
}
else
{
error.text = res.error;
}
}
public override void Show(bool instant = false)
{
base.Show(instant);
error.text = "";
}
public static SellDuplicatePanel Get()
{
return instance;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5ce95a7fcf922b24ab9c82030e9d130a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,200 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
namespace TcgEngine.UI
{
public class SettingsPanel : UIPanel
{
public string tab_group;
public SliderDrag master_vol;
public SliderDrag music_vol;
public SliderDrag sfx_vol;
public SliderDrag quality;
public SliderDrag resolution;
public Toggle windowed;
public Text master_vol_txt;
public Text music_vol_txt;
public Text sfx_vol_txt;
public Text quality_txt;
public Text resolution_txt;
public static HashSet<string> reso_hash = new HashSet<string>();
public static List<Resolution> resolutions = new List<Resolution>();
private bool refreshing = false;
private static SettingsPanel instance;
protected override void Awake()
{
base.Awake();
instance = this;
}
protected override void Start()
{
base.Start();
//Default min max
master_vol.minValue = 0;
master_vol.maxValue = 100;
music_vol.minValue = 0;
music_vol.maxValue = 100;
sfx_vol.minValue = 0;
sfx_vol.maxValue = 100;
quality.minValue = 0;
resolution.minValue = 0;
master_vol.onValueChanged += RefreshText;
music_vol.onValueChanged += RefreshText;
sfx_vol.onValueChanged += RefreshText;
quality.onValueChanged += RefreshText;
resolution.onValueChanged += RefreshText;
master_vol.onEndDrag += OnChangeAudio;
music_vol.onEndDrag += OnChangeAudio;
sfx_vol.onEndDrag += OnChangeAudio;
quality.onEndDrag += OnChangeQuality;
resolution.onEndDrag += OnChangeResolution;
windowed.onValueChanged.AddListener(OnChangeWindowed);
foreach (Resolution reso in Screen.resolutions)
{
string reso_tag = reso.width + "x" + reso.height;
if (!reso_hash.Contains(reso_tag))
{
resolutions.Add(reso);
reso_hash.Add(reso_tag);
}
}
quality.maxValue = QualitySettings.names.Length - 1;
resolution.maxValue = resolutions.Count - 1;
foreach (TabButton btn in TabButton.GetAll(tab_group))
btn.onClick += OnClickTab;
}
private void RefreshPanel()
{
refreshing = true;
master_vol.value = AudioTool.Get().master_vol * 100f;
music_vol.value = AudioTool.Get().music_vol * 100f;
sfx_vol.value = AudioTool.Get().sfx_vol * 100f;
int quality_value = QualitySettings.GetQualityLevel();
int reso_value = GetResolutionIndex();
bool windowed_value = !Screen.fullScreen;
quality.value = quality_value;
resolution.value = reso_value;
windowed.isOn = windowed_value;
refreshing = false;
RefreshText();
}
private void RefreshText()
{
master_vol_txt.text = master_vol.value.ToString();
music_vol_txt.text = music_vol.value.ToString();
sfx_vol_txt.text = sfx_vol.value.ToString();
int quality_value = Mathf.RoundToInt(quality.value);
quality_txt.text = QualitySettings.names[quality_value];
resolution_txt.text = "";
int reso_value = Mathf.RoundToInt(resolution.value);
if (resolutions.Count > 0)
{
Resolution resolu = resolutions[reso_value];
string reso_tag = resolu.width + "x" + resolu.height + " " + Screen.currentResolution.refreshRate + "Hz";
resolution_txt.text = reso_tag;
}
}
private void OnChangeAudio()
{
if (!refreshing)
{
AudioTool.Get().master_vol = master_vol.value / 100f;
AudioTool.Get().sfx_vol = sfx_vol.value / 100f;
AudioTool.Get().music_vol = music_vol.value / 100f;
AudioTool.Get().RefreshVolume();
AudioTool.Get().SavePrefs();
RefreshText();
}
}
private void OnChangeQuality()
{
if (!refreshing)
{
int quality_value = Mathf.RoundToInt(quality.value);
QualitySettings.SetQualityLevel(quality_value);
RefreshText();
}
}
private void OnChangeResolution()
{
if (!refreshing && resolutions.Count > 0)
{
int reso_value = Mathf.RoundToInt(resolution.value);
Resolution resolu = resolutions[reso_value];
Screen.SetResolution(resolu.width, resolu.height, !windowed.isOn);
RefreshText();
}
}
private void OnChangeWindowed(bool val)
{
OnChangeResolution();
}
private void OnClickTab()
{
Hide();
}
public void OnClickOK()
{
Hide();
}
private int GetResolutionIndex()
{
int dist_min = 99999;
int closest = 0;
for (int i=0; i<resolutions.Count; i++)
{
Resolution res = resolutions[i];
int dist = Mathf.Abs(res.height - Screen.height) + Mathf.Abs(res.width - Screen.width);
if (dist < dist_min)
{
dist_min = dist;
closest = i;
}
}
return closest;
}
public override void Show(bool instant = false)
{
base.Show(instant);
RefreshPanel();
}
public override void Hide(bool instant = false)
{
base.Hide(instant);
}
public static SettingsPanel Get()
{
return instance;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 022a0dacae037e4408501f0f75f93cb5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,62 @@
using UnityEngine;
using System.Collections;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.UI;
namespace TcgEngine.UI
{
public class SliderDrag : MonoBehaviour, IPointerUpHandler, IPointerDownHandler
{
public UnityAction onStartDrag;
public UnityAction onEndDrag;
public UnityAction onValueChanged;
private Slider slider;
void Awake()
{
slider = GetComponent<Slider>();
slider.onValueChanged.AddListener((float v) => { onValueChanged?.Invoke(); });
}
public void OnPointerDown(PointerEventData eventData)
{
onStartDrag?.Invoke();
}
public void OnPointerUp(PointerEventData eventData)
{
onEndDrag?.Invoke();
}
public Slider Slider
{
get
{
if (slider == null)
slider = GetComponent<Slider>();
return slider;
}
}
public float maxValue
{
get { return Slider.maxValue; }
set { Slider.maxValue = value; }
}
public float minValue
{
get { return Slider.minValue; }
set { Slider.minValue = value; }
}
public float value
{
get { return Slider.value; }
set { Slider.value = value; }
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6b81b0da5becc5849a8a4dcbe6702a63
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,65 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
namespace TcgEngine.UI
{
/// <summary>
/// In the CardPreviewUI, a list of current status appear
/// This is one of those
/// </summary>
public class StatusLine : MonoBehaviour
{
public Text title;
public Text desc;
private float timer = 0f;
private void Start()
{
gameObject.SetActive(false);
}
void Update()
{
timer += Time.deltaTime;
}
public void SetLine(CardData icard, AbilityData ability)
{
if (!string.IsNullOrWhiteSpace(ability.desc))
{
title.text = ability.GetTitle();
desc.text = ability.GetDesc(icard);
gameObject.SetActive(true);
timer = 0f;
}
}
public void SetLine(StatusType effect, int value)
{
StatusData sdata = StatusData.Get(effect);
if (sdata != null)
SetLine(sdata, value);
}
public void SetLine(StatusData effect, int value)
{
if (!string.IsNullOrWhiteSpace(effect.desc))
{
title.text = effect.GetTitle();
desc.text = effect.GetDesc(value);
gameObject.SetActive(true);
timer = 0f;
}
}
public void Hide()
{
if (timer > 0.05f)
gameObject.SetActive(false);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e74074ad5fa74c84cb2e0a23824dc3ff
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,107 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Events;
namespace TcgEngine.UI
{
/// <summary>
/// A toggle button that let you change tab panel
/// </summary>
public class TabButton : MonoBehaviour
{
public string group;
public bool active;
public GameObject highlight;
public UIPanel ui_panel;
public UnityAction onClick;
public static UnityAction<TabButton> onClickAny;
private static List<TabButton> tab_list = new List<TabButton>();
private void Awake()
{
tab_list.Add(this);
}
private void OnDestroy()
{
tab_list.Remove(this);
}
void Start()
{
Button button = GetComponent<Button>();
if (button != null)
button.onClick.AddListener(OnClick);
if (active && ui_panel != null)
ui_panel.Show();
}
void Update()
{
if (highlight != null)
highlight.SetActive(active);
}
private void OnClick()
{
Activate();
onClick?.Invoke();
onClickAny?.Invoke(this);
}
public void Activate()
{
SetAll(group, false);
active = true;
if (ui_panel != null)
ui_panel.Show();
}
public void Deactivate()
{
active = false;
if (ui_panel != null)
ui_panel.Hide();
}
public bool IsActive()
{
return active;
}
public static void SetAll(string group, bool act)
{
foreach (TabButton btn in tab_list)
{
if (btn.group == group)
{
btn.active = act;
if(btn.ui_panel != null)
btn.ui_panel.SetVisible(act);
}
}
}
public static List<TabButton> GetAll(string group)
{
List<TabButton> glist = new List<TabButton>();
foreach (TabButton btn in tab_list)
{
if (btn.group == group)
glist.Add(btn);
}
return glist;
}
public static List<TabButton> GetAll()
{
return tab_list;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 63c2a82fe228eb1448987b03b5e45ab7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,46 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TcgEngine;
namespace TcgEngine.UI
{
/// <summary>
/// Changes the color of a unity ui toggle text
/// </summary>
public class ToggleText : MonoBehaviour
{
public Color on_color = Color.yellow;
public Color off_color = Color.white;
private Toggle toggle;
private Text toggle_txt;
private bool previous = false;
void Awake()
{
toggle = GetComponent<Toggle>();
toggle_txt = GetComponentInChildren<Text>();
}
private void Start()
{
Refresh();
}
void Update()
{
if (previous != toggle.isOn)
Refresh();
}
private void Refresh()
{
toggle_txt.color = toggle.isOn ? on_color : off_color;
previous = toggle.isOn;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a6af74289ee0b364a823f4503fe820b1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,41 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
namespace TcgEngine.UI
{
/// <summary>
/// Shows a trait or custom card stats, add it to the array of a CardUI
/// </summary>
public class TraitUI : MonoBehaviour
{
public TraitData trait;
public Image bg;
public Text text;
void Start()
{
}
public void SetCard(Card card)
{
bool has_trait = card.HasTrait(trait);
int val = card.GetTraitValue(trait);
text.text = val.ToString();
bg.enabled = has_trait;
text.enabled = has_trait;
}
public void SetCard(CardData card)
{
bool has_trait = card.HasTrait(trait);
int val = card.GetStat(trait.id);
text.text = val.ToString();
bg.enabled = has_trait;
text.enabled = has_trait;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ec3511fcffc77c147bd5d1d09bad4072
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,51 @@
using System.Collections;
using System.Collections.Generic;
using TcgEngine.Client;
using UnityEngine;
namespace TcgEngine.UI
{
/// <summary>
/// History bar shows all the previous moved perform by a player this turn
/// </summary>
public class TurnHistoryBar : MonoBehaviour
{
public bool is_opponent;
public TurnHistoryLine[] history_lines;
void Start()
{
}
void Update()
{
if (!GameClient.Get().IsReady())
return;
int player_id = is_opponent ? GameClient.Get().GetOpponentPlayerID() : GameClient.Get().GetPlayerID();
Game data = GameClient.Get().GetGameData();
Player player = data.GetPlayer(player_id);
if (player != null && player.history_list != null)
{
int index = 0;
foreach (ActionHistory order in player.history_list)
{
if (index < history_lines.Length)
{
history_lines[index].SetLine(order);
index++;
}
}
while (index < history_lines.Length)
{
history_lines[index].Hide();
index++;
}
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 92cc6a8ff3d92d543b6827277c986100
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,148 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TcgEngine.Client;
using UnityEngine.EventSystems;
namespace TcgEngine.UI
{
/// <summary>
/// One of the squares in the history bar
/// </summary>
public class TurnHistoryLine : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler
{
public HoverTargetUI hover;
public Image card_img;
private Card card;
private float timer = 0f;
private bool is_hover = false;
private static List<TurnHistoryLine> line_list = new List<TurnHistoryLine>();
void Awake()
{
line_list.Add(this);
}
void OnDestroy()
{
line_list.Add(this);
}
void Start()
{
gameObject.SetActive(false);
}
private void Update()
{
timer += Time.deltaTime;
}
public void SetLine(ActionHistory history)
{
Game gdata = GameClient.Get().GetGameData();
Card acard = gdata.GetCard(history.card_uid);
Card target = gdata.GetCard(history.target_uid);
Player ptarget = gdata.GetPlayer(history.target_id);
CardData icard = CardData.Get(history.card_id);
CardData itarget = CardData.Get(target?.card_id);
VariantData variant = acard.VariantData;
AbilityData iability = AbilityData.Get(history.ability_id);
card = acard;
if (icard == null)
return;
if (history.type == GameAction.PlayCard)
{
string text = icard.title + " was played";
SetLine(icard, variant, text);
}
if (history.type == GameAction.Move)
{
string text = icard.title + " moved";
SetLine(icard, variant, text);
}
if (history.type == GameAction.Attack && itarget != null)
{
string text = icard.title + " attacked " + itarget.title;
SetLine(icard, variant, text);
}
if (history.type == GameAction.AttackPlayer && ptarget != null)
{
string text = icard.title + " attacked " + ptarget.username;
SetLine(icard, variant, text);
}
if (history.type == GameAction.CastAbility && iability != null)
{
if (iability.target == AbilityTarget.SelectTarget && itarget != null)
{
string text = icard.title + " casted " + iability.GetTitle() + " on " + itarget.title;
SetLine(icard, variant, text);
}
else
{
string text = icard.title + " casted " + iability.GetTitle();
SetLine(icard, variant, text);
}
}
if (history.type == GameAction.SecretTriggered)
{
string text = icard.title + " was triggered";
SetLine(icard, variant, text);
}
}
public void SetLine(CardData icard, VariantData variant, string text)
{
card_img.sprite = icard.GetFullArt(variant);
hover.text = text;
gameObject.SetActive(true);
timer = 0f;
}
public void Hide()
{
card = null;
if (timer > 0.05f)
gameObject.SetActive(false);
}
public void OnPointerEnter(PointerEventData eventData)
{
timer = 0f;
is_hover = true;
}
public void OnPointerExit(PointerEventData eventData)
{
timer = 0f;
is_hover = false;
}
void OnDisable()
{
is_hover = false;
}
public static Card GetHoverCard()
{
foreach (TurnHistoryLine line in line_list)
{
if (line.card != null && line.is_hover)
return line.card;
}
return null;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ea734741506910f4ab2681d9d9528ecf
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Some files were not shown because too many files have changed in this diff Show More