├── .gitignore
├── .vs
└── LOOM-Multi-Threading-Framework
│ └── v14
│ └── .suo
├── Assembly-CSharp.csproj
├── Assets
├── LOOM Framework.meta
└── LOOM Framework
│ ├── Examples.meta
│ ├── Examples
│ ├── Prefabs.meta
│ ├── Prefabs
│ │ ├── CannonBall.prefab
│ │ ├── CannonBall.prefab.meta
│ │ ├── FlockingManager.prefab
│ │ └── FlockingManager.prefab.meta
│ ├── Scenes.meta
│ ├── Scenes
│ │ ├── FlockingMassive.unity
│ │ ├── FlockingMassive.unity.meta
│ │ ├── SimpleExampleImplementation.unity
│ │ ├── SimpleExampleImplementation.unity.meta
│ │ ├── TextureBlur.unity
│ │ └── TextureBlur.unity.meta
│ ├── Scripts.meta
│ ├── Scripts
│ │ ├── FlockingMassive.meta
│ │ ├── FlockingMassive
│ │ │ ├── Cannon.cs
│ │ │ ├── Cannon.cs.meta
│ │ │ ├── FlockHelper.cs
│ │ │ ├── FlockHelper.cs.meta
│ │ │ ├── HUDmanager.cs
│ │ │ ├── HUDmanager.cs.meta
│ │ │ ├── MassiveFlockingExample.cs
│ │ │ ├── MassiveFlockingExample.cs.meta
│ │ │ ├── MovingBodies.cs
│ │ │ ├── MovingBodies.cs.meta
│ │ │ ├── ThreadedFlocking.cs
│ │ │ └── ThreadedFlocking.cs.meta
│ │ ├── Simple Implementations.meta
│ │ ├── Simple Implementations
│ │ │ ├── SimpleThreadingExample.cs
│ │ │ └── SimpleThreadingExample.cs.meta
│ │ ├── TextureBlur.meta
│ │ └── TextureBlur
│ │ │ ├── TextureBlurCodeExplained.jpg
│ │ │ ├── TextureBlurCodeExplained.jpg.meta
│ │ │ ├── TextureBlurThreaded.cs
│ │ │ └── TextureBlurThreaded.cs.meta
│ ├── Visuals.meta
│ └── Visuals
│ │ ├── Cubemap.jpg
│ │ ├── Cubemap.jpg.meta
│ │ ├── FlockingDemoLogo.jpg
│ │ ├── FlockingDemoLogo.jpg.meta
│ │ ├── Floor.jpg
│ │ ├── Floor.jpg.meta
│ │ ├── FrameClean.fbx
│ │ ├── FrameClean.fbx.meta
│ │ ├── FrameHighPoly.fbx
│ │ ├── FrameHighPoly.fbx.meta
│ │ ├── Materials.meta
│ │ ├── Materials
│ │ ├── CannonBall.mat
│ │ ├── CannonBall.mat.meta
│ │ ├── Export_Logo_Clean_mi_car_paint_phen_x_passes1.mat
│ │ ├── Export_Logo_Clean_mi_car_paint_phen_x_passes1.mat.meta
│ │ ├── Floor.mat
│ │ ├── Floor.mat.meta
│ │ ├── Frame.mat
│ │ ├── Frame.mat.meta
│ │ ├── Particle.mat
│ │ ├── Particle.mat.meta
│ │ ├── Spheres.mat
│ │ ├── Spheres.mat.meta
│ │ ├── lambert1.mat
│ │ ├── lambert1.mat.meta
│ │ ├── mi_car_paint_phen_x_passes1.mat
│ │ └── mi_car_paint_phen_x_passes1.mat.meta
│ │ ├── Particle.png
│ │ ├── Particle.png.meta
│ │ ├── Plane1x1.fbx
│ │ ├── Plane1x1.fbx.meta
│ │ ├── Rock_n_Snow.JPG
│ │ └── Rock_n_Snow.JPG.meta
│ ├── LOOM.meta
│ └── LOOM
│ ├── IThreadWorkerObject.cs
│ ├── IThreadWorkerObject.cs.meta
│ ├── Internal.meta
│ ├── Internal
│ ├── MainThreadDispatcher.cs
│ ├── MainThreadDispatcher.cs.meta
│ ├── MainThreadWatchdog.cs
│ ├── MainThreadWatchdog.cs.meta
│ ├── MultithreadedWorkloadHelper.cs
│ ├── MultithreadedWorkloadHelper.cs.meta
│ ├── SingleThreadStarter.cs
│ ├── SingleThreadStarter.cs.meta
│ ├── ThreadDispatchAction.cs
│ ├── ThreadDispatchAction.cs.meta
│ ├── ThreadPoolSchedulerWorkerObjects.cs
│ ├── ThreadPoolSchedulerWorkerObjects.cs.meta
│ ├── ThreadWaitCommands.cs
│ ├── ThreadWaitCommands.cs.meta
│ ├── UnityActivityWatchdog.cs
│ └── UnityActivityWatchdog.cs.meta
│ ├── Loom.cs
│ ├── Loom.cs.meta
│ ├── ThreadPoolScheduler.cs
│ └── ThreadPoolScheduler.cs.meta
├── LOOM - Multi Threading Framework16.unitypackage
├── LOOM-Multi-Threading-Framework.csproj
├── LOOM-Multi-Threading-Framework.sln
└── ProjectSettings
├── AudioManager.asset
├── ClusterInputManager.asset
├── DynamicsManager.asset
├── EditorBuildSettings.asset
├── EditorSettings.asset
├── GraphicsSettings.asset
├── InputManager.asset
├── NavMeshAreas.asset
├── NetworkManager.asset
├── Physics2DSettings.asset
├── ProjectSettings.asset
├── ProjectVersion.txt
├── QualitySettings.asset
├── TagManager.asset
├── TimeManager.asset
├── UnityAdsSettings.asset
└── UnityConnectSettings.asset
/.gitignore:
--------------------------------------------------------------------------------
1 | Library/
2 | Temp/
3 |
--------------------------------------------------------------------------------
/.vs/LOOM-Multi-Threading-Framework/v14/.suo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/superowner/LOOM-Multi-Threading-Framework/56a811efcc3e135782559424e51392c69de8fb2f/.vs/LOOM-Multi-Threading-Framework/v14/.suo
--------------------------------------------------------------------------------
/Assembly-CSharp.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | AnyCPU
6 | 10.0.20506
7 | 2.0
8 |
9 | {1531EB7A-9E70-6350-9B3A-FB55757FB8FD}
10 | Library
11 | Properties
12 | Assembly-CSharp
13 | v3.5
14 | 512
15 | Assets
16 |
17 |
18 | true
19 | full
20 | false
21 | Temp\bin\Debug\
22 | DEBUG;TRACE;UNITY_5_3_OR_NEWER;UNITY_5_3_4;UNITY_5_3;UNITY_5;ENABLE_NEW_BUGREPORTER;ENABLE_AUDIO;ENABLE_CACHING;ENABLE_CLOTH;ENABLE_FRAME_DEBUGGER;ENABLE_GENERICS;ENABLE_HOME_SCREEN;ENABLE_IMAGEEFFECTS;ENABLE_LIGHT_PROBES_LEGACY;ENABLE_MICROPHONE;ENABLE_MULTIPLE_DISPLAYS;ENABLE_PHYSICS;ENABLE_PLUGIN_INSPECTOR;ENABLE_SHADOWS;ENABLE_SINGLE_INSTANCE_BUILD_SETTING;ENABLE_SPRITERENDERER_FLIPPING;ENABLE_SPRITES;ENABLE_SPRITE_POLYGON;ENABLE_TERRAIN;ENABLE_RAKNET;ENABLE_UNET;ENABLE_UNITYEVENTS;ENABLE_VR;ENABLE_WEBCAM;ENABLE_WWW;ENABLE_CLOUD_SERVICES;ENABLE_CLOUD_SERVICES_ADS;ENABLE_CLOUD_HUB;ENABLE_CLOUD_PROJECT_ID;ENABLE_CLOUD_SERVICES_PURCHASING;ENABLE_CLOUD_SERVICES_ANALYTICS;ENABLE_CLOUD_SERVICES_UNET;ENABLE_CLOUD_SERVICES_BUILD;ENABLE_CLOUD_LICENSE;ENABLE_EDITOR_METRICS;ENABLE_EDITOR_METRICS_CACHING;INCLUDE_DYNAMIC_GI;INCLUDE_GI;INCLUDE_IL2CPP;INCLUDE_DIRECTX12;PLATFORM_SUPPORTS_MONO;ENABLE_LOCALIZATION;ENABLE_ANDROID_ATLAS_ETC1_COMPRESSION;ENABLE_EDITOR_TESTS_RUNNER;UNITY_ANDROID;UNITY_ANDROID_API;ENABLE_SUBSTANCE;ENABLE_TEXTUREID_MAP;ENABLE_EGL;ENABLE_NETWORK;ENABLE_RUNTIME_GI;ENABLE_CRUNCH_TEXTURE_COMPRESSION;ENABLE_LOG_MIXED_STACKTRACE;ENABLE_UNITYWEBREQUEST;PLATFORM_SUPPORTS_ADS_ID;ENABLE_UNITYADS_RUNTIME;UNITY_UNITYADS_API;ENABLE_MONO;ENABLE_PROFILER;UNITY_ASSERTIONS;UNITY_EDITOR;UNITY_EDITOR_64;UNITY_EDITOR_WIN;UNITY_TEAM_LICENSE;UNITY_PRO_LICENSE
23 | prompt
24 | 4
25 | 0169
26 |
27 |
28 | pdbonly
29 | true
30 | Temp\bin\Release\
31 | prompt
32 | 4
33 | 0169
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 | C:/Program Files/Unity/Editor/Data/Managed/UnityEngine.dll
42 |
43 |
44 | C:/Program Files/Unity/Editor/Data/Managed/UnityEditor.dll
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 | C:/Program Files/Unity/Editor/Data/UnityExtensions/Unity/GUISystem/UnityEngine.UI.dll
69 |
70 |
71 | C:/Program Files/Unity/Editor/Data/UnityExtensions/Unity/Networking/UnityEngine.Networking.dll
72 |
73 |
74 |
75 |
82 |
83 |
84 |
--------------------------------------------------------------------------------
/Assets/LOOM Framework.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 19266bd63c5fd4d1aabe5a5fb93a10ae
3 | folderAsset: yes
4 | timeCreated: 1496323769
5 | licenseType: Free
6 | DefaultImporter:
7 | userData:
8 | assetBundleName:
9 | assetBundleVariant:
10 |
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 0c9fcae2849e7cf4699c28a9bbe2d9f2
3 | folderAsset: yes
4 | timeCreated: 1496323769
5 | licenseType: Free
6 | DefaultImporter:
7 | userData:
8 | assetBundleName:
9 | assetBundleVariant:
10 |
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Prefabs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: ea9b0669b96b46046b14fac37577b925
3 | folderAsset: yes
4 | timeCreated: 1496323769
5 | licenseType: Free
6 | DefaultImporter:
7 | userData:
8 | assetBundleName:
9 | assetBundleVariant:
10 |
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Prefabs/CannonBall.prefab:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/superowner/LOOM-Multi-Threading-Framework/56a811efcc3e135782559424e51392c69de8fb2f/Assets/LOOM Framework/Examples/Prefabs/CannonBall.prefab
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Prefabs/CannonBall.prefab.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: eaf411afab22f0d46a05bc6761c04263
3 | NativeFormatImporter:
4 | userData:
5 | assetBundleName:
6 | assetBundleVariant:
7 |
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Prefabs/FlockingManager.prefab:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/superowner/LOOM-Multi-Threading-Framework/56a811efcc3e135782559424e51392c69de8fb2f/Assets/LOOM Framework/Examples/Prefabs/FlockingManager.prefab
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Prefabs/FlockingManager.prefab.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: bafca668293ac4840a771ba443f76963
3 | NativeFormatImporter:
4 | userData:
5 | assetBundleName:
6 | assetBundleVariant:
7 |
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Scenes.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 82d3af87267129e43b539639ca30cc0c
3 | folderAsset: yes
4 | timeCreated: 1496323769
5 | licenseType: Free
6 | DefaultImporter:
7 | userData:
8 | assetBundleName:
9 | assetBundleVariant:
10 |
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Scenes/FlockingMassive.unity:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/superowner/LOOM-Multi-Threading-Framework/56a811efcc3e135782559424e51392c69de8fb2f/Assets/LOOM Framework/Examples/Scenes/FlockingMassive.unity
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Scenes/FlockingMassive.unity.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 15f6e8237305ce343922a426c214c637
3 | DefaultImporter:
4 | userData:
5 | assetBundleName:
6 | assetBundleVariant:
7 |
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Scenes/SimpleExampleImplementation.unity:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/superowner/LOOM-Multi-Threading-Framework/56a811efcc3e135782559424e51392c69de8fb2f/Assets/LOOM Framework/Examples/Scenes/SimpleExampleImplementation.unity
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Scenes/SimpleExampleImplementation.unity.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 2aba94d896fd9114691ae36beac41c5d
3 | DefaultImporter:
4 | userData:
5 | assetBundleName:
6 | assetBundleVariant:
7 |
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Scenes/TextureBlur.unity:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/superowner/LOOM-Multi-Threading-Framework/56a811efcc3e135782559424e51392c69de8fb2f/Assets/LOOM Framework/Examples/Scenes/TextureBlur.unity
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Scenes/TextureBlur.unity.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: a9f9b379d1b8be64883c6181f8d6e4ec
3 | DefaultImporter:
4 | userData:
5 | assetBundleName:
6 | assetBundleVariant:
7 |
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Scripts.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: c2e17f82cc9859b4c81cc6a5976f3356
3 | folderAsset: yes
4 | timeCreated: 1496323769
5 | licenseType: Free
6 | DefaultImporter:
7 | userData:
8 | assetBundleName:
9 | assetBundleVariant:
10 |
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Scripts/FlockingMassive.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: ba2e25d3c1a5e734d8cc03470d26e754
3 | folderAsset: yes
4 | timeCreated: 1496323769
5 | licenseType: Free
6 | DefaultImporter:
7 | userData:
8 | assetBundleName:
9 | assetBundleVariant:
10 |
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Scripts/FlockingMassive/Cannon.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 | using System.Collections;
3 | using System.Collections.Generic;
4 |
5 | public class Cannon : MonoBehaviour
6 | {
7 | public Transform CannonballToInstantiate;
8 |
9 | public float LeftBorder;
10 | public float BottomBorder;
11 | public float TopBorder;
12 | public float RightBorder = 350;
13 |
14 | public float CannonballSpeed = 80;
15 |
16 | private List cannonBalls = new List();
17 | private Camera cam;
18 | private float lastShot = 0f;
19 | private HUDmanager hud;
20 |
21 | private void Start()
22 | {
23 | cam = this.gameObject.GetComponentInChildren();
24 | hud = (HUDmanager)GameObject.FindObjectOfType(typeof(HUDmanager));
25 | }
26 |
27 |
28 | // Update is called once per frame
29 | void Update ()
30 | {
31 | if (hud.panelIdx == 0 && Input.GetMouseButton(0))
32 | {
33 | if (Time.realtimeSinceStartup - lastShot > 0.35f)
34 | {
35 | Vector2 invMousePos = new Vector2(Input.mousePosition.x, Screen.height - Input.mousePosition.y);
36 | if (invMousePos.y > 50)
37 | {
38 |
39 | //New Cananball
40 | Transform cannonball = (Transform)Instantiate(CannonballToInstantiate);
41 | Vector3 newForward = cam.ScreenPointToRay(Input.mousePosition).direction;
42 | cannonball.position = cam.transform.position + (newForward * 15f);
43 | cannonball.forward = newForward;
44 | cannonBalls.Add(cannonball);
45 |
46 | lastShot = Time.realtimeSinceStartup;
47 | }
48 | }
49 | }
50 |
51 |
52 | List destroyAndRemove = new List();
53 | foreach (Transform cannonball in cannonBalls)
54 | {
55 | cannonball.position += cannonball.forward * (Time.deltaTime * CannonballSpeed);
56 |
57 | if (cannonball.position.y < -20f)
58 | destroyAndRemove.Add(cannonball);
59 | }
60 |
61 | if (destroyAndRemove.Count > 0)
62 | {
63 | foreach (Transform cannonball in destroyAndRemove)
64 | {
65 | Destroy(cannonball.gameObject);
66 | cannonBalls.Remove(cannonball);
67 | }
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Scripts/FlockingMassive/Cannon.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: d636995327d02ed45bd342e438441c2a
3 | MonoImporter:
4 | serializedVersion: 2
5 | defaultReferences: []
6 | executionOrder: 0
7 | icon: {instanceID: 0}
8 | userData:
9 | assetBundleName:
10 | assetBundleVariant:
11 |
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Scripts/FlockingMassive/FlockHelper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using UnityEngine;
4 |
5 | public static class FlockHelper
6 | {
7 | public static void Shuffle(this IList list)
8 | {
9 | System.Random rng = new System.Random();
10 | int n = list.Count;
11 | while (n > 1)
12 | {
13 | n--;
14 | int k = rng.Next(n + 1);
15 | T value = list[k];
16 | list[k] = list[n];
17 | list[n] = value;
18 | }
19 | }
20 |
21 | public static Vector3 ReflectVector(Vector3 surfaceUpNormalized, Vector3 incommingDirection)
22 | {
23 | return 2f * -Vector3.Dot(incommingDirection, surfaceUpNormalized) * surfaceUpNormalized + incommingDirection;
24 | }
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Scripts/FlockingMassive/FlockHelper.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: e225f75706cc01f4ba1268dfd766cbc4
3 | MonoImporter:
4 | serializedVersion: 2
5 | defaultReferences: []
6 | executionOrder: 0
7 | icon: {instanceID: 0}
8 | userData:
9 | assetBundleName:
10 | assetBundleVariant:
11 |
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Scripts/FlockingMassive/HUDmanager.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 | using System.Collections;
3 | using System.Collections.Generic;
4 |
5 | public class HUDmanager : MonoBehaviour
6 | {
7 | private Vector2 guiScale = new Vector2(1f, 1f);
8 | public float IntroDuration = 3f;
9 | public Texture2D IntroScreen;
10 | private float fadeAlpha = 1f;
11 |
12 |
13 |
14 | public int panelIdx = 0;
15 | private float particleDestinationLerp = 0f;
16 |
17 |
18 | private MassiveFlockingExample flockingManager;
19 | private Transform[] Cubes;
20 |
21 | // Use this for initialization
22 | void Start ()
23 | {
24 | flockingManager = (MassiveFlockingExample)GameObject.FindObjectOfType(typeof(MassiveFlockingExample));
25 |
26 | List cubeList = new List();
27 | GameObject[] colliders = GameObject.FindGameObjectsWithTag("EnvironmentCollider");
28 | foreach (GameObject coll in colliders)
29 | {
30 | if (coll.name == "Cube")
31 | {
32 | cubeList.Add(coll.transform);
33 | }
34 | }
35 |
36 | if (Application.platform == RuntimePlatform.Android || Application.platform == RuntimePlatform.IPhonePlayer)
37 | guiScale = new Vector2(1.5f, 1.5f);
38 |
39 | Cubes = cubeList.ToArray();
40 | UpdateStickToFrame();
41 | }
42 |
43 |
44 |
45 | private void UpdateStickToFrame()
46 | {
47 | flockingManager.FlockingDestinationAttractRadius = Mathf.Lerp(0, flockingManager.FlockingBoundsRadius, particleDestinationLerp);
48 | flockingManager.FlockingDestinationReachedRadius = Mathf.Lerp(0, 20, particleDestinationLerp);
49 | flockingManager.ParticleSize = Mathf.Lerp(1.5f, 2.5f, particleDestinationLerp);
50 |
51 | float cubeScale = Mathf.Lerp(7, 1, particleDestinationLerp);
52 | foreach (Transform cube in Cubes)
53 | cube.localScale = new Vector3(cubeScale, cubeScale, cubeScale);
54 | }
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 | void OnGUI()
71 | {
72 |
73 | GUI.color = panelIdx == 0 ? Color.grey : panelIdx == 1 ? Color.cyan : Color.yellow ;
74 | if (GUI.Button(new Rect(0, 0, Screen.width, 40), panelIdx == 0 ? "Tap here to toggle modes" : panelIdx == 1 ? "Flocking settings" : "Threading settings"))
75 | {
76 | panelIdx ++;
77 | if (panelIdx >= 3)
78 | panelIdx = 0;
79 | }
80 |
81 | GUI.color = Color.white;
82 | Matrix4x4 mBackup = GUI.matrix;
83 |
84 |
85 | //Flocking settings
86 | if (panelIdx == 1)
87 | {
88 | Rect PanelRect = new Rect(0, 50, Screen.width / guiScale.x, 200);
89 | GUIUtility.ScaleAroundPivot(guiScale, Vector2.zero);
90 | GUI.Box(PanelRect, string.Empty);
91 | GUILayout.BeginArea(PanelRect);
92 |
93 |
94 |
95 | //--------------- Stick-to-Frame Slider --------------------
96 | GUILayout.BeginHorizontal();
97 |
98 | if (GUILayout.Button("Randomize", GUILayout.Width(85), GUILayout.Height(85)))
99 | {
100 | //flockingManager.FlockingSteeringSpeed = Random.Range(0f, 4f);
101 | //flockingManager.FlockingBoundsRadius = Random.Range(25f, 150f);
102 |
103 | flockingManager.FlockingSeperationWeight = Random.Range(0, 10f);
104 | flockingManager.FlockingSeperationRadius = Random.Range(0f, flockingManager.FlockingBoundsRadius);
105 |
106 | flockingManager.FlockingCohesionWeight = Random.Range(0, 10f);
107 | flockingManager.FlockingCohesionRadius = Random.Range(0f, flockingManager.FlockingBoundsRadius);
108 |
109 | flockingManager.FlockingAlignmentWeight = Random.Range(0, 10f);
110 | flockingManager.FlockingAlignmentRadius = Random.Range(0f, flockingManager.FlockingBoundsRadius);
111 | }
112 |
113 | GUILayout.BeginVertical();
114 | DrawSlider("Stick to Frame", ref particleDestinationLerp, 0f, 1f);
115 | DrawSlider("BoundsRadius", ref flockingManager.FlockingBoundsRadius, 25f, 150f);
116 | DrawSlider("Steer Speed", ref flockingManager.FlockingSteeringSpeed, 0f, 4f);
117 | GUILayout.EndVertical();
118 |
119 | UpdateStickToFrame();
120 | GUILayout.EndHorizontal();
121 | //--------------- Stick-to-Frame Slider --------------------
122 |
123 |
124 | GUILayout.BeginVertical();
125 | GUILayout.Space(15);
126 |
127 | GUILayout.BeginHorizontal();
128 | GUILayout.BeginVertical();
129 | DrawSlider("Seperation W", ref flockingManager.FlockingSeperationWeight, 0f, 10);
130 | DrawSlider("Alignment W", ref flockingManager.FlockingAlignmentWeight, 0f, 10);
131 | DrawSlider("Cohesion W", ref flockingManager.FlockingCohesionWeight, 0f, 10);
132 | GUILayout.EndVertical();
133 |
134 |
135 | GUILayout.BeginVertical();
136 | DrawSlider("Seperation R", ref flockingManager.FlockingSeperationRadius, 0f, flockingManager.FlockingBoundsRadius);
137 | DrawSlider("Alignment R", ref flockingManager.FlockingAlignmentRadius, 0f, flockingManager.FlockingBoundsRadius);
138 | DrawSlider("Cohesion R", ref flockingManager.FlockingCohesionRadius, 0f, flockingManager.FlockingBoundsRadius);
139 | GUILayout.EndVertical();
140 |
141 | GUILayout.EndHorizontal();
142 | GUILayout.EndVertical();
143 | GUILayout.EndArea();
144 |
145 | GUI.matrix = mBackup;
146 | }
147 |
148 | //Threading Settings
149 | else if (panelIdx == 2)
150 | {
151 | Rect PanelRect = new Rect(0, 50, Screen.width / guiScale.x, 100);
152 | GUIUtility.ScaleAroundPivot(guiScale, Vector2.zero);
153 | GUI.Box(PanelRect, string.Empty);
154 | GUILayout.BeginArea(PanelRect);
155 |
156 | GUILayout.BeginVertical();
157 | GUILayout.BeginHorizontal();
158 |
159 | GUI.color = flockingManager.MultithreadingEnabled ? Color.green : Color.red;
160 | if (GUILayout.Button(flockingManager.MultithreadingEnabled ? "Multi Threading Enabled" : " Multi Threading Disabled", GUILayout.Height(50)))
161 | flockingManager.MultithreadingEnabled = !flockingManager.MultithreadingEnabled;
162 |
163 | GUI.color = Color.white;
164 | if (GUILayout.Button("Add 500 boids", GUILayout.Height(50)))
165 | flockingManager.FlockingSpawnCount += 500;
166 |
167 | if (GUILayout.Button("Remove 500 boids", GUILayout.Height(50)))
168 | flockingManager.FlockingSpawnCount = Mathf.Max(0, flockingManager.FlockingSpawnCount - 500);
169 |
170 | GUILayout.EndHorizontal();
171 | GUILayout.BeginHorizontal();
172 |
173 | GUI.color = Color.white;
174 | GUILayout.Space(20);
175 | GUI.enabled = flockingManager.MultithreadingEnabled;
176 |
177 | GUILayout.BeginVertical();
178 | DrawTextField("Number of Threads", ref flockingManager.ThreadingMaxThreads);
179 | GUILayout.EndVertical();
180 |
181 | GUI.enabled = true;
182 |
183 | GUILayout.EndHorizontal();
184 | GUILayout.EndVertical();
185 | GUILayout.EndArea();
186 | GUI.matrix = mBackup;
187 | }
188 |
189 |
190 | //--------------- FPS Feedback --------------------
191 | if (flockingManager.myThreadScheduler != null)
192 | {
193 | Rect totalBar = new Rect(20, Screen.height - 125, 350, 25);
194 | DrawProgressBar(totalBar, "FLocking Behaviour Progress: ", flockingManager.myThreadScheduler.Progress);
195 | }
196 |
197 | Rect particleCountRect = new Rect(20, Screen.height - 100, 350, 25);
198 | GUI.Label(particleCountRect, "Number of Boids: " + flockingManager.FlockingSpawnCount);
199 |
200 | Rect flockingFpsRect = new Rect(20, Screen.height - 75, 350, 20);
201 | GUI.Label(flockingFpsRect, "FLocking Behaviour FPS: " + (1f / flockingManager.flockingUpdateTime));
202 |
203 | Rect gameFpsRect = new Rect(20, Screen.height - 50, 350, 20);
204 | float gameFPS = (1f / Time.deltaTime);
205 |
206 | GUI.color = gameFPS < 20f ? Color.red : Color.white;
207 | GUI.Label(gameFpsRect, "Game FPS: " + gameFPS);
208 |
209 | GUI.color = Color.white;
210 | //--------------- FPS Feedback --------------------
211 |
212 |
213 | //--------------- Intro Screen --------------------
214 | if (Time.realtimeSinceStartup < IntroDuration)
215 | {
216 | GUI.DrawTexture(new Rect(0f, 0f, Screen.width, Screen.height), IntroScreen, ScaleMode.ScaleAndCrop);
217 | }
218 | else
219 | {
220 | fadeAlpha -= Time.deltaTime;
221 | if (fadeAlpha > 0f)
222 | {
223 | GUI.color = new Color(1f, 1f, 1f, fadeAlpha);
224 | GUI.DrawTexture(new Rect(0f, 0f, Screen.width, Screen.height), IntroScreen, ScaleMode.ScaleAndCrop);
225 | }
226 | else
227 | {
228 | GUI.enabled = true;
229 | }
230 | }
231 | //--------------- Intro Screen --------------------
232 |
233 | }
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 | //--------------- GUI Calls --------------------
242 | private void DrawTextField(string prefix, ref int value)
243 | {
244 | GUILayout.BeginHorizontal();
245 | GUILayout.Label(prefix + ": ", GUILayout.Width(150));
246 |
247 | string strValue = value.ToString();
248 | strValue = GUILayout.TextField(strValue);
249 | int.TryParse(strValue, out value);
250 |
251 | GUILayout.EndHorizontal();
252 | }
253 |
254 | private void DrawSlider(string prefix, ref float value, float minValue, float maxValue)
255 | {
256 | GUILayout.BeginHorizontal();
257 | GUILayout.Label(prefix + ": " + RoundWithPrecision(value, 1).ToString(), GUILayout.Width(125));
258 |
259 | if (GUILayout.Button("-", GUILayout.Width(30), GUILayout.Height(25)))
260 | value = Mathf.Clamp(value - ((maxValue - minValue) / 5f), minValue, maxValue);
261 |
262 | value = GUILayout.HorizontalSlider(value, minValue, maxValue);
263 |
264 | if (GUILayout.Button("+", GUILayout.Width(30), GUILayout.Height(25)))
265 | value = Mathf.Clamp(value + ((maxValue - minValue) / 5f), minValue, maxValue);
266 |
267 | GUILayout.EndHorizontal();
268 | }
269 |
270 | public static float RoundWithPrecision(float value, int precision)
271 | {
272 | float multiplier = Mathf.Pow(10, (float)precision);
273 | value *= multiplier;
274 | value = Mathf.Round(value);
275 |
276 | return value / multiplier;
277 | }
278 |
279 |
280 | private void DrawProgressBar(Rect rect, string prefix, float progress)
281 | {
282 | GUI.Box(rect, prefix + Mathf.Round(progress * 100f).ToString());
283 | rect.width *= progress;
284 |
285 | GUI.color = Color.green;
286 | GUI.Box(rect, string.Empty);
287 | GUI.color = Color.white;
288 | }
289 |
290 | //--------------- GUI Calls --------------------
291 |
292 | }
293 |
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Scripts/FlockingMassive/HUDmanager.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 1d891166f7cfb714ea54e74712261412
3 | MonoImporter:
4 | serializedVersion: 2
5 | defaultReferences: []
6 | executionOrder: 0
7 | icon: {instanceID: 0}
8 | userData:
9 | assetBundleName:
10 | assetBundleVariant:
11 |
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Scripts/FlockingMassive/MassiveFlockingExample.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 | using System.Collections;
3 | using System.Collections.Generic;
4 | using Frankfort.Threading;
5 |
6 |
7 | public class MassiveFlockingExample : MonoBehaviour
8 | {
9 | public bool FlockingDebugMode = false;
10 | public int TargetFrameRate = 30;
11 | public float ParticleSize = 3f;
12 | public float ParticleColorLerpSpeed = 3f;
13 | public int FlockingSpawnCount = 10000;
14 | public int FlockingMaxRandomSiblingsTested = 500;
15 |
16 | public float FlockingMaxSpawnRadius = 50f;
17 | public float FlockingStartVelocityMin = 15f;
18 | public float FlockingStartVelocityMax = 20f;
19 | public float FlockingSteeringSpeed = 0.5f;
20 |
21 | public float FlockingSeperationWeight = 1f;
22 | public float FlockingAlignmentWeight = 1f;
23 | public float FlockingCohesionWeight = 1f;
24 |
25 | public float FlockingSeperationRadius = 10;
26 | public float FlockingAlignmentRadius = 30;
27 | public float FlockingCohesionRadius = 75f;
28 |
29 | public float FlockingDestinationAttractRadius = 0f;
30 | public float FlockingDestinationReachedRadius = 0f;
31 | public float FlockingBoundsRadius = 100f;
32 |
33 |
34 | public bool MultithreadingEnabled = false;
35 | public int ThreadingMaxThreads = -1;
36 | public int ThreadingPackagesPerThread = 4;
37 |
38 | private FlockData[] flockers;
39 | private EnvironmentCollider[] colliders;
40 | private Vector3[] destinationPoints;
41 |
42 | private ParticleSystem flockParticleEmitter;
43 | private FlockingDataWorker[] workerObjects;
44 |
45 | public ThreadPoolScheduler myThreadScheduler;
46 |
47 | private float flockingStartTime = 0;
48 | public float flockingUpdateTime = 0;
49 |
50 |
51 | void awake()
52 | {
53 | Application.targetFrameRate = TargetFrameRate;
54 | }
55 |
56 |
57 | // Use this for initialization
58 | void Start ()
59 | {
60 | flockParticleEmitter = this.gameObject.GetComponentInChildren();
61 |
62 |
63 | //--------------- Gather all colliders --------------------
64 | colliders = GetColliders();
65 | //--------------- Gather all colliders --------------------
66 |
67 |
68 | //--------------- Gather all Destination points --------------------
69 | destinationPoints = GetDestinationPoints();
70 | destinationPoints.Shuffle();
71 | //--------------- Gather all Destination points --------------------
72 |
73 |
74 | //--------------- Spawn Flocks --------------------
75 | flockers = new FlockData[FlockingSpawnCount];
76 | int i = FlockingSpawnCount;
77 |
78 | Vector3 center = this.transform.position;
79 | while (--i > -1)
80 | SpawnRandomFlockSpherical(center, flockers, i);
81 | //--------------- Spawn Flocks --------------------
82 |
83 |
84 |
85 | //--------------- For each Flock, spawn a Particle--------------------
86 | if (flockParticleEmitter != null)
87 | {
88 | ParticleSystem.Particle[] particles = new ParticleSystem.Particle[FlockingSpawnCount];
89 | i = FlockingSpawnCount;
90 | while (--i > -1)
91 | SpawnNewParticle(particles, i);
92 |
93 | flockParticleEmitter.SetParticles(particles, particles.Length);
94 | flockParticleEmitter.Play();
95 | }
96 | //--------------- For each Flock, spawn a Particle --------------------
97 |
98 | InitThreadPool();
99 | }
100 |
101 |
102 | private void InitThreadPool()
103 | {
104 | //--------------- Cap the number of threads --------------------
105 | int maxThreads = ThreadingMaxThreads;
106 | if (maxThreads <= 0)
107 | maxThreads = Mathf.Max(SystemInfo.processorCount - 1, 1);
108 | //--------------- Cap the number of threads --------------------
109 |
110 | //--------------- Spread the Flocks over multiple worker-packages --------------------
111 | int ThreadingPoolPackages = ThreadingPackagesPerThread * maxThreads;
112 |
113 | int flocksPerBlock = Mathf.CeilToInt((float)FlockingSpawnCount / (float)ThreadingPoolPackages);
114 | workerObjects = new FlockingDataWorker[ThreadingPoolPackages];
115 |
116 | int i = ThreadingPoolPackages;
117 | int startIdx = 0;
118 | while (--i > -1)
119 | {
120 | FlockingDataWorker workerBlock = new FlockingDataWorker();
121 | UpdateWorkerObjectStats(workerBlock);
122 |
123 | workerBlock.startWorkIndex = startIdx;
124 | workerBlock.endWorkIndex = Mathf.Min(flockers.Length, startIdx + flocksPerBlock);
125 | workerObjects[i] = workerBlock;
126 | startIdx += flocksPerBlock;
127 | }
128 | //--------------- Spread the Flocks over multiple worker-packages --------------------
129 |
130 |
131 | myThreadScheduler = Loom.CreateThreadPoolScheduler();
132 | myThreadScheduler.ForceToMainThread = !MultithreadingEnabled;
133 | myThreadScheduler.StartASyncThreads(workerObjects, onThreadWorkComplete, null, maxThreads);
134 | }
135 |
136 | private void RestartThreadPoolWork()
137 | {
138 | //if (tickTock && !myThreadScheduler.isBusy && workerObjects != null)
139 | if (workerObjects != null)
140 | {
141 | //--------------- Update WorkerObjects first--------------------
142 | colliders = GetColliders();
143 |
144 | int i = workerObjects.Length;
145 | while (--i > -1)
146 | UpdateWorkerObjectStats(workerObjects[i]);
147 | //--------------- Update WorkerObjects first --------------------
148 |
149 | //--------------- Then restart the calculations --------------------
150 | myThreadScheduler.ForceToMainThread = !MultithreadingEnabled;
151 | myThreadScheduler.StartASyncThreads(workerObjects, onThreadWorkComplete, null, ThreadingMaxThreads);
152 | //--------------- Then restart the calculations --------------------
153 | }
154 | }
155 |
156 |
157 |
158 |
159 | private EnvironmentCollider[] GetColliders()
160 | {
161 | GameObject[] collGOs = GameObject.FindGameObjectsWithTag("EnvironmentCollider");
162 |
163 | EnvironmentCollider[] result = new EnvironmentCollider[collGOs.Length];
164 | int i = collGOs.Length;
165 | while(--i > -1)
166 | {
167 | MeshFilter filter = collGOs[i].gameObject.GetComponentInChildren();
168 | if(filter != null)
169 | {
170 | Vector3 sizeRadius = Vector3.Scale( filter.mesh.bounds.extents, collGOs[i].transform.localScale);
171 | result[i] = new EnvironmentCollider(collGOs[i].transform.position, Mathf.Max(sizeRadius.x, sizeRadius.y, sizeRadius.z) * 1.2f);
172 | }
173 | }
174 | return result;
175 | }
176 |
177 |
178 |
179 | private Vector3[] GetDestinationPoints()
180 | {
181 | List result = new List();
182 |
183 | GameObject[] destGOs = GameObject.FindGameObjectsWithTag("ParticleDestination");
184 | int i = destGOs.Length;
185 | while (--i > -1)
186 | {
187 | Transform goTransform = destGOs[i].transform;
188 | MeshFilter filter = destGOs[i].gameObject.GetComponentInChildren();
189 | if (filter != null)
190 | {
191 | Vector3[] verts = filter.mesh.vertices;
192 | int j = verts.Length;
193 | while (--j > -1)
194 | verts[j] = goTransform.TransformPoint(verts[j]);
195 |
196 | result.AddRange(verts);
197 | }
198 | }
199 |
200 | return result.ToArray();
201 | }
202 |
203 |
204 |
205 | private void SpawnRandomFlockSpherical(Vector3 center, FlockData[] storeTo, int index)
206 | {
207 | Vector3 randomDirection = new Vector3(Random.Range(-1f, 1f), Random.Range(-1f, 1f), Random.Range(-1f, 1f)).normalized;
208 | Vector3 randomOrientation = new Vector3(Random.Range(-1f, 1f), Random.Range(-1f, 1f), Random.Range(-1f, 1f)).normalized;
209 | Vector3 pos = center + (randomDirection * Random.Range(0f, FlockingMaxSpawnRadius));
210 |
211 | FlockData flock = new FlockData();
212 | flock.position = pos;
213 | flock.currentDirection = randomOrientation;
214 | flock.targetDirection = randomOrientation;
215 | flock.targetVelocity = Random.Range(FlockingStartVelocityMin, FlockingStartVelocityMax);
216 |
217 | if (index < destinationPoints.Length)
218 | flock.destinationPoint = destinationPoints[index];
219 |
220 | storeTo[index] = flock;
221 | }
222 |
223 | private void SpawnNewParticle(ParticleSystem.Particle[] storeTo, int index)
224 | {
225 | ParticleSystem.Particle particle = new ParticleSystem.Particle();
226 | particle.position = flockers[index].position;
227 | particle.startLifetime = float.MaxValue;
228 | particle.lifetime = float.MaxValue;
229 | particle.size = ParticleSize;
230 | particle.color = Color.white;
231 | storeTo[index] = particle;
232 | }
233 |
234 |
235 | private void UpdateWorkerObjectStats(FlockingDataWorker flockingDataWorker)
236 | {
237 | flockingDataWorker.universeCenter = this.transform.position;
238 | flockingDataWorker.AllFlocks = flockers;
239 | flockingDataWorker.AllColliders = colliders;
240 | flockingDataWorker.maxRandomSiblingsTested = FlockingMaxRandomSiblingsTested;
241 | flockingDataWorker.maxBoundsRadius = FlockingBoundsRadius;
242 | flockingDataWorker.seperationWeight = FlockingSeperationWeight;
243 | flockingDataWorker.seperationRadius = FlockingSeperationRadius;
244 | flockingDataWorker.alignmentWeight = FlockingAlignmentWeight;
245 | flockingDataWorker.alignmentRadius = FlockingAlignmentRadius;
246 | flockingDataWorker.cohesionWeight = FlockingCohesionWeight;
247 | flockingDataWorker.cohesionRadius = FlockingCohesionRadius;
248 | flockingDataWorker.destinationAttractRadius = FlockingDestinationAttractRadius;
249 | flockingDataWorker.destinationReachedRadius = FlockingDestinationReachedRadius;
250 | }
251 |
252 |
253 | private void onThreadWorkComplete(IThreadWorkerObject[] finishedObjects)
254 | {
255 | flockingUpdateTime = Time.realtimeSinceStartup - flockingStartTime;
256 | flockingStartTime = Time.realtimeSinceStartup;
257 |
258 | //--------------- Resize arrays if needed --------------------
259 | if (flockers.Length != FlockingSpawnCount)
260 | {
261 | int startCount = flockers.Length;
262 | System.Array.Resize(ref flockers, FlockingSpawnCount);
263 |
264 | ParticleSystem.Particle[] particles = new ParticleSystem.Particle[flockParticleEmitter.particleCount];
265 | flockParticleEmitter.GetParticles(particles);
266 | System.Array.Resize(ref particles, FlockingSpawnCount);
267 |
268 | if (startCount < FlockingSpawnCount)
269 | {
270 | Vector3 center = this.transform.position;
271 | for (int i = startCount; i < FlockingSpawnCount; i++)
272 | {
273 | SpawnRandomFlockSpherical(center, flockers, i);
274 | SpawnNewParticle(particles, i);
275 | }
276 | }
277 | flockParticleEmitter.SetParticles(particles, particles.Length);
278 |
279 | if (myThreadScheduler != null)
280 | Destroy(myThreadScheduler.gameObject);
281 |
282 | //Reinit the threadpool
283 | InitThreadPool();
284 | }
285 | else
286 | {
287 | //Restart the threadpool
288 | RestartThreadPoolWork();
289 | }
290 | //--------------- Resize arrays if needed --------------------
291 |
292 | }
293 |
294 |
295 |
296 |
297 |
298 |
299 | // Update is called once per frame
300 | void Update ()
301 | {
302 | //--------------- Get particles to alter --------------------
303 | ParticleSystem.Particle[] particles = new ParticleSystem.Particle[flockParticleEmitter.particleCount];
304 | flockParticleEmitter.GetParticles(particles);
305 | //--------------- Get particles to alter --------------------
306 |
307 |
308 |
309 | int i = Mathf.Min(flockers.Length, particles.Length); //Should be the same, but hey...
310 | while (--i > -1)
311 | {
312 | //--------------- Update Flocking positions based on Velocity and targetDirection --------------------
313 | FlockData flock = flockers[i];
314 | flock.currentDirection = Vector3.Slerp(flock.currentDirection, flock.targetDirection, Time.deltaTime * FlockingSteeringSpeed);
315 | flock.position += flock.currentDirection * (Time.deltaTime * flock.currentVelocity);
316 | flock.currentColor = Color.Lerp(flock.currentColor, flock.targetColor, Time.deltaTime * ParticleColorLerpSpeed);
317 | //--------------- Update Flocking positions based on Velocity and targetDirection --------------------
318 |
319 | //--------------- Update assosiated particle --------------------
320 | particles[i].position = flock.position;
321 | particles[i].lifetime = float.MaxValue;
322 | particles[i].color = flock.currentColor;
323 | particles[i].size = ParticleSize;
324 | //--------------- Update assosiated particle --------------------
325 |
326 | if (FlockingDebugMode)
327 | {
328 | Debug.DrawRay(flock.position, flock.targetDirection * 2f, Color.white);
329 | Debug.DrawRay(flock.position, flock.currentDirection * 2f, Color.red);
330 | }
331 | }
332 |
333 | flockParticleEmitter.SetParticles(particles, particles.Length);
334 | }
335 | }
336 |
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Scripts/FlockingMassive/MassiveFlockingExample.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 06775bb744db53240a14a12dd4579847
3 | MonoImporter:
4 | serializedVersion: 2
5 | defaultReferences: []
6 | executionOrder: 0
7 | icon: {instanceID: 0}
8 | userData:
9 | assetBundleName:
10 | assetBundleVariant:
11 |
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Scripts/FlockingMassive/MovingBodies.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 | using System.Collections;
3 |
4 | public class MovingBodies : MonoBehaviour
5 | {
6 | public Transform rotateAroundTarget;
7 | public Vector3 rotateAroundAxis = Vector3.up;
8 | public float rotateAroundSpeed;
9 |
10 | private float angle;
11 |
12 |
13 | // Update is called once per frame
14 | void Update ()
15 | {
16 | this.transform.RotateAround(rotateAroundTarget.position, rotateAroundAxis, Time.deltaTime * rotateAroundSpeed);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Scripts/FlockingMassive/MovingBodies.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 95ae2982143650543879a70c590d86d7
3 | MonoImporter:
4 | serializedVersion: 2
5 | defaultReferences: []
6 | executionOrder: 0
7 | icon: {instanceID: 0}
8 | userData:
9 | assetBundleName:
10 | assetBundleVariant:
11 |
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Scripts/FlockingMassive/ThreadedFlocking.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using UnityEngine;
4 | using Frankfort.Threading;
5 |
6 |
7 |
8 | public class FlockData
9 | {
10 | public Vector3 position;
11 | public Vector3 currentDirection;
12 | public Vector3 targetDirection;
13 | public Color targetColor;
14 | public Color currentColor;
15 | public Vector3 destinationPoint;
16 | public float targetVelocity;
17 | public float currentVelocity;
18 | }
19 |
20 |
21 | public struct EnvironmentCollider
22 | {
23 | public Vector3 position;
24 | public float radius;
25 | public float radiusSqr;
26 |
27 | public EnvironmentCollider(Vector3 position, float radius)
28 | {
29 | this.position = position;
30 | this.radius = radius;
31 | this.radiusSqr = radius * radius;
32 | }
33 | }
34 |
35 |
36 | public class FlockingDataWorker : IThreadWorkerObject
37 | {
38 |
39 | //--------------- Flock Frame/Cycledata --------------------
40 | public FlockData[] AllFlocks;
41 | public EnvironmentCollider[] AllColliders;
42 | public int startWorkIndex;
43 | public int endWorkIndex;
44 | public int maxRandomSiblingsTested;
45 |
46 | public Vector3 universeCenter;
47 | public float maxBoundsRadius;
48 |
49 | public float seperationWeight;
50 | public float alignmentWeight;
51 | public float cohesionWeight;
52 |
53 | private float _seperationRadius;
54 | private float _seperationRadiusSqr;
55 | private float _alignmentRadius;
56 | private float _alignmentRadiusSqr;
57 | private float _cohesionRadius;
58 | private float _cohesionRadiusSqr;
59 | private float _destinationAttractRadius;
60 | private float _destinationAttractRadiusSqr;
61 | public float destinationReachedRadius;
62 |
63 |
64 | public float seperationRadius
65 | {
66 | get { return _seperationRadius; }
67 | set { _seperationRadius = value; _seperationRadiusSqr = value * value; }
68 | }
69 | public float alignmentRadius
70 | {
71 | get { return _alignmentRadius; }
72 | set { _alignmentRadius = value; _alignmentRadiusSqr = value * value; }
73 | }
74 |
75 | public float cohesionRadius
76 | {
77 | get { return _cohesionRadius; }
78 | set { _cohesionRadius = value; _cohesionRadiusSqr = value * value; }
79 | }
80 | public float destinationAttractRadius
81 | {
82 | get { return _destinationAttractRadius; }
83 | set { _destinationAttractRadius = value; _destinationAttractRadiusSqr = value * value; }
84 | }
85 |
86 |
87 | public float seperationRadiusSqr
88 | {
89 | get { return _seperationRadiusSqr; }
90 | }
91 | public float alignmentRadiusSqr
92 | {
93 | get { return _alignmentRadiusSqr; }
94 | }
95 | public float cohesionRadiusSqr
96 | {
97 | get { return _cohesionRadiusSqr; }
98 | }
99 | public float destinationAttractRadiusSqr
100 | {
101 | get { return _destinationAttractRadiusSqr; }
102 | }
103 | //--------------- Flock Frame/Cycledata --------------------
104 |
105 |
106 |
107 |
108 | //--------------- IThreadWorker Implementation --------------------
109 | private bool isAborted = false;
110 |
111 | public void AbortThreadedWork()
112 | {
113 | isAborted = true;
114 | }
115 | //--------------- IThreadWorker Implementation --------------------
116 |
117 |
118 |
119 |
120 | public void ExecuteThreadedWork()
121 | {
122 | startWorkIndex = Mathf.Clamp(startWorkIndex, 0, AllFlocks.Length);
123 | endWorkIndex = Mathf.Clamp(endWorkIndex, 0, AllFlocks.Length);
124 |
125 | //--------------- Creat list with indexes --------------------
126 | int[] randomIndexes = new int[AllFlocks.Length];
127 | int i = AllFlocks.Length;
128 | while (--i > -1)
129 | randomIndexes[i] = i;
130 |
131 | //--------------- Creat list with indexes --------------------
132 |
133 |
134 | for (i = startWorkIndex; i < endWorkIndex && !isAborted; i++)
135 | {
136 | //--------------- Shuffle indexes every-something-flocks --------------------
137 | if ((float)i % (float)maxRandomSiblingsTested == 0f)
138 | randomIndexes.Shuffle();
139 | //--------------- Shuffle indexes every-something-flocks --------------------
140 |
141 | FlockData flock = AllFlocks[i];
142 |
143 | if (flock.position.y < 0f) //Through the ground....
144 | {
145 | flock.position.y = -flock.position.y;
146 | flock.targetDirection.y = Mathf.Abs(flock.targetDirection.y);
147 | flock.currentDirection = flock.targetDirection;
148 | flock.currentColor = flock.targetColor = new Color(1f, 1f, 0f, 0.65f);
149 | flock.currentVelocity = flock.targetVelocity;
150 | }
151 | else
152 | {
153 | Vector3 toCenterVec = universeCenter - flock.position;
154 | if (toCenterVec.sqrMagnitude > maxBoundsRadius * maxBoundsRadius) //If outside of univere limits
155 | {
156 | flock.targetDirection = toCenterVec.normalized;
157 | flock.targetColor = new Color(1f, 0f, 1f, 0.25f);
158 | flock.currentVelocity = flock.targetVelocity;
159 | }
160 | else
161 | {
162 | //--------------- Check for Collisions --------------------
163 | bool isColliding = false;
164 | int j = AllColliders.Length;
165 |
166 | Vector3 collisionAvoidenceDir = Vector3.zero;
167 | while (--j > -1 && !isAborted)
168 | {
169 | EnvironmentCollider coll = AllColliders[j];
170 | Vector3 diffVec = coll.position - flock.position;
171 |
172 | if (diffVec.sqrMagnitude < coll.radiusSqr)
173 | {
174 | isColliding = true;
175 | Vector3 invDiff = -diffVec.normalized;
176 | Vector3 reflectionDir = FlockHelper.ReflectVector(invDiff, flock.currentDirection);
177 | collisionAvoidenceDir += reflectionDir;
178 | flock.position = coll.position + (invDiff * coll.radius);
179 | }
180 | }
181 | //--------------- Check for Collisions --------------------
182 |
183 | if (isColliding) //If Colliding
184 | {
185 | flock.targetDirection = flock.currentDirection = collisionAvoidenceDir.normalized;
186 | flock.currentColor = flock.targetColor = new Color(1f, 0.1f, 0f, 0.85f);
187 | flock.currentVelocity = flock.targetVelocity * 2f;
188 | }
189 | else
190 | {
191 | Vector3 diffDestionation = flock.destinationPoint - flock.position;
192 | if (diffDestionation.sqrMagnitude < destinationAttractRadiusSqr) //If close to unique target point...
193 | {
194 | flock.targetDirection = diffDestionation.normalized;
195 | float lerpT = Mathf.Clamp01(diffDestionation.magnitude / destinationReachedRadius);
196 | flock.currentVelocity = flock.targetVelocity * lerpT;
197 | flock.targetColor = Color.Lerp(new Color(0f, 1f, 0f, 1f), new Color(1f, 1f, 1f, 0.15f), lerpT);
198 | }
199 | else
200 | {
201 | Vector3 combinedDirection = flock.targetDirection;
202 | Vector3 combinedColor = Vector3.zero;
203 |
204 | j = Mathf.Min(AllFlocks.Length, maxRandomSiblingsTested);
205 | while (--j > -1 && !isAborted)
206 | {
207 |
208 | //--------------- Get a random sibling --------------------
209 | int randomIndex = randomIndexes[j];
210 | if (i == randomIndex)
211 | continue;
212 | FlockData sibling = AllFlocks[randomIndex];
213 | //--------------- Get a random sibling --------------------
214 |
215 |
216 | Vector3 diffVec = sibling.position - flock.position;
217 | float distSqr = diffVec.sqrMagnitude;
218 |
219 | if (distSqr < seperationRadiusSqr)
220 | {
221 | combinedDirection += Vector3.Cross(flock.currentDirection, diffVec.normalized) * seperationWeight;
222 | combinedColor.y += seperationWeight; //y == green;
223 | }
224 | //else if (distSqr < alignmentRadiusSqr)
225 | if (distSqr < alignmentRadiusSqr)
226 | {
227 | combinedDirection += sibling.currentDirection * alignmentWeight;
228 | combinedColor.z += alignmentWeight; //z == blue;
229 | }
230 | //else if (distSqr < cohesionRadiusSqr)
231 | if (distSqr < cohesionRadiusSqr)
232 | {
233 | combinedDirection += diffVec.normalized * cohesionWeight;
234 | combinedColor += new Vector3(cohesionWeight, cohesionWeight, cohesionWeight); //Add white
235 | }
236 | }
237 |
238 | flock.targetDirection = combinedDirection.normalized;
239 | flock.currentVelocity = flock.targetVelocity;
240 | combinedColor.Normalize();
241 | flock.targetColor = new Color(combinedColor.x, combinedColor.y, combinedColor.z, 0.15f);
242 | }
243 | }
244 | }
245 | }
246 | }
247 | }
248 |
249 | }
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Scripts/FlockingMassive/ThreadedFlocking.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 271342b3c6fbfa741b8a107ce3997267
3 | MonoImporter:
4 | serializedVersion: 2
5 | defaultReferences: []
6 | executionOrder: 0
7 | icon: {instanceID: 0}
8 | userData:
9 | assetBundleName:
10 | assetBundleVariant:
11 |
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Scripts/Simple Implementations.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 84c06b5da589be54397746f0ce5dae32
3 | folderAsset: yes
4 | timeCreated: 1496323769
5 | licenseType: Free
6 | DefaultImporter:
7 | userData:
8 | assetBundleName:
9 | assetBundleVariant:
10 |
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Scripts/Simple Implementations/SimpleThreadingExample.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using UnityEngine;
3 | using Frankfort.Threading;
4 | using System.Threading;
5 | using System.Collections;
6 |
7 |
8 | public class SimpleThreadingExample : MonoBehaviour
9 | {
10 | // TEST>>>>>>>>>>>>>>>>>>>>>>>>>>
11 |
12 | public int maxThreads = 2;
13 | public int TestWorkerObjects = 40;
14 | public int minCalculations = 10000000;
15 | public int maxCalculations = 50000000;
16 | public float abortAfterSeconds = 3f;
17 |
18 | public Thread threadA;
19 | public Thread threadB;
20 |
21 | private ThreadPoolScheduler myThreadScheduler;
22 |
23 | void Awake()
24 | {
25 | Application.targetFrameRate = 25;
26 | myThreadScheduler = Loom.CreateThreadPoolScheduler();
27 |
28 | //--------------- Ending Single threaded routine --------------------
29 | threadA = Loom.StartSingleThread(EndingSingleThreadCoroutine, System.Threading.ThreadPriority.Normal, true);
30 | //--------------- Ending Single threaded routine --------------------
31 |
32 | //--------------- Continues Single threaded routine --------------------
33 | threadB = Loom.StartSingleThread(ContinuesSingleThreadCoroutine, System.Threading.ThreadPriority.Normal, true);
34 | //--------------- Continues Single threaded routine --------------------
35 |
36 | //--------------- Start Multithreaded packages --------------------
37 | int i = TestWorkerObjects;
38 | IThreadWorkerObject[] workerObjects = new IThreadWorkerObject[TestWorkerObjects];
39 |
40 | while (--i > -1)
41 | workerObjects[i] = new LotsOfNumbers(UnityEngine.Random.Range(minCalculations, maxCalculations));
42 |
43 | myThreadScheduler.StartASyncThreads(workerObjects, OnThreadWorkComplete, OnWorkerObjectDone, maxThreads);
44 | StartCoroutine(AbortAllThreadsAfterDelay());
45 | //--------------- Start Multithreaded packages --------------------
46 | }
47 |
48 |
49 |
50 |
51 |
52 | //--------------- Managing a simple single Thread --------------------
53 | private void EndingSingleThreadCoroutine()
54 | {
55 | Debug.Log("Starting an Coroutine on a seperate Thread!");
56 |
57 | Loom.WaitForNextFrame(30);
58 | Loom.DispatchToMainThread(() => Debug.Log("I waited atleast 30 frames. Whats the current frameCount? : " + Time.frameCount), true);
59 |
60 | Loom.WaitForSeconds(10);
61 | Loom.DispatchToMainThread(() => Debug.Log("I waited atleast 10 seconds. Whats the current frameCount? : " + Time.frameCount), true);
62 |
63 | //Throw error to show safemode nicely throws errors in the MainThread.
64 |
65 | Debug.LogWarning("About the throw an error...");
66 | throw new Exception("This is an safe Error and should showup in the Console");
67 |
68 | Debug.Log("It won't get here, but the Thread will die anyways.");
69 | }
70 |
71 |
72 |
73 | private void ContinuesSingleThreadCoroutine()
74 | {
75 | Debug.Log("Starting an never ending Coroutine on a seperate Thread!");
76 | while (true)
77 | {
78 | Loom.WaitForNextFrame(10);
79 | Loom.DispatchToMainThread(() => Debug.Log("I waited atleast 10 frames. Whats the current frameCount? : " + Time.frameCount), true);
80 |
81 | Loom.WaitForSeconds(1);
82 | Loom.DispatchToMainThread(() => Debug.Log("I waited atleast 1 second. Whats the current frameCount? : " + Time.frameCount), true);
83 | }
84 | Debug.Log("It will never get here, but thats oke...");
85 | }
86 | //--------------- Managing a simple single Thread --------------------
87 |
88 |
89 |
90 |
91 |
92 |
93 | //--------------- Managing a simple multithreaded ThreadPoolScheduler implementation --------------------
94 | public void OnWorkerObjectDone(IThreadWorkerObject finishedObj)
95 | {
96 | LotsOfNumbers fCast = (LotsOfNumbers)finishedObj;
97 | Debug.LogWarning("Object done! result: " + fCast.result + ", maxIterations: " + fCast.maxIterations + ", ID: " + Thread.CurrentThread.ManagedThreadId + ", progress: " + (myThreadScheduler.Progress * 100f));
98 | }
99 |
100 | public void OnThreadWorkComplete(IThreadWorkerObject[] finishedObjects)
101 | {
102 | Debug.LogWarning("All work done! Managed Thread ID:" + Thread.CurrentThread.ManagedThreadId);
103 | }
104 | private IEnumerator AbortAllThreadsAfterDelay()
105 | {
106 | yield return new WaitForSeconds(abortAfterSeconds);
107 |
108 | if (myThreadScheduler.isBusy) //Threaded work didn't finish in the meantime: time to abort.
109 | {
110 | Debug.Log("Terminate all worker Threads.");
111 | myThreadScheduler.AbortASyncThreads();
112 |
113 | Debug.Log("Terminate thread A & B.");
114 | if (threadA != null && threadA.IsAlive)
115 | threadA.Abort();
116 |
117 | if (threadB != null && threadB.IsAlive)
118 | threadB.Abort();
119 | }
120 | }
121 | //--------------- Managing a simple multithreaded ThreadPoolScheduler implementation --------------------
122 |
123 | }
124 |
125 |
126 |
127 |
128 | public class LotsOfNumbers : IThreadWorkerObject
129 | {
130 | private bool isAborted;
131 | public long maxIterations = 0;
132 | public long result = 0;
133 |
134 |
135 | public LotsOfNumbers(long maxIterations)
136 | {
137 | this.maxIterations = maxIterations;
138 | }
139 |
140 | public void ExecuteThreadedWork()
141 | {
142 | long i = maxIterations;
143 | while (--i > -1 && !isAborted)
144 | {
145 | //This lightweight method checks if Unity is still active.
146 | //If your app lozes focus or gets pauzed, it will sleep the thread.
147 | //If the application quits, it will abort the thread.
148 | Loom.SleepOrAbortIfUnityInactive();
149 |
150 | if (i == (maxIterations / 2))
151 | {
152 | Loom.DispatchToMainThread(() =>
153 | Debug.Log("Dispatch: is this the MainThread? " + Loom.CheckIfMainThread()), true);
154 |
155 | Debug.Log("From WorkerThread: is this the MainThread? " + Loom.CheckIfMainThread());
156 |
157 | GameObject cube = (GameObject)Loom.DispatchToMainThreadReturn(TestThreadSafeDispatch, true);
158 | Loom.DispatchToMainThread(() => cube.name += "_RenamedFrom: " + Thread.CurrentThread.Name);
159 | }
160 | result++;
161 | }
162 | }
163 |
164 | public void AbortThreadedWork()
165 | {
166 | isAborted = true;
167 | }
168 |
169 |
170 | private object TestThreadSafeDispatch()
171 | {
172 | GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
173 | cube.transform.position = new Vector3(UnityEngine.Random.Range(-20, 20), UnityEngine.Random.Range(-20, 20), UnityEngine.Random.Range(-20, 20));
174 | cube.name = "MainThreadCube";
175 | return cube;
176 | }
177 |
178 | private object ThreadSafeGetFrameCount()
179 | {
180 | return Time.frameCount;
181 | }
182 | }
183 |
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Scripts/Simple Implementations/SimpleThreadingExample.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: f665c9e031556854d9cc008d9e560d4a
3 | MonoImporter:
4 | serializedVersion: 2
5 | defaultReferences: []
6 | executionOrder: 0
7 | icon: {instanceID: 0}
8 | userData:
9 | assetBundleName:
10 | assetBundleVariant:
11 |
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Scripts/TextureBlur.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 1b8c710e9fc383543a7299502a484ad7
3 | folderAsset: yes
4 | timeCreated: 1496323769
5 | licenseType: Free
6 | DefaultImporter:
7 | userData:
8 | assetBundleName:
9 | assetBundleVariant:
10 |
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Scripts/TextureBlur/TextureBlurCodeExplained.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/superowner/LOOM-Multi-Threading-Framework/56a811efcc3e135782559424e51392c69de8fb2f/Assets/LOOM Framework/Examples/Scripts/TextureBlur/TextureBlurCodeExplained.jpg
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Scripts/TextureBlur/TextureBlurCodeExplained.jpg.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 35945138b9ab61c4db6dfe344c68de59
3 | TextureImporter:
4 | fileIDToRecycleName: {}
5 | serializedVersion: 2
6 | mipmaps:
7 | mipMapMode: 0
8 | enableMipMap: 1
9 | linearTexture: 0
10 | correctGamma: 0
11 | fadeOut: 0
12 | borderMipMap: 0
13 | mipMapFadeDistanceStart: 1
14 | mipMapFadeDistanceEnd: 3
15 | bumpmap:
16 | convertToNormalMap: 0
17 | externalNormalMap: 0
18 | heightScale: .25
19 | normalMapFilter: 0
20 | isReadable: 0
21 | grayScaleToAlpha: 0
22 | generateCubemap: 0
23 | cubemapConvolution: 0
24 | cubemapConvolutionSteps: 8
25 | cubemapConvolutionExponent: 1.5
26 | seamlessCubemap: 0
27 | textureFormat: -1
28 | maxTextureSize: 1024
29 | textureSettings:
30 | filterMode: -1
31 | aniso: -1
32 | mipBias: -1
33 | wrapMode: -1
34 | nPOTScale: 1
35 | lightmap: 0
36 | rGBM: 0
37 | compressionQuality: 50
38 | allowsAlphaSplitting: 0
39 | spriteMode: 0
40 | spriteExtrude: 1
41 | spriteMeshType: 1
42 | alignment: 0
43 | spritePivot: {x: .5, y: .5}
44 | spriteBorder: {x: 0, y: 0, z: 0, w: 0}
45 | spritePixelsToUnits: 100
46 | alphaIsTransparency: 0
47 | textureType: -1
48 | buildTargetSettings: []
49 | spriteSheet:
50 | sprites: []
51 | spritePackingTag:
52 | userData:
53 | assetBundleName:
54 | assetBundleVariant:
55 |
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Scripts/TextureBlur/TextureBlurThreaded.cs:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/superowner/LOOM-Multi-Threading-Framework/56a811efcc3e135782559424e51392c69de8fb2f/Assets/LOOM Framework/Examples/Scripts/TextureBlur/TextureBlurThreaded.cs
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Scripts/TextureBlur/TextureBlurThreaded.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: df25dc8cc1736674281c69b30da3fe61
3 | MonoImporter:
4 | serializedVersion: 2
5 | defaultReferences: []
6 | executionOrder: 0
7 | icon: {instanceID: 0}
8 | userData:
9 | assetBundleName:
10 | assetBundleVariant:
11 |
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Visuals.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 0cd7ef8f6350bea4da72277f5f3ac154
3 | folderAsset: yes
4 | timeCreated: 1496323769
5 | licenseType: Free
6 | DefaultImporter:
7 | userData:
8 | assetBundleName:
9 | assetBundleVariant:
10 |
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Visuals/Cubemap.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/superowner/LOOM-Multi-Threading-Framework/56a811efcc3e135782559424e51392c69de8fb2f/Assets/LOOM Framework/Examples/Visuals/Cubemap.jpg
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Visuals/Cubemap.jpg.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: afcb080795d535a4099391b07e41fe9e
3 | TextureImporter:
4 | fileIDToRecycleName:
5 | 8900000: generatedCubemap
6 | serializedVersion: 2
7 | mipmaps:
8 | mipMapMode: 0
9 | enableMipMap: 1
10 | linearTexture: 0
11 | correctGamma: 0
12 | fadeOut: 0
13 | borderMipMap: 0
14 | mipMapFadeDistanceStart: 1
15 | mipMapFadeDistanceEnd: 3
16 | bumpmap:
17 | convertToNormalMap: 0
18 | externalNormalMap: 0
19 | heightScale: .25
20 | normalMapFilter: 0
21 | isReadable: 0
22 | grayScaleToAlpha: 0
23 | generateCubemap: 1
24 | cubemapConvolution: 0
25 | cubemapConvolutionSteps: 8
26 | cubemapConvolutionExponent: 1.5
27 | seamlessCubemap: 0
28 | textureFormat: -1
29 | maxTextureSize: 1024
30 | textureSettings:
31 | filterMode: -1
32 | aniso: -1
33 | mipBias: -1
34 | wrapMode: 1
35 | nPOTScale: 1
36 | lightmap: 0
37 | rGBM: 0
38 | compressionQuality: 50
39 | allowsAlphaSplitting: 0
40 | spriteMode: 0
41 | spriteExtrude: 1
42 | spriteMeshType: 1
43 | alignment: 0
44 | spritePivot: {x: .5, y: .5}
45 | spriteBorder: {x: 0, y: 0, z: 0, w: 0}
46 | spritePixelsToUnits: 100
47 | alphaIsTransparency: 0
48 | textureType: 3
49 | buildTargetSettings: []
50 | spriteSheet:
51 | sprites: []
52 | spritePackingTag:
53 | userData:
54 | assetBundleName:
55 | assetBundleVariant:
56 |
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Visuals/FlockingDemoLogo.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/superowner/LOOM-Multi-Threading-Framework/56a811efcc3e135782559424e51392c69de8fb2f/Assets/LOOM Framework/Examples/Visuals/FlockingDemoLogo.jpg
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Visuals/FlockingDemoLogo.jpg.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 0d477911e69fc6e428e856c20744b4c7
3 | TextureImporter:
4 | fileIDToRecycleName: {}
5 | serializedVersion: 2
6 | mipmaps:
7 | mipMapMode: 0
8 | enableMipMap: 0
9 | linearTexture: 0
10 | correctGamma: 0
11 | fadeOut: 0
12 | borderMipMap: 0
13 | mipMapFadeDistanceStart: 1
14 | mipMapFadeDistanceEnd: 3
15 | bumpmap:
16 | convertToNormalMap: 0
17 | externalNormalMap: 0
18 | heightScale: .25
19 | normalMapFilter: 0
20 | isReadable: 0
21 | grayScaleToAlpha: 0
22 | generateCubemap: 0
23 | cubemapConvolution: 0
24 | cubemapConvolutionSteps: 8
25 | cubemapConvolutionExponent: 1.5
26 | seamlessCubemap: 0
27 | textureFormat: 32
28 | maxTextureSize: 2048
29 | textureSettings:
30 | filterMode: -1
31 | aniso: -1
32 | mipBias: -1
33 | wrapMode: -1
34 | nPOTScale: 1
35 | lightmap: 0
36 | rGBM: 0
37 | compressionQuality: 50
38 | allowsAlphaSplitting: 0
39 | spriteMode: 0
40 | spriteExtrude: 1
41 | spriteMeshType: 1
42 | alignment: 0
43 | spritePivot: {x: .5, y: .5}
44 | spriteBorder: {x: 0, y: 0, z: 0, w: 0}
45 | spritePixelsToUnits: 100
46 | alphaIsTransparency: 0
47 | textureType: 5
48 | buildTargetSettings:
49 | - buildTarget: Android
50 | maxTextureSize: 2048
51 | textureFormat: 34
52 | compressionQuality: 100
53 | allowsAlphaSplitting: 0
54 | spriteSheet:
55 | sprites: []
56 | spritePackingTag:
57 | userData:
58 | assetBundleName:
59 | assetBundleVariant:
60 |
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Visuals/Floor.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/superowner/LOOM-Multi-Threading-Framework/56a811efcc3e135782559424e51392c69de8fb2f/Assets/LOOM Framework/Examples/Visuals/Floor.jpg
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Visuals/Floor.jpg.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 2b89995f6caf9814892cda064ad152a8
3 | TextureImporter:
4 | fileIDToRecycleName: {}
5 | serializedVersion: 2
6 | mipmaps:
7 | mipMapMode: 0
8 | enableMipMap: 1
9 | linearTexture: 0
10 | correctGamma: 0
11 | fadeOut: 0
12 | borderMipMap: 0
13 | mipMapFadeDistanceStart: 1
14 | mipMapFadeDistanceEnd: 3
15 | bumpmap:
16 | convertToNormalMap: 0
17 | externalNormalMap: 0
18 | heightScale: .25
19 | normalMapFilter: 0
20 | isReadable: 0
21 | grayScaleToAlpha: 0
22 | generateCubemap: 0
23 | cubemapConvolution: 0
24 | cubemapConvolutionSteps: 8
25 | cubemapConvolutionExponent: 1.5
26 | seamlessCubemap: 0
27 | textureFormat: -1
28 | maxTextureSize: 1024
29 | textureSettings:
30 | filterMode: -1
31 | aniso: -1
32 | mipBias: -1
33 | wrapMode: -1
34 | nPOTScale: 1
35 | lightmap: 0
36 | rGBM: 0
37 | compressionQuality: 50
38 | allowsAlphaSplitting: 0
39 | spriteMode: 0
40 | spriteExtrude: 1
41 | spriteMeshType: 1
42 | alignment: 0
43 | spritePivot: {x: .5, y: .5}
44 | spriteBorder: {x: 0, y: 0, z: 0, w: 0}
45 | spritePixelsToUnits: 100
46 | alphaIsTransparency: 0
47 | textureType: -1
48 | buildTargetSettings: []
49 | spriteSheet:
50 | sprites: []
51 | spritePackingTag:
52 | userData:
53 | assetBundleName:
54 | assetBundleVariant:
55 |
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Visuals/FrameClean.fbx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/superowner/LOOM-Multi-Threading-Framework/56a811efcc3e135782559424e51392c69de8fb2f/Assets/LOOM Framework/Examples/Visuals/FrameClean.fbx
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Visuals/FrameClean.fbx.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 4cf1f862042268f42be35324a029e68b
3 | ModelImporter:
4 | serializedVersion: 18
5 | fileIDToRecycleName:
6 | 4300000: FrameClean
7 | materials:
8 | importMaterials: 1
9 | materialName: 0
10 | materialSearch: 1
11 | animations:
12 | legacyGenerateAnimations: 4
13 | bakeSimulation: 0
14 | optimizeGameObjects: 0
15 | motionNodeName:
16 | animationImportErrors:
17 | animationImportWarnings:
18 | animationRetargetingWarnings:
19 | animationDoRetargetingWarnings: 0
20 | animationCompression: 1
21 | animationRotationError: .5
22 | animationPositionError: .5
23 | animationScaleError: .5
24 | animationWrapMode: 0
25 | extraExposedTransformPaths: []
26 | clipAnimations: []
27 | isReadable: 1
28 | meshes:
29 | lODScreenPercentages: []
30 | globalScale: 1
31 | meshCompression: 0
32 | addColliders: 0
33 | importBlendShapes: 1
34 | swapUVChannels: 0
35 | generateSecondaryUV: 0
36 | useFileUnits: 1
37 | optimizeMeshForGPU: 1
38 | keepQuads: 0
39 | weldVertices: 1
40 | secondaryUVAngleDistortion: 8
41 | secondaryUVAreaDistortion: 15.000001
42 | secondaryUVHardAngle: 88
43 | secondaryUVPackMargin: 4
44 | useFileScale: 0
45 | tangentSpace:
46 | normalSmoothAngle: 60
47 | splitTangentsAcrossUV: 1
48 | normalImportMode: 0
49 | tangentImportMode: 1
50 | importAnimation: 1
51 | copyAvatar: 0
52 | humanDescription:
53 | human: []
54 | skeleton: []
55 | armTwist: .5
56 | foreArmTwist: .5
57 | upperLegTwist: .5
58 | legTwist: .5
59 | armStretch: .0500000007
60 | legStretch: .0500000007
61 | feetSpacing: 0
62 | rootMotionBoneName:
63 | hasTranslationDoF: 0
64 | lastHumanDescriptionAvatarSource: {instanceID: 0}
65 | animationType: 1
66 | humanoidOversampling: 1
67 | additionalBone: 0
68 | userData:
69 | assetBundleName:
70 | assetBundleVariant:
71 |
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Visuals/FrameHighPoly.fbx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/superowner/LOOM-Multi-Threading-Framework/56a811efcc3e135782559424e51392c69de8fb2f/Assets/LOOM Framework/Examples/Visuals/FrameHighPoly.fbx
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Visuals/FrameHighPoly.fbx.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 00938428866bd134fac665e08a6602c4
3 | ModelImporter:
4 | serializedVersion: 18
5 | fileIDToRecycleName:
6 | 4300000: FrameHighPoly
7 | 4300002: FrameHighPoly_MeshPart0
8 | 4300004: FrameHighPoly_MeshPart1
9 | materials:
10 | importMaterials: 1
11 | materialName: 0
12 | materialSearch: 1
13 | animations:
14 | legacyGenerateAnimations: 4
15 | bakeSimulation: 0
16 | optimizeGameObjects: 0
17 | motionNodeName:
18 | animationImportErrors:
19 | animationImportWarnings:
20 | animationRetargetingWarnings:
21 | animationDoRetargetingWarnings: 0
22 | animationCompression: 1
23 | animationRotationError: .5
24 | animationPositionError: .5
25 | animationScaleError: .5
26 | animationWrapMode: 0
27 | extraExposedTransformPaths: []
28 | clipAnimations: []
29 | isReadable: 1
30 | meshes:
31 | lODScreenPercentages: []
32 | globalScale: 1
33 | meshCompression: 0
34 | addColliders: 0
35 | importBlendShapes: 1
36 | swapUVChannels: 0
37 | generateSecondaryUV: 0
38 | useFileUnits: 1
39 | optimizeMeshForGPU: 1
40 | keepQuads: 0
41 | weldVertices: 1
42 | secondaryUVAngleDistortion: 8
43 | secondaryUVAreaDistortion: 15.000001
44 | secondaryUVHardAngle: 88
45 | secondaryUVPackMargin: 4
46 | useFileScale: 0
47 | tangentSpace:
48 | normalSmoothAngle: 60
49 | splitTangentsAcrossUV: 1
50 | normalImportMode: 0
51 | tangentImportMode: 1
52 | importAnimation: 1
53 | copyAvatar: 0
54 | humanDescription:
55 | human: []
56 | skeleton: []
57 | armTwist: .5
58 | foreArmTwist: .5
59 | upperLegTwist: .5
60 | legTwist: .5
61 | armStretch: .0500000007
62 | legStretch: .0500000007
63 | feetSpacing: 0
64 | rootMotionBoneName:
65 | hasTranslationDoF: 0
66 | lastHumanDescriptionAvatarSource: {instanceID: 0}
67 | animationType: 1
68 | humanoidOversampling: 1
69 | additionalBone: 0
70 | userData:
71 | assetBundleName:
72 | assetBundleVariant:
73 |
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Visuals/Materials.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 8d73b0eb5902dec41898f64eab8fb411
3 | folderAsset: yes
4 | timeCreated: 1496323769
5 | licenseType: Free
6 | DefaultImporter:
7 | userData:
8 | assetBundleName:
9 | assetBundleVariant:
10 |
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Visuals/Materials/CannonBall.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/superowner/LOOM-Multi-Threading-Framework/56a811efcc3e135782559424e51392c69de8fb2f/Assets/LOOM Framework/Examples/Visuals/Materials/CannonBall.mat
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Visuals/Materials/CannonBall.mat.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 9973d51ae6bcbd048a5aacddf0256477
3 | NativeFormatImporter:
4 | userData:
5 | assetBundleName:
6 | assetBundleVariant:
7 |
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Visuals/Materials/Export_Logo_Clean_mi_car_paint_phen_x_passes1.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/superowner/LOOM-Multi-Threading-Framework/56a811efcc3e135782559424e51392c69de8fb2f/Assets/LOOM Framework/Examples/Visuals/Materials/Export_Logo_Clean_mi_car_paint_phen_x_passes1.mat
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Visuals/Materials/Export_Logo_Clean_mi_car_paint_phen_x_passes1.mat.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: f1b46cbf81d77be4f88ea176051b01a4
3 | NativeFormatImporter:
4 | userData:
5 | assetBundleName:
6 | assetBundleVariant:
7 |
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Visuals/Materials/Floor.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/superowner/LOOM-Multi-Threading-Framework/56a811efcc3e135782559424e51392c69de8fb2f/Assets/LOOM Framework/Examples/Visuals/Materials/Floor.mat
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Visuals/Materials/Floor.mat.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: b1b8b6e6bf5e4f1449abc772e4464f3d
3 | NativeFormatImporter:
4 | userData:
5 | assetBundleName:
6 | assetBundleVariant:
7 |
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Visuals/Materials/Frame.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/superowner/LOOM-Multi-Threading-Framework/56a811efcc3e135782559424e51392c69de8fb2f/Assets/LOOM Framework/Examples/Visuals/Materials/Frame.mat
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Visuals/Materials/Frame.mat.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 836d2a376d9bc5f4dbdb04a462eb1dec
3 | NativeFormatImporter:
4 | userData:
5 | assetBundleName:
6 | assetBundleVariant:
7 |
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Visuals/Materials/Particle.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/superowner/LOOM-Multi-Threading-Framework/56a811efcc3e135782559424e51392c69de8fb2f/Assets/LOOM Framework/Examples/Visuals/Materials/Particle.mat
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Visuals/Materials/Particle.mat.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: a61d61f5dab29b249929635ed32edab7
3 | NativeFormatImporter:
4 | userData:
5 | assetBundleName:
6 | assetBundleVariant:
7 |
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Visuals/Materials/Spheres.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/superowner/LOOM-Multi-Threading-Framework/56a811efcc3e135782559424e51392c69de8fb2f/Assets/LOOM Framework/Examples/Visuals/Materials/Spheres.mat
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Visuals/Materials/Spheres.mat.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: cd662e242d655b64bb9bee15b56bae85
3 | NativeFormatImporter:
4 | userData:
5 | assetBundleName:
6 | assetBundleVariant:
7 |
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Visuals/Materials/lambert1.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/superowner/LOOM-Multi-Threading-Framework/56a811efcc3e135782559424e51392c69de8fb2f/Assets/LOOM Framework/Examples/Visuals/Materials/lambert1.mat
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Visuals/Materials/lambert1.mat.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: d18537a22534fde4b8a52630439a08af
3 | NativeFormatImporter:
4 | userData:
5 | assetBundleName:
6 | assetBundleVariant:
7 |
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Visuals/Materials/mi_car_paint_phen_x_passes1.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/superowner/LOOM-Multi-Threading-Framework/56a811efcc3e135782559424e51392c69de8fb2f/Assets/LOOM Framework/Examples/Visuals/Materials/mi_car_paint_phen_x_passes1.mat
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Visuals/Materials/mi_car_paint_phen_x_passes1.mat.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 25bb2686a20873645b48d26335869eec
3 | NativeFormatImporter:
4 | userData:
5 | assetBundleName:
6 | assetBundleVariant:
7 |
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Visuals/Particle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/superowner/LOOM-Multi-Threading-Framework/56a811efcc3e135782559424e51392c69de8fb2f/Assets/LOOM Framework/Examples/Visuals/Particle.png
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Visuals/Particle.png.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 3ea02907605adc145b9db0787c419ade
3 | TextureImporter:
4 | fileIDToRecycleName: {}
5 | serializedVersion: 2
6 | mipmaps:
7 | mipMapMode: 0
8 | enableMipMap: 0
9 | linearTexture: 0
10 | correctGamma: 0
11 | fadeOut: 0
12 | borderMipMap: 0
13 | mipMapFadeDistanceStart: 1
14 | mipMapFadeDistanceEnd: 3
15 | bumpmap:
16 | convertToNormalMap: 0
17 | externalNormalMap: 0
18 | heightScale: .25
19 | normalMapFilter: 0
20 | isReadable: 0
21 | grayScaleToAlpha: 0
22 | generateCubemap: 0
23 | cubemapConvolution: 0
24 | cubemapConvolutionSteps: 8
25 | cubemapConvolutionExponent: 1.5
26 | seamlessCubemap: 0
27 | textureFormat: -3
28 | maxTextureSize: 1024
29 | textureSettings:
30 | filterMode: -1
31 | aniso: -1
32 | mipBias: -1
33 | wrapMode: -1
34 | nPOTScale: 1
35 | lightmap: 0
36 | rGBM: 0
37 | compressionQuality: 50
38 | allowsAlphaSplitting: 0
39 | spriteMode: 0
40 | spriteExtrude: 1
41 | spriteMeshType: 1
42 | alignment: 0
43 | spritePivot: {x: .5, y: .5}
44 | spriteBorder: {x: 0, y: 0, z: 0, w: 0}
45 | spritePixelsToUnits: 100
46 | alphaIsTransparency: 0
47 | textureType: 5
48 | buildTargetSettings: []
49 | spriteSheet:
50 | sprites: []
51 | spritePackingTag:
52 | userData:
53 | assetBundleName:
54 | assetBundleVariant:
55 |
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Visuals/Plane1x1.fbx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/superowner/LOOM-Multi-Threading-Framework/56a811efcc3e135782559424e51392c69de8fb2f/Assets/LOOM Framework/Examples/Visuals/Plane1x1.fbx
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Visuals/Plane1x1.fbx.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 3745e45a63361c04b8df832bc4b69bd9
3 | ModelImporter:
4 | serializedVersion: 18
5 | fileIDToRecycleName:
6 | 4300000: pPlane1
7 | materials:
8 | importMaterials: 1
9 | materialName: 0
10 | materialSearch: 1
11 | animations:
12 | legacyGenerateAnimations: 4
13 | bakeSimulation: 0
14 | optimizeGameObjects: 0
15 | motionNodeName:
16 | animationImportErrors:
17 | animationImportWarnings:
18 | animationRetargetingWarnings:
19 | animationDoRetargetingWarnings: 0
20 | animationCompression: 1
21 | animationRotationError: .5
22 | animationPositionError: .5
23 | animationScaleError: .5
24 | animationWrapMode: 0
25 | extraExposedTransformPaths: []
26 | clipAnimations: []
27 | isReadable: 1
28 | meshes:
29 | lODScreenPercentages: []
30 | globalScale: 1
31 | meshCompression: 0
32 | addColliders: 0
33 | importBlendShapes: 1
34 | swapUVChannels: 0
35 | generateSecondaryUV: 0
36 | useFileUnits: 1
37 | optimizeMeshForGPU: 1
38 | keepQuads: 0
39 | weldVertices: 1
40 | secondaryUVAngleDistortion: 8
41 | secondaryUVAreaDistortion: 15.000001
42 | secondaryUVHardAngle: 88
43 | secondaryUVPackMargin: 4
44 | useFileScale: 0
45 | tangentSpace:
46 | normalSmoothAngle: 60
47 | splitTangentsAcrossUV: 1
48 | normalImportMode: 0
49 | tangentImportMode: 1
50 | importAnimation: 1
51 | copyAvatar: 0
52 | humanDescription:
53 | human: []
54 | skeleton: []
55 | armTwist: .5
56 | foreArmTwist: .5
57 | upperLegTwist: .5
58 | legTwist: .5
59 | armStretch: .0500000007
60 | legStretch: .0500000007
61 | feetSpacing: 0
62 | rootMotionBoneName:
63 | hasTranslationDoF: 0
64 | lastHumanDescriptionAvatarSource: {instanceID: 0}
65 | animationType: 1
66 | humanoidOversampling: 1
67 | additionalBone: 0
68 | userData:
69 | assetBundleName:
70 | assetBundleVariant:
71 |
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Visuals/Rock_n_Snow.JPG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/superowner/LOOM-Multi-Threading-Framework/56a811efcc3e135782559424e51392c69de8fb2f/Assets/LOOM Framework/Examples/Visuals/Rock_n_Snow.JPG
--------------------------------------------------------------------------------
/Assets/LOOM Framework/Examples/Visuals/Rock_n_Snow.JPG.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 284d8e2e94c7b6141b82e70f60f6fecd
3 | TextureImporter:
4 | fileIDToRecycleName: {}
5 | serializedVersion: 2
6 | mipmaps:
7 | mipMapMode: 0
8 | enableMipMap: 0
9 | linearTexture: 0
10 | correctGamma: 0
11 | fadeOut: 0
12 | borderMipMap: 0
13 | mipMapFadeDistanceStart: 1
14 | mipMapFadeDistanceEnd: 3
15 | bumpmap:
16 | convertToNormalMap: 0
17 | externalNormalMap: 0
18 | heightScale: .25
19 | normalMapFilter: 0
20 | isReadable: 1
21 | grayScaleToAlpha: 0
22 | generateCubemap: 0
23 | cubemapConvolution: 0
24 | cubemapConvolutionSteps: 8
25 | cubemapConvolutionExponent: 1.5
26 | seamlessCubemap: 0
27 | textureFormat: 32
28 | maxTextureSize: 512
29 | textureSettings:
30 | filterMode: -1
31 | aniso: -1
32 | mipBias: -1
33 | wrapMode: -1
34 | nPOTScale: 1
35 | lightmap: 0
36 | rGBM: 0
37 | compressionQuality: 50
38 | allowsAlphaSplitting: 0
39 | spriteMode: 0
40 | spriteExtrude: 1
41 | spriteMeshType: 1
42 | alignment: 0
43 | spritePivot: {x: .5, y: .5}
44 | spriteBorder: {x: 0, y: 0, z: 0, w: 0}
45 | spritePixelsToUnits: 100
46 | alphaIsTransparency: 0
47 | textureType: 5
48 | buildTargetSettings:
49 | - buildTarget: Android
50 | maxTextureSize: 512
51 | textureFormat: 34
52 | compressionQuality: 100
53 | allowsAlphaSplitting: 0
54 | spriteSheet:
55 | sprites: []
56 | spritePackingTag:
57 | userData:
58 | assetBundleName:
59 | assetBundleVariant:
60 |
--------------------------------------------------------------------------------
/Assets/LOOM Framework/LOOM.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 5b4e7e6d2eee0324db98fbfe6de8a534
3 | folderAsset: yes
4 | timeCreated: 1496323769
5 | licenseType: Free
6 | DefaultImporter:
7 | userData:
8 | assetBundleName:
9 | assetBundleVariant:
10 |
--------------------------------------------------------------------------------
/Assets/LOOM Framework/LOOM/IThreadWorkerObject.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 |
4 | namespace Frankfort.Threading
5 | {
6 |
7 |
8 |
9 | public interface IThreadWorkerObject
10 | {
11 | ///
12 | /// This method is called by the Scheduler as the main entryPoint to start working.
13 | /// - Note: Make sure it doesn't throw any errors, because errors outside of the Mainthread are "eaten" by Unity.
14 | /// - You can enable "savemode" if required, which executes all the work within a Try-catch statement to keep it going...
15 | /// Example:
16 | ///
17 | /// private bool isAborted;
18 | /// public void ExecuteThreadedWork()
19 | /// {
20 | /// long i = 10000000;
21 | /// while (--i > -1 && !isAborted)
22 | /// result++;
23 | /// }
24 | ///
25 | /// public void AbortThreadedWork()
26 | /// {
27 | /// isAborted = true;
28 | /// }
29 | ///
30 | void ExecuteThreadedWork();
31 |
32 |
33 | ///
34 | /// When called by the Scheduler, do whatever you need to do to directly interupt/stop the work in progress.
35 | /// Why no aborting the thread? Its not possible to interupt an loop without calling Thread.Abort() or Thread.Join().
36 | /// This freamwork does NOT use Thread.Abort & Thread.Join because of webplayer-sandbox restrictions etc.
37 | /// Therefore its up to you to implement a way to always directly abort the process as shown in the example bellow.
38 | /// - Note: Make sure it doesn't throw any errors, because errors outside of the Mainthread are "eaten" by Unity.
39 | /// - You can enable "savemode" if required, which executes all the work within a Try-catch statement to keep it going...
40 | ///
41 | /// Example:
42 | ///
43 | /// private bool isAborted;
44 | /// public void ExecuteThreadedWork()
45 | /// {
46 | /// long i = 10000000;
47 | /// while (--i > -1 && !isAborted)
48 | /// result++;
49 | /// }
50 | ///
51 | /// public void AbortThreadedWork()
52 | /// {
53 | /// isAborted = true;
54 | /// }
55 | ///
56 | void AbortThreadedWork();
57 | }
58 | }
--------------------------------------------------------------------------------
/Assets/LOOM Framework/LOOM/IThreadWorkerObject.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 279175d999cc838408e393434804488e
3 | MonoImporter:
4 | serializedVersion: 2
5 | defaultReferences: []
6 | executionOrder: 0
7 | icon: {instanceID: 0}
8 | userData:
9 | assetBundleName:
10 | assetBundleVariant:
11 |
--------------------------------------------------------------------------------
/Assets/LOOM Framework/LOOM/Internal.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 903616312b54f644d84a2043649ba33c
3 | folderAsset: yes
4 | timeCreated: 1496323769
5 | licenseType: Free
6 | DefaultImporter:
7 | userData:
8 | assetBundleName:
9 | assetBundleVariant:
10 |
--------------------------------------------------------------------------------
/Assets/LOOM Framework/LOOM/Internal/MainThreadDispatcher.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using UnityEngine;
3 | using System.Threading;
4 | using System.Collections.Generic;
5 |
6 |
7 |
8 | namespace Frankfort.Threading
9 | {
10 | ///
11 | /// Fire and forget: The MainThread will execute this method witout any arguments to pass, nothing will be returned.
12 | ///
13 | public delegate void ThreadDispatchDelegate();
14 |
15 | ///
16 | /// Alows you to pass a argument to the delegate.
17 | ///
18 | /// Once the MainThread executes this action, the argument will be passed to the delegate
19 | public delegate void ThreadDispatchDelegateArg(object arg);
20 |
21 | ///
22 | /// Alows you to pass a argument to the delegate.
23 | /// Allows you to dispatch an delegate returning an object (for example: a newly instantiated gameobject) that is directly available in your ThreadPool-Thread.
24 | /// Because the thread you are dispatching from is not the MainThread, your ThreadPool-thread needs to wait till the MainThread executed the method, and the returned value can be used directly
25 | ///
26 | /// Once the MainThread executes this action, the argument will be passed to the delegate
27 | ///
28 | public delegate object ThreadDispatchDelegateArgReturn(object arg);
29 |
30 |
31 | ///
32 | /// Allows you to dispatch an delegate returning an object (for example: a newly instantiated gameobject) that is directly available in your ThreadPool-Thread.
33 | /// Because the thread you are dispatching from is not the MainThread, your ThreadPool-thread needs to wait till the MainThread executed the method, and the returned value can be used directly
34 | ///
35 | /// Once the MainThread executes this action, the argument will be passed to the delegate
36 | public delegate object ThreadDispatchDelegateReturn();
37 | }
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 | namespace Frankfort.Threading.Internal
47 | {
48 | ///
49 | /// This static class helps you use Unity-engine related objects like GameObjects or Components, without violating threadsafty of Unity.
50 | ///
51 | public static class MainThreadDispatcher
52 | {
53 |
54 | private static List dispatchActions = new List();
55 | private static bool helperCreated;
56 | public static int currentFrame = 0;
57 |
58 |
59 |
60 |
61 | //--------------------------------------- INIT --------------------------------------
62 | //--------------------------------------- INIT --------------------------------------
63 | #region INIT
64 |
65 | //Sins this class is static, it needs to be called from the MainThread, by some monobehaviour-awake (ThreadPoolScheduler that is...)
66 | public static void Init()
67 | {
68 | if (!helperCreated)
69 | CreateHelperGameObject();
70 | }
71 |
72 | private static void CreateHelperGameObject()
73 | {
74 | GameObject helperGO = new GameObject("MainThreadDispatchHelper");
75 | MainThreadDispatchHelper helper = helperGO.AddComponent();
76 | helper.hideFlags = helperGO.hideFlags = HideFlags.HideInHierarchy | HideFlags.HideInInspector;
77 | GameObject.DontDestroyOnLoad(helperGO);
78 | helperCreated = true;
79 | }
80 |
81 | #endregion
82 | //--------------------------------------- INIT --------------------------------------
83 | //--------------------------------------- INIT --------------------------------------
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 | //--------------------------------------- UPDATE CALLED BY HELPER --------------------------------------
94 | //--------------------------------------- UPDATE CALLED BY HELPER --------------------------------------
95 |
96 | #region UPDATE CALLED BY HELPER
97 | public static void Update()
98 | {
99 | DispatchActionsIfPresent();
100 | }
101 |
102 |
103 | private static void DispatchActionsIfPresent()
104 | {
105 | if (dispatchActions != null && dispatchActions.Count > 0)
106 | {
107 | lock (dispatchActions)
108 | {
109 | foreach (ThreadDispatchAction action in dispatchActions)
110 | {
111 | if (!action.executed) //Might be executed internally. This happens when de event was dispatched from the MainThread in the firstplace....
112 | action.ExecuteDispatch();
113 | }
114 | dispatchActions.Clear();
115 | Monitor.PulseAll(dispatchActions);
116 | }
117 | }
118 | }
119 |
120 | #endregion
121 |
122 | //--------------------------------------- UPDATE CALLED BY HELPER --------------------------------------
123 | //--------------------------------------- UPDATE CALLED BY HELPER --------------------------------------
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 | //--------------------------------------- 4 DISPATCH OVERLOADS --------------------------------------
136 | //--------------------------------------- 4 DISPATCH OVERLOADS --------------------------------------
137 | #region 4 DISPATCH OVERLOADS
138 |
139 |
140 | ///
141 | /// Fire and forget: The MainThread will execute this method witout any arguments to pass, nothing will be returned.
142 | ///
143 | /// Example: "() => Debug.Log("This will be fired from the MainThread: " + System.Threading.Thread.CurrentThread.Name)"
144 | /// Freezes the thread, waiting for the MainThread to execute & finish the "dispatchCall".
145 | /// Executes all the computations within try-catch events, logging it the message + stacktrace
146 | public static void DispatchToMainThread(ThreadDispatchDelegate dispatchCall, bool waitForExecution = false, bool safeMode = true)
147 | {
148 | if (MainThreadWatchdog.CheckIfMainThread())
149 | {
150 | if (dispatchCall != null)
151 | dispatchCall();
152 | }
153 | else
154 | {
155 | ThreadDispatchAction action = new ThreadDispatchAction();
156 | lock (dispatchActions) { dispatchActions.Add(action); }
157 | action.Init(dispatchCall, waitForExecution, safeMode);
158 | }
159 | }
160 |
161 |
162 |
163 | ///
164 | /// When executed by the MainThread, this argument will be passed to the "dispatchCall";
165 | ///
166 | /// Example: "(object obj) => Debug.Log("This will be fired from the MainThread: " + System.Threading.Thread.CurrentThread.Name + "\nObject: " + obj.toString())"
167 | /// Once the MainThread executes this action, the argument will be passed to the delegate
168 | /// Freezes the thread, waiting for the MainThread to execute & finish the "dispatchCall".
169 | /// Executes all the computations within try-catch events, logging it the message + stacktrace
170 | public static void DispatchToMainThread(ThreadDispatchDelegateArg dispatchCall, object dispatchArgument, bool waitForExecution = false, bool safeMode = true)
171 | {
172 | if (MainThreadWatchdog.CheckIfMainThread())
173 | {
174 | if (dispatchCall != null)
175 | dispatchCall(dispatchArgument);
176 | }
177 | else
178 | {
179 | ThreadDispatchAction action = new ThreadDispatchAction();
180 | lock (dispatchActions) { dispatchActions.Add(action); }
181 | action.Init(dispatchCall, dispatchArgument, waitForExecution, safeMode);
182 | }
183 | }
184 |
185 |
186 |
187 |
188 | ///
189 | /// When executed by the MainThread, this argument will be passed to the "dispatchCall";
190 | /// Allows you to dispatch an delegate returning an object (for example: a newly instantiated gameobject) that is directly available in your ThreadPool-Thread.
191 | /// Because the thread you are dispatching from is not the MainThread, your ThreadPool-thread needs to wait till the MainThread executed the method, and the returned value can be used directly
192 | ///
193 | /// Example: "(object obj) => Debug.Log("This will be fired from the MainThread: " + System.Threading.Thread.CurrentThread.Name + "\nObject: " + obj.toString())"
194 | /// Once the MainThread executes this action, the argument will be passed to the delegate
195 | /// Executes all the computations within try-catch events, logging it the message + stacktrace
196 | /// After the MainThread has executed the "dispatchCall" (and the worker-thread has been waiting), it will return whatever the dispatchCall returns to the worker-thread
197 | public static object DispatchToMainThreadReturn(ThreadDispatchDelegateArgReturn dispatchCall, object dispatchArgument, bool safeMode = true)
198 | {
199 | if (MainThreadWatchdog.CheckIfMainThread())
200 | {
201 | if (dispatchCall != null)
202 | return dispatchCall(dispatchArgument);
203 | }
204 | else
205 | {
206 | ThreadDispatchAction action = new ThreadDispatchAction();
207 | lock (dispatchActions) { dispatchActions.Add(action); }
208 | action.Init(dispatchCall, dispatchArgument, safeMode); //Puts the Thread to sleep while waiting for the action to be invoked.
209 | return action.dispatchExecutionResult;
210 | }
211 | return null;
212 | }
213 |
214 |
215 |
216 |
217 |
218 | ///
219 | /// Allows you to dispatch an delegate returning an object (for example: a newly instantiated gameobject) that is directly available in your ThreadPool-Thread.
220 | /// Because the thread you are dispatching from is not the MainThread, your ThreadPool-thread needs to wait till the MainThread executed the method, and the returned value can be used directly
221 | ///
222 | /// Example: "(object obj) => Debug.Log("This will be fired from the MainThread: " + System.Threading.Thread.CurrentThread.Name + "\nObject: " + obj.toString())"
223 | /// Executes all the computations within try-catch events, logging it the message + stacktrace
224 | /// After the MainThread has executed the "dispatchCall" (and the worker-thread has been waiting), it will return whatever the dispatchCall returns to the worker-thread
225 | public static object DispatchToMainThreadReturn(ThreadDispatchDelegateReturn dispatchCall, bool safeMode = true)
226 | {
227 | if (MainThreadWatchdog.CheckIfMainThread())
228 | {
229 | if (dispatchCall != null)
230 | return dispatchCall();
231 | }
232 | else
233 | {
234 | ThreadDispatchAction action = new ThreadDispatchAction();
235 | lock (dispatchActions) { dispatchActions.Add(action); }
236 | action.Init(dispatchCall, safeMode); //Puts the Thread to sleep while waiting for the action to be invoked.
237 | return action.dispatchExecutionResult;
238 | }
239 | return null;
240 | }
241 |
242 | #endregion
243 | //--------------------------------------- 4 DISPATCH OVERLOADS --------------------------------------
244 | //--------------------------------------- 4 DISPATCH OVERLOADS --------------------------------------
245 |
246 | }
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 | //--------------------------------------- HELPER GAME OBJECT WITH COMPONENT --------------------------------------
257 | //--------------------------------------- HELPER GAME OBJECT WITH COMPONENT --------------------------------------
258 | #region HELPER GAME OBJECT WITH COMPONENT
259 |
260 |
261 | public class MainThreadDispatchHelper : MonoBehaviour
262 | {
263 | private float WaitForSecondsTime = 0.005f;
264 |
265 | private void Awake()
266 | {
267 | MainThreadWatchdog.Init();
268 | UnityActivityWatchdog.Init();
269 | InvokeRepeating("UpdateMainThreadDispatcher", WaitForSecondsTime, WaitForSecondsTime);
270 | }
271 |
272 |
273 | private void Update()
274 | {
275 | MainThreadDispatcher.currentFrame = Time.frameCount;
276 | }
277 | private void UpdateMainThreadDispatcher()
278 | {
279 | MainThreadDispatcher.Update();
280 | }
281 | }
282 | #endregion
283 | //--------------------------------------- HELPER GAME OBJECT WITH COMPONENT --------------------------------------
284 | //--------------------------------------- HELPER GAME OBJECT WITH COMPONENT --------------------------------------
285 |
286 | }
--------------------------------------------------------------------------------
/Assets/LOOM Framework/LOOM/Internal/MainThreadDispatcher.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 9f6b754fff034db41bfd722da8b9daf1
3 | MonoImporter:
4 | serializedVersion: 2
5 | defaultReferences: []
6 | executionOrder: 0
7 | icon: {instanceID: 0}
8 | userData:
9 | assetBundleName:
10 | assetBundleVariant:
11 |
--------------------------------------------------------------------------------
/Assets/LOOM Framework/LOOM/Internal/MainThreadWatchdog.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading;
3 | using UnityEngine;
4 |
5 | namespace Frankfort.Threading.Internal
6 | {
7 | ///
8 | /// Keeps track of the MainThread. This is needed to handle the MainThread-edispatcher, WaitForNextFrame & WaitForSeconds safely.
9 | ///
10 | public class MainThreadWatchdog
11 | {
12 |
13 | //--------------------------------------- MANAGE MAIN THREAD VALIDATION --------------------------------------
14 | //--------------------------------------- MANAGE MAIN THREAD VALIDATION --------------------------------------
15 | #region MANAGE MAIN THREAD VALIDATION
16 | private static Thread mainThread = null;
17 |
18 | ///
19 | /// Set the CurrentThread to be the MainThread, if the CurrentThread happens NOT to be MultiThreadedApartment, NOT a ThreadPoolThread, and with an ID of <= 1;
20 | ///
21 | public static void Init()
22 | {
23 | if (mainThread == null)
24 | {
25 | Thread currentThread = Thread.CurrentThread;
26 | if(currentThread.GetApartmentState() == ApartmentState.MTA || currentThread.ManagedThreadId > 1 || currentThread.IsThreadPoolThread)
27 | {
28 | Debug.Log("Trying to Init a WorkerThread as the MainThread! ");
29 | }
30 | else
31 | {
32 | mainThread = currentThread;
33 | }
34 | }
35 | }
36 |
37 |
38 |
39 | ///
40 | /// If you need your current code to be running on the MainThread, you can always call this method to check if its the MainThread or not...
41 | ///
42 | /// Returns TRUE if its the MainThread
43 | public static bool CheckIfMainThread()
44 | {
45 | Init(); //Just to be sure....
46 | return Thread.CurrentThread == mainThread;
47 | }
48 | #endregion
49 |
50 | //--------------------------------------- MANAGE MAIN THREAD VALIDATION --------------------------------------
51 | //--------------------------------------- MANAGE MAIN THREAD VALIDATION --------------------------------------
52 |
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/Assets/LOOM Framework/LOOM/Internal/MainThreadWatchdog.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 68cbbba4b882bd94985461106f12aee3
3 | MonoImporter:
4 | serializedVersion: 2
5 | defaultReferences: []
6 | executionOrder: 0
7 | icon: {instanceID: 0}
8 | userData:
9 | assetBundleName:
10 | assetBundleVariant:
11 |
--------------------------------------------------------------------------------
/Assets/LOOM Framework/LOOM/Internal/MultithreadedWorkloadHelper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Frankfort.Threading;
3 | using UnityEngine;
4 |
5 | namespace Frankfort.Threading
6 | {
7 | public delegate void MultithreadedWorkloadComplete(T[] workLoad);
8 | public delegate void MultithreadedWorkloadPackageComplete(T[] workLoad, int firstIndex, int lastIndex);
9 | }
10 |
11 |
12 |
13 |
14 | namespace Frankfort.Threading.Internal
15 | {
16 | public delegate void ThreadWorkloadExecutor(T workload);
17 | public delegate void ThreadWorkloadExecutorIndexed(T workload, int workloadIndex);
18 | public delegate void ThreadWorkloadExecutorArg(T workload, object extraArgument);
19 | public delegate void ThreadWorkloadExecutorArgIndexed(T workload, int workloadIndex, object extraArgument);
20 |
21 |
22 |
23 | ///
24 | /// Helps making use of the IThreadWorkerObject-interface and helps you distribute the workload evenly to multiple-cores the easy way.
25 | /// This class divides your workload into smaller pieces, feeds them to the ThreadPool.
26 | ///
27 | public static class MultithreadedWorkloadHelper
28 | {
29 |
30 |
31 | ///
32 | /// Helps spreading the same repetetive workload over multiple threads/cores in an easy way.
33 | ///
34 | /// Generic-Type of the delegate that will be executed and compute the workload
35 | /// Generic-Type of the object you want to be computed by the executor
36 | /// A (static) method that computes one workLoad-object at a time
37 | /// An array with objects you want to get computed by the executor
38 | /// Fired when all re-packaged workLoad-objects are finished computing
39 | /// Fires foreach finished re-packaged set of workLoad-object
40 | /// Lets you choose how many threads will be run simultaneously by the threadpool. Default: -1 == number of cores minus one, to make sure the MainThread has at least one core to run on. (quadcore == 1 core Mainthread, 3 cores used by the ThreadPoolScheduler)
41 | /// If Null, a new ThreadPoolScheduler will be instantiated.
42 | /// Executes all the computations within try-catch events, logging it the message + stacktrace
43 | /// A ThreadPoolScheduler that handles all the repackaged workLoad-Objects =
44 | public static ThreadPoolScheduler StartMultithreadedWorkloadExecution(D executor, T[] workLoad, object extraArgument, MultithreadedWorkloadComplete onComplete, MultithreadedWorkloadPackageComplete onPackageComplete, int maxThreads = -1, ThreadPoolScheduler scheduler = null, bool safeMode = true)
45 | {
46 | if (scheduler == null)
47 | {
48 | scheduler = Loom.CreateThreadPoolScheduler();
49 | }
50 | else if (scheduler.isBusy)
51 | {
52 | Debug.LogError("Provided Scheduler stil busy!!!");
53 | }
54 |
55 | if (maxThreads <= 0)
56 | maxThreads = Mathf.Max(SystemInfo.processorCount - 1, 1);
57 |
58 | int packagesPerThread = 1;
59 | if (maxThreads > 1) //If we are running in just one thread at a time, just use one, if more, for sake of better cpu-saturation, subdive into smaller packages per core.
60 | packagesPerThread = 2;
61 |
62 | int packages = Mathf.Min(maxThreads * packagesPerThread, workLoad.Length);
63 | int objectsPerPackage = (int)Mathf.Ceil((float)workLoad.Length / (float)packages);
64 |
65 | ThreadWorkDistribution[] workerPackages = new ThreadWorkDistribution[packages];
66 | Type delegateType = typeof(D);
67 | //Debug.Log(delegateType.FullName);
68 |
69 | int count = 0;
70 | for (int i = 0; i < packages; i++)
71 | {
72 | int packagedSize = Mathf.Min(workLoad.Length - count, objectsPerPackage);
73 | if (delegateType == typeof(ThreadWorkloadExecutor))
74 | {
75 | workerPackages[i] = new ThreadWorkDistribution((executor as ThreadWorkloadExecutor), workLoad, count, count + packagedSize);
76 | }
77 | else if (delegateType == typeof(ThreadWorkloadExecutorIndexed))
78 | {
79 | workerPackages[i] = new ThreadWorkDistribution((executor as ThreadWorkloadExecutorIndexed), workLoad, count, count + packagedSize);
80 | }
81 | else if (delegateType == typeof(ThreadWorkloadExecutorArg))
82 | {
83 | workerPackages[i] = new ThreadWorkDistribution((executor as ThreadWorkloadExecutorArg), workLoad, extraArgument, count, count + packagedSize);
84 | }
85 | else if (delegateType == typeof(ThreadWorkloadExecutorArgIndexed))
86 | {
87 | workerPackages[i] = new ThreadWorkDistribution((executor as ThreadWorkloadExecutorArgIndexed), workLoad, extraArgument, count, count + packagedSize);
88 | }
89 |
90 | workerPackages[i].ID = i;
91 | count += objectsPerPackage;
92 | }
93 |
94 |
95 |
96 | //--------------- Store session data --------------------
97 | ThreadWorkDistributionSession sessionData = new ThreadWorkDistributionSession();
98 | sessionData.workLoad = workLoad;
99 | sessionData.onComplete = onComplete;
100 | sessionData.onPackageComplete = onPackageComplete;
101 | sessionData.packages = workerPackages;
102 | //--------------- Store session data --------------------
103 |
104 |
105 | scheduler.StartASyncThreads(workerPackages, sessionData.onCompleteBubble, sessionData.onPackageCompleteBubble, maxThreads, safeMode);
106 | return scheduler;
107 | }
108 |
109 | }
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 | ///
124 | /// Generic class to store temporary divideed Threadwork data for internal usage
125 | ///
126 | /// The generic Type of the object being processed by the Executor
127 | public class ThreadWorkDistributionSession
128 | {
129 | public MultithreadedWorkloadComplete onComplete;
130 | public MultithreadedWorkloadPackageComplete onPackageComplete;
131 | public T[] workLoad;
132 | public ThreadWorkDistribution[] packages;
133 |
134 |
135 | public void onCompleteBubble(IThreadWorkerObject[] finishedObjects)
136 | {
137 | if (onComplete != null)
138 | onComplete(workLoad);
139 | }
140 | public void onPackageCompleteBubble(IThreadWorkerObject finishedObject)
141 | {
142 | if (onPackageComplete != null)
143 | {
144 | ThreadWorkDistribution fCast = (ThreadWorkDistribution)finishedObject;
145 |
146 | if (fCast != null)
147 | onPackageComplete(fCast.workLoad, fCast.startIndex, fCast.endIndex - 1);
148 | }
149 | }
150 | }
151 |
152 |
153 |
154 | ///
155 | /// Simple IThreadWorkerObject implementation that spreads the workload-objects for you. This saves you the efford to subdive your workload into multiple packages yourself.
156 | ///
157 | /// Generic-Type of the object you want to be computed by the executor
158 | public class ThreadWorkDistribution : IThreadWorkerObject
159 | {
160 | public int ID;
161 | public ThreadWorkloadExecutor workloadExecutor;
162 | public ThreadWorkloadExecutorIndexed workloadExecutorIndexed;
163 | public ThreadWorkloadExecutorArg workloadExecutorArg;
164 | public ThreadWorkloadExecutorArgIndexed workloadExecutorArgIndexed;
165 |
166 | public int startIndex;
167 | public int endIndex;
168 | public T[] workLoad;
169 | public object extraArgument;
170 | private bool _isAborted = false;
171 |
172 |
173 | ///
174 | /// ThreadWorkDistribion is a workload-packages containing a subdived segment of work based on the workload divided by the amount of packages
175 | ///
176 | /// A (static) method that computes one workLoad-object at a time
177 | /// An array with objects you want to get computed by the executor
178 | public ThreadWorkDistribution(ThreadWorkloadExecutor workloadExecutor, T[] workLoad, int startIndex, int endIndex)
179 | {
180 | this.workloadExecutor = workloadExecutor;
181 | this.workLoad = workLoad;
182 | this.startIndex = startIndex;
183 | this.endIndex = endIndex;
184 | }
185 |
186 | ///
187 | /// ThreadWorkDistribion is a workload-packages containing a subdived segment of work based on the workload divided by the amount of packages
188 | ///
189 | /// A (static) method that computes one workLoad-object at a time and provides the index of the array it origionally came from
190 | /// An array with objects you want to get computed by the executor
191 | public ThreadWorkDistribution(ThreadWorkloadExecutorIndexed workloadExecutorIndexed, T[] workLoad, int startIndex, int endIndex)
192 | {
193 | this.workloadExecutorIndexed = workloadExecutorIndexed;
194 | this.workLoad = workLoad;
195 | this.startIndex = startIndex;
196 | this.endIndex = endIndex;
197 | }
198 |
199 |
200 | ///
201 | /// ThreadWorkDistribion is a workload-packages containing a subdived segment of work based on the workload divided by the amount of packages
202 | ///
203 | /// A (static) method that computes one workLoad-object at a time and provides the index of the array it origionally came from
204 | /// An array with objects you want to get computed by the executor
205 | /// An extra Argument will be passed to the Executor if present
206 | public ThreadWorkDistribution(ThreadWorkloadExecutorArg workloadExecutorArg, T[] workLoad, object extraArgument, int startIndex, int endIndex)
207 | {
208 | this.workloadExecutorArg = workloadExecutorArg;
209 | this.workLoad = workLoad;
210 | this.startIndex = startIndex;
211 | this.endIndex = endIndex;
212 | this.extraArgument = extraArgument;
213 | }
214 |
215 | ///
216 | /// ThreadWorkDistribion is a workload-packages containing a subdived segment of work based on the workload divided by the amount of packages
217 | ///
218 | /// A (static) method that computes one workLoad-object at a time and provides the index of the array it origionally came from
219 | /// An array with objects you want to get computed by the executor
220 | /// An extra Argument will be passed to the Executor if present
221 | public ThreadWorkDistribution(ThreadWorkloadExecutorArgIndexed workloadExecutorArgIndexed, T[] workLoad, object extraArgument, int startIndex, int endIndex)
222 | {
223 | this.workloadExecutorArgIndexed = workloadExecutorArgIndexed;
224 | this.workLoad = workLoad;
225 | this.startIndex = startIndex;
226 | this.endIndex = endIndex;
227 | this.extraArgument = extraArgument;
228 | }
229 |
230 |
231 |
232 |
233 |
234 | ///
235 | /// IThreadWorkerObject implementation: This method computes all the work.
236 | ///
237 | public void ExecuteThreadedWork()
238 | {
239 | if (workLoad == null || workLoad.Length == 0)
240 | return;
241 |
242 | //Debug.Log("Execute ID: " + ID + ", startIndex: " + startIndex + ", endIndex: " + endIndex);
243 | if (workloadExecutor != null)
244 | {
245 | for (int i = startIndex; i < endIndex && !_isAborted; i++)
246 | {
247 | UnityActivityWatchdog.SleepOrAbortIfUnityInactive();
248 | workloadExecutor(workLoad[i]);
249 | }
250 | }
251 | else if (workloadExecutorIndexed != null)
252 | {
253 | for (int i = startIndex; i < endIndex && !_isAborted; i++)
254 | {
255 | UnityActivityWatchdog.SleepOrAbortIfUnityInactive();
256 | workloadExecutorIndexed(workLoad[i], i);
257 | }
258 | }
259 | else if (workloadExecutorArg != null)
260 | {
261 | for (int i = startIndex; i < endIndex && !_isAborted; i++)
262 | {
263 | UnityActivityWatchdog.SleepOrAbortIfUnityInactive();
264 | workloadExecutorArg(workLoad[i], extraArgument);
265 | }
266 | }
267 | else if (workloadExecutorArgIndexed != null)
268 | {
269 | for (int i = startIndex; i < endIndex && !_isAborted; i++)
270 | {
271 | UnityActivityWatchdog.SleepOrAbortIfUnityInactive();
272 | workloadExecutorArgIndexed(workLoad[i], i, extraArgument);
273 | }
274 | }
275 | }
276 |
277 | public void AbortThreadedWork()
278 | {
279 | _isAborted = true;
280 | }
281 | }
282 |
283 | }
284 |
--------------------------------------------------------------------------------
/Assets/LOOM Framework/LOOM/Internal/MultithreadedWorkloadHelper.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: b29333d89ca53dd49837fcd9418f3cf3
3 | MonoImporter:
4 | serializedVersion: 2
5 | defaultReferences: []
6 | executionOrder: 0
7 | icon: {instanceID: 0}
8 | userData:
9 | assetBundleName:
10 | assetBundleVariant:
11 |
--------------------------------------------------------------------------------
/Assets/LOOM Framework/LOOM/Internal/SingleThreadStarter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Threading;
4 | using Frankfort.Threading;
5 | using UnityEngine;
6 |
7 |
8 | namespace Frankfort.Threading.Internal
9 | {
10 |
11 | ///
12 | /// The SingleThreadStarter is a safe/managed wrapper around the normal new Thread() & Thread.Start();
13 | /// It also initiates all the helpers such as the MainThreadDispatcher, WaitForSeconds & WaitForSeconds commands.
14 | ///
15 | public static class SingleThreadStarter
16 | {
17 |
18 | //--------------------------------------- SAFEMODE WRAPPERS --------------------------------------
19 | //--------------------------------------- SAFEMODE WRAPPERS --------------------------------------
20 | #region SAFEMODE WRAPPERS
21 |
22 | ///
23 | /// Internal temporary session data needed to fire a Singele-thread safely.
24 | ///
25 | private class SafeSingleThreadSession
26 | {
27 | private ThreadStart targetMethod;
28 | private ParameterizedThreadStart paramTargetMethod;
29 |
30 | public SafeSingleThreadSession(ThreadStart targetMethod)
31 | {
32 | this.targetMethod = targetMethod;
33 | }
34 | public SafeSingleThreadSession(ParameterizedThreadStart targetMethod)
35 | {
36 | this.paramTargetMethod = targetMethod;
37 | }
38 |
39 |
40 |
41 | public void SafeExecte_ThreadStart()
42 | {
43 | try
44 | {
45 | targetMethod();
46 | }
47 | catch (Exception e)
48 | {
49 | Loom.DispatchToMainThread(() => Debug.LogError(e.Message + e.StackTrace + "\n\n"), true);
50 | }
51 | }
52 |
53 | public void SafeExecte_ParamThreadStart(object argument)
54 | {
55 | try
56 | {
57 | paramTargetMethod(argument);
58 | }
59 | catch (Exception e)
60 | {
61 | Loom.DispatchToMainThread(() => Debug.LogError(e.Message + e.StackTrace + "\n\n"), true);
62 | }
63 | }
64 | }
65 |
66 | #endregion
67 | //--------------------------------------- SAFEMODE WRAPPERS --------------------------------------
68 | //--------------------------------------- SAFEMODE WRAPPERS --------------------------------------
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 | //--------------------------------------- 2 START SINGLE THREAD OVERLOADS --------------------------------------
84 | //--------------------------------------- 2 START SINGLE THREAD OVERLOADS --------------------------------------
85 | #region 2 START SINGLE THREAD OVERLOADS
86 |
87 |
88 | private static bool helperCreated;
89 | private static List startedThreads = new List();
90 |
91 |
92 |
93 | ///
94 | /// Starts an method running on a new thread. The Thread dies when the method has stopped running.
95 | /// You can now make use of the DispatchToMainThread-actions & WaitForNextFrame
96 | ///
97 | /// The method that will be executed by the thread
98 | /// Thread priority
99 | /// Newly instantiated Thread
100 | public static Thread StartSingleThread(ThreadStart targetMethod, System.Threading.ThreadPriority priority = System.Threading.ThreadPriority.Normal, bool safeMode = true)
101 | {
102 | Init();
103 | MainThreadWatchdog.Init();
104 | MainThreadDispatcher.Init();
105 | UnityActivityWatchdog.Init();
106 |
107 | Thread result = null;
108 | if(safeMode)
109 | {
110 | SafeSingleThreadSession sessionData = new SafeSingleThreadSession(targetMethod);
111 | result = new Thread(sessionData.SafeExecte_ThreadStart);
112 | }
113 | else
114 | {
115 | result = new Thread(targetMethod);
116 | }
117 |
118 | result.Priority = priority;
119 | startedThreads.Add(result);
120 | result.Start();
121 | return result;
122 | }
123 |
124 |
125 |
126 | ///
127 | /// Starts an method running on a new thread. The Thread dies when the method has stopped running.
128 | /// You can now make use of the DispatchToMainThread-actions & WaitForNextFrame
129 | ///
130 | /// The method that will be executed by the thread
131 | /// Object to pass to the targetMethod as soon as the Thread is started
132 | /// Thread priority
133 | /// Newly instantiated Thread
134 | public static Thread StartSingleThread(ParameterizedThreadStart targetMethod, object argument, System.Threading.ThreadPriority priority = System.Threading.ThreadPriority.Normal, bool safeMode = true)
135 | {
136 | Init();
137 | MainThreadWatchdog.Init();
138 | MainThreadDispatcher.Init();
139 | UnityActivityWatchdog.Init();
140 |
141 | Thread result = null;
142 | if (safeMode)
143 | {
144 | SafeSingleThreadSession sessionData = new SafeSingleThreadSession(targetMethod);
145 | result = new Thread(sessionData.SafeExecte_ParamThreadStart);
146 | }
147 | else
148 | {
149 | result = new Thread(targetMethod);
150 | }
151 |
152 | result.Priority = priority;
153 | startedThreads.Add(result);
154 |
155 | result.Start(argument);
156 | return result;
157 | }
158 |
159 | #endregion
160 | //--------------------------------------- 2 START SINGLE THREAD OVERLOADS --------------------------------------
161 | //--------------------------------------- 2 START SINGLE THREAD OVERLOADS --------------------------------------
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 | //--------------------------------------- INIT --------------------------------------
177 | //--------------------------------------- INIT --------------------------------------
178 | #region INIT
179 |
180 | ///
181 | /// Starts the Helper & validates the running Threads.
182 | ///
183 | private static void Init()
184 | {
185 | ValidateThreadStates();
186 | if (!helperCreated)
187 | CreateHelperGameObject();
188 | }
189 |
190 |
191 | private static void CreateHelperGameObject()
192 | {
193 | GameObject helperGO = new GameObject("SingleThreadHelper");
194 | SingleThreadHelper helper = helperGO.AddComponent();
195 | helperGO.hideFlags = helper.hideFlags = HideFlags.HideInHierarchy | HideFlags.HideInInspector;
196 | GameObject.DontDestroyOnLoad(helperGO);
197 | helperCreated = true;
198 | }
199 | #endregion
200 | //--------------------------------------- INIT --------------------------------------
201 | //--------------------------------------- INIT --------------------------------------
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 | //--------------------------------------- MANAGE THREADS --------------------------------------
215 | //--------------------------------------- MANAGE THREADS --------------------------------------
216 | #region MANAGE THREADS
217 |
218 | ///
219 | /// Aborts all running threads.
220 | ///
221 | public static void AbortRunningThreads()
222 | {
223 | ValidateThreadStates();
224 | Debug.Log("Abort running Threads: " + startedThreads.Count);
225 | foreach (Thread thread in startedThreads)
226 | thread.Abort();
227 | }
228 |
229 | ///
230 | /// Thread-state validation.
231 | ///
232 | private static void ValidateThreadStates()
233 | {
234 | int i = startedThreads.Count;
235 | while (--i > -1)
236 | {
237 | Thread thread = startedThreads[i];
238 | if( thread.ThreadState == ThreadState.Aborted ||
239 | thread.ThreadState == ThreadState.AbortRequested ||
240 | thread.ThreadState == ThreadState.Stopped ||
241 | thread.ThreadState == ThreadState.StopRequested ||
242 | thread.ThreadState == ThreadState.Unstarted )
243 | {
244 | startedThreads.RemoveAt(i);
245 | }
246 | }
247 | }
248 |
249 | #endregion
250 | //--------------------------------------- MANAGE THREADS --------------------------------------
251 | //--------------------------------------- MANAGE THREADS --------------------------------------
252 | }
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 | //--------------------------------------- SINGLE THREAD HELPER COMPONENT --------------------------------------
265 | //--------------------------------------- SINGLE THREAD HELPER COMPONENT --------------------------------------
266 | #region SINGLE THREAD HELPER COMPONENT
267 |
268 | public class SingleThreadHelper : MonoBehaviour
269 | {
270 | private void OnApplicationQuit()
271 | {
272 | SingleThreadStarter.AbortRunningThreads();
273 | }
274 | }
275 |
276 | #endregion
277 | //--------------------------------------- SINGLE THREAD HELPER COMPONENT --------------------------------------
278 | //--------------------------------------- SINGLE THREAD HELPER COMPONENT --------------------------------------
279 |
280 | }
281 |
--------------------------------------------------------------------------------
/Assets/LOOM Framework/LOOM/Internal/SingleThreadStarter.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: ecb136529f44b7d4992d3dbf506fd649
3 | MonoImporter:
4 | serializedVersion: 2
5 | defaultReferences: []
6 | executionOrder: 0
7 | icon: {instanceID: 0}
8 | userData:
9 | assetBundleName:
10 | assetBundleVariant:
11 |
--------------------------------------------------------------------------------
/Assets/LOOM Framework/LOOM/Internal/ThreadDispatchAction.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading;
3 |
4 | namespace Frankfort.Threading.Internal
5 | {
6 | public class ThreadDispatchAction
7 | {
8 | public bool executed = false;
9 | public object dispatchExecutionResult = null;
10 |
11 | private ThreadDispatchDelegate dispatchCallClean;
12 | private ThreadDispatchDelegateArg dispatchCallArg;
13 | private ThreadDispatchDelegateArgReturn dispatchCallArgReturn;
14 | private ThreadDispatchDelegateReturn dispatchCallReturn;
15 |
16 | private object dispatchArgParam;
17 | private bool safeMode;
18 |
19 |
20 | public ThreadDispatchAction()
21 | {
22 | //Do nothing...
23 | }
24 |
25 |
26 |
27 | //--------------------------------------- 4 DIFFERENT OVERLOADS --------------------------------------
28 | //--------------------------------------- 4 DIFFERENT OVERLOADS --------------------------------------
29 | #region 4 DIFFERENT OVERLOADS
30 |
31 | public void Init(ThreadDispatchDelegate dispatchCall, bool waitForExecution, bool safeMode)
32 | {
33 | this.safeMode = safeMode;
34 | this.dispatchCallClean = dispatchCall;
35 | ValidateExecutionOnInit(waitForExecution);
36 | }
37 |
38 | public void Init(ThreadDispatchDelegateArg dispatchCall, object dispatchArgumentParameter, bool waitForExecution, bool safeMode)
39 | {
40 | this.safeMode = safeMode;
41 | this.dispatchCallArg = dispatchCall;
42 | this.dispatchArgParam = dispatchArgumentParameter;
43 | ValidateExecutionOnInit(waitForExecution);
44 | }
45 |
46 | public void Init(ThreadDispatchDelegateArgReturn dispatchCall, object dispatchArgumentParameter, bool safeMode)
47 | {
48 | this.safeMode = safeMode;
49 | this.dispatchCallArgReturn = dispatchCall;
50 | this.dispatchArgParam = dispatchArgumentParameter;
51 | ValidateExecutionOnInit(true); //Forced to wait, the return-result should always be available after execution
52 | }
53 |
54 | public void Init(ThreadDispatchDelegateReturn dispatchCall, bool safeMode)
55 | {
56 | this.safeMode = safeMode;
57 | this.dispatchCallReturn = dispatchCall;
58 | ValidateExecutionOnInit(true); //Forced to wait, the return-result should always be available after execution
59 | }
60 | #endregion
61 | //--------------------------------------- 4 DIFFERENT OVERLOADS --------------------------------------
62 | //--------------------------------------- 4 DIFFERENT OVERLOADS --------------------------------------
63 |
64 |
65 |
66 |
67 |
68 |
69 | private void ValidateExecutionOnInit(bool waitForExecution)
70 | {
71 | if (waitForExecution)
72 | {
73 | if (!MainThreadWatchdog.CheckIfMainThread())
74 | {
75 | while (!executed)
76 | Thread.Sleep(1);
77 | }
78 | else
79 | {
80 | ExecuteDispatch();
81 | }
82 | }
83 | }
84 |
85 | public void ExecuteDispatch()
86 | {
87 | if (safeMode)
88 | {
89 | try
90 | {
91 | if (dispatchCallClean != null)
92 | {
93 | dispatchCallClean();
94 | }
95 | else if (dispatchCallArg != null)
96 | {
97 | dispatchCallArg(dispatchArgParam);
98 | }
99 | else if (dispatchCallArgReturn != null)
100 | {
101 | dispatchExecutionResult = dispatchCallArgReturn(dispatchArgParam);
102 | }
103 | else if (dispatchCallReturn != null)
104 | {
105 | dispatchExecutionResult = dispatchCallReturn();
106 | }
107 | }
108 | catch (Exception e)
109 | {
110 | //At this point, we should always be in the MainThread anyways...
111 | UnityEngine.Debug.Log(e.Message + e.StackTrace);
112 | }
113 | }
114 | else
115 | {
116 | if (dispatchCallClean != null)
117 | {
118 | dispatchCallClean();
119 | }
120 | else if (dispatchCallArg != null)
121 | {
122 | dispatchCallArg(dispatchArgParam);
123 | }
124 | else if (dispatchCallArgReturn != null)
125 | {
126 | dispatchExecutionResult = dispatchCallArgReturn(dispatchArgParam);
127 | }
128 | else if (dispatchCallReturn != null)
129 | {
130 | dispatchExecutionResult = dispatchCallReturn();
131 | }
132 | }
133 |
134 | executed = true;
135 | }
136 | }
137 | }
138 |
--------------------------------------------------------------------------------
/Assets/LOOM Framework/LOOM/Internal/ThreadDispatchAction.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 79a2844752fc02e4f9b1fe3a3e63a0f2
3 | MonoImporter:
4 | serializedVersion: 2
5 | defaultReferences: []
6 | executionOrder: 0
7 | icon: {instanceID: 0}
8 | userData:
9 | assetBundleName:
10 | assetBundleVariant:
11 |
--------------------------------------------------------------------------------
/Assets/LOOM Framework/LOOM/Internal/ThreadPoolSchedulerWorkerObjects.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Threading;
4 | using UnityEngine;
5 |
6 |
7 |
8 | namespace Frankfort.Threading.Internal
9 | {
10 | public class ThreadWorkStatePackage
11 | {
12 | public bool safeMode = true;
13 | //public bool safeModeErrorFound;
14 | //public List safeModeErrorLog = new List();
15 |
16 | public bool started;
17 | public bool running;
18 | public bool finishedWorking;
19 | public bool eventFired;
20 |
21 | public IThreadWorkerObject workerObject;
22 | public AutoResetEvent waitHandle;
23 |
24 |
25 | public void ExecuteThreadWork(object obj)
26 | {
27 | running = true;
28 |
29 | if (workerObject == null || waitHandle == null)
30 | return;
31 |
32 | //Thread.CurrentThread.Priority = System.Threading.ThreadPriority.AboveNormal;
33 |
34 | if (safeMode)
35 | {
36 | try
37 | {
38 | workerObject.ExecuteThreadedWork();
39 | }
40 | catch (Exception e)
41 | {
42 | //safeModeErrorFound = true;
43 | //safeModeErrorLog.Add(e.Message + e.StackTrace);
44 | Loom.DispatchToMainThread(() => Debug.LogError(e.Message + e.StackTrace + "\n\n"), true);
45 | }
46 | }
47 | else
48 | {
49 | workerObject.ExecuteThreadedWork();
50 | }
51 |
52 | running = false;
53 | finishedWorking = true;
54 | waitHandle.Set(); //Fire back to the MainThread!
55 | }
56 | }
57 |
58 |
59 |
60 |
61 | ///
62 | /// Used as packaged set of variables to be fed to the WorkProvider-Thread.
63 | ///
64 | public class ASyncThreadWorkData
65 | {
66 | public ThreadWorkStatePackage[] workerPackages;
67 | public int maxWorkingThreads;
68 |
69 | public ASyncThreadWorkData(IThreadWorkerObject[] workerObjects, bool safeMode, int maxWorkingThreads = -1)
70 | {
71 | if (workerObjects == null)
72 | return;
73 |
74 | workerPackages = new ThreadWorkStatePackage[workerObjects.Length];
75 |
76 | int i = workerObjects.Length;
77 | while (--i > -1)
78 | {
79 | ThreadWorkStatePackage package = new ThreadWorkStatePackage();
80 | package.waitHandle = new AutoResetEvent(false);
81 | package.workerObject = workerObjects[i];
82 | package.safeMode = safeMode;
83 | workerPackages[i] = package;
84 | }
85 |
86 | if (maxWorkingThreads <= 0)
87 | {
88 | maxWorkingThreads = Mathf.Max(SystemInfo.processorCount - 1, 1);
89 | }
90 | else
91 | {
92 | this.maxWorkingThreads = maxWorkingThreads;
93 | }
94 | }
95 |
96 |
97 | public void Dispose()
98 | {
99 | if (workerPackages != null)
100 | {
101 | foreach (ThreadWorkStatePackage package in workerPackages)
102 | {
103 | if (package.waitHandle != null)
104 | package.waitHandle.Close();
105 |
106 | package.waitHandle = null;
107 | package.workerObject = null;
108 | }
109 | }
110 | workerPackages = null;
111 | }
112 | }
113 | }
--------------------------------------------------------------------------------
/Assets/LOOM Framework/LOOM/Internal/ThreadPoolSchedulerWorkerObjects.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 4d6f36171468b624bac7bf4b80fc3744
3 | MonoImporter:
4 | serializedVersion: 2
5 | defaultReferences: []
6 | executionOrder: 0
7 | icon: {instanceID: 0}
8 | userData:
9 | assetBundleName:
10 | assetBundleVariant:
11 |
--------------------------------------------------------------------------------
/Assets/LOOM Framework/LOOM/Internal/ThreadWaitCommands.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading;
3 | using UnityEngine;
4 |
5 | namespace Frankfort.Threading.Internal
6 | {
7 | public class ThreadWaitForSeconds
8 | {
9 | public ThreadWaitForSeconds(float seconds)
10 | {
11 | if (MainThreadWatchdog.CheckIfMainThread())
12 | {
13 | Debug.Log("Its not allowed to put the MainThread to sleep!");
14 | return;
15 | }
16 |
17 | Thread.Sleep((int)Mathf.Max( 1, Mathf.Round(seconds * 1000f)));
18 |
19 | while (!UnityActivityWatchdog.CheckUnityActive())
20 | Thread.Sleep(5);
21 | }
22 | }
23 |
24 |
25 | public class ThreadWaitForNextFrame
26 | {
27 | public ThreadWaitForNextFrame(int waitFrames = 1, int sleepTime = 5)
28 | {
29 | if (waitFrames > 0)
30 | {
31 | if (MainThreadWatchdog.CheckIfMainThread())
32 | {
33 | Debug.Log("Its not allowed to put the MainThread to sleep!");
34 | return;
35 | }
36 |
37 | int startFrame = MainThreadDispatcher.currentFrame;
38 | Thread.Sleep(sleepTime);
39 |
40 | while (!UnityActivityWatchdog.CheckUnityActive() || startFrame + waitFrames >= MainThreadDispatcher.currentFrame)
41 | Thread.Sleep(sleepTime);
42 | }
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/Assets/LOOM Framework/LOOM/Internal/ThreadWaitCommands.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 675d17e578edce543b1e6db0561c5e87
3 | MonoImporter:
4 | serializedVersion: 2
5 | defaultReferences: []
6 | executionOrder: 0
7 | icon: {instanceID: 0}
8 | userData:
9 | assetBundleName:
10 | assetBundleVariant:
11 |
--------------------------------------------------------------------------------
/Assets/LOOM Framework/LOOM/Internal/UnityActivityWatchdog.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using UnityEngine;
3 | using System.Threading;
4 |
5 |
6 | namespace Frankfort.Threading.Internal
7 | {
8 | public class UnityActivityWatchdog : MonoBehaviour
9 | {
10 | private static bool helperCreated = false;
11 | private static bool unityRunning = true;
12 | private static bool unityPaused = false;
13 | private static bool unityFocused = true;
14 | private static bool combinedActive = true;
15 |
16 |
17 |
18 |
19 | //--------------------------------------- CHECK UNTIY ACTIVE --------------------------------------
20 | //--------------------------------------- CHECK UNTIY ACTIVE --------------------------------------
21 | #region CHECK UNTIY ACTIVE
22 |
23 | ///
24 | /// A easy way to check if Unity is still running, focused and not pauzed.
25 | /// This comes in handy if threads keep running heavy workloads on seperate threads while IOS for example tries to puch the Application to the background.
26 | /// If you are executing a giant routine on a seperate thread that takes several seconds per cycle, you might want to check regularly if unity is still active by using this check.
27 | ///
28 | /// Returns TRUE if Unity is still running, not pauzed and has focus.
29 | public static bool CheckUnityActive()
30 | {
31 | Init();
32 | return combinedActive;
33 | }
34 |
35 |
36 |
37 | ///
38 | /// !IMPORTANT! This method should be called regularly within routines that take more then half a second to complete, to make sure IOS for example is able to force an application to sleep when it looses focus or gets puched to the background.
39 | /// This is a very light-weight check, internally it only needs to check two static booleans once everything is Initialized and running.
40 | /// You can use this without causing any serious overhead.
41 | /// Motivation: Sins Threads cannot be put asleep from the outside, it needs the be managed from within the thread itself, thats why this method was build.
42 | ///
43 | /// Example:
44 | /// for(int i = 0; i < 999999999; i++)
45 | /// {
46 | /// Loom.SleepOrAbortIfUnityInactive(); //Prevents IOS for example of killing this app because the threads won't sleep once your unity-app is puched to the background.
47 | /// //Do something heavy that will cause this routine to run more then 0.5 seconds.
48 | /// }
49 | ///
50 | public static void SleepOrAbortIfUnityInactive()
51 | {
52 | Init();
53 | while (!combinedActive && !MainThreadWatchdog.CheckIfMainThread())
54 | {
55 | if (unityRunning)
56 | {
57 | //Debug.Log("UNITY INACTIVE: About to sleep for 100 ms: " + Thread.CurrentThread.ManagedThreadId);
58 | Thread.Sleep(100);
59 | }
60 | else
61 | {
62 | //Debug.Log("UNITY NOT RUNNING: About to abort: " + Thread.CurrentThread.ManagedThreadId);
63 | Thread.CurrentThread.Abort();
64 | }
65 | }
66 | }
67 |
68 | #endregion
69 | //--------------------------------------- CHECK UNTIY ACTIVE --------------------------------------
70 | //--------------------------------------- CHECK UNTIY ACTIVE --------------------------------------
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 | //--------------------------------------- INIT --------------------------------------
83 | //--------------------------------------- INIT --------------------------------------
84 | #region INIT
85 |
86 | ///
87 | /// Starts the Helper & validates the running Threads.
88 | ///
89 | public static void Init()
90 | {
91 | if (!helperCreated)
92 | CreateHelperGameObject();
93 | }
94 |
95 |
96 | private static void CreateHelperGameObject()
97 | {
98 | GameObject helperGO = new GameObject("UnityActivityHelper");
99 | UnityActivityWatchdog helper = helperGO.AddComponent();
100 | helperGO.hideFlags = helper.hideFlags = HideFlags.HideInHierarchy | HideFlags.HideInInspector;
101 | GameObject.DontDestroyOnLoad(helperGO);
102 | helperCreated = true;
103 | }
104 |
105 | #endregion
106 | //--------------------------------------- INIT --------------------------------------
107 | //--------------------------------------- INIT --------------------------------------
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 | //--------------------------------------- LISTEN TO UNITY CALLS --------------------------------------
119 | //--------------------------------------- LISTEN TO UNITY CALLS --------------------------------------
120 | #region LISTEN TO UNITY CALLS
121 |
122 | private void OnApplicationQuit()
123 | {
124 | unityRunning = false;
125 | UpdateStatus();
126 | Debug.Log("UnityActivityWatchdog: OnApplicationQuit");
127 | }
128 | private void OnApplicationPause(bool pause)
129 | {
130 | unityPaused = pause;
131 | UpdateStatus();
132 | Debug.Log("UnityActivityWatchdog: OnApplicationPauze [" + pause + "]");
133 | }
134 | private void OnApplicationFocus(bool focus)
135 | {
136 | unityFocused = focus;
137 | UpdateStatus();
138 | Debug.Log("UnityActivityWatchdog: OnApplicationFocus [" + focus + "]");
139 | }
140 |
141 | private static void UpdateStatus()
142 | {
143 | #if UNITY_IPHONE
144 | combinedActive = unityRunning && unityFocused && !unityPaused;
145 | #elif UNITY_ANDROID
146 | combinedActive = unityRunning && unityFocused && !unityPaused;
147 | #else
148 | combinedActive = unityRunning && !unityPaused;
149 | #endif
150 | }
151 | #endregion
152 | //--------------------------------------- LISTEN TO UNITY CALLS --------------------------------------
153 | //--------------------------------------- LISTEN TO UNITY CALLS --------------------------------------
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 | }
162 | }
--------------------------------------------------------------------------------
/Assets/LOOM Framework/LOOM/Internal/UnityActivityWatchdog.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: f4f34b4872834024097444da6c8b8ae0
3 | MonoImporter:
4 | serializedVersion: 2
5 | defaultReferences: []
6 | executionOrder: 0
7 | icon: {instanceID: 0}
8 | userData:
9 | assetBundleName:
10 | assetBundleVariant:
11 |
--------------------------------------------------------------------------------
/Assets/LOOM Framework/LOOM/Loom.cs:
--------------------------------------------------------------------------------
1 | /*
2 | Thank you for using "Loom for Unity". This code was written by Michiel Frankfort - Q1 2013.
3 |
4 | Features:
5 | - Turn your app into a true Multi-Threaded application overnight! Starting a simple worker/background thread is not a challenge... Utilizing all the available cores for one (or more) heavy-duty tasks is a true challenge! This framework helps you spread the workload to all cores and manage them the easy way.
6 | - Powerfull “DispatchToMainThread” tools, which let you instantiate and directly use Unity-objects from the external threads!
7 | - Three Demo's included:
8 | Flocking Massive: A Multi-threaded flocking demo, prept to run on a Samsung Galaxy S3 with 7000 boids!!!
9 |
10 | Texture blur: Shows how easy it is to use this framework for repetitive tasks, using the “StartMultithreadedWorkloadExecution” tool, which subdivides work into smaller packages and feeds them to multiple cores/threads.
11 |
12 | SimpleExampleImplementation: Showing how to use the “Abort”, “DispatchToMainThread-tools” and “WaitForNextFrame” actions.
13 |
14 | - No Threading experience required: you'll learn fast enough from the provided examples!
15 | - Pick your max Cores/Threads to do the work for you.
16 | - All ThreadPoolScheduler events (onComplete, onWorkerObjectDone) are fired in the MainThread / GameThread.
17 |
18 |
19 | Why did I build this?
20 | This framework was initially created as the cornerstone of the Realtime-Raytracing-engine that I'm currently working on (yes, when its done, I'll put it in the store as well)
21 | In order to obtain Realtime-Raytracing, I needed more horsepower and utilize multiple cores while keeping the MainThread alive, smooth & unblocked.
22 | So I ended up building a ThreadScheduler which fires all events in the MainThread, but does not block it.
23 |
24 | Any Field-experience so far?
25 | Products always get better when you use them yourself and where born out of need instead of theoretical appliances.
26 | This framework is up and running within my own Raytracer and has proves perfect workload delegation between cores, with low overhead.
27 | For as long as my Raytracer is under development, I'll keep iterating on this tool, and if people actually buy this tool, I'll keep providing Updates :-)
28 |
29 | API Documentation: http://www.frankfortsoftware.com/LOOM/Documentation/
30 | Support: LoomThreadingFramework@gmail.com
31 | */
32 |
33 |
34 |
35 | //111
36 |
37 |
38 |
39 | using System;
40 | using System.Threading;
41 | using System.Collections.Generic;
42 | using Frankfort.Threading;
43 | using Frankfort.Threading.Internal;
44 | using UnityEngine;
45 |
46 |
47 |
48 |
49 |
50 | ///
51 | /// Primairy accespoint/interface to all framework methods & helpers. This is just a static wrapper-class for sake of ease...
52 | ///
53 | public static class Loom
54 | {
55 |
56 |
57 | // -----test win 10.。。。。。。。 速度
58 |
59 |
60 | //--------------------------------------- 2 START SINGLE THREAD OVERLOADS --------------------------------------
61 | //--------------------------------------- 2 START SINGLE THREAD OVERLOADS --------------------------------------
62 | #region 2 START SINGLE THREAD OVERLOADS
63 |
64 |
65 |
66 | ///
67 | /// Starts an method running on a new thread. The Thread dies when the method has stopped running.
68 | /// You can now make use of the DispatchToMainThread-actions & WaitForNextFrame
69 | ///
70 | /// The method that will be executed by the new thread
71 | /// Thread Priority
72 | /// Default TRUE: Executes the targetMethod within a Try-Catch statement and will log any errors back to the MainThread
73 | /// Newly instantiated Thread
74 | public static Thread StartSingleThread(ThreadStart targetMethod, System.Threading.ThreadPriority priority = System.Threading.ThreadPriority.Normal, bool safeMode = true)
75 | {
76 | return SingleThreadStarter.StartSingleThread(targetMethod, priority, safeMode);
77 | }
78 |
79 |
80 |
81 |
82 | ///
83 | /// Starts an method running on a new thread. The Thread dies when the method has stopped running.
84 | /// You can now make use of the DispatchToMainThread-actions & WaitForNextFrame
85 | ///
86 | /// The method that will be executed by the new thread
87 | /// Object to pass to the targetMethod as soon as the Thread is started
88 | /// Thread Priority
89 | /// Default TRUE: Executes the targetMethod within a Try-Catch statement and will log any errors back to the MainThread
90 | /// Newly instantiated Thread
91 | public static Thread StartSingleThread(ParameterizedThreadStart targetMethod, object argument, System.Threading.ThreadPriority priority = System.Threading.ThreadPriority.Normal, bool safeMode = true)
92 | {
93 | return SingleThreadStarter.StartSingleThread(targetMethod, argument, priority, safeMode);
94 | }
95 |
96 |
97 | #endregion
98 | //--------------------------------------- 2 START SINGLE THREAD OVERLOADS --------------------------------------
99 | //--------------------------------------- 2 START SINGLE THREAD OVERLOADS --------------------------------------
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 | //--------------------------------------- 4 MULTI THREADED WORK EXECUTION OVERLOADS --------------------------------------
114 | //--------------------------------------- 4 MULTI THREADED WORK EXECUTION OVERLOADS --------------------------------------
115 |
116 | #region 4 MULTI THREADED WORK EXECUTION OVERLOADS
117 | ///
118 | /// Helps spreading the same repetetive workload over multiple threads/cores in an easy way.
119 | ///
120 | /// T: Generic-Type of the object you want to be computed by the executor
121 | /// A (static) method that computes one workLoad-object at a time
122 | /// An array with objects you want to get computed by the executor
123 | /// Fired when all re-packaged workLoad-objects are finished computing
124 | /// Fires foreach finished re-packaged set of workLoad-object
125 | /// Lets you choose how many threads will be run simultaneously by the threadpool. Default: -1 == number of cores minus one, to make sure the MainThread has at least one core to run on. (quadcore == 1 core Mainthread, 3 cores used by the ThreadPoolScheduler)
126 | /// If Null, a new ThreadPoolScheduler will be instantiated.
127 | /// Executes all the computations within try-catch events, logging it the message + stacktrace
128 | /// A ThreadPoolScheduler that handles all the repackaged workLoad-Objects
129 | public static ThreadPoolScheduler StartMultithreadedWorkloadExecution(ThreadWorkloadExecutor workloadExecutor, T[] workLoad, MultithreadedWorkloadComplete onComplete, MultithreadedWorkloadPackageComplete onPackageComplete, int maxThreads = -1, ThreadPoolScheduler scheduler = null, bool safeMode = true)
130 | {
131 | return MultithreadedWorkloadHelper.StartMultithreadedWorkloadExecution, T>(workloadExecutor, workLoad, null, onComplete, onPackageComplete, maxThreads, scheduler, safeMode);
132 | }
133 |
134 |
135 |
136 | ///
137 | /// Helps spreading the same repetetive workload over multiple threads/cores in an easy way.
138 | /// Besides the workLoad-object, the current index of the workLoad-array is passed to the Executor-delegate.
139 | ///
140 | /// T: Generic-Type of the object you want to be computed by the executor
141 | /// A (static) method that computes one workLoad-object at a time
142 | /// An array with objects you want to get computed by the executor
143 | /// Fired when all re-packaged workLoad-objects are finished computing
144 | /// Fires foreach finished re-packaged set of workLoad-object
145 | /// Lets you choose how many threads will be run simultaneously by the threadpool. Default: -1 == number of cores minus one, to make sure the MainThread has at least one core to run on. (quadcore == 1 core Mainthread, 3 cores used by the ThreadPoolScheduler)
146 | /// If Null, a new ThreadPoolScheduler will be instantiated.
147 | /// Executes all the computations within try-catch events, logging it the message + stacktrace
148 | /// A ThreadPoolScheduler that handles all the repackaged workLoad-Objects
149 | public static ThreadPoolScheduler StartMultithreadedWorkloadExecution(ThreadWorkloadExecutorIndexed workloadExecutor, T[] workLoad, MultithreadedWorkloadComplete onComplete, MultithreadedWorkloadPackageComplete onPackageComplete, int maxThreads = -1, ThreadPoolScheduler scheduler = null, bool safeMode = true)
150 | {
151 | return MultithreadedWorkloadHelper.StartMultithreadedWorkloadExecution, T>(workloadExecutor, workLoad, null, onComplete, onPackageComplete, maxThreads, scheduler, safeMode);
152 | }
153 |
154 |
155 | ///
156 | /// Helps spreading the same repetetive workload over multiple threads/cores in an easy way.
157 | /// Besides the workLoad-object, an extra Argument will be passed to the Executor-delegate
158 | ///
159 | /// T: Generic-Type of the object you want to be computed by the executor
160 | /// A (static) method that computes one workLoad-object at a time
161 | /// An array with objects you want to get computed by the executor
162 | /// Fired when all re-packaged workLoad-objects are finished computing
163 | /// Fires foreach finished re-packaged set of workLoad-object
164 | /// Lets you choose how many threads will be run simultaneously by the threadpool. Default: -1 == number of cores minus one, to make sure the MainThread has at least one core to run on. (quadcore == 1 core Mainthread, 3 cores used by the ThreadPoolScheduler)
165 | /// If Null, a new ThreadPoolScheduler will be instantiated.
166 | /// Executes all the computations within try-catch events, logging it the message + stacktrace
167 | /// A ThreadPoolScheduler that handles all the repackaged workLoad-Objects
168 | public static ThreadPoolScheduler StartMultithreadedWorkloadExecution(ThreadWorkloadExecutorArg workloadExecutor, T[] workLoad, object extraArgument, MultithreadedWorkloadComplete onComplete, MultithreadedWorkloadPackageComplete onPackageComplete, int maxThreads = -1, ThreadPoolScheduler scheduler = null, bool safeMode = true)
169 | {
170 | return MultithreadedWorkloadHelper.StartMultithreadedWorkloadExecution, T>(workloadExecutor, workLoad, extraArgument, onComplete, onPackageComplete, maxThreads, scheduler, safeMode);
171 | }
172 |
173 |
174 | ///
175 | /// Helps spreading the same repetetive workload over multiple threads/cores in an easy way.
176 | /// Besides the workLoad-object, an extra Argument & the current index of the workLoad-array is passed to the Executor-delegate.
177 | ///
178 | /// T: Generic-Type of the object you want to be computed by the executor
179 | /// A (static) method that computes one workLoad-object at a time
180 | /// An array with objects you want to get computed by the executor
181 | /// Fired when all re-packaged workLoad-objects are finished computing
182 | /// Fires foreach finished re-packaged set of workLoad-object
183 | /// Lets you choose how many threads will be run simultaneously by the threadpool. Default: -1 == number of cores minus one, to make sure the MainThread has at least one core to run on. (quadcore == 1 core Mainthread, 3 cores used by the ThreadPoolScheduler)
184 | /// If Null, a new ThreadPoolScheduler will be instantiated.
185 | /// Executes all the computations within try-catch events, logging it the message + stacktrace
186 | /// A ThreadPoolScheduler that handles all the repackaged workLoad-Objects
187 | public static ThreadPoolScheduler StartMultithreadedWorkloadExecution(ThreadWorkloadExecutorArgIndexed workloadExecutor, T[] workLoad, object extraArgument, MultithreadedWorkloadComplete onComplete, MultithreadedWorkloadPackageComplete onPackageComplete, int maxThreads = -1, ThreadPoolScheduler scheduler = null, bool safeMode = true)
188 | {
189 | return MultithreadedWorkloadHelper.StartMultithreadedWorkloadExecution, T>(workloadExecutor, workLoad, extraArgument, onComplete, onPackageComplete, maxThreads, scheduler, safeMode);
190 | }
191 |
192 | #endregion
193 |
194 | //--------------------------------------- 4 MULTI THREADED WORK EXECUTION OVERLOADS --------------------------------------
195 | //--------------------------------------- 4 MULTI THREADED WORK EXECUTION OVERLOADS --------------------------------------
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 | //--------------------------------------- THREAD POOL SCHEDULER --------------------------------------
212 | //--------------------------------------- THREAD POOL SCHEDULER --------------------------------------
213 |
214 | #region THREAD POOL SCHEDULER
215 |
216 |
217 | ///
218 | /// Unlike "StartMultithreadedWorkloadExecution", you will have to build your own IThreadWorkerObject.
219 | /// Downside: It requires some extra work. Upside: you got more controll over what goes in and comes out
220 | /// Infact: You can create you own polymorphed IThreadWorkerObject-array, each ellement being a completely different type. For example: the statemachines of enemies are IThreadWorkerObject's and the array contains completely different classes with enemies/AI-behaviours.
221 | ///
222 | /// An array of IThreadWorkerObject objects to be handled by the threads. If you want multiple cores/threads to be active, make sure that the number of IThreadWorkerObject's proves matches/exeeds your preferred number maxWorkingThreads.
223 | /// Fired when all re-packaged workLoad-objects are finished computing
224 | /// Fires foreach finished re-packaged set of workLoad-object
225 | /// Lets you choose how many threads will be run simultaneously by the threadpool. Default: -1 == number of cores minus one, to make sure the MainThread has at least one core to run on. (quadcore == 1 core Mainthread, 3 cores used by the ThreadPoolScheduler)
226 | /// If Null, a new ThreadPoolScheduler will be instantiated.
227 | /// Executes all the computations within try-catch events, logging it the message + stacktrace
228 | /// A ThreadPoolScheduler that handles all the repackaged workLoad-Objects
229 | public static ThreadPoolScheduler StartMultithreadedWorkerObjects(IThreadWorkerObject[] workerObjects, ThreadPoolSchedulerEvent onCompleteCallBack, ThreadedWorkCompleteEvent onPackageExecuted = null, int maxThreads = -1, ThreadPoolScheduler scheduler = null, bool safeMode = true)
230 | {
231 | if (scheduler == null)
232 | scheduler = CreateThreadPoolScheduler();
233 |
234 | scheduler.StartASyncThreads(workerObjects, onCompleteCallBack, onPackageExecuted, maxThreads, safeMode);
235 | return scheduler;
236 | }
237 |
238 |
239 |
240 | ///
241 | /// Creates an ThreadPoolScheduler instance, which happens to be a Monobehaviour and therefore will showup as gameobject "ThreadPoolScheduler";
242 | ///
243 | ///
244 | public static ThreadPoolScheduler CreateThreadPoolScheduler()
245 | {
246 | GameObject go = new GameObject("ThreadPoolScheduler");
247 | return go.AddComponent();
248 | }
249 |
250 |
251 | ///
252 | /// Creates an ThreadPoolScheduler instance, which happens to be a Monobehaviour and therefore will showup by the name you provide (default: "ThreadPoolScheduler");
253 | ///
254 | ///
255 | public static ThreadPoolScheduler CreateThreadPoolScheduler(string name)
256 | {
257 | GameObject go = new GameObject(name == null || name == string.Empty ? "ThreadPoolScheduler" : name);
258 | return go.AddComponent();
259 | }
260 |
261 |
262 | #endregion
263 |
264 | //--------------------------------------- THREAD POOL SCHEDULER --------------------------------------
265 | //--------------------------------------- THREAD POOL SCHEDULER --------------------------------------
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 | //--------------------------------------- THREAD WAIT COMMANDS --------------------------------------
282 | //--------------------------------------- THREAD WAIT COMMANDS --------------------------------------
283 |
284 | #region THREAD WAIT COMMANDS
285 |
286 | ///
287 | /// Halts/Sleeps the current thread until Unity has rendered a frame. This can be used Coroutine-wise and is safe to be placed within an endless while-loop. Not recommended though...
288 | /// If fired from the MainThread, an error-log will be thrown because its not allowed to freeze the MainThread.
289 | ///
290 | /// By default set to 1. You can let the Thread wait several frames if needed
291 | public static void WaitForNextFrame(int waitFrames = 1)
292 | {
293 | new ThreadWaitForNextFrame(waitFrames);
294 | }
295 |
296 |
297 | ///
298 | /// Halts/Sleeps the current thread until "seconds" has expired. This can be used Coroutine-wise and is safe to be placed within an endless while-loop. Not recommended though...
299 | /// If fired from the MainThread, an error-log will be thrown because its not allowed to freeze the MainThread.
300 | ///
301 | /// Amount of time you want the Thread to sleep.
302 | public static void WaitForSeconds(float seconds)
303 | {
304 | new ThreadWaitForSeconds(seconds);
305 | }
306 |
307 | #endregion
308 |
309 | //--------------------------------------- THREAD WAIT COMMANDS --------------------------------------
310 | //--------------------------------------- THREAD WAIT COMMANDS --------------------------------------
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 | //--------------------------------------- 4 DISPATCHER OVERLOADS --------------------------------------
326 | //--------------------------------------- 4 DISPATCHER OVERLOADS --------------------------------------
327 |
328 | #region 4 DISPATCHER OVERLOADS
329 |
330 |
331 |
332 | ///
333 | /// Fire and forget: The MainThread will execute this method witout any arguments to pass, nothing will be returned.
334 | ///
335 | /// Example: "() => Debug.Log("This will be fired from the MainThread: " + System.Threading.Thread.CurrentThread.Name)"
336 | /// Freezes the thread, waiting for the MainThread to execute & finish the "dispatchCall".
337 | /// Executes all the computations within try-catch events, logging it the message + stacktrace
338 | public static void DispatchToMainThread(ThreadDispatchDelegate dispatchCall, bool waitForExecution = false, bool safeMode = true)
339 | {
340 | MainThreadDispatcher.DispatchToMainThread(dispatchCall, waitForExecution, safeMode);
341 | }
342 |
343 |
344 |
345 |
346 | ///
347 | /// When executed by the MainThread, this argument will be passed to the "dispatchCall";
348 | ///
349 | /// Example: "(object obj) => Debug.Log("This will be fired from the MainThread: " + System.Threading.Thread.CurrentThread.Name + "\nObject: " + obj.toString())"
350 | /// Once the MainThread executes this action, the argument will be passed to the delegate
351 | /// Freezes the thread, waiting for the MainThread to execute & finish the "dispatchCall".
352 | /// Executes all the computations within try-catch events, logging it the message + stacktrace
353 | public static void DispatchToMainThread(ThreadDispatchDelegateArg dispatchCall, object dispatchArgument, bool waitForExecution = false, bool safeMode = true)
354 | {
355 | MainThreadDispatcher.DispatchToMainThread(dispatchCall, dispatchArgument, waitForExecution, safeMode);
356 | }
357 |
358 |
359 |
360 |
361 | ///
362 | /// When executed by the MainThread, this argument will be passed to the "dispatchCall";
363 | /// Allows you to dispatch an delegate returning an object (for example: a newly instantiated gameobject) that is directly available in your ThreadPool-Thread.
364 | /// Because the thread you are dispatching from is not the MainThread, your ThreadPool-thread needs to wait till the MainThread executed the method, and the returned value can be used directly
365 | ///
366 | /// Example: "(object obj) => Debug.Log("This will be fired from the MainThread: " + System.Threading.Thread.CurrentThread.Name + "\nObject: " + obj.toString())"
367 | /// Once the MainThread executes this action, the argument will be passed to the delegate
368 | /// Executes all the computations within try-catch events, logging it the message + stacktrace
369 | /// After the MainThread has executed the "dispatchCall" (and the worker-thread has been waiting), it will return whatever the dispatchCall returns to the worker-thread
370 | public static object DispatchToMainThreadReturn(ThreadDispatchDelegateArgReturn dispatchCall, object dispatchArgument, bool safeMode = true)
371 | {
372 | return MainThreadDispatcher.DispatchToMainThreadReturn(dispatchCall, dispatchArgument, safeMode);
373 | }
374 |
375 |
376 | ///
377 | /// Allows you to dispatch an delegate returning an object (for example: a newly instantiated gameobject) that is directly available in your ThreadPool-Thread.
378 | /// Because the thread you are dispatching from is not the MainThread, your ThreadPool-thread needs to wait till the MainThread executed the method, and the returned value can be used directly
379 | ///
380 | /// Example: "(object obj) => Debug.Log("This will be fired from the MainThread: " + System.Threading.Thread.CurrentThread.Name + "\nObject: " + obj.toString())"
381 | /// Executes all the computations within try-catch events, logging it the message + stacktrace
382 | /// After the MainThread has executed the "dispatchCall" (and the worker-thread has been waiting), it will return whatever the dispatchCall returns to the worker-thread
383 | public static object DispatchToMainThreadReturn(ThreadDispatchDelegateReturn dispatchCall, bool safeMode = true)
384 | {
385 | return MainThreadDispatcher.DispatchToMainThreadReturn(dispatchCall, safeMode);
386 | }
387 |
388 |
389 | #endregion
390 |
391 | //--------------------------------------- 4 DISPATCHER OVERLOADS --------------------------------------
392 | //--------------------------------------- 4 DISPATCHER OVERLOADS --------------------------------------
393 |
394 |
395 |
396 |
397 |
398 |
399 |
400 |
401 | //--------------------------------------- CHECK UNITY ACTIVITY --------------------------------------
402 | //--------------------------------------- CHECK UNITY ACTIVITY --------------------------------------
403 | #region CHECK UNITY ACTIVITY
404 |
405 | ///
406 | /// A easy way to check if Unity is still running, focused and not pauzed.
407 | /// This comes in handy if threads keep running heavy workloads on seperate threads while IOS for example tries to puch the Application to the background.
408 | /// If you are executing a giant routine on a seperate thread that takes several seconds per cycle, you might want to check regularly if unity is still active by using this check.
409 | ///
410 | /// Returns TRUE if Unity is still running, not pauzed and has focus.
411 | public static bool CheckUnityActive()
412 | {
413 | return UnityActivityWatchdog.CheckUnityActive();
414 | }
415 |
416 |
417 |
418 |
419 | ///
420 | /// !IMPORTANT! This method should be called regularly within routines that take more then half a second to complete, to make sure IOS for example is able to force an application to sleep when it looses focus or gets puched to the background.
421 | /// This is a very light-weight check, internally it only needs to check two static booleans once everything is Initialized and running.
422 | /// You can use this without causing any serious overhead.
423 | /// Motivation: Sins Threads cannot be put asleep from the outside, it needs the be managed from within the thread itself, thats why this method was build.
424 | ///
425 | /// Example:
426 | /// for(int i = 0; i < 999999999; i++)
427 | /// {
428 | /// Loom.SleepOrAbortIfUnityInactive(); //Prevents IOS for example of killing this app because the threads won't sleep once your unity-app is puched to the background.
429 | /// //Do something heavy that will cause this routine to run more then 0.5 seconds.
430 | /// }
431 | ///
432 | public static void SleepOrAbortIfUnityInactive()
433 | {
434 | UnityActivityWatchdog.SleepOrAbortIfUnityInactive();
435 | }
436 | #endregion
437 | //--------------------------------------- CHECK UNITY ACTIVITY --------------------------------------
438 | //--------------------------------------- CHECK UNITY ACTIVITY --------------------------------------
439 |
440 |
441 |
442 |
443 |
444 |
445 |
446 |
447 |
448 |
449 | //--------------------------------------- MAIN THREAD WATCHDOG --------------------------------------
450 | //--------------------------------------- MAIN THREAD WATCHDOG --------------------------------------
451 | #region MAIN THREAD WATCHDOG
452 |
453 | ///
454 | /// If you need your current code to be running on the MainThread, you can always call this method to check if its the MainThread or not...
455 | ///
456 | /// Returns TRUE if its the MainThread
457 | public static bool CheckIfMainThread()
458 | {
459 | return MainThreadWatchdog.CheckIfMainThread();
460 | }
461 |
462 |
463 | #endregion
464 | //--------------------------------------- MAIN THREAD WATCHDOG --------------------------------------
465 | //--------------------------------------- MAIN THREAD WATCHDOG --------------------------------------
466 |
467 | }
--------------------------------------------------------------------------------
/Assets/LOOM Framework/LOOM/Loom.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 09415fb5e1c39ea4fa09211559d64bd7
3 | MonoImporter:
4 | serializedVersion: 2
5 | defaultReferences: []
6 | executionOrder: 0
7 | icon: {instanceID: 0}
8 | userData:
9 | assetBundleName:
10 | assetBundleVariant:
11 |
--------------------------------------------------------------------------------
/Assets/LOOM Framework/LOOM/ThreadPoolScheduler.cs:
--------------------------------------------------------------------------------
1 |
2 |
3 | using System;
4 | using System.Collections;
5 | using System.Threading;
6 | using System.Collections.Generic;
7 | using UnityEngine;
8 | using Frankfort.Threading.Internal;
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | namespace Frankfort.Threading
19 | {
20 | public delegate void ThreadPoolSchedulerEvent(IThreadWorkerObject[] finishedObjects);
21 | public delegate void ThreadedWorkCompleteEvent(IThreadWorkerObject finishedObject);
22 |
23 |
24 | ///
25 | /// This is the most important class of the framework. It starts & stops threads, caps the amount of threads running at the same time, handles Mainthread completion-delegates, etc.
26 | ///
27 | public class ThreadPoolScheduler : MonoBehaviour
28 | {
29 |
30 | //--------------- public Session Variables --------------------
31 | public bool DebugMode = false;
32 | public bool ForceToMainThread = false;
33 | public float WaitForSecondsTime = 0.001f; //Wait 1 ms per tick!
34 |
35 | public bool isBusy
36 | {
37 | get
38 | {
39 | return _shedularBusy;
40 | }
41 | }
42 |
43 | public float Progress
44 | {
45 | get
46 | {
47 | if (workData == null || workData.workerPackages == null || workData.workerPackages.Length == 0)
48 | return 1f;
49 |
50 | //return (float)GetHandledFinishedPackages().Length / (float)workData.workerPackages.Length;
51 | int finishedPackages = 0;
52 | int i = workData.workerPackages.Length;
53 | while(--i > -1)
54 | {
55 | if (workData.workerPackages[i].finishedWorking)
56 | finishedPackages++;
57 | }
58 |
59 | return (float)finishedPackages / (float)workData.workerPackages.Length;
60 | }
61 | }
62 | //--------------- public Session Variables --------------------
63 |
64 |
65 |
66 |
67 | //--------------- PrivateSession Variables --------------------
68 | private bool _providerThreadBusy;
69 | private bool _shedularBusy;
70 | private bool _isAborted;
71 | private ASyncThreadWorkData workData;
72 | private Thread providerThread;
73 | private int workObjectIndex;
74 | private ThreadPoolSchedulerEvent onCompleteCallBack;
75 | private ThreadedWorkCompleteEvent onWorkerObjectDoneCallBack;
76 | private bool safeMode;
77 | //--------------- Private Session Variables --------------------
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 | //--------------------------------------- UNITY MONOBEHAVIOUR COMMANDS --------------------------------------
87 | //--------------------------------------- UNITY MONOBEHAVIOUR COMMANDS --------------------------------------
88 | #region UNITY MONOBEHAVIOUR COMMANDS
89 |
90 | protected virtual void Awake()
91 | {
92 | MainThreadWatchdog.Init();
93 | MainThreadDispatcher.Init();
94 | UnityActivityWatchdog.Init();
95 | }
96 |
97 | protected virtual void OnApplicationQuit()
98 | {
99 | Debug.Log("ThreadPoolScheduler.OnApplicationQuit!");
100 | AbortASyncThreads(false);
101 | }
102 |
103 | protected virtual void OnDestroy()
104 | {
105 | Debug.Log("ThreadPoolScheduler.OnDestroy!");
106 | AbortASyncThreads(false);
107 |
108 | if (providerThread != null && providerThread.IsAlive)
109 | providerThread.Abort();
110 | }
111 | #endregion
112 | //--------------------------------------- UNITY MONOBEHAVIOUR COMMANDS --------------------------------------
113 | //--------------------------------------- UNITY MONOBEHAVIOUR COMMANDS --------------------------------------
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 | //--------------------------------------- UNITY COROUTINE & PROVIDER-THREAD IMPLEMENTATION --------------------------------------
128 | //--------------------------------------- UNITY COROUTINE & PROVIDER-THREAD IMPLEMENTATION --------------------------------------
129 | #region UNITY COROUTINE & PROVIDER-THREAD IMPLEMENTATION
130 |
131 | ///
132 | /// Unlike "StartMultithreadedWorkloadExecution", you will have to build your own IThreadWorkerObject.
133 | /// Downside: It requires some extra work. Upside: you got more controll over what goes in and comes out
134 | /// Infact: You can create you own polymorphed IThreadWorkerObject-array, each ellement being a completely different type. For example: the statemachines of enemies are IThreadWorkerObject's and the array contains completely different classes with enemies/AI-behaviours.
135 | ///
136 | /// An array of IThreadWorkerObject objects to be handled by the threads. If you want multiple cores/threads to be active, make sure that the number of IThreadWorkerObject's proves matches/exeeds your preferred number maxWorkingThreads.
137 | /// Fired when all re-packaged workLoad-objects are finished computing
138 | /// Fires foreach finished re-packaged set of workLoad-object
139 | /// Lets you choose how many threads will be run simultaneously by the threadpool. Default: -1 == number of cores minus one, to make sure the MainThread has at least one core to run on. (quadcore == 1 core Mainthread, 3 cores used by the ThreadPoolScheduler)
140 | /// If Null, a new ThreadPoolScheduler will be instantiated.
141 | /// Executes all the computations within try-catch events, logging it the message + stacktrace
142 | public void StartASyncThreads(IThreadWorkerObject[] workerObjects, ThreadPoolSchedulerEvent onCompleteCallBack, ThreadedWorkCompleteEvent onPackageExecuted = null, int maxThreads = -1, bool safeMode = true)
143 | {
144 | if (_shedularBusy)
145 | {
146 | Debug.LogError("You are trying the start a new ASync threading-process, but is still Busy!");
147 | return;
148 | }
149 |
150 | if (workerObjects == null || workerObjects.Length == 0)
151 | {
152 | Debug.LogError("Please provide an Array with atleast \"IThreadWorkerObject\"-object!");
153 | return;
154 | }
155 |
156 | _isAborted = false;
157 | _shedularBusy = true;
158 | _providerThreadBusy = true;
159 | this.onCompleteCallBack = onCompleteCallBack;
160 | this.onWorkerObjectDoneCallBack = onPackageExecuted;
161 |
162 | if (!ForceToMainThread)
163 | {
164 | //--------------- Start Waiting for the Provider-thread to complete --------------------
165 | StartCoroutine("WaitForCompletion");
166 | workData = new ASyncThreadWorkData(workerObjects, safeMode, maxThreads);
167 | providerThread = new Thread(new ThreadStart(InvokeASyncThreadPoolWork));
168 | providerThread.Start();
169 | //--------------- Start Waiting for the Provider-thread to complete --------------------
170 | }
171 | else
172 | {
173 | //--------------- Execute all work in one bunch! --------------------
174 | StartCoroutine(WaitAndExecuteWorkerObjects(workerObjects));
175 | //--------------- Execute all work in one bunch! --------------------
176 | }
177 | }
178 |
179 |
180 |
181 |
182 | private IEnumerator WaitAndExecuteWorkerObjects(IThreadWorkerObject[] workerObjects)
183 | {
184 | yield return new WaitForEndOfFrame();
185 | for (int i = 0; i < workerObjects.Length; i++)
186 | {
187 | workerObjects[i].ExecuteThreadedWork();
188 |
189 | if (onWorkerObjectDoneCallBack != null)
190 | onWorkerObjectDoneCallBack(workerObjects[i]);
191 | }
192 |
193 | _shedularBusy = false;
194 | _providerThreadBusy = false;
195 |
196 | if (onCompleteCallBack != null)
197 | onCompleteCallBack(workerObjects);
198 | }
199 |
200 |
201 |
202 |
203 | private IEnumerator WaitForCompletion()
204 | {
205 | if (DebugMode)
206 | Debug.Log(" ----- WaitForCompletion: " + Thread.CurrentThread.ManagedThreadId);
207 |
208 | while (true)
209 | {
210 | //After waiting a while, in the meantime it might have finished itself, or got aborted!
211 | yield return new WaitForSeconds(WaitForSecondsTime);
212 | if (_isAborted)
213 | break;
214 |
215 | //--------------- fire events while still working --------------------
216 | int finishedObjectsCount = GetFinishedPackagesCount();
217 | if (finishedObjectsCount == workData.workerPackages.Length)
218 | break;
219 |
220 | int unhandledPackagesCount = GetUnhandledFinishedPackagesCount();
221 | if (DebugMode)
222 | Debug.Log(" ----- unhandledPackages: " + unhandledPackagesCount + " ( out of: " + finishedObjectsCount + " completed so far...)");
223 |
224 | if (unhandledPackagesCount > 0)
225 | {
226 | foreach (ThreadWorkStatePackage package in workData.workerPackages)
227 | {
228 | if (package.finishedWorking && !package.eventFired)
229 | {
230 | if (onWorkerObjectDoneCallBack != null)
231 | onWorkerObjectDoneCallBack(package.workerObject);
232 |
233 | package.eventFired = true;
234 | }
235 | }
236 | }
237 | //--------------- fire events while still working --------------------
238 | }
239 |
240 | if (DebugMode)
241 | Debug.Log(" ----- Coroutine knows its done!");
242 |
243 | IThreadWorkerObject[] workedObjects = GetWorkerObjectsFromPackages();
244 |
245 | workData.Dispose();
246 | workData = null;
247 | _shedularBusy = false;
248 |
249 | if (onCompleteCallBack != null)
250 | onCompleteCallBack(workedObjects);
251 | }
252 |
253 | #endregion
254 | //--------------------------------------- UNITY COROUTINE & PROVIDER-THREAD IMPLEMENTATION --------------------------------------
255 | //--------------------------------------- UNITY COROUTINE & PROVIDER-THREAD IMPLEMENTATION --------------------------------------
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 | //--------------------------------------- EXTRA COMMANDS & ACTIONS --------------------------------------
268 | //--------------------------------------- EXTRA COMMANDS & ACTIONS --------------------------------------
269 | #region EXTRA COMMANDS & ACTIONS
270 |
271 | ///
272 | /// Aborts all worker processes currently queued.
273 | ///
274 | /// if true: Makes sure that after invoking "AbortASyncThreads" the ThreadPoolSheduler is available again, but halts the MainThread while waiting for the other threads to finish
275 | public void AbortASyncThreads(bool sleepTillAborted = false)
276 | {
277 | if (!_providerThreadBusy)
278 | return;
279 |
280 | _isAborted = true;
281 | StopCoroutine("WaitForCompletion");
282 |
283 | if(workData != null && workData.workerPackages != null)
284 | {
285 | lock (workData.workerPackages)
286 | {
287 | foreach (ThreadWorkStatePackage package in workData.workerPackages)
288 | {
289 | if (package.running && !package.finishedWorking)
290 | package.workerObject.AbortThreadedWork();
291 | }
292 | }
293 |
294 | //At this point in code, _isBusy should be set to FALSE, by the providerThread;
295 | if (sleepTillAborted && isBusy)
296 | {
297 | while (_providerThreadBusy)
298 | Thread.Sleep(1);
299 | }
300 | }
301 |
302 | workData = null;
303 | }
304 |
305 | #endregion
306 | //--------------------------------------- EXTRA COMMANDS & ACTIONS --------------------------------------
307 | //--------------------------------------- EXTRA COMMANDS & ACTIONS --------------------------------------
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 | //--------------------------------------- .NET THREADPOOL IMPLEMENTATION --------------------------------------
320 | //--------------------------------------- .NET THREADPOOL IMPLEMENTATION --------------------------------------
321 | #region .NET THREADPOOL IMPLEMENTATION
322 |
323 | ///
324 | /// This method is the work-provider-method. It makes sure the .NET threadpool has things to do...
325 | /// This method is NOT invoked by the mainThread, therefor is safe to use WaitHandle.WaitAll / WaitAny without halting Unity's gameThread!
326 | ///
327 | public void InvokeASyncThreadPoolWork()
328 | {
329 | UnityActivityWatchdog.SleepOrAbortIfUnityInactive();
330 |
331 | int totalWork = workData.workerPackages.Length;
332 | int startBurst = Mathf.Clamp(workData.maxWorkingThreads, 1, totalWork);
333 |
334 | if (DebugMode)
335 | Debug.Log(" ----- InvokeASyncThreadPoolWork. startBurst: " + startBurst + ", totalWork: " + totalWork);
336 |
337 | //--------------- Initial Startup burst --------------------
338 | for (int i = 0; i < startBurst && !_isAborted; i++)
339 | {
340 | //Add to .NET ThreadPool
341 | if (workData.workerPackages[i] != null)
342 | {
343 | workData.workerPackages[i].started = true;
344 | ThreadPool.QueueUserWorkItem(workData.workerPackages[i].ExecuteThreadWork, i);
345 | }
346 | }
347 | //--------------- Initial Startup burst ---------------s-----
348 |
349 |
350 | if (DebugMode)
351 | Debug.Log(" ----- Burst with WorkerObjects being processed!");
352 |
353 | //--------------- Create a new Thread to keep the Threadpool running & cores saturated! --------------------
354 | workObjectIndex = startBurst; //at this point the amount of running WorkObjects/Threads is equal to the startBurst;
355 | while (workObjectIndex < totalWork && !_isAborted)
356 | {
357 | UnityActivityWatchdog.SleepOrAbortIfUnityInactive();
358 |
359 | AutoResetEvent[] startedEvents = GetStartedPackageEvents();
360 | if (startedEvents.Length > 0)
361 | WaitHandle.WaitAny(startedEvents);
362 |
363 | workData.workerPackages[workObjectIndex].started = true;
364 | ThreadPool.QueueUserWorkItem(workData.workerPackages[workObjectIndex].ExecuteThreadWork, workObjectIndex);
365 | workObjectIndex++;
366 | }
367 | //--------------- Create a new Thread to keep the Threadpool running & cores saturated! --------------------
368 |
369 |
370 | if (DebugMode)
371 | Debug.Log(" ----- all packages fed to the pool!");
372 |
373 | //--------------- Wait till all are finished! --------------------
374 | //All WorkObjects have been set to work, but the last few Threads might still be pending!
375 | AutoResetEvent[] pendingEvents = GetStartedPackageEvents();
376 | if (pendingEvents.Length > 0)
377 | {
378 | UnityActivityWatchdog.SleepOrAbortIfUnityInactive();
379 | WaitHandle.WaitAll(pendingEvents);
380 | }
381 | //--------------- Wait till all are finished! --------------------
382 |
383 |
384 | if (DebugMode)
385 | Debug.Log(" ----- PROVIDER THREAD DONE");
386 |
387 | //DONE!
388 | _providerThreadBusy = false;
389 | }
390 |
391 | #endregion
392 | //--------------------------------------- .NET THREADPOOL IMPLEMENTATION --------------------------------------
393 | //--------------------------------------- .NET THREADPOOL IMPLEMENTATION --------------------------------------
394 |
395 |
396 |
397 |
398 |
399 |
400 |
401 |
402 |
403 |
404 |
405 |
406 |
407 | //--------------------------------------- MISC --------------------------------------
408 | //--------------------------------------- MISC --------------------------------------
409 | #region MISC
410 |
411 | private AutoResetEvent[] GetStartedPackageEvents()
412 | {
413 | List result = new List();
414 | for (int i = 0; i < workData.workerPackages.Length; i++)
415 | {
416 | ThreadWorkStatePackage package = workData.workerPackages[i];
417 | if(package.started && !package.finishedWorking)
418 | result.Add(package.waitHandle);
419 | }
420 | return result.ToArray();
421 | }
422 |
423 |
424 | private IThreadWorkerObject[] GetWorkerObjectsFromPackages()
425 | {
426 | if (workData == null || workData.workerPackages == null)
427 | return new IThreadWorkerObject[0];
428 |
429 | IThreadWorkerObject[] result = new IThreadWorkerObject[workData.workerPackages.Length];
430 | int i = workData.workerPackages.Length;
431 | while (--i > -1)
432 | result[i] = workData.workerPackages[i].workerObject;
433 |
434 | return result;
435 | }
436 |
437 | public int GetFinishedPackagesCount()
438 | {
439 | if (workData == null || workData.workerPackages == null)
440 | return 0;
441 |
442 | int count = 0;
443 | int i = workData.workerPackages.Length;
444 | while (--i > -1)
445 | {
446 | if (workData.workerPackages[i].finishedWorking)
447 | count++;
448 | }
449 | return count;
450 | }
451 |
452 | public int GetUnhandledFinishedPackagesCount()
453 | {
454 | if (workData == null || workData.workerPackages == null)
455 | return 0;
456 |
457 | int count = 0;
458 | int i = workData.workerPackages.Length;
459 | while (--i > -1)
460 | {
461 | if (workData.workerPackages[i].finishedWorking && !workData.workerPackages[i].eventFired)
462 | count++;
463 | }
464 | return count;
465 | }
466 |
467 | #endregion
468 | //--------------------------------------- MISC --------------------------------------
469 | //--------------------------------------- MISC --------------------------------------
470 |
471 |
472 | }
473 | }
--------------------------------------------------------------------------------
/Assets/LOOM Framework/LOOM/ThreadPoolScheduler.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: e1034b8fef65f454f91a663a126ba33a
3 | MonoImporter:
4 | serializedVersion: 2
5 | defaultReferences: []
6 | executionOrder: 0
7 | icon: {instanceID: 0}
8 | userData:
9 | assetBundleName:
10 | assetBundleVariant:
11 |
--------------------------------------------------------------------------------
/LOOM - Multi Threading Framework16.unitypackage:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/superowner/LOOM-Multi-Threading-Framework/56a811efcc3e135782559424e51392c69de8fb2f/LOOM - Multi Threading Framework16.unitypackage
--------------------------------------------------------------------------------
/LOOM-Multi-Threading-Framework.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | AnyCPU
6 | 10.0.20506
7 | 2.0
8 | {68004739-CEDE-0F70-A436-F1A2003B06A1}
9 | Library
10 | Assembly-CSharp
11 | 512
12 | {E097FAD1-6243-4DAD-9C02-E9B9EFC3FFC1};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
13 | .NETFramework
14 | v4.5.2
15 |
16 |
17 |
18 |
19 | Game:1
20 | Android:13
21 | 5.3.4f1
22 |
23 |
24 | 4
25 |
26 |
27 | pdbonly
28 | false
29 | Temp\UnityVS_bin\Debug\
30 | Temp\UnityVS_obj\Debug\
31 | prompt
32 | 4
33 | DEBUG;TRACE;UNITY_5_3_OR_NEWER;UNITY_5_3_4;UNITY_5_3;UNITY_5;ENABLE_NEW_BUGREPORTER;ENABLE_AUDIO;ENABLE_CACHING;ENABLE_CLOTH;ENABLE_FRAME_DEBUGGER;ENABLE_GENERICS;ENABLE_HOME_SCREEN;ENABLE_IMAGEEFFECTS;ENABLE_LIGHT_PROBES_LEGACY;ENABLE_MICROPHONE;ENABLE_MULTIPLE_DISPLAYS;ENABLE_PHYSICS;ENABLE_PLUGIN_INSPECTOR;ENABLE_SHADOWS;ENABLE_SINGLE_INSTANCE_BUILD_SETTING;ENABLE_SPRITERENDERER_FLIPPING;ENABLE_SPRITES;ENABLE_SPRITE_POLYGON;ENABLE_TERRAIN;ENABLE_RAKNET;ENABLE_UNET;ENABLE_UNITYEVENTS;ENABLE_VR;ENABLE_WEBCAM;ENABLE_WWW;ENABLE_CLOUD_SERVICES;ENABLE_CLOUD_SERVICES_ADS;ENABLE_CLOUD_HUB;ENABLE_CLOUD_PROJECT_ID;ENABLE_CLOUD_SERVICES_PURCHASING;ENABLE_CLOUD_SERVICES_ANALYTICS;ENABLE_CLOUD_SERVICES_UNET;ENABLE_CLOUD_SERVICES_BUILD;ENABLE_CLOUD_LICENSE;ENABLE_EDITOR_METRICS;ENABLE_EDITOR_METRICS_CACHING;INCLUDE_DYNAMIC_GI;INCLUDE_GI;INCLUDE_IL2CPP;INCLUDE_DIRECTX12;PLATFORM_SUPPORTS_MONO;ENABLE_LOCALIZATION;ENABLE_ANDROID_ATLAS_ETC1_COMPRESSION;ENABLE_EDITOR_TESTS_RUNNER;UNITY_ANDROID;UNITY_ANDROID_API;ENABLE_SUBSTANCE;UNITY_ANDROID_API;ENABLE_TEXTUREID_MAP;ENABLE_EGL;ENABLE_NETWORK;ENABLE_RUNTIME_GI;ENABLE_CRUNCH_TEXTURE_COMPRESSION;ENABLE_LOG_MIXED_STACKTRACE;ENABLE_UNITYWEBREQUEST;PLATFORM_SUPPORTS_ADS_ID;ENABLE_UNITYADS_RUNTIME;UNITY_UNITYADS_API;ENABLE_MONO;ENABLE_PROFILER;DEBUG;TRACE;UNITY_ASSERTIONS;UNITY_EDITOR;UNITY_EDITOR_64;UNITY_EDITOR_WIN;UNITY_TEAM_LICENSE;UNITY_PRO_LICENSE
34 | false
35 | false
36 |
37 |
38 | pdbonly
39 | false
40 | Temp\UnityVS_bin\Release\
41 | Temp\UnityVS_obj\Release\
42 | prompt
43 | 4
44 | TRACE;UNITY_5_3_OR_NEWER;UNITY_5_3_4;UNITY_5_3;UNITY_5;ENABLE_NEW_BUGREPORTER;ENABLE_AUDIO;ENABLE_CACHING;ENABLE_CLOTH;ENABLE_FRAME_DEBUGGER;ENABLE_GENERICS;ENABLE_HOME_SCREEN;ENABLE_IMAGEEFFECTS;ENABLE_LIGHT_PROBES_LEGACY;ENABLE_MICROPHONE;ENABLE_MULTIPLE_DISPLAYS;ENABLE_PHYSICS;ENABLE_PLUGIN_INSPECTOR;ENABLE_SHADOWS;ENABLE_SINGLE_INSTANCE_BUILD_SETTING;ENABLE_SPRITERENDERER_FLIPPING;ENABLE_SPRITES;ENABLE_SPRITE_POLYGON;ENABLE_TERRAIN;ENABLE_RAKNET;ENABLE_UNET;ENABLE_UNITYEVENTS;ENABLE_VR;ENABLE_WEBCAM;ENABLE_WWW;ENABLE_CLOUD_SERVICES;ENABLE_CLOUD_SERVICES_ADS;ENABLE_CLOUD_HUB;ENABLE_CLOUD_PROJECT_ID;ENABLE_CLOUD_SERVICES_PURCHASING;ENABLE_CLOUD_SERVICES_ANALYTICS;ENABLE_CLOUD_SERVICES_UNET;ENABLE_CLOUD_SERVICES_BUILD;ENABLE_CLOUD_LICENSE;ENABLE_EDITOR_METRICS;ENABLE_EDITOR_METRICS_CACHING;INCLUDE_DYNAMIC_GI;INCLUDE_GI;INCLUDE_IL2CPP;INCLUDE_DIRECTX12;PLATFORM_SUPPORTS_MONO;ENABLE_LOCALIZATION;ENABLE_ANDROID_ATLAS_ETC1_COMPRESSION;ENABLE_EDITOR_TESTS_RUNNER;UNITY_ANDROID;UNITY_ANDROID_API;ENABLE_SUBSTANCE;UNITY_ANDROID_API;ENABLE_TEXTUREID_MAP;ENABLE_EGL;ENABLE_NETWORK;ENABLE_RUNTIME_GI;ENABLE_CRUNCH_TEXTURE_COMPRESSION;ENABLE_LOG_MIXED_STACKTRACE;ENABLE_UNITYWEBREQUEST;PLATFORM_SUPPORTS_ADS_ID;ENABLE_UNITYADS_RUNTIME;UNITY_UNITYADS_API;ENABLE_MONO;ENABLE_PROFILER;DEBUG;TRACE;UNITY_ASSERTIONS;UNITY_EDITOR;UNITY_EDITOR_64;UNITY_EDITOR_WIN;UNITY_TEAM_LICENSE;UNITY_PRO_LICENSE
45 | false
46 | false
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 | Library\UnityAssemblies\UnityEngine.dll
59 |
60 |
61 | Library\UnityAssemblies\UnityEngine.UI.dll
62 |
63 |
64 | Library\UnityAssemblies\UnityEngine.Networking.dll
65 |
66 |
67 | Library\UnityAssemblies\UnityEditor.dll
68 |
69 |
70 | Library\UnityAssemblies\UnityEditor.iOS.Extensions.Xcode.dll
71 |
72 |
73 | Library\UnityAssemblies\UnityEditor.iOS.Extensions.Common.dll
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
--------------------------------------------------------------------------------
/LOOM-Multi-Threading-Framework.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 2015
4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LOOM-Multi-Threading-Framework", "LOOM-Multi-Threading-Framework.csproj", "{68004739-CEDE-0F70-A436-F1A2003B06A1}"
5 | EndProject
6 | Global
7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
8 | Debug|Any CPU = Debug|Any CPU
9 | Release|Any CPU = Release|Any CPU
10 | EndGlobalSection
11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
12 | {68004739-CEDE-0F70-A436-F1A2003B06A1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
13 | {68004739-CEDE-0F70-A436-F1A2003B06A1}.Debug|Any CPU.Build.0 = Debug|Any CPU
14 | {68004739-CEDE-0F70-A436-F1A2003B06A1}.Release|Any CPU.ActiveCfg = Release|Any CPU
15 | {68004739-CEDE-0F70-A436-F1A2003B06A1}.Release|Any CPU.Build.0 = Release|Any CPU
16 | EndGlobalSection
17 | GlobalSection(SolutionProperties) = preSolution
18 | HideSolutionNode = FALSE
19 | EndGlobalSection
20 | EndGlobal
21 |
--------------------------------------------------------------------------------
/ProjectSettings/AudioManager.asset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/superowner/LOOM-Multi-Threading-Framework/56a811efcc3e135782559424e51392c69de8fb2f/ProjectSettings/AudioManager.asset
--------------------------------------------------------------------------------
/ProjectSettings/ClusterInputManager.asset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/superowner/LOOM-Multi-Threading-Framework/56a811efcc3e135782559424e51392c69de8fb2f/ProjectSettings/ClusterInputManager.asset
--------------------------------------------------------------------------------
/ProjectSettings/DynamicsManager.asset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/superowner/LOOM-Multi-Threading-Framework/56a811efcc3e135782559424e51392c69de8fb2f/ProjectSettings/DynamicsManager.asset
--------------------------------------------------------------------------------
/ProjectSettings/EditorBuildSettings.asset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/superowner/LOOM-Multi-Threading-Framework/56a811efcc3e135782559424e51392c69de8fb2f/ProjectSettings/EditorBuildSettings.asset
--------------------------------------------------------------------------------
/ProjectSettings/EditorSettings.asset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/superowner/LOOM-Multi-Threading-Framework/56a811efcc3e135782559424e51392c69de8fb2f/ProjectSettings/EditorSettings.asset
--------------------------------------------------------------------------------
/ProjectSettings/GraphicsSettings.asset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/superowner/LOOM-Multi-Threading-Framework/56a811efcc3e135782559424e51392c69de8fb2f/ProjectSettings/GraphicsSettings.asset
--------------------------------------------------------------------------------
/ProjectSettings/InputManager.asset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/superowner/LOOM-Multi-Threading-Framework/56a811efcc3e135782559424e51392c69de8fb2f/ProjectSettings/InputManager.asset
--------------------------------------------------------------------------------
/ProjectSettings/NavMeshAreas.asset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/superowner/LOOM-Multi-Threading-Framework/56a811efcc3e135782559424e51392c69de8fb2f/ProjectSettings/NavMeshAreas.asset
--------------------------------------------------------------------------------
/ProjectSettings/NetworkManager.asset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/superowner/LOOM-Multi-Threading-Framework/56a811efcc3e135782559424e51392c69de8fb2f/ProjectSettings/NetworkManager.asset
--------------------------------------------------------------------------------
/ProjectSettings/Physics2DSettings.asset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/superowner/LOOM-Multi-Threading-Framework/56a811efcc3e135782559424e51392c69de8fb2f/ProjectSettings/Physics2DSettings.asset
--------------------------------------------------------------------------------
/ProjectSettings/ProjectSettings.asset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/superowner/LOOM-Multi-Threading-Framework/56a811efcc3e135782559424e51392c69de8fb2f/ProjectSettings/ProjectSettings.asset
--------------------------------------------------------------------------------
/ProjectSettings/ProjectVersion.txt:
--------------------------------------------------------------------------------
1 | m_EditorVersion: 5.3.4f1
2 | m_StandardAssetsVersion: 0
3 |
--------------------------------------------------------------------------------
/ProjectSettings/QualitySettings.asset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/superowner/LOOM-Multi-Threading-Framework/56a811efcc3e135782559424e51392c69de8fb2f/ProjectSettings/QualitySettings.asset
--------------------------------------------------------------------------------
/ProjectSettings/TagManager.asset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/superowner/LOOM-Multi-Threading-Framework/56a811efcc3e135782559424e51392c69de8fb2f/ProjectSettings/TagManager.asset
--------------------------------------------------------------------------------
/ProjectSettings/TimeManager.asset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/superowner/LOOM-Multi-Threading-Framework/56a811efcc3e135782559424e51392c69de8fb2f/ProjectSettings/TimeManager.asset
--------------------------------------------------------------------------------
/ProjectSettings/UnityAdsSettings.asset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/superowner/LOOM-Multi-Threading-Framework/56a811efcc3e135782559424e51392c69de8fb2f/ProjectSettings/UnityAdsSettings.asset
--------------------------------------------------------------------------------
/ProjectSettings/UnityConnectSettings.asset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/superowner/LOOM-Multi-Threading-Framework/56a811efcc3e135782559424e51392c69de8fb2f/ProjectSettings/UnityConnectSettings.asset
--------------------------------------------------------------------------------