diff --git a/Assets/CrystalFramework.meta b/Assets/CrystalFramework.meta
new file mode 100644
index 0000000..c061fcf
--- /dev/null
+++ b/Assets/CrystalFramework.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: e8572b3145bb59e4fbe17b91176d1013
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/CrystalFramework/Utility.meta b/Assets/CrystalFramework/Utility.meta
new file mode 100644
index 0000000..0136c5b
--- /dev/null
+++ b/Assets/CrystalFramework/Utility.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: b45c7b45c9256a745978ed0eb3cf5663
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/CrystalFramework/Utility/SafeArea.cs b/Assets/CrystalFramework/Utility/SafeArea.cs
new file mode 100644
index 0000000..7ac1a57
--- /dev/null
+++ b/Assets/CrystalFramework/Utility/SafeArea.cs
@@ -0,0 +1,233 @@
+using UnityEngine;
+
+namespace Crystal
+{
+ ///
+ /// Safe area implementation for notched mobile devices. Usage:
+ /// (1) Add this component to the top level of any GUI panel.
+ /// (2) If the panel uses a full screen background image, then create an immediate child and put the component on that instead, with all other elements childed below it.
+ /// This will allow the background image to stretch to the full extents of the screen behind the notch, which looks nicer.
+ /// (3) For other cases that use a mixture of full horizontal and vertical background stripes, use the Conform X & Y controls on separate elements as needed.
+ ///
+ public class SafeArea : MonoBehaviour
+ {
+ #region Simulations
+ ///
+ /// Simulation device that uses safe area due to a physical notch or software home bar. For use in Editor only.
+ ///
+ public enum SimDevice
+ {
+ ///
+ /// Don't use a simulated safe area - GUI will be full screen as normal.
+ ///
+ None,
+ ///
+ /// Simulate the iPhone X and Xs (identical safe areas).
+ ///
+ iPhoneX,
+ ///
+ /// Simulate the iPhone Xs Max and XR (identical safe areas).
+ ///
+ iPhoneXsMax,
+ ///
+ /// Simulate the Google Pixel 3 XL using landscape left.
+ ///
+ Pixel3XL_LSL,
+ ///
+ /// Simulate the Google Pixel 3 XL using landscape right.
+ ///
+ Pixel3XL_LSR
+ }
+
+ ///
+ /// Simulation mode for use in editor only. This can be edited at runtime to toggle between different safe areas.
+ ///
+ public static SimDevice Sim = SimDevice.None;
+
+ ///
+ /// Normalised safe areas for iPhone X with Home indicator (ratios are identical to Xs, 11 Pro). Absolute values:
+ /// PortraitU x=0, y=102, w=1125, h=2202 on full extents w=1125, h=2436;
+ /// PortraitD x=0, y=102, w=1125, h=2202 on full extents w=1125, h=2436 (not supported, remains in Portrait Up);
+ /// LandscapeL x=132, y=63, w=2172, h=1062 on full extents w=2436, h=1125;
+ /// LandscapeR x=132, y=63, w=2172, h=1062 on full extents w=2436, h=1125.
+ /// Aspect Ratio: ~19.5:9.
+ ///
+ Rect[] NSA_iPhoneX = new Rect[]
+ {
+ new Rect (0f, 102f / 2436f, 1f, 2202f / 2436f), // Portrait
+ new Rect (132f / 2436f, 63f / 1125f, 2172f / 2436f, 1062f / 1125f) // Landscape
+ };
+
+ ///
+ /// Normalised safe areas for iPhone Xs Max with Home indicator (ratios are identical to XR, 11, 11 Pro Max). Absolute values:
+ /// PortraitU x=0, y=102, w=1242, h=2454 on full extents w=1242, h=2688;
+ /// PortraitD x=0, y=102, w=1242, h=2454 on full extents w=1242, h=2688 (not supported, remains in Portrait Up);
+ /// LandscapeL x=132, y=63, w=2424, h=1179 on full extents w=2688, h=1242;
+ /// LandscapeR x=132, y=63, w=2424, h=1179 on full extents w=2688, h=1242.
+ /// Aspect Ratio: ~19.5:9.
+ ///
+ Rect[] NSA_iPhoneXsMax = new Rect[]
+ {
+ new Rect (0f, 102f / 2688f, 1f, 2454f / 2688f), // Portrait
+ new Rect (132f / 2688f, 63f / 1242f, 2424f / 2688f, 1179f / 1242f) // Landscape
+ };
+
+ ///
+ /// Normalised safe areas for Pixel 3 XL using landscape left. Absolute values:
+ /// PortraitU x=0, y=0, w=1440, h=2789 on full extents w=1440, h=2960;
+ /// PortraitD x=0, y=0, w=1440, h=2789 on full extents w=1440, h=2960;
+ /// LandscapeL x=171, y=0, w=2789, h=1440 on full extents w=2960, h=1440;
+ /// LandscapeR x=0, y=0, w=2789, h=1440 on full extents w=2960, h=1440.
+ /// Aspect Ratio: 18.5:9.
+ ///
+ Rect[] NSA_Pixel3XL_LSL = new Rect[]
+ {
+ new Rect (0f, 0f, 1f, 2789f / 2960f), // Portrait
+ new Rect (0f, 0f, 2789f / 2960f, 1f) // Landscape
+ };
+
+ ///
+ /// Normalised safe areas for Pixel 3 XL using landscape right. Absolute values and aspect ratio same as above.
+ ///
+ Rect[] NSA_Pixel3XL_LSR = new Rect[]
+ {
+ new Rect (0f, 0f, 1f, 2789f / 2960f), // Portrait
+ new Rect (171f / 2960f, 0f, 2789f / 2960f, 1f) // Landscape
+ };
+ #endregion
+
+ RectTransform Panel;
+ Rect LastSafeArea = new Rect (0, 0, 0, 0);
+ Vector2Int LastScreenSize = new Vector2Int (0, 0);
+ ScreenOrientation LastOrientation = ScreenOrientation.AutoRotation;
+ [SerializeField] bool ConformX = true; // Conform to screen safe area on X-axis (default true, disable to ignore)
+ [SerializeField] bool ConformY = true; // Conform to screen safe area on Y-axis (default true, disable to ignore)
+ [SerializeField] bool Logging = false; // Conform to screen safe area on Y-axis (default true, disable to ignore)
+
+ void Awake ()
+ {
+ Panel = GetComponent ();
+
+ if (Panel == null)
+ {
+ Debug.LogError ("Cannot apply safe area - no RectTransform found on " + name);
+ Destroy (gameObject);
+ }
+
+ Refresh ();
+ }
+
+ void Update ()
+ {
+ Refresh ();
+ }
+
+ void Refresh ()
+ {
+ Rect safeArea = GetSafeArea ();
+
+ if (safeArea != LastSafeArea
+ || Screen.width != LastScreenSize.x
+ || Screen.height != LastScreenSize.y
+ || Screen.orientation != LastOrientation)
+ {
+ // Fix for having auto-rotate off and manually forcing a screen orientation.
+ // See https://forum.unity.com/threads/569236/#post-4473253 and https://forum.unity.com/threads/569236/page-2#post-5166467
+ LastScreenSize.x = Screen.width;
+ LastScreenSize.y = Screen.height;
+ LastOrientation = Screen.orientation;
+
+ ApplySafeArea (safeArea);
+ }
+ }
+
+ Rect GetSafeArea ()
+ {
+ Rect safeArea = Screen.safeArea;
+
+ if (Application.isEditor && Sim != SimDevice.None)
+ {
+ Rect nsa = new Rect (0, 0, Screen.width, Screen.height);
+
+ switch (Sim)
+ {
+ case SimDevice.iPhoneX:
+ if (Screen.height > Screen.width) // Portrait
+ nsa = NSA_iPhoneX[0];
+ else // Landscape
+ nsa = NSA_iPhoneX[1];
+ break;
+ case SimDevice.iPhoneXsMax:
+ if (Screen.height > Screen.width) // Portrait
+ nsa = NSA_iPhoneXsMax[0];
+ else // Landscape
+ nsa = NSA_iPhoneXsMax[1];
+ break;
+ case SimDevice.Pixel3XL_LSL:
+ if (Screen.height > Screen.width) // Portrait
+ nsa = NSA_Pixel3XL_LSL[0];
+ else // Landscape
+ nsa = NSA_Pixel3XL_LSL[1];
+ break;
+ case SimDevice.Pixel3XL_LSR:
+ if (Screen.height > Screen.width) // Portrait
+ nsa = NSA_Pixel3XL_LSR[0];
+ else // Landscape
+ nsa = NSA_Pixel3XL_LSR[1];
+ break;
+ default:
+ break;
+ }
+
+ safeArea = new Rect (Screen.width * nsa.x, Screen.height * nsa.y, Screen.width * nsa.width, Screen.height * nsa.height);
+ }
+
+ return safeArea;
+ }
+
+ void ApplySafeArea (Rect r)
+ {
+ LastSafeArea = r;
+
+ // Ignore x-axis?
+ if (!ConformX)
+ {
+ r.x = 0;
+ r.width = Screen.width;
+ }
+
+ // Ignore y-axis?
+ if (!ConformY)
+ {
+ r.y = 0;
+ r.height = Screen.height;
+ }
+
+ // Check for invalid screen startup state on some Samsung devices (see below)
+ if (Screen.width > 0 && Screen.height > 0)
+ {
+ // Convert safe area rectangle from absolute pixels to normalised anchor coordinates
+ Vector2 anchorMin = r.position;
+ Vector2 anchorMax = r.position + r.size;
+ anchorMin.x /= Screen.width;
+ anchorMin.y /= Screen.height;
+ anchorMax.x /= Screen.width;
+ anchorMax.y /= Screen.height;
+
+ // Fix for some Samsung devices (e.g. Note 10+, A71, S20) where Refresh gets called twice and the first time returns NaN anchor coordinates
+ // See https://forum.unity.com/threads/569236/page-2#post-6199352
+ if (anchorMin.x >= 0 && anchorMin.y >= 0 && anchorMax.x >= 0 && anchorMax.y >= 0)
+ {
+ Panel.anchorMin = anchorMin;
+ Panel.anchorMax = anchorMax;
+ }
+ }
+
+ if (Logging)
+ {
+ Debug.LogFormat ("New safe area applied to {0}: x={1}, y={2}, w={3}, h={4} on full extents w={5}, h={6}",
+ name, r.x, r.y, r.width, r.height, Screen.width, Screen.height);
+ }
+ }
+ }
+}
diff --git a/Assets/CrystalFramework/Utility/SafeArea.cs.meta b/Assets/CrystalFramework/Utility/SafeArea.cs.meta
new file mode 100644
index 0000000..7c604b6
--- /dev/null
+++ b/Assets/CrystalFramework/Utility/SafeArea.cs.meta
@@ -0,0 +1,18 @@
+fileFormatVersion: 2
+guid: c97afc556caea1c44969477eb7ddec74
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+AssetOrigin:
+ serializedVersion: 1
+ productId: 130488
+ packageName: Safe Area Helper
+ packageVersion: 1.0.6
+ assetPath: Assets/CrystalFramework/Utility/SafeArea.cs
+ uploadId: 385285
diff --git a/Assets/DarkMatter/Code/Core/Contracts/ILeaderBoardController.cs b/Assets/DarkMatter/Code/Core/Contracts/ILeaderBoardController.cs
index 0ee7f33..b5eb51d 100644
--- a/Assets/DarkMatter/Code/Core/Contracts/ILeaderBoardController.cs
+++ b/Assets/DarkMatter/Code/Core/Contracts/ILeaderBoardController.cs
@@ -1,10 +1,11 @@
+using Cysharp.Threading.Tasks;
using UnityEngine;
namespace Darkmatter.Core
{
public interface ILeaderBoardController
{
- void ShowLeaderBoard();
- void UpdateLeaderBoardScore(int score);
+ UniTask ShowLeaderBoardAsync();
+ UniTask UpdateLeaderBoardScore(int score);
}
}
diff --git a/Assets/DarkMatter/Code/Core/CoreAssembly.asmdef b/Assets/DarkMatter/Code/Core/CoreAssembly.asmdef
index 0f01b10..ea2ccda 100644
--- a/Assets/DarkMatter/Code/Core/CoreAssembly.asmdef
+++ b/Assets/DarkMatter/Code/Core/CoreAssembly.asmdef
@@ -4,7 +4,8 @@
"references": [
"GUID:4307f53044263cf4b835bd812fc161a4",
"GUID:b0214a6008ed146ff8f122a6a9c2f6cc",
- "GUID:75469ad4d38634e559750d17036d5f7c"
+ "GUID:75469ad4d38634e559750d17036d5f7c",
+ "GUID:f51ebe6a0ceec4240a699833d6309b23"
],
"includePlatforms": [],
"excludePlatforms": [],
diff --git a/Assets/DarkMatter/Code/Domain/GenericPool.meta b/Assets/DarkMatter/Code/Domain/GenericPool.meta
new file mode 100644
index 0000000..b36c544
--- /dev/null
+++ b/Assets/DarkMatter/Code/Domain/GenericPool.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 75a2920ba3d7abc4b94a5b95351e7dac
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/DarkMatter/Code/Domain/GenericPool/ObjectPool.cs b/Assets/DarkMatter/Code/Domain/GenericPool/ObjectPool.cs
new file mode 100644
index 0000000..d2ccfb9
--- /dev/null
+++ b/Assets/DarkMatter/Code/Domain/GenericPool/ObjectPool.cs
@@ -0,0 +1,57 @@
+using Darkmatter.Core;
+using System.Collections.Generic;
+using UnityEngine;
+using VContainer;
+using VContainer.Unity;
+
+namespace Darkmatter.Domain
+{
+ public class ObjectPool : MonoBehaviour,IPool where T : Component
+ {
+ [SerializeField] T prefab;
+ [SerializeField] private Transform prefabParent;
+ [SerializeField] private int poolSize = 15;
+
+ public Queue pool = new Queue();
+ [Inject] IObjectResolver resolver;
+
+ public IReadOnlyCollection All => pool;
+
+ private void Awake()
+ {
+ CreateObjectPool();
+ }
+
+ private void CreateObjectPool()
+ {
+ for(int i=0;i