Compare commits
101 Commits
UI-showcas
...
WES-XX-tim
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2736de811d | ||
| b729981edf | |||
|
|
a0dd0ae39f | ||
|
|
f63b49ebc7 | ||
|
|
3dded6c3e6 | ||
|
|
10649e9b85 | ||
|
|
349ca1cb44 | ||
|
|
785e56b883 | ||
|
|
8c69ec3cc6 | ||
|
|
3d99184717 | ||
|
|
7505ae7262 | ||
|
|
1f5b855f61 | ||
|
|
384c7a249d | ||
|
|
bdf3c05102 | ||
|
|
584dc0d97d | ||
|
|
084724c175 | ||
|
|
1cceb3cb89 | ||
|
|
f99a73f230 | ||
|
|
e0c948292d | ||
|
|
7df6ea1ecd | ||
|
|
e9753a727e | ||
|
|
a4c29a3146 | ||
|
|
53fc361af4 | ||
|
|
d593f22c10 | ||
|
|
9b88537d70 | ||
|
|
96b1c9f6bc | ||
|
|
1e09f09dae | ||
|
|
1413f80d73 | ||
|
|
227099631e | ||
|
|
48b915acba | ||
|
|
672ff367e2 | ||
|
|
ae29ef9835 | ||
| c3ebf48cdc | |||
|
|
59bf2392d8 | ||
|
|
e9db885301 | ||
|
|
43887af670 | ||
|
|
06aa9206ac | ||
|
|
c24fe037f6 | ||
|
|
b10358930b | ||
|
|
89f343780a | ||
|
|
259259ac9c | ||
|
|
bc502361cd | ||
|
|
fb234480f7 | ||
|
|
b9bbef8dcf | ||
|
|
c4b6c60288 | ||
| c457a195df | |||
|
|
67575cfbbd | ||
|
|
05b230dd9d | ||
|
|
94d2ccfa8d | ||
|
|
966475455a | ||
|
|
4fdb8f95cb | ||
|
|
fcd8acad1e | ||
| 5b4a3ec4e7 | |||
|
|
77850bfbe6 | ||
|
|
f9fff14662 | ||
| aed09649e3 | |||
|
|
c8dfa96c8f | ||
|
|
4e9d801e61 | ||
|
|
04d9a4bf2b | ||
|
|
2b71bde592 | ||
|
|
73c4756f19 | ||
|
|
f5615bbef3 | ||
|
|
8670fcc4ce | ||
|
|
e6d10db5ca | ||
|
|
8db7c80dad | ||
|
|
197a6200c1 | ||
|
|
68372d859b | ||
|
|
2a7dd16f5f | ||
|
|
e6b0cbd596 | ||
|
|
c358ac59e4 | ||
|
|
c20cd89c3a | ||
|
|
5f4408063f | ||
| 3499e61bb0 | |||
|
|
aefc75f3c4 | ||
|
|
f95e34c6fe | ||
|
|
edf1805a92 | ||
|
|
a808e73a29 | ||
|
|
b955d2164c | ||
|
|
e96f1ff7ca | ||
|
|
b8cdcd128b | ||
|
|
ea13788199 | ||
|
|
564ec209c7 | ||
| a3735af649 | |||
|
|
692b4318bf | ||
|
|
0015c1453c | ||
|
|
c78ef0e773 | ||
|
|
45f545b13f | ||
|
|
d3af75f676 | ||
|
|
5f7216f24c | ||
|
|
b012e40df8 | ||
|
|
f69e2385fc | ||
|
|
37905a904c | ||
|
|
0019a4d07f | ||
|
|
4402e80d0c | ||
|
|
d95a6590d5 | ||
|
|
7b6eb4db69 | ||
|
|
8696aff135 | ||
|
|
001cf6dedb | ||
|
|
669bcb3793 | ||
|
|
668b769094 | ||
|
|
fee989006c |
46
.drone.yml
46
.drone.yml
@@ -27,7 +27,7 @@ steps:
|
||||
pull: if-not-exists
|
||||
image: sonarsource/sonar-scanner-cli
|
||||
commands:
|
||||
- sonar-scanner -Dsonar.host.url=$SONAR_HOST -Dsonar.login=$SONAR_TOKEN -Dsonar.projectKey=$SONAR_PROJECT_KEY -Dsonar.coverageReportPaths="./code_coverage/Report/SonarQube.xml"
|
||||
- sonar-scanner -Dsonar.host.url=$SONAR_HOST -Dsonar.login=$SONAR_TOKEN -Dsonar.projectKey=$SONAR_PROJECT_KEY -Dsonar.projectVersion=$DRONE_REPO_BRANCH-$DRONE_COMMIT_AUTHOR-$DRONE_COMMIT -Dsonar.coverageReportPaths="./code_coverage/Report/SonarQube.xml"
|
||||
environment:
|
||||
SONAR_HOST:
|
||||
from_secret: sonar_host
|
||||
@@ -37,47 +37,3 @@ steps:
|
||||
from_secret: sonar_project_key
|
||||
|
||||
|
||||
---
|
||||
kind: pipeline
|
||||
name: builds
|
||||
type: docker
|
||||
|
||||
trigger:
|
||||
event:
|
||||
- push
|
||||
branch:
|
||||
- master
|
||||
- development
|
||||
- Automatic-Builds
|
||||
|
||||
steps:
|
||||
- name: unity-builds
|
||||
image: docker.io/library/unity-runner:0.1
|
||||
commands:
|
||||
- mkdir -p ./wesign-builds/{tmp,WeSign-Windows,WeSign-Linux,WeSign-MacOS}
|
||||
- /opt/unity/editors/2021.3.19f1/Editor/Unity -batchmode -nographics -projectPath . -buildWindowsPlayer ./wesign-builds/tmp/WeSign-Windows.exe -quit --headless || true
|
||||
- chmod 777 -R .
|
||||
- /opt/unity/editors/2021.3.19f1/Editor/Unity -batchmode -nographics -projectPath . -buildWindowsPlayer ./wesign-builds/WeSign-Windows/WeSign.exe -quit --headless
|
||||
- /opt/unity/editors/2021.3.19f1/Editor/Unity -batchmode -nographics -projectPath . -buildLinux64Player ./wesign-builds/WeSign-Linux/WeSign -quit --headless
|
||||
- /opt/unity/editors/2021.3.19f1/Editor/Unity -batchmode -nographics -projectPath . -buildOSXUniversalPlayer ./wesign-builds/WeSign-MacOS/WeSign.app -quit --headless
|
||||
- name: commit-files
|
||||
image: alpine/git
|
||||
environment:
|
||||
GIT_AUTHOR_NAME: DroneCI
|
||||
GIT_AUTHOR_EMAIL: droneci@wesign.com
|
||||
GIT_COMMITTER_NAME: DroneCI
|
||||
GIT_COMMITTER_EMAIL: droneci@wesign.com
|
||||
commands:
|
||||
- git config --global user.name "DroneCI"
|
||||
- git config --global user.email "droneci@wesign.com"
|
||||
|
||||
- zip -r ./wesign-builds/WeSign-Windows.zip ./wesign-builds/WeSign-Windows
|
||||
- zip -r ./wesign-builds/WeSign-MacOS.zip ./wesign-builds/WeSign-MacOS
|
||||
- zip -r ./wesign-builds/WeSign-Linux.zip ./wesign-builds/WeSign-Linux
|
||||
|
||||
- git add ./wesign-builds/WeSign-Windows.zip
|
||||
- git add ./wesign-builds/WeSign-MacOS.zip
|
||||
- git add ./wesign-builds/WeSign-Linux.zip
|
||||
|
||||
- git commit -m "Add build files [skip ci]"
|
||||
- git push -f https://oauth2:ixKiNbp48zzmP5PF-epo@gitlab.ilabt.imec.be/wesign/unity-application/
|
||||
|
||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -9,6 +9,7 @@
|
||||
/[Bb]uilds/
|
||||
/[Ll]ogs/
|
||||
/[Uu]ser[Ss]ettings/
|
||||
/[Cc]ode[Cc]overage/
|
||||
|
||||
# MemoryCaptures can get excessive in size.
|
||||
# They also could contain extremely sensitive data
|
||||
@@ -72,4 +73,6 @@ crashlytics-build.properties
|
||||
/[Aa]ssets/[Ss]treamingAssets/aa.meta
|
||||
/[Aa]ssets/[Ss]treamingAssets/aa/*
|
||||
|
||||
.DS_Store
|
||||
.DS_Store
|
||||
/ProjectSettings/Packages/com.unity.testtools.codecoverage/Settings.json
|
||||
CodeCoverage/
|
||||
|
||||
137
Assets/Accounts/Prefabs/Axes Tick Marker.prefab
Normal file
137
Assets/Accounts/Prefabs/Axes Tick Marker.prefab
Normal file
@@ -0,0 +1,137 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1 &7141392721760992647
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 7141392721760992646}
|
||||
- component: {fileID: 7141392721760992644}
|
||||
- component: {fileID: 2518831828376613321}
|
||||
m_Layer: 5
|
||||
m_Name: Axes Tick Marker
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &7141392721760992646
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 7141392721760992647}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0.5}
|
||||
m_AnchorMax: {x: 0, y: 0.5}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 50, y: 50}
|
||||
m_Pivot: {x: 0, y: 0}
|
||||
--- !u!222 &7141392721760992644
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 7141392721760992647}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!114 &2518831828376613321
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 7141392721760992647}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_text: 0
|
||||
m_isRightToLeft: 0
|
||||
m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
|
||||
m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
|
||||
m_fontSharedMaterials: []
|
||||
m_fontMaterial: {fileID: 0}
|
||||
m_fontMaterials: []
|
||||
m_fontColor32:
|
||||
serializedVersion: 2
|
||||
rgba: 4279242768
|
||||
m_fontColor: {r: 0.0627451, g: 0.0627451, b: 0.0627451, a: 1}
|
||||
m_enableVertexGradient: 0
|
||||
m_colorMode: 3
|
||||
m_fontColorGradient:
|
||||
topLeft: {r: 1, g: 1, b: 1, a: 1}
|
||||
topRight: {r: 1, g: 1, b: 1, a: 1}
|
||||
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
|
||||
bottomRight: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_fontColorGradientPreset: {fileID: 0}
|
||||
m_spriteAsset: {fileID: 0}
|
||||
m_tintAllSprites: 0
|
||||
m_StyleSheet: {fileID: 0}
|
||||
m_TextStyleHashCode: -1183493901
|
||||
m_overrideHtmlColors: 0
|
||||
m_faceColor:
|
||||
serializedVersion: 2
|
||||
rgba: 4294967295
|
||||
m_fontSize: 36
|
||||
m_fontSizeBase: 36
|
||||
m_fontWeight: 400
|
||||
m_enableAutoSizing: 0
|
||||
m_fontSizeMin: 18
|
||||
m_fontSizeMax: 36
|
||||
m_fontStyle: 0
|
||||
m_HorizontalAlignment: 4
|
||||
m_VerticalAlignment: 512
|
||||
m_textAlignment: 65535
|
||||
m_characterSpacing: 0
|
||||
m_wordSpacing: 0
|
||||
m_lineSpacing: 0
|
||||
m_lineSpacingMax: 0
|
||||
m_paragraphSpacing: 0
|
||||
m_charWidthMaxAdj: 0
|
||||
m_enableWordWrapping: 0
|
||||
m_wordWrappingRatios: 0.4
|
||||
m_overflowMode: 0
|
||||
m_linkedTextComponent: {fileID: 0}
|
||||
parentLinkedComponent: {fileID: 0}
|
||||
m_enableKerning: 1
|
||||
m_enableExtraPadding: 0
|
||||
checkPaddingRequired: 0
|
||||
m_isRichText: 1
|
||||
m_parseCtrlCharacters: 1
|
||||
m_isOrthographic: 1
|
||||
m_isCullingEnabled: 0
|
||||
m_horizontalMapping: 0
|
||||
m_verticalMapping: 0
|
||||
m_uvLineOffset: 0
|
||||
m_geometrySortingOrder: 0
|
||||
m_IsTextObjectScaleStatic: 0
|
||||
m_VertexBufferAutoSizeReduction: 0
|
||||
m_useMaxVisibleDescender: 1
|
||||
m_pageToDisplay: 1
|
||||
m_margin: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_isUsingLegacyAnimationComponent: 0
|
||||
m_isVolumetricText: 0
|
||||
m_hasFontAssetChanged: 0
|
||||
m_baseMaterial: {fileID: 0}
|
||||
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
|
||||
7
Assets/Accounts/Prefabs/Axes Tick Marker.prefab.meta
Normal file
7
Assets/Accounts/Prefabs/Axes Tick Marker.prefab.meta
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9d96609216a825843b33f6af9cdfa29b
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -343,6 +343,12 @@ MonoBehaviour:
|
||||
button: {fileID: -2577348215772602702}
|
||||
courseProgress:
|
||||
entries: []
|
||||
courseIndex: 0
|
||||
progress: -1
|
||||
completedLearnables: 0
|
||||
inUseLearnables: 0
|
||||
totalLearnables: 0
|
||||
learnables: []
|
||||
courseList: {fileID: 11400000, guid: a7ab583094b7897468bbca9243717608, type: 2}
|
||||
thumbnail: {fileID: 5101881939775039227}
|
||||
title: {fileID: 5101881939882359064}
|
||||
@@ -491,15 +497,15 @@ MonoBehaviour:
|
||||
m_Calls: []
|
||||
m_text: <Minigame title>
|
||||
m_isRightToLeft: 0
|
||||
m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
|
||||
m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
|
||||
m_fontAsset: {fileID: 11400000, guid: 1baf2eae62f542f4585aaf3c9c3e229a, type: 2}
|
||||
m_sharedMaterial: {fileID: -2577534979213189211, guid: 1baf2eae62f542f4585aaf3c9c3e229a, type: 2}
|
||||
m_fontSharedMaterials: []
|
||||
m_fontMaterial: {fileID: 0}
|
||||
m_fontMaterials: []
|
||||
m_fontColor32:
|
||||
serializedVersion: 2
|
||||
rgba: 4294967295
|
||||
m_fontColor: {r: 1, g: 1, b: 1, a: 1}
|
||||
rgba: 4284235525
|
||||
m_fontColor: {r: 0.019607844, g: 0.24705882, b: 0.36078432, a: 1}
|
||||
m_enableVertexGradient: 0
|
||||
m_colorMode: 3
|
||||
m_fontColorGradient:
|
||||
@@ -617,7 +623,7 @@ MonoBehaviour:
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 0, g: 0.7529412, b: 1, a: 1}
|
||||
m_Color: {r: 0.9490196, g: 0.49803922, b: 0.047058824, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
|
||||
@@ -33,8 +33,8 @@ RectTransform:
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 0, y: 0}
|
||||
m_AnchorMin: {x: 1, y: 0.5}
|
||||
m_AnchorMax: {x: 1, y: 0.5}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 50, y: 50}
|
||||
m_Pivot: {x: 0, y: 0}
|
||||
|
||||
515
Assets/Accounts/Prefabs/LearnableProgressCard.prefab
Normal file
515
Assets/Accounts/Prefabs/LearnableProgressCard.prefab
Normal file
@@ -0,0 +1,515 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1 &758255480231791509
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 758255480231791508}
|
||||
- component: {fileID: 758255480231791506}
|
||||
- component: {fileID: 758255480231791507}
|
||||
- component: {fileID: 8445851122681183268}
|
||||
m_Layer: 0
|
||||
m_Name: LearnableProgressCard
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &758255480231791508
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 758255480231791509}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children:
|
||||
- {fileID: 758255481422566555}
|
||||
- {fileID: 758255481061489079}
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 0, y: 0}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 0, y: 0}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &758255480231791506
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 758255480231791509}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!114 &758255480231791507
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 758255480231791509}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_Sprite: {fileID: 0}
|
||||
m_Type: 0
|
||||
m_PreserveAspect: 1
|
||||
m_FillCenter: 1
|
||||
m_FillMethod: 4
|
||||
m_FillAmount: 1
|
||||
m_FillClockwise: 1
|
||||
m_FillOrigin: 0
|
||||
m_UseSpriteMesh: 0
|
||||
m_PixelsPerUnitMultiplier: 1
|
||||
--- !u!114 &8445851122681183268
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 758255480231791509}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 7835fc450a6bbf24d95f0a19491fb8c1, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
progress:
|
||||
entries: []
|
||||
index: 0
|
||||
inUse: 0
|
||||
name:
|
||||
progress: 0
|
||||
course: {fileID: 0}
|
||||
thumbnail: {fileID: 758255481422566554}
|
||||
stars:
|
||||
- {fileID: 758255481653936988}
|
||||
- {fileID: 758255481997431046}
|
||||
- {fileID: 758255482122419822}
|
||||
--- !u!1 &758255481061489032
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 758255481061489079}
|
||||
- component: {fileID: 758255481061489077}
|
||||
- component: {fileID: 758255481061489078}
|
||||
- component: {fileID: 758255481061489076}
|
||||
m_Layer: 0
|
||||
m_Name: Status
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &758255481061489079
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 758255481061489032}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children:
|
||||
- {fileID: 758255481653936989}
|
||||
- {fileID: 758255481997431047}
|
||||
- {fileID: 758255482122419823}
|
||||
m_Father: {fileID: 758255480231791508}
|
||||
m_RootOrder: 1
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 1, y: 0}
|
||||
m_AnchoredPosition: {x: 0, y: -32}
|
||||
m_SizeDelta: {x: -20, y: 45}
|
||||
m_Pivot: {x: 0.5, y: 0}
|
||||
--- !u!222 &758255481061489077
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 758255481061489032}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!114 &758255481061489078
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 758255481061489032}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 0.5803922, g: 0.58431375, b: 0.6, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_Sprite: {fileID: 0}
|
||||
m_Type: 0
|
||||
m_PreserveAspect: 1
|
||||
m_FillCenter: 1
|
||||
m_FillMethod: 4
|
||||
m_FillAmount: 1
|
||||
m_FillClockwise: 1
|
||||
m_FillOrigin: 0
|
||||
m_UseSpriteMesh: 0
|
||||
m_PixelsPerUnitMultiplier: 1
|
||||
--- !u!114 &758255481061489076
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 758255481061489032}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 30649d3a9faa99c48a7b1166b86bf2a0, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Padding:
|
||||
m_Left: 0
|
||||
m_Right: 0
|
||||
m_Top: 0
|
||||
m_Bottom: 0
|
||||
m_ChildAlignment: 4
|
||||
m_Spacing: 0
|
||||
m_ChildForceExpandWidth: 1
|
||||
m_ChildForceExpandHeight: 1
|
||||
m_ChildControlWidth: 1
|
||||
m_ChildControlHeight: 0
|
||||
m_ChildScaleWidth: 0
|
||||
m_ChildScaleHeight: 0
|
||||
m_ReverseArrangement: 0
|
||||
--- !u!1 &758255481422566556
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 758255481422566555}
|
||||
- component: {fileID: 758255481422566553}
|
||||
- component: {fileID: 758255481422566554}
|
||||
m_Layer: 0
|
||||
m_Name: Image
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &758255481422566555
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 758255481422566556}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 758255480231791508}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 1, y: 1}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 0, y: 0}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &758255481422566553
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 758255481422566556}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!114 &758255481422566554
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 758255481422566556}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_Sprite: {fileID: 21300000, guid: 5e3c345e006acf74791d272061159b89, type: 3}
|
||||
m_Type: 0
|
||||
m_PreserveAspect: 1
|
||||
m_FillCenter: 1
|
||||
m_FillMethod: 4
|
||||
m_FillAmount: 1
|
||||
m_FillClockwise: 1
|
||||
m_FillOrigin: 0
|
||||
m_UseSpriteMesh: 0
|
||||
m_PixelsPerUnitMultiplier: 1
|
||||
--- !u!1 &758255481653936990
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 758255481653936989}
|
||||
- component: {fileID: 758255481653936987}
|
||||
- component: {fileID: 758255481653936988}
|
||||
m_Layer: 0
|
||||
m_Name: Image
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &758255481653936989
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 758255481653936990}
|
||||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 758255481061489079}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 0, y: 0}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 0, y: 60}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &758255481653936987
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 758255481653936990}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!114 &758255481653936988
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 758255481653936990}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_Sprite: {fileID: -2086278073, guid: 4d6d852f751f20046ae733db5bdb1af1, type: 3}
|
||||
m_Type: 0
|
||||
m_PreserveAspect: 1
|
||||
m_FillCenter: 1
|
||||
m_FillMethod: 4
|
||||
m_FillAmount: 1
|
||||
m_FillClockwise: 1
|
||||
m_FillOrigin: 0
|
||||
m_UseSpriteMesh: 0
|
||||
m_PixelsPerUnitMultiplier: 1
|
||||
--- !u!1 &758255481997431064
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 758255481997431047}
|
||||
- component: {fileID: 758255481997431045}
|
||||
- component: {fileID: 758255481997431046}
|
||||
m_Layer: 0
|
||||
m_Name: Image (1)
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &758255481997431047
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 758255481997431064}
|
||||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 758255481061489079}
|
||||
m_RootOrder: 1
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 0, y: 0}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 0, y: 60}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &758255481997431045
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 758255481997431064}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!114 &758255481997431046
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 758255481997431064}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 0, g: 0, b: 0, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_Sprite: {fileID: -2086278073, guid: 4d6d852f751f20046ae733db5bdb1af1, type: 3}
|
||||
m_Type: 0
|
||||
m_PreserveAspect: 1
|
||||
m_FillCenter: 1
|
||||
m_FillMethod: 4
|
||||
m_FillAmount: 1
|
||||
m_FillClockwise: 1
|
||||
m_FillOrigin: 0
|
||||
m_UseSpriteMesh: 0
|
||||
m_PixelsPerUnitMultiplier: 1
|
||||
--- !u!1 &758255482122419808
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 758255482122419823}
|
||||
- component: {fileID: 758255482122419821}
|
||||
- component: {fileID: 758255482122419822}
|
||||
m_Layer: 0
|
||||
m_Name: Image (2)
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &758255482122419823
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 758255482122419808}
|
||||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 758255481061489079}
|
||||
m_RootOrder: 2
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 0, y: 0}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 0, y: 60}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &758255482122419821
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 758255482122419808}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!114 &758255482122419822
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 758255482122419808}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 0, g: 0, b: 0, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_Sprite: {fileID: -2086278073, guid: 4d6d852f751f20046ae733db5bdb1af1, type: 3}
|
||||
m_Type: 0
|
||||
m_PreserveAspect: 1
|
||||
m_FillCenter: 1
|
||||
m_FillMethod: 4
|
||||
m_FillAmount: 1
|
||||
m_FillClockwise: 1
|
||||
m_FillOrigin: 0
|
||||
m_UseSpriteMesh: 0
|
||||
m_PixelsPerUnitMultiplier: 1
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b7a9a8ccb77a37740bfdf5579cb179ca
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -68,15 +68,15 @@ MonoBehaviour:
|
||||
m_Calls: []
|
||||
m_text: 'Topscore: 123456789'
|
||||
m_isRightToLeft: 0
|
||||
m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
|
||||
m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
|
||||
m_fontAsset: {fileID: 11400000, guid: 1baf2eae62f542f4585aaf3c9c3e229a, type: 2}
|
||||
m_sharedMaterial: {fileID: -2577534979213189211, guid: 1baf2eae62f542f4585aaf3c9c3e229a, type: 2}
|
||||
m_fontSharedMaterials: []
|
||||
m_fontMaterial: {fileID: 0}
|
||||
m_fontMaterials: []
|
||||
m_fontColor32:
|
||||
serializedVersion: 2
|
||||
rgba: 4294967295
|
||||
m_fontColor: {r: 1, g: 1, b: 1, a: 1}
|
||||
rgba: 4284235525
|
||||
m_fontColor: {r: 0.019607844, g: 0.24705882, b: 0.36078432, a: 1}
|
||||
m_enableVertexGradient: 0
|
||||
m_colorMode: 3
|
||||
m_fontColorGradient:
|
||||
@@ -275,6 +275,9 @@ MonoBehaviour:
|
||||
button: {fileID: 5555894415693752970}
|
||||
minigameProgress:
|
||||
entries: []
|
||||
minigameIndex: 0
|
||||
latestScores: []
|
||||
highestScores: []
|
||||
minigameList: {fileID: 11400000, guid: 51453f9b41bc72f468ba3e67ab622f8f, type: 2}
|
||||
thumbnail: {fileID: 5101881939775039227}
|
||||
title: {fileID: 5101881939882359064}
|
||||
@@ -423,15 +426,15 @@ MonoBehaviour:
|
||||
m_Calls: []
|
||||
m_text: <Minigame title>
|
||||
m_isRightToLeft: 0
|
||||
m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
|
||||
m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
|
||||
m_fontAsset: {fileID: 11400000, guid: 1baf2eae62f542f4585aaf3c9c3e229a, type: 2}
|
||||
m_sharedMaterial: {fileID: -2577534979213189211, guid: 1baf2eae62f542f4585aaf3c9c3e229a, type: 2}
|
||||
m_fontSharedMaterials: []
|
||||
m_fontMaterial: {fileID: 0}
|
||||
m_fontMaterials: []
|
||||
m_fontColor32:
|
||||
serializedVersion: 2
|
||||
rgba: 4294967295
|
||||
m_fontColor: {r: 1, g: 1, b: 1, a: 1}
|
||||
rgba: 4284235525
|
||||
m_fontColor: {r: 0.019607844, g: 0.24705882, b: 0.36078432, a: 1}
|
||||
m_enableVertexGradient: 0
|
||||
m_colorMode: 3
|
||||
m_fontColorGradient:
|
||||
|
||||
@@ -96,7 +96,7 @@ MonoBehaviour:
|
||||
m_SelectOnDown: {fileID: 0}
|
||||
m_SelectOnLeft: {fileID: 0}
|
||||
m_SelectOnRight: {fileID: 0}
|
||||
m_Transition: 1
|
||||
m_Transition: 0
|
||||
m_Colors:
|
||||
m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
|
||||
@@ -277,15 +277,15 @@ MonoBehaviour:
|
||||
m_Calls: []
|
||||
m_text: Gebruiker
|
||||
m_isRightToLeft: 0
|
||||
m_fontAsset: {fileID: 11400000, guid: 3602bedf0ebe5b64596873f09eddf57b, type: 2}
|
||||
m_sharedMaterial: {fileID: -1030930060397404263, guid: 3602bedf0ebe5b64596873f09eddf57b, type: 2}
|
||||
m_fontAsset: {fileID: 11400000, guid: 1baf2eae62f542f4585aaf3c9c3e229a, type: 2}
|
||||
m_sharedMaterial: {fileID: -2577534979213189211, guid: 1baf2eae62f542f4585aaf3c9c3e229a, type: 2}
|
||||
m_fontSharedMaterials: []
|
||||
m_fontMaterial: {fileID: 0}
|
||||
m_fontMaterials: []
|
||||
m_fontColor32:
|
||||
serializedVersion: 2
|
||||
rgba: 4281479730
|
||||
m_fontColor: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1}
|
||||
rgba: 4284235525
|
||||
m_fontColor: {r: 0.019607844, g: 0.24705882, b: 0.36078432, a: 1}
|
||||
m_enableVertexGradient: 0
|
||||
m_colorMode: 3
|
||||
m_fontColorGradient:
|
||||
@@ -481,13 +481,6 @@ MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: 172fcacd3bd90f442a6b94f0ff43a76a, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
userList: {fileID: 11400000, guid: 072bec636a40f7e4e93b0ac624a3bda2, type: 2}
|
||||
user:
|
||||
username:
|
||||
avatar: {fileID: 0}
|
||||
playtime: 0
|
||||
courses: []
|
||||
minigames: []
|
||||
button: {fileID: 7566391564300576381}
|
||||
avatar: {fileID: 5164936991071620901}
|
||||
username: {fileID: 7566391564272109414}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
42
Assets/Accounts/ScriptableObjects/UserAvatarList.asset
Normal file
42
Assets/Accounts/ScriptableObjects/UserAvatarList.asset
Normal file
@@ -0,0 +1,42 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 81765ea55baf15d45b01b02187b02429, type: 3}
|
||||
m_Name: UserAvatarList
|
||||
m_EditorClassIdentifier:
|
||||
avatars:
|
||||
- {fileID: 21300000, guid: 6feaaea4b64633f49b4538bfd4b3755c, type: 3}
|
||||
- {fileID: 21300000, guid: 399cc241fc79bd74db314f146e7fb6b9, type: 3}
|
||||
- {fileID: 21300000, guid: 4654657a2ebea444898fa6eeaefcd18d, type: 3}
|
||||
- {fileID: 21300000, guid: 0cc198f1cde659246a199b30459720b1, type: 3}
|
||||
- {fileID: 21300000, guid: 7f105a09a3d164547925ee1bdfa595ca, type: 3}
|
||||
- {fileID: 21300000, guid: 313c22e5834595645989d609fe9d8853, type: 3}
|
||||
- {fileID: 21300000, guid: e5f3d99cdf5298d4f86d42dd019a6bad, type: 3}
|
||||
- {fileID: 21300000, guid: b67b99d98d1ceb1489743bcd78b9ab70, type: 3}
|
||||
- {fileID: 21300000, guid: e4af402f37099cd4195d7d2654519744, type: 3}
|
||||
- {fileID: 21300000, guid: 73f4e028d9efb644aa23538a749667c5, type: 3}
|
||||
- {fileID: 21300000, guid: 61e56570163833e448037bc353ada0ac, type: 3}
|
||||
- {fileID: 21300000, guid: 8e69dfd19237abb4f98eb11e74153109, type: 3}
|
||||
- {fileID: 21300000, guid: bc11ff9d6cc35de45ab58f39f13d7142, type: 3}
|
||||
- {fileID: 21300000, guid: f989719a5c45c7a4183b2bc12c1c4905, type: 3}
|
||||
- {fileID: 21300000, guid: 1392922567cd59d4fb0beceea3f5917a, type: 3}
|
||||
- {fileID: 21300000, guid: 3c314ae9e10eafb49b57c98c9e779bd8, type: 3}
|
||||
- {fileID: 21300000, guid: 33509e453b5093e43a148a668a961c56, type: 3}
|
||||
- {fileID: 21300000, guid: 39ac3b86729423846be1fbd56b8d92d6, type: 3}
|
||||
- {fileID: 21300000, guid: 1118d67f50622cc4ab02aa23c6dc1fd4, type: 3}
|
||||
- {fileID: 21300000, guid: e519f0f7b00e6834187963a0131cae52, type: 3}
|
||||
- {fileID: 21300000, guid: eefb367ff44256d43a14cde2c3924321, type: 3}
|
||||
- {fileID: 21300000, guid: 83d6525e4efa4954091e08095349f45a, type: 3}
|
||||
- {fileID: 21300000, guid: db31bca6363270441ab54421f55c1263, type: 3}
|
||||
- {fileID: 21300000, guid: 9d5771baa6ea6e041b066135d6798e1c, type: 3}
|
||||
- {fileID: 21300000, guid: 2b01165a5836ab14593d7a5862bd6793, type: 3}
|
||||
- {fileID: 21300000, guid: 8c304fe460423214ea0bb6ebc235ed2d, type: 3}
|
||||
- {fileID: 21300000, guid: b203b4e5f8568ff46b2277ce6d61017a, type: 3}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 017ec1af3b6cc4d4ab2b506911a4edad
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,17 +0,0 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 0
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 3f3d6d68c3c3db64e91cf5ec9537ccda, type: 3}
|
||||
m_Name: UserList
|
||||
m_EditorClassIdentifier:
|
||||
storedUserList:
|
||||
currentUserIndex: 0
|
||||
storedUsers: []
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 072bec636a40f7e4e93b0ac624a3bda2
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -3,6 +3,7 @@
|
||||
"rootNamespace": "",
|
||||
"references": [
|
||||
"GUID:6055be8ebefd69e48b49212b09b47b2f",
|
||||
"GUID:e83ddf9a537a96b4a804a16bb7872ec1",
|
||||
"GUID:7f2d0ee6dd21e1d4eb25b71b7a749d25"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
|
||||
@@ -22,11 +22,6 @@ public class ChangeUserScreen : MonoBehaviour
|
||||
/// </summary>
|
||||
public GameObject error;
|
||||
|
||||
/// <summary>
|
||||
/// Reference to the user list
|
||||
/// </summary>
|
||||
public UserList userList;
|
||||
|
||||
/// <summary>
|
||||
/// Index of the current selected user in the UserList
|
||||
/// </summary>
|
||||
@@ -42,6 +37,7 @@ public class ChangeUserScreen : MonoBehaviour
|
||||
/// </summary>
|
||||
void Start()
|
||||
{
|
||||
PersistentDataController.GetInstance().Load();
|
||||
error.SetActive(false);
|
||||
DisplayUsers();
|
||||
}
|
||||
@@ -52,12 +48,10 @@ public class ChangeUserScreen : MonoBehaviour
|
||||
private void DisplayUsers()
|
||||
{
|
||||
foreach (Transform child in usersContainer)
|
||||
{
|
||||
Destroy(child.gameObject);
|
||||
}
|
||||
|
||||
List<User> users = userList.GetUsers();
|
||||
currentUserIndex = userList.GetCurrentUserIndex();
|
||||
List<User> users = UserList.GetUsers();
|
||||
currentUserIndex = UserList.IndexOf(UserList.GetCurrentUser().GetUsername());
|
||||
for (int i = 0; i < users.Count; i++)
|
||||
{
|
||||
User user = users[i];
|
||||
@@ -78,7 +72,7 @@ public class ChangeUserScreen : MonoBehaviour
|
||||
Image background = instance.GetComponent<Image>();
|
||||
userBackgrounds.Add(background);
|
||||
// Set background color
|
||||
background.color = i == currentUserIndex ? Color.blue : Color.gray;
|
||||
background.color = i == currentUserIndex ? new Color(66 / 255f, 158 / 255f, 189 / 255f, 1f) : new Color(159 / 255f, 231 / 255f, 245 / 255f, 1f);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,9 +82,9 @@ public class ChangeUserScreen : MonoBehaviour
|
||||
/// <param name="index">Index to the user in the <c>this.userBackgrounds</c> list</param>
|
||||
private void UpdateSelection(int index)
|
||||
{
|
||||
userBackgrounds[currentUserIndex].color = Color.gray;
|
||||
userBackgrounds[currentUserIndex].color = new Color(159 / 255f, 231 / 255f, 245 / 255f, 1f);
|
||||
currentUserIndex = index;
|
||||
userBackgrounds[currentUserIndex].color = Color.blue;
|
||||
userBackgrounds[currentUserIndex].color = new Color(66 / 255f, 158 / 255f, 189 / 255f, 1f);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -98,8 +92,7 @@ public class ChangeUserScreen : MonoBehaviour
|
||||
/// </summary>
|
||||
public void IChooseYou()
|
||||
{
|
||||
userList.ChangeCurrentUser(currentUserIndex);
|
||||
userList.Save();
|
||||
UserList.ChangeCurrentUser(currentUserIndex);
|
||||
SystemController.GetInstance().BackToPreviousScene();
|
||||
}
|
||||
|
||||
|
||||
@@ -21,10 +21,10 @@ public class CourseProgressCard : MonoBehaviour
|
||||
/// <summary>
|
||||
/// Reference to the progress so we can display a progress bar
|
||||
/// </summary>
|
||||
public Progress courseProgress;
|
||||
public PersistentDataController.SavedCourseProgress courseProgress;
|
||||
|
||||
/// <summary>
|
||||
/// Reference to the list of courses so we can query the correct course
|
||||
/// Reference to the list of minigameCards so we can query the correct course
|
||||
/// </summary>
|
||||
public CourseList courseList;
|
||||
|
||||
@@ -48,11 +48,11 @@ public class CourseProgressCard : MonoBehaviour
|
||||
/// </summary>
|
||||
void Start()
|
||||
{
|
||||
Course course = courseList.GetCourseByIndex(courseProgress.Get<CourseIndex>("courseIndex"));
|
||||
Course course = courseList.GetCourseByIndex(courseProgress.courseIndex);
|
||||
|
||||
thumbnail.sprite = course.thumbnail;
|
||||
title.text = course.title;
|
||||
progressBar.value = courseProgress.Get<float>("courseProgress");
|
||||
progressBar.value = courseProgress.progress;
|
||||
button.onClick.AddListener(selectActivity);
|
||||
}
|
||||
}
|
||||
|
||||
40
Assets/Accounts/Scripts/LearnableProgressCard.cs
Normal file
40
Assets/Accounts/Scripts/LearnableProgressCard.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
/// <summary>
|
||||
/// Class to handle learnable progress card display
|
||||
/// </summary>
|
||||
public class LearnableProgressCard : MonoBehaviour
|
||||
{
|
||||
/// <summary>
|
||||
/// Reference to the progress so we can display a progress bar
|
||||
/// </summary>
|
||||
public PersistentDataController.SavedLearnableProgress progress;
|
||||
|
||||
/// <summary>
|
||||
/// Reference to the list of minigameCards so we can query the correct course
|
||||
/// </summary>
|
||||
public Learnable learnable;
|
||||
|
||||
/// <summary>
|
||||
/// UI reference to the thumbnail of the course
|
||||
/// </summary>
|
||||
public Image thumbnail;
|
||||
|
||||
/// <summary>
|
||||
/// UI refeerence to the title of the course
|
||||
/// </summary>
|
||||
public List<Image> stars;
|
||||
|
||||
/// <summary>
|
||||
/// Start is called before the first frame update
|
||||
/// </summary>
|
||||
void Start()
|
||||
{
|
||||
thumbnail.sprite = learnable.image;
|
||||
var starRewards = new float[] { 1.0f, 2.5f, 4.0f, };
|
||||
for (int i = 0; i < 3; i++)
|
||||
stars[i].color = starRewards[i] < progress.progress ? Color.white : Color.black;
|
||||
}
|
||||
}
|
||||
11
Assets/Accounts/Scripts/LearnableProgressCard.cs.meta
Normal file
11
Assets/Accounts/Scripts/LearnableProgressCard.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7835fc450a6bbf24d95f0a19491fb8c1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
@@ -22,7 +23,7 @@ public class MinigameProgressCard : MonoBehaviour
|
||||
/// <summary>
|
||||
/// Reference to the minigame progress
|
||||
/// </summary>
|
||||
public Progress minigameProgress;
|
||||
public PersistentDataController.SavedMinigameProgress minigameProgress;
|
||||
|
||||
/// <summary>
|
||||
/// Reference to the minigame list
|
||||
@@ -49,13 +50,15 @@ public class MinigameProgressCard : MonoBehaviour
|
||||
/// </summary>
|
||||
void Start()
|
||||
{
|
||||
Minigame minigame = minigameList.GetMinigameByIndex(minigameProgress.Get<MinigameIndex>("minigameIndex"));
|
||||
Minigame minigame = minigameList.GetMinigameByIndex(minigameProgress.minigameIndex);
|
||||
|
||||
thumbnail.sprite = minigame.thumbnail;
|
||||
title.text = minigame.title;
|
||||
List<Score> highscores = minigameProgress.Get<List<Score>>("highestScores");
|
||||
int score = highscores.Count > 0 ? highscores[0].scoreValue : 0;
|
||||
highscore.text = $"Topscore: {score}";
|
||||
button.onClick.AddListener(selectActivity);
|
||||
List<Score> highscores = minigameProgress.highestScores;
|
||||
if (0 < highscores.Count)
|
||||
highscore.text = $"TOPSCORE: {highscores.Max((s) => s.scoreValue)}";
|
||||
else
|
||||
highscore.text = "(NOG) GEEN TOPSCORE";
|
||||
}
|
||||
}
|
||||
|
||||
130
Assets/Accounts/Scripts/PanelCourseProgress.cs
Normal file
130
Assets/Accounts/Scripts/PanelCourseProgress.cs
Normal file
@@ -0,0 +1,130 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
/// <summary>
|
||||
/// Class to handle course list progress display
|
||||
/// </summary>
|
||||
public class PanelCourseProgress : MonoBehaviour
|
||||
{
|
||||
/// <summary>
|
||||
/// Reference to the current user
|
||||
/// </summary>
|
||||
private User user;
|
||||
|
||||
/// <summary>
|
||||
/// Reference to the courses list
|
||||
/// </summary>
|
||||
public CourseList courseList;
|
||||
|
||||
/// <summary>
|
||||
/// Prefab of a course card
|
||||
/// </summary>
|
||||
public GameObject courseCardPrefab;
|
||||
|
||||
/// <summary>
|
||||
/// UI reference to the container holding all course cards
|
||||
/// </summary>
|
||||
public Transform coursesContainer;
|
||||
|
||||
/// <summary>
|
||||
/// UI reference to the course info panel
|
||||
/// </summary>
|
||||
public GameObject courseInfo;
|
||||
|
||||
/// <summary>
|
||||
/// UI reference to the message that displays when no course progress is present
|
||||
/// </summary>
|
||||
public GameObject emptyCourses;
|
||||
|
||||
/// <summary>
|
||||
/// Reference to the title on the info panel
|
||||
/// </summary>
|
||||
public TMP_Text courseTitle;
|
||||
|
||||
/// <summary>
|
||||
/// Reference to the learnable card prefab
|
||||
/// </summary>
|
||||
public GameObject learnableCardPrefab;
|
||||
|
||||
/// <summary>
|
||||
/// Reference to the container for holding the learnable cards
|
||||
/// </summary>
|
||||
public Transform learnablesContainer;
|
||||
|
||||
/// <summary>
|
||||
/// Reference to the course progress bar on the info panel
|
||||
/// </summary>
|
||||
public SlicedSlider progressBar;
|
||||
|
||||
/// <summary>
|
||||
/// Current selected course
|
||||
/// </summary>
|
||||
private int selectedCourse = 0;
|
||||
|
||||
/// <summary>
|
||||
/// List of course backgrounds and indices
|
||||
/// </summary>
|
||||
private List<Tuple<Image, CourseIndex>> courseCards = new List<Tuple<Image, CourseIndex>>();
|
||||
|
||||
/// <summary>
|
||||
/// Start is called before the first frame update
|
||||
/// </summary>
|
||||
void Start()
|
||||
{
|
||||
PersistentDataController.GetInstance().Load();
|
||||
user = UserList.GetCurrentUser();
|
||||
|
||||
var courses = user.GetCourses();
|
||||
courseInfo.SetActive(0 < courses.Count);
|
||||
emptyCourses.SetActive(courses.Count <= 0);
|
||||
int i = 0;
|
||||
foreach (var courseProgress in courses)
|
||||
{
|
||||
// Create instance of prefab
|
||||
GameObject instance = GameObject.Instantiate(courseCardPrefab, coursesContainer);
|
||||
int j = i++;
|
||||
|
||||
// Initialize card
|
||||
CourseProgressCard cpc = instance.GetComponent<CourseProgressCard>();
|
||||
cpc.courseProgress = courseProgress;
|
||||
cpc.selectActivity = () => UpdateSelection(j);
|
||||
|
||||
// Store reference to background so we can apply fancy coloring
|
||||
Image background = instance.GetComponent<Image>();
|
||||
background.color = new Color(159 / 255f, 231 / 255f, 245 / 255f, 120/255f);
|
||||
this.courseCards.Add(Tuple.Create(background, courseProgress.courseIndex));
|
||||
}
|
||||
if (0 < courses.Count)
|
||||
UpdateSelection(0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update the current selected course
|
||||
/// </summary>
|
||||
/// <param name="newCourse">Index to the new course</param>
|
||||
private void UpdateSelection(int newCourse)
|
||||
{
|
||||
courseCards[selectedCourse].Item1.color = new Color(159 / 255f, 231 / 255f, 245 / 255f, 120 / 255f);
|
||||
selectedCourse = newCourse;
|
||||
courseCards[selectedCourse].Item1.color = new Color(66 / 255f, 158 / 255f, 189 / 255f, 1f);
|
||||
|
||||
var progress = user.GetCourseProgress(courseCards[selectedCourse].Item2);
|
||||
var course = courseList.GetCourseByIndex(progress.courseIndex);
|
||||
courseTitle.text = course.title;
|
||||
progressBar.fillAmount = progress.progress;
|
||||
|
||||
foreach (Transform child in learnablesContainer)
|
||||
Destroy(child.gameObject);
|
||||
|
||||
for (int i = 0; i < course.theme.learnables.Count; i++)
|
||||
{
|
||||
GameObject instance = GameObject.Instantiate(learnableCardPrefab, learnablesContainer);
|
||||
var script = instance.GetComponent<LearnableProgressCard>();
|
||||
script.learnable = course.theme.learnables[i];
|
||||
script.progress = progress.learnables[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/Accounts/Scripts/PanelCourseProgress.cs.meta
Normal file
11
Assets/Accounts/Scripts/PanelCourseProgress.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ba7d548c45e9ade4593922d9530cd56d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
127
Assets/Accounts/Scripts/PanelMinigameProgress.cs
Normal file
127
Assets/Accounts/Scripts/PanelMinigameProgress.cs
Normal file
@@ -0,0 +1,127 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
/// <summary>
|
||||
/// Class to handle minigame list progress display
|
||||
/// </summary>
|
||||
public class PanelMinigameProgress : MonoBehaviour
|
||||
{
|
||||
/// <summary>
|
||||
/// Reference to the current user
|
||||
/// </summary>
|
||||
private User user;
|
||||
|
||||
/// <summary>
|
||||
/// Reference to the minigames list
|
||||
/// </summary>
|
||||
public MinigameList minigameList;
|
||||
|
||||
/// <summary>
|
||||
/// Prefab of a minigame card
|
||||
/// </summary>
|
||||
public GameObject minigameCardPrefab;
|
||||
|
||||
/// <summary>
|
||||
/// UI reference to the container holding all the minigame cards
|
||||
/// </summary>
|
||||
public Transform minigamesContainer;
|
||||
|
||||
/// <summary>
|
||||
/// UI reference to the minigame info panel
|
||||
/// </summary>
|
||||
public GameObject minigameInfo;
|
||||
|
||||
/// <summary>
|
||||
/// UI reference to the message that displays when no minigame progress is present
|
||||
/// </summary>
|
||||
public GameObject emptyMinigames;
|
||||
|
||||
/// <summary>
|
||||
/// UI reference to the plot
|
||||
/// </summary>
|
||||
public ProgressGraph progressGraph;
|
||||
|
||||
/// <summary>
|
||||
/// Reference to the title of the minigame of the info panel
|
||||
/// </summary>
|
||||
public TMP_Text minigameTitle;
|
||||
|
||||
/// <summary>
|
||||
/// Reference to the text that will display when an empty minigame progress object is selected
|
||||
/// </summary>
|
||||
public GameObject emptyHighscore;
|
||||
|
||||
/// <summary>
|
||||
/// Current selected course
|
||||
/// </summary>
|
||||
private int selectedMinigame = 0;
|
||||
|
||||
/// <summary>
|
||||
/// List of course backgrounds and indices
|
||||
/// </summary>
|
||||
private List<Tuple<Image, MinigameIndex>> minigameCards = new List<Tuple<Image, MinigameIndex>>();
|
||||
|
||||
/// <summary>
|
||||
/// Start is called before the first frame update
|
||||
/// </summary>
|
||||
void Start()
|
||||
{
|
||||
PersistentDataController.GetInstance().Load();
|
||||
user = UserList.GetCurrentUser();
|
||||
|
||||
var minigames = user.GetMinigames();
|
||||
minigameInfo.SetActive(minigames.Count > 0);
|
||||
emptyMinigames.SetActive(minigames.Count <= 0);
|
||||
int i = 0;
|
||||
foreach (var minigameProgress in minigames)
|
||||
{
|
||||
// Create instance of prefab
|
||||
GameObject instance = GameObject.Instantiate(minigameCardPrefab, minigamesContainer);
|
||||
int j = i++;
|
||||
|
||||
// Initialize card
|
||||
MinigameProgressCard mpc = instance.GetComponent<MinigameProgressCard>();
|
||||
mpc.minigameProgress = minigameProgress;
|
||||
mpc.selectActivity = () => UpdateSelection(j);
|
||||
|
||||
// Store reference to background so we can apply fancy coloring
|
||||
Image background = instance.GetComponent<Image>();
|
||||
background.color = new Color(159 / 255f, 231 / 255f, 245 / 255f, 120 / 255f);
|
||||
minigameCards.Add(Tuple.Create(background, minigameProgress.minigameIndex));
|
||||
}
|
||||
if (0 < minigames.Count)
|
||||
UpdateSelection(0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update the current selected course
|
||||
/// </summary>
|
||||
/// <param name="newMinigame">Index to the new course</param>
|
||||
private void UpdateSelection(int newMinigame)
|
||||
{
|
||||
minigameCards[selectedMinigame].Item1.color = new Color(159 / 255f, 231 / 255f, 245 / 255f, 120 / 255f);
|
||||
selectedMinigame = newMinigame;
|
||||
minigameCards[selectedMinigame].Item1.color = new Color(66 / 255f, 158 / 255f, 189 / 255f, 1f);
|
||||
|
||||
var progress = user.GetMinigameProgress(minigameCards[selectedMinigame].Item2);
|
||||
minigameTitle.text = minigameList.GetMinigameByIndex(progress.minigameIndex).title;
|
||||
|
||||
List<Score> latestScores = progress.latestScores;
|
||||
List<Score> highestScores = progress.highestScores;
|
||||
if (0 < highestScores.Count)
|
||||
{
|
||||
emptyHighscore.SetActive(false);
|
||||
progressGraph.gameObject.SetActive(true);
|
||||
progressGraph.Plot(latestScores.ConvertAll<double>((s) => (double)s.scoreValue), highestScores.Max((s) => s.scoreValue));
|
||||
}
|
||||
else
|
||||
{
|
||||
emptyHighscore.SetActive(true);
|
||||
progressGraph.gameObject.SetActive(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/Accounts/Scripts/PanelMinigameProgress.cs.meta
Normal file
11
Assets/Accounts/Scripts/PanelMinigameProgress.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8c17533febddc854f8b01bacf617d45f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,104 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Runtime.Serialization.Formatters.Binary;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// A class for holding all progress belonging to a user
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class Progress
|
||||
{
|
||||
/// <summary>
|
||||
/// A helper class for handling the stored progress
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
protected class DataEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// The key, used to reference the data object
|
||||
/// </summary>
|
||||
public string key;
|
||||
|
||||
/// <summary>
|
||||
/// The object, representated as a list of byte (which can be serialized)
|
||||
/// </summary>
|
||||
public List<byte> bytes = new List<byte>();
|
||||
|
||||
public DataEntry(string key, byte[] data)
|
||||
{
|
||||
this.key = key;
|
||||
this.bytes = new List<byte>(data);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Entries in the <c>Progress</c> object
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
private List<DataEntry> entries = new List<DataEntry>();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Update the value of a certain key,
|
||||
/// or add a new value if the key was not present
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the data to be added/updated</typeparam>
|
||||
/// <param name="key">The key, used for referencing the data</param>
|
||||
/// <param name="data">The object of type <typeparamref name="T"/></param>
|
||||
/// <returns><c>true</c> if successful, <c>false</c> otherwise</returns>
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the data object of a certain key
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the data object</typeparam>
|
||||
/// <param name="key">The key referencing the data object</param>
|
||||
/// <returns>The data, cast to a type <typeparamref name="T"/></returns>
|
||||
/// <exception cref="KeyNotFoundException"></exception>
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d887bc641cc7a8f4abf9d4eb34d26923
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
263
Assets/Accounts/Scripts/ProgressGraph.cs
Normal file
263
Assets/Accounts/Scripts/ProgressGraph.cs
Normal file
@@ -0,0 +1,263 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
/// <summary>
|
||||
/// Class to handle and draw a nice line graph to a Texture2D
|
||||
/// </summary>
|
||||
public class ProgressGraph : MonoBehaviour
|
||||
{
|
||||
/// <summary>
|
||||
/// UI reference to the plot
|
||||
/// </summary>
|
||||
public RawImage progressGraph;
|
||||
|
||||
/// <summary>
|
||||
/// Prefab of the highscore marker to display on the graph
|
||||
/// </summary>
|
||||
public GameObject highscoreMarker;
|
||||
|
||||
/// <summary>
|
||||
/// Prefab of the axes tick marker to display on the graph
|
||||
/// </summary>
|
||||
public GameObject axesTickMarker;
|
||||
|
||||
/// <summary>
|
||||
/// Color of the graph line
|
||||
/// </summary>
|
||||
public Color lineColor;
|
||||
|
||||
/// <summary>
|
||||
/// Bckground color
|
||||
/// </summary>
|
||||
public Color backgroundColor;
|
||||
|
||||
/// <summary>
|
||||
/// Color of the text and axes grid
|
||||
/// </summary>
|
||||
public Color textColor;
|
||||
|
||||
/// <summary>
|
||||
/// Color of the highscore line
|
||||
/// </summary>
|
||||
public Color highscoreColor;
|
||||
|
||||
/// <summary>
|
||||
/// Left and right padding of the graph
|
||||
/// </summary>
|
||||
private const int GRAPH_PADDING_X_PX = 50;
|
||||
|
||||
/// <summary>
|
||||
/// Top and bottom padding of the graph
|
||||
/// </summary>
|
||||
private const int GRAPH_PADDING_Y_PX = 50;
|
||||
|
||||
/// <summary>
|
||||
/// Radius of the point on the graph
|
||||
/// </summary>
|
||||
private const int GRAPH_POINT_RADIUS = 10;
|
||||
|
||||
/// <summary>
|
||||
/// Size of the line on the graph
|
||||
/// </summary>
|
||||
private const int GRAPH_LINE_SIZE = 4;
|
||||
|
||||
/// <summary>
|
||||
/// Plot points and a highscore on the graph
|
||||
/// </summary>
|
||||
/// <param name="scores">List of score values to plot</param>
|
||||
/// <param name="highscore">Highscore value (this will be plotted in a fancy color)</param>
|
||||
public void Plot(List<double> scores, double highscore)
|
||||
{
|
||||
// Remove previous marker(s)
|
||||
foreach (Transform child in progressGraph.gameObject.transform)
|
||||
Destroy(child.gameObject);
|
||||
|
||||
// Get texture reference
|
||||
Texture2D tex = progressGraph.texture as Texture2D;
|
||||
RectTransform rect = progressGraph.gameObject.transform as RectTransform;
|
||||
if (tex == null)
|
||||
{
|
||||
tex = new Texture2D(
|
||||
width: (int)rect.sizeDelta.x,
|
||||
height: (int)rect.sizeDelta.y,
|
||||
textureFormat: TextureFormat.ARGB32,
|
||||
mipCount: 3,
|
||||
linear: true
|
||||
);
|
||||
}
|
||||
tex.filterMode = FilterMode.Point;
|
||||
FillTexture(tex, backgroundColor);
|
||||
|
||||
// calculate positions and offsets
|
||||
int x0 = GRAPH_PADDING_X_PX, x1 = tex.width - GRAPH_PADDING_X_PX;
|
||||
int y0 = GRAPH_PADDING_Y_PX, y1 = tex.height - GRAPH_PADDING_Y_PX;
|
||||
double min = scores.Min();
|
||||
double max = scores.Max();
|
||||
|
||||
List<Tuple<int, int>> points = new List<Tuple<int, int>>();
|
||||
for (int i = 0; i < scores.Count; i++)
|
||||
{
|
||||
int _x = x0 + (scores.Count > 1 ? i * ((x1 - x0) / (scores.Count - 1)) : (x1 - x0) / 2);
|
||||
int _y = y0 + (int)((y1 - y0) * (min != max ? (scores[i] - min) / (max - min) : 0.5));
|
||||
points.Add(Tuple.Create(_x, _y));
|
||||
}
|
||||
|
||||
// Calculate scaling
|
||||
const int NUMBER_OF_AXES = 5;
|
||||
|
||||
double spacing = 0.0;
|
||||
if (min == max)
|
||||
{
|
||||
spacing = CalculateSpacing(highscore, NUMBER_OF_AXES);
|
||||
max = highscore + 2 * spacing;
|
||||
min = highscore - 2 * spacing;
|
||||
}
|
||||
|
||||
spacing = CalculateSpacing(max - min, NUMBER_OF_AXES);
|
||||
double begin = spacing * Math.Round(min / spacing);
|
||||
|
||||
// Draw axes
|
||||
double pixels_per_unit = (y1 - y0) / (max - min);
|
||||
double Y = begin;
|
||||
int y = y0 + (int)(pixels_per_unit * (Y - min));
|
||||
int total = 0;
|
||||
do
|
||||
{
|
||||
if (y0 <= y)
|
||||
{
|
||||
DrawLine(tex, x0, y, x1, y, 2, textColor);
|
||||
|
||||
GameObject tick = GameObject.Instantiate(axesTickMarker, rect);
|
||||
tick.GetComponent<RectTransform>().localPosition = new Vector3(-10 - rect.sizeDelta.y * rect.pivot.x, y - 25 - rect.sizeDelta.y * rect.pivot.y, 0);
|
||||
TMP_Text txt = tick.GetComponent<TMP_Text>();
|
||||
txt.text = $"{Y}";
|
||||
txt.color = textColor;
|
||||
}
|
||||
total += 1;
|
||||
Y += spacing;
|
||||
y = y0 + (int)(pixels_per_unit * (Y - min));
|
||||
|
||||
// Fail save
|
||||
if (2 * NUMBER_OF_AXES < total)
|
||||
break;
|
||||
} while (y <= y1);
|
||||
|
||||
|
||||
// Draw highscore
|
||||
if (min <= highscore && highscore <= max)
|
||||
{
|
||||
y = y0 + (int)(pixels_per_unit * (highscore - min));
|
||||
DrawLine(tex, x0, y, x1, y, GRAPH_LINE_SIZE, highscoreColor);
|
||||
GameObject marker = GameObject.Instantiate(highscoreMarker, rect);
|
||||
marker.GetComponent<RectTransform>().localPosition = new Vector3(tex.width - 50 - rect.sizeDelta.x * rect.pivot.x, y - 25 - rect.sizeDelta.y * rect.pivot.y, 0);
|
||||
}
|
||||
|
||||
// Draw points
|
||||
for (int i = 0; i < points.Count; i++)
|
||||
{
|
||||
Tuple<int, int> p = points[i];
|
||||
if (0 < i)
|
||||
{
|
||||
Tuple<int, int> q = points[i - 1];
|
||||
DrawLine(tex, p.Item1, p.Item2, q.Item1, q.Item2, GRAPH_LINE_SIZE, lineColor);
|
||||
}
|
||||
DrawPoint(tex, p.Item1, p.Item2, GRAPH_POINT_RADIUS, lineColor);
|
||||
}
|
||||
|
||||
// Apply to graph GameObject
|
||||
tex.Apply();
|
||||
progressGraph.texture = tex;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculate nice spacing
|
||||
/// </summary>
|
||||
/// <param name="mu">Either `max - min` if max != min, otherwise `highscore`</param>
|
||||
/// <param name="numberOfAxes">Number of horizontal axes grid lines shown on the graph</param>
|
||||
/// <returns>Spacing between each axes grid line</returns>
|
||||
private double CalculateSpacing(double mu, int numberOfAxes)
|
||||
{
|
||||
if (mu == 0)
|
||||
return 1.0;
|
||||
|
||||
double[] otherSpacings = { 0.5, 1.0, 2.0, 5.0 };
|
||||
|
||||
int mag = (int)Math.Floor(Math.Log10(Math.Abs(mu)));
|
||||
int MAG = (int)Math.Pow(10, mag);
|
||||
double spacing = MAG;
|
||||
foreach (double o in otherSpacings)
|
||||
{
|
||||
if (Math.Abs(mu - numberOfAxes * spacing) <= Math.Abs(mu - numberOfAxes * o * MAG))
|
||||
continue;
|
||||
spacing = o * MAG;
|
||||
}
|
||||
return spacing;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set all the pixels of a texture to a given color
|
||||
/// </summary>
|
||||
/// <param name="tex">Texture to fill</param>
|
||||
/// <param name="color">Color to set the texture to</param>
|
||||
private void FillTexture(Texture2D tex, Color color)
|
||||
{
|
||||
for (int y = 0; y < tex.height; y++)
|
||||
for (int x = 0; x < tex.width; x++)
|
||||
tex.SetPixel(x, y, color);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draw a point to a texture
|
||||
/// </summary>
|
||||
/// <param name="tex">Texture2D to plot point on</param>
|
||||
/// <param name="xc">Center x-pos</param>
|
||||
/// <param name="yc">Center y-pos</param>
|
||||
/// <param name="r">Radius (aka width and height)</param>
|
||||
/// <param name="color">Color of the point</param>
|
||||
private void DrawPoint(Texture2D tex, int xc, int yc, int r, Color color)
|
||||
{
|
||||
for (int y = yc - r; y < yc + r; y++)
|
||||
for (int x = xc - r; x < xc + r; x++)
|
||||
tex.SetPixel(x, y, color);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draw a line to a texture
|
||||
/// </summary>
|
||||
/// <param name="tex">Texture2D to plot line on</param>
|
||||
/// <param name="x0">Starting x-pos</param>
|
||||
/// <param name="y0">Strating y-pos</param>
|
||||
/// <param name="x1">Ending x-pos</param>
|
||||
/// <param name="y1">Ending y-pos</param>
|
||||
/// <param name="size">Size of the line (width)</param>
|
||||
/// <param name="color">Color of the line</param>
|
||||
private void DrawLine(Texture2D tex, int x0, int y0, int x1, int y1, int size, Color color)
|
||||
{
|
||||
int w = x1 - x0;
|
||||
int h = y1 - y0;
|
||||
|
||||
int length = Mathf.Abs(x1 - x0);
|
||||
if (Mathf.Abs(y1 - y0) > length)
|
||||
length = Mathf.Abs(h);
|
||||
|
||||
double dx = w / (double)length;
|
||||
double dy = h / (double)length;
|
||||
|
||||
double x = x0;
|
||||
double y = y0;
|
||||
double r = size / 2;
|
||||
for (int i = 0; i <= length; i++)
|
||||
{
|
||||
for (int j = (int)(y - r); j < y + r; j++)
|
||||
for (int k = (int)(x - r); k < x + r; k++)
|
||||
tex.SetPixel(k, j, color);
|
||||
|
||||
x += dx;
|
||||
y += dy;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/Accounts/Scripts/ProgressGraph.cs.meta
Normal file
11
Assets/Accounts/Scripts/ProgressGraph.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 73c708fbc5395aa4b9765d4b6985bacc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,104 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
/// <summary>
|
||||
/// SystemController singleton
|
||||
/// </summary>
|
||||
public class SystemController
|
||||
{
|
||||
/// <summary>
|
||||
/// The instance controlling the singleton
|
||||
/// </summary>
|
||||
private static SystemController instance = null;
|
||||
|
||||
/// <summary>
|
||||
/// Stack of the loaded scenes, used to easily go back to previous scenes
|
||||
/// </summary>
|
||||
private Stack<int> sceneStack = new Stack<int>();
|
||||
|
||||
/// <summary>
|
||||
/// Get the instance loaded by the singleton
|
||||
/// </summary>
|
||||
/// <returns>SystemController instance</returns>
|
||||
public static SystemController GetInstance()
|
||||
{
|
||||
// Create a new instance if non exists
|
||||
if (instance == null)
|
||||
{
|
||||
instance = new SystemController();
|
||||
instance.sceneStack.Push(SceneManager.GetActiveScene().buildIndex);
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Load the scene and push on the stack
|
||||
/// </summary>
|
||||
/// <param name="scenePath">Path of the scene</param>
|
||||
public void LoadNextScene(string scenePath)
|
||||
{
|
||||
LoadNextScene(SceneUtility.GetBuildIndexByScenePath(scenePath));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Load the scene and push on the stack
|
||||
/// </summary>
|
||||
/// <param name="sceneIndex">Buildindex of the scene</param>
|
||||
public void LoadNextScene(int sceneIndex)
|
||||
{
|
||||
sceneStack.Push(sceneIndex);
|
||||
SceneManager.LoadScene(sceneIndex);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Swap the current scene with the new scene on the stack
|
||||
/// </summary>
|
||||
/// <param name="scenePath">Path of the scene</param>
|
||||
public void SwapScene(string scenePath)
|
||||
{
|
||||
SwapScene(SceneUtility.GetBuildIndexByScenePath(scenePath));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Swap the current scene with the new scene on the stack
|
||||
/// </summary>
|
||||
/// <param name="sceneIndex">Buildindex of the scene</param>
|
||||
public void SwapScene(int sceneIndex)
|
||||
{
|
||||
sceneStack.Pop();
|
||||
LoadNextScene(sceneIndex);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Go back to the previous scene and unload the current scene
|
||||
/// </summary>
|
||||
public void BackToPreviousScene()
|
||||
{
|
||||
sceneStack.Pop();
|
||||
|
||||
if (sceneStack.Count > 0) SceneManager.LoadScene(sceneStack.Peek());
|
||||
else Application.Quit();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Go back to a specific scene, unloading all the scenes on the way
|
||||
/// </summary>
|
||||
/// <param name="scenePath">Path of the scene</param>
|
||||
public void BackToScene(string scenePath)
|
||||
{
|
||||
BackToScene(SceneUtility.GetBuildIndexByScenePath(scenePath));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Go back to a specific scene, unloading all the scene on the way
|
||||
/// </summary>
|
||||
/// <param name="sceneIndex">Buildindex of the scene</param>
|
||||
public void BackToScene(int sceneIndex)
|
||||
{
|
||||
while (0 < sceneStack.Count && sceneStack.Peek() != sceneIndex) sceneStack.Pop();
|
||||
|
||||
if (sceneStack.Count > 0) SceneManager.LoadScene(sceneStack.Peek());
|
||||
else Application.Quit();
|
||||
}
|
||||
}
|
||||
@@ -2,92 +2,129 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using static PersistentDataController;
|
||||
|
||||
/// <summary>
|
||||
/// A class holding all information of a user
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class User
|
||||
{
|
||||
/// <summary>
|
||||
/// User nickname
|
||||
/// Reference to the user stored data record
|
||||
/// </summary>
|
||||
public string username;
|
||||
private SavedUserData storedUserData;
|
||||
|
||||
/// <summary>
|
||||
/// The avatar of the user
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
public Sprite avatar;
|
||||
/// <param name="data">Reference to the user stored data record</param>
|
||||
public User(SavedUserData data)
|
||||
{
|
||||
this.storedUserData = data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The total playtime of the user
|
||||
/// Get the username
|
||||
/// </summary>
|
||||
/// <remarks>TODO: needs to be implemented</remarks>
|
||||
public double playtime;
|
||||
public string GetUsername() { return storedUserData.username; }
|
||||
|
||||
/// <summary>
|
||||
/// List of courses a user started/completed
|
||||
/// Get the total playtime
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
public List<Progress> courses = new List<Progress>();
|
||||
public double GetPlaytime() { return storedUserData.playtime; }
|
||||
|
||||
/// <summary>
|
||||
/// List of minigames a user played
|
||||
/// Get the avatar
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
public List<Progress> minigames = new List<Progress>();
|
||||
public Sprite GetAvatar() { return UserList.AVATARS[storedUserData.avatarIndex]; }
|
||||
|
||||
/// <summary>
|
||||
/// Get a list of all recently started courses
|
||||
/// Get a list of all recently started minigameCards
|
||||
/// </summary>
|
||||
/// <returns>A <c>List</c> of <c>Tuples</c>, containing the <c>CourseIndex</c>
|
||||
/// and a <c>float</c> holding the progress (value between 0 and 1) of the user in this course</returns>
|
||||
public List<Tuple<CourseIndex, float>> GetRecentCourses()
|
||||
{
|
||||
// TODO: return better results (for now only return all courses)
|
||||
// TODO: return better results (for now only return all minigameCards)
|
||||
List<Tuple<CourseIndex, float>> recentCourses = new List<Tuple<CourseIndex, float>>();
|
||||
foreach (Progress courseProgress in courses)
|
||||
foreach (var courseProgress in storedUserData.courses)
|
||||
{
|
||||
CourseIndex idx = courseProgress.Get<CourseIndex>("courseIndex");
|
||||
float progress = courseProgress.Get<float>("courseProgress");
|
||||
CourseIndex idx = courseProgress.courseIndex;
|
||||
float progress = courseProgress.progress;
|
||||
recentCourses.Add(Tuple.Create<CourseIndex, float>(idx, progress));
|
||||
}
|
||||
return recentCourses.Take(3).ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a list of all recommended courses
|
||||
/// Get a list of all recommended minigameCards
|
||||
/// </summary>
|
||||
/// <returns>A <c>List</c> of <c>Tuples</c>, containing the <c>CourseIndex</c>
|
||||
/// and a <c>float</c> holding the progress (value between 0 and 1) of the user in this course</returns>
|
||||
public List<Tuple<CourseIndex, float>> GetRecommendedCourses()
|
||||
{
|
||||
List<Tuple<CourseIndex, float>> recommenedCourses = new List<Tuple<CourseIndex, float>>();
|
||||
if (courses.Count == 0)
|
||||
if (storedUserData.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)
|
||||
// TODO: return better results (for now only return all minigameCards)
|
||||
foreach (var courseProgress in storedUserData.courses)
|
||||
{
|
||||
CourseIndex idx = courseProgress.Get<CourseIndex>("courseIndex");
|
||||
float progress = courseProgress.Get<float>("courseProgress");
|
||||
CourseIndex idx = courseProgress.courseIndex;
|
||||
float progress = courseProgress.progress;
|
||||
recommenedCourses.Add(Tuple.Create<CourseIndex, float>(idx, progress));
|
||||
}
|
||||
}
|
||||
return recommenedCourses.Take(3).ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the progress of all minigameCards the user did
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public List<SavedCourseProgress> GetCourses()
|
||||
{
|
||||
return storedUserData.courses;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the progress of a certain course
|
||||
/// </summary>
|
||||
/// <param name="courseIndex">Index of course</param>
|
||||
/// <returns><c>Progress</c> belonging to the <c>courseIndex</c>, <c>null</c> if course was not found</returns>
|
||||
public Progress GetCourseProgress(CourseIndex courseIndex)
|
||||
public SavedCourseProgress GetCourseProgress(CourseIndex courseIndex)
|
||||
{
|
||||
return courses.Find((p) => p.Get<CourseIndex>("courseIndex") == courseIndex);
|
||||
return storedUserData.courses.Find((p) => p.courseIndex == courseIndex);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add new progress of a course
|
||||
/// </summary>
|
||||
/// <param name="progress">SavedCourseProgress data record</param>
|
||||
public void AddCourseProgress(SavedCourseProgress progress)
|
||||
{
|
||||
storedUserData.courses.Add(progress);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reset progress of a course
|
||||
/// </summary>
|
||||
/// <param name="courseIndex">Index of course</param>
|
||||
public void ResetCourseProgress(CourseIndex courseIndex)
|
||||
{
|
||||
storedUserData.courses.RemoveAll((p) => p.courseIndex == courseIndex);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the progress of all minigames the user did
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public List<SavedMinigameProgress> GetMinigames()
|
||||
{
|
||||
return storedUserData.minigames;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -95,8 +132,26 @@ public class User
|
||||
/// </summary>
|
||||
/// <param name="minigameIndex">Index of the minigame</param>
|
||||
/// <returns><c>Progress</c> belonging to the <c>minigameIndex</c>, <c>null</c> if minigame was not found</returns>
|
||||
public Progress GetMinigameProgress(MinigameIndex minigameIndex)
|
||||
public SavedMinigameProgress GetMinigameProgress(MinigameIndex minigameIndex)
|
||||
{
|
||||
return minigames.Find((p) => p.Get<MinigameIndex>("minigameIndex") == minigameIndex);
|
||||
return storedUserData.minigames.Find((p) => p.minigameIndex == minigameIndex);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add new progress of a minigame
|
||||
/// </summary>
|
||||
/// <param name="progress">SavedMinigameProgress data record</param>
|
||||
public void AddMinigameProgress(SavedMinigameProgress progress)
|
||||
{
|
||||
storedUserData.minigames.Add(progress);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reset progress of a minigame
|
||||
/// </summary>
|
||||
/// <param name="minigameIndex">Index of the minigame</param>
|
||||
public void ResetMinigameProgress(MinigameIndex minigameIndex)
|
||||
{
|
||||
storedUserData.minigames.RemoveAll((p) => p.minigameIndex == minigameIndex);
|
||||
}
|
||||
}
|
||||
|
||||
22
Assets/Accounts/Scripts/UserAvatarList.cs
Normal file
22
Assets/Accounts/Scripts/UserAvatarList.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// Container to hold a reference to all possible user avatar sprites
|
||||
/// </summary>
|
||||
[CreateAssetMenu(menuName = "Create new Scriptable/User Avatar List")]
|
||||
public class UserAvatarList : ScriptableObject
|
||||
{
|
||||
/// <summary>
|
||||
/// List of avatar sprites
|
||||
/// </summary>
|
||||
public List<Sprite> avatars = new List<Sprite>();
|
||||
|
||||
/// <summary>
|
||||
/// Awake is called when the object gets created
|
||||
/// </summary>
|
||||
public void Awake()
|
||||
{
|
||||
UserList.AVATARS = avatars;
|
||||
}
|
||||
}
|
||||
11
Assets/Accounts/Scripts/UserAvatarList.cs.meta
Normal file
11
Assets/Accounts/Scripts/UserAvatarList.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 81765ea55baf15d45b01b02187b02429
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -8,11 +8,6 @@ using UnityEngine.UI;
|
||||
/// </summary>
|
||||
public class UserCard : MonoBehaviour
|
||||
{
|
||||
/// <summary>
|
||||
/// Reference to the userlist
|
||||
/// </summary>
|
||||
public UserList userList;
|
||||
|
||||
/// <summary>
|
||||
/// User to upload info into this card
|
||||
/// </summary>
|
||||
@@ -53,8 +48,8 @@ public class UserCard : MonoBehaviour
|
||||
/// </summary>
|
||||
void Start()
|
||||
{
|
||||
avatar.sprite = user.avatar;
|
||||
username.text = user.username;
|
||||
avatar.sprite = user.GetAvatar();
|
||||
username.text = user.GetUsername();
|
||||
button.onClick.AddListener(selectUser);
|
||||
}
|
||||
|
||||
@@ -63,10 +58,9 @@ public class UserCard : MonoBehaviour
|
||||
/// </summary>
|
||||
public void DeleteUser()
|
||||
{
|
||||
if (userList.DeleteUser(user))
|
||||
if (UserList.DeleteUser(user.GetUsername()))
|
||||
{
|
||||
// User is removed, update and save
|
||||
userList.Save();
|
||||
updateUserCardContainer();
|
||||
}
|
||||
else
|
||||
|
||||
@@ -34,20 +34,9 @@ public class UserCreationScreen : MonoBehaviour
|
||||
/// </summary>
|
||||
public GameObject avatarPrefab;
|
||||
|
||||
/// <summary>
|
||||
/// List of all sprites that are supported as avatars
|
||||
/// </summary>
|
||||
public List<Sprite> sprites = new List<Sprite>();
|
||||
|
||||
/// <summary>
|
||||
/// Reference to the UserList ScriptableObject
|
||||
/// </summary>
|
||||
public UserList users;
|
||||
|
||||
/// <summary>
|
||||
/// Current selected avatar
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
private int selectedAvatar = 0;
|
||||
|
||||
/// <summary>
|
||||
@@ -55,6 +44,15 @@ public class UserCreationScreen : MonoBehaviour
|
||||
/// </summary>
|
||||
private List<Image> avatars = new List<Image>();
|
||||
|
||||
/// <summary>
|
||||
/// Reference to the back button, so we can deactivate it when the user cannot go back (when no user is found at startup)
|
||||
/// </summary>
|
||||
public GameObject backButton;
|
||||
|
||||
/// <summary>
|
||||
/// Boolean used to check whether the user can go back to the previous scene
|
||||
/// </summary>
|
||||
public static bool canGoBack = true;
|
||||
|
||||
/// <summary>
|
||||
/// Start is called before the first frame update
|
||||
@@ -62,8 +60,12 @@ public class UserCreationScreen : MonoBehaviour
|
||||
void Start()
|
||||
{
|
||||
errorMessage.SetActive(false);
|
||||
backButton.SetActive(canGoBack);
|
||||
|
||||
for (int i = 0; i < sprites.Count; i++)
|
||||
// Reset to default value
|
||||
UserCreationScreen.canGoBack = true;
|
||||
|
||||
for (int i = 0; i < UserList.AVATARS.Count; i++)
|
||||
{
|
||||
// Create instance of prefab
|
||||
GameObject instance = GameObject.Instantiate(avatarPrefab, avatarsContainer);
|
||||
@@ -77,9 +79,9 @@ public class UserCreationScreen : MonoBehaviour
|
||||
Image background = instance.GetComponent<Image>();
|
||||
avatars.Add(background);
|
||||
// Set background color
|
||||
background.color = selectedAvatar == i ? Color.blue : Color.gray;
|
||||
background.color = selectedAvatar == i ? new Color(66 / 255f, 158 / 255f, 189 / 255f, 1f) : Color.gray;
|
||||
// Find correct component for setting the sprite
|
||||
instance.transform.Find("Image").GetComponent<Image>().sprite = sprites[i];
|
||||
instance.transform.Find("Image").GetComponent<Image>().sprite = UserList.AVATARS[i];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,7 +93,7 @@ public class UserCreationScreen : MonoBehaviour
|
||||
{
|
||||
avatars[selectedAvatar].color = Color.gray;
|
||||
selectedAvatar = newAvatar;
|
||||
avatars[selectedAvatar].color = Color.blue;
|
||||
avatars[selectedAvatar].color = new Color(66 / 255f, 158 / 255f, 189 / 255f, 1f);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -113,10 +115,10 @@ public class UserCreationScreen : MonoBehaviour
|
||||
string username = inputName.text;
|
||||
if (IsValidUsername(username))
|
||||
{
|
||||
if (users.GetUserByUsername(username) == null)
|
||||
if (UserList.GetUserByUsername(username) == null)
|
||||
{
|
||||
// Create a new entry in the UserList ScriptableObject
|
||||
users.ChangeCurrentUser(users.CreateAndAddNewUser(username, sprites[selectedAvatar]));
|
||||
UserList.AddUser(username, UserList.AVATARS[selectedAvatar]);
|
||||
SystemController.GetInstance().BackToPreviousScene();
|
||||
}
|
||||
// Warn user that username already exists
|
||||
|
||||
@@ -1,78 +1,33 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// Keep track of all users
|
||||
/// </summary>
|
||||
[CreateAssetMenu(menuName = "Create new Scriptable/UserList")]
|
||||
public class UserList : ScriptableObject
|
||||
public static class UserList
|
||||
{
|
||||
/// <summary>
|
||||
/// Helper class to enable serialization of the UserList class
|
||||
/// (<c>ScriptableObject</c>s cannot be serialized)
|
||||
/// List of possible avatar sprites
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class StoredUserList
|
||||
{
|
||||
/// <summary>
|
||||
/// The index of the current/last logged in user in the <c>storedUsers</c> list
|
||||
/// </summary>
|
||||
public int currentUserIndex;
|
||||
|
||||
/// <summary>
|
||||
/// A list containing all users (which can be serialized)
|
||||
/// </summary>
|
||||
public List<User> storedUsers = new List<User>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reference to the serializable version of <c>UserList</c>
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
private StoredUserList storedUserList = new StoredUserList();
|
||||
|
||||
/// <summary>
|
||||
/// Path of the <c>.json</c>-file to store all serialized data
|
||||
/// </summary>
|
||||
public static string PATH = null;
|
||||
|
||||
/// <summary>
|
||||
/// OnEnable will make sure the <c>PATH</c>-variable is correctly initialized
|
||||
/// </summary>
|
||||
void OnEnable()
|
||||
{
|
||||
PATH = $"{Application.persistentDataPath}/users.json";
|
||||
Load();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new user
|
||||
/// </summary>
|
||||
/// <param name="name">The username of the new user</param>
|
||||
/// <param name="avatar">Reference to the user avatar</param>
|
||||
/// <returns>A newly created user</returns>
|
||||
public User CreateNewUser(string name, Sprite avatar)
|
||||
{
|
||||
User user = new User();
|
||||
user.username = name;
|
||||
user.avatar = avatar;
|
||||
return user;
|
||||
}
|
||||
public static List<Sprite> AVATARS = new List<Sprite>();
|
||||
|
||||
/// <summary>
|
||||
/// Create a new user and save (add to list)
|
||||
/// </summary>
|
||||
/// <param name="name">The username of the new user</param>
|
||||
/// <param name="username">The username of the new user</param>
|
||||
/// <param name="avatar">Reference to the user avatar</param>
|
||||
/// <returns>A newly created user</returns>
|
||||
public User CreateAndAddNewUser(string name, Sprite avatar)
|
||||
public static User AddUser(string username, Sprite avatar)
|
||||
{
|
||||
User user = CreateNewUser(name, avatar);
|
||||
storedUserList.storedUsers.Add(user);
|
||||
Save();
|
||||
return user;
|
||||
PersistentDataController pdc = PersistentDataController.GetInstance();
|
||||
PersistentDataController.SavedUserData data = new PersistentDataController.SavedUserData();
|
||||
data.username = username;
|
||||
data.playtime = 0.0;
|
||||
data.avatarIndex = AVATARS.IndexOf(avatar);
|
||||
|
||||
pdc.AddUser(data);
|
||||
return new User(data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -80,110 +35,127 @@ public class UserList : ScriptableObject
|
||||
/// </summary>
|
||||
/// <param name="username">The username of the user</param>
|
||||
/// <returns><c>User</c>-object if a user with such username was found, <c>null</c> otherwise</returns>
|
||||
public User GetUserByUsername(string username)
|
||||
public static User GetUserByUsername(string username)
|
||||
{
|
||||
foreach (User user in storedUserList.storedUsers)
|
||||
if (user.username == username) return user;
|
||||
foreach (User user in GetUsers())
|
||||
if (user.GetUsername() == username) return user;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a user by index
|
||||
/// </summary>
|
||||
/// <param name="index">The index of the user</param>
|
||||
/// <returns>User object</returns>
|
||||
/// <exception cref="IndexOutOfRangeException"></exception>
|
||||
public static User GetUserByIndex(int index)
|
||||
{
|
||||
List<User> users = GetUsers();
|
||||
if (index < 0 || users.Count <= index)
|
||||
throw new IndexOutOfRangeException();
|
||||
|
||||
return users[index];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a list of all users currently stored
|
||||
/// </summary>
|
||||
/// <returns>A list of all users</returns>
|
||||
public List<User> GetUsers()
|
||||
public static List<User> GetUsers()
|
||||
{
|
||||
return storedUserList.storedUsers;
|
||||
PersistentDataController pdc = PersistentDataController.GetInstance();
|
||||
return pdc.GetUsers().ConvertAll((d) => new User(d));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the current logged in user
|
||||
/// </summary>
|
||||
/// <returns>The current logged in user</returns>
|
||||
public User GetCurrentUser()
|
||||
public static User GetCurrentUser()
|
||||
{
|
||||
return storedUserList.storedUsers[storedUserList.currentUserIndex];
|
||||
List<User> users = GetUsers();
|
||||
if (users.Count == 0)
|
||||
return null;
|
||||
return users[PersistentDataController.GetInstance().GetCurrentUser()];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the index in the userlist of the current playing user
|
||||
/// Get the index in the userlist of a user
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public int GetCurrentUserIndex()
|
||||
public static int IndexOf(string username)
|
||||
{
|
||||
return storedUserList.currentUserIndex;
|
||||
int idx = GetUsers().FindIndex((e) => e.GetUsername() == username);
|
||||
if (idx < 0)
|
||||
throw new KeyNotFoundException();
|
||||
return idx;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Change the current user
|
||||
/// </summary>
|
||||
/// <param name="index">Index of the user in the userlist</param>
|
||||
public void ChangeCurrentUser(int index)
|
||||
/// <exception cref="IndexOutOfRangeException"></exception>
|
||||
public static void ChangeCurrentUser(int index)
|
||||
{
|
||||
storedUserList.currentUserIndex = index;
|
||||
if (index < 0 || GetUsers().Count <= index)
|
||||
throw new IndexOutOfRangeException();
|
||||
|
||||
PersistentDataController.GetInstance().SetCurrentUser(index, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Change the current user
|
||||
/// </summary>
|
||||
/// <param name="user">Reference to the user in the userlist</param>
|
||||
public void ChangeCurrentUser(User user)
|
||||
/// <param name="index">Username of the user</param>
|
||||
/// <exception cref="KeyNotFoundException"></exception>
|
||||
public static void ChangeCurrentUser(string username)
|
||||
{
|
||||
storedUserList.currentUserIndex = storedUserList.storedUsers.IndexOf(user);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove the user
|
||||
/// </summary>
|
||||
/// <param name="index">The index of the user in the userlist</param>
|
||||
/// <returns>true if user was successful removed, false otherwise</returns>
|
||||
public bool DeleteUser(int index)
|
||||
{
|
||||
return DeleteUser(storedUserList.storedUsers[index]);
|
||||
int index = GetUsers().FindIndex((e) => e.GetUsername() == username);
|
||||
try { ChangeCurrentUser(index); }
|
||||
catch (IndexOutOfRangeException) { throw new KeyNotFoundException(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// I am inevitable, *snap*
|
||||
/// </summary>
|
||||
/// <param name="user">Reference to the user to be removed</param>
|
||||
/// <param name="index">The index of the user in the userlist</param>
|
||||
/// <returns>true if the user was successful removed, false otherwise</returns>
|
||||
public bool DeleteUser(User user)
|
||||
/// <exception cref="IndexOutOfRangeException"></exception>
|
||||
public static bool DeleteUser(int index)
|
||||
{
|
||||
if (1 < storedUserList.storedUsers.Count)
|
||||
{
|
||||
if (storedUserList.currentUserIndex == storedUserList.storedUsers.Count - 1)
|
||||
{
|
||||
storedUserList.currentUserIndex--;
|
||||
}
|
||||
List<User> users = GetUsers();
|
||||
if (index < 0 || users.Count <= index)
|
||||
throw new IndexOutOfRangeException();
|
||||
|
||||
return storedUserList.storedUsers.Remove(user);
|
||||
if (1 < users.Count)
|
||||
{
|
||||
PersistentDataController.GetInstance().DeleteUser(index);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Save the users
|
||||
/// Delete a user from the userliset
|
||||
/// </summary>
|
||||
public void Save()
|
||||
/// <param name="username">Username of the user</param>
|
||||
/// <returns>true if the user was successful removed, false otherwise</returns>
|
||||
/// <exception cref="KeyNotFoundException"></exception>
|
||||
public static bool DeleteUser(string username)
|
||||
{
|
||||
string json = JsonUtility.ToJson(storedUserList);
|
||||
File.CreateText(PATH).Close();
|
||||
File.WriteAllText(PATH, json);
|
||||
int index = GetUsers().FindIndex((e) => e.GetUsername() == username);
|
||||
|
||||
try { return DeleteUser(index); }
|
||||
catch (IndexOutOfRangeException) { throw new KeyNotFoundException(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override the current content of the userlist by what is stored on disk
|
||||
/// Save the current UserList
|
||||
/// </summary>
|
||||
public void Load()
|
||||
public static void Save()
|
||||
{
|
||||
try
|
||||
{
|
||||
storedUserList.storedUsers.Clear();
|
||||
|
||||
string text = File.ReadAllText(PATH);
|
||||
storedUserList = JsonUtility.FromJson<StoredUserList>(text);
|
||||
}
|
||||
catch (FileNotFoundException) { Debug.Log($"Path '{PATH}' not found"); }
|
||||
PersistentDataController.GetInstance().Save();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
@@ -10,11 +7,6 @@ using UnityEngine.UI;
|
||||
/// </summary>
|
||||
public class UserProgressScreen : MonoBehaviour
|
||||
{
|
||||
/// <summary>
|
||||
/// Reference to the userlist
|
||||
/// </summary>
|
||||
public UserList userList;
|
||||
|
||||
/// <summary>
|
||||
/// Reference to the current user
|
||||
/// </summary>
|
||||
@@ -31,80 +23,24 @@ public class UserProgressScreen : MonoBehaviour
|
||||
public Image avatar;
|
||||
|
||||
/// <summary>
|
||||
/// UI reference to the user total playtime
|
||||
/// Reference to the courses panel
|
||||
/// </summary>
|
||||
public TMP_Text playtime;
|
||||
public GameObject coursesPanel;
|
||||
|
||||
/// <summary>
|
||||
/// Prefab of the highscore marker to display on the graph
|
||||
/// Reference to the minigame panel
|
||||
/// </summary>
|
||||
public GameObject highscoreMarker;
|
||||
public GameObject minigamesPanel;
|
||||
|
||||
/// <summary>
|
||||
/// Prefab of a course card
|
||||
/// Reference to the courses tab button (to set nice color)
|
||||
/// </summary>
|
||||
public GameObject courseCardPrefab;
|
||||
public Image coursesTabButton;
|
||||
|
||||
/// <summary>
|
||||
/// UI reference to the container holding all course cards
|
||||
/// Reference to the minigames tab button (to set nice color)
|
||||
/// </summary>
|
||||
public GameObject coursesContainer;
|
||||
|
||||
/// <summary>
|
||||
/// UI reference to the message that displays when no course progress is present
|
||||
/// </summary>
|
||||
public GameObject emptyCourses;
|
||||
|
||||
/// <summary>
|
||||
/// Prefab of a minigame card
|
||||
/// </summary>
|
||||
public GameObject minigameCardPrefab;
|
||||
|
||||
/// <summary>
|
||||
/// UI reference to the container holding all the minigame cards
|
||||
/// </summary>
|
||||
public GameObject minigamesContainer;
|
||||
|
||||
/// <summary>
|
||||
/// UI reference to the message that displays when no minigame progress is present
|
||||
/// </summary>
|
||||
public GameObject emptyMinigames;
|
||||
|
||||
/// <summary>
|
||||
/// UI reference to the plot
|
||||
/// </summary>
|
||||
public RawImage progressGraph;
|
||||
|
||||
/// <summary>
|
||||
/// Left and right padding of the graph
|
||||
/// </summary>
|
||||
private const int GRAPH_PADDING_X_PX = 50;
|
||||
|
||||
/// <summary>
|
||||
/// Top and bottom padding of the graph
|
||||
/// </summary>
|
||||
private const int GRAPH_PADDING_Y_PX = 50;
|
||||
|
||||
/// <summary>
|
||||
/// Radius of the point on the graph
|
||||
/// </summary>
|
||||
private const int GRAPH_POINT_RADIUS = 10;
|
||||
|
||||
/// <summary>
|
||||
/// Size of the line on the graph
|
||||
/// </summary>
|
||||
private const int GRAPH_LINE_SIZE = 4;
|
||||
|
||||
/// <summary>
|
||||
/// Current selected activity draw to the graph
|
||||
/// </summary>
|
||||
private int selectedActivity = -1;
|
||||
|
||||
/// <summary>
|
||||
/// List of activity backgrounds and indices
|
||||
/// </summary>
|
||||
private List<Tuple<Image, int>> activities = new List<Tuple<Image, int>>();
|
||||
|
||||
public Image minigamesTabButton;
|
||||
|
||||
/// <summary>
|
||||
/// Start is called before the first frame update
|
||||
@@ -112,266 +48,35 @@ public class UserProgressScreen : MonoBehaviour
|
||||
void Start()
|
||||
{
|
||||
// Assign the current user
|
||||
user = userList.GetCurrentUser();
|
||||
PersistentDataController.GetInstance().Load();
|
||||
user = UserList.GetCurrentUser();
|
||||
|
||||
// Set correct displayed items
|
||||
username.text = user.username;
|
||||
avatar.sprite = user.avatar;
|
||||
// TODO: implement total playtime
|
||||
//playtime.text = $"Totale speeltijd: {user.playtime.ToString("0.00")}";
|
||||
username.text = user.GetUsername();
|
||||
avatar.sprite = user.GetAvatar();
|
||||
|
||||
// Set graph inactive
|
||||
progressGraph.gameObject.SetActive(false);
|
||||
|
||||
int i = 0;
|
||||
// Display courses
|
||||
coursesContainer.SetActive(user.courses.Count > 0);
|
||||
emptyCourses.SetActive(user.courses.Count <= 0);
|
||||
foreach (Progress courseProgress in user.courses)
|
||||
{
|
||||
// Create instance of prefab
|
||||
GameObject instance = GameObject.Instantiate(courseCardPrefab, coursesContainer.transform.Find("Viewport").Find("Content").transform);
|
||||
int j = i++;
|
||||
|
||||
// Initialize card
|
||||
CourseProgressCard cpc = instance.GetComponent<CourseProgressCard>();
|
||||
cpc.courseProgress = courseProgress;
|
||||
cpc.selectActivity = () => UpdateSelection(j);
|
||||
|
||||
// Store reference to background so we can apply fancy coloring
|
||||
Image background = instance.GetComponent<Image>();
|
||||
background.color = Color.gray;
|
||||
activities.Add(Tuple.Create(background, (int)courseProgress.Get<CourseIndex>("courseIndex")));
|
||||
}
|
||||
|
||||
// Display minigames
|
||||
minigamesContainer.SetActive(user.minigames.Count > 0);
|
||||
emptyMinigames.SetActive(user.minigames.Count <= 0);
|
||||
foreach (Progress minigameProgress in user.minigames)
|
||||
{
|
||||
// Create instance of prefab
|
||||
GameObject instance = GameObject.Instantiate(minigameCardPrefab, minigamesContainer.transform.Find("Viewport").Find("Content").transform);
|
||||
int j = i++;
|
||||
|
||||
// Initialize card
|
||||
MinigameProgressCard mpc = instance.GetComponent<MinigameProgressCard>();
|
||||
mpc.minigameProgress = minigameProgress;
|
||||
mpc.selectActivity = () => UpdateSelection(j);
|
||||
|
||||
// Store reference to background so we can apply fancy coloring
|
||||
Image background = instance.GetComponent<Image>();
|
||||
background.color = Color.gray;
|
||||
activities.Add(Tuple.Create(background, (int)minigameProgress.Get<MinigameIndex>("minigameIndex")));
|
||||
}
|
||||
DisplayCourses();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update the current selected activity
|
||||
/// Switch to displaying the courses
|
||||
/// </summary>
|
||||
/// <param name="newActivity">Index to the new activity</param>
|
||||
private void UpdateSelection(int newActivity)
|
||||
public void DisplayCourses()
|
||||
{
|
||||
if (selectedActivity < 0)
|
||||
{
|
||||
progressGraph.gameObject.SetActive(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
activities[selectedActivity].Item1.color = Color.gray;
|
||||
}
|
||||
|
||||
selectedActivity = newActivity;
|
||||
activities[selectedActivity].Item1.color = Color.blue;
|
||||
if (selectedActivity < user.courses.Count)
|
||||
{
|
||||
// TODO: create a better graph
|
||||
//DisplayCourseGraph((CourseIndex)activities[selectedActivity].Item2);
|
||||
// For now: just deactivate graph rendering
|
||||
progressGraph.gameObject.SetActive(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
DisplayMinigameGraph((MinigameIndex)activities[selectedActivity].Item2);
|
||||
// TODO: remove line, this is only because courses deactivates the graph
|
||||
progressGraph.gameObject.SetActive(true);
|
||||
}
|
||||
coursesPanel.SetActive(true);
|
||||
coursesTabButton.color = new Color(247 / 255f, 173 / 255f, 25 / 255f, 1f);
|
||||
minigamesPanel.SetActive(false);
|
||||
minigamesTabButton.color = new Color(247 / 255f, 173 / 255f, 25 / 255f, 120/255f);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Plot the graph of a course
|
||||
/// Switch to displaying the minigames
|
||||
/// </summary>
|
||||
/// <param name="index">Index of the course</param>
|
||||
/// <remarks>TODO: create a better plot</remarks>
|
||||
private void DisplayCourseGraph(CourseIndex index) { }
|
||||
|
||||
/// <summary>
|
||||
/// Plot the graph of a minigame
|
||||
/// </summary>
|
||||
/// <param name="minigameIndex">Index of the minigame</param>
|
||||
private void DisplayMinigameGraph(MinigameIndex minigameIndex)
|
||||
public void DisplayMinigames()
|
||||
{
|
||||
Progress progress = user.GetMinigameProgress(minigameIndex);
|
||||
List<Score> latestScores = progress.Get<List<Score>>("latestScores");
|
||||
List<Score> highestScores = progress.Get<List<Score>>("highestScores");
|
||||
if (0 < highestScores.Count)
|
||||
{
|
||||
PlotGraph(latestScores.ConvertAll<double>((s) => (double)s.scoreValue), highestScores[0].scoreValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
progressGraph.gameObject.SetActive(false);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Plot points and a highscore on the graph
|
||||
/// </summary>
|
||||
/// <param name="scores">List of score values to plot</param>
|
||||
/// <param name="highscore">Highscore value (this will be plotted in a fancy color)</param>
|
||||
private void PlotGraph(List<double> scores, double highscore)
|
||||
{
|
||||
// Remove previous marker(s)
|
||||
foreach (Transform child in progressGraph.gameObject.transform)
|
||||
{
|
||||
Destroy(child.gameObject);
|
||||
}
|
||||
|
||||
// Get texture reference
|
||||
Texture2D tex = progressGraph.texture as Texture2D;
|
||||
if (tex == null)
|
||||
{
|
||||
RectTransform rt = progressGraph.gameObject.transform as RectTransform;
|
||||
tex = new Texture2D(
|
||||
width: (int)rt.sizeDelta.x,
|
||||
height: (int)rt.sizeDelta.y,
|
||||
textureFormat: TextureFormat.ARGB32,
|
||||
mipCount: 3,
|
||||
linear: true
|
||||
);
|
||||
}
|
||||
tex.filterMode = FilterMode.Point;
|
||||
|
||||
// calculate positions and offsets
|
||||
int x0 = GRAPH_PADDING_X_PX, x1 = tex.width - GRAPH_PADDING_X_PX;
|
||||
int y0 = GRAPH_PADDING_Y_PX, y1 = tex.height - GRAPH_PADDING_Y_PX;
|
||||
double min = scores.Min();
|
||||
double max = scores.Max();
|
||||
|
||||
List<Tuple<int, int>> points = new List<Tuple<int, int>>();
|
||||
for (int i = 0; i < scores.Count; i++)
|
||||
{
|
||||
int x = x0 + (scores.Count > 1 ? i * ((x1 - x0) / (scores.Count - 1)) : (x1 - x0) / 2);
|
||||
int y = y0 + (int)((y1 - y0) * (min != max ? (scores[i] - min) / (max - min) : 0.5));
|
||||
points.Add(Tuple.Create(x, y));
|
||||
}
|
||||
|
||||
// Calculate scaling
|
||||
int mag = (int)Math.Round(Math.Log10(max));
|
||||
int MAG = (int)Math.Pow(10, mag);
|
||||
double c = max / MAG;
|
||||
|
||||
// Draw axes
|
||||
if (min != max)
|
||||
{
|
||||
for (double d = c / 5.0; d < c; d += 0.2 * c)
|
||||
{
|
||||
int y = y0 + (int)((y1 - y0) * (MAG * d - min) / (max - min));
|
||||
DrawLine(tex, x0, y, x1, y, 2, Color.gray);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int y = y0 + (int)((y1 - y0) * 0.5);
|
||||
DrawLine(tex, x0, y0, x1, y0, 2, Color.gray);
|
||||
DrawLine(tex, x0, y, x1, y, 2, Color.gray);
|
||||
DrawLine(tex, x0, y1, x1, y1, 2, Color.gray);
|
||||
}
|
||||
|
||||
// Draw highscore
|
||||
if (min <= highscore && highscore <= max)
|
||||
{
|
||||
int y = y0 + (int)((y1 - y0) * (min != max ? (highscore - min) / (max - min) : 0.5));
|
||||
DrawLine(tex, x0, y, x1, y, 3, new Color(255, 192, 0));
|
||||
GameObject marker = GameObject.Instantiate(highscoreMarker, progressGraph.gameObject.transform);
|
||||
RectTransform rect = marker.GetComponent<RectTransform>();
|
||||
rect.localPosition = new Vector3(0, y - 25, 0);
|
||||
}
|
||||
|
||||
// Draw points
|
||||
for (int i = 0; i < points.Count; i++)
|
||||
{
|
||||
Tuple<int, int> p = points[i];
|
||||
if (0 < i)
|
||||
{
|
||||
Tuple<int, int> q = points[i - 1];
|
||||
DrawLine(tex, p.Item1, p.Item2, q.Item1, q.Item2, GRAPH_LINE_SIZE, Color.blue);
|
||||
}
|
||||
DrawPoint(tex, p.Item1, p.Item2, GRAPH_POINT_RADIUS, Color.blue);
|
||||
}
|
||||
|
||||
// Apply to graph GameObject
|
||||
tex.Apply();
|
||||
progressGraph.texture = tex;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draw a point to a texture
|
||||
/// </summary>
|
||||
/// <param name="tex">Texture2D to plot point on</param>
|
||||
/// <param name="xc">Center x-pos</param>
|
||||
/// <param name="yc">Center y-pos</param>
|
||||
/// <param name="r">Radius (aka width and height)</param>
|
||||
/// <param name="color">Color of the point</param>
|
||||
private void DrawPoint(Texture2D tex, int xc, int yc, int r, Color color)
|
||||
{
|
||||
for (int y = yc - r; y < yc + r; y++)
|
||||
{
|
||||
for (int x = xc - r; x < xc + r; x++)
|
||||
{
|
||||
tex.SetPixel(x, y, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draw a line to a texture
|
||||
/// </summary>
|
||||
/// <param name="tex">Texture2D to plot line on</param>
|
||||
/// <param name="x0">Starting x-pos</param>
|
||||
/// <param name="y0">Strating y-pos</param>
|
||||
/// <param name="x1">Ending x-pos</param>
|
||||
/// <param name="y1">Ending y-pos</param>
|
||||
/// <param name="size">Size of the line (width)</param>
|
||||
/// <param name="color">Color of the line</param>
|
||||
private void DrawLine(Texture2D tex, int x0, int y0, int x1, int y1, int size, Color color)
|
||||
{
|
||||
int w = x1 - x0;
|
||||
int h = y1 - y0;
|
||||
|
||||
int length = Mathf.Abs(x1 - x0);
|
||||
if (Mathf.Abs(y1 - y0) > length)
|
||||
{
|
||||
length = Mathf.Abs(h);
|
||||
}
|
||||
|
||||
double dx = w / (double)length;
|
||||
double dy = h / (double)length;
|
||||
|
||||
double x = x0;
|
||||
double y = y0;
|
||||
double r = size / 2;
|
||||
for (int i = 0; i <= length; i++)
|
||||
{
|
||||
for (int j = (int)(y - r); j < y + r; j++)
|
||||
{
|
||||
for (int k = (int)(x - r); k < x + r; k++)
|
||||
{
|
||||
tex.SetPixel(k, j, color);
|
||||
}
|
||||
}
|
||||
|
||||
x += dx;
|
||||
y += dy;
|
||||
}
|
||||
coursesPanel.SetActive(false);
|
||||
coursesTabButton.color = new Color(247 / 255f, 173 / 255f, 25 / 255f, 120 / 255f);
|
||||
minigamesPanel.SetActive(true);
|
||||
minigamesTabButton.color = new Color(247 / 255f, 173 / 255f, 25 / 255f, 1f);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
{
|
||||
"name": "AccountsTests",
|
||||
"rootNamespace": "",
|
||||
"references": [
|
||||
"UnityEngine.TestRunner",
|
||||
"UnityEditor.TestRunner",
|
||||
"AccountsScripts",
|
||||
"InterfacesScripts"
|
||||
],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": true,
|
||||
"precompiledReferences": [
|
||||
"nunit.framework.dll"
|
||||
],
|
||||
"autoReferenced": false,
|
||||
"defineConstraints": [
|
||||
"UNITY_INCLUDE_TESTS"
|
||||
],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
8
Assets/Accounts/Tests/EditMode.meta
Normal file
8
Assets/Accounts/Tests/EditMode.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fa6a54c35531563408befe54af56be0f
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
26
Assets/Accounts/Tests/EditMode/AccountEditMode.asmdef
Normal file
26
Assets/Accounts/Tests/EditMode/AccountEditMode.asmdef
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"name": "AccountEditMode",
|
||||
"rootNamespace": "",
|
||||
"references": [
|
||||
"UnityEngine.TestRunner",
|
||||
"UnityEditor.TestRunner",
|
||||
"AccountsScripts",
|
||||
"InterfacesScripts",
|
||||
"ArchitectureScripts"
|
||||
],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": true,
|
||||
"precompiledReferences": [
|
||||
"nunit.framework.dll"
|
||||
],
|
||||
"autoReferenced": false,
|
||||
"defineConstraints": [
|
||||
"UNITY_INCLUDE_TESTS"
|
||||
],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
27
Assets/Accounts/Tests/EditMode/UserAvatarListTests.cs
Normal file
27
Assets/Accounts/Tests/EditMode/UserAvatarListTests.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using NUnit.Framework;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// Test the UserAvatarList class
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
public class UserAvatarListTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Test the UserAvatarList class correctly initializes the UserList class
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Test_Awake()
|
||||
{
|
||||
UserList.AVATARS = new List<Sprite>();
|
||||
|
||||
var scriptableObject = AssetDatabase.LoadAssetAtPath<UserAvatarList>("Assets/Accounts/ScriptableObjects/UserAvatarList.asset");
|
||||
scriptableObject.Awake();
|
||||
|
||||
for (int i = 0; i < scriptableObject.avatars.Count; i++)
|
||||
Assert.AreEqual(scriptableObject.avatars[i], UserList.AVATARS[i]);
|
||||
}
|
||||
}
|
||||
|
||||
11
Assets/Accounts/Tests/EditMode/UserAvatarListTests.cs.meta
Normal file
11
Assets/Accounts/Tests/EditMode/UserAvatarListTests.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: af1cab5bd60427144a07155705d63dd9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
33
Assets/Accounts/Tests/EditMode/UserCreationScreenTests.cs
Normal file
33
Assets/Accounts/Tests/EditMode/UserCreationScreenTests.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using NUnit.Framework;
|
||||
|
||||
/// <summary>
|
||||
/// Test the UserCreationScreen class
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
public class UserCreationScreenTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Tets IsValidUsername will return <c>true</c> for an valid username
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Test_UserCreationScreen_IsValidUsername_True()
|
||||
{
|
||||
foreach (char c in "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
|
||||
Assert.IsTrue(UserCreationScreen.IsValidUsername(c.ToString()));
|
||||
|
||||
Assert.IsTrue(UserCreationScreen.IsValidUsername("123456789AbC"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tets IsValidUsername will return <c>false</c> for an invalid username
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Test_UserCreationScreen_IsValidUsername_False()
|
||||
{
|
||||
Assert.IsFalse(UserCreationScreen.IsValidUsername(string.Empty));
|
||||
foreach (char c in " \n\t+-*/%_.,;:!?(){}[]\\'\"|&~^$")
|
||||
Assert.IsFalse(UserCreationScreen.IsValidUsername(c.ToString()));
|
||||
|
||||
Assert.IsFalse(UserCreationScreen.IsValidUsername("123456789_10_11_12_13"));
|
||||
}
|
||||
}
|
||||
444
Assets/Accounts/Tests/EditMode/UserListTests.cs
Normal file
444
Assets/Accounts/Tests/EditMode/UserListTests.cs
Normal file
@@ -0,0 +1,444 @@
|
||||
using NUnit.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// Test the UserList class
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
public class UserListTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Create a new path so the existing .json file will not be overwritten
|
||||
/// </summary>
|
||||
private static string PATH = $"{Application.persistentDataPath}/wesign_unit_test.json";
|
||||
|
||||
/// <summary>
|
||||
/// Helper variable for quick user creation
|
||||
/// </summary>
|
||||
private string username = "u5erNam3";
|
||||
|
||||
/// <summary>
|
||||
/// Helper variable for quick user creation
|
||||
/// </summary>
|
||||
private Sprite avatar = null;
|
||||
|
||||
/// <summary>
|
||||
/// Setup the tests
|
||||
/// </summary>
|
||||
[SetUp]
|
||||
public void Setup_UserList()
|
||||
{
|
||||
PersistentDataController.PATH = UserListTests.PATH;
|
||||
|
||||
if (File.Exists(PATH))
|
||||
File.Delete(PATH);
|
||||
|
||||
PersistentDataController.GetInstance().Load();
|
||||
AssetDatabase.LoadAssetAtPath<UserAvatarList>("Assets/Accounts/ScriptableObjects/UserAvatarList.asset").Awake();
|
||||
avatar = UserList.AVATARS[0];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cleanup after testing
|
||||
/// </summary>
|
||||
[TearDown]
|
||||
public void TearDown_UserList()
|
||||
{
|
||||
PersistentDataController.PATH = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test for creation of a new UserList
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Test_New_UserList()
|
||||
{
|
||||
Assert.Zero(UserList.GetUsers().Count);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test for creation of new user (without adding the user to the list)
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Test_UserList_AddUser()
|
||||
{
|
||||
Assert.Zero(UserList.GetUsers().Count);
|
||||
User user = UserList.AddUser(username, avatar);
|
||||
|
||||
Assert.IsNotNull(user);
|
||||
Assert.AreEqual(1, UserList.GetUsers().Count);
|
||||
Assert.AreEqual(username, user.GetUsername());
|
||||
Assert.AreEqual(avatar, user.GetAvatar());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether an existing user can be found by its username
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Test_UserList_GetUserByUsername_Valid()
|
||||
{
|
||||
User u = UserList.AddUser(username, avatar);
|
||||
User v = UserList.GetUserByUsername(username);
|
||||
Assert.AreEqual(u.GetUsername(), v.GetUsername());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether a non-existing user can not be found
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Test_UserList_GetUserByUsername_Null()
|
||||
{
|
||||
User user = UserList.GetUserByUsername("not-a-user");
|
||||
Assert.IsNull(user);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether an existing user can be found by its username
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Test_UserList_GetUserByIndex_Valid()
|
||||
{
|
||||
User u = UserList.AddUser(username, avatar);
|
||||
User v = UserList.GetUserByIndex(0);
|
||||
Assert.AreEqual(u.GetUsername(), v.GetUsername());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether a non-existing user can not be found
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Test_UserList_GetUserByIndex_Exception()
|
||||
{
|
||||
Assert.Throws<IndexOutOfRangeException>(delegate { UserList.GetUserByIndex(0); });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether a userlist is correctly returned
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Test_UserList_GetUsers()
|
||||
{
|
||||
List<User> u = new List<User>();
|
||||
for (int i = 0; i < 5; i++)
|
||||
u.Add(UserList.AddUser($"{username}_{i}", avatar));
|
||||
|
||||
List<User> v = UserList.GetUsers();
|
||||
Assert.AreEqual(v.Count, u.Count);
|
||||
for (int i = 0; i < 5; i++)
|
||||
Assert.AreEqual(u[i].GetUsername(), v[i].GetUsername());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether the correct current user is returned
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Test_UserList_GetCurrentUser()
|
||||
{
|
||||
User u = UserList.AddUser($"{username}_{'u'}", avatar);
|
||||
User v = UserList.AddUser($"{username}_{'v'}", avatar);
|
||||
User w = UserList.AddUser($"{username}_{'w'}", avatar);
|
||||
UserList.ChangeCurrentUser(2);
|
||||
|
||||
User W = UserList.GetCurrentUser();
|
||||
Assert.AreEqual(w.GetUsername(), W.GetUsername());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether a null user is returned when the userlist is empty
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Test_UserList_GetCurrentUser_Empty()
|
||||
{
|
||||
User user = UserList.GetCurrentUser();
|
||||
Assert.IsNull(user);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether the correct index is returned for the current user
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Test_UserList_IndexOf_Valid()
|
||||
{
|
||||
User u = UserList.AddUser($"{username}_{'u'}", avatar);
|
||||
User v = UserList.AddUser($"{username}_{'v'}", avatar);
|
||||
User w = UserList.AddUser($"{username}_{'w'}", avatar);
|
||||
UserList.ChangeCurrentUser(2);
|
||||
|
||||
Assert.AreEqual(0, UserList.IndexOf(u.GetUsername()));
|
||||
Assert.AreEqual(1, UserList.IndexOf(v.GetUsername()));
|
||||
Assert.AreEqual(2, UserList.IndexOf(w.GetUsername()));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether the correct index is returned for the current user
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Test_UserList_IndexOf_Exception()
|
||||
{
|
||||
User u = new User(new PersistentDataController.SavedUserData()
|
||||
{
|
||||
username = username,
|
||||
avatarIndex = 0
|
||||
});
|
||||
Assert.Throws<KeyNotFoundException>(delegate { UserList.IndexOf(u.GetUsername()); });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether the current user (referenced by index) is correctly changed
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Test_UserList_ChangeCurrentUser_ValidIndex()
|
||||
{
|
||||
User u = UserList.AddUser($"{username}_{'u'}", avatar);
|
||||
User v = UserList.AddUser($"{username}_{'v'}", avatar);
|
||||
User w = UserList.AddUser($"{username}_{'w'}", avatar);
|
||||
UserList.ChangeCurrentUser(2);
|
||||
|
||||
User W = UserList.GetCurrentUser();
|
||||
Assert.AreEqual(w.GetUsername(), W.GetUsername());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether the current user is not changed when a bad index is given
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Test_UserList_ChangeCurrentUser_InvalidIndex()
|
||||
{
|
||||
User u = UserList.AddUser($"{username}_{'u'}", avatar);
|
||||
User v = UserList.AddUser($"{username}_{'v'}", avatar);
|
||||
User w = UserList.AddUser($"{username}_{'w'}", avatar);
|
||||
Assert.Throws<IndexOutOfRangeException>(delegate { UserList.ChangeCurrentUser(-1); });
|
||||
Assert.Throws<IndexOutOfRangeException>(delegate { UserList.ChangeCurrentUser(5); });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether the current user is not changed when a bad index is given
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Test_UserList_ChangeCurrentUser_IndexEmpty()
|
||||
{
|
||||
Assert.Throws<IndexOutOfRangeException>(delegate { UserList.ChangeCurrentUser(0); });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether the current user is correctly changed
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Test_UserList_ChangeCurrentUser_ValidUsername()
|
||||
{
|
||||
User u = UserList.AddUser($"{username}_{'u'}", avatar);
|
||||
User v = UserList.AddUser($"{username}_{'v'}", avatar);
|
||||
User w = UserList.AddUser($"{username}_{'w'}", avatar);
|
||||
UserList.ChangeCurrentUser(v.GetUsername());
|
||||
User V = UserList.GetCurrentUser();
|
||||
Assert.AreEqual(v.GetUsername(), V.GetUsername());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether the current user is not changed when a non-existing user is given
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Test_UserList_ChangeCurrentUser_InvalidUsername()
|
||||
{
|
||||
User u = UserList.AddUser($"{username}_{'u'}", avatar);
|
||||
User v = new User(new PersistentDataController.SavedUserData()
|
||||
{
|
||||
username = $"{username}_{'v'}",
|
||||
avatarIndex = 0
|
||||
});
|
||||
Assert.Throws<KeyNotFoundException>(delegate { UserList.ChangeCurrentUser(v.GetUsername()); });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether the current user is not changed when a null user is given
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Test_UserList_ChangeCurrentUser_NullUsername()
|
||||
{
|
||||
Assert.Throws<KeyNotFoundException>(delegate { UserList.ChangeCurrentUser(null); });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether deleting a existing user (referenced by index) will correctly be removed
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Test_UserList_DeleteUser_ValidIndex()
|
||||
{
|
||||
User u = UserList.AddUser($"{username}_{'u'}", avatar);
|
||||
User v = UserList.AddUser($"{username}_{'v'}", avatar);
|
||||
User w = UserList.AddUser($"{username}_{'w'}", avatar);
|
||||
Assert.IsTrue(UserList.DeleteUser(1));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether deleting a non-existing user (referenced by wrong index) will fail
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Test_UserList_DeleteUser_InvalidIndex()
|
||||
{
|
||||
User u = UserList.AddUser($"{username}_{'u'}", avatar);
|
||||
User v = UserList.AddUser($"{username}_{'v'}", avatar);
|
||||
User w = UserList.AddUser($"{username}_{'w'}", avatar);
|
||||
Assert.Throws<IndexOutOfRangeException>(delegate { UserList.DeleteUser(-1); });
|
||||
Assert.Throws<IndexOutOfRangeException>(delegate { UserList.DeleteUser(5); });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether deleting any user from an empty userlist will fail
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Test_UserList_DeleteUser_IndexEmpty()
|
||||
{
|
||||
Assert.Throws<IndexOutOfRangeException>(delegate { UserList.DeleteUser(0); });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether deleting an existing user will correctly remove the user and set the currentUserIndex correctly
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Test_UserList_DeleteUser_BeforeCurrentUser()
|
||||
{
|
||||
User u = UserList.AddUser($"{username}_{'u'}", avatar);
|
||||
User v = UserList.AddUser($"{username}_{'v'}", avatar);
|
||||
User w = UserList.AddUser($"{username}_{'w'}", avatar);
|
||||
UserList.ChangeCurrentUser(1);
|
||||
|
||||
Assert.AreEqual(3, UserList.GetUsers().Count);
|
||||
Assert.AreEqual(1, UserList.IndexOf(UserList.GetCurrentUser().GetUsername()));
|
||||
Assert.IsTrue(UserList.DeleteUser(u.GetUsername()));
|
||||
Assert.AreEqual(2, UserList.GetUsers().Count);
|
||||
Assert.AreEqual(0, UserList.IndexOf(UserList.GetCurrentUser().GetUsername()));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether deleting an existing user will correctly remove the user and set the currentUserIndex correctly
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Test_UserList_DeleteUser_CurrentUser()
|
||||
{
|
||||
User u = UserList.AddUser($"{username}_{'u'}", avatar);
|
||||
User v = UserList.AddUser($"{username}_{'v'}", avatar);
|
||||
User w = UserList.AddUser($"{username}_{'w'}", avatar);
|
||||
UserList.ChangeCurrentUser(1);
|
||||
|
||||
Assert.AreEqual(3, UserList.GetUsers().Count);
|
||||
Assert.AreEqual(1, UserList.IndexOf(UserList.GetCurrentUser().GetUsername()));
|
||||
Assert.IsTrue(UserList.DeleteUser(v.GetUsername()));
|
||||
Assert.AreEqual(2, UserList.GetUsers().Count);
|
||||
Assert.AreEqual(0, UserList.IndexOf(UserList.GetCurrentUser().GetUsername()));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether deleting an existing user will correctly remove the user and set the currentUserIndex correctly
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Test_UserList_DeleteUser_AfterCurrentUser()
|
||||
{
|
||||
User u = UserList.AddUser($"{username}_{'u'}", avatar);
|
||||
User v = UserList.AddUser($"{username}_{'v'}", avatar);
|
||||
User w = UserList.AddUser($"{username}_{'w'}", avatar);
|
||||
UserList.ChangeCurrentUser(1);
|
||||
|
||||
Assert.AreEqual(3, UserList.GetUsers().Count);
|
||||
Assert.AreEqual(1, UserList.IndexOf(UserList.GetCurrentUser().GetUsername()));
|
||||
Assert.IsTrue(UserList.DeleteUser(w.GetUsername()));
|
||||
Assert.AreEqual(2, UserList.GetUsers().Count);
|
||||
Assert.AreEqual(1, UserList.IndexOf(UserList.GetCurrentUser().GetUsername()));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether deleting a non-existing user will not affect the userlist
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Test_UserList_DeleteUser_Invalid()
|
||||
{
|
||||
User u = UserList.AddUser($"{username}_{'u'}", avatar);
|
||||
User v = new User(new PersistentDataController.SavedUserData()
|
||||
{
|
||||
username = $"{username}_{'v'}",
|
||||
avatarIndex = 0
|
||||
});
|
||||
|
||||
Assert.AreEqual(1, UserList.GetUsers().Count);
|
||||
Assert.Throws<KeyNotFoundException>(delegate { UserList.DeleteUser(v.GetUsername()); });
|
||||
Assert.AreEqual(1, UserList.GetUsers().Count);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether calling the DeleteUser function on an empty list will not affect the userlist
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Test_UserList_DeleteUser_Empty()
|
||||
{
|
||||
User user = new User(new PersistentDataController.SavedUserData()
|
||||
{
|
||||
username = username,
|
||||
avatarIndex = 0
|
||||
});
|
||||
Assert.Zero(UserList.GetUsers().Count);
|
||||
Assert.Throws<KeyNotFoundException>(delegate { UserList.DeleteUser(user.GetUsername()); });
|
||||
Assert.Zero(UserList.GetUsers().Count);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether a savefile is correctly constructed when no savefile is present
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Test_UserList_Save_New()
|
||||
{
|
||||
List<User> u = new List<User>();
|
||||
for (int i = 0; i < 5; i++)
|
||||
u.Add(UserList.AddUser($"{username}_{i}", avatar));
|
||||
|
||||
UserList.ChangeCurrentUser(3);
|
||||
UserList.Save();
|
||||
FileAssert.Exists(PATH);
|
||||
|
||||
string content = File.ReadAllText(PATH);
|
||||
string expected = $"{{\"version\":{PersistentDataController.VERSION},\"users\":[{{\"entries\":[],\"username\":\"u5erNam3_0\",\"avatarIndex\":0,\"playtime\":0.0,\"minigames\":[],\"courses\":[]}},{{\"entries\":[],\"username\":\"u5erNam3_1\",\"avatarIndex\":0,\"playtime\":0.0,\"minigames\":[],\"courses\":[]}},{{\"entries\":[],\"username\":\"u5erNam3_2\",\"avatarIndex\":0,\"playtime\":0.0,\"minigames\":[],\"courses\":[]}},{{\"entries\":[],\"username\":\"u5erNam3_3\",\"avatarIndex\":0,\"playtime\":0.0,\"minigames\":[],\"courses\":[]}},{{\"entries\":[],\"username\":\"u5erNam3_4\",\"avatarIndex\":0,\"playtime\":0.0,\"minigames\":[],\"courses\":[]}}],\"currentUser\":3,\"currentMinigame\":0,\"currentCourse\":0,\"currentTheme\":0,\"useGPU\":false}}";
|
||||
Assert.AreEqual(expected, content);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether a savefile is correctly constructed when a savefile already exists
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Test_UserList_Save_Existing()
|
||||
{
|
||||
if (!File.Exists(PATH))
|
||||
{
|
||||
File.CreateText(PATH).Close();
|
||||
File.WriteAllText(PATH, "https://www.youtube.com/watch?v=dQw4w9WgXcQ");
|
||||
}
|
||||
|
||||
List<User> u = new List<User>();
|
||||
for (int i = 0; i < 5; i++)
|
||||
u.Add(UserList.AddUser($"{username}_{i}", avatar));
|
||||
|
||||
UserList.ChangeCurrentUser(3);
|
||||
UserList.Save();
|
||||
FileAssert.Exists(PATH);
|
||||
|
||||
string content = File.ReadAllText(PATH);
|
||||
string expected = $"{{\"version\":{PersistentDataController.VERSION},\"users\":[{{\"entries\":[],\"username\":\"u5erNam3_0\",\"avatarIndex\":0,\"playtime\":0.0,\"minigames\":[],\"courses\":[]}},{{\"entries\":[],\"username\":\"u5erNam3_1\",\"avatarIndex\":0,\"playtime\":0.0,\"minigames\":[],\"courses\":[]}},{{\"entries\":[],\"username\":\"u5erNam3_2\",\"avatarIndex\":0,\"playtime\":0.0,\"minigames\":[],\"courses\":[]}},{{\"entries\":[],\"username\":\"u5erNam3_3\",\"avatarIndex\":0,\"playtime\":0.0,\"minigames\":[],\"courses\":[]}},{{\"entries\":[],\"username\":\"u5erNam3_4\",\"avatarIndex\":0,\"playtime\":0.0,\"minigames\":[],\"courses\":[]}}],\"currentUser\":3,\"currentMinigame\":0,\"currentCourse\":0,\"currentTheme\":0,\"useGPU\":false}}";
|
||||
Assert.AreEqual(expected, content);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether a save file is correctly constructed from an empty userlist
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Test_UserList_Save_Empty()
|
||||
{
|
||||
UserList.Save();
|
||||
FileAssert.Exists(PATH);
|
||||
|
||||
string content = File.ReadAllText(PATH);
|
||||
string expected = $"{{\"version\":{PersistentDataController.VERSION},\"users\":[],\"currentUser\":-1,\"currentMinigame\":0,\"currentCourse\":0,\"currentTheme\":0,\"useGPU\":false}}";
|
||||
Assert.AreEqual(expected, content);
|
||||
}
|
||||
}
|
||||
11
Assets/Accounts/Tests/EditMode/UserListTests.cs.meta
Normal file
11
Assets/Accounts/Tests/EditMode/UserListTests.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cc44c73b32b9af7469b76bd6071f0cf5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
225
Assets/Accounts/Tests/EditMode/UserTests.cs
Normal file
225
Assets/Accounts/Tests/EditMode/UserTests.cs
Normal file
@@ -0,0 +1,225 @@
|
||||
using NUnit.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
/// <summary>
|
||||
/// Test the User class
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
public class UserTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Reference to the user to be tested
|
||||
/// </summary>
|
||||
private User user;
|
||||
|
||||
/// <summary>
|
||||
/// Setup the tests
|
||||
/// </summary>
|
||||
[SetUp]
|
||||
public void Setup_User()
|
||||
{
|
||||
PersistentDataController.SavedUserData data = new PersistentDataController.SavedUserData();
|
||||
data.username = "username";
|
||||
data.avatarIndex = 0;
|
||||
user = new User(data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test for the creation of a new user
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Test_New_User()
|
||||
{
|
||||
Assert.NotNull(user);
|
||||
Assert.Zero(user.GetCourses().Count);
|
||||
Assert.Zero(user.GetMinigames().Count);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether the correct username is returned
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Test_User_GetUsername()
|
||||
{
|
||||
Assert.AreEqual("username", user.GetUsername());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether the correct avatar is returned
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Test_User_GetAvatar()
|
||||
{
|
||||
Assert.AreEqual(UserList.AVATARS[0], user.GetAvatar());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether the correct total playtime is returned
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Test_User_GetPlaytime()
|
||||
{
|
||||
Assert.AreEqual(0.0, user.GetPlaytime());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether progress on a new course can be added
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Test_User_AddCourse()
|
||||
{
|
||||
var p = new PersistentDataController.SavedCourseProgress();
|
||||
user.AddCourseProgress(p);
|
||||
Assert.AreEqual(user.GetCourses().Count, 1);
|
||||
Assert.Zero(user.GetMinigames().Count);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether progress on a new minigame can be added
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Test_User_AddMinigame()
|
||||
{
|
||||
var p = new PersistentDataController.SavedMinigameProgress();
|
||||
user.AddMinigameProgress(p);
|
||||
Assert.Zero(user.GetCourses().Count);
|
||||
Assert.AreEqual(user.GetMinigames().Count, 1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test GetRecentCourses will return empty when no progress is stored
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Test_User_GetRecentCourses_Empty()
|
||||
{
|
||||
Assert.Zero(user.GetRecentCourses().Count);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// TEMPORARY test for GetRecentCourses will return all progress that is stored
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Test_User_GetRecentCourses_All()
|
||||
{
|
||||
var p = new PersistentDataController.SavedCourseProgress();
|
||||
p.courseIndex = CourseIndex.FINGERSPELLING;
|
||||
p.progress = 0.5f;
|
||||
user.AddCourseProgress(p);
|
||||
List<Tuple<CourseIndex, float>> list = user.GetRecentCourses();
|
||||
Assert.AreEqual(list.Count, 1);
|
||||
Assert.AreEqual(list[0].Item1, CourseIndex.FINGERSPELLING);
|
||||
Assert.AreEqual(list[0].Item2, 0.5f);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test GetRecommendedCourses will return <c>Tuple<CourseIndex.FINGERSPELLING, 0.0></c> when no progress is stored
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Test_User_GetRecommendedCourses_Empty()
|
||||
{
|
||||
List<Tuple<CourseIndex, float>> list = user.GetRecommendedCourses();
|
||||
Assert.AreEqual(list.Count, 1);
|
||||
Assert.AreEqual(list[0].Item1, CourseIndex.FINGERSPELLING);
|
||||
Assert.AreEqual(list[0].Item2, 0.0f);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// TEMPORARY test for GetRecommenedCourses will return all progress that is stored
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Test_User_GetRecommendedCourses_All()
|
||||
{
|
||||
var p = new PersistentDataController.SavedCourseProgress();
|
||||
p.courseIndex = CourseIndex.FINGERSPELLING;
|
||||
p.progress = 0.5f;
|
||||
user.AddCourseProgress(p);
|
||||
List<Tuple<CourseIndex, float>> list = user.GetRecommendedCourses();
|
||||
Assert.AreEqual(list.Count, 1);
|
||||
Assert.AreEqual(list[0].Item1, CourseIndex.FINGERSPELLING);
|
||||
Assert.AreEqual(list[0].Item2, 0.5f);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test GetCourseProgress returns null when course cannot be found
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Test_User_GetCourseProgress_Null()
|
||||
{
|
||||
Assert.Null(user.GetCourseProgress(CourseIndex.FINGERSPELLING));
|
||||
Assert.Null(user.GetCourseProgress((CourseIndex)100));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test GetCourseProgress returns correct progress object
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Test_User_GetCourseProgress_Valid()
|
||||
{
|
||||
var p = new PersistentDataController.SavedCourseProgress();
|
||||
p.courseIndex = CourseIndex.FINGERSPELLING;
|
||||
p.progress = 3.14159265f;
|
||||
user.AddCourseProgress(p);
|
||||
var q = user.GetCourseProgress(CourseIndex.FINGERSPELLING);
|
||||
Assert.AreEqual(q.courseIndex, CourseIndex.FINGERSPELLING);
|
||||
Assert.AreEqual(q.progress, 3.14159265f);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test progress of a course is correctly reset (aka removed)
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Test_User_ResetCourseProgres()
|
||||
{
|
||||
var p = new PersistentDataController.SavedCourseProgress();
|
||||
p.courseIndex = CourseIndex.FINGERSPELLING;
|
||||
user.AddCourseProgress(p);
|
||||
Assert.IsNotNull(user.GetCourseProgress(CourseIndex.FINGERSPELLING));
|
||||
user.ResetCourseProgress(CourseIndex.FINGERSPELLING);
|
||||
Assert.IsNull(user.GetCourseProgress(CourseIndex.FINGERSPELLING));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test GetMinigameProgress returns null when minigame cannot be found
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Test_User_GetMinigameProgress_Null()
|
||||
{
|
||||
Assert.Null(user.GetMinigameProgress(MinigameIndex.SPELLING_BEE));
|
||||
Assert.Null(user.GetMinigameProgress((MinigameIndex)100));
|
||||
|
||||
var p = new PersistentDataController.SavedMinigameProgress();
|
||||
p.minigameIndex = MinigameIndex.SPELLING_BEE;
|
||||
user.AddMinigameProgress(p);
|
||||
Assert.Null(user.GetMinigameProgress(MinigameIndex.HANGMAN));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test GetMinigameProgress returns correct progress object
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Test_User_GetMinigameProgress_Valid()
|
||||
{
|
||||
var p = new PersistentDataController.SavedMinigameProgress();
|
||||
p.minigameIndex = MinigameIndex.SPELLING_BEE;
|
||||
user.AddMinigameProgress(p);
|
||||
var q = user.GetMinigameProgress(MinigameIndex.SPELLING_BEE);
|
||||
Assert.AreEqual(q.minigameIndex, MinigameIndex.SPELLING_BEE);
|
||||
Assert.Zero(q.latestScores.Count);
|
||||
Assert.Zero(q.highestScores.Count);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test progress of a minigame is correctly reset (aka removed)
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Test_User_ResetMinigameProgres()
|
||||
{
|
||||
var p = new PersistentDataController.SavedMinigameProgress();
|
||||
p.minigameIndex = MinigameIndex.SPELLING_BEE;
|
||||
user.AddMinigameProgress(p);
|
||||
Assert.IsNotNull(user.GetMinigameProgress(MinigameIndex.SPELLING_BEE));
|
||||
user.ResetMinigameProgress(MinigameIndex.SPELLING_BEE);
|
||||
Assert.IsNull(user.GetMinigameProgress(MinigameIndex.SPELLING_BEE));
|
||||
}
|
||||
}
|
||||
8
Assets/Accounts/Tests/PlayMode.meta
Normal file
8
Assets/Accounts/Tests/PlayMode.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 03b891ac179161f4b99b84a2205edffa
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
26
Assets/Accounts/Tests/PlayMode/AccountPlayMode.asmdef
Normal file
26
Assets/Accounts/Tests/PlayMode/AccountPlayMode.asmdef
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"name": "AccountPlayMode",
|
||||
"rootNamespace": "",
|
||||
"references": [
|
||||
"UnityEngine.TestRunner",
|
||||
"UnityEditor.TestRunner",
|
||||
"AccountsScripts",
|
||||
"InterfacesScripts",
|
||||
"Unity.TextMeshPro",
|
||||
"CommonScripts",
|
||||
"ArchitectureScripts"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": true,
|
||||
"precompiledReferences": [
|
||||
"nunit.framework.dll"
|
||||
],
|
||||
"autoReferenced": false,
|
||||
"defineConstraints": [
|
||||
"UNITY_INCLUDE_TESTS"
|
||||
],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3692a9a813d54b0449b55e372a28697a
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
379
Assets/Accounts/Tests/PlayMode/ChangeUserScreenTests.cs
Normal file
379
Assets/Accounts/Tests/PlayMode/ChangeUserScreenTests.cs
Normal file
@@ -0,0 +1,379 @@
|
||||
using NUnit.Framework;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
using UnityEngine.UI;
|
||||
|
||||
/// <summary>
|
||||
/// Test the ChangeUserScreen class
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
public class ChangeUserScreenTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Wait time between scene transitions
|
||||
/// </summary>
|
||||
private const float WAIT_TIME = 0.2f;
|
||||
|
||||
/// <summary>
|
||||
/// The default current user when dealing with multiple users
|
||||
/// </summary>
|
||||
private const int currentUser = 2;
|
||||
|
||||
/// <summary>
|
||||
/// Setup the tests for a single user
|
||||
/// </summary>
|
||||
private IEnumerator Setup_ChangeUserScreen_SingleUser(string startScreen = "Accounts/Scenes/ChangeUserScreen")
|
||||
{
|
||||
string path = $"{Application.persistentDataPath}/wesign_unit_test.json";
|
||||
string oneUser = "{\"version\":1537,\"users\":[{\"entries\":[],\"username\":\"Tester0\",\"avatarIndex\":0,\"playtime\":0.0,\"minigames\":[],\"courses\":[]}],\"currentUser\":0,\"currentMinigame\":0,\"currentCourse\":0,\"currentTheme\":0,\"useGPU\":false}";
|
||||
|
||||
File.WriteAllText(path, oneUser);
|
||||
PersistentDataController.PATH = path;
|
||||
PersistentDataController.GetInstance().Load();
|
||||
AssetDatabase.LoadAssetAtPath<UserAvatarList>("Assets/Accounts/ScriptableObjects/UserAvatarList.asset").Awake();
|
||||
|
||||
SystemController.GetInstance().SwapScene(startScreen);
|
||||
yield return new WaitForSeconds(WAIT_TIME);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Setup the tests for a multiple users
|
||||
/// </summary>
|
||||
private IEnumerator Setup_ChangeUserScreen_MultipleUsers(string startScreen = "Accounts/Scenes/ChangeUserScreen")
|
||||
{
|
||||
string path = $"{Application.persistentDataPath}/wesign_unit_test.json";
|
||||
string users = "";
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
users += $"{{\"entries\":[],\"username\":\"Tester{i}\",\"avatarIndex\":{i},\"playtime\":0.0,\"minigames\":[],\"courses\":[]}}";
|
||||
if (i < 4) users += ",";
|
||||
}
|
||||
const int currentUser = 2;
|
||||
string fiveUsers = $"{{\"version\":1537,\"users\":[{users}],\"currentUser\":{currentUser},\"currentMinigame\":0,\"currentCourse\":0,\"currentTheme\":0,\"useGPU\":false}}";
|
||||
|
||||
File.WriteAllText(path, fiveUsers);
|
||||
PersistentDataController.PATH = path;
|
||||
PersistentDataController.GetInstance().Load();
|
||||
AssetDatabase.LoadAssetAtPath<UserAvatarList>("Assets/Accounts/ScriptableObjects/UserAvatarList.asset").Awake();
|
||||
|
||||
SystemController.GetInstance().SwapScene(startScreen);
|
||||
yield return new WaitForSeconds(WAIT_TIME);
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cleanup after testing
|
||||
/// </summary>
|
||||
[TearDown]
|
||||
public void TearDown_ChangeUserScreen()
|
||||
{
|
||||
PersistentDataController.PATH = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether every item that needs to be assign in the editor, is assigned
|
||||
/// </summary>
|
||||
[UnityTest]
|
||||
public IEnumerator Test_EditorAssignments()
|
||||
{
|
||||
yield return Setup_ChangeUserScreen_SingleUser();
|
||||
|
||||
var changeUserController = GameObject.FindObjectOfType<ChangeUserScreen>();
|
||||
Assert.IsNotNull(changeUserController);
|
||||
Assert.IsNotNull(changeUserController.userPrefab);
|
||||
Assert.IsNotNull(changeUserController.usersContainer);
|
||||
Assert.IsNotNull(changeUserController.error);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether the screen is correctly initialized (one user)
|
||||
/// </summary>
|
||||
[UnityTest]
|
||||
public IEnumerator Test_Start_SingleUser()
|
||||
{
|
||||
yield return Setup_ChangeUserScreen_SingleUser();
|
||||
|
||||
var changeUserController = GameObject.FindObjectOfType<ChangeUserScreen>();
|
||||
Assert.IsFalse(changeUserController.error.activeSelf);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether the users is correctly displayed (one user)
|
||||
/// </summary>
|
||||
[UnityTest]
|
||||
public IEnumerator Test_DisplayUsers_SingleUser()
|
||||
{
|
||||
yield return Setup_ChangeUserScreen_SingleUser();
|
||||
|
||||
// The content of the usercard is tested in the `UserCardTests`-script
|
||||
// Here, we only check the amount of users
|
||||
Assert.AreEqual(1, UserList.GetUsers().Count);
|
||||
var cards = GameObject.FindObjectsOfType<UserCard>().ToList();
|
||||
Assert.AreEqual(1, cards.Count);
|
||||
Assert.AreEqual(new Color(66 / 255f, 158 / 255f, 189 / 255f, 1f), cards[0].gameObject.GetComponent<Image>().color);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether the users are correctly displayed (mulitple users)
|
||||
/// </summary>
|
||||
[UnityTest]
|
||||
public IEnumerator Test_DisplayUsers_MultipleUsers()
|
||||
{
|
||||
yield return Setup_ChangeUserScreen_MultipleUsers();
|
||||
|
||||
// The content of the usercard is tested in the `UserCardTests`-script
|
||||
// Here, we only check the amount of users and whether the correct one is selected
|
||||
Assert.AreEqual(UserList.GetCurrentUser().GetUsername(), UserList.GetUserByIndex(currentUser).GetUsername());
|
||||
var cards = GameObject.FindObjectsOfType<UserCard>().ToList();
|
||||
Assert.AreEqual(UserList.GetUsers().Count, cards.Count);
|
||||
for (int i = 0; i < cards.Count; i++)
|
||||
{
|
||||
Color expected = i == currentUser ? new Color(66 / 255f, 158 / 255f, 189 / 255f, 1f) : new Color(159 / 255f, 231 / 255f, 245 / 255f, 1f);
|
||||
Assert.AreEqual(expected, cards[i].gameObject.GetComponent<Image>().color);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether selecting a new user before the current one updates the display correctly
|
||||
/// </summary>
|
||||
[UnityTest]
|
||||
public IEnumerator Test_UpdateSelection_BeforeCurrentUser()
|
||||
{
|
||||
yield return Setup_ChangeUserScreen_MultipleUsers();
|
||||
|
||||
var cards = GameObject.FindObjectsOfType<UserCard>().ToList();
|
||||
|
||||
// Before update
|
||||
for (int i = 0; i < cards.Count; i++)
|
||||
{
|
||||
Color expected = i == currentUser ? new Color(66 / 255f, 158 / 255f, 189 / 255f, 1f) : new Color(159 / 255f, 231 / 255f, 245 / 255f, 1f);
|
||||
Assert.AreEqual(expected, cards[i].gameObject.GetComponent<Image>().color);
|
||||
}
|
||||
|
||||
// Update
|
||||
const int newUser = 1;
|
||||
cards[newUser].selectUser.Invoke();
|
||||
|
||||
// After update
|
||||
for (int i = 0; i < cards.Count; i++)
|
||||
{
|
||||
Color expected = i == newUser ? new Color(66 / 255f, 158 / 255f, 189 / 255f, 1f) : new Color(159 / 255f, 231 / 255f, 245 / 255f, 1f);
|
||||
Assert.AreEqual(expected, cards[i].gameObject.GetComponent<Image>().color);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether selecting the current user for update the display will change nothing
|
||||
/// </summary>
|
||||
[UnityTest]
|
||||
public IEnumerator Test_UpdateSelection_CurrentUser()
|
||||
{
|
||||
yield return Setup_ChangeUserScreen_MultipleUsers();
|
||||
|
||||
var cards = GameObject.FindObjectsOfType<UserCard>().ToList();
|
||||
|
||||
// Before update
|
||||
for (int i = 0; i < cards.Count; i++)
|
||||
{
|
||||
Color expected = i == currentUser ? new Color(66 / 255f, 158 / 255f, 189 / 255f, 1f) : new Color(159 / 255f, 231 / 255f, 245 / 255f, 1f);
|
||||
Assert.AreEqual(expected, cards[i].gameObject.GetComponent<Image>().color);
|
||||
}
|
||||
|
||||
// Update
|
||||
cards[currentUser].selectUser.Invoke();
|
||||
|
||||
// After update
|
||||
for (int i = 0; i < cards.Count; i++)
|
||||
{
|
||||
Color expected = i == currentUser ? new Color(66 / 255f, 158 / 255f, 189 / 255f, 1f) : new Color(159 / 255f, 231 / 255f, 245 / 255f, 1f);
|
||||
Assert.AreEqual(expected, cards[i].gameObject.GetComponent<Image>().color);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether selecting a new user after the current one updates the display correctly
|
||||
/// </summary>
|
||||
[UnityTest]
|
||||
public IEnumerator Test_UpdateSelection_AfterCurrentUser()
|
||||
{
|
||||
yield return Setup_ChangeUserScreen_MultipleUsers();
|
||||
|
||||
var cards = GameObject.FindObjectsOfType<UserCard>().ToList();
|
||||
|
||||
// Before update
|
||||
for (int i = 0; i < cards.Count; i++)
|
||||
{
|
||||
Color expected = i == currentUser ? new Color(66 / 255f, 158 / 255f, 189 / 255f, 1f) : new Color(159 / 255f, 231 / 255f, 245 / 255f, 1f);
|
||||
Assert.AreEqual(expected, cards[i].gameObject.GetComponent<Image>().color);
|
||||
}
|
||||
|
||||
// Update
|
||||
const int newUser = 3;
|
||||
cards[newUser].selectUser.Invoke();
|
||||
|
||||
// After update
|
||||
for (int i = 0; i < cards.Count; i++)
|
||||
{
|
||||
Color expected = i == newUser ? new Color(66 / 255f, 158 / 255f, 189 / 255f, 1f) : new Color(159 / 255f, 231 / 255f, 245 / 255f, 1f);
|
||||
Assert.AreEqual(expected, cards[i].gameObject.GetComponent<Image>().color);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test IChooseYou callback
|
||||
/// </summary>
|
||||
[UnityTest]
|
||||
public IEnumerator Test_IChooseYou()
|
||||
{
|
||||
yield return Setup_ChangeUserScreen_SingleUser("Common/Scenes/MainMenuScreen");
|
||||
|
||||
SystemController.GetInstance().LoadNextScene("Accounts/Scenes/ChangeUserScreen");
|
||||
yield return new WaitForSeconds(WAIT_TIME);
|
||||
|
||||
var changeUserController = GameObject.FindObjectOfType<ChangeUserScreen>();
|
||||
changeUserController.IChooseYou();
|
||||
yield return new WaitForSeconds(WAIT_TIME);
|
||||
|
||||
Assert.AreEqual(SystemController.GetSceneIndex("Common/Scenes/MainMenuScreen"), SystemController.GetInstance().currentScene);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test the GotoUserCreation callback
|
||||
/// </summary>
|
||||
[UnityTest]
|
||||
public IEnumerator Test_GotoUserCreation()
|
||||
{
|
||||
yield return Setup_ChangeUserScreen_SingleUser();
|
||||
|
||||
var changeUserController = GameObject.FindObjectOfType<ChangeUserScreen>();
|
||||
changeUserController.GotoUserCreation();
|
||||
yield return new WaitForSeconds(WAIT_TIME);
|
||||
|
||||
var userCreationController = GameObject.FindObjectOfType<UserCreationScreen>();
|
||||
Assert.IsNotNull(userCreationController);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test the user cards DeleteUser callback
|
||||
/// </summary>
|
||||
[UnityTest]
|
||||
public IEnumerator Test_UserCardDeleteUser_BeforeCurrentUser()
|
||||
{
|
||||
yield return Setup_ChangeUserScreen_MultipleUsers();
|
||||
|
||||
// Before update
|
||||
var oldCards = GameObject.FindObjectsOfType<UserCard>().ToList();
|
||||
for (int i = 0; i < oldCards.Count; i++)
|
||||
{
|
||||
Color expected = i == currentUser ? new Color(66 / 255f, 158 / 255f, 189 / 255f, 1f) : new Color(159 / 255f, 231 / 255f, 245 / 255f, 1f);
|
||||
Assert.AreEqual(expected, oldCards[i].gameObject.GetComponent<Image>().color);
|
||||
}
|
||||
|
||||
// Update
|
||||
oldCards[1].DeleteUser();
|
||||
var changeUserController = GameObject.FindObjectOfType<ChangeUserScreen>();
|
||||
Assert.IsFalse(changeUserController.error.activeSelf);
|
||||
yield return new WaitForSeconds(WAIT_TIME);
|
||||
|
||||
// After update
|
||||
var newCards = GameObject.FindObjectsOfType<UserCard>().ToList();
|
||||
Assert.AreEqual(oldCards.Count - 1, newCards.Count);
|
||||
for (int i = 0; i < newCards.Count; i++)
|
||||
{
|
||||
Color expected = i == (currentUser - 1) ? new Color(66 / 255f, 158 / 255f, 189 / 255f, 1f) : new Color(159 / 255f, 231 / 255f, 245 / 255f, 1f);
|
||||
Assert.AreEqual(expected, newCards[i].gameObject.GetComponent<Image>().color);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test the user cards DeleteUser callback
|
||||
/// </summary>
|
||||
[UnityTest]
|
||||
public IEnumerator Test_UserCardDeleteUser_CurrentUser()
|
||||
{
|
||||
yield return Setup_ChangeUserScreen_MultipleUsers();
|
||||
|
||||
// Before update
|
||||
var oldCards = GameObject.FindObjectsOfType<UserCard>().ToList();
|
||||
for (int i = 0; i < oldCards.Count; i++)
|
||||
{
|
||||
Color expected = i == currentUser ? new Color(66 / 255f, 158 / 255f, 189 / 255f, 1f) : new Color(159 / 255f, 231 / 255f, 245 / 255f, 1f);
|
||||
Assert.AreEqual(expected, oldCards[i].gameObject.GetComponent<Image>().color);
|
||||
}
|
||||
|
||||
// Update
|
||||
oldCards[currentUser].DeleteUser();
|
||||
var changeUserController = GameObject.FindObjectOfType<ChangeUserScreen>();
|
||||
Assert.IsFalse(changeUserController.error.activeSelf);
|
||||
yield return new WaitForSeconds(WAIT_TIME);
|
||||
|
||||
// After update
|
||||
var newCards = GameObject.FindObjectsOfType<UserCard>().ToList();
|
||||
Assert.AreEqual(oldCards.Count - 1, newCards.Count);
|
||||
for (int i = 0; i < newCards.Count; i++)
|
||||
{
|
||||
Color expected = i == currentUser ? new Color(66 / 255f, 158 / 255f, 189 / 255f, 1f) : new Color(159 / 255f, 231 / 255f, 245 / 255f, 1f);
|
||||
Assert.AreEqual(expected, newCards[i].gameObject.GetComponent<Image>().color);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test the user cards DeleteUser callback
|
||||
/// </summary>
|
||||
[UnityTest]
|
||||
public IEnumerator Test_UserCardDeleteUser_AfterCurrentUser()
|
||||
{
|
||||
yield return Setup_ChangeUserScreen_MultipleUsers();
|
||||
|
||||
// Before update
|
||||
var oldCards = GameObject.FindObjectsOfType<UserCard>().ToList();
|
||||
for (int i = 0; i < oldCards.Count; i++)
|
||||
{
|
||||
Color expected = i == currentUser ? new Color(66 / 255f, 158 / 255f, 189 / 255f, 1f) : new Color(159 / 255f, 231 / 255f, 245 / 255f, 1f);
|
||||
Assert.AreEqual(expected, oldCards[i].gameObject.GetComponent<Image>().color);
|
||||
}
|
||||
|
||||
// Update
|
||||
oldCards[3].DeleteUser();
|
||||
var changeUserController = GameObject.FindObjectOfType<ChangeUserScreen>();
|
||||
Assert.IsFalse(changeUserController.error.activeSelf);
|
||||
yield return new WaitForSeconds(WAIT_TIME);
|
||||
|
||||
// After update
|
||||
var newCards = GameObject.FindObjectsOfType<UserCard>().ToList();
|
||||
Assert.AreEqual(oldCards.Count - 1, newCards.Count);
|
||||
for (int i = 0; i < newCards.Count; i++)
|
||||
{
|
||||
Color expected = i == currentUser ? new Color(66 / 255f, 158 / 255f, 189 / 255f, 1f) : new Color(159 / 255f, 231 / 255f, 245 / 255f, 1f);
|
||||
Assert.AreEqual(expected, newCards[i].gameObject.GetComponent<Image>().color);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test the user cards DeleteUser callback
|
||||
/// </summary>
|
||||
[UnityTest]
|
||||
public IEnumerator Test_UserCardDeleteUser_Invalid()
|
||||
{
|
||||
yield return Setup_ChangeUserScreen_SingleUser();
|
||||
|
||||
// Before update
|
||||
var oldCards = GameObject.FindObjectsOfType<UserCard>().ToList();
|
||||
Assert.AreEqual(1, oldCards.Count);
|
||||
Assert.AreEqual(new Color(66 / 255f, 158 / 255f, 189 / 255f, 1f), oldCards[0].gameObject.GetComponent<Image>().color);
|
||||
|
||||
// Update
|
||||
oldCards[0].DeleteUser();
|
||||
var changeUserController = GameObject.FindObjectOfType<ChangeUserScreen>();
|
||||
Assert.IsTrue(changeUserController.error.activeSelf);
|
||||
|
||||
// After update
|
||||
var newCards = GameObject.FindObjectsOfType<UserCard>().ToList();
|
||||
Assert.AreEqual(1, newCards.Count);
|
||||
Assert.AreEqual(new Color(66 / 255f, 158 / 255f, 189 / 255f, 1f), newCards[0].gameObject.GetComponent<Image>().color);
|
||||
}
|
||||
}
|
||||
11
Assets/Accounts/Tests/PlayMode/ChangeUserScreenTests.cs.meta
Normal file
11
Assets/Accounts/Tests/PlayMode/ChangeUserScreenTests.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 82964bdf541a6d64bae05c104ef64494
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
80
Assets/Accounts/Tests/PlayMode/CourseProgressCardTests.cs
Normal file
80
Assets/Accounts/Tests/PlayMode/CourseProgressCardTests.cs
Normal file
@@ -0,0 +1,80 @@
|
||||
using NUnit.Framework;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
|
||||
/// <summary>
|
||||
/// Test the CourseProgressCard class
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
public class CourseProgressCardTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Wait time between scene transitions
|
||||
/// </summary>
|
||||
private const float WAIT_TIME = 0.2f;
|
||||
|
||||
/// <summary>
|
||||
/// Setup the CourseProgressCard tests
|
||||
/// </summary>
|
||||
[UnitySetUp]
|
||||
public IEnumerator Setup_CourseProgressCard()
|
||||
{
|
||||
string path = $"{Application.persistentDataPath}/wesign_unit_test.json";
|
||||
string course = "{\"entries\":[],\"courseIndex\":0,\"progress\":0.03846153989434242,\"completedLearnables\":1,\"inUseLearnables\":7,\"totalLearnables\":26,\"learnables\":[{\"entries\":[],\"index\":0,\"inUse\":true,\"name\":\"A\",\"progress\":3.0},{\"entries\":[],\"index\":1,\"inUse\":true,\"name\":\"B\",\"progress\":4.5},{\"entries\":[],\"index\":2,\"inUse\":true,\"name\":\"C\",\"progress\":1.5},{\"entries\":[],\"index\":3,\"inUse\":true,\"name\":\"D\",\"progress\":1.5},{\"entries\":[],\"index\":4,\"inUse\":true,\"name\":\"E\",\"progress\":1.5},{\"entries\":[],\"index\":5,\"inUse\":true,\"name\":\"F\",\"progress\":1.5},{\"entries\":[],\"index\":6,\"inUse\":true,\"name\":\"G\",\"progress\":0.0},{\"entries\":[],\"index\":7,\"inUse\":false,\"name\":\"H\",\"progress\":0.0},{\"entries\":[],\"index\":8,\"inUse\":false,\"name\":\"I\",\"progress\":0.0},{\"entries\":[],\"index\":9,\"inUse\":false,\"name\":\"J\",\"progress\":0.0},{\"entries\":[],\"index\":10,\"inUse\":false,\"name\":\"K\",\"progress\":0.0},{\"entries\":[],\"index\":11,\"inUse\":false,\"name\":\"L\",\"progress\":0.0},{\"entries\":[],\"index\":12,\"inUse\":false,\"name\":\"M\",\"progress\":0.0},{\"entries\":[],\"index\":13,\"inUse\":false,\"name\":\"N\",\"progress\":0.0},{\"entries\":[],\"index\":14,\"inUse\":false,\"name\":\"O\",\"progress\":0.0},{\"entries\":[],\"index\":15,\"inUse\":false,\"name\":\"P\",\"progress\":0.0},{\"entries\":[],\"index\":16,\"inUse\":false,\"name\":\"Q\",\"progress\":0.0},{\"entries\":[],\"index\":17,\"inUse\":false,\"name\":\"R\",\"progress\":0.0},{\"entries\":[],\"index\":18,\"inUse\":false,\"name\":\"S\",\"progress\":0.0},{\"entries\":[],\"index\":19,\"inUse\":false,\"name\":\"T\",\"progress\":0.0},{\"entries\":[],\"index\":20,\"inUse\":false,\"name\":\"U\",\"progress\":0.0},{\"entries\":[],\"index\":21,\"inUse\":false,\"name\":\"V\",\"progress\":0.0},{\"entries\":[],\"index\":22,\"inUse\":false,\"name\":\"W\",\"progress\":0.0},{\"entries\":[],\"index\":23,\"inUse\":false,\"name\":\"X\",\"progress\":0.0},{\"entries\":[],\"index\":24,\"inUse\":false,\"name\":\"Y\",\"progress\":0.0},{\"entries\":[],\"index\":25,\"inUse\":false,\"name\":\"Z\",\"progress\":0.0}]}";
|
||||
string oneUser = $"{{\"version\":1537,\"users\":[{{\"entries\":[],\"username\":\"Tester0\",\"avatarIndex\":0,\"playtime\":0.0,\"minigames\":[],\"courses\":[{course}]}}],\"currentUser\":0,\"currentMinigame\":0,\"currentCourse\":0,\"currentTheme\":0,\"useGPU\":false}}";
|
||||
|
||||
File.WriteAllText(path, oneUser);
|
||||
PersistentDataController.PATH = path;
|
||||
PersistentDataController.GetInstance().Load();
|
||||
AssetDatabase.LoadAssetAtPath<UserAvatarList>("Assets/Accounts/ScriptableObjects/UserAvatarList.asset").Awake();
|
||||
|
||||
SystemController.GetInstance().SwapScene("Accounts/Scenes/UserProgressScreen");
|
||||
yield return new WaitForSeconds(WAIT_TIME);
|
||||
|
||||
GameObject.FindObjectOfType<UserProgressScreen>().DisplayCourses();
|
||||
yield return new WaitForSeconds(WAIT_TIME);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cleanup after testing
|
||||
/// </summary>
|
||||
[TearDown]
|
||||
public void TearDown_MinigameProgressCard()
|
||||
{
|
||||
PersistentDataController.PATH = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether every item that needs to be assign in the editor, is assigned
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Test_EditorAssignments()
|
||||
{
|
||||
var card = GameObject.FindObjectOfType<CourseProgressCard>();
|
||||
Assert.IsNotNull(card);
|
||||
Assert.IsNotNull(card.button);
|
||||
Assert.IsNotNull(card.courseProgress);
|
||||
Assert.IsNotNull(card.courseList);
|
||||
Assert.IsNotNull(card.thumbnail);
|
||||
Assert.IsNotNull(card.title);
|
||||
Assert.IsNotNull(card.progressBar);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether the card is correctly initialized
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Test_Start()
|
||||
{
|
||||
var card = GameObject.FindObjectOfType<CourseProgressCard>();
|
||||
Course course = card.courseList.GetCourseByIndex(card.courseProgress.courseIndex);
|
||||
|
||||
Assert.AreEqual(course.thumbnail, card.thumbnail.sprite);
|
||||
Assert.AreEqual(course.title, card.title.text);
|
||||
Assert.AreEqual(card.courseProgress.progress, card.progressBar.value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 82e22c178ff48c146b6c87a7552e97ed
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
78
Assets/Accounts/Tests/PlayMode/LearnableProgressCardTests.cs
Normal file
78
Assets/Accounts/Tests/PlayMode/LearnableProgressCardTests.cs
Normal file
@@ -0,0 +1,78 @@
|
||||
using NUnit.Framework;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
|
||||
/// <summary>
|
||||
/// Test the LearnableProgressCard class
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
public class LearnableProgressCardTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Wait time between scene transitions
|
||||
/// </summary>
|
||||
private const float WAIT_TIME = 0.2f;
|
||||
|
||||
/// <summary>
|
||||
/// Setup the LearnableProgressCard tests
|
||||
/// </summary>
|
||||
[UnitySetUp]
|
||||
public IEnumerator Setup_CourseProgressCard()
|
||||
{
|
||||
string path = $"{Application.persistentDataPath}/wesign_unit_test.json";
|
||||
string course = "{\"entries\":[],\"courseIndex\":0,\"progress\":0.03846153989434242,\"completedLearnables\":1,\"inUseLearnables\":7,\"totalLearnables\":26,\"learnables\":[{\"entries\":[],\"index\":0,\"inUse\":true,\"name\":\"A\",\"progress\":3.0},{\"entries\":[],\"index\":1,\"inUse\":true,\"name\":\"B\",\"progress\":4.5},{\"entries\":[],\"index\":2,\"inUse\":true,\"name\":\"C\",\"progress\":1.5},{\"entries\":[],\"index\":3,\"inUse\":true,\"name\":\"D\",\"progress\":1.5},{\"entries\":[],\"index\":4,\"inUse\":true,\"name\":\"E\",\"progress\":1.5},{\"entries\":[],\"index\":5,\"inUse\":true,\"name\":\"F\",\"progress\":1.5},{\"entries\":[],\"index\":6,\"inUse\":true,\"name\":\"G\",\"progress\":0.0},{\"entries\":[],\"index\":7,\"inUse\":false,\"name\":\"H\",\"progress\":0.0},{\"entries\":[],\"index\":8,\"inUse\":false,\"name\":\"I\",\"progress\":0.0},{\"entries\":[],\"index\":9,\"inUse\":false,\"name\":\"J\",\"progress\":0.0},{\"entries\":[],\"index\":10,\"inUse\":false,\"name\":\"K\",\"progress\":0.0},{\"entries\":[],\"index\":11,\"inUse\":false,\"name\":\"L\",\"progress\":0.0},{\"entries\":[],\"index\":12,\"inUse\":false,\"name\":\"M\",\"progress\":0.0},{\"entries\":[],\"index\":13,\"inUse\":false,\"name\":\"N\",\"progress\":0.0},{\"entries\":[],\"index\":14,\"inUse\":false,\"name\":\"O\",\"progress\":0.0},{\"entries\":[],\"index\":15,\"inUse\":false,\"name\":\"P\",\"progress\":0.0},{\"entries\":[],\"index\":16,\"inUse\":false,\"name\":\"Q\",\"progress\":0.0},{\"entries\":[],\"index\":17,\"inUse\":false,\"name\":\"R\",\"progress\":0.0},{\"entries\":[],\"index\":18,\"inUse\":false,\"name\":\"S\",\"progress\":0.0},{\"entries\":[],\"index\":19,\"inUse\":false,\"name\":\"T\",\"progress\":0.0},{\"entries\":[],\"index\":20,\"inUse\":false,\"name\":\"U\",\"progress\":0.0},{\"entries\":[],\"index\":21,\"inUse\":false,\"name\":\"V\",\"progress\":0.0},{\"entries\":[],\"index\":22,\"inUse\":false,\"name\":\"W\",\"progress\":0.0},{\"entries\":[],\"index\":23,\"inUse\":false,\"name\":\"X\",\"progress\":0.0},{\"entries\":[],\"index\":24,\"inUse\":false,\"name\":\"Y\",\"progress\":0.0},{\"entries\":[],\"index\":25,\"inUse\":false,\"name\":\"Z\",\"progress\":0.0}]}";
|
||||
string oneUser = $"{{\"version\":1537,\"users\":[{{\"entries\":[],\"username\":\"Tester0\",\"avatarIndex\":0,\"playtime\":0.0,\"minigames\":[],\"courses\":[{course}]}}],\"currentUser\":0,\"currentMinigame\":0,\"currentCourse\":0,\"currentTheme\":0,\"useGPU\":false}}";
|
||||
|
||||
File.WriteAllText(path, oneUser);
|
||||
PersistentDataController.PATH = path;
|
||||
PersistentDataController.GetInstance().Load();
|
||||
AssetDatabase.LoadAssetAtPath<UserAvatarList>("Assets/Accounts/ScriptableObjects/UserAvatarList.asset").Awake();
|
||||
|
||||
SystemController.GetInstance().SwapScene("Accounts/Scenes/UserProgressScreen");
|
||||
yield return new WaitForSeconds(WAIT_TIME);
|
||||
|
||||
GameObject.FindObjectOfType<UserProgressScreen>().DisplayCourses();
|
||||
yield return new WaitForSeconds(WAIT_TIME);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cleanup after testing
|
||||
/// </summary>
|
||||
[TearDown]
|
||||
public void TearDown_MinigameProgressCard()
|
||||
{
|
||||
PersistentDataController.PATH = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether every item that needs to be assign in the editor, is assigned
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Test_EditorAssignments()
|
||||
{
|
||||
var card = GameObject.FindObjectOfType<LearnableProgressCard>();
|
||||
Assert.IsNotNull(card);
|
||||
Assert.IsNotNull(card.learnable);
|
||||
Assert.IsNotNull(card.thumbnail);
|
||||
Assert.IsNotNull(card.stars);
|
||||
Assert.AreEqual(3, card.stars.Count);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether the card is correctly initialized
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Test_Start()
|
||||
{
|
||||
var card = GameObject.FindObjectOfType<LearnableProgressCard>();
|
||||
|
||||
Assert.AreEqual(card.learnable.image, card.thumbnail.sprite);
|
||||
var starRewards = new float[] { 1.0f, 2.5f, 4.0f, };
|
||||
for (int i = 0; i < 3; i++)
|
||||
Assert.AreEqual(starRewards[i] < card.progress.progress ? Color.white : Color.black, card.stars[i].color);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 238c4a8454aff2744ac782a49d2fbbd6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
120
Assets/Accounts/Tests/PlayMode/MinigameProgressCardTests.cs
Normal file
120
Assets/Accounts/Tests/PlayMode/MinigameProgressCardTests.cs
Normal file
@@ -0,0 +1,120 @@
|
||||
using NUnit.Framework;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
|
||||
/// <summary>
|
||||
/// Test the MinigameProgressCard class
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
public class MinigameProgressCardTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Wait time between scene transitions
|
||||
/// </summary>
|
||||
private const float WAIT_TIME = 0.2f;
|
||||
|
||||
/// <summary>
|
||||
/// Setup the MinigameProgressCard tests
|
||||
/// </summary>
|
||||
private IEnumerator Setup_MinigameProgressCard()
|
||||
{
|
||||
string path = $"{Application.persistentDataPath}/wesign_unit_test.json";
|
||||
string minigame = "{\"entries\":[],\"minigameIndex\":1,\"latestScores\":[{\"scoreValue\":70,\"time\":\"19/04/2023 22:32:39\"},{\"scoreValue\":55,\"time\":\"20/04/2023 11:50:10\"},{\"scoreValue\":55,\"time\":\"20/04/2023 13:27:15\"}],\"highestScores\":[{\"scoreValue\":70,\"time\":\"19/04/2023 22:32:39\"},{\"scoreValue\":55,\"time\":\"20/04/2023 11:50:10\"},{\"scoreValue\":55,\"time\":\"20/04/2023 13:27:15\"}]}";
|
||||
string oneUser = $"{{\"version\":1537,\"users\":[{{\"entries\":[],\"username\":\"Tester0\",\"avatarIndex\":0,\"playtime\":0.0,\"minigames\":[{minigame}],\"courses\":[]}}],\"currentUser\":0,\"currentMinigame\":0,\"currentCourse\":0,\"currentTheme\":0,\"useGPU\":false}}";
|
||||
|
||||
File.WriteAllText(path, oneUser);
|
||||
PersistentDataController.PATH = path;
|
||||
PersistentDataController.GetInstance().Load();
|
||||
AssetDatabase.LoadAssetAtPath<UserAvatarList>("Assets/Accounts/ScriptableObjects/UserAvatarList.asset").Awake();
|
||||
|
||||
SystemController.GetInstance().SwapScene("Accounts/Scenes/UserProgressScreen");
|
||||
yield return new WaitForSeconds(WAIT_TIME);
|
||||
|
||||
GameObject.FindObjectOfType<UserProgressScreen>().DisplayMinigames();
|
||||
yield return new WaitForSeconds(WAIT_TIME);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Setup the MinigameProgressCard tests
|
||||
/// </summary>
|
||||
private IEnumerator Setup_MinigameProgressCard_Empty()
|
||||
{
|
||||
string path = $"{Application.persistentDataPath}/wesign_unit_test.json";
|
||||
string minigame = "{\"entries\":[],\"minigameIndex\":0,\"latestScores\":[],\"highestScores\":[]}";
|
||||
string oneUser = $"{{\"version\":1537,\"users\":[{{\"entries\":[],\"username\":\"Tester0\",\"avatarIndex\":0,\"playtime\":0.0,\"minigames\":[{minigame}],\"courses\":[]}}],\"currentUser\":0,\"currentMinigame\":0,\"currentCourse\":0,\"currentTheme\":0,\"useGPU\":false}}";
|
||||
|
||||
File.WriteAllText(path, oneUser);
|
||||
PersistentDataController.PATH = path;
|
||||
PersistentDataController.GetInstance().Load();
|
||||
AssetDatabase.LoadAssetAtPath<UserAvatarList>("Assets/Accounts/ScriptableObjects/UserAvatarList.asset").Awake();
|
||||
|
||||
SystemController.GetInstance().SwapScene("Accounts/Scenes/UserProgressScreen");
|
||||
yield return new WaitForSeconds(WAIT_TIME);
|
||||
|
||||
GameObject.FindObjectOfType<UserProgressScreen>().DisplayMinigames();
|
||||
yield return new WaitForSeconds(WAIT_TIME);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cleanup after testing
|
||||
/// </summary>
|
||||
[TearDown]
|
||||
public void TearDown_MinigameProgressCard()
|
||||
{
|
||||
PersistentDataController.PATH = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether every item that needs to be assign in the editor, is assigned
|
||||
/// </summary>
|
||||
[UnityTest]
|
||||
public IEnumerator Test_EditorAssignments()
|
||||
{
|
||||
yield return Setup_MinigameProgressCard();
|
||||
|
||||
var card = GameObject.FindObjectOfType<MinigameProgressCard>();
|
||||
Assert.IsNotNull(card);
|
||||
Assert.IsNotNull(card.button);
|
||||
Assert.IsNotNull(card.minigameProgress);
|
||||
Assert.IsNotNull(card.minigameList);
|
||||
Assert.IsNotNull(card.thumbnail);
|
||||
Assert.IsNotNull(card.title);
|
||||
Assert.IsNotNull(card.highscore);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether the card is correctly initialized
|
||||
/// </summary>
|
||||
[UnityTest]
|
||||
public IEnumerator Test_Start()
|
||||
{
|
||||
yield return Setup_MinigameProgressCard();
|
||||
|
||||
var card = GameObject.FindObjectOfType<MinigameProgressCard>();
|
||||
Minigame minigame = card.minigameList.GetMinigameByIndex(card.minigameProgress.minigameIndex);
|
||||
|
||||
Assert.AreEqual(minigame.thumbnail, card.thumbnail.sprite);
|
||||
Assert.AreEqual(minigame.title, card.title.text);
|
||||
Assert.AreEqual($"TOPSCORE: {card.minigameProgress.highestScores[0].scoreValue}", card.highscore.text);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether an empty card is correctly initialized
|
||||
/// </summary>
|
||||
[UnityTest]
|
||||
public IEnumerator Test_Start_Empty()
|
||||
{
|
||||
yield return Setup_MinigameProgressCard_Empty();
|
||||
|
||||
var card = GameObject.FindObjectOfType<MinigameProgressCard>();
|
||||
Minigame minigame = card.minigameList.GetMinigameByIndex(card.minigameProgress.minigameIndex);
|
||||
|
||||
Assert.AreEqual(minigame.thumbnail, card.thumbnail.sprite);
|
||||
Assert.AreEqual(minigame.title, card.title.text);
|
||||
Assert.AreEqual("(NOG) GEEN TOPSCORE", card.highscore.text);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5c4901279eafb874a897edf876b30def
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
168
Assets/Accounts/Tests/PlayMode/PanelCourseProgressTests.cs
Normal file
168
Assets/Accounts/Tests/PlayMode/PanelCourseProgressTests.cs
Normal file
File diff suppressed because one or more lines are too long
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 20981edad710f544984afd94847fa502
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
199
Assets/Accounts/Tests/PlayMode/PanelMinigamesProgressTests.cs
Normal file
199
Assets/Accounts/Tests/PlayMode/PanelMinigamesProgressTests.cs
Normal file
@@ -0,0 +1,199 @@
|
||||
using NUnit.Framework;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
using UnityEngine.UI;
|
||||
|
||||
/// <summary>
|
||||
/// Test the PanelMinigameProgress class
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
public class PanelMinigameProgressTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Wait time between scene transitions
|
||||
/// </summary>
|
||||
private const float WAIT_TIME = 0.2f;
|
||||
|
||||
/// <summary>
|
||||
/// Setup the PanelMinigameProgress tests
|
||||
/// </summary>
|
||||
private IEnumerator Setup_PanelMinigameProgress()
|
||||
{
|
||||
string path = $"{Application.persistentDataPath}/wesign_unit_test.json";
|
||||
string minigame = "{\"entries\":[],\"minigameIndex\":1,\"latestScores\":[{\"scoreValue\":70,\"time\":\"19/04/2023 22:32:39\"},{\"scoreValue\":55,\"time\":\"20/04/2023 11:50:10\"},{\"scoreValue\":55,\"time\":\"20/04/2023 13:27:15\"}],\"highestScores\":[{\"scoreValue\":70,\"time\":\"19/04/2023 22:32:39\"},{\"scoreValue\":55,\"time\":\"20/04/2023 11:50:10\"},{\"scoreValue\":55,\"time\":\"20/04/2023 13:27:15\"}]}";
|
||||
string oneUser = $"{{\"version\":1537,\"users\":[{{\"entries\":[],\"username\":\"Tester0\",\"avatarIndex\":0,\"playtime\":0.0,\"minigames\":[{minigame}],\"courses\":[]}}],\"currentUser\":0,\"currentMinigame\":0,\"currentCourse\":0,\"currentTheme\":0,\"useGPU\":false}}";
|
||||
|
||||
File.WriteAllText(path, oneUser);
|
||||
PersistentDataController.PATH = path;
|
||||
PersistentDataController.GetInstance().Load();
|
||||
AssetDatabase.LoadAssetAtPath<UserAvatarList>("Assets/Accounts/ScriptableObjects/UserAvatarList.asset").Awake();
|
||||
|
||||
SystemController.GetInstance().SwapScene("Accounts/Scenes/UserProgressScreen");
|
||||
yield return new WaitForSeconds(WAIT_TIME);
|
||||
|
||||
GameObject.FindObjectOfType<UserProgressScreen>().DisplayMinigames();
|
||||
yield return new WaitForSeconds(WAIT_TIME);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Setup the PanelMinigameProgress tests
|
||||
/// </summary>
|
||||
private IEnumerator Setup_PanelMinigameProgress_Empty()
|
||||
{
|
||||
string path = $"{Application.persistentDataPath}/wesign_unit_test.json";
|
||||
string oneUser = $"{{\"version\":1537,\"users\":[{{\"entries\":[],\"username\":\"Tester0\",\"avatarIndex\":0,\"playtime\":0.0,\"minigames\":[],\"courses\":[]}}],\"currentUser\":0,\"currentMinigame\":0,\"currentCourse\":0,\"currentTheme\":0,\"useGPU\":false}}";
|
||||
|
||||
File.WriteAllText(path, oneUser);
|
||||
PersistentDataController.PATH = path;
|
||||
PersistentDataController.GetInstance().Load();
|
||||
AssetDatabase.LoadAssetAtPath<UserAvatarList>("Assets/Accounts/ScriptableObjects/UserAvatarList.asset").Awake();
|
||||
|
||||
SystemController.GetInstance().SwapScene("Accounts/Scenes/UserProgressScreen");
|
||||
yield return new WaitForSeconds(WAIT_TIME);
|
||||
|
||||
GameObject.FindObjectOfType<UserProgressScreen>().DisplayMinigames();
|
||||
yield return new WaitForSeconds(WAIT_TIME);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Setup the PanelMinigameProgress tests
|
||||
/// </summary>
|
||||
private IEnumerator Setup_PanelMinigameProgress_NoScorePresent()
|
||||
{
|
||||
string path = $"{Application.persistentDataPath}/wesign_unit_test.json";
|
||||
string minigame = "{\"entries\":[],\"minigameIndex\":1,\"latestScores\":[],\"highestScores\":[]}";
|
||||
string oneUser = $"{{\"version\":1537,\"users\":[{{\"entries\":[],\"username\":\"Tester0\",\"avatarIndex\":0,\"playtime\":0.0,\"minigames\":[{minigame}],\"courses\":[]}}],\"currentUser\":0,\"currentMinigame\":0,\"currentCourse\":0,\"currentTheme\":0,\"useGPU\":false}}";
|
||||
|
||||
File.WriteAllText(path, oneUser);
|
||||
PersistentDataController.PATH = path;
|
||||
PersistentDataController.GetInstance().Load();
|
||||
AssetDatabase.LoadAssetAtPath<UserAvatarList>("Assets/Accounts/ScriptableObjects/UserAvatarList.asset").Awake();
|
||||
|
||||
SystemController.GetInstance().SwapScene("Accounts/Scenes/UserProgressScreen");
|
||||
yield return new WaitForSeconds(WAIT_TIME);
|
||||
|
||||
GameObject.FindObjectOfType<UserProgressScreen>().DisplayMinigames();
|
||||
yield return new WaitForSeconds(WAIT_TIME);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Setup the PanelMinigameProgress tests
|
||||
/// </summary>
|
||||
private IEnumerator Setup_PanelMinigameProgress_Multiple()
|
||||
{
|
||||
string path = $"{Application.persistentDataPath}/wesign_unit_test.json";
|
||||
string minigame = "[{\"entries\":[],\"minigameIndex\":1,\"latestScores\":[{\"scoreValue\":70,\"time\":\"20/04/2023 16:08:43\"},{\"scoreValue\":20,\"time\":\"20/04/2023 16:11:53\"}],\"highestScores\":[{\"scoreValue\":70,\"time\":\"20/04/2023 16:08:43\"},{\"scoreValue\":20,\"time\":\"20/04/2023 16:11:53\"}]},{\"entries\":[],\"minigameIndex\":2,\"latestScores\":[{\"scoreValue\":194,\"time\":\"20/04/2023 15:27:41\"},{\"scoreValue\":155,\"time\":\"20/04/2023 15:28:56\"},{\"scoreValue\":84,\"time\":\"20/04/2023 15:42:10\"},{\"scoreValue\":465,\"time\":\"20/04/2023 16:14:22\"}],\"highestScores\":[{\"scoreValue\":465,\"time\":\"20/04/2023 16:14:22\"},{\"scoreValue\":194,\"time\":\"20/04/2023 15:27:41\"},{\"scoreValue\":155,\"time\":\"20/04/2023 15:28:56\"},{\"scoreValue\":84,\"time\":\"20/04/2023 15:42:10\"}]},{\"entries\":[],\"minigameIndex\":0,\"latestScores\":[{\"scoreValue\":1090,\"time\":\"20/04/2023 16:02:14\"},{\"scoreValue\":1180,\"time\":\"20/04/2023 16:07:02\"}],\"highestScores\":[{\"scoreValue\":1180,\"time\":\"20/04/2023 16:07:02\"},{\"scoreValue\":1090,\"time\":\"20/04/2023 16:02:14\"}]}]";
|
||||
string oneUser = $"{{\"version\":1537,\"users\":[{{\"entries\":[],\"username\":\"Tester0\",\"avatarIndex\":0,\"playtime\":0.0,\"minigames\":{minigame},\"courses\":[]}}],\"currentUser\":0,\"currentMinigame\":0,\"currentCourse\":0,\"currentTheme\":0,\"useGPU\":false}}";
|
||||
|
||||
File.WriteAllText(path, oneUser);
|
||||
PersistentDataController.PATH = path;
|
||||
PersistentDataController.GetInstance().Load();
|
||||
AssetDatabase.LoadAssetAtPath<UserAvatarList>("Assets/Accounts/ScriptableObjects/UserAvatarList.asset").Awake();
|
||||
|
||||
SystemController.GetInstance().SwapScene("Accounts/Scenes/UserProgressScreen");
|
||||
yield return new WaitForSeconds(WAIT_TIME);
|
||||
|
||||
GameObject.FindObjectOfType<UserProgressScreen>().DisplayMinigames();
|
||||
yield return new WaitForSeconds(WAIT_TIME);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cleanup after testing
|
||||
/// </summary>
|
||||
[TearDown]
|
||||
public void TearDown_PanelMinigameProgress()
|
||||
{
|
||||
PersistentDataController.PATH = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether every item that needs to be assign in the editor, is assigned
|
||||
/// </summary>
|
||||
[UnityTest]
|
||||
public IEnumerator Test_EditorAssignments()
|
||||
{
|
||||
yield return Setup_PanelMinigameProgress();
|
||||
|
||||
var panel = GameObject.FindObjectOfType<PanelMinigameProgress>();
|
||||
Assert.IsNotNull(panel);
|
||||
Assert.IsNotNull(panel.minigameList);
|
||||
Assert.IsNotNull(panel.minigameCardPrefab);
|
||||
Assert.IsNotNull(panel.minigamesContainer);
|
||||
Assert.IsNotNull(panel.minigameInfo);
|
||||
Assert.IsNotNull(panel.emptyMinigames);
|
||||
Assert.IsNotNull(panel.minigameTitle);
|
||||
Assert.IsNotNull(panel.progressGraph);
|
||||
Assert.IsNotNull(panel.emptyHighscore);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether the panel is correctly initialized
|
||||
/// </summary>
|
||||
[UnityTest]
|
||||
public IEnumerator Test_Start()
|
||||
{
|
||||
yield return Setup_PanelMinigameProgress();
|
||||
|
||||
var panel = GameObject.FindObjectOfType<PanelMinigameProgress>();
|
||||
Assert.IsTrue(panel.minigameInfo.gameObject.activeSelf);
|
||||
Assert.IsFalse(panel.emptyMinigames.gameObject.activeSelf);
|
||||
Assert.IsFalse(panel.emptyHighscore.gameObject.activeSelf);
|
||||
Assert.IsTrue(panel.progressGraph.gameObject.activeSelf);
|
||||
|
||||
var minigame = panel.minigameList.GetMinigameByIndex(MinigameIndex.HANGMAN);
|
||||
Assert.AreEqual(minigame.title, panel.minigameTitle.text);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether the panel is correctly initialized when there is no minigame progress
|
||||
/// </summary>
|
||||
[UnityTest]
|
||||
public IEnumerator Test_Start_Empty()
|
||||
{
|
||||
yield return Setup_PanelMinigameProgress_Empty();
|
||||
|
||||
var panel = GameObject.FindObjectOfType<PanelMinigameProgress>();
|
||||
Assert.IsFalse(panel.minigameInfo.gameObject.activeSelf);
|
||||
Assert.IsTrue(panel.emptyMinigames.gameObject.activeSelf);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether the panel is correctly initialized when there are minigames, but these don't have any score
|
||||
/// </summary>
|
||||
[UnityTest]
|
||||
public IEnumerator Test_Start_NoScorePresent()
|
||||
{
|
||||
yield return Setup_PanelMinigameProgress_NoScorePresent();
|
||||
|
||||
var panel = GameObject.FindObjectOfType<PanelMinigameProgress>();
|
||||
Assert.IsTrue(panel.minigameInfo.gameObject.activeSelf);
|
||||
Assert.IsFalse(panel.emptyMinigames.gameObject.activeSelf);
|
||||
Assert.IsTrue(panel.emptyHighscore.gameObject.activeSelf);
|
||||
Assert.IsFalse(panel.progressGraph.gameObject.activeSelf);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether we can select a minigame
|
||||
/// </summary>
|
||||
[UnityTest]
|
||||
public IEnumerator Test_UpdateSelection()
|
||||
{
|
||||
yield return Setup_PanelMinigameProgress_Multiple();
|
||||
|
||||
var panel = GameObject.FindObjectOfType<PanelMinigameProgress>();
|
||||
var minigames = GameObject.FindObjectsOfType<MinigameProgressCard>();
|
||||
|
||||
var currentMinigame = minigames[0];
|
||||
currentMinigame.selectActivity.Invoke();
|
||||
yield return new WaitForSeconds(WAIT_TIME);
|
||||
|
||||
Assert.AreEqual(new Color(66 / 255f, 158 / 255f, 189 / 255f, 1f), currentMinigame.GetComponent<Image>().color);
|
||||
for (int i = 1; i < minigames.Length; i++)
|
||||
Assert.AreEqual(new Color(159 / 255f, 231 / 255f, 245 / 255f, 120 / 255f), minigames[i].GetComponent<Image>().color);
|
||||
|
||||
Assert.AreEqual(currentMinigame.title.text, panel.minigameTitle.text);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f046d113e8709db438b49af46e271111
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
152
Assets/Accounts/Tests/PlayMode/ProgressGraphTests.cs
Normal file
152
Assets/Accounts/Tests/PlayMode/ProgressGraphTests.cs
Normal file
@@ -0,0 +1,152 @@
|
||||
using NUnit.Framework;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
|
||||
/// <summary>
|
||||
/// Test the ProgressGraph class
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
public class ProgressGraphTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Wait time between scene transitions
|
||||
/// </summary>
|
||||
private const float WAIT_TIME = 0.2f;
|
||||
|
||||
/// <summary>
|
||||
/// Setup the ProgressGraph tests
|
||||
/// </summary>
|
||||
private IEnumerator Setup_ProgressGraph(int amount, Func<int, int> f)
|
||||
{
|
||||
string path = $"{Application.persistentDataPath}/wesign_unit_test.json";
|
||||
string score = "";
|
||||
for (int i = 0; i < amount; i++)
|
||||
{
|
||||
score += $"{{\"scoreValue\":{f(i)},\"time\":\"19/04/2023 22:32:39\"}}";
|
||||
if (i < amount - 1)
|
||||
score += ",";
|
||||
}
|
||||
|
||||
string minigame = $"{{\"entries\":[],\"minigameIndex\":1,\"latestScores\":[{score}],\"highestScores\":[{score}]}}";
|
||||
string oneUser = $"{{\"version\":1537,\"users\":[{{\"entries\":[],\"username\":\"Tester0\",\"avatarIndex\":0,\"playtime\":0.0,\"minigames\":[{minigame}],\"courses\":[]}}],\"currentUser\":0,\"currentMinigame\":0,\"currentCourse\":0,\"currentTheme\":0,\"useGPU\":false}}";
|
||||
|
||||
File.WriteAllText(path, oneUser);
|
||||
PersistentDataController.PATH = path;
|
||||
PersistentDataController.GetInstance().Load();
|
||||
AssetDatabase.LoadAssetAtPath<UserAvatarList>("Assets/Accounts/ScriptableObjects/UserAvatarList.asset").Awake();
|
||||
|
||||
SystemController.GetInstance().SwapScene("Accounts/Scenes/UserProgressScreen");
|
||||
yield return new WaitForSeconds(WAIT_TIME);
|
||||
|
||||
GameObject.FindObjectOfType<UserProgressScreen>().DisplayMinigames();
|
||||
yield return new WaitForSeconds(WAIT_TIME);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Test whether every item that needs to be assign in the editor, is assigned
|
||||
/// </summary>
|
||||
[UnityTest]
|
||||
public IEnumerator Test_EditorAssignments()
|
||||
{
|
||||
yield return Setup_ProgressGraph(1, (i) => i);
|
||||
|
||||
var graph = GameObject.FindObjectOfType<ProgressGraph>();
|
||||
Assert.IsNotNull(graph);
|
||||
Assert.IsNotNull(graph.progressGraph);
|
||||
Assert.IsNotNull(graph.highscoreMarker);
|
||||
Assert.IsNotNull(graph.axesTickMarker);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether negative values are correctly plotted
|
||||
/// </summary>
|
||||
[UnityTest]
|
||||
public IEnumerator Test_PlotGraph_Negative()
|
||||
{
|
||||
yield return Setup_ProgressGraph(4, (i) => -5 * (i + 1));
|
||||
yield return new WaitForSeconds(5.0f);
|
||||
Assert.IsTrue(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether values between 0 and 1 are correctly plotted
|
||||
/// </summary>
|
||||
[UnityTest]
|
||||
public IEnumerator Test_PlotGraph_SmallerThen1()
|
||||
{
|
||||
yield return Setup_ProgressGraph(4, (i) => (3 * i + 20) / 100);
|
||||
yield return new WaitForSeconds(5.0f);
|
||||
Assert.IsTrue(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether values around 0 are correctly plotted
|
||||
/// </summary>
|
||||
[UnityTest]
|
||||
public IEnumerator Test_PlotGraph_AroundZero()
|
||||
{
|
||||
yield return Setup_ProgressGraph(4, (i) => 5 * i - 10);
|
||||
yield return new WaitForSeconds(5.0f);
|
||||
Assert.IsTrue(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether all 0 values are correctly plotted
|
||||
/// </summary>
|
||||
[UnityTest]
|
||||
public IEnumerator Test_PlotGraph_AllZeros()
|
||||
{
|
||||
yield return Setup_ProgressGraph(4, (i) => 0);
|
||||
yield return new WaitForSeconds(5.0f);
|
||||
Assert.IsTrue(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether values between -1 and 1 are correctly plotted
|
||||
/// </summary>
|
||||
[UnityTest]
|
||||
public IEnumerator Test_PlotGraph_BetweenPos1AndNeg1()
|
||||
{
|
||||
yield return Setup_ProgressGraph(10, (i) => (i % 3) - 1);
|
||||
yield return new WaitForSeconds(5.0f);
|
||||
Assert.IsTrue(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether a single value is correctly plotted
|
||||
/// </summary>
|
||||
[UnityTest]
|
||||
public IEnumerator Test_PlotGraph_Single()
|
||||
{
|
||||
yield return Setup_ProgressGraph(1, (i) => i + 500);
|
||||
yield return new WaitForSeconds(5.0f);
|
||||
Assert.IsTrue(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether multiple values are correctly plotted
|
||||
/// </summary>
|
||||
[UnityTest]
|
||||
public IEnumerator Test_PlotGraph_Multiple()
|
||||
{
|
||||
yield return Setup_ProgressGraph(5, (i) => 5 * i);
|
||||
yield return new WaitForSeconds(5.0f);
|
||||
Assert.IsTrue(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether too many values (capped at 10) are correctly plotted
|
||||
/// </summary>
|
||||
[UnityTest]
|
||||
public IEnumerator Test_PlotGraph_TooMany()
|
||||
{
|
||||
yield return Setup_ProgressGraph(10, (i) => 5 * i);
|
||||
yield return new WaitForSeconds(5.0f);
|
||||
Assert.IsTrue(true);
|
||||
}
|
||||
}
|
||||
11
Assets/Accounts/Tests/PlayMode/ProgressGraphTests.cs.meta
Normal file
11
Assets/Accounts/Tests/PlayMode/ProgressGraphTests.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: be53c4208fff73845b85978e1ecae7d4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
71
Assets/Accounts/Tests/PlayMode/UserCardTests.cs
Normal file
71
Assets/Accounts/Tests/PlayMode/UserCardTests.cs
Normal file
@@ -0,0 +1,71 @@
|
||||
using NUnit.Framework;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
|
||||
/// <summary>
|
||||
/// Test the UserCard class
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
public class UserCardTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Wait time between scene transitions
|
||||
/// </summary>
|
||||
private const float WAIT_TIME = 0.2f;
|
||||
|
||||
/// <summary>
|
||||
/// Setup the tests
|
||||
/// </summary>
|
||||
[UnitySetUp]
|
||||
public IEnumerator Setup_UserCard()
|
||||
{
|
||||
string path = $"{Application.persistentDataPath}/wesign_unit_test.json";
|
||||
string oneUser = "{\"version\":1537,\"users\":[{\"entries\":[],\"username\":\"Tester0\",\"avatarIndex\":0,\"playtime\":0.0,\"minigames\":[],\"courses\":[]}],\"currentUser\":0,\"currentMinigame\":0,\"currentCourse\":0,\"currentTheme\":0,\"useGPU\":false}";
|
||||
|
||||
File.WriteAllText(path, oneUser);
|
||||
PersistentDataController.PATH = path;
|
||||
PersistentDataController.GetInstance().Load();
|
||||
AssetDatabase.LoadAssetAtPath<UserAvatarList>("Assets/Accounts/ScriptableObjects/UserAvatarList.asset").Awake();
|
||||
|
||||
SystemController.GetInstance().SwapScene("Accounts/Scenes/ChangeUserScreen");
|
||||
yield return new WaitForSeconds(WAIT_TIME);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cleanup after testing
|
||||
/// </summary>
|
||||
[TearDown]
|
||||
public void TearDown_UserCard()
|
||||
{
|
||||
PersistentDataController.PATH = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether every item that needs to be assign in the editor, is assigned
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Test_EditorAssignments()
|
||||
{
|
||||
var card = GameObject.FindObjectOfType<UserCard>();
|
||||
Assert.IsNotNull(card);
|
||||
Assert.IsNotNull(card.user);
|
||||
Assert.IsNotNull(card.button);
|
||||
Assert.IsNotNull(card.avatar);
|
||||
Assert.IsNotNull(card.username);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether the card is correctly initialized
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Test_Start()
|
||||
{
|
||||
var card = GameObject.FindObjectOfType<UserCard>();
|
||||
Assert.AreEqual(card.user.GetAvatar(), card.avatar.sprite);
|
||||
Assert.AreEqual(card.user.GetUsername(), card.username.text);
|
||||
}
|
||||
}
|
||||
|
||||
11
Assets/Accounts/Tests/PlayMode/UserCardTests.cs.meta
Normal file
11
Assets/Accounts/Tests/PlayMode/UserCardTests.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3a9cd2a546e38bc4ba1ba66f5f9c8f71
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
173
Assets/Accounts/Tests/PlayMode/UserCreationScreenTests.cs
Normal file
173
Assets/Accounts/Tests/PlayMode/UserCreationScreenTests.cs
Normal file
@@ -0,0 +1,173 @@
|
||||
using NUnit.Framework;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using TMPro;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
using UnityEngine.UI;
|
||||
|
||||
/// <summary>
|
||||
/// Test the UserCreationScreen class
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
public class UserCreationScreenTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Wait time between scene transitions
|
||||
/// </summary>
|
||||
private const float WAIT_TIME = 0.2f;
|
||||
|
||||
/// <summary>
|
||||
/// Setup the UserCreationScreen tests
|
||||
/// </summary>
|
||||
private IEnumerator Setup_UserCreationScreen(string startScreen = "Accounts/Scenes/UserCreationScreen")
|
||||
{
|
||||
string path = $"{Application.persistentDataPath}/wesign_unit_test.json";
|
||||
string oneUser = "{\"version\":1537,\"users\":[{\"entries\":[],\"username\":\"Tester0\",\"avatarIndex\":0,\"playtime\":0.0,\"minigames\":[],\"courses\":[]}],\"currentUser\":0,\"currentMinigame\":0,\"currentCourse\":0,\"currentTheme\":0,\"useGPU\":false}";
|
||||
|
||||
File.WriteAllText(path, oneUser);
|
||||
PersistentDataController.PATH = path;
|
||||
PersistentDataController.GetInstance().Load();
|
||||
AssetDatabase.LoadAssetAtPath<UserAvatarList>("Assets/Accounts/ScriptableObjects/UserAvatarList.asset").Awake();
|
||||
|
||||
SystemController.GetInstance().SwapScene(startScreen);
|
||||
yield return new WaitForSeconds(WAIT_TIME);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cleanup after testing
|
||||
/// </summary>
|
||||
[TearDown]
|
||||
public void TearDown_UserCreationScreen()
|
||||
{
|
||||
PersistentDataController.PATH = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether every item that needs to be assign in the editor, is assigned
|
||||
/// </summary>
|
||||
[UnityTest]
|
||||
public IEnumerator Test_EditorAssignments()
|
||||
{
|
||||
yield return Setup_UserCreationScreen();
|
||||
|
||||
var userCreationController = GameObject.FindObjectOfType<UserCreationScreen>();
|
||||
Assert.IsNotNull(userCreationController);
|
||||
Assert.IsNotNull(userCreationController.errorMessage);
|
||||
Assert.IsNotNull(userCreationController.inputName);
|
||||
Assert.IsNotNull(userCreationController.avatarsContainer);
|
||||
Assert.IsNotNull(userCreationController.avatarPrefab);
|
||||
Assert.IsNotNull(userCreationController.backButton);
|
||||
Assert.IsTrue(UserCreationScreen.canGoBack);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether the screen is correctly initialized
|
||||
/// </summary>
|
||||
[UnityTest]
|
||||
public IEnumerator Test_Start()
|
||||
{
|
||||
yield return Setup_UserCreationScreen();
|
||||
|
||||
var userCreationController = GameObject.FindObjectOfType<UserCreationScreen>();
|
||||
Assert.IsFalse(userCreationController.errorMessage.activeSelf);
|
||||
Assert.IsTrue(userCreationController.backButton.activeSelf);
|
||||
|
||||
var avatars = userCreationController.avatarsContainer.GetComponentsInChildren<Button>().ToList()
|
||||
.ConvertAll((b) => b.GetComponentsInChildren<Image>().Except(b.GetComponents<Image>()).First());
|
||||
|
||||
Assert.AreEqual(UserList.AVATARS.Count, avatars.Count);
|
||||
for (int i = 0; i < avatars.Count; i++)
|
||||
Assert.AreEqual(UserList.AVATARS[i], avatars[i].sprite);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether the screen is correctly initialized (from invalid savefile)
|
||||
/// </summary>
|
||||
[UnityTest]
|
||||
public IEnumerator Test_Start_InvalidSavefile()
|
||||
{
|
||||
string path = $"{Application.persistentDataPath}/wesign_unit_test.json";
|
||||
File.Delete(path);
|
||||
PersistentDataController.PATH = path;
|
||||
PersistentDataController.GetInstance().Load();
|
||||
AssetDatabase.LoadAssetAtPath<UserAvatarList>("Assets/Accounts/ScriptableObjects/UserAvatarList.asset").Awake();
|
||||
|
||||
SystemController.GetInstance().SwapScene("Common/Scenes/Boot");
|
||||
yield return new WaitForSeconds(WAIT_TIME);
|
||||
|
||||
var userCreationController = GameObject.FindObjectOfType<UserCreationScreen>();
|
||||
Assert.IsNotNull(userCreationController);
|
||||
Assert.IsFalse(userCreationController.backButton.activeSelf);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether a new user can be created
|
||||
/// </summary>
|
||||
[UnityTest]
|
||||
public IEnumerator Test_CreateUser_Valid()
|
||||
{
|
||||
yield return Setup_UserCreationScreen("Common/Scenes/MainMenuScreen");
|
||||
|
||||
SystemController.GetInstance().LoadNextScene("Accounts/Scenes/UserCreationScreen");
|
||||
yield return new WaitForSeconds(WAIT_TIME);
|
||||
|
||||
var userCreationController = GameObject.FindObjectOfType<UserCreationScreen>();
|
||||
userCreationController.inputName.text = "newTester";
|
||||
userCreationController.CreateUser();
|
||||
Assert.IsFalse(userCreationController.errorMessage.activeSelf);
|
||||
yield return new WaitForSeconds(WAIT_TIME);
|
||||
|
||||
Assert.AreEqual(SystemController.GetSceneIndex("Common/Scenes/MainMenuScreen"), SystemController.GetInstance().currentScene);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether no new user is created when the username is too long
|
||||
/// </summary>
|
||||
[UnityTest]
|
||||
public IEnumerator Test_CreateUser_UsernameTooLong()
|
||||
{
|
||||
yield return Setup_UserCreationScreen();
|
||||
|
||||
var userCreationController = GameObject.FindObjectOfType<UserCreationScreen>();
|
||||
userCreationController.inputName.text = "aninvalidsuperduperlongusername";
|
||||
userCreationController.CreateUser();
|
||||
Assert.IsTrue(userCreationController.errorMessage.activeSelf);
|
||||
Assert.AreEqual("Je gebruikersnaam moet bestaan uit minimum 1 en maximum 12 letters (a-z en A-Z) of cijfers (0-9).", userCreationController.errorMessage.GetComponent<TMP_Text>().text);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Test whether no new user is created when the username contains invalid characters
|
||||
/// </summary>
|
||||
[UnityTest]
|
||||
public IEnumerator Test_CreateUser_UsernameInvalidChars()
|
||||
{
|
||||
yield return Setup_UserCreationScreen();
|
||||
|
||||
var userCreationController = GameObject.FindObjectOfType<UserCreationScreen>();
|
||||
userCreationController.inputName.text = "! an invalid username !";
|
||||
userCreationController.CreateUser();
|
||||
Assert.IsTrue(userCreationController.errorMessage.activeSelf);
|
||||
Assert.AreEqual("Je gebruikersnaam moet bestaan uit minimum 1 en maximum 12 letters (a-z en A-Z) of cijfers (0-9).", userCreationController.errorMessage.GetComponent<TMP_Text>().text);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Test whether no new user is created when the username already exists
|
||||
/// </summary>
|
||||
[UnityTest]
|
||||
public IEnumerator Test_CreateUser_UsernameAlreadyExists()
|
||||
{
|
||||
yield return Setup_UserCreationScreen();
|
||||
|
||||
var userCreationController = GameObject.FindObjectOfType<UserCreationScreen>();
|
||||
userCreationController.inputName.text = "Tester0";
|
||||
userCreationController.CreateUser();
|
||||
Assert.IsTrue(userCreationController.errorMessage.activeSelf);
|
||||
Assert.AreEqual("Deze gebruikersnaam bestaat al! Kies een andere.", userCreationController.errorMessage.GetComponent<TMP_Text>().text);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2f151a9a85fa2ce41953b3ad00ebb167
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
138
Assets/Accounts/Tests/PlayMode/UserProgressScreenTests.cs
Normal file
138
Assets/Accounts/Tests/PlayMode/UserProgressScreenTests.cs
Normal file
@@ -0,0 +1,138 @@
|
||||
using NUnit.Framework;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
|
||||
/// <summary>
|
||||
/// Test the UserProgressScreen class
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
public class UserProgressScreenTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Wait time between scene transitions
|
||||
/// </summary>
|
||||
private const float WAIT_TIME = 0.2f;
|
||||
|
||||
/// <summary>
|
||||
/// Setup the UserProgressScreen tests
|
||||
/// </summary>
|
||||
private IEnumerator Setup_UserProgressScreen(bool progress = true)
|
||||
{
|
||||
string path = $"{Application.persistentDataPath}/wesign_unit_test.json";
|
||||
string course = "{\"entries\":[],\"courseIndex\":0,\"progress\":0.03846153989434242,\"completedLearnables\":1,\"inUseLearnables\":7,\"totalLearnables\":26,\"learnables\":[{\"entries\":[],\"index\":0,\"inUse\":true,\"name\":\"A\",\"progress\":3.0},{\"entries\":[],\"index\":1,\"inUse\":true,\"name\":\"B\",\"progress\":4.5},{\"entries\":[],\"index\":2,\"inUse\":true,\"name\":\"C\",\"progress\":1.5},{\"entries\":[],\"index\":3,\"inUse\":true,\"name\":\"D\",\"progress\":1.5},{\"entries\":[],\"index\":4,\"inUse\":true,\"name\":\"E\",\"progress\":1.5},{\"entries\":[],\"index\":5,\"inUse\":true,\"name\":\"F\",\"progress\":1.5},{\"entries\":[],\"index\":6,\"inUse\":true,\"name\":\"G\",\"progress\":0.0},{\"entries\":[],\"index\":7,\"inUse\":false,\"name\":\"H\",\"progress\":0.0},{\"entries\":[],\"index\":8,\"inUse\":false,\"name\":\"I\",\"progress\":0.0},{\"entries\":[],\"index\":9,\"inUse\":false,\"name\":\"J\",\"progress\":0.0},{\"entries\":[],\"index\":10,\"inUse\":false,\"name\":\"K\",\"progress\":0.0},{\"entries\":[],\"index\":11,\"inUse\":false,\"name\":\"L\",\"progress\":0.0},{\"entries\":[],\"index\":12,\"inUse\":false,\"name\":\"M\",\"progress\":0.0},{\"entries\":[],\"index\":13,\"inUse\":false,\"name\":\"N\",\"progress\":0.0},{\"entries\":[],\"index\":14,\"inUse\":false,\"name\":\"O\",\"progress\":0.0},{\"entries\":[],\"index\":15,\"inUse\":false,\"name\":\"P\",\"progress\":0.0},{\"entries\":[],\"index\":16,\"inUse\":false,\"name\":\"Q\",\"progress\":0.0},{\"entries\":[],\"index\":17,\"inUse\":false,\"name\":\"R\",\"progress\":0.0},{\"entries\":[],\"index\":18,\"inUse\":false,\"name\":\"S\",\"progress\":0.0},{\"entries\":[],\"index\":19,\"inUse\":false,\"name\":\"T\",\"progress\":0.0},{\"entries\":[],\"index\":20,\"inUse\":false,\"name\":\"U\",\"progress\":0.0},{\"entries\":[],\"index\":21,\"inUse\":false,\"name\":\"V\",\"progress\":0.0},{\"entries\":[],\"index\":22,\"inUse\":false,\"name\":\"W\",\"progress\":0.0},{\"entries\":[],\"index\":23,\"inUse\":false,\"name\":\"X\",\"progress\":0.0},{\"entries\":[],\"index\":24,\"inUse\":false,\"name\":\"Y\",\"progress\":0.0},{\"entries\":[],\"index\":25,\"inUse\":false,\"name\":\"Z\",\"progress\":0.0}]}";
|
||||
string minigame = "{\"entries\":[],\"minigameIndex\":1,\"latestScores\":[{\"scoreValue\":70,\"time\":\"19/04/2023 22:32:39\"},{\"scoreValue\":55,\"time\":\"20/04/2023 11:50:10\"},{\"scoreValue\":55,\"time\":\"20/04/2023 13:27:15\"}],\"highestScores\":[{\"scoreValue\":70,\"time\":\"19/04/2023 22:32:39\"},{\"scoreValue\":55,\"time\":\"20/04/2023 11:50:10\"},{\"scoreValue\":55,\"time\":\"20/04/2023 13:27:15\"}]}";
|
||||
if (!progress) course = minigame = "";
|
||||
string oneUser = $"{{\"version\":1537,\"users\":[{{\"entries\":[],\"username\":\"Tester0\",\"avatarIndex\":0,\"playtime\":0.0,\"minigames\":[{minigame}],\"courses\":[{course}]}}],\"currentUser\":0,\"currentMinigame\":0,\"currentCourse\":0,\"currentTheme\":0,\"useGPU\":false}}";
|
||||
|
||||
File.WriteAllText(path, oneUser);
|
||||
PersistentDataController.PATH = path;
|
||||
PersistentDataController.GetInstance().Load();
|
||||
AssetDatabase.LoadAssetAtPath<UserAvatarList>("Assets/Accounts/ScriptableObjects/UserAvatarList.asset").Awake();
|
||||
|
||||
SystemController.GetInstance().SwapScene("Accounts/Scenes/UserProgressScreen");
|
||||
yield return new WaitForSeconds(WAIT_TIME);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cleanup after testing
|
||||
/// </summary>
|
||||
[TearDown]
|
||||
public void TearDown_UserProgressScreen()
|
||||
{
|
||||
PersistentDataController.PATH = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether every item that needs to be assign in the editor, is assigned
|
||||
/// </summary>
|
||||
[UnityTest]
|
||||
public IEnumerator Test_EditorAssignments()
|
||||
{
|
||||
yield return Setup_UserProgressScreen();
|
||||
|
||||
var userProgressController = GameObject.FindObjectOfType<UserProgressScreen>();
|
||||
Assert.IsNotNull(userProgressController.username);
|
||||
Assert.IsNotNull(userProgressController.avatar);
|
||||
Assert.IsNotNull(userProgressController.coursesPanel);
|
||||
Assert.IsNotNull(userProgressController.coursesTabButton);
|
||||
Assert.IsNotNull(userProgressController.minigamesPanel);
|
||||
Assert.IsNotNull(userProgressController.minigamesTabButton);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether the screen is correctly initialized
|
||||
/// </summary>
|
||||
[UnityTest]
|
||||
public IEnumerator Test_Start_NoProgress()
|
||||
{
|
||||
yield return Setup_UserProgressScreen(false);
|
||||
|
||||
var userProgressController = GameObject.FindObjectOfType<UserProgressScreen>();
|
||||
var user = UserList.GetCurrentUser();
|
||||
|
||||
Assert.AreEqual(user.GetUsername(), userProgressController.username.text);
|
||||
Assert.AreEqual(user.GetAvatar(), userProgressController.avatar.sprite);
|
||||
|
||||
Assert.IsTrue(userProgressController.coursesPanel.activeSelf);
|
||||
Assert.Zero(GameObject.FindObjectsOfType<CourseProgressCard>().Length);
|
||||
Assert.IsFalse(userProgressController.minigamesPanel.activeSelf);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether the screen is correctly initialized
|
||||
/// </summary>
|
||||
[UnityTest]
|
||||
public IEnumerator Test_Start_WithProgress()
|
||||
{
|
||||
yield return Setup_UserProgressScreen();
|
||||
|
||||
var userProgressController = GameObject.FindObjectOfType<UserProgressScreen>();
|
||||
var user = UserList.GetCurrentUser();
|
||||
|
||||
Assert.AreEqual(user.GetUsername(), userProgressController.username.text);
|
||||
Assert.AreEqual(user.GetAvatar(), userProgressController.avatar.sprite);
|
||||
|
||||
Assert.IsTrue(userProgressController.coursesPanel.activeSelf);
|
||||
var courses = GameObject.FindObjectsOfType<CourseProgressCard>().ToList();
|
||||
Assert.AreEqual(user.GetCourses().Count, courses.Count);
|
||||
Assert.IsFalse(userProgressController.minigamesPanel.activeSelf);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether the course panel is displayed
|
||||
/// </summary>
|
||||
[UnityTest]
|
||||
public IEnumerator Test_DisplayCourses()
|
||||
{
|
||||
yield return Setup_UserProgressScreen();
|
||||
|
||||
var userProgressController = GameObject.FindObjectOfType<UserProgressScreen>();
|
||||
userProgressController.DisplayCourses();
|
||||
yield return new WaitForSeconds(WAIT_TIME);
|
||||
|
||||
Assert.IsTrue(userProgressController.coursesPanel.activeSelf);
|
||||
Assert.IsFalse(userProgressController.minigamesPanel.activeSelf);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether the minigames panel is displayed
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[UnityTest]
|
||||
public IEnumerator Test_DisplayMinigames()
|
||||
{
|
||||
yield return Setup_UserProgressScreen();
|
||||
|
||||
var userProgressController = GameObject.FindObjectOfType<UserProgressScreen>();
|
||||
userProgressController.DisplayMinigames();
|
||||
yield return new WaitForSeconds(WAIT_TIME);
|
||||
|
||||
Assert.IsFalse(userProgressController.coursesPanel.activeSelf);
|
||||
Assert.IsTrue(userProgressController.minigamesPanel.activeSelf);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2f185e2e48bd67e4587fd36aeb2638fd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,233 +0,0 @@
|
||||
using NUnit.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.Serialization;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// Test the Progress class
|
||||
/// </summary>
|
||||
public class TestProgress
|
||||
{
|
||||
/// <summary>
|
||||
/// A dummy serializable struct to perform test operations on
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
private struct SerializableStruct
|
||||
{
|
||||
public int r, g, b;
|
||||
public float x, y, z;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A dummy non-serializable struct to perform test operations on
|
||||
/// </summary>
|
||||
private struct NonSerializableStruct
|
||||
{
|
||||
public int r, g, b;
|
||||
public float x, y, z;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method
|
||||
/// </summary>
|
||||
/// <returns><c>true</c> if <c>Progress.AddOrUpdate(...)</c> throws a <c>SerializationException</c></returns>
|
||||
private bool AddNonSerializableStruct()
|
||||
{
|
||||
Progress progress = new Progress();
|
||||
NonSerializableStruct nss = new NonSerializableStruct();
|
||||
try { progress.AddOrUpdate<NonSerializableStruct>("key", nss); }
|
||||
catch (SerializationException) { return true; }
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method
|
||||
/// </summary>
|
||||
/// <returns><c>true</c> if <c>Progress.Get(...)</c> throws a <c>KeyNotFoundException</c></returns>
|
||||
private bool AccessInvalidKey()
|
||||
{
|
||||
Progress progress = new Progress();
|
||||
try { progress.Get<int>("non-existing key"); }
|
||||
catch (KeyNotFoundException) { return true; }
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method
|
||||
/// </summary>
|
||||
/// <returns><c>true</c> if <c>Progress.Get(...)</c> throws a <c>InvalidCastException</c></returns>
|
||||
private bool AccessInvalidType()
|
||||
{
|
||||
Progress progress = new Progress();
|
||||
progress.AddOrUpdate<int>("key", 123456789);
|
||||
try { progress.Get<double>("key"); }
|
||||
catch (InvalidCastException) { return true; }
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test for creation of a new progress
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestNewProgress()
|
||||
{
|
||||
Progress progress = new Progress();
|
||||
Debug.Assert(progress != null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether invalid data will not be added
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestProgressAddInvalidData()
|
||||
{
|
||||
Progress progress = new Progress();
|
||||
Debug.Assert(!progress.AddOrUpdate<GameObject>("key", null));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether a duplicated key will be added
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestProgressAddDuplicateKey()
|
||||
{
|
||||
Progress progress = new Progress();
|
||||
progress.AddOrUpdate<int>("key 1", 0);
|
||||
Debug.Assert(progress.AddOrUpdate<int>("key 1", 1));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether a <c>int</c> value can be added
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestProgressAddInt()
|
||||
{
|
||||
Progress progress = new Progress();
|
||||
Debug.Assert(progress.AddOrUpdate<int>("key", 1));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether a <c>double</c> value can be added
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestProgressAddDouble()
|
||||
{
|
||||
Progress progress = new Progress();
|
||||
Debug.Assert(progress.AddOrUpdate<double>("key", 1.0));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether a <c>string</c> value can be added
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestProgressAddString()
|
||||
{
|
||||
Progress progress = new Progress();
|
||||
Debug.Assert(progress.AddOrUpdate<string>("key", "Hello World!"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether a serializable struct can be added
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestProgressAddSerializableStruct()
|
||||
{
|
||||
Progress progress = new Progress();
|
||||
Debug.Assert(progress.AddOrUpdate<SerializableStruct>("key", new SerializableStruct()));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether a non-serializable struct will throw an error
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestProgressAddNonSerializableStruct()
|
||||
{
|
||||
Debug.Assert(AddNonSerializableStruct());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether an invalid key will throw an error
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestProgressGetInvalidKey()
|
||||
{
|
||||
Debug.Assert(AccessInvalidKey());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether an invalid type will throw an error
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestProgressGetInvalidType()
|
||||
{
|
||||
Debug.Assert(AccessInvalidType());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether a value is correctly updated
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestProgressUpdate()
|
||||
{
|
||||
Progress progress = new Progress();
|
||||
progress.AddOrUpdate<int>("key", 1);
|
||||
Debug.Assert(progress.Get<int>("key") == 1);
|
||||
progress.AddOrUpdate<int>("key", 2);
|
||||
Debug.Assert(progress.Get<int>("key") == 2);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether a <c>int</c> value can be read
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestProgressGetInt()
|
||||
{
|
||||
Progress progress = new Progress();
|
||||
progress.AddOrUpdate<int>("key", 1);
|
||||
Debug.Assert(progress.Get<int>("key") == 1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether a <c>double</c> value can be read
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestProgressGetDouble()
|
||||
{
|
||||
Progress progress = new Progress();
|
||||
progress.AddOrUpdate<double>("key", 1.0);
|
||||
Debug.Assert(progress.Get<double>("key") == 1.0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether a <c>string</c> value can be read
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestProgressGetString()
|
||||
{
|
||||
Progress progress = new Progress();
|
||||
progress.AddOrUpdate<string>("key", "Hello World!");
|
||||
Debug.Assert(progress.Get<string>("key") == "Hello World!");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether a serializable struct can be read
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestProgressGetStruct()
|
||||
{
|
||||
Progress progress = new Progress();
|
||||
|
||||
int R = 1, G = 10, B = 100;
|
||||
float X = 0.1f, Y = 0.01f, Z = 0.001f;
|
||||
SerializableStruct data = new SerializableStruct { r = R, g = G, b = B, x = X, y = Y, z = Z };
|
||||
progress.AddOrUpdate<SerializableStruct>("key", data);
|
||||
SerializableStruct result = progress.Get<SerializableStruct>("key");
|
||||
Debug.Assert(result.r == R);
|
||||
Debug.Assert(result.g == G);
|
||||
Debug.Assert(result.b == B);
|
||||
Debug.Assert(result.x == X);
|
||||
Debug.Assert(result.y == Y);
|
||||
Debug.Assert(result.z == Z);
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 30234b937b9c84460ad4846ae1941484
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,30 +0,0 @@
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// Test the UserCreationScreen class
|
||||
/// </summary>
|
||||
public class TestUserCreationScreen
|
||||
{
|
||||
/// <summary>
|
||||
/// Tets IsValidUsername will return <c>true</c> for an valid username
|
||||
/// </summary>
|
||||
public void TestIsValidUsernameTrue()
|
||||
{
|
||||
foreach (char c in "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
|
||||
Debug.Assert(UserCreationScreen.IsValidUsername(c.ToString()));
|
||||
|
||||
Debug.Assert(UserCreationScreen.IsValidUsername("123456789AbC"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tets IsValidUsername will return <c>false</c> for an invalid username
|
||||
/// </summary>
|
||||
public void TestIsValidUsernameFalse()
|
||||
{
|
||||
Debug.Assert(!UserCreationScreen.IsValidUsername(string.Empty));
|
||||
foreach (char c in " \n\t+-*/%_.,;:!?(){}[]\\'\"|&~^$")
|
||||
Debug.Assert(!UserCreationScreen.IsValidUsername(c.ToString()));
|
||||
|
||||
Debug.Assert(!UserCreationScreen.IsValidUsername("123456789_10_11_12_13"));
|
||||
}
|
||||
}
|
||||
@@ -1,150 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// Test the User class
|
||||
/// </summary>
|
||||
public class TestUser
|
||||
{
|
||||
/// <summary>
|
||||
/// Test for the creation of a new user
|
||||
/// </summary>
|
||||
public void TestNewUser()
|
||||
{
|
||||
User user = new User();
|
||||
Debug.Assert(user != null);
|
||||
Debug.Assert(user.courses.Count == 0);
|
||||
Debug.Assert(user.minigames.Count == 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether progress on a new course can be added
|
||||
/// </summary>
|
||||
public void TestUserAddCourse()
|
||||
{
|
||||
User user = new User();
|
||||
Progress p = new Progress();
|
||||
user.courses.Add(p);
|
||||
Debug.Assert(user.courses.Count == 1);
|
||||
Debug.Assert(user.minigames.Count == 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether progress on a new minigame can be added
|
||||
/// </summary>
|
||||
public void TestUserAddMinigame()
|
||||
{
|
||||
User user = new User();
|
||||
Progress p = new Progress();
|
||||
user.minigames.Add(p);
|
||||
Debug.Assert(user.courses.Count == 0);
|
||||
Debug.Assert(user.minigames.Count == 1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test GetRecentCourses will return empty when no progress is stored
|
||||
/// </summary>
|
||||
public void TestGetRecentCoursesEmpty()
|
||||
{
|
||||
User user = new User();
|
||||
Debug.Assert(user.GetRecentCourses().Count == 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Temporary test for GetRecentCourses will return all progress that is stored
|
||||
/// </summary>
|
||||
public void TestGetRecentCoursesAll()
|
||||
{
|
||||
User user = new User();
|
||||
Progress p = new Progress();
|
||||
p.AddOrUpdate<CourseIndex>("courseIndex", CourseIndex.FINGERSPELLING);
|
||||
p.AddOrUpdate<float>("courseProgress", 0.5f);
|
||||
user.courses.Add(p);
|
||||
List<Tuple<CourseIndex, float>> list = user.GetRecentCourses();
|
||||
Debug.Assert(list.Count == 1);
|
||||
Debug.Assert(list[0].Item1 == CourseIndex.FINGERSPELLING);
|
||||
Debug.Assert(list[0].Item2 == 0.5f);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test GetRecommendedCourses will return <c>Tuple<CourseIndex.FINGERSPELLING, 0.0></c> when no progress is stored
|
||||
/// </summary>
|
||||
public void TestGetRecommendedCoursesEmpty()
|
||||
{
|
||||
User user = new User();
|
||||
List<Tuple<CourseIndex, float>> list = user.GetRecommendedCourses();
|
||||
Debug.Assert(list.Count == 1);
|
||||
Debug.Assert(list[0].Item1 == CourseIndex.FINGERSPELLING);
|
||||
Debug.Assert(list[0].Item2 == 0.0f);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Temporary test for GetRecommenedCourses will return all progress that is stored
|
||||
/// </summary>
|
||||
public void TestGetRecommendedCoursesAll()
|
||||
{
|
||||
User user = new User();
|
||||
Progress p = new Progress();
|
||||
p.AddOrUpdate<CourseIndex>("courseIndex", CourseIndex.FINGERSPELLING);
|
||||
p.AddOrUpdate<float>("courseProgress", 0.5f);
|
||||
user.courses.Add(p);
|
||||
List<Tuple<CourseIndex, float>> list = user.GetRecommendedCourses();
|
||||
Debug.Assert(list.Count == 1);
|
||||
Debug.Assert(list[0].Item1 == CourseIndex.FINGERSPELLING);
|
||||
Debug.Assert(list[0].Item2 == 0.5f);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test GetCourseProgress returns null when course cannot be found
|
||||
/// </summary>
|
||||
public void TestGetCourseProgressNull()
|
||||
{
|
||||
User user = new User();
|
||||
Debug.Assert(user.GetCourseProgress(CourseIndex.FINGERSPELLING) == null);
|
||||
Debug.Assert(user.GetCourseProgress((CourseIndex)100) == null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test GetCourseProgress returns correct progress object
|
||||
/// </summary>
|
||||
public void TestGetCourseProgressValid()
|
||||
{
|
||||
User user = new User();
|
||||
Progress p = new Progress();
|
||||
p.AddOrUpdate<CourseIndex>("courseIndex", CourseIndex.FINGERSPELLING);
|
||||
p.AddOrUpdate<float>("courseProgress", 3.14159265f);
|
||||
user.courses.Add(p);
|
||||
Progress q = user.GetCourseProgress(CourseIndex.FINGERSPELLING);
|
||||
Debug.Assert(q.Get<CourseIndex>("courseIndex") == CourseIndex.FINGERSPELLING);
|
||||
Debug.Assert(q.Get<float>("courseProgress") == 3.14159265f);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test GetMinigameProgress returns null when minigame cannot be found
|
||||
/// </summary>
|
||||
public void TestGetMinigameProgressNull()
|
||||
{
|
||||
User user = new User();
|
||||
Debug.Assert(user.GetMinigameProgress(MinigameIndex.SPELLING_BEE) == null);
|
||||
Debug.Assert(user.GetMinigameProgress((MinigameIndex)100) == null);
|
||||
|
||||
Progress p = new Progress();
|
||||
p.AddOrUpdate<MinigameIndex>("minigameIndex", MinigameIndex.SPELLING_BEE);
|
||||
user.minigames.Add(p);
|
||||
Debug.Assert(user.GetMinigameProgress(MinigameIndex.HANGMAN) == null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test GetMinigameProgress returns correct progress object
|
||||
/// </summary>
|
||||
public void TestGetMinigameProgressValid()
|
||||
{
|
||||
User user = new User();
|
||||
Progress p = new Progress();
|
||||
p.AddOrUpdate<MinigameIndex>("minigameIndex", MinigameIndex.SPELLING_BEE);
|
||||
user.minigames.Add(p);
|
||||
Progress q = user.GetMinigameProgress(MinigameIndex.SPELLING_BEE);
|
||||
Debug.Assert(q.Get<CourseIndex>("minigameIndex") == CourseIndex.FINGERSPELLING);
|
||||
}
|
||||
}
|
||||
8
Assets/Architecture.meta
Normal file
8
Assets/Architecture.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 00903f60e81ce95419bc0c62a11ddfd1
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/Architecture/Scripts.meta
Normal file
8
Assets/Architecture/Scripts.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 17374f544297b194aa5517c196ca2f07
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
14
Assets/Architecture/Scripts/ArchitectureScripts.asmdef
Normal file
14
Assets/Architecture/Scripts/ArchitectureScripts.asmdef
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"name": "ArchitectureScripts",
|
||||
"rootNamespace": "",
|
||||
"references": [],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e83ddf9a537a96b4a804a16bb7872ec1
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -5,6 +5,7 @@
|
||||
public enum CourseIndex
|
||||
{
|
||||
FINGERSPELLING,
|
||||
BASIC_SIGNS,
|
||||
CLOTHING,
|
||||
ANIMALS,
|
||||
FOOD,
|
||||
674
Assets/Architecture/Scripts/PersistentDataController.cs
Normal file
674
Assets/Architecture/Scripts/PersistentDataController.cs
Normal file
@@ -0,0 +1,674 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization.Formatters.Binary;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// PersistentDataController singleton
|
||||
/// </summary>
|
||||
public class PersistentDataController
|
||||
{
|
||||
/// <summary>
|
||||
/// The instance controlling the singleton
|
||||
/// </summary>
|
||||
private static PersistentDataController instance = null;
|
||||
|
||||
/// <summary>
|
||||
/// Current implementation version of the PersistentDataController
|
||||
/// </summary>
|
||||
/// <remarks>MSB represent sprint version, LSB represent subversion</remarks>
|
||||
public const int VERSION = 0x06_01;
|
||||
|
||||
/// <summary>
|
||||
/// Path of the <c>.json</c>-file to store all serialized data
|
||||
/// </summary>
|
||||
public static string PATH = null;
|
||||
|
||||
/// <summary>
|
||||
/// Class to hold a list of data records
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class PersistentDataContainer
|
||||
{
|
||||
/// <summary>
|
||||
/// A helper class for handling the stored progress
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class PersistentDataEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// The key, used to reference the data object
|
||||
/// </summary>
|
||||
public string key;
|
||||
|
||||
/// <summary>
|
||||
/// The object, representated as a list of byte (which can be serialized)
|
||||
/// </summary>
|
||||
public List<byte> data = new List<byte>();
|
||||
|
||||
/// <summary>
|
||||
/// Create a new PersistentDataEntry
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="data"></param>
|
||||
public PersistentDataEntry(string key, byte[] data) : this(key, data.ToList())
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new PersistentDataEntry
|
||||
/// </summary>
|
||||
public PersistentDataEntry(string key, List<byte> data)
|
||||
{
|
||||
this.key = key;
|
||||
this.data = data;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// List of data records
|
||||
/// </summary>
|
||||
public List<PersistentDataEntry> entries = new List<PersistentDataEntry>();
|
||||
|
||||
/// <summary>
|
||||
/// Update the value of a certain key,
|
||||
/// or add a new value if the key was not present.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the data to be added/updated</typeparam>
|
||||
/// <param name="key">The key, used for referencing the data</param>
|
||||
/// <param name="data">The object of type <typeparamref name="T"/></param>
|
||||
/// <returns><c>true</c> if successful, <c>false</c> otherwise</returns>
|
||||
public bool Set<T>(string key, T data)
|
||||
{
|
||||
if (data == null)
|
||||
return false;
|
||||
|
||||
PersistentDataEntry 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.data.Clear();
|
||||
entry.data.AddRange(ms.ToArray());
|
||||
}
|
||||
else
|
||||
{
|
||||
entries.Add(new PersistentDataEntry(key, ms.ToArray()));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the data object of a certain key
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the data object</typeparam>
|
||||
/// <param name="key">The key referencing the data object</param>
|
||||
/// <returns>The data, cast to a type <typeparamref name="T"/></returns>
|
||||
/// <exception cref="KeyNotFoundException"></exception>
|
||||
/// <exception cref="InvalidCastException"></exception>
|
||||
public T Get<T>(string key)
|
||||
{
|
||||
BinaryFormatter bf = new BinaryFormatter();
|
||||
using (MemoryStream ms = new MemoryStream())
|
||||
{
|
||||
// Find the correct key
|
||||
foreach (PersistentDataEntry entry in entries)
|
||||
{
|
||||
if (entry.key == key)
|
||||
{
|
||||
// Hacky serialization stuff
|
||||
byte[] data = entry.data.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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove a key-value from the data.
|
||||
/// </summary>
|
||||
/// <param name="key">The key referencing the data object</param>
|
||||
/// <exception cref="KeyNotFoundException"></exception>
|
||||
public void Remove(string key)
|
||||
{
|
||||
if (!Has(key))
|
||||
throw new KeyNotFoundException();
|
||||
|
||||
entries.Remove(entries.Find(x => x.key == key));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove and return value from the data.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the data object</typeparam>
|
||||
/// <param name="key">The key referencing the data object</param>
|
||||
/// <param name="save">Whether the removal of the data should also be saved to disk</param>
|
||||
/// <returns></returns>
|
||||
public T Pop<T>(string key)
|
||||
{
|
||||
T data = Get<T>(key);
|
||||
Remove(key);
|
||||
return data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check whether a key is present
|
||||
/// </summary>
|
||||
/// <param name="key">The key to check</param>
|
||||
/// <returns>true if a item can be found with the specified key</returns>
|
||||
public bool Has(string key)
|
||||
{
|
||||
return entries.Find(x => x.key == key) != null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stored user data record
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class SavedUserData : PersistentDataContainer
|
||||
{
|
||||
/// <summary>
|
||||
/// The user's username
|
||||
/// </summary>
|
||||
public string username = null;
|
||||
|
||||
/// <summary>
|
||||
/// The index of the user's avatar in the UserList.AVATARS list
|
||||
/// </summary>
|
||||
public int avatarIndex = -1;
|
||||
|
||||
/// <summary>
|
||||
/// The total playtime of the user
|
||||
/// </summary>
|
||||
/// <remarks>Not implemented yet</remarks>
|
||||
public double playtime = 0.0;
|
||||
|
||||
/// <summary>
|
||||
/// A list of progress on minigames the user has
|
||||
/// </summary>
|
||||
public List<SavedMinigameProgress> minigames = new List<SavedMinigameProgress>();
|
||||
|
||||
/// <summary>
|
||||
/// A list of progress on courses the user has
|
||||
/// </summary>
|
||||
public List<SavedCourseProgress> courses = new List<SavedCourseProgress>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stored course progress data record
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class SavedCourseProgress : PersistentDataContainer
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Update the progress value of the SavedLearnableProgress with the given learnableName.
|
||||
/// </summary>
|
||||
/// <param name="learnableName"></param>
|
||||
/// <param name="addValue"></param>
|
||||
public void UpdateLearnable(string learnableName, float addValue)
|
||||
{
|
||||
SavedLearnableProgress learnable = learnables.Find(l => l.name == learnableName);
|
||||
if (learnable == null)
|
||||
throw new KeyNotFoundException();
|
||||
|
||||
// Update the progress value of the SavedLearnableProgress
|
||||
learnable.progress += addValue;
|
||||
// crop the learnable progress around -5 and 5
|
||||
if (learnable.progress > 5.0f)
|
||||
learnable.progress = 5.0f;
|
||||
else if (learnable.progress < -5.0f)
|
||||
learnable.progress = -5.0f;
|
||||
|
||||
// if learnable progress is big enough it is "completed"
|
||||
if (learnable.progress > 3)
|
||||
completedLearnables++;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check whether there are enough inUse Learnables
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private bool EnoughLearnables()
|
||||
{
|
||||
// There need to be more then 5 non completed learnables
|
||||
return inUseLearnables - completedLearnables > 5 || totalLearnables == inUseLearnables;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Find a SavedLearnableProgress with the given name
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <returns> SavedLearnableProgress with the given name </returns>
|
||||
public SavedLearnableProgress FindLearnable(string name)
|
||||
{
|
||||
return learnables.Find(l => l.name == name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Find learnable in learnables which is not yet in use, and set it active
|
||||
/// </summary>
|
||||
/// <returns> SavedLearnableProgress learnable </returns>
|
||||
private SavedLearnableProgress UseUnusedLearnable()
|
||||
{
|
||||
SavedLearnableProgress learnable = learnables.Find(l => !l.inUse);
|
||||
if (learnable == null)
|
||||
return null;
|
||||
|
||||
learnable.inUse = true;
|
||||
inUseLearnables++;
|
||||
return learnable;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a random inUse learnable
|
||||
/// </summary>
|
||||
/// <returns> a randomly selected inUse SavedLearnable which is not yet completed</returns>
|
||||
public SavedLearnableProgress GetRandomLearnable()
|
||||
{
|
||||
if (!EnoughLearnables())
|
||||
return UseUnusedLearnable();
|
||||
|
||||
// only select inUse learnables which are not yet completed (progress < 3.5f)
|
||||
List<SavedLearnableProgress> inUseLearnables = learnables.FindAll(l => l.inUse && l.progress <= 3.5f);
|
||||
|
||||
if (inUseLearnables.Count == 0)
|
||||
return null;
|
||||
|
||||
// Select a random index from the in-use learnables list
|
||||
int randomIndex = UnityEngine.Random.Range(0, inUseLearnables.Count);
|
||||
return inUseLearnables[randomIndex];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create new SavedLearnableProgress object and assigns the index and name values
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="index"></param>
|
||||
/// <returns> bool which indicates the success of the function</returns>
|
||||
public bool AddLearnable(string name, int index)
|
||||
{
|
||||
if (learnables.Any(learnable => learnable.name == name || learnable.index == index))
|
||||
return false;
|
||||
|
||||
SavedLearnableProgress savedLearnableProgress = new SavedLearnableProgress();
|
||||
savedLearnableProgress.index = index;
|
||||
savedLearnableProgress.name = name;
|
||||
learnables.Add(savedLearnableProgress);
|
||||
totalLearnables++;
|
||||
return true;
|
||||
}
|
||||
|
||||
public CourseIndex courseIndex;
|
||||
public float progress = -1.0f;
|
||||
public int completedLearnables = 0;
|
||||
public int inUseLearnables = 0;
|
||||
public int totalLearnables = 0;
|
||||
public List<SavedLearnableProgress> learnables = new List<SavedLearnableProgress>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stored individual learnable progress
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class SavedLearnableProgress : PersistentDataContainer
|
||||
{
|
||||
/// <summary>
|
||||
/// Index of the Learnbable in its Theme
|
||||
/// </summary>
|
||||
public int index;
|
||||
|
||||
/// <summary>
|
||||
/// Bool that indicated whether the user already started learning this Learnable
|
||||
/// </summary>
|
||||
public bool inUse = false;
|
||||
|
||||
/// <summary>
|
||||
/// Display name of the Learnable
|
||||
/// </summary>
|
||||
public string name;
|
||||
|
||||
/// <summary>
|
||||
/// Progress of the learnabe, a number between -5.0 and +5.0
|
||||
/// </summary>
|
||||
public float progress = 0.0f;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stored minigame progress data record
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class SavedMinigameProgress : PersistentDataContainer
|
||||
{
|
||||
/// <summary>
|
||||
/// Index of the minigame
|
||||
/// </summary>
|
||||
public MinigameIndex minigameIndex;
|
||||
|
||||
/// <summary>
|
||||
/// The 10 last scores of a user
|
||||
/// </summary>
|
||||
public List<Score> latestScores = new List<Score>();
|
||||
|
||||
/// <summary>
|
||||
/// Top 10 scores of a user
|
||||
/// </summary>
|
||||
public List<Score> highestScores = new List<Score>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stored WeSign data record
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
private class SavedDataStructure
|
||||
{
|
||||
/// <summary>
|
||||
/// The version of the PersistentDataController with which this savefile is created
|
||||
/// </summary>
|
||||
public int version = VERSION;
|
||||
|
||||
/// <summary>
|
||||
/// A list of all users
|
||||
/// </summary>
|
||||
public List<SavedUserData> users = new List<SavedUserData>();
|
||||
|
||||
/// <summary>
|
||||
/// The index of the current user in the this.users list
|
||||
/// </summary>
|
||||
public int currentUser = -1;
|
||||
|
||||
/// <summary>
|
||||
/// The index of the current minigame
|
||||
/// </summary>
|
||||
public MinigameIndex currentMinigame;
|
||||
|
||||
/// <summary>
|
||||
/// The index of the current course
|
||||
/// </summary>
|
||||
public CourseIndex currentCourse;
|
||||
|
||||
/// <summary>
|
||||
/// The index of the current theme
|
||||
/// </summary>
|
||||
public ThemeIndex currentTheme;
|
||||
|
||||
/// <summary>
|
||||
/// The use hardware acceleration user preferences
|
||||
/// </summary>
|
||||
public bool useGPU = false;
|
||||
|
||||
/// <summary>
|
||||
/// Initiate the SavedDataStructure, by setting the user preferences
|
||||
/// </summary>
|
||||
public SavedDataStructure()
|
||||
{
|
||||
RestoreSettings();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reset the user preferences to the default values
|
||||
/// </summary>
|
||||
public void RestoreSettings()
|
||||
{
|
||||
useGPU = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The object holding the data references
|
||||
/// </summary>
|
||||
private SavedDataStructure json = new SavedDataStructure();
|
||||
|
||||
/// <summary>
|
||||
/// Get the instance loaded by the singleton
|
||||
/// </summary>
|
||||
/// <returns><c>PersistentDataController</c> instance</returns>
|
||||
public static PersistentDataController GetInstance()
|
||||
{
|
||||
// Create a new instance if non exists
|
||||
if (instance == null || PATH == null)
|
||||
{
|
||||
if (PATH == null)
|
||||
PersistentDataController.PATH = $"{Application.persistentDataPath}/wesign_saved_data.json";
|
||||
instance = new PersistentDataController();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// PersistentDataController contructor
|
||||
/// </summary>
|
||||
private PersistentDataController()
|
||||
{
|
||||
Load();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clear everything stored in the PersistentDataController, won't save to disk
|
||||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
json.users.Clear();
|
||||
json.currentUser = -1;
|
||||
json.useGPU = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Save all data to disk
|
||||
/// </summary>
|
||||
public void Save()
|
||||
{
|
||||
string text = JsonUtility.ToJson(json);
|
||||
File.CreateText(PATH).Close();
|
||||
File.WriteAllText(PATH, text);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override current data with the data from disk, will just clear if no data was found.
|
||||
/// </summary>
|
||||
/// <param name="overrideOnFail"><c>true</c> if you want to override the existing file if it exists and the loading failed.</param>
|
||||
/// <remarks>If the data on disk is outdated (version number is lower than the current version), the loading will also fail</remarks>
|
||||
/// <returns><c>true</c> if successful, <c>false</c> otherwise</returns>
|
||||
public bool Load(bool overrideOnFail = true)
|
||||
{
|
||||
Clear();
|
||||
if (!File.Exists(PATH))
|
||||
goto failed;
|
||||
|
||||
try
|
||||
{
|
||||
string text = File.ReadAllText(PATH);
|
||||
SavedDataStructure newJson = JsonUtility.FromJson<SavedDataStructure>(text);
|
||||
if (newJson == null || newJson.version != VERSION)
|
||||
goto failed;
|
||||
|
||||
json = newJson;
|
||||
return true;
|
||||
}
|
||||
catch (Exception) { goto failed; }
|
||||
|
||||
failed:
|
||||
if (overrideOnFail)
|
||||
Save();
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a user to the WeSign data record
|
||||
/// </summary>
|
||||
/// <param name="user">User data record</param>
|
||||
/// <param name="save">Whether to save the addition immediately to disk</param>
|
||||
public void AddUser(SavedUserData user, bool save = true)
|
||||
{
|
||||
if (json.users.Count == 0)
|
||||
json.currentUser = 0;
|
||||
json.users.Add(user);
|
||||
|
||||
if (save)
|
||||
Save();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a list of all user data records
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public List<SavedUserData> GetUsers()
|
||||
{
|
||||
return json.users;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the index of the current user
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public int GetCurrentUser()
|
||||
{
|
||||
return json.currentUser;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the index of the current record
|
||||
/// </summary>
|
||||
/// <param name="index">New index</param>
|
||||
/// <param name="save">Whether to save the change immediately to disk</param>
|
||||
/// <exception cref="IndexOutOfRangeException"></exception>
|
||||
public void SetCurrentUser(int index, bool save = true)
|
||||
{
|
||||
if (index < 0 || json.users.Count <= index)
|
||||
throw new IndexOutOfRangeException();
|
||||
json.currentUser = index;
|
||||
|
||||
if (save)
|
||||
Save();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove a user data record
|
||||
/// </summary>
|
||||
/// <param name="index">Index of the user</param>
|
||||
/// <param name="save">Whether to save the deletion immediately to disk</param>
|
||||
/// <exception cref="IndexOutOfRangeException"></exception>
|
||||
public void DeleteUser(int index, bool save = true)
|
||||
{
|
||||
if (index < 0 || json.users.Count <= index)
|
||||
throw new IndexOutOfRangeException();
|
||||
|
||||
if (0 < json.currentUser && index <= json.currentUser)
|
||||
json.currentUser--;
|
||||
json.users.RemoveAt(index);
|
||||
|
||||
if (save)
|
||||
Save();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the current course
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public CourseIndex GetCurrentCourse()
|
||||
{
|
||||
return json.currentCourse;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the current course
|
||||
/// </summary>
|
||||
/// <param name="course">New course index</param>
|
||||
/// <param name="save">Whether to save the change immediately to disk</param>
|
||||
public void SetCurrentCourse(CourseIndex course, bool save = true)
|
||||
{
|
||||
json.currentCourse = course;
|
||||
|
||||
if (save)
|
||||
Save();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the current minigame
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public MinigameIndex GetCurrentMinigame()
|
||||
{
|
||||
return json.currentMinigame;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the current minigame
|
||||
/// </summary>
|
||||
/// <param name="minigame">New minigame index</param>
|
||||
/// <param name="save">Whether to save the change immediately to disk</param>
|
||||
public void SetCurrentMinigame(MinigameIndex minigame, bool save = true)
|
||||
{
|
||||
json.currentMinigame = minigame;
|
||||
|
||||
if (save)
|
||||
Save();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the current theme
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public ThemeIndex GetCurrentTheme()
|
||||
{
|
||||
return json.currentTheme;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the current theme
|
||||
/// </summary>
|
||||
/// <param name="theme">New theme index</param>
|
||||
/// <param name="save">Whether to save the change immediately to disk</param>
|
||||
public void SetCurrentTheme(ThemeIndex theme, bool save = true)
|
||||
{
|
||||
json.currentTheme = theme;
|
||||
|
||||
if (save)
|
||||
Save();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Whether the user wants to use hardware acceleration or not
|
||||
/// </summary>
|
||||
public bool IsUsingGPU()
|
||||
{
|
||||
return json.useGPU;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the preference of the user for hardware acceleration
|
||||
/// </summary>
|
||||
/// <param name="value">Value of the preference</param>
|
||||
/// <param name="save">Whether to save the change immediately to disk</param>
|
||||
public void SetGPUUsage(bool value, bool save = true)
|
||||
{
|
||||
json.useGPU = value;
|
||||
|
||||
if (save)
|
||||
Save();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Restore preferences to default factory settings
|
||||
/// </summary>
|
||||
/// <param name="save">Whether to save the change immediately to disk</param>
|
||||
public void RestoreSettings(bool save = true)
|
||||
{
|
||||
json.RestoreSettings();
|
||||
|
||||
if (save)
|
||||
Save();
|
||||
}
|
||||
}
|
||||
11
Assets/Architecture/Scripts/PersistentDataController.cs.meta
Normal file
11
Assets/Architecture/Scripts/PersistentDataController.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 164b1accbeff688429a4311f1e40bd59
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
19
Assets/Architecture/Scripts/Score.cs
Normal file
19
Assets/Architecture/Scripts/Score.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using System;
|
||||
|
||||
/// <summary>
|
||||
/// Score class
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class Score
|
||||
{
|
||||
/// <summary>
|
||||
/// The actual score
|
||||
/// </summary>
|
||||
public int scoreValue;
|
||||
|
||||
/// <summary>
|
||||
/// The time when the score is achieved, in string format
|
||||
/// </summary>
|
||||
public string time;
|
||||
}
|
||||
|
||||
647
Assets/Architecture/Scripts/SlicedSlider.cs
Normal file
647
Assets/Architecture/Scripts/SlicedSlider.cs
Normal file
@@ -0,0 +1,647 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
#if UNITY_2017_4 || UNITY_2018_2_OR_NEWER
|
||||
using UnityEngine.U2D;
|
||||
#endif
|
||||
using Sprites = UnityEngine.Sprites;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
|
||||
// Custom Editor to order the variables in the Inspector similar to Image component
|
||||
[CustomEditor(typeof(SlicedSlider)), CanEditMultipleObjects]
|
||||
public class SlicedSliderEditor : Editor
|
||||
{
|
||||
private SerializedProperty spriteProp, colorProp;
|
||||
private GUIContent spriteLabel;
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
spriteProp = serializedObject.FindProperty("m_Sprite");
|
||||
colorProp = serializedObject.FindProperty("m_Color");
|
||||
spriteLabel = new GUIContent("Source Image");
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
serializedObject.Update();
|
||||
|
||||
EditorGUILayout.PropertyField(spriteProp, spriteLabel);
|
||||
EditorGUILayout.PropertyField(colorProp);
|
||||
DrawPropertiesExcluding(serializedObject, "m_Script", "m_Sprite", "m_Color", "m_OnCullStateChanged");
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Credit: https://bitbucket.org/Unity-Technologies/ui/src/2018.4/UnityEngine.UI/UI/Core/Image.cs
|
||||
[RequireComponent(typeof(CanvasRenderer))]
|
||||
[AddComponentMenu("UI/Sliced Slider", 11)]
|
||||
public class SlicedSlider : MaskableGraphic, ISerializationCallbackReceiver, ILayoutElement, ICanvasRaycastFilter
|
||||
{
|
||||
private static class SetPropertyUtility
|
||||
{
|
||||
public static bool SetStruct<T>(ref T currentValue, T newValue) where T : struct
|
||||
{
|
||||
if (EqualityComparer<T>.Default.Equals(currentValue, newValue))
|
||||
return false;
|
||||
|
||||
currentValue = newValue;
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool SetClass<T>(ref T currentValue, T newValue) where T : class
|
||||
{
|
||||
if ((currentValue == null && newValue == null) || (currentValue != null && currentValue.Equals(newValue)))
|
||||
return false;
|
||||
|
||||
currentValue = newValue;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public enum FillDirection { Right = 0, Left = 1, Up = 2, Down = 3 }
|
||||
|
||||
private static readonly Vector3[] s_Vertices = new Vector3[4];
|
||||
private static readonly Vector2[] s_UVs = new Vector2[4];
|
||||
private static readonly Vector2[] s_SlicedVertices = new Vector2[4];
|
||||
private static readonly Vector2[] s_SlicedUVs = new Vector2[4];
|
||||
|
||||
#pragma warning disable 1692
|
||||
#pragma warning disable IDE1006 // Suppress 'Naming rule violation' warnings
|
||||
#pragma warning disable 0649
|
||||
[SerializeField]
|
||||
private Sprite m_Sprite;
|
||||
public Sprite sprite
|
||||
{
|
||||
get { return m_Sprite; }
|
||||
set
|
||||
{
|
||||
if (SetPropertyUtility.SetClass(ref m_Sprite, value))
|
||||
{
|
||||
SetAllDirty();
|
||||
TrackImage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private FillDirection m_FillDirection;
|
||||
public FillDirection fillDirection
|
||||
{
|
||||
get { return m_FillDirection; }
|
||||
set
|
||||
{
|
||||
if (SetPropertyUtility.SetStruct(ref m_FillDirection, value))
|
||||
SetVerticesDirty();
|
||||
}
|
||||
}
|
||||
|
||||
[Range(0, 1)]
|
||||
[SerializeField]
|
||||
private float m_FillAmount = 1f;
|
||||
public float fillAmount
|
||||
{
|
||||
get { return m_FillAmount; }
|
||||
set
|
||||
{
|
||||
if (SetPropertyUtility.SetStruct(ref m_FillAmount, Mathf.Clamp01(value)))
|
||||
SetVerticesDirty();
|
||||
}
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private bool m_FillCenter = true;
|
||||
public bool fillCenter
|
||||
{
|
||||
get { return m_FillCenter; }
|
||||
set
|
||||
{
|
||||
if (SetPropertyUtility.SetStruct(ref m_FillCenter, value))
|
||||
SetVerticesDirty();
|
||||
}
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private float m_PixelsPerUnitMultiplier = 1f;
|
||||
public float pixelsPerUnitMultiplier
|
||||
{
|
||||
get { return m_PixelsPerUnitMultiplier; }
|
||||
set { m_PixelsPerUnitMultiplier = Mathf.Max(0.01f, value); }
|
||||
}
|
||||
|
||||
public float pixelsPerUnit
|
||||
{
|
||||
get
|
||||
{
|
||||
float spritePixelsPerUnit = 100;
|
||||
if (activeSprite)
|
||||
spritePixelsPerUnit = activeSprite.pixelsPerUnit;
|
||||
|
||||
float referencePixelsPerUnit = 100;
|
||||
if (canvas)
|
||||
referencePixelsPerUnit = canvas.referencePixelsPerUnit;
|
||||
|
||||
return m_PixelsPerUnitMultiplier * spritePixelsPerUnit / referencePixelsPerUnit;
|
||||
}
|
||||
}
|
||||
#pragma warning restore 0649
|
||||
|
||||
[NonSerialized]
|
||||
private Sprite m_OverrideSprite;
|
||||
public Sprite overrideSprite
|
||||
{
|
||||
get { return activeSprite; }
|
||||
set
|
||||
{
|
||||
if (SetPropertyUtility.SetClass(ref m_OverrideSprite, value))
|
||||
{
|
||||
SetAllDirty();
|
||||
TrackImage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Sprite activeSprite { get { return m_OverrideSprite != null ? m_OverrideSprite : m_Sprite; } }
|
||||
|
||||
public override Texture mainTexture
|
||||
{
|
||||
get
|
||||
{
|
||||
if (activeSprite != null)
|
||||
return activeSprite.texture;
|
||||
|
||||
return material != null && material.mainTexture != null ? material.mainTexture : s_WhiteTexture;
|
||||
}
|
||||
}
|
||||
|
||||
public bool hasBorder
|
||||
{
|
||||
get
|
||||
{
|
||||
if (activeSprite != null)
|
||||
{
|
||||
Vector4 v = activeSprite.border;
|
||||
return v.sqrMagnitude > 0f;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public override Material material
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_Material != null)
|
||||
return m_Material;
|
||||
|
||||
if (activeSprite && activeSprite.associatedAlphaSplitTexture != null)
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
if (Application.isPlaying)
|
||||
#endif
|
||||
return Image.defaultETC1GraphicMaterial;
|
||||
}
|
||||
|
||||
return defaultMaterial;
|
||||
}
|
||||
set { base.material = value; }
|
||||
}
|
||||
|
||||
public float alphaHitTestMinimumThreshold { get; set; }
|
||||
#pragma warning restore IDE1006
|
||||
#pragma warning restore 1692
|
||||
|
||||
protected SlicedSlider()
|
||||
{
|
||||
useLegacyMeshGeneration = false;
|
||||
}
|
||||
|
||||
protected override void OnEnable()
|
||||
{
|
||||
base.OnEnable();
|
||||
TrackImage();
|
||||
}
|
||||
|
||||
protected override void OnDisable()
|
||||
{
|
||||
base.OnDisable();
|
||||
|
||||
if (m_Tracked)
|
||||
UnTrackImage();
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
protected override void OnValidate()
|
||||
{
|
||||
base.OnValidate();
|
||||
m_PixelsPerUnitMultiplier = Mathf.Max(0.01f, m_PixelsPerUnitMultiplier);
|
||||
}
|
||||
#endif
|
||||
|
||||
protected override void OnPopulateMesh(VertexHelper vh)
|
||||
{
|
||||
if (activeSprite == null)
|
||||
{
|
||||
base.OnPopulateMesh(vh);
|
||||
return;
|
||||
}
|
||||
|
||||
GenerateSlicedFilledSprite(vh);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update the renderer's material.
|
||||
/// </summary>
|
||||
protected override void UpdateMaterial()
|
||||
{
|
||||
base.UpdateMaterial();
|
||||
|
||||
// Check if this sprite has an associated alpha texture (generated when splitting RGBA = RGB + A as two textures without alpha)
|
||||
if (activeSprite == null)
|
||||
{
|
||||
canvasRenderer.SetAlphaTexture(null);
|
||||
return;
|
||||
}
|
||||
|
||||
Texture2D alphaTex = activeSprite.associatedAlphaSplitTexture;
|
||||
if (alphaTex != null)
|
||||
canvasRenderer.SetAlphaTexture(alphaTex);
|
||||
}
|
||||
|
||||
private void GenerateSlicedFilledSprite(VertexHelper vh)
|
||||
{
|
||||
vh.Clear();
|
||||
|
||||
if (m_FillAmount < 0.001f)
|
||||
return;
|
||||
|
||||
Rect rect = GetPixelAdjustedRect();
|
||||
Vector4 outer = Sprites.DataUtility.GetOuterUV(activeSprite);
|
||||
Vector4 padding = Sprites.DataUtility.GetPadding(activeSprite);
|
||||
|
||||
if (!hasBorder)
|
||||
{
|
||||
Vector2 size = activeSprite.rect.size;
|
||||
|
||||
int spriteW = Mathf.RoundToInt(size.x);
|
||||
int spriteH = Mathf.RoundToInt(size.y);
|
||||
|
||||
// Image's dimensions used for drawing. X = left, Y = bottom, Z = right, W = top.
|
||||
Vector4 vertices = new Vector4(
|
||||
rect.x + rect.width * (padding.x / spriteW),
|
||||
rect.y + rect.height * (padding.y / spriteH),
|
||||
rect.x + rect.width * ((spriteW - padding.z) / spriteW),
|
||||
rect.y + rect.height * ((spriteH - padding.w) / spriteH));
|
||||
|
||||
GenerateFilledSprite(vh, vertices, outer, m_FillAmount);
|
||||
return;
|
||||
}
|
||||
|
||||
Vector4 inner = Sprites.DataUtility.GetInnerUV(activeSprite);
|
||||
Vector4 border = GetAdjustedBorders(activeSprite.border / pixelsPerUnit, rect);
|
||||
|
||||
padding = padding / pixelsPerUnit;
|
||||
|
||||
s_SlicedVertices[0] = new Vector2(padding.x, padding.y);
|
||||
s_SlicedVertices[3] = new Vector2(rect.width - padding.z, rect.height - padding.w);
|
||||
|
||||
s_SlicedVertices[1].x = border.x;
|
||||
s_SlicedVertices[1].y = border.y;
|
||||
|
||||
s_SlicedVertices[2].x = rect.width - border.z;
|
||||
s_SlicedVertices[2].y = rect.height - border.w;
|
||||
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
s_SlicedVertices[i].x += rect.x;
|
||||
s_SlicedVertices[i].y += rect.y;
|
||||
}
|
||||
|
||||
s_SlicedUVs[0] = new Vector2(outer.x, outer.y);
|
||||
s_SlicedUVs[1] = new Vector2(inner.x, inner.y);
|
||||
s_SlicedUVs[2] = new Vector2(inner.z, inner.w);
|
||||
s_SlicedUVs[3] = new Vector2(outer.z, outer.w);
|
||||
|
||||
float rectStartPos;
|
||||
float _1OverTotalSize;
|
||||
if (m_FillDirection == FillDirection.Left || m_FillDirection == FillDirection.Right)
|
||||
{
|
||||
rectStartPos = s_SlicedVertices[0].x;
|
||||
|
||||
float totalSize = (s_SlicedVertices[3].x - s_SlicedVertices[0].x);
|
||||
_1OverTotalSize = totalSize > 0f ? 1f / totalSize : 1f;
|
||||
}
|
||||
else
|
||||
{
|
||||
rectStartPos = s_SlicedVertices[0].y;
|
||||
|
||||
float totalSize = (s_SlicedVertices[3].y - s_SlicedVertices[0].y);
|
||||
_1OverTotalSize = totalSize > 0f ? 1f / totalSize : 1f;
|
||||
}
|
||||
|
||||
for (int x = 0; x < 3; x++)
|
||||
{
|
||||
int x2 = x + 1;
|
||||
|
||||
for (int y = 0; y < 3; y++)
|
||||
{
|
||||
if (!m_FillCenter && x == 1 && y == 1)
|
||||
continue;
|
||||
|
||||
int y2 = y + 1;
|
||||
|
||||
float sliceStart, sliceEnd;
|
||||
switch (m_FillDirection)
|
||||
{
|
||||
case FillDirection.Right:
|
||||
sliceStart = (s_SlicedVertices[x].x - rectStartPos) * _1OverTotalSize;
|
||||
sliceEnd = (s_SlicedVertices[x2].x - rectStartPos) * _1OverTotalSize;
|
||||
break;
|
||||
case FillDirection.Up:
|
||||
sliceStart = (s_SlicedVertices[y].y - rectStartPos) * _1OverTotalSize;
|
||||
sliceEnd = (s_SlicedVertices[y2].y - rectStartPos) * _1OverTotalSize;
|
||||
break;
|
||||
case FillDirection.Left:
|
||||
sliceStart = 1f - (s_SlicedVertices[x2].x - rectStartPos) * _1OverTotalSize;
|
||||
sliceEnd = 1f - (s_SlicedVertices[x].x - rectStartPos) * _1OverTotalSize;
|
||||
break;
|
||||
case FillDirection.Down:
|
||||
sliceStart = 1f - (s_SlicedVertices[y2].y - rectStartPos) * _1OverTotalSize;
|
||||
sliceEnd = 1f - (s_SlicedVertices[y].y - rectStartPos) * _1OverTotalSize;
|
||||
break;
|
||||
default: // Just there to get rid of the "Use of unassigned local variable" compiler error
|
||||
sliceStart = sliceEnd = 0f;
|
||||
break;
|
||||
}
|
||||
|
||||
if (sliceStart >= m_FillAmount)
|
||||
continue;
|
||||
|
||||
Vector4 vertices = new Vector4(s_SlicedVertices[x].x, s_SlicedVertices[y].y, s_SlicedVertices[x2].x, s_SlicedVertices[y2].y);
|
||||
Vector4 uvs = new Vector4(s_SlicedUVs[x].x, s_SlicedUVs[y].y, s_SlicedUVs[x2].x, s_SlicedUVs[y2].y);
|
||||
float fillAmount = (m_FillAmount - sliceStart) / (sliceEnd - sliceStart);
|
||||
|
||||
GenerateFilledSprite(vh, vertices, uvs, fillAmount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Vector4 GetAdjustedBorders(Vector4 border, Rect adjustedRect)
|
||||
{
|
||||
Rect originalRect = rectTransform.rect;
|
||||
|
||||
for (int axis = 0; axis <= 1; axis++)
|
||||
{
|
||||
float borderScaleRatio;
|
||||
|
||||
// The adjusted rect (adjusted for pixel correctness) may be slightly larger than the original rect.
|
||||
// Adjust the border to match the adjustedRect to avoid small gaps between borders (case 833201).
|
||||
if (originalRect.size[axis] != 0)
|
||||
{
|
||||
borderScaleRatio = adjustedRect.size[axis] / originalRect.size[axis];
|
||||
border[axis] *= borderScaleRatio;
|
||||
border[axis + 2] *= borderScaleRatio;
|
||||
}
|
||||
|
||||
// If the rect is smaller than the combined borders, then there's not room for the borders at their normal size.
|
||||
// In order to avoid artefacts with overlapping borders, we scale the borders down to fit.
|
||||
float combinedBorders = border[axis] + border[axis + 2];
|
||||
if (adjustedRect.size[axis] < combinedBorders && combinedBorders != 0)
|
||||
{
|
||||
borderScaleRatio = adjustedRect.size[axis] / combinedBorders;
|
||||
border[axis] *= borderScaleRatio;
|
||||
border[axis + 2] *= borderScaleRatio;
|
||||
}
|
||||
}
|
||||
|
||||
return border;
|
||||
}
|
||||
|
||||
private void GenerateFilledSprite(VertexHelper vh, Vector4 vertices, Vector4 uvs, float fillAmount)
|
||||
{
|
||||
if (m_FillAmount < 0.001f)
|
||||
return;
|
||||
|
||||
float uvLeft = uvs.x;
|
||||
float uvBottom = uvs.y;
|
||||
float uvRight = uvs.z;
|
||||
float uvTop = uvs.w;
|
||||
|
||||
if (fillAmount < 1f)
|
||||
{
|
||||
if (m_FillDirection == FillDirection.Left || m_FillDirection == FillDirection.Right)
|
||||
{
|
||||
if (m_FillDirection == FillDirection.Left)
|
||||
{
|
||||
vertices.x = vertices.z - (vertices.z - vertices.x) * fillAmount;
|
||||
uvLeft = uvRight - (uvRight - uvLeft) * fillAmount;
|
||||
}
|
||||
else
|
||||
{
|
||||
vertices.z = vertices.x + (vertices.z - vertices.x) * fillAmount;
|
||||
uvRight = uvLeft + (uvRight - uvLeft) * fillAmount;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_FillDirection == FillDirection.Down)
|
||||
{
|
||||
vertices.y = vertices.w - (vertices.w - vertices.y) * fillAmount;
|
||||
uvBottom = uvTop - (uvTop - uvBottom) * fillAmount;
|
||||
}
|
||||
else
|
||||
{
|
||||
vertices.w = vertices.y + (vertices.w - vertices.y) * fillAmount;
|
||||
uvTop = uvBottom + (uvTop - uvBottom) * fillAmount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s_Vertices[0] = new Vector3(vertices.x, vertices.y);
|
||||
s_Vertices[1] = new Vector3(vertices.x, vertices.w);
|
||||
s_Vertices[2] = new Vector3(vertices.z, vertices.w);
|
||||
s_Vertices[3] = new Vector3(vertices.z, vertices.y);
|
||||
|
||||
s_UVs[0] = new Vector2(uvLeft, uvBottom);
|
||||
s_UVs[1] = new Vector2(uvLeft, uvTop);
|
||||
s_UVs[2] = new Vector2(uvRight, uvTop);
|
||||
s_UVs[3] = new Vector2(uvRight, uvBottom);
|
||||
|
||||
int startIndex = vh.currentVertCount;
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
vh.AddVert(s_Vertices[i], color, s_UVs[i]);
|
||||
|
||||
vh.AddTriangle(startIndex, startIndex + 1, startIndex + 2);
|
||||
vh.AddTriangle(startIndex + 2, startIndex + 3, startIndex);
|
||||
}
|
||||
|
||||
int ILayoutElement.layoutPriority { get { return 0; } }
|
||||
float ILayoutElement.minWidth { get { return 0; } }
|
||||
float ILayoutElement.minHeight { get { return 0; } }
|
||||
float ILayoutElement.flexibleWidth { get { return -1; } }
|
||||
float ILayoutElement.flexibleHeight { get { return -1; } }
|
||||
|
||||
float ILayoutElement.preferredWidth
|
||||
{
|
||||
get
|
||||
{
|
||||
if (activeSprite == null)
|
||||
return 0;
|
||||
|
||||
return Sprites.DataUtility.GetMinSize(activeSprite).x / pixelsPerUnit;
|
||||
}
|
||||
}
|
||||
|
||||
float ILayoutElement.preferredHeight
|
||||
{
|
||||
get
|
||||
{
|
||||
if (activeSprite == null)
|
||||
return 0;
|
||||
|
||||
return Sprites.DataUtility.GetMinSize(activeSprite).y / pixelsPerUnit;
|
||||
}
|
||||
}
|
||||
|
||||
void ILayoutElement.CalculateLayoutInputHorizontal() { }
|
||||
void ILayoutElement.CalculateLayoutInputVertical() { }
|
||||
|
||||
bool ICanvasRaycastFilter.IsRaycastLocationValid(Vector2 screenPoint, Camera eventCamera)
|
||||
{
|
||||
if (alphaHitTestMinimumThreshold <= 0)
|
||||
return true;
|
||||
|
||||
if (alphaHitTestMinimumThreshold > 1)
|
||||
return false;
|
||||
|
||||
if (activeSprite == null)
|
||||
return true;
|
||||
|
||||
Vector2 local;
|
||||
if (!RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, screenPoint, eventCamera, out local))
|
||||
return false;
|
||||
|
||||
Rect rect = GetPixelAdjustedRect();
|
||||
|
||||
// Convert to have lower left corner as reference point.
|
||||
local.x += rectTransform.pivot.x * rect.width;
|
||||
local.y += rectTransform.pivot.y * rect.height;
|
||||
|
||||
Rect spriteRect = activeSprite.rect;
|
||||
Vector4 border = activeSprite.border;
|
||||
Vector4 adjustedBorder = GetAdjustedBorders(border / pixelsPerUnit, rect);
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
if (local[i] <= adjustedBorder[i])
|
||||
continue;
|
||||
|
||||
if (rect.size[i] - local[i] <= adjustedBorder[i + 2])
|
||||
{
|
||||
local[i] -= (rect.size[i] - spriteRect.size[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
float lerp = Mathf.InverseLerp(adjustedBorder[i], rect.size[i] - adjustedBorder[i + 2], local[i]);
|
||||
local[i] = Mathf.Lerp(border[i], spriteRect.size[i] - border[i + 2], lerp);
|
||||
}
|
||||
|
||||
// Normalize local coordinates.
|
||||
Rect textureRect = activeSprite.textureRect;
|
||||
Vector2 normalized = new Vector2(local.x / textureRect.width, local.y / textureRect.height);
|
||||
|
||||
// Convert to texture space.
|
||||
float x = Mathf.Lerp(textureRect.x, textureRect.xMax, normalized.x) / activeSprite.texture.width;
|
||||
float y = Mathf.Lerp(textureRect.y, textureRect.yMax, normalized.y) / activeSprite.texture.height;
|
||||
|
||||
switch (m_FillDirection)
|
||||
{
|
||||
case FillDirection.Right:
|
||||
if (x > m_FillAmount)
|
||||
return false;
|
||||
break;
|
||||
case FillDirection.Left:
|
||||
if (1f - x > m_FillAmount)
|
||||
return false;
|
||||
break;
|
||||
case FillDirection.Up:
|
||||
if (y > m_FillAmount)
|
||||
return false;
|
||||
break;
|
||||
case FillDirection.Down:
|
||||
if (1f - y > m_FillAmount)
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return activeSprite.texture.GetPixelBilinear(x, y).a >= alphaHitTestMinimumThreshold;
|
||||
}
|
||||
catch (UnityException e)
|
||||
{
|
||||
Debug.LogError("Using alphaHitTestMinimumThreshold greater than 0 on Image whose sprite texture cannot be read. " + e.Message + " Also make sure to disable sprite packing for this sprite.", this);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void ISerializationCallbackReceiver.OnBeforeSerialize() { }
|
||||
void ISerializationCallbackReceiver.OnAfterDeserialize()
|
||||
{
|
||||
m_FillAmount = Mathf.Clamp01(m_FillAmount);
|
||||
}
|
||||
|
||||
// Whether this is being tracked for Atlas Binding
|
||||
private bool m_Tracked = false;
|
||||
|
||||
#if UNITY_2017_4 || UNITY_2018_2_OR_NEWER
|
||||
private static List<SlicedSlider> m_TrackedTexturelessImages = new List<SlicedSlider>();
|
||||
private static bool s_Initialized;
|
||||
#endif
|
||||
|
||||
private void TrackImage()
|
||||
{
|
||||
if (activeSprite != null && activeSprite.texture == null)
|
||||
{
|
||||
#if UNITY_2017_4 || UNITY_2018_2_OR_NEWER
|
||||
if (!s_Initialized)
|
||||
{
|
||||
SpriteAtlasManager.atlasRegistered += RebuildImage;
|
||||
s_Initialized = true;
|
||||
}
|
||||
|
||||
m_TrackedTexturelessImages.Add(this);
|
||||
#endif
|
||||
m_Tracked = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void UnTrackImage()
|
||||
{
|
||||
#if UNITY_2017_4 || UNITY_2018_2_OR_NEWER
|
||||
m_TrackedTexturelessImages.Remove(this);
|
||||
#endif
|
||||
m_Tracked = false;
|
||||
}
|
||||
|
||||
#if UNITY_2017_4 || UNITY_2018_2_OR_NEWER
|
||||
private static void RebuildImage(SpriteAtlas spriteAtlas)
|
||||
{
|
||||
for (int i = m_TrackedTexturelessImages.Count - 1; i >= 0; i--)
|
||||
{
|
||||
SlicedSlider image = m_TrackedTexturelessImages[i];
|
||||
if (spriteAtlas.CanBindTo(image.activeSprite))
|
||||
{
|
||||
image.SetAllDirty();
|
||||
m_TrackedTexturelessImages.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
11
Assets/Architecture/Scripts/SlicedSlider.cs.meta
Normal file
11
Assets/Architecture/Scripts/SlicedSlider.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b69b55aa2ac2e0e4592740cf1269d52c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
133
Assets/Architecture/Scripts/SystemController.cs
Normal file
133
Assets/Architecture/Scripts/SystemController.cs
Normal file
@@ -0,0 +1,133 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
/// <summary>
|
||||
/// SystemController singleton
|
||||
/// </summary>
|
||||
public class SystemController
|
||||
{
|
||||
/// <summary>
|
||||
/// The instance controlling the singleton
|
||||
/// </summary>
|
||||
private static SystemController instance = null;
|
||||
|
||||
/// <summary>
|
||||
/// Stack of the loaded scenes, used to easily go back to previous scenes
|
||||
/// </summary>
|
||||
private Stack<int> sceneStack = new Stack<int>();
|
||||
|
||||
/// <summary>
|
||||
/// Index of the previous loaded scene
|
||||
/// </summary>
|
||||
public int previousScene = -1;
|
||||
|
||||
/// <summary>
|
||||
/// Index of the current loaded scene
|
||||
/// </summary>
|
||||
public int currentScene = -1;
|
||||
|
||||
/// <summary>
|
||||
/// Get the instance loaded by the singleton
|
||||
/// </summary>
|
||||
/// <returns>SystemController instance</returns>
|
||||
public static SystemController GetInstance()
|
||||
{
|
||||
// Create a new instance if non exists
|
||||
if (instance == null)
|
||||
{
|
||||
instance = new SystemController();
|
||||
instance.currentScene = SceneManager.GetActiveScene().buildIndex;
|
||||
instance.sceneStack.Push(instance.currentScene);
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the number of passively 'active' scenes
|
||||
/// </summary>
|
||||
public int GetSceneStackSize() { return sceneStack.Count; }
|
||||
|
||||
/// <summary>
|
||||
/// Load the scene and push on the stack
|
||||
/// </summary>
|
||||
/// <param name="scenePath">Path of the scene</param>
|
||||
public void LoadNextScene(string scenePath)
|
||||
{
|
||||
LoadNextScene(SystemController.GetSceneIndex(scenePath));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the index of a given scene
|
||||
/// </summary>
|
||||
/// <param name="scenePath">Path of the scene</param>
|
||||
/// <returns></returns>
|
||||
public static int GetSceneIndex(string scenePath)
|
||||
{
|
||||
return SceneUtility.GetBuildIndexByScenePath(scenePath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Load the scene and push on the stack
|
||||
/// </summary>
|
||||
/// <param name="sceneIndex">Buildindex of the scene</param>
|
||||
public void LoadNextScene(int sceneIndex)
|
||||
{
|
||||
previousScene = currentScene;
|
||||
currentScene = sceneIndex;
|
||||
|
||||
sceneStack.Push(currentScene);
|
||||
SceneManager.LoadScene(currentScene);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Swap the current scene with the new scene on the stack
|
||||
/// </summary>
|
||||
/// <param name="scenePath">Path of the scene</param>
|
||||
public void SwapScene(string scenePath)
|
||||
{
|
||||
SwapScene(SystemController.GetSceneIndex(scenePath));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Swap the current scene with the new scene on the stack
|
||||
/// </summary>
|
||||
/// <param name="sceneIndex">Buildindex of the scene</param>
|
||||
public void SwapScene(int sceneIndex)
|
||||
{
|
||||
currentScene = sceneStack.Pop();
|
||||
LoadNextScene(sceneIndex);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Go back to the previous scene and unload the current scene
|
||||
/// </summary>
|
||||
public void BackToPreviousScene()
|
||||
{
|
||||
previousScene = sceneStack.Pop();
|
||||
if (sceneStack.Count > 0) SceneManager.LoadScene(currentScene = sceneStack.Peek());
|
||||
else Application.Quit();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Go back to a specific scene, unloading all the scenes on the way
|
||||
/// </summary>
|
||||
/// <param name="scenePath">Path of the scene</param>
|
||||
public void BackToScene(string scenePath)
|
||||
{
|
||||
BackToScene(SystemController.GetSceneIndex(scenePath));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Go back to a specific scene, unloading all the scene on the way
|
||||
/// </summary>
|
||||
/// <param name="sceneIndex">Buildindex of the scene</param>
|
||||
public void BackToScene(int sceneIndex)
|
||||
{
|
||||
previousScene = currentScene;
|
||||
while (0 < sceneStack.Count && sceneStack.Peek() != sceneIndex) sceneStack.Pop();
|
||||
|
||||
if (sceneStack.Count > 0) SceneManager.LoadScene(currentScene = sceneStack.Peek());
|
||||
else Application.Quit();
|
||||
}
|
||||
}
|
||||
19
Assets/Architecture/Scripts/ThemeIndex.cs
Normal file
19
Assets/Architecture/Scripts/ThemeIndex.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
|
||||
/// <summary>
|
||||
/// Enum for easy indexing and checking if a course is of a certain kind
|
||||
/// </summary>
|
||||
public enum ThemeIndex
|
||||
{
|
||||
SIGN_ALPHABET,
|
||||
SIGN_BASICS,
|
||||
SIGN_CLOTHING,
|
||||
SIGN_ANIMALS,
|
||||
SIGN_FOOD,
|
||||
SIGN_HOBBIES,
|
||||
SIGN_HOUSE,
|
||||
SIGN_FAMILY,
|
||||
SPELLING_COUNTRIES,
|
||||
SPELLING_WILD,
|
||||
SPELLING_FARM,
|
||||
SPELLING_CAPITALS
|
||||
}
|
||||
8
Assets/Architecture/Tests.meta
Normal file
8
Assets/Architecture/Tests.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8559f509b8f924f44bc10e2d20ac3eed
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/Architecture/Tests/EditMode.meta
Normal file
8
Assets/Architecture/Tests/EditMode.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 05ae9a4f64d7f5049b18346b8277e525
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"name": "ArchitectureEditMode",
|
||||
"rootNamespace": "",
|
||||
"references": [
|
||||
"UnityEditor.TestRunner",
|
||||
"UnityEngine.TestRunner",
|
||||
"ArchitectureScripts"
|
||||
],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": true,
|
||||
"precompiledReferences": [
|
||||
"nunit.framework.dll"
|
||||
],
|
||||
"autoReferenced": false,
|
||||
"defineConstraints": [
|
||||
"UNITY_INCLUDE_TESTS"
|
||||
],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b1a4ef95cbacdca459433eb2ddc05755
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user