Skip to content

Commit

Permalink
Fix game and card creation
Browse files Browse the repository at this point in the history
  • Loading branch information
davidmfinol committed Jan 14, 2024
1 parent 2f5f60d commit 4ad4724
Show file tree
Hide file tree
Showing 8 changed files with 754 additions and 171 deletions.
307 changes: 170 additions & 137 deletions Assets/Prefabs/Menus/Card Editor Menu.prefab

Large diffs are not rendered by default.

449 changes: 442 additions & 7 deletions Assets/Prefabs/Menus/Card Game Editor Menu.prefab

Large diffs are not rendered by default.

7 changes: 4 additions & 3 deletions Assets/Prefabs/Menus/Deck Load Menu.prefab

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

44 changes: 41 additions & 3 deletions Assets/Scripts/Cgs/Cards/CardEditorMenu.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
using FinolDigital.Cgs.CardGameDef.Unity;
using JetBrains.Annotations;
using SFB;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
Expand All @@ -32,6 +33,8 @@ public class CardEditorMenu : Modal
public const string ImageImportFailedWarningMessage = "Failed to get the image! Unable to import the card.";

public GameObject downloadMenuPrefab;
public RectTransform scrollRectContent;
public RectTransform cardPropertyTemplate;
public List<InputField> inputFields;
public InputField cardIdInputField;
public InputField setCodeInputField;
Expand All @@ -46,7 +49,9 @@ public string CardId
get => _cardId;
set
{
_cardId = UnityFileMethods.GetSafeFileName(value)[..64];
_cardId = UnityFileMethods.GetSafeFileName(value);
if (_cardId.Length >= 64)
_cardId = _cardId[..64];
if (!_cardId.Equals(cardIdInputField.text))
cardIdInputField.text = _cardId;
}
Expand All @@ -61,6 +66,8 @@ public string SetCode
set
{
_setCode = UnityFileMethods.GetSafeFilePath(value);
if (_cardId.Length >= 64)
_cardId = _cardId[..64];
if (!_setCode.Equals(setCodeInputField.text))
setCodeInputField.text = _setCode;
}
Expand Down Expand Up @@ -100,9 +107,12 @@ private Sprite CardImageSprite

private UnityAction _onCreationCallback;

private readonly List<TMP_InputField> _inputFields = new();

private void Update()
{
if (!IsFocused || inputFields.Any(inputField => inputField.isFocused))
if (!IsFocused || inputFields.Any(inputField => inputField.isFocused) ||
_inputFields.Any(field => field.isFocused))
return;

if ((Inputs.IsSubmit || Inputs.IsNew) && saveButton.interactable)
Expand All @@ -120,7 +130,21 @@ public void Show(UnityAction onCreationCallback)
Show();
SetCode = string.Concat(CardGameManager.Current.Name.Where(char.IsLetterOrDigit));
cardImage.sprite = CardImageSprite != null ? CardImageSprite : CardGameManager.Current.CardBackImageSprite;

_onCreationCallback = onCreationCallback;

for (var i = _inputFields.Count - 1; i >= 0; i--)
Destroy(_inputFields[i].transform.parent.gameObject);
_inputFields.Clear();
foreach (var propertyDef in CardGameManager.Current.CardProperties.Where(def =>
PropertyType.String.Equals(def.Type)))
{
var newTransform = Instantiate(cardPropertyTemplate.gameObject, scrollRectContent)
.transform;
newTransform.gameObject.SetActive(true);
newTransform.GetComponentInChildren<Text>().text = propertyDef.Display;
_inputFields.Add(newTransform.GetComponentInChildren<TMP_InputField>());
}
}

[UsedImplicitly]
Expand Down Expand Up @@ -213,11 +237,25 @@ private IEnumerator SaveCard()

saveButton.interactable = false;

var propertyDefValuePairs = new Dictionary<string, PropertyDefValuePair>();
var stringProperties =
CardGameManager.Current.CardProperties.Where(def => PropertyType.String.Equals(def.Type)).ToList();
for (var i = 0; i < stringProperties.Count && i < _inputFields.Count; i++)
{
var propertyName = stringProperties[i].Name;
var propertyDefValuePair = new PropertyDefValuePair
{
Def = stringProperties[i],
Value = _inputFields[i].text
};
propertyDefValuePairs[propertyName] = propertyDefValuePair;
}

var card = new UnityCard(CardGameManager.Current,
string.IsNullOrEmpty(CardId)
? Guid.NewGuid().ToString().ToUpper()
: CardId, CardName,
string.IsNullOrEmpty(SetCode) ? Set.DefaultCode : SetCode, null,
string.IsNullOrEmpty(SetCode) ? Set.DefaultCode : SetCode, propertyDefValuePairs,
false)
{ImageWebUrl = CardImageUri.AbsoluteUri};
yield return UnityFileMethods.SaveUrlToFile(CardImageUri.AbsoluteUri, card.ImageFilePath);
Expand Down
21 changes: 17 additions & 4 deletions Assets/Scripts/Cgs/Menu/CardGameEditorMenu.cs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ public string Height

[UsedImplicitly] public string RulesUrl { get; set; }

[UsedImplicitly] public string CardProperty { get; set; } = "description";

private void Update()
{
if (!IsFocused || inputFields.Any(inputField => inputField.isFocused))
Expand Down Expand Up @@ -350,6 +352,16 @@ public void StartCreation()
StartCoroutine(CreateGame());
}

private static List<PropertyDef> Of(string property)
{
var propertyDefs = new List<PropertyDef>();
var textInfo = CultureInfo.CurrentCulture.TextInfo;
var display = textInfo.ToTitleCase(property);
var propertyDef = new PropertyDef(property, PropertyType.String, display);
propertyDefs.Add(propertyDef);
return propertyDefs;
}

private IEnumerator CreateGame()
{
ValidateCreateButton();
Expand All @@ -374,14 +386,15 @@ private IEnumerator CreateGame()
PlayMatImageFileType = PlayMatImageFileType == 0 ? "png" : "jpg",
PlayMatImageUrl = _game.PlayMatImageUrl,
Copyright = string.IsNullOrWhiteSpace(Copyright) ? "" : Copyright,
RulesUrl = Uri.IsWellFormedUriString(RulesUrl, UriKind.Absolute) ? new Uri(RulesUrl) : null
RulesUrl = Uri.IsWellFormedUriString(RulesUrl, UriKind.Absolute) ? new Uri(RulesUrl) : null,
CardPrimaryProperty = string.IsNullOrWhiteSpace(CardProperty) ? "" : CardProperty,
CardProperties = string.IsNullOrWhiteSpace(CardProperty) ? new List<PropertyDef>() : Of(CardProperty)
};

if (!Directory.Exists(newCardGame.GameDirectoryPath))
Directory.CreateDirectory(newCardGame.GameDirectoryPath);
var defaultContractResolver = new DefaultContractResolver()
{NamingStrategy = new CamelCaseNamingStrategy()};
var jsonSerializerSettings = new JsonSerializerSettings()
var defaultContractResolver = new DefaultContractResolver {NamingStrategy = new CamelCaseNamingStrategy()};
var jsonSerializerSettings = new JsonSerializerSettings
{
ContractResolver = defaultContractResolver,
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
Expand Down
12 changes: 7 additions & 5 deletions Assets/Scripts/UnityExtensionMethods/UnityFileMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -229,11 +229,13 @@ public static IEnumerator SaveUrlToFile(string url, string filePath, string post
yield break;
}

var uriBuilder = new UriBuilder(url)
{
Scheme = Uri.UriSchemeHttps,
Port = -1 // default port for scheme
};
var uriBuilder = url.StartsWith("http")
? new UriBuilder(url)
{
Scheme = Uri.UriSchemeHttps, // enforce https over http
Port = -1 // default port for scheme
}
: new UriBuilder(url);
var uri = uriBuilder.Uri;

using var unityWebRequest =
Expand Down
77 changes: 69 additions & 8 deletions Assets/Tests/PlayMode/CardGameManagerTests.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Cgs;
using FinolDigital.Cgs.CardGameDef;
using FinolDigital.Cgs.CardGameDef.Unity;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using NUnit.Framework;
using UnityEngine;
using UnityEngine.TestTools;
using UnityExtensionMethods;
using Object = UnityEngine.Object;

namespace Tests.PlayMode
Expand All @@ -31,6 +37,69 @@ public void Setup()
Object.Instantiate(Resources.Load<GameObject>("CardGameManager"));
}

[UnityTest]
public IEnumerator CanCreateNewGameAndCard()
{
var newCardGame = new UnityCardGame(CardGameManager.Instance, "gameName")
{
AutoUpdate = -1, CardSize = new Float2(250, 350),
BannerImageFileType = "png",
BannerImageUrl = null,
CardBackImageFileType = "png",
CardBackImageUrl = null,
CardSetIdentifier = "setCode",
PlayMatImageFileType = "png",
PlayMatImageUrl = null,
Copyright = "",
RulesUrl = null,
CardPrimaryProperty = "",
CardProperties = new List<PropertyDef>()
};
if (Directory.Exists(newCardGame.GameDirectoryPath))
Directory.Delete(newCardGame.GameDirectoryPath, true);

var previousDeveloperMode = PlayerPrefs.GetInt("DeveloperMode", 0);
PlayerPrefs.SetInt("DeveloperMode", 1);

Directory.CreateDirectory(newCardGame.GameDirectoryPath);
var defaultContractResolver = new DefaultContractResolver {NamingStrategy = new CamelCaseNamingStrategy()};
var jsonSerializerSettings = new JsonSerializerSettings
{
ContractResolver = defaultContractResolver,
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
};
File.WriteAllText(newCardGame.GameFilePath,
JsonConvert.SerializeObject(newCardGame, jsonSerializerSettings));

yield return CardGameManager.Instance.UpdateCardGame(newCardGame);

CardGameManager.Instance.AllCardGames[newCardGame.Id] = newCardGame;
CardGameManager.Instance.Select(newCardGame.Id);

var card = new UnityCard(CardGameManager.Current,
Guid.NewGuid().ToString().ToUpper()
, "Test",
Set.DefaultCode, null,
false);

yield return UnityFileMethods.SaveUrlToFile(new Uri(UnityFileMethods.CacheFile(
Application.streamingAssetsPath
+ "/" +
Tags.StandardPlayingCardsDirectoryName + "/" +
"CardBack.png")).AbsoluteUri,
card.ImageFilePath);

CardGameManager.Current.Add(card);

Assert.IsTrue(CardGameManager.Current.HasLoaded);
Assert.IsTrue(string.IsNullOrEmpty(CardGameManager.Current.Error));
Assert.IsTrue(CardGameManager.Current.Cards.Count > 0);
Assert.IsTrue(File.Exists(CardGameManager.Current.Cards.First().Value.ImageFilePath));
Assert.AreEqual("gameName", CardGameManager.Current.Name);

PlayerPrefs.SetInt("DeveloperMode", previousDeveloperMode);
}

[UnityTest]
[Timeout(3600000)]
public IEnumerator CanGetGames()
Expand Down Expand Up @@ -102,13 +171,5 @@ public IEnumerator CanLoadDefaultGames()
Assert.AreEqual("Dominoes", CardGameManager.Current.Name);
#endif
}

[Test]
[Ignore("TODO")]
public void CanRecoverFromFailure()
{
// TODO:
Assert.Fail();
}
}
}
8 changes: 4 additions & 4 deletions docs/pages/roadmap.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@ permalink: roadmap.html
# Roadmap

## What's New - v1.102
- Bug-Fix: Game Creation Menu copyright on portrait
- Bug-Fix: Card Creation description
- Bug-Fix: Card Creation import image
- Bug-Fix: Card Creation

## Active Sprint
- Bug-Fix: Sync button does not update Game
Expand Down Expand Up @@ -36,6 +34,8 @@ permalink: roadmap.html
- Game-Play: gamePlayDefaultDecks and gamePlayDefaultCards
- Game-Play: Apply permissions for each other's decks/stacks/cards, shuffling, moving, deleting, viewing facedown, etc
- Game-Play: Move card to zone, stack, or drawer (E)

## Backlog - 2024 Q3
- Game-Play: Rename Stacks
- Game-Play: Add restart button in Play Settings Menu
- Decks: Support organizing decks into folders
Expand All @@ -49,7 +49,7 @@ permalink: roadmap.html
- Cards: Support more than 1 card face (Dual-Faced Cards)
- Cards: Support multiple card backs

## Backlog - 2024 Q3
## Backlog - 2024 Q4
- Game-Play: Support multiple playmats
- Game-Play: Setup gamepad and keyboard shortcuts/hotkeys for Game-Play and Settings
- Platforms: Display gamepad and keyboard shortcuts/hotkeys in-app
Expand Down

0 comments on commit 4ad4724

Please sign in to comment.