├── UpgradeLog.htm ├── GIFs ├── CoverFlow.gif ├── CarouselFlow.gif ├── CoverFlowEditor.gif └── MessyPaperFlow.gif ├── Assets ├── Scenes │ ├── Test │ │ ├── CoverFlow.unity │ │ └── CoverFlow.unity.meta │ └── Test.meta ├── Plugins.meta ├── Prefabs.meta ├── Scenes.meta ├── Scripts.meta ├── Prefabs │ ├── UI.meta │ └── UI │ │ ├── CollectionViewCells │ │ ├── TestCell.prefab │ │ ├── TestCell.prefab.meta │ │ ├── TestNGUICell.prefab.meta │ │ └── TestNGUICell.prefab │ │ └── CollectionViewCells.meta ├── Scripts │ ├── UI.meta │ ├── Utility.meta │ ├── UI │ │ ├── CollectionView.meta │ │ └── CollectionView │ │ │ ├── Test.meta │ │ │ ├── CollectionViewCell.meta │ │ │ ├── CollectionViewLayout.meta │ │ │ ├── CellPoolService.cs.meta │ │ │ ├── Test │ │ │ ├── TestFlows.cs.meta │ │ │ └── TestFlows.cs │ │ │ ├── UICollectionView.cs.meta │ │ │ ├── CollectionViewCell │ │ │ ├── NGUICell.cs.meta │ │ │ ├── QuadCell.cs.meta │ │ │ ├── UICollectionCell.cs.meta │ │ │ ├── NGUICell.cs │ │ │ ├── QuadCell.cs │ │ │ └── UICollectionCell.cs │ │ │ ├── CollectionViewLayout │ │ │ ├── CoverFlowLayout.cs.meta │ │ │ ├── DepthFlowLayout.cs.meta │ │ │ ├── CarouselFlowLayout.cs.meta │ │ │ ├── CollectionViewLayout.cs.meta │ │ │ ├── MessyPaperFlowLayout.cs.meta │ │ │ ├── CarouselFlowLayout.cs │ │ │ ├── DepthFlowLayout.cs │ │ │ ├── CoverFlowLayout.cs │ │ │ ├── MessyPaperFlowLayout.cs │ │ │ └── CollectionViewLayout.cs │ │ │ ├── CellPoolService.cs │ │ │ └── UICollectionView.cs │ └── Utility │ │ ├── Singleton.cs.meta │ │ ├── MethodExtensionForMonoBehaviourTransform.cs.meta │ │ ├── MethodExtensionForMonoBehaviourTransform.cs │ │ └── Singleton.cs └── Plugins │ ├── Pixelplacement.meta │ └── Pixelplacement │ ├── iTween.meta │ └── iTween │ ├── Sample │ ├── Sample.unity.meta │ ├── Sample.unity │ ├── MoveSample.cs.meta │ ├── SampleInfo.cs.meta │ ├── RotateSample.cs.meta │ ├── MoveSample.cs │ ├── RotateSample.cs │ └── SampleInfo.cs │ ├── ReadMe! │ ├── ReadMe!.txt.meta │ └── ReadMe!.txt │ ├── ReadMe!.meta │ ├── Sample.meta │ └── iTween.cs.meta ├── ProjectSettings ├── AudioManager.asset ├── InputManager.asset ├── NavMeshAreas.asset ├── ProjectVersion.txt ├── TagManager.asset ├── TimeManager.asset ├── VFXManager.asset ├── EditorSettings.asset ├── NavMeshLayers.asset ├── NetworkManager.asset ├── PresetManager.asset ├── DynamicsManager.asset ├── GraphicsSettings.asset ├── Physics2DSettings.asset ├── ProjectSettings.asset ├── QualitySettings.asset ├── ClusterInputManager.asset ├── EditorBuildSettings.asset ├── UnityConnectSettings.asset └── XRSettings.asset ├── .gitignore ├── LICENSE ├── Packages └── manifest.json └── README.md /UpgradeLog.htm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IainS1986/UnityCoverFlow/HEAD/UpgradeLog.htm -------------------------------------------------------------------------------- /GIFs/CoverFlow.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IainS1986/UnityCoverFlow/HEAD/GIFs/CoverFlow.gif -------------------------------------------------------------------------------- /GIFs/CarouselFlow.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IainS1986/UnityCoverFlow/HEAD/GIFs/CarouselFlow.gif -------------------------------------------------------------------------------- /GIFs/CoverFlowEditor.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IainS1986/UnityCoverFlow/HEAD/GIFs/CoverFlowEditor.gif -------------------------------------------------------------------------------- /GIFs/MessyPaperFlow.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IainS1986/UnityCoverFlow/HEAD/GIFs/MessyPaperFlow.gif -------------------------------------------------------------------------------- /Assets/Scenes/Test/CoverFlow.unity: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IainS1986/UnityCoverFlow/HEAD/Assets/Scenes/Test/CoverFlow.unity -------------------------------------------------------------------------------- /ProjectSettings/AudioManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IainS1986/UnityCoverFlow/HEAD/ProjectSettings/AudioManager.asset -------------------------------------------------------------------------------- /ProjectSettings/InputManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IainS1986/UnityCoverFlow/HEAD/ProjectSettings/InputManager.asset -------------------------------------------------------------------------------- /ProjectSettings/NavMeshAreas.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IainS1986/UnityCoverFlow/HEAD/ProjectSettings/NavMeshAreas.asset -------------------------------------------------------------------------------- /ProjectSettings/ProjectVersion.txt: -------------------------------------------------------------------------------- 1 | m_EditorVersion: 2019.2.8f1 2 | m_EditorVersionWithRevision: 2019.2.8f1 (ff5b465c8d13) 3 | -------------------------------------------------------------------------------- /ProjectSettings/TagManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IainS1986/UnityCoverFlow/HEAD/ProjectSettings/TagManager.asset -------------------------------------------------------------------------------- /ProjectSettings/TimeManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IainS1986/UnityCoverFlow/HEAD/ProjectSettings/TimeManager.asset -------------------------------------------------------------------------------- /ProjectSettings/VFXManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IainS1986/UnityCoverFlow/HEAD/ProjectSettings/VFXManager.asset -------------------------------------------------------------------------------- /ProjectSettings/EditorSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IainS1986/UnityCoverFlow/HEAD/ProjectSettings/EditorSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/NavMeshLayers.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IainS1986/UnityCoverFlow/HEAD/ProjectSettings/NavMeshLayers.asset -------------------------------------------------------------------------------- /ProjectSettings/NetworkManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IainS1986/UnityCoverFlow/HEAD/ProjectSettings/NetworkManager.asset -------------------------------------------------------------------------------- /ProjectSettings/PresetManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IainS1986/UnityCoverFlow/HEAD/ProjectSettings/PresetManager.asset -------------------------------------------------------------------------------- /ProjectSettings/DynamicsManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IainS1986/UnityCoverFlow/HEAD/ProjectSettings/DynamicsManager.asset -------------------------------------------------------------------------------- /ProjectSettings/GraphicsSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IainS1986/UnityCoverFlow/HEAD/ProjectSettings/GraphicsSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/Physics2DSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IainS1986/UnityCoverFlow/HEAD/ProjectSettings/Physics2DSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/ProjectSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IainS1986/UnityCoverFlow/HEAD/ProjectSettings/ProjectSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/QualitySettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IainS1986/UnityCoverFlow/HEAD/ProjectSettings/QualitySettings.asset -------------------------------------------------------------------------------- /ProjectSettings/ClusterInputManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IainS1986/UnityCoverFlow/HEAD/ProjectSettings/ClusterInputManager.asset -------------------------------------------------------------------------------- /ProjectSettings/EditorBuildSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IainS1986/UnityCoverFlow/HEAD/ProjectSettings/EditorBuildSettings.asset -------------------------------------------------------------------------------- /Assets/Plugins.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f946331c7bdbfec4d97d66d3b9bc87cb 3 | folderAsset: yes 4 | DefaultImporter: 5 | userData: 6 | -------------------------------------------------------------------------------- /Assets/Prefabs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b8464488d3099624d947efc532e5c6bb 3 | folderAsset: yes 4 | DefaultImporter: 5 | userData: 6 | -------------------------------------------------------------------------------- /Assets/Scenes.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b2cbd6abc3d262c42a1d3962b1898b15 3 | folderAsset: yes 4 | DefaultImporter: 5 | userData: 6 | -------------------------------------------------------------------------------- /Assets/Scenes/Test/CoverFlow.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 211d294c7498644de98979365e34ae7a 3 | DefaultImporter: 4 | userData: 5 | -------------------------------------------------------------------------------- /Assets/Scripts.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b6f5e29a1e4d09e4b92c96b06b0c827d 3 | folderAsset: yes 4 | DefaultImporter: 5 | userData: 6 | -------------------------------------------------------------------------------- /ProjectSettings/UnityConnectSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IainS1986/UnityCoverFlow/HEAD/ProjectSettings/UnityConnectSettings.asset -------------------------------------------------------------------------------- /Assets/Prefabs/UI.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c87169828b7c1fc4a9e0ca2ea6ce8dd0 3 | folderAsset: yes 4 | DefaultImporter: 5 | userData: 6 | -------------------------------------------------------------------------------- /Assets/Scenes/Test.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8d53979fb68a30843a35618919ff8ced 3 | folderAsset: yes 4 | DefaultImporter: 5 | userData: 6 | -------------------------------------------------------------------------------- /Assets/Scripts/UI.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 38bfe78013e04654491dcfa16772cf1f 3 | folderAsset: yes 4 | DefaultImporter: 5 | userData: 6 | -------------------------------------------------------------------------------- /Assets/Scripts/Utility.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b683a66de7489a54494387814f101b69 3 | folderAsset: yes 4 | DefaultImporter: 5 | userData: 6 | -------------------------------------------------------------------------------- /Assets/Plugins/Pixelplacement.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8a34e0eeedd2b4bb7a52529c26d5fd03 3 | folderAsset: yes 4 | DefaultImporter: 5 | userData: 6 | -------------------------------------------------------------------------------- /Assets/Plugins/Pixelplacement/iTween.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 62c61d3ebfdbc4210b98849503e254dc 3 | folderAsset: yes 4 | DefaultImporter: 5 | userData: 6 | -------------------------------------------------------------------------------- /Assets/Plugins/Pixelplacement/iTween/Sample/Sample.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 17c6d1d46ed4a4cd19bb7f7a231386ba 3 | DefaultImporter: 4 | userData: 5 | -------------------------------------------------------------------------------- /Assets/Prefabs/UI/CollectionViewCells/TestCell.prefab: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IainS1986/UnityCoverFlow/HEAD/Assets/Prefabs/UI/CollectionViewCells/TestCell.prefab -------------------------------------------------------------------------------- /Assets/Scripts/UI/CollectionView.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: cbb585d901976489a90b0006f7f10022 3 | folderAsset: yes 4 | DefaultImporter: 5 | userData: 6 | -------------------------------------------------------------------------------- /Assets/Plugins/Pixelplacement/iTween/ReadMe!/ReadMe!.txt.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b68b11cac1ab04f95985e32ea67b8435 3 | TextScriptImporter: 4 | userData: 5 | -------------------------------------------------------------------------------- /Assets/Plugins/Pixelplacement/iTween/Sample/Sample.unity: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IainS1986/UnityCoverFlow/HEAD/Assets/Plugins/Pixelplacement/iTween/Sample/Sample.unity -------------------------------------------------------------------------------- /Assets/Prefabs/UI/CollectionViewCells.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5c18ace4cc95a494892ba64fbd33a945 3 | folderAsset: yes 4 | DefaultImporter: 5 | userData: 6 | -------------------------------------------------------------------------------- /Assets/Prefabs/UI/CollectionViewCells/TestCell.prefab.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c51b2d39edec0400ea0c1a09cb73ff3f 3 | NativeFormatImporter: 4 | userData: 5 | -------------------------------------------------------------------------------- /Assets/Prefabs/UI/CollectionViewCells/TestNGUICell.prefab.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e651f0433145d4ce5b479184f84af2c0 3 | NativeFormatImporter: 4 | userData: 5 | -------------------------------------------------------------------------------- /Assets/Scripts/UI/CollectionView/Test.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1dbf0b40322aa42709d0d0eac1dfed66 3 | folderAsset: yes 4 | DefaultImporter: 5 | userData: 6 | -------------------------------------------------------------------------------- /Assets/Plugins/Pixelplacement/iTween/ReadMe!.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2d2cb0af9aa924b12bd57127320643a3 3 | folderAsset: yes 4 | DefaultImporter: 5 | userData: 6 | -------------------------------------------------------------------------------- /Assets/Plugins/Pixelplacement/iTween/Sample.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2b4957ecfb9d44cb59b99d2305c1848c 3 | folderAsset: yes 4 | DefaultImporter: 5 | userData: 6 | -------------------------------------------------------------------------------- /Assets/Prefabs/UI/CollectionViewCells/TestNGUICell.prefab: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IainS1986/UnityCoverFlow/HEAD/Assets/Prefabs/UI/CollectionViewCells/TestNGUICell.prefab -------------------------------------------------------------------------------- /Assets/Scripts/UI/CollectionView/CollectionViewCell.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3406ddb33bb524e9db6e84bb9b805804 3 | folderAsset: yes 4 | DefaultImporter: 5 | userData: 6 | -------------------------------------------------------------------------------- /Assets/Scripts/UI/CollectionView/CollectionViewLayout.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 78465a3afd0ed45229cef31b4dea16a8 3 | folderAsset: yes 4 | DefaultImporter: 5 | userData: 6 | -------------------------------------------------------------------------------- /ProjectSettings/XRSettings.asset: -------------------------------------------------------------------------------- 1 | { 2 | "m_SettingKeys": [ 3 | "VR Device Disabled", 4 | "VR Device User Alert" 5 | ], 6 | "m_SettingValues": [ 7 | "False", 8 | "False" 9 | ] 10 | } -------------------------------------------------------------------------------- /Assets/Scripts/Utility/Singleton.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 65652d08692c943d694604f75c1e7edb 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /Assets/Plugins/Pixelplacement/iTween/iTween.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 521257714fc9e437a9163df2d37f2ea2 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /Assets/Scripts/UI/CollectionView/CellPoolService.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f87fbfe9741e14fdb85afd0abfb916cc 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /Assets/Scripts/UI/CollectionView/Test/TestFlows.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6f8d9b0a3d3f94f0a8a32353610035cb 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /Assets/Scripts/UI/CollectionView/UICollectionView.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3857d969918444e52adfd995b7f97c0e 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /Assets/Plugins/Pixelplacement/iTween/Sample/MoveSample.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 93cb45d44c16f45a4bbd5099fe096c20 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /Assets/Plugins/Pixelplacement/iTween/Sample/SampleInfo.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5273cf41de20842a5917d8346dffe707 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /Assets/Plugins/Pixelplacement/iTween/Sample/RotateSample.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d6bc01eb564f142a1ada6ced5215636a 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /Assets/Scripts/UI/CollectionView/CollectionViewCell/NGUICell.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: dec1488defea143138ed531055ad20fc 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /Assets/Scripts/UI/CollectionView/CollectionViewCell/QuadCell.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7b5d71bb3ac0e4fe38594c6058e70c35 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /Assets/Scripts/Utility/MethodExtensionForMonoBehaviourTransform.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a26ec03e8bb57488d8b2900039c03698 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /Assets/Scripts/UI/CollectionView/CollectionViewCell/UICollectionCell.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 166b079b5236643abb051203ef7ac785 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /Assets/Scripts/UI/CollectionView/CollectionViewLayout/CoverFlowLayout.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7fb57aa9664df4afb9b55639cc3261e8 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /Assets/Scripts/UI/CollectionView/CollectionViewLayout/DepthFlowLayout.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5f8349b47b89e0b49805360ba72d912d 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /Assets/Scripts/UI/CollectionView/CollectionViewLayout/CarouselFlowLayout.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: da027aa820f0d406a987a6ac0a7709de 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /Assets/Scripts/UI/CollectionView/CollectionViewLayout/CollectionViewLayout.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 80c927a3c41b4401da3642cefa54bbaa 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /Assets/Scripts/UI/CollectionView/CollectionViewLayout/MessyPaperFlowLayout.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7ab9928d594744b469dff0d25c07746b 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /Assets/Plugins/Pixelplacement/iTween/Sample/MoveSample.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | 4 | public class MoveSample : MonoBehaviour 5 | { 6 | void Start(){ 7 | iTween.MoveBy(gameObject, iTween.Hash("x", 2, "easeType", "easeInOutExpo", "loopType", "pingPong", "delay", .1)); 8 | } 9 | } 10 | 11 | -------------------------------------------------------------------------------- /Assets/Plugins/Pixelplacement/iTween/Sample/RotateSample.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | 4 | public class RotateSample : MonoBehaviour 5 | { 6 | void Start(){ 7 | iTween.RotateBy(gameObject, iTween.Hash("x", .25, "easeType", "easeInOutBack", "loopType", "pingPong", "delay", .4)); 8 | } 9 | } 10 | 11 | -------------------------------------------------------------------------------- /Assets/Plugins/Pixelplacement/iTween/ReadMe!/ReadMe!.txt: -------------------------------------------------------------------------------- 1 | iTween can be used with all scripting languages that Unity supports including JavaScript, C# and Boo. To install iTween create a folder named "Plugins" in your project's assets (if you are using C# the location of iTween does not matter as long as it is inside your assets folder). 2 | 3 | For complete documentation, examples and information visit: http://itween.pixelplacement.com -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /[Ll]ibrary/ 2 | /[Tt]emp/ 3 | /[Oo]bj/ 4 | /[Bb]uild/ 5 | /[Bb]uilds/ 6 | /Assets/AssetStoreTools* 7 | 8 | # Visual Studio 2015 cache directory 9 | /.vs/ 10 | 11 | # Autogenerated VS/MD/Consulo solution and project files 12 | ExportedObj/ 13 | .consulo/ 14 | *.csproj 15 | *.unityproj 16 | *.sln 17 | *.suo 18 | *.tmp 19 | *.user 20 | *.userprefs 21 | *.pidb 22 | *.booproj 23 | *.svd 24 | *.pdb 25 | 26 | # Unity3D generated meta files 27 | *.pidb.meta 28 | 29 | # Unity3D Generated File On Crash Reports 30 | sysinfo.txt 31 | 32 | # Builds 33 | *.apk 34 | *.unitypackage 35 | -------------------------------------------------------------------------------- /Assets/Scripts/Utility/MethodExtensionForMonoBehaviourTransform.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | 4 | static public class MethodExtensionForMonoBehaviourTransform { 5 | /// 6 | /// Gets or add a component. Usage example: 7 | /// BoxCollider boxCollider = transform.GetOrAddComponent(); 8 | /// 9 | static public T GetOrAddComponent (this Component child) where T: Component { 10 | T result = child.GetComponent(); 11 | if (result == null) { 12 | result = child.gameObject.AddComponent(); 13 | } 14 | return result; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Assets/Plugins/Pixelplacement/iTween/Sample/SampleInfo.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | 4 | public class SampleInfo : MonoBehaviour 5 | { 6 | void OnGUI(){ 7 | GUILayout.Label("iTween can spin, shake, punch, move, handle audio, fade color and transparency \nand much more with each task needing only one line of code."); 8 | GUILayout.BeginHorizontal(); 9 | GUILayout.Label("iTween works with C#, JavaScript and Boo. For full documentation and examples visit:"); 10 | if(GUILayout.Button("http://itween.pixelplacement.com")){ 11 | Application.OpenURL("http://itween.pixelplacement.com"); 12 | } 13 | GUILayout.EndHorizontal(); 14 | } 15 | } 16 | 17 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 IainS1986 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Assets/Scripts/UI/CollectionView/CollectionViewCell/NGUICell.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using System; 4 | 5 | public class NGUICell : iCollectionViewCell { 6 | 7 | public int index; 8 | 9 | public void Update() 10 | { 11 | index = Index; 12 | } 13 | 14 | public override string NibName 15 | { 16 | get 17 | { 18 | return "NGUICell"; 19 | } 20 | } 21 | 22 | Material m_material; 23 | Renderer m_renderer; 24 | 25 | public override void SetData(object data) 26 | { 27 | base.SetData(data); 28 | 29 | if(m_renderer==null) 30 | m_renderer = GetComponent(); 31 | 32 | if(m_renderer!=null && m_material==null) 33 | { 34 | m_material = m_renderer.material; 35 | } 36 | 37 | //Set Color 38 | if(m_material!=null) 39 | { 40 | QuadCell.QuadCellData quadData = data as QuadCell.QuadCellData; 41 | if(quadData!=null && quadData.MainColor != null) 42 | { 43 | m_material.color = quadData.MainColor; 44 | m_renderer.material = m_material; 45 | } 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Assets/Scripts/UI/CollectionView/Test/TestFlows.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | 5 | public class TestFlows : MonoBehaviour { 6 | 7 | [SerializeField] 8 | private UICollectionView m_coverFlow; 9 | 10 | [SerializeField] 11 | private Color[] m_colourData; 12 | 13 | [SerializeField] 14 | private int m_numberOfCells = 10; 15 | 16 | [SerializeField] 17 | private int m_groupSizes = 10; 18 | 19 | // Use this for initialization 20 | void Start () 21 | { 22 | //Build cells 23 | if(m_coverFlow!=null) 24 | { 25 | //Build a bunch of cells - pass in data 26 | List data = new List(); 27 | for (int i = 0; i < m_numberOfCells; i++) 28 | { 29 | if(m_colourData!=null && m_colourData.Length > 0) 30 | { 31 | data.Add(new QuadCell.QuadCellData() { MainColor = m_colourData[(i / m_groupSizes) % m_colourData.Length] }); 32 | } 33 | else 34 | { 35 | data.Add(new QuadCell.QuadCellData()); 36 | } 37 | 38 | } 39 | 40 | //Bleugh 41 | m_coverFlow.Data = new List(data.ToArray()); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Assets/Scripts/UI/CollectionView/CollectionViewCell/QuadCell.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | 4 | public class QuadCell : iCollectionViewCell 5 | { 6 | //This was needed as Color can't be null 7 | public class QuadCellData 8 | { 9 | private Color m_color; 10 | public Color MainColor 11 | { 12 | get { return m_color; } 13 | set { m_color = value; } 14 | } 15 | } 16 | 17 | public int index; 18 | 19 | public void Update() 20 | { 21 | index = Index; 22 | } 23 | 24 | public override string NibName 25 | { 26 | get 27 | { 28 | return "QuadCell"; 29 | } 30 | } 31 | 32 | Material m_material; 33 | Renderer m_renderer; 34 | 35 | public override void SetData(object data) 36 | { 37 | base.SetData(data); 38 | 39 | if(m_renderer==null) 40 | m_renderer = GetComponent(); 41 | 42 | if(m_renderer!=null && m_material==null) 43 | { 44 | m_material = m_renderer.material; 45 | } 46 | 47 | //Set Color 48 | if(m_material!=null) 49 | { 50 | QuadCellData quadData = data as QuadCellData; 51 | if(quadData!=null && quadData.MainColor != null) 52 | { 53 | m_material.color = quadData.MainColor; 54 | m_renderer.material = m_material; 55 | } 56 | } 57 | } 58 | 59 | } 60 | 61 | -------------------------------------------------------------------------------- /Packages/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "com.unity.collab-proxy": "1.2.16", 4 | "com.unity.ext.nunit": "1.0.0", 5 | "com.unity.ide.rider": "1.1.0", 6 | "com.unity.ide.vscode": "1.1.2", 7 | "com.unity.package-manager-ui": "2.2.0", 8 | "com.unity.test-framework": "1.0.13", 9 | "com.unity.textmeshpro": "2.0.1", 10 | "com.unity.timeline": "1.1.0", 11 | "com.unity.ugui": "1.0.0", 12 | "com.unity.modules.ai": "1.0.0", 13 | "com.unity.modules.androidjni": "1.0.0", 14 | "com.unity.modules.animation": "1.0.0", 15 | "com.unity.modules.assetbundle": "1.0.0", 16 | "com.unity.modules.audio": "1.0.0", 17 | "com.unity.modules.cloth": "1.0.0", 18 | "com.unity.modules.director": "1.0.0", 19 | "com.unity.modules.imageconversion": "1.0.0", 20 | "com.unity.modules.imgui": "1.0.0", 21 | "com.unity.modules.jsonserialize": "1.0.0", 22 | "com.unity.modules.particlesystem": "1.0.0", 23 | "com.unity.modules.physics": "1.0.0", 24 | "com.unity.modules.physics2d": "1.0.0", 25 | "com.unity.modules.screencapture": "1.0.0", 26 | "com.unity.modules.terrain": "1.0.0", 27 | "com.unity.modules.terrainphysics": "1.0.0", 28 | "com.unity.modules.tilemap": "1.0.0", 29 | "com.unity.modules.ui": "1.0.0", 30 | "com.unity.modules.uielements": "1.0.0", 31 | "com.unity.modules.umbra": "1.0.0", 32 | "com.unity.modules.unityanalytics": "1.0.0", 33 | "com.unity.modules.unitywebrequest": "1.0.0", 34 | "com.unity.modules.unitywebrequestassetbundle": "1.0.0", 35 | "com.unity.modules.unitywebrequestaudio": "1.0.0", 36 | "com.unity.modules.unitywebrequesttexture": "1.0.0", 37 | "com.unity.modules.unitywebrequestwww": "1.0.0", 38 | "com.unity.modules.vehicles": "1.0.0", 39 | "com.unity.modules.video": "1.0.0", 40 | "com.unity.modules.vr": "1.0.0", 41 | "com.unity.modules.wind": "1.0.0", 42 | "com.unity.modules.xr": "1.0.0" 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Assets/Scripts/UI/CollectionView/CollectionViewCell/UICollectionCell.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using System; 4 | 5 | public abstract class iCollectionViewCell : MonoBehaviour 6 | { 7 | public abstract string NibName { get; } 8 | 9 | public EventHandler OnClickEvent; 10 | 11 | public int Index { get; set; } 12 | 13 | public bool Snap { get; set; } 14 | 15 | public float FlowIndexOffset { get; set; } 16 | 17 | public bool IsActive { get; set; } 18 | 19 | public object Data { get; set; } 20 | 21 | public iCollectionViewCell CreateCell() 22 | { 23 | return (iCollectionViewCell)Instantiate(this); 24 | } 25 | 26 | public void OnMouseUpAsButton() 27 | { 28 | if(OnClickEvent!=null) 29 | { 30 | OnClickEvent(this, EventArgs.Empty); 31 | } 32 | } 33 | 34 | public void OnClick() 35 | { 36 | if(OnClickEvent != null) 37 | { 38 | OnClickEvent(this, EventArgs.Empty); 39 | } 40 | } 41 | 42 | public void SetActive(bool active, GameObject owner = null) 43 | { 44 | if(active) 45 | { 46 | if(owner!=null) 47 | transform.parent = owner.transform; 48 | 49 | OnCellReuse(); 50 | } 51 | else 52 | { 53 | OnCellDestroy(); 54 | } 55 | } 56 | 57 | //This will happen before Start! 58 | public virtual void SetData(object data) 59 | { 60 | Data = data; 61 | } 62 | 63 | protected virtual void OnCellDestroy() 64 | { 65 | IsActive = false; 66 | Data = null; 67 | OnClickEvent = null; 68 | Index = 0; 69 | FlowIndexOffset = 0; 70 | transform.parent = CellPoolService.Instance.transform; 71 | gameObject.SetActive(false); 72 | } 73 | 74 | //Called whena cell is reactivated or created 75 | protected virtual void OnCellReuse() 76 | { 77 | IsActive = true; 78 | gameObject.SetActive(true); 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # UnityCoverFlow 2 | Unity3D UI CoverFlow and other Layout options 3 | 4 | # Overview 5 | Some years ago I was required to build a simple Cover Flow Layout (think, iTunes Carousel). Originally I build the project in a Windows Forms application for a client we were working with. Sometime later we then needed a similar system in a project we were doing in Unity3D. 6 | 7 | This is just a simple recreation of that work. 8 | 9 | Its very old, and it wasn't originally done in GitHub so I've just commited the whole project in one commit. 10 | 11 | There are some simple layouts included to demonstrate the flexibility of the system, 12 | 13 | * The classic Cover Flow layout (iTunes Album Artwork style) 14 | * A Carousel Layout (Z-Depth carousel) 15 | * A "Messy Paper" Layout - Cells shift from 1 messy pile to another 16 | 17 | # Further Features 18 | Cell reuse is supported using a simple Cell Pool with UICollectionCells registering Prefabs as "nibs" to be reused. 19 | 20 | Data "binding" can be expanded upon with the cell reuse. 21 | 22 | All layouts have various settings to tweak positions, speeds, snapping, wrapping and the like. These can also be updated at runtime in the editor to see results in real time. 23 | 24 | 25 | # Demos 26 | 27 | Here's a few GIFs showing the layouts in action in the editor (GIFs are only at 30fps and appear to have bad artifacts in them, running in the editor is obviously at full FPS with no rendering issues). 28 | 29 | * Cover Flow Layout 30 | ![Cover Flow](https://github.com/IainS1986/UnityCoverFlow/blob/master/GIFs/CoverFlow.gif) 31 | 32 | * Carousel Layout 33 | ![Carousel Flow](https://github.com/IainS1986/UnityCoverFlow/blob/master/GIFs/CarouselFlow.gif) 34 | 35 | * Messy Paper Layout 36 | ![Messy Paper Flow](https://github.com/IainS1986/UnityCoverFlow/blob/master/GIFs/MessyPaperFlow.gif) 37 | 38 | * Layouts can have multiple configurable elements, here's an example of the Cover Flow properties being edited at runtime... 39 | ![Editable Properties](https://github.com/IainS1986/UnityCoverFlow/blob/master/GIFs/CoverFlowEditor.gif) -------------------------------------------------------------------------------- /Assets/Scripts/UI/CollectionView/CellPoolService.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | 4 | //Has to be a monobehaviour as this acts as a "physical" pool of the cells too 5 | using System.Collections.Generic; 6 | 7 | 8 | public class CellPoolService : Singleton { 9 | 10 | //Prefabs 11 | private Dictionary m_nibs; 12 | 13 | //Pools 14 | private Dictionary> m_pools; 15 | 16 | //Guarantee this will always be a singleton only 17 | protected CellPoolService() 18 | { 19 | m_nibs = new Dictionary(); 20 | m_pools = new Dictionary>(); 21 | } 22 | 23 | //This will overwrite any previously registered! 24 | public void RegisterCell(iCollectionViewCell prefab) 25 | { 26 | if(m_nibs.ContainsKey(prefab.NibName)) 27 | { 28 | m_nibs[prefab.NibName] = prefab; 29 | } 30 | else 31 | { 32 | m_nibs.Add(prefab.NibName, prefab); 33 | } 34 | } 35 | public void RegisterCellForNib(iCollectionViewCell prefab, string nib) 36 | { 37 | if(m_nibs.ContainsKey(nib)) 38 | { 39 | m_nibs[nib] = prefab; 40 | } 41 | else 42 | { 43 | m_nibs.Add(nib, prefab); 44 | } 45 | } 46 | 47 | public iCollectionViewCell CreateCell(string nib, GameObject owner = null) 48 | { 49 | //Check we have nib registered 50 | if(!m_nibs.ContainsKey(nib)) 51 | throw new UnityException(string.Format("No Prefab registered for {0}", nib)); 52 | 53 | //Check pool 54 | if(m_pools.ContainsKey(nib)) 55 | { 56 | List pool = m_pools[nib]; 57 | 58 | //Check for any not being used 59 | foreach(iCollectionViewCell cell in pool) 60 | { 61 | if(!cell.IsActive) 62 | { 63 | cell.SetActive(true, owner); 64 | return cell; 65 | } 66 | } 67 | 68 | } 69 | else 70 | { 71 | //Make Pool 72 | m_pools.Add(nib, new List()); 73 | } 74 | 75 | //No free cells, so make a new one 76 | iCollectionViewCell c = m_nibs[nib].CreateCell(); 77 | c.SetActive(true, owner); 78 | 79 | m_pools[nib].Add(c); 80 | 81 | return c; 82 | } 83 | 84 | } 85 | -------------------------------------------------------------------------------- /Assets/Scripts/UI/CollectionView/CollectionViewLayout/CarouselFlowLayout.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using System; 4 | 5 | public class CarouselFlowLayout : CollectionViewLayout 6 | { 7 | [SerializeField] 8 | private float m_width = 10; 9 | 10 | [SerializeField] 11 | private float m_depth = 10; 12 | 13 | public override bool IndexWrap { get { return true; } } 14 | 15 | private double Angle { get; set; } 16 | 17 | #if UNITY_EDITOR 18 | private float m_lastTime; 19 | private float m_lastWidth, m_lastDepth; 20 | #endif 21 | 22 | #if UNITY_EDITOR 23 | void Awake() 24 | { 25 | m_lastTime = m_animTime; 26 | m_lastWidth = m_width; 27 | m_lastDepth = m_depth; 28 | } 29 | #endif 30 | 31 | #if UNITY_EDITOR 32 | void Update() 33 | { 34 | if(m_lastTime != m_animTime || 35 | m_lastDepth != m_depth || 36 | m_lastWidth != m_width) 37 | { 38 | //Relayout 39 | RequiresRelayout = true; 40 | 41 | m_lastTime = m_animTime; 42 | m_lastDepth = m_depth; 43 | m_lastWidth = m_width; 44 | } 45 | } 46 | #endif 47 | 48 | protected override void PreLayout(System.Collections.Generic.List data, System.Collections.Generic.List cells, bool dragging) 49 | { 50 | base.PreLayout(data, cells, dragging); 51 | 52 | //Work out Cost and Sint 53 | int totalCells = Math.Min(cells.Count, TotalCellsNeeded); 54 | totalCells += (totalCells / 3) + ((totalCells % 2 == 1) ? 1 : 0); 55 | Angle = (2 * Math.PI) / totalCells; 56 | } 57 | 58 | protected override Vector3 EulerAngle(float indexOffset, int cellIndex) 59 | { 60 | return new Vector3(0,0,0); 61 | } 62 | 63 | protected override Vector3 Position(float indexOffset, int cellIndex) 64 | { 65 | return new Vector3(TranslationX(indexOffset), 66 | TranslationY(indexOffset), 67 | TranslationZ(indexOffset)); 68 | } 69 | 70 | protected override Vector3 Scale(float indexOffset, int cellIndex) 71 | { 72 | return new Vector3(1, 1, 1); 73 | } 74 | 75 | private float TranslationX(float indexOffset) 76 | { 77 | return (float) (m_width * Math.Sin(Angle * indexOffset)); 78 | } 79 | 80 | private float TranslationY(float indexOffset) 81 | { 82 | return 0; 83 | } 84 | 85 | private float TranslationZ(float indexOffset) 86 | { 87 | return (float) (-m_depth * Math.Cos(Angle * indexOffset)) + m_depth; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /Assets/Scripts/Utility/Singleton.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | /// 4 | /// Be aware this will not prevent a non singleton constructor 5 | /// such as `T myT = new T();` 6 | /// To prevent that, add `protected T () {}` to your singleton class. 7 | /// 8 | /// A monobehaviour Singleton 9 | /// 10 | public class Singleton : MonoBehaviour where T : MonoBehaviour 11 | { 12 | private static T _instance; 13 | 14 | private static object _lock = new object(); 15 | 16 | public static T Instance 17 | { 18 | get 19 | { 20 | if (applicationIsQuitting) { 21 | Debug.LogWarning("[Singleton] Instance '"+ typeof(T) + 22 | "' already destroyed on application quit." + 23 | " Won't create again - returning null."); 24 | return null; 25 | } 26 | 27 | lock(_lock) 28 | { 29 | if (_instance == null) 30 | { 31 | _instance = (T) FindObjectOfType(typeof(T)); 32 | 33 | if ( FindObjectsOfType(typeof(T)).Length > 1 ) 34 | { 35 | Debug.LogError("[Singleton] Something went really wrong " + 36 | " - there should never be more than 1 singleton!" + 37 | " Reopenning the scene might fix it."); 38 | return _instance; 39 | } 40 | 41 | if (_instance == null) 42 | { 43 | GameObject singleton = new GameObject(); 44 | _instance = singleton.AddComponent(); 45 | singleton.name = "(singleton) "+ typeof(T).ToString(); 46 | 47 | DontDestroyOnLoad(singleton); 48 | 49 | Debug.Log("[Singleton] An instance of " + typeof(T) + 50 | " is needed in the scene, so '" + singleton + 51 | "' was created with DontDestroyOnLoad."); 52 | } else { 53 | Debug.Log("[Singleton] Using instance already created: " + 54 | _instance.gameObject.name); 55 | } 56 | } 57 | 58 | return _instance; 59 | } 60 | } 61 | } 62 | 63 | private static bool applicationIsQuitting = false; 64 | /// 65 | /// When Unity quits, it destroys objects in a random order. 66 | /// In principle, a Singleton is only destroyed when application quits. 67 | /// If any script calls Instance after it have been destroyed, 68 | /// it will create a buggy ghost object that will stay on the Editor scene 69 | /// even after stopping playing the Application. Really bad! 70 | /// So, this was made to be sure we're not creating that buggy ghost object. 71 | /// 72 | public void OnDestroy () { 73 | applicationIsQuitting = true; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /Assets/Scripts/UI/CollectionView/CollectionViewLayout/DepthFlowLayout.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | 4 | public class DepthFlowLayout : CollectionViewLayout 5 | { 6 | 7 | [SerializeField] 8 | private float m_sideGaps = 0.2f; 9 | 10 | [SerializeField] 11 | private float m_centralGap = 1; 12 | 13 | [SerializeField] 14 | private float m_sideDepth = 0; 15 | 16 | [SerializeField] 17 | private float m_centralDepth = 1; 18 | 19 | [SerializeField] 20 | private float m_sideAngles = 90; 21 | 22 | [SerializeField] 23 | private bool m_wrap = false; 24 | 25 | public override bool IndexWrap { get { return m_wrap; } } 26 | 27 | #if UNITY_EDITOR 28 | private float m_lastTime, m_lastSideGaps, m_lastCentralGap, m_lastSideDepth, m_lastSideAngles, m_lastCentralDepth; 29 | private bool m_wrapBefore; 30 | #endif 31 | 32 | #if UNITY_EDITOR 33 | void Awake() 34 | { 35 | m_lastTime = m_animTime; 36 | m_lastSideGaps = m_sideGaps; 37 | m_lastCentralGap = m_centralGap; 38 | m_lastSideDepth = m_sideDepth; 39 | m_lastSideAngles = m_sideAngles; 40 | m_lastCentralDepth = m_centralDepth; 41 | m_wrapBefore = m_wrap; 42 | } 43 | #endif 44 | 45 | #if UNITY_EDITOR 46 | void Update() 47 | { 48 | if(m_lastTime != m_animTime || 49 | m_lastSideGaps != m_sideGaps || 50 | m_lastCentralGap != m_centralGap || 51 | m_lastSideDepth != m_sideDepth || 52 | m_lastSideAngles != m_sideAngles || 53 | m_lastCentralDepth != m_centralDepth || 54 | m_wrapBefore != m_wrap) 55 | { 56 | //Relayout 57 | RequiresRelayout = true; 58 | InstantLayout |= (m_wrapBefore != m_wrap); 59 | 60 | m_lastTime = m_animTime; 61 | m_lastSideGaps = m_sideGaps; 62 | m_lastCentralGap = m_centralGap; 63 | m_lastSideDepth = m_sideDepth; 64 | m_lastSideAngles = m_sideAngles; 65 | m_lastCentralDepth = m_centralDepth; 66 | m_wrapBefore = m_wrap; 67 | } 68 | } 69 | #endif 70 | 71 | protected override Vector3 EulerAngle(float indexOffset, int cellIndex) 72 | { 73 | return new Vector3(0,0,RotationAngle(indexOffset, cellIndex)); 74 | } 75 | 76 | protected override Vector3 Position(float indexOffset, int cellIndex) 77 | { 78 | return new Vector3(TranslationX(indexOffset, cellIndex), 79 | TranslationY(indexOffset, cellIndex), 80 | TranslationZ(indexOffset, cellIndex)); 81 | } 82 | 83 | protected override Vector3 Scale(float indexOffset, int cellIndex) 84 | { 85 | return new Vector3(1, 1, 1); 86 | } 87 | 88 | private float RotationAngle(float indexOffset, int cellIndex) 89 | { 90 | return 0; 91 | } 92 | 93 | private float TranslationX(float indexOffset, int cellIndex) 94 | { 95 | return 0; 96 | } 97 | 98 | private float TranslationY(float indexOffset, int cellIndex) 99 | { 100 | return 0; 101 | } 102 | 103 | private float TranslationZ(float indexOffset, int cellIndex) 104 | { 105 | return 0; 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /Assets/Scripts/UI/CollectionView/CollectionViewLayout/CoverFlowLayout.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | public class CoverFlowLayout : CollectionViewLayout 6 | { 7 | [SerializeField] 8 | private float m_sideGaps = 0.2f; 9 | 10 | [SerializeField] 11 | private float m_centralGap = 1; 12 | 13 | [SerializeField] 14 | private float m_sideDepth = 0; 15 | 16 | [SerializeField] 17 | private float m_centralDepth = 1; 18 | 19 | [SerializeField] 20 | private float m_sideAngles = 90; 21 | 22 | [SerializeField] 23 | private bool m_wrap = false; 24 | 25 | public override bool IndexWrap { get { return m_wrap; } } 26 | 27 | #if UNITY_EDITOR 28 | private float m_lastTime, m_lastSideGaps, m_lastCentralGap, m_lastSideDepth, m_lastSideAngles, m_lastCentralDepth; 29 | private bool m_wrapBefore; 30 | #endif 31 | 32 | #if UNITY_EDITOR 33 | void Awake() 34 | { 35 | m_lastTime = m_animTime; 36 | m_lastSideGaps = m_sideGaps; 37 | m_lastCentralGap = m_centralGap; 38 | m_lastSideDepth = m_sideDepth; 39 | m_lastSideAngles = m_sideAngles; 40 | m_lastCentralDepth = m_centralDepth; 41 | m_wrapBefore = m_wrap; 42 | } 43 | #endif 44 | 45 | #if UNITY_EDITOR 46 | void Update() 47 | { 48 | if(m_lastTime != m_animTime || 49 | m_lastSideGaps != m_sideGaps || 50 | m_lastCentralGap != m_centralGap || 51 | m_lastSideDepth != m_sideDepth || 52 | m_lastSideAngles != m_sideAngles || 53 | m_lastCentralDepth != m_centralDepth || 54 | m_wrapBefore != m_wrap) 55 | { 56 | //Relayout 57 | RequiresRelayout = true; 58 | InstantLayout |= (m_wrapBefore != m_wrap); 59 | 60 | m_lastTime = m_animTime; 61 | m_lastSideGaps = m_sideGaps; 62 | m_lastCentralGap = m_centralGap; 63 | m_lastSideDepth = m_sideDepth; 64 | m_lastSideAngles = m_sideAngles; 65 | m_lastCentralDepth = m_centralDepth; 66 | m_wrapBefore = m_wrap; 67 | } 68 | } 69 | #endif 70 | 71 | protected override Vector3 EulerAngle(float indexOffset, int cellIndex) 72 | { 73 | return new Vector3(0, RotationAngle(indexOffset), 0); 74 | } 75 | 76 | protected override Vector3 Position(float indexOffset, int cellIndex) 77 | { 78 | return new Vector3(TranslationX(indexOffset), 0, TranslationZ(indexOffset)); 79 | } 80 | 81 | protected override Vector3 Scale(float indexOffset, int cellIndex) 82 | { 83 | return new Vector3(1, 1, 1); 84 | } 85 | 86 | private float RotationAngle(float indexOffset) 87 | { 88 | if(indexOffset >= 1 || indexOffset <= -1) 89 | { 90 | return Sign(indexOffset) * m_sideAngles; 91 | } 92 | else 93 | { 94 | return Math.Abs(indexOffset) * Sign(indexOffset) * m_sideAngles; 95 | } 96 | } 97 | 98 | private float TranslationX(float indexOffset) 99 | { 100 | if(indexOffset >= 1 || indexOffset <= -1) 101 | { 102 | return indexOffset * m_sideGaps + Sign(indexOffset) * m_centralGap; 103 | } 104 | else 105 | { 106 | return Sign(indexOffset) * m_centralGap * Math.Abs(indexOffset); 107 | } 108 | } 109 | 110 | private float TranslationZ(float indexOffset) 111 | { 112 | if(indexOffset >= 1 || indexOffset <= -1) 113 | { 114 | return m_sideDepth; 115 | } 116 | else 117 | { 118 | return m_centralDepth - Math.Abs(indexOffset) * (m_centralDepth - m_sideDepth); 119 | } 120 | } 121 | } 122 | 123 | -------------------------------------------------------------------------------- /Assets/Scripts/UI/CollectionView/CollectionViewLayout/MessyPaperFlowLayout.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System; 5 | 6 | public class MessyPaperFlowLayout : CollectionViewLayout 7 | { 8 | [SerializeField] 9 | private Vector3 m_positionOffsetScale = new Vector3(1,1,1); 10 | 11 | [SerializeField] 12 | private float m_rotationOffsetScale = 20; 13 | 14 | [SerializeField] 15 | private Vector3 m_leftPosition = Vector3.zero; 16 | 17 | [SerializeField] 18 | private Vector3 m_rightPosition = Vector3.zero; 19 | 20 | [SerializeField] 21 | private Vector3 m_centralPosition = Vector3.zero; 22 | 23 | private System.Random m_random; 24 | private List m_positionOffsetsLeft = new List(); 25 | private List m_rotationOffsetsLeft = new List(); 26 | private List m_positionOffsetsRight = new List(); 27 | private List m_rotationOffsetsRight = new List(); 28 | private int RandomCount { get { return m_positionOffsetsLeft.Count; } } 29 | private bool ReRandom { get; set; } 30 | 31 | #if UNITY_EDITOR 32 | private float m_lastRotationOffsetScale, m_lastTime; 33 | private Vector3 m_lastPositionOffsetScale, m_lastLeftPosition, m_lastRightPosition, m_lastCentralPosition; 34 | #endif 35 | 36 | #if UNITY_EDITOR 37 | void Awake() 38 | { 39 | m_lastTime = m_animTime; 40 | m_lastPositionOffsetScale = m_positionOffsetScale; 41 | m_lastLeftPosition = m_leftPosition; 42 | m_lastRightPosition = m_rightPosition; 43 | m_lastRotationOffsetScale = m_rotationOffsetScale; 44 | m_lastCentralPosition = m_centralPosition; 45 | } 46 | #endif 47 | 48 | #if UNITY_EDITOR 49 | void Update() 50 | { 51 | if(m_lastTime != m_animTime || 52 | m_lastPositionOffsetScale != m_positionOffsetScale || 53 | m_lastLeftPosition != m_leftPosition || 54 | m_lastRightPosition != m_rightPosition || 55 | m_lastRotationOffsetScale != m_rotationOffsetScale || 56 | m_lastCentralPosition != m_centralPosition) 57 | { 58 | //Relayout 59 | RequiresRelayout = true; 60 | ReRandom = true; 61 | 62 | m_lastTime = m_animTime; 63 | m_lastPositionOffsetScale = m_positionOffsetScale; 64 | m_lastLeftPosition = m_leftPosition; 65 | m_lastRightPosition = m_rightPosition; 66 | m_lastRotationOffsetScale = m_rotationOffsetScale; 67 | m_lastCentralPosition = m_centralPosition; 68 | } 69 | } 70 | #endif 71 | 72 | protected override void PreLayout (System.Collections.Generic.List data, System.Collections.Generic.List cells, bool dragging) 73 | { 74 | base.PreLayout (data, cells, dragging); 75 | 76 | //Do we need to calculate new random positions/rotations etc 77 | if (data.Count != RandomCount || ReRandom) 78 | { 79 | m_positionOffsetsLeft.Clear(); 80 | m_rotationOffsetsLeft.Clear(); 81 | m_positionOffsetsRight.Clear(); 82 | m_rotationOffsetsRight.Clear(); 83 | 84 | //Generate Random stuff 85 | m_random = new System.Random(0); 86 | //Add left hand side (n-1) 87 | //Add right hand side (n-1) 88 | for(int i=0; i= 1) 134 | { 135 | return m_rotationOffsetsRight[cellIndex]; 136 | } else if (indexOffset <= -1) 137 | { 138 | return m_rotationOffsetsLeft[cellIndex]; 139 | } else if (indexOffset > 0) 140 | { 141 | return Math.Abs(indexOffset) * m_rotationOffsetsRight[cellIndex]; 142 | } else if (indexOffset < 0) 143 | { 144 | return Math.Abs(indexOffset) * m_rotationOffsetsLeft[cellIndex]; 145 | } else 146 | { 147 | return 0; 148 | } 149 | } 150 | 151 | private float TranslationX(float indexOffset, int cellIndex) 152 | { 153 | if (indexOffset >= 1) 154 | { 155 | return m_rightPosition.x + m_positionOffsetsRight[cellIndex].x; 156 | } else if (indexOffset <= -1) 157 | { 158 | return m_leftPosition.x + m_positionOffsetsLeft[cellIndex].x; 159 | } else if (indexOffset > 0) 160 | { 161 | return m_centralPosition.x + indexOffset * (Math.Abs (m_rightPosition.x + m_positionOffsetsRight[cellIndex].x) - m_centralPosition.x); 162 | } else if (indexOffset < 0) 163 | { 164 | return m_centralPosition.x + indexOffset * (Math.Abs (m_leftPosition.x + m_positionOffsetsLeft[cellIndex].x) + m_centralPosition.x); 165 | } else 166 | { 167 | return m_centralPosition.x; 168 | } 169 | } 170 | 171 | private float TranslationY(float indexOffset, int cellIndex) 172 | { 173 | if (indexOffset >= 1) 174 | { 175 | return m_rightPosition.y + m_positionOffsetsRight[cellIndex].y; 176 | } else if (indexOffset <= -1) 177 | { 178 | return m_leftPosition.y + m_positionOffsetsLeft[cellIndex].y; 179 | } else if (indexOffset > 0) 180 | { 181 | return m_centralPosition.y + Math.Abs(indexOffset) * (m_rightPosition.y + m_positionOffsetsRight[cellIndex].y - m_centralPosition.y); 182 | } else if (indexOffset < 0) 183 | { 184 | return m_centralPosition.y + Math.Abs(indexOffset) * (m_leftPosition.y + m_positionOffsetsLeft[cellIndex].y - m_centralPosition.y); 185 | } else 186 | { 187 | return m_centralPosition.y; 188 | } 189 | } 190 | 191 | private float TranslationZ(float indexOffset, int cellIndex) 192 | { 193 | if (indexOffset >= 1 || indexOffset <= -1) 194 | { 195 | return Math.Abs(indexOffset) * 0.001f; 196 | } 197 | else 198 | { 199 | return m_centralPosition.z - Math.Abs(indexOffset) * (m_centralPosition.z - 0.001f); 200 | } 201 | } 202 | 203 | } 204 | -------------------------------------------------------------------------------- /Assets/Scripts/UI/CollectionView/CollectionViewLayout/CollectionViewLayout.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System; 5 | 6 | public abstract class CollectionViewLayout : MonoBehaviour 7 | { 8 | [SerializeField] 9 | protected float m_animTime = 1; 10 | 11 | [SerializeField] 12 | private int m_maxCells = 16; 13 | 14 | protected string NibInUse { get; set; } 15 | 16 | protected EventHandler OnCellClick { get; set; } 17 | 18 | public float CurrentIndex { get; set; } 19 | 20 | public bool RequiresRelayout { get; set; } 21 | 22 | public bool InstantLayout { get; set; } 23 | 24 | public virtual int TotalCellsNeeded { get { return m_maxCells; } } 25 | 26 | public virtual bool IndexWrap { get { return false; } } 27 | 28 | /// 29 | /// This handles reuse, it will work out the indices we need, add delete/add cell 30 | /// as needed. 31 | /// 32 | /// Call before layout 33 | /// 34 | /// Data - The whole data we are laying out. 35 | /// Cells - The array of cells we will add/delete from as needed 36 | private void PrepareCells(List data, List cells) 37 | { 38 | int totCells = Math.Min(TotalCellsNeeded, data.Count); 39 | 40 | int curIndex = (int)Math.Round(CurrentIndex); 41 | int min = curIndex - (totCells / 2); 42 | int max = curIndex + (totCells / 2); 43 | 44 | if(!IndexWrap) 45 | { 46 | if(min < 0) 47 | { 48 | min = 0; 49 | max = totCells; 50 | } 51 | else if (max >= data.Count) 52 | { 53 | max = data.Count; 54 | min = max - totCells; 55 | } 56 | } 57 | 58 | //GO through cells, any with an index we no longer need, turn off 59 | int minVal = (min < 0) ? min + data.Count : min; 60 | int maxVal = (max >= data.Count) ? max - data.Count : max; 61 | 62 | 63 | if (!IndexWrap) { 64 | if (max >= data.Count) { 65 | maxVal = data.Count - 1; 66 | minVal = maxVal - m_maxCells; 67 | } 68 | 69 | min = minVal; 70 | max = maxVal; 71 | } 72 | 73 | 74 | for(int i=0; i minVal && (c.Index <= maxVal && c.Index >= minVal)) 85 | continue; 86 | 87 | //If min value is bigger than max were in a "wrap" 88 | if(minVal > maxVal && (c.Index >= minVal || c.Index <= maxVal)) 89 | continue; 90 | c.SetActive(false); 91 | cells.Remove(c); 92 | i--; 93 | } 94 | 95 | //Go through cells, add any indices we need and set their data TODO - How to do this quickly? 96 | for(int i = min; i <= max; i++) 97 | { 98 | int index = i; 99 | //Wrap index 100 | if(index<0) 101 | index += data.Count; 102 | else if(index >= data.Count) 103 | index -= data.Count; 104 | 105 | //Check if we have htis index 106 | bool found = false; 107 | foreach(iCollectionViewCell cell in cells) 108 | { 109 | if(cell.Index == index) 110 | { 111 | found = true; 112 | //Set Data if null 113 | if(cell.Data == null) 114 | cell.SetData(data[index]); 115 | break; 116 | } 117 | } 118 | 119 | if(!found) 120 | { 121 | 122 | //Add a new one 123 | iCollectionViewCell c = CellPoolService.Instance.CreateCell(NibInUse, gameObject); 124 | c.transform.localPosition = Vector3.zero; 125 | c.Index = index; 126 | c.Snap = true; 127 | c.SetData(data[index]); 128 | 129 | if(OnCellClick!=null) 130 | c.OnClickEvent += OnCellClick; 131 | 132 | cells.Add(c); 133 | } 134 | } 135 | } 136 | 137 | /// 138 | /// Register a cell for use with this layout 139 | /// 140 | /// Cell - iCoverFlowCell being used 141 | /// On cell click - Optional OnCellClick event 142 | public void RegisterCell(iCollectionViewCell cell, EventHandler onCellClick = null) 143 | { 144 | //Register pool 145 | CellPoolService.Instance.RegisterCell(cell); 146 | 147 | NibInUse = cell.NibName; 148 | if(onCellClick!=null) 149 | OnCellClick = onCellClick; 150 | } 151 | 152 | /// 153 | /// Layout function 154 | /// 155 | /// Data - The whole data we are laying out 156 | /// Cells - The cell list 157 | /// If set to true we are currently dragging the layout dragging. 158 | public virtual void Layout(List data, List cells, bool dragging = false) 159 | { 160 | PrepareCells(data, cells); 161 | 162 | PreLayout(data, cells); 163 | 164 | //Layout 165 | foreach(iCollectionViewCell cell in cells) 166 | { 167 | bool snap = InstantLayout || cell.Snap; 168 | //Get index Offset based on wrap 169 | float offset = cell.Index - CurrentIndex; 170 | 171 | if(IndexWrap) 172 | { 173 | if(offset > data.Count / 2) 174 | { 175 | offset -= data.Count; 176 | } 177 | else if(offset < -data.Count / 2) 178 | { 179 | offset += data.Count; 180 | } 181 | 182 | //We want to "snap" if we go from extreme left/right to the other side 183 | if(Math.Abs(cell.FlowIndexOffset - offset) > data.Count / 2) 184 | snap = true; 185 | } 186 | 187 | cell.FlowIndexOffset = offset; 188 | 189 | Vector3 pos = Position(offset, cell.Index); 190 | Vector3 rot = EulerAngle(offset, cell.Index); 191 | Vector3 scale = Scale(offset, cell.Index); 192 | 193 | //Position is local in layout but iTween is world 194 | pos += transform.position; 195 | 196 | if(snap) 197 | { 198 | //Kill all tween and snap 199 | iTween.Stop(cell.gameObject); 200 | 201 | if(cell.gameObject.transform.position != pos) 202 | cell.gameObject.transform.position = pos; 203 | 204 | if(cell.gameObject.transform.localEulerAngles != rot) 205 | cell.gameObject.transform.localEulerAngles = rot; 206 | 207 | if(cell.gameObject.transform.localScale != scale) 208 | cell.gameObject.transform.localScale = scale; 209 | 210 | } 211 | else if(dragging) 212 | { 213 | //Kill all tweens and smooth update 214 | iTween.Stop(cell.gameObject); 215 | 216 | if(cell.gameObject.transform.position != pos) 217 | iTween.MoveUpdate(cell.gameObject, pos, m_animTime); 218 | 219 | if(cell.gameObject.transform.localEulerAngles != rot) 220 | iTween.RotateUpdate(cell.gameObject, rot, m_animTime); 221 | 222 | if(cell.gameObject.transform.localScale != scale) 223 | iTween.ScaleUpdate(cell.gameObject, scale, m_animTime); 224 | } 225 | else 226 | { 227 | if(cell.gameObject.transform.position != pos) 228 | iTween.MoveTo(cell.gameObject, pos, m_animTime); 229 | 230 | if(cell.gameObject.transform.localEulerAngles != rot) 231 | iTween.RotateTo(cell.gameObject, rot, m_animTime); 232 | 233 | if(cell.gameObject.transform.localScale != scale) 234 | iTween.ScaleTo(cell.gameObject, scale, m_animTime); 235 | } 236 | } 237 | 238 | PostLayout(data, cells); 239 | 240 | RequiresRelayout = false; 241 | InstantLayout = false; 242 | } 243 | 244 | protected abstract Vector3 EulerAngle(float indexOffset, int cellIndex); 245 | 246 | protected abstract Vector3 Position(float indexOffset, int cellIndex); 247 | 248 | protected abstract Vector3 Scale(float indexOffset, int cellIndex); 249 | 250 | protected virtual float Alpha(float indexOffset, int cellIndex) { return 1.0f; } 251 | 252 | /// 253 | /// Called before the cells are laid out, but after the cell reuse pass has been done. Cells will be the right size (array size). 254 | /// 255 | /// Data. 256 | /// Cells. 257 | /// If set to true dragging. 258 | protected virtual void PreLayout(List data, List cells, bool dragging = false) { } 259 | 260 | /// 261 | /// Called after cells have been laid out (snapped or tweens added) 262 | /// 263 | /// Data. 264 | /// Cells. 265 | /// If set to true dragging. 266 | protected virtual void PostLayout(List data, List cells, bool dragging = false) { } 267 | 268 | //Mathf.Sign(0) returns 1, but we want 0 269 | protected int Sign(float x) 270 | { 271 | if(x<0) 272 | return -1; 273 | if(x>0) 274 | return 1; 275 | 276 | return 0; 277 | } 278 | 279 | } 280 | -------------------------------------------------------------------------------- /Assets/Scripts/UI/CollectionView/UICollectionView.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System; 5 | 6 | public class UICollectionView : MonoBehaviour { 7 | 8 | private enum DragState 9 | { 10 | None, 11 | Starting, 12 | Dragging, 13 | } 14 | 15 | [SerializeField] 16 | private LayerMask m_inputDragLayer; 17 | 18 | [SerializeField] 19 | private Camera m_inputCamera; 20 | 21 | [SerializeField] 22 | private iCollectionViewCell m_cell; 23 | 24 | [SerializeField] 25 | private CollectionViewLayout m_layout; 26 | 27 | [SerializeField] 28 | private bool m_tapSelectEnabled = true; 29 | 30 | [SerializeField] 31 | private bool m_dragEnabled = true; 32 | 33 | [SerializeField] 34 | private float m_dragSpeed = 1; 35 | 36 | [SerializeField] 37 | private float m_minDragAmount = 0.05f; 38 | 39 | [SerializeField] 40 | private float m_maxDragAmount = 0.2f; 41 | 42 | [SerializeField] 43 | private GameObject m_dragPlane; 44 | 45 | private DragState m_dragState = DragState.None; 46 | private Vector2 m_lastScreenPos = Vector2.zero; 47 | private Vector2 m_totalDrag = Vector2.zero; 48 | private bool Dirty { get; set; } 49 | 50 | private CollectionViewLayout m_prevLayout; 51 | 52 | private List m_data; 53 | public List Data 54 | { 55 | get 56 | { 57 | return m_data; 58 | } 59 | set 60 | { 61 | m_data = value; 62 | Dirty = true; 63 | 64 | //Instant 65 | if(m_layout!=null) 66 | m_layout.InstantLayout = true; 67 | } 68 | } 69 | 70 | //Store cells here, the Layouts will deal with these 71 | private List m_cells; 72 | 73 | void Awake() 74 | { 75 | m_prevLayout = m_layout; 76 | 77 | if(m_cell!=null && m_layout!=null) 78 | m_layout.RegisterCell(m_cell, OnCellClickEvent); 79 | 80 | //Register with any other components 81 | CollectionViewLayout[] layouts = GetComponents(); 82 | foreach(CollectionViewLayout layout in layouts) 83 | { 84 | if(m_layout!=layout) 85 | layout.RegisterCell(m_cell, OnCellClickEvent); 86 | } 87 | 88 | m_cells = new List(); 89 | } 90 | 91 | void Update() 92 | { 93 | #if UNITY_EDITOR 94 | KeyboardInput(); 95 | if(m_dragEnabled) 96 | MouseDrag(); 97 | #elif UNITY_IPHONE 98 | if(m_dragEnabled) 99 | TouchDrag(); 100 | #endif 101 | 102 | if(m_prevLayout!=m_layout) 103 | { 104 | m_layout.InstantLayout=true; 105 | m_layout.CurrentIndex = m_prevLayout.CurrentIndex; 106 | Dirty = true; 107 | m_prevLayout = m_layout; 108 | } 109 | 110 | if (m_layout != null) 111 | { 112 | if (Dirty || m_layout.RequiresRelayout) 113 | { 114 | m_layout.Layout(Data, m_cells, m_dragState == DragState.Dragging); 115 | Dirty = false; 116 | } 117 | } 118 | } 119 | 120 | public void Relayout() 121 | { 122 | Dirty = true; 123 | } 124 | 125 | public void SetLayout(CollectionViewLayout layout) 126 | { 127 | layout.RegisterCell(m_cell, OnCellClickEvent); 128 | layout.CurrentIndex = m_layout.CurrentIndex; 129 | m_prevLayout = m_layout; 130 | m_layout = layout; 131 | Dirty = true; 132 | m_layout.InstantLayout = true; 133 | } 134 | 135 | public void StepLeft() 136 | { 137 | if(m_layout.CurrentIndex > 0) 138 | { 139 | m_layout.CurrentIndex--; 140 | Dirty = true; 141 | } 142 | else if(m_layout.IndexWrap) 143 | { 144 | m_layout.CurrentIndex = Data.Count - 1; 145 | Dirty = true; 146 | } 147 | } 148 | 149 | public void StepRight() 150 | { 151 | if(m_layout.CurrentIndex < Data.Count - 1) 152 | { 153 | m_layout.CurrentIndex++; 154 | Dirty = true; 155 | } 156 | else if(m_layout.IndexWrap) 157 | { 158 | m_layout.CurrentIndex = 0; 159 | Dirty = true; 160 | } 161 | } 162 | 163 | private void OnCellClickEvent(object sender, EventArgs e) 164 | { 165 | if(!m_tapSelectEnabled || m_dragState == DragState.Dragging) 166 | return; 167 | 168 | iCollectionViewCell cell = sender as iCollectionViewCell; 169 | if(cell!=null && m_layout!=null) 170 | { 171 | StopDrag(); 172 | m_layout.CurrentIndex = cell.Index; 173 | Dirty = true; 174 | } 175 | } 176 | 177 | private void KeyboardInput() 178 | { 179 | if(m_layout!=null && Data.Count > 0) 180 | { 181 | if(Input.GetKeyDown(KeyCode.RightArrow)) 182 | { 183 | StepRight(); 184 | 185 | } 186 | if(Input.GetKeyDown(KeyCode.LeftArrow)) 187 | { 188 | StepLeft(); 189 | } 190 | } 191 | } 192 | 193 | private void MouseDrag() 194 | { 195 | if(m_layout!=null && Data.Count > 0) 196 | { 197 | if(m_dragState == DragState.None) 198 | { 199 | //Look for drag start 200 | if(Input.GetMouseButtonDown(0)) 201 | { 202 | //See if we click on any cells, and snap to that 203 | Camera cam = (m_inputCamera!=null) ? m_inputCamera : Camera.main; 204 | 205 | RaycastHit hit; 206 | Ray r = cam.ScreenPointToRay(Input.mousePosition); 207 | if(Physics.Raycast(r, out hit, float.MaxValue, m_inputDragLayer.value)) 208 | { 209 | //Click start 210 | m_dragState = DragState.Starting; 211 | m_totalDrag = Vector2.zero; 212 | m_lastScreenPos = Input.mousePosition; 213 | } 214 | } 215 | } 216 | else 217 | { 218 | //See if we've moved 219 | //If no mouse stop 220 | if(Input.GetMouseButton(0)) 221 | { 222 | //Drag 223 | Vector2 newPoint = Input.mousePosition; 224 | Vector2 delta = m_lastScreenPos - newPoint; 225 | 226 | //Normalize delta to screen size 227 | delta.x /= Screen.width; 228 | delta.y /= Screen.height; 229 | 230 | if(delta.x > m_maxDragAmount) 231 | delta.x = m_maxDragAmount; 232 | else if(delta.x < -m_maxDragAmount) 233 | delta.x = -m_maxDragAmount; 234 | 235 | if(delta.y > m_maxDragAmount) 236 | delta.y = m_maxDragAmount; 237 | else if(delta.y < -m_maxDragAmount) 238 | delta.y = -m_maxDragAmount; 239 | 240 | if(m_dragState == DragState.Starting) 241 | { 242 | //Tally up 243 | m_totalDrag.x += Math.Abs(delta.x); 244 | m_totalDrag.y += Math.Abs(delta.y); 245 | 246 | //Dragged enough? 247 | if(m_totalDrag.x >= m_minDragAmount || m_totalDrag.y >= m_minDragAmount) 248 | m_dragState = DragState.Dragging; 249 | } 250 | 251 | if(m_dragState == DragState.Dragging) 252 | { 253 | //Update index based off delta and drag speed 254 | m_layout.CurrentIndex += delta.x * m_dragSpeed; 255 | 256 | if(m_layout.IndexWrap) 257 | { 258 | //Wrap the CUrrentIndex 259 | if(m_layout.CurrentIndex < 0) 260 | m_layout.CurrentIndex += Data.Count; 261 | else if(m_layout.CurrentIndex >= Data.Count) 262 | m_layout.CurrentIndex -= Data.Count; 263 | } 264 | Dirty = true; 265 | } 266 | 267 | m_lastScreenPos = newPoint; 268 | } 269 | else 270 | { 271 | StopDrag(); 272 | } 273 | } 274 | } 275 | } 276 | 277 | private void TouchDrag() 278 | { 279 | //Single touch only 280 | if(Input.touchCount != 1) 281 | { 282 | StopDrag(); 283 | return; 284 | } 285 | 286 | Touch t = Input.touches[0]; 287 | 288 | if(m_layout!=null && Data.Count > 0) 289 | { 290 | if(m_dragState == DragState.None) 291 | { 292 | //Look for touch start 293 | if(t.phase == TouchPhase.Began) 294 | { 295 | //See if we click on any cells, and snap to that 296 | Camera cam = (m_inputCamera!=null) ? m_inputCamera : Camera.main; 297 | 298 | RaycastHit hit; 299 | Vector3 point = new Vector3(t.position.x, t.position.y, 0); 300 | Ray r = Camera.main.ScreenPointToRay(point); 301 | if(Physics.Raycast(r, out hit, float.MaxValue, m_inputDragLayer.value)) 302 | { 303 | //Click start 304 | m_dragState = DragState.Starting; 305 | m_totalDrag = Vector2.zero; 306 | m_lastScreenPos = t.position; 307 | } 308 | } 309 | } 310 | else 311 | { 312 | if(t.phase == TouchPhase.Moved) 313 | { 314 | //Drag 315 | Vector2 newPoint = t.position; 316 | Vector2 delta = m_lastScreenPos - newPoint; 317 | 318 | //Normalize delta to screen size 319 | delta.x /= Screen.width; 320 | delta.y /= Screen.height; 321 | 322 | if(delta.x > m_maxDragAmount) 323 | delta.x = m_maxDragAmount; 324 | else if(delta.x < -m_maxDragAmount) 325 | delta.x = -m_maxDragAmount; 326 | 327 | if(delta.y > m_maxDragAmount) 328 | delta.y = m_maxDragAmount; 329 | else if(delta.y < -m_maxDragAmount) 330 | delta.y = -m_maxDragAmount; 331 | 332 | if(m_dragState == DragState.Starting) 333 | { 334 | //Tally up 335 | m_totalDrag.x += Math.Abs(delta.x); 336 | m_totalDrag.y += Math.Abs(delta.y); 337 | 338 | //Dragged enough? 339 | if(m_totalDrag.x >= m_minDragAmount || m_totalDrag.y >= m_minDragAmount) 340 | m_dragState = DragState.Dragging; 341 | } 342 | 343 | if(m_dragState == DragState.Dragging) 344 | { 345 | //Update index based off delta and drag speed 346 | m_layout.CurrentIndex += delta.x * m_dragSpeed; 347 | 348 | if(m_layout.IndexWrap) 349 | { 350 | //Wrap the CUrrentIndex 351 | if(m_layout.CurrentIndex < 0) 352 | m_layout.CurrentIndex += Data.Count; 353 | else if(m_layout.CurrentIndex >= Data.Count) 354 | m_layout.CurrentIndex -= Data.Count; 355 | } 356 | Dirty = true; 357 | } 358 | 359 | m_lastScreenPos = newPoint; 360 | } 361 | else if(t.phase != TouchPhase.Stationary) 362 | { 363 | StopDrag(); 364 | } 365 | } 366 | } 367 | } 368 | 369 | private void StopDrag() 370 | { 371 | m_dragState = DragState.None; 372 | m_totalDrag = Vector2.zero; 373 | m_lastScreenPos = Vector2.zero; 374 | Dirty = true; 375 | 376 | //Clamp the layout to the nearest index 377 | //TODO - Momentum? 378 | // - Store velocity of movement (either take last Delta, or maybe have a seperate velocity being set) 379 | // - Coroutine or in Update, update the Index based off momentum until velocity is near 0 380 | // - When done, snap to nearest index like below... 381 | if(m_layout!=null) 382 | { 383 | m_layout.CurrentIndex = Mathf.Round(m_layout.CurrentIndex); 384 | 385 | if(!m_layout.IndexWrap) 386 | { 387 | if(m_layout.CurrentIndex < 0) 388 | m_layout.CurrentIndex = 0; 389 | else if(m_layout.CurrentIndex > Data.Count - 1) 390 | m_layout.CurrentIndex = Data.Count - 1; 391 | } 392 | else 393 | { 394 | //Wrap the CUrrentIndex 395 | if(m_layout.CurrentIndex < 0) 396 | m_layout.CurrentIndex += Data.Count; 397 | else if(m_layout.CurrentIndex >= Data.Count) 398 | m_layout.CurrentIndex -= Data.Count; 399 | } 400 | } 401 | } 402 | 403 | void OnDrawGizmos() 404 | { 405 | if(m_dragPlane==null) 406 | return; 407 | 408 | Gizmos.color = Color.red; 409 | 410 | //Draw the corners of the quad 411 | float radius = 0.025f; 412 | Gizmos.DrawSphere(m_dragPlane.transform.position + new Vector3(-m_dragPlane.transform.localScale.x / 2, -m_dragPlane.transform.localScale.y / 2), radius); 413 | Gizmos.DrawSphere(m_dragPlane.transform.position + new Vector3(m_dragPlane.transform.localScale.x / 2, -m_dragPlane.transform.localScale.y / 2), radius); 414 | Gizmos.DrawSphere(m_dragPlane.transform.position + new Vector3(m_dragPlane.transform.localScale.x / 2, m_dragPlane.transform.localScale.y / 2), radius); 415 | Gizmos.DrawSphere(m_dragPlane.transform.position + new Vector3(-m_dragPlane.transform.localScale.x / 2, m_dragPlane.transform.localScale.y / 2), radius); 416 | 417 | Gizmos.DrawWireCube(m_dragPlane.transform.position, new Vector3(m_dragPlane.transform.localScale.x, m_dragPlane.transform.localScale.y)); 418 | } 419 | } 420 | --------------------------------------------------------------------------------