Wes xx build fix

This commit is contained in:
Dries Van Schuylenbergh
2023-03-09 12:44:11 +00:00
committed by Louis Adriaens
parent 601cf38c61
commit 2fa54620ef
74 changed files with 1009 additions and 214 deletions

View File

@@ -0,0 +1,79 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using UnityEngine;
[Serializable]
// Can not be created from Editor
public class Progress
{
[Serializable]
// Helper class to serialize into byte[]
protected class DataEntry
{
public string key;
public List<byte> bytes = new List<byte>();
public DataEntry(string key, byte[] data)
{
this.key = key;
this.bytes = new List<byte>(data);
}
}
[Header("Course or Minigame")]
[SerializeField]
// values belonging to a certain key, in List (which can be serialized)
private List<DataEntry> entries = new List<DataEntry>();
// Add new `key` := `value`, returns `true` if successful
public bool AddOrUpdate<T>(string key, T data)
{
if (data == null)
return false;
DataEntry entry = entries.Find(x => x.key == key);
// Hacky serialization stuff
BinaryFormatter bf = new BinaryFormatter();
using (MemoryStream ms = new MemoryStream())
{
bf.Serialize(ms, data);
if (entry != null)
{
entry.bytes.Clear();
entry.bytes.AddRange(ms.ToArray());
}
else
{
entries.Add(new DataEntry(key, ms.ToArray()));
}
return true;
}
}
// Get the value of type `T` belonging to `key`
public T Get<T>(string key)
{
BinaryFormatter bf = new BinaryFormatter();
using (MemoryStream ms = new MemoryStream())
{
// Find the correct key
foreach (DataEntry entry in entries)
{
if (entry.key == key)
{
// Hacky serialization stuff
byte[] data = entry.bytes.ToArray();
ms.Write(data, 0, data.Length);
ms.Seek(0, SeekOrigin.Begin);
return (T)bf.Deserialize(ms);
}
}
}
// Raise an exception when key is not found
throw new KeyNotFoundException();
}
}

View File

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

View File

@@ -0,0 +1,62 @@
using System;
using System.Collections.Generic;
using UnityEngine;
[Serializable]
public class User
{
[Header("Personal data")]
// User nickname
public string username;
// User avatar
public Sprite avatar;
[Header("Personal settings")]
// TODO: set personal settings and preferences
[Header("Progress")]
// Total playtime
public double playtime;
[SerializeField]
// List of courses a user started/completed
public List<Progress> courses = new List<Progress>();
[SerializeField]
// List of minigames a user played
public List<Progress> minigames = new List<Progress>();
// Get a list of all recently started courses, returns a list of tuples of `<CourseIndex idx, float courseProgress>`
public List<Tuple<CourseIndex, float>> GetRecentCourses()
{
// TODO: return better results (for now only return all courses)
List<Tuple<CourseIndex, float>> recentCourses = new List<Tuple<CourseIndex, float>>();
foreach (Progress courseProgress in courses)
{
CourseIndex idx = courseProgress.Get<CourseIndex>("courseIndex");
float progress = courseProgress.Get<float>("courseProgress");
recentCourses.Add(Tuple.Create<CourseIndex, float>(idx, progress));
}
return recentCourses;
}
// Get a list of all recommended courses, returns a list of tuples of `<CourseIndex idx, float courseProgress>`
public List<Tuple<CourseIndex, float>> GetRecommendedCourses()
{
List<Tuple<CourseIndex, float>> recommenedCourses = new List<Tuple<CourseIndex, float>>();
if (courses.Count == 0)
{
recommenedCourses.Add(Tuple.Create<CourseIndex, float>(CourseIndex.FINGERSPELLING, 0.0f));
}
else
{
// TODO: return better results (for now only return all courses)
foreach (Progress courseProgress in courses)
{
CourseIndex idx = courseProgress.Get<CourseIndex>("courseIndex");
float progress = courseProgress.Get<float>("courseProgress");
recommenedCourses.Add(Tuple.Create<CourseIndex, float>(idx, progress));
}
}
return recommenedCourses;
}
}

View File

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

View File

@@ -0,0 +1,98 @@
using System.Collections.Generic;
using System.Text.RegularExpressions;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class UserCreationScreen : MonoBehaviour
{
// Max length of a username
private const int MAX_USERNAME_LENGTH = 12;
[Header("UI References")]
// Reference to the input text field for username
public TMP_InputField inputName;
// Reference to the avatar-list container
public Transform avatarsContainer;
[Header("Prefab")]
// Avatar prefab
public GameObject avatarPrefab;
// List of all sprites that are supported as avatars
public List<Sprite> sprites = new List<Sprite>();
[Header("Users List")]
// Reference to the UserList ScriptableObject
public UserList users;
[SerializeField]
// Current selected avatar
private int selectedAvatar = 0;
// List of references to avatar background sprites (so we can color them nicely)
private List<Image> avatars = new List<Image>();
void Start()
{
for (int i = 0; i < sprites.Count; i++)
{
// Create instance of prefab
GameObject instance = GameObject.Instantiate(avatarPrefab, avatarsContainer);
// Store value of i so we can use it the callback (else it would get the value of sprites.Count)
int x = i;
// Add onClick callback
instance.GetComponent<Button>().onClick.AddListener(() => UpdateAvatar(x));
// Store reference to image for fancy coloring
Image background = instance.GetComponent<Image>();
avatars.Add(background);
// Set background color
background.color = selectedAvatar == i ? Color.blue : Color.gray;
// Find correct component for setting the sprite
foreach (Image img in background.GetComponentsInChildren<Image>())
if (img != background)
{
img.sprite = sprites[i];
break;
}
}
}
// Update the current selected avatar
private void UpdateAvatar(int newAvatar)
{
avatars[selectedAvatar].color = Color.gray;
selectedAvatar = newAvatar;
avatars[selectedAvatar].color = Color.blue;
}
// Check if a given string is a correct username (using Regex)
static public bool IsValidUsername(string username)
{
return new Regex($@"^[abcdefghijklmnopqrstuvwxyz]{{1,{MAX_USERNAME_LENGTH}}}$").IsMatch(username);
}
// Create a new user (will be called by button)
public void CreateUser()
{
string username = inputName.text;
if (IsValidUsername(username))
{
if (users.GetUserByUsername(username) == null)
{
// Create a new entry in the UserList ScriptableObject
users.CreateAndAddNewUser(username, sprites[selectedAvatar]);
// TODO: change scene, for now just change to StartScreen
SceneManager.LoadScene("Common/Scenes/StartScreen");
}
// TODO: give more feedback to user
// Warn user that username already exists
else Debug.LogWarning($"Username '{username}' already exists!");
}
// TODO: give more feedback to user
// Warn user that username is invalid
else Debug.LogWarning($"Invalid username '{username}'!");
}
}

View File

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

View File

@@ -0,0 +1,89 @@
using System;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
[CreateAssetMenu(menuName = "Create new Scriptable/UserList")]
public class UserList : ScriptableObject
{
// Serializable UserList content
[Serializable]
public class StoredUserList
{
public int currentUserIndex;
public List<User> storedUsers = new List<User>();
}
[Header("Users")]
[SerializeField]
// Reference to serializable version of UserList
private StoredUserList storedUserList = new StoredUserList();
// Path to .json file
public static string PATH = null;
void OnEnable()
{
PATH = $"{Application.dataPath}/users.json";
Load();
}
// Create a new User
public User CreateNewUser(string name, Sprite avatar)
{
User user = new User();
user.username = name;
user.avatar = avatar;
return user;
}
// Create a new User and add to list
public User CreateAndAddNewUser(string name, Sprite avatar)
{
User user = CreateNewUser(name, avatar);
storedUserList.storedUsers.Add(user);
Save();
return user;
}
// Get user by username, returns `null` if no user can be found with such name
public User GetUserByUsername(string username)
{
foreach (User user in storedUserList.storedUsers)
if (user.username == username) return user;
return null;
}
// Get a list of all users
public List<User> GetUsers()
{
return storedUserList.storedUsers;
}
// Get the current active user
public User GetCurrentUser()
{
return storedUserList.storedUsers[storedUserList.currentUserIndex];
}
// Save the userList
public void Save()
{
string json = JsonUtility.ToJson(storedUserList);
File.CreateText(PATH).Close();
File.WriteAllText(PATH, json);
}
// Load the userList into this object
public void Load()
{
try
{
storedUserList.storedUsers.Clear();
string text = File.ReadAllText(PATH);
storedUserList = JsonUtility.FromJson<StoredUserList>(text);
}
catch (FileNotFoundException) { Debug.Log($"Path '{PATH}' not found"); }
}
}

View File

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