├── CHANGELOG.md ├── CHANGELOG.md.meta ├── CreateChangeLog.bat ├── CreateChangeLog.bat.meta ├── Documentation~ └── signals-preview-screenshot.png ├── LICENSE ├── LICENSE.meta ├── README.md ├── README.md.meta ├── Samples~ ├── Basic.meta ├── Basic │ ├── BasicSignalExample.unity │ ├── BasicSignalExample.unity.meta │ ├── Scripts.meta │ ├── Scripts │ │ ├── BasicExampleSignal.cs │ │ ├── BasicExampleSignal.cs.meta │ │ ├── BasicExampleSignalTest.cs │ │ ├── BasicExampleSignalTest.cs.meta │ │ ├── CustomSerializedStructSignal.cs │ │ ├── CustomSerializedStructSignal.cs.meta │ │ ├── GameObjectDispatcher.cs │ │ ├── GameObjectDispatcher.cs.meta │ │ ├── GameObjectListener.cs │ │ ├── GameObjectListener.cs.meta │ │ ├── GameObjectSignal.cs │ │ ├── GameObjectSignal.cs.meta │ │ ├── UnusedSignal.cs │ │ └── UnusedSignal.cs.meta │ ├── SignalWithParameter.unity │ └── SignalWithParameter.unity.meta ├── StressTest.meta ├── StressTest │ ├── Scripts.meta │ ├── Scripts │ │ ├── DebugListener.cs │ │ ├── DebugListener.cs.meta │ │ ├── SignalStressTest.cs │ │ ├── SignalStressTest.cs.meta │ │ ├── StressTestSignal.cs │ │ └── StressTestSignal.cs.meta │ ├── StressTest.unity │ └── StressTest.unity.meta ├── UPMExport.meta └── UPMExport │ ├── Editor.meta │ └── Editor │ ├── CopyExamplesFolder.asset │ ├── CopyExamplesFolder.asset.meta │ ├── ExportSignalSamples.asset │ ├── ExportSignalSamples.asset.meta │ ├── ExportSignals.asset │ └── ExportSignals.asset.meta ├── Scripts.meta ├── Scripts ├── Editor.meta ├── Editor │ ├── EditorSignalLog.cs │ ├── EditorSignalLog.cs.meta │ ├── SignalEditorPlayModeHandler.cs │ ├── SignalEditorPlayModeHandler.cs.meta │ ├── SignalListenerViewDrawer.cs │ ├── SignalListenerViewDrawer.cs.meta │ ├── SignalLogViewDrawer.cs │ ├── SignalLogViewDrawer.cs.meta │ ├── SignalReflectionHelper.cs │ ├── SignalReflectionHelper.cs.meta │ ├── SignalsAboutWindow.cs │ ├── SignalsAboutWindow.cs.meta │ ├── SignalsEditorConsoleWindow.cs │ ├── SignalsEditorConsoleWindow.cs.meta │ ├── SignalsEditorDatabase.cs │ ├── SignalsEditorDatabase.cs.meta │ ├── SignalsEditorUtilities.cs │ ├── SignalsEditorUtilities.cs.meta │ ├── SignalsEditorWindow.cs │ ├── SignalsEditorWindow.cs.meta │ ├── SignalsLogTreeView.cs │ ├── SignalsLogTreeView.cs.meta │ ├── SignalsTreeView.cs │ ├── SignalsTreeView.cs.meta │ ├── SignalsTreeViewItem.cs │ ├── SignalsTreeViewItem.cs.meta │ ├── SignalsTreeViewItems.cs │ ├── SignalsTreeViewItems.cs.meta │ ├── Supyrb.Signals.Editor.asmdef │ └── Supyrb.Signals.Editor.asmdef.meta ├── Runtime.meta └── Runtime │ ├── ASignal.cs │ ├── ASignal.cs.meta │ ├── ASignalAction.cs │ ├── ASignalAction.cs.meta │ ├── ISignal.cs │ ├── ISignal.cs.meta │ ├── Logging.meta │ ├── Logging │ ├── Libraries.meta │ ├── Libraries │ │ ├── SerializableDateTime.cs │ │ ├── SerializableDateTime.cs.meta │ │ ├── SerializableSystemType.cs │ │ └── SerializableSystemType.cs.meta │ ├── SignalLog.cs │ ├── SignalLog.cs.meta │ ├── SignalLogEntry.cs │ ├── SignalLogEntry.cs.meta │ ├── Supyrb.Signals.Logging.asmdef │ └── Supyrb.Signals.Logging.asmdef.meta │ ├── OrderedList.cs │ ├── OrderedList.cs.meta │ ├── Signal.cs │ ├── Signal.cs.meta │ ├── Signals.cs │ ├── Signals.cs.meta │ ├── Supyrb.Signals.asmdef │ └── Supyrb.Signals.asmdef.meta ├── Tests.meta ├── Tests ├── NoArgumentSignalTests.cs ├── NoArgumentSignalTests.cs.meta ├── OneArgumentSignalTests.cs ├── OneArgumentSignalTests.cs.meta ├── OrderedListTests.cs ├── OrderedListTests.cs.meta ├── SignalRegistryTests.cs ├── SignalRegistryTests.cs.meta ├── SignalTests.cs ├── SignalTests.cs.meta ├── Signals.meta ├── Signals │ ├── TestSignal.cs │ ├── TestSignal.cs.meta │ ├── TestSignalInt.cs │ ├── TestSignalInt.cs.meta │ ├── TestSignalObjectStringInt.cs │ ├── TestSignalObjectStringInt.cs.meta │ ├── TestSignalStringInt.cs │ └── TestSignalStringInt.cs.meta ├── Supyrb.Signals.Tests.asmdef ├── Supyrb.Signals.Tests.asmdef.meta ├── ThreeArgumentSignalTests.cs ├── ThreeArgumentSignalTests.cs.meta ├── TwoArgumentSignalTests.cs └── TwoArgumentSignalTests.cs.meta ├── package.json └── package.json.meta /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | ## [0.5.0](https://github.com/supyrb/signals/tree/0.5.0) (2020-04-05) 4 | [Full Changelog](https://github.com/supyrb/signals/compare/0.4.3...0.5.0) 5 | 6 | **Implemented enhancements:** 7 | 8 | - Signal log [\#16](https://github.com/supyrb/signals/issues/16) 9 | 10 | **Closed issues:** 11 | 12 | - Reset signal hub in edit mode [\#17](https://github.com/supyrb/signals/issues/17) 13 | 14 | ## [0.4.3](https://github.com/supyrb/signals/tree/0.4.3) (2020-03-10) 15 | [Full Changelog](https://github.com/supyrb/signals/compare/0.4.2...0.4.3) 16 | 17 | ## [0.4.2](https://github.com/supyrb/signals/tree/0.4.2) (2020-03-10) 18 | [Full Changelog](https://github.com/supyrb/signals/compare/0.4.1...0.4.2) 19 | 20 | **Closed issues:** 21 | 22 | - TypeLoadException in Signlas Window with Unity 2019.3 [\#15](https://github.com/supyrb/signals/issues/15) 23 | 24 | ## [0.4.1](https://github.com/supyrb/signals/tree/0.4.1) (2020-03-06) 25 | [Full Changelog](https://github.com/supyrb/signals/compare/0.4.0...0.4.1) 26 | 27 | ## [0.4.0](https://github.com/supyrb/signals/tree/0.4.0) (2020-03-05) 28 | [Full Changelog](https://github.com/supyrb/signals/compare/0.3.1...0.4.0) 29 | 30 | **Implemented enhancements:** 31 | 32 | - Add editor window for easy signal access [\#14](https://github.com/supyrb/signals/issues/14) 33 | 34 | ## [0.3.1](https://github.com/supyrb/signals/tree/0.3.1) (2020-01-29) 35 | [Full Changelog](https://github.com/supyrb/signals/compare/0.3.0...0.3.1) 36 | 37 | **Closed issues:** 38 | 39 | - Remove Test folder from unity packages [\#13](https://github.com/supyrb/signals/issues/13) 40 | 41 | **Merged pull requests:** 42 | 43 | - Fix namespace 'NUnit' not found on version 0.3.0 [\#12](https://github.com/supyrb/signals/pull/12) ([tony707](https://github.com/tony707)) 44 | 45 | ## [0.3.0](https://github.com/supyrb/signals/tree/0.3.0) (2020-01-04) 46 | [Full Changelog](https://github.com/supyrb/signals/compare/0.2.1...0.3.0) 47 | 48 | **Implemented enhancements:** 49 | 50 | - Add test cases [\#7](https://github.com/supyrb/signals/issues/7) 51 | 52 | **Closed issues:** 53 | 54 | - Create minimal abstract base class for signals [\#11](https://github.com/supyrb/signals/issues/11) 55 | - Create test cases for Signals with arguments [\#10](https://github.com/supyrb/signals/issues/10) 56 | 57 | **Merged pull requests:** 58 | 59 | - Fixed error in installation [\#9](https://github.com/supyrb/signals/pull/9) ([AntiGuide](https://github.com/AntiGuide)) 60 | 61 | ## [0.2.1](https://github.com/supyrb/signals/tree/0.2.1) (2019-12-11) 62 | [Full Changelog](https://github.com/supyrb/signals/compare/0.2.0...0.2.1) 63 | 64 | ## [0.2.0](https://github.com/supyrb/signals/tree/0.2.0) (2019-12-03) 65 | [Full Changelog](https://github.com/supyrb/signals/compare/0.1.5...0.2.0) 66 | 67 | ## [0.1.5](https://github.com/supyrb/signals/tree/0.1.5) (2019-12-03) 68 | [Full Changelog](https://github.com/supyrb/signals/compare/0.1.4...0.1.5) 69 | 70 | **Fixed bugs:** 71 | 72 | - Adding and removing Listeners while Signal is dispatching [\#6](https://github.com/supyrb/signals/issues/6) 73 | 74 | ## [0.1.4](https://github.com/supyrb/signals/tree/0.1.4) (2019-12-03) 75 | [Full Changelog](https://github.com/supyrb/signals/compare/0.1.3...0.1.4) 76 | 77 | **Implemented enhancements:** 78 | 79 | - Possibility to clear hub entries [\#5](https://github.com/supyrb/signals/issues/5) 80 | 81 | **Closed issues:** 82 | 83 | - Add code documentation [\#1](https://github.com/supyrb/signals/issues/1) 84 | 85 | ## [0.1.3](https://github.com/supyrb/signals/tree/0.1.3) (2019-11-15) 86 | [Full Changelog](https://github.com/supyrb/signals/compare/0.1.2...0.1.3) 87 | 88 | **Closed issues:** 89 | 90 | - Add example to package [\#4](https://github.com/supyrb/signals/issues/4) 91 | - Changelog generation [\#2](https://github.com/supyrb/signals/issues/2) 92 | 93 | ## [0.1.2](https://github.com/supyrb/signals/tree/0.1.2) (2019-07-19) 94 | [Full Changelog](https://github.com/supyrb/signals/compare/0.1.1...0.1.2) 95 | 96 | ## [0.1.1](https://github.com/supyrb/signals/tree/0.1.1) (2019-07-19) 97 | [Full Changelog](https://github.com/supyrb/signals/compare/0.1.0...0.1.1) 98 | 99 | ## [0.1.0](https://github.com/supyrb/signals/tree/0.1.0) (2019-07-15) 100 | 101 | 102 | \* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)* -------------------------------------------------------------------------------- /CHANGELOG.md.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 912c9923f4c0bab43a51509211d143e5 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /CreateChangeLog.bat: -------------------------------------------------------------------------------- 1 | github_changelog_generator -u supyrb -p signals 2 | PAUSE -------------------------------------------------------------------------------- /CreateChangeLog.bat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: fdc31b48f3456b14ea9a9c84989a72c8 3 | DefaultImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Documentation~/signals-preview-screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/supyrb/signals/0952fbaf61b8f719dd93d33e67a9ad7a88e65762/Documentation~/signals-preview-screenshot.png -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Yanko Oliveira, 2019 by Johannes Deml 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /LICENSE.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c8c780e36f7936f4e8099e84390549b6 3 | DefaultImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Signals ❇ 2 | 3 | ![Signals Editor Window Screenshot](Documentation~/signals-preview-screenshot.png) 4 | 5 | ### A typesafe, lightweight, tested messaging package for Unity. 6 | [![openupm](https://img.shields.io/npm/v/com.supyrb.signals?label=openupm®istry_uri=https://package.openupm.com)](https://openupm.com/packages/com.supyrb.signals/) [![](https://img.shields.io/github/release-date/supyrb/signals.svg)](https://github.com/supyrb/signals/releases) [![Unity 5.6 or later](https://img.shields.io/badge/unity-5.6%20or%20later-blue.svg?logo=unity&cacheSeconds=2592000)](https://unity3d.com/get-unity/download/archive) [![Tested up to Unity 2020.2](https://img.shields.io/badge/tested%20up%20to%20unity-2021.3-green.svg?logo=unity&cacheSeconds=2592000)](https://unity3d.com/get-unity/download/archive) 7 | 8 | ## Installation 9 | 10 | Install the package with [OpenUPM](https://openupm.com/) 11 | 12 | ```sh 13 | $ openupm add com.supyrb.signals 14 | ``` 15 | 16 | or download the [Latest Unity Packages](../../releases/latest) 17 | 18 | ## Features 19 | 20 | * Signal Hub as a global Registry for everyone to access 21 | * Signal with up to three parameters 22 | * Signal Listener Order 23 | * Consuming Signals 24 | * Pausing Signals 25 | 26 | As well as 27 | * An editor window 28 | * A filterable list of all signals in the project 29 | * Dispatch signals with custom parameters 30 | * A signal log for each signal 31 | * List of all subscribed listeners for a signal 32 | * An editor console window 33 | * Similar to Unity's console, just for signals 34 | * Options to clear console on enter playmode, script recompile or after builds 35 | 36 | * Easy integration with UPM 37 | * Unit tests for runtime scripts 38 | * Sample packages to get started fast 39 | * XML comments for all public methods and properties 40 | * GC Free dispatching and very small memory footprint 41 | 42 | ## Usage 43 | 44 | [BasicExample](./Samples~/Basic/Scripts/BasicExampleSignalTest.cs) 45 | 46 | ### Get Signal 47 | 48 | ```c# 49 | BasicExampleSignal exampleSignal; 50 | 51 | // Get the signal by passing its variable 52 | Signals.Get(out exampleSignal); 53 | // or with a generic get 54 | exampleSignal = Signals.Get(); 55 | // or by passing the type 56 | exampleSignal = Signals.Get(typeof(BasicExampleSignal)); 57 | ``` 58 | ### Subscribe to Signal 59 | 60 | ```c# 61 | //if you didn't store the Signal in a variable you can use 62 | Signals.Get().AddListener(DefaultListener); 63 | 64 | // Default subscription with order 0 65 | exampleSignal.AddListener(DefaultListener); 66 | 67 | // Subscribe with an earlier order to be called first 68 | exampleSignal.AddListener(FirstListener, -100); 69 | ``` 70 | ### Unsubscribe to Signal 71 | 72 | ```c# 73 | //if you didn't store the Signal in a variable you can use 74 | Signals.Get().RemoveListener(DefaultListener); 75 | 76 | // Unsubscribe does not care for the listening order 77 | exampleSignal.RemoveListener(DefaultListener); 78 | 79 | ``` 80 | 81 | ### Dispatch Signal 82 | 83 | ```c# 84 | // Send the signal to all listeners (if not consumed or paused in between) 85 | exampleSignal.Dispatch(); 86 | 87 | // If your type has a parameter, is is added in the dispatch method 88 | Signals.Get().Dispatch(gameObject); 89 | ``` 90 | ### Pause & Continue 91 | 92 | ```c# 93 | // No more listeners will be called until the signal is continued 94 | exampleSignal.Pause(); 95 | 96 | // Will continue after the listener that paused the signal 97 | exampleSignal.Continue(); 98 | ``` 99 | If you want to pause the further propagation of a signal (wait for a *user input*/*scene that needs to load*/*network package*) you can easily do that with `signal.Pause()` and `signal.Continue()`. 100 | 101 | ### Consume Signals 102 | 103 | ```c# 104 | // No more listeners will receive this signal 105 | exampleSignal.Consume(); 106 | ``` 107 | Sometimes only one script should handle a signal or the signal should not reach others. Unity for example does this with keystrokes in the editor, you can decide in the script if the [event is used](https://docs.unity3d.com/ScriptReference/Event.Use.html). Similar to that, you can consume signals with `signal.Consume()`. Always be away of the order of your listeners. Listeners with a lower order value are called first and therefore decide before others if they should get the event as well. 108 | 109 | ## Editor Window 110 | 111 | The editor window can be accessed through `Window->Signals->Singals`. On the first start and whenever you added a signal you want to debug, just hit the refresh button in the bottom right corner of the window 112 | 113 | * In the top right corner there is a search field which you can use to filter your signals 114 | * Click on a signal in the list, to see the details of that signal 115 | 116 | ### Detail View 117 | 118 | * You can dispatch, consume, pause and continue the signal. For dispatching you will get the needed fields to enter your custom arguments. Most common types are supported, for non supported types you will see an information. 119 | * The log shows a history of all dispatched of that signal with a timestamp of the real time all well as the game time of that dispatch 120 | * The Listeners list shows all subscribed methods to that signal sorted with their order. Additionally the listeners are colored if the last dispatch is at a certain listener 121 | * Green: The signal is currently running at this listener 122 | * Yellow: The signal was paused at this listener 123 | * Red: The signal was consumed at this listener 124 | 125 | ## Caveats 126 | 127 | * Each signal is only lazily instanced once (nice!). This results in reusing the same signal over and over. While in general this is great, you will have to remember that fact while using the signals. Consider the following case: 128 | Signal A has Listeners 1,2,3 and 4. 129 | Signal A gets dispatched. 130 | 131 | - 1 processes the event 132 | - 2 processes the event and decides to dispatch A again 133 | - 1 processes the event 134 | - 2 processes the event 135 | - 3 processes the event 136 | - 4 processes the event 137 | 138 | In this case 1 and 2 got called two times, but 3 and 4 only one time. This might be wanted, but might also be unexpected. 139 | 140 | * When using the signal editor window, you will get a GC for every signal of 48bytes. This only happens if the window is open and won't happen in the build or if there is no window open. 141 | 142 | 143 | 144 | ## Contribute 145 | 146 | Contributions to the repository are always welcome. There are several ways to contribute: 147 | * [Create an issue](../../issues) for a problem you found or an idea on how to improve the project 148 | * Solve existing issues with PRs 149 | * Write test cases to make sure everything is running the way it is supposed to run 150 | * Create CI actions (e.g. run automated tests, trigger new version creation) 151 | * Refactor / Cleanup code 152 | * Document code functionality 153 | * Write wiki entries 154 | * Improve editor integration of signals 155 | * Post your thoughts in the [Unity Forum](https://forum.unity.com/threads/open-source-signals-a-decoupled-typesafe-messaging-system.803487/) 156 | 157 | ### Code Contribution 158 | 159 | #### Setup 160 | 161 | 1. Create a new Unity Project 162 | 2. Clone git repository in your Assets folder `C:\UnityProject\Assets> git clone https://github.com/supyrb/signals.git` 163 | 3. Get access to the samples 164 | 1. Simple way: Copy folder `UnityProject/Assets/Signals/Samples~` to `UnityProject/Assets/SignalSamples` in order to see/use the examples. Whenever you make changes in the new folder, you would manually need to copy them to the ~Samples folder again. 165 | 2. Hard way: Run a command prompt as admin and go to the Assets folder of the project, then run `mklink /D SignalSamples .\signals\Samples~`. This will allow you to see the otherwise hidden folder and changes done to the samples with show up as changes in git directly. 166 | 167 | 168 | #### Guidelines 169 | 170 | * Use Tabs 171 | * Use namespace `Supyrb` 172 | * Use private fields with `[SerializeField]` when you need to expose fields in the editor 173 | * Use [XML comments](https://docs.microsoft.com/en-us/dotnet/csharp/codedoc) for public methods and classes 174 | * Follow the [Supyrb Guidelines](https://github.com/supyrb/SupyrbConventions) in your code. 175 | * Use present tense git commits as described [here](https://github.com/supyrb/SupyrbConventions/tree/develop/git#commit-messages) 176 | * Use reflection for the editor window to access data from the signals, do not change field visibility just for editor tools. 177 | 178 | ## Credits 179 | 180 | * Built on the shoulders of [Signals](https://github.com/yankooliveira/signals) by [Yanko Oliveira](https://github.com/yankooliveira) 181 | * Inspired by [JS-Signas](https://github.com/millermedeiros/js-signals) by [Miller Medeiros](https://github.com/millermedeiros) 182 | * Thanks to [Benny Berger](https://github.com/Asorano) for introducing me to the pattern 183 | * Thanks to [Bryan Keiren](https://github.com/bkeiren) for [SerializableDateTime](./Scripts/Runtime/Logging/Libraries/SerializableDateTime.cs) 184 | * Developed by [Johannes Deml](https://github.com/JohannesDeml) – [public@deml.io](mailto:public@deml.io) 185 | 186 | ## License 187 | 188 | * MIT - see [LICENSE](./LICENSE.md) 189 | 190 | *![💥Supyrb](https://supyrb.com/data/supyrb-inline-logo.svg)* 191 | -------------------------------------------------------------------------------- /README.md.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 929e30121530d4841b78b5cd443f8417 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Samples~/Basic.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: cb85a1e7034b49d5963217aa20d1570f 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Samples~/Basic/BasicSignalExample.unity: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!29 &1 4 | OcclusionCullingSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 2 7 | m_OcclusionBakeSettings: 8 | smallestOccluder: 5 9 | smallestHole: 0.25 10 | backfaceThreshold: 100 11 | m_SceneGUID: 00000000000000000000000000000000 12 | m_OcclusionCullingData: {fileID: 0} 13 | --- !u!104 &2 14 | RenderSettings: 15 | m_ObjectHideFlags: 0 16 | serializedVersion: 10 17 | m_Fog: 0 18 | m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} 19 | m_FogMode: 3 20 | m_FogDensity: 0.01 21 | m_LinearFogStart: 0 22 | m_LinearFogEnd: 300 23 | m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} 24 | m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} 25 | m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} 26 | m_AmbientIntensity: 1 27 | m_AmbientMode: 0 28 | m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} 29 | m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0} 30 | m_HaloStrength: 0.5 31 | m_FlareStrength: 1 32 | m_FlareFadeSpeed: 3 33 | m_HaloTexture: {fileID: 0} 34 | m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} 35 | m_DefaultReflectionMode: 0 36 | m_DefaultReflectionResolution: 128 37 | m_ReflectionBounces: 1 38 | m_ReflectionIntensity: 1 39 | m_CustomReflection: {fileID: 0} 40 | m_Sun: {fileID: 705507994} 41 | m_UseRadianceAmbientProbe: 0 42 | --- !u!157 &3 43 | LightmapSettings: 44 | m_ObjectHideFlags: 0 45 | serializedVersion: 13 46 | m_BakeOnSceneLoad: 0 47 | m_GISettings: 48 | serializedVersion: 2 49 | m_BounceScale: 1 50 | m_IndirectOutputScale: 1 51 | m_AlbedoBoost: 1 52 | m_EnvironmentLightingMode: 0 53 | m_EnableBakedLightmaps: 1 54 | m_EnableRealtimeLightmaps: 1 55 | m_LightmapEditorSettings: 56 | serializedVersion: 12 57 | m_Resolution: 2 58 | m_BakeResolution: 40 59 | m_AtlasSize: 1024 60 | m_AO: 0 61 | m_AOMaxDistance: 1 62 | m_CompAOExponent: 1 63 | m_CompAOExponentDirect: 0 64 | m_ExtractAmbientOcclusion: 0 65 | m_Padding: 2 66 | m_LightmapParameters: {fileID: 0} 67 | m_LightmapsBakeMode: 1 68 | m_TextureCompression: 1 69 | m_ReflectionCompression: 2 70 | m_MixedBakeMode: 2 71 | m_BakeBackend: 1 72 | m_PVRSampling: 1 73 | m_PVRDirectSampleCount: 32 74 | m_PVRSampleCount: 500 75 | m_PVRBounces: 2 76 | m_PVREnvironmentSampleCount: 500 77 | m_PVREnvironmentReferencePointCount: 2048 78 | m_PVRFilteringMode: 2 79 | m_PVRDenoiserTypeDirect: 0 80 | m_PVRDenoiserTypeIndirect: 0 81 | m_PVRDenoiserTypeAO: 0 82 | m_PVRFilterTypeDirect: 0 83 | m_PVRFilterTypeIndirect: 0 84 | m_PVRFilterTypeAO: 0 85 | m_PVREnvironmentMIS: 0 86 | m_PVRCulling: 1 87 | m_PVRFilteringGaussRadiusDirect: 1 88 | m_PVRFilteringGaussRadiusIndirect: 5 89 | m_PVRFilteringGaussRadiusAO: 2 90 | m_PVRFilteringAtrousPositionSigmaDirect: 0.5 91 | m_PVRFilteringAtrousPositionSigmaIndirect: 2 92 | m_PVRFilteringAtrousPositionSigmaAO: 1 93 | m_ExportTrainingData: 0 94 | m_TrainingDataDestination: TrainingData 95 | m_LightProbeSampleCountMultiplier: 4 96 | m_LightingDataAsset: {fileID: 112000000, guid: 58526ec2755ff4643aa49c559962edb1, 97 | type: 2} 98 | m_LightingSettings: {fileID: 4890085278179872738, guid: 448a362263b2e674c8f0a78139dc9a11, 99 | type: 2} 100 | --- !u!196 &4 101 | NavMeshSettings: 102 | serializedVersion: 2 103 | m_ObjectHideFlags: 0 104 | m_BuildSettings: 105 | serializedVersion: 3 106 | agentTypeID: 0 107 | agentRadius: 0.5 108 | agentHeight: 2 109 | agentSlope: 45 110 | agentClimb: 0.4 111 | ledgeDropHeight: 0 112 | maxJumpAcrossDistance: 0 113 | minRegionArea: 2 114 | manualCellSize: 0 115 | cellSize: 0.16666667 116 | manualTileSize: 0 117 | tileSize: 256 118 | buildHeightMesh: 0 119 | maxJobWorkers: 0 120 | preserveTilesOutsideBounds: 0 121 | debug: 122 | m_Flags: 0 123 | m_NavMeshData: {fileID: 0} 124 | --- !u!1 &705507993 125 | GameObject: 126 | m_ObjectHideFlags: 0 127 | m_CorrespondingSourceObject: {fileID: 0} 128 | m_PrefabInstance: {fileID: 0} 129 | m_PrefabAsset: {fileID: 0} 130 | serializedVersion: 6 131 | m_Component: 132 | - component: {fileID: 705507995} 133 | - component: {fileID: 705507994} 134 | m_Layer: 0 135 | m_Name: Directional Light 136 | m_TagString: Untagged 137 | m_Icon: {fileID: 0} 138 | m_NavMeshLayer: 0 139 | m_StaticEditorFlags: 0 140 | m_IsActive: 1 141 | --- !u!108 &705507994 142 | Light: 143 | m_ObjectHideFlags: 0 144 | m_CorrespondingSourceObject: {fileID: 0} 145 | m_PrefabInstance: {fileID: 0} 146 | m_PrefabAsset: {fileID: 0} 147 | m_GameObject: {fileID: 705507993} 148 | m_Enabled: 1 149 | serializedVersion: 11 150 | m_Type: 1 151 | m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1} 152 | m_Intensity: 1 153 | m_Range: 10 154 | m_SpotAngle: 30 155 | m_InnerSpotAngle: 21.80208 156 | m_CookieSize: 10 157 | m_Shadows: 158 | m_Type: 2 159 | m_Resolution: -1 160 | m_CustomResolution: -1 161 | m_Strength: 1 162 | m_Bias: 0.05 163 | m_NormalBias: 0.4 164 | m_NearPlane: 0.2 165 | m_CullingMatrixOverride: 166 | e00: 1 167 | e01: 0 168 | e02: 0 169 | e03: 0 170 | e10: 0 171 | e11: 1 172 | e12: 0 173 | e13: 0 174 | e20: 0 175 | e21: 0 176 | e22: 1 177 | e23: 0 178 | e30: 0 179 | e31: 0 180 | e32: 0 181 | e33: 1 182 | m_UseCullingMatrixOverride: 0 183 | m_Cookie: {fileID: 0} 184 | m_DrawHalo: 0 185 | m_Flare: {fileID: 0} 186 | m_RenderMode: 0 187 | m_CullingMask: 188 | serializedVersion: 2 189 | m_Bits: 4294967295 190 | m_RenderingLayerMask: 1 191 | m_Lightmapping: 1 192 | m_LightShadowCasterMode: 0 193 | m_AreaSize: {x: 1, y: 1} 194 | m_BounceIntensity: 1 195 | m_ColorTemperature: 6570 196 | m_UseColorTemperature: 0 197 | m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} 198 | m_UseBoundingSphereOverride: 0 199 | m_UseViewFrustumForShadowCasterCull: 1 200 | m_ForceVisible: 0 201 | m_ShadowRadius: 0 202 | m_ShadowAngle: 0 203 | m_LightUnit: 1 204 | m_LuxAtDistance: 1 205 | m_EnableSpotReflector: 1 206 | --- !u!4 &705507995 207 | Transform: 208 | m_ObjectHideFlags: 0 209 | m_CorrespondingSourceObject: {fileID: 0} 210 | m_PrefabInstance: {fileID: 0} 211 | m_PrefabAsset: {fileID: 0} 212 | m_GameObject: {fileID: 705507993} 213 | serializedVersion: 2 214 | m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261} 215 | m_LocalPosition: {x: 0, y: 3, z: 0} 216 | m_LocalScale: {x: 1, y: 1, z: 1} 217 | m_ConstrainProportionsScale: 0 218 | m_Children: [] 219 | m_Father: {fileID: 0} 220 | m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0} 221 | --- !u!1 &840701598 222 | GameObject: 223 | m_ObjectHideFlags: 0 224 | m_CorrespondingSourceObject: {fileID: 0} 225 | m_PrefabInstance: {fileID: 0} 226 | m_PrefabAsset: {fileID: 0} 227 | serializedVersion: 6 228 | m_Component: 229 | - component: {fileID: 840701600} 230 | - component: {fileID: 840701599} 231 | m_Layer: 0 232 | m_Name: ExampleSignal 233 | m_TagString: Untagged 234 | m_Icon: {fileID: 0} 235 | m_NavMeshLayer: 0 236 | m_StaticEditorFlags: 0 237 | m_IsActive: 1 238 | --- !u!114 &840701599 239 | MonoBehaviour: 240 | m_ObjectHideFlags: 0 241 | m_CorrespondingSourceObject: {fileID: 0} 242 | m_PrefabInstance: {fileID: 0} 243 | m_PrefabAsset: {fileID: 0} 244 | m_GameObject: {fileID: 840701598} 245 | m_Enabled: 1 246 | m_EditorHideFlags: 0 247 | m_Script: {fileID: 11500000, guid: f482e16b3f9f44a5909d1ed00d4ee71a, type: 3} 248 | m_Name: 249 | m_EditorClassIdentifier: 250 | logListeners: 1 251 | --- !u!4 &840701600 252 | Transform: 253 | m_ObjectHideFlags: 0 254 | m_CorrespondingSourceObject: {fileID: 0} 255 | m_PrefabInstance: {fileID: 0} 256 | m_PrefabAsset: {fileID: 0} 257 | m_GameObject: {fileID: 840701598} 258 | serializedVersion: 2 259 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 260 | m_LocalPosition: {x: 0, y: 0, z: 0} 261 | m_LocalScale: {x: 1, y: 1, z: 1} 262 | m_ConstrainProportionsScale: 0 263 | m_Children: [] 264 | m_Father: {fileID: 0} 265 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 266 | --- !u!1 &963194225 267 | GameObject: 268 | m_ObjectHideFlags: 0 269 | m_CorrespondingSourceObject: {fileID: 0} 270 | m_PrefabInstance: {fileID: 0} 271 | m_PrefabAsset: {fileID: 0} 272 | serializedVersion: 6 273 | m_Component: 274 | - component: {fileID: 963194228} 275 | - component: {fileID: 963194227} 276 | - component: {fileID: 963194226} 277 | m_Layer: 0 278 | m_Name: Main Camera 279 | m_TagString: MainCamera 280 | m_Icon: {fileID: 0} 281 | m_NavMeshLayer: 0 282 | m_StaticEditorFlags: 0 283 | m_IsActive: 1 284 | --- !u!81 &963194226 285 | AudioListener: 286 | m_ObjectHideFlags: 0 287 | m_CorrespondingSourceObject: {fileID: 0} 288 | m_PrefabInstance: {fileID: 0} 289 | m_PrefabAsset: {fileID: 0} 290 | m_GameObject: {fileID: 963194225} 291 | m_Enabled: 1 292 | --- !u!20 &963194227 293 | Camera: 294 | m_ObjectHideFlags: 0 295 | m_CorrespondingSourceObject: {fileID: 0} 296 | m_PrefabInstance: {fileID: 0} 297 | m_PrefabAsset: {fileID: 0} 298 | m_GameObject: {fileID: 963194225} 299 | m_Enabled: 1 300 | serializedVersion: 2 301 | m_ClearFlags: 1 302 | m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} 303 | m_projectionMatrixMode: 1 304 | m_GateFitMode: 2 305 | m_FOVAxisMode: 0 306 | m_Iso: 200 307 | m_ShutterSpeed: 0.005 308 | m_Aperture: 16 309 | m_FocusDistance: 10 310 | m_FocalLength: 50 311 | m_BladeCount: 5 312 | m_Curvature: {x: 2, y: 11} 313 | m_BarrelClipping: 0.25 314 | m_Anamorphism: 0 315 | m_SensorSize: {x: 36, y: 24} 316 | m_LensShift: {x: 0, y: 0} 317 | m_NormalizedViewPortRect: 318 | serializedVersion: 2 319 | x: 0 320 | y: 0 321 | width: 1 322 | height: 1 323 | near clip plane: 0.3 324 | far clip plane: 1000 325 | field of view: 60 326 | orthographic: 0 327 | orthographic size: 5 328 | m_Depth: -1 329 | m_CullingMask: 330 | serializedVersion: 2 331 | m_Bits: 4294967295 332 | m_RenderingPath: -1 333 | m_TargetTexture: {fileID: 0} 334 | m_TargetDisplay: 0 335 | m_TargetEye: 3 336 | m_HDR: 1 337 | m_AllowMSAA: 1 338 | m_AllowDynamicResolution: 0 339 | m_ForceIntoRT: 0 340 | m_OcclusionCulling: 1 341 | m_StereoConvergence: 10 342 | m_StereoSeparation: 0.022 343 | --- !u!4 &963194228 344 | Transform: 345 | m_ObjectHideFlags: 0 346 | m_CorrespondingSourceObject: {fileID: 0} 347 | m_PrefabInstance: {fileID: 0} 348 | m_PrefabAsset: {fileID: 0} 349 | m_GameObject: {fileID: 963194225} 350 | serializedVersion: 2 351 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 352 | m_LocalPosition: {x: 0, y: 1, z: -10} 353 | m_LocalScale: {x: 1, y: 1, z: 1} 354 | m_ConstrainProportionsScale: 0 355 | m_Children: [] 356 | m_Father: {fileID: 0} 357 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 358 | --- !u!1660057539 &9223372036854775807 359 | SceneRoots: 360 | m_ObjectHideFlags: 0 361 | m_Roots: 362 | - {fileID: 963194228} 363 | - {fileID: 705507995} 364 | - {fileID: 840701600} 365 | -------------------------------------------------------------------------------- /Samples~/Basic/BasicSignalExample.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: dcd943a919d455d45aac560cdc3546f5 3 | DefaultImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Samples~/Basic/Scripts.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 24adcfe2a27836242b4d380b5b1ae34c 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Samples~/Basic/Scripts/BasicExampleSignal.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) 2019 Supyrb. All rights reserved. 4 | // 5 | // 6 | // Johannes Deml 7 | // send@johannesdeml.com 8 | // 9 | // -------------------------------------------------------------------------------------------------------------------- 10 | 11 | 12 | namespace Supyrb 13 | { 14 | public class BasicExampleSignal : Signal 15 | { 16 | // Override invoke to make sure that the derived signal class shows up in the stacktrace 17 | protected override void Invoke(int index) 18 | { 19 | base.Invoke(index); 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /Samples~/Basic/Scripts/BasicExampleSignal.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: cbfef6c3f1fe48b18554663369d822d9 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Samples~/Basic/Scripts/BasicExampleSignalTest.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) Supyrb. All rights reserved. 4 | // 5 | // 6 | // Johannes Deml 7 | // send@johannesdeml.com 8 | // 9 | // -------------------------------------------------------------------------------------------------------------------- 10 | 11 | using System.Collections; 12 | using UnityEngine; 13 | 14 | namespace Supyrb 15 | { 16 | 17 | public class BasicExampleSignalTest : MonoBehaviour 18 | { 19 | [SerializeField] 20 | private bool logListeners = true; 21 | 22 | private BasicExampleSignal basicExampleSignal; 23 | private void Awake() 24 | { 25 | Signals.Get(out basicExampleSignal); 26 | SubscribeListeners(); 27 | } 28 | 29 | private void Start() 30 | { 31 | DispatchSignal(); 32 | } 33 | 34 | private void SubscribeListeners() 35 | { 36 | basicExampleSignal.AddListener(FirstListener, -100); 37 | basicExampleSignal.AddListener(PauseTwoSecondsListener, -10); 38 | basicExampleSignal.AddListener(DefaultListener); 39 | basicExampleSignal.AddListener(ConsumeEventListener, 10); 40 | basicExampleSignal.AddListener(LastListener, 100); 41 | } 42 | 43 | private void OnDestroy() 44 | { 45 | basicExampleSignal.RemoveListener(FirstListener); 46 | basicExampleSignal.RemoveListener(PauseTwoSecondsListener); 47 | basicExampleSignal.RemoveListener(DefaultListener); 48 | basicExampleSignal.RemoveListener(ConsumeEventListener); 49 | basicExampleSignal.RemoveListener(LastListener); 50 | } 51 | 52 | [ContextMenu("DispatchSignal")] 53 | public void DispatchSignal() 54 | { 55 | basicExampleSignal.Dispatch(); 56 | } 57 | 58 | private void FirstListener() 59 | { 60 | ConditionalLog("First Listener (Order -100)"); 61 | } 62 | 63 | private void PauseTwoSecondsListener() 64 | { 65 | ConditionalLog("Pausing for 2 seconds (Order -10)"); 66 | basicExampleSignal.Pause(); 67 | StartCoroutine(ContinueAfterDelay(basicExampleSignal, 2f)); 68 | } 69 | 70 | private void DefaultListener() 71 | { 72 | ConditionalLog("Default order Listener (Order 0)"); 73 | } 74 | 75 | private void ConsumeEventListener() 76 | { 77 | ConditionalLog("Consume Signal (Order 10)"); 78 | basicExampleSignal.Consume(); 79 | } 80 | 81 | private void LastListener() 82 | { 83 | ConditionalLog("Won't be called, since the signal was consumed. (Order 100)"); 84 | } 85 | 86 | private IEnumerator ContinueAfterDelay(Signal signal, float delay) 87 | { 88 | yield return new WaitForSeconds(delay); 89 | signal.Continue(); 90 | } 91 | 92 | private void ConditionalLog(string text) 93 | { 94 | if (logListeners) 95 | { 96 | Debug.Log(text, this); 97 | } 98 | } 99 | } 100 | } -------------------------------------------------------------------------------- /Samples~/Basic/Scripts/BasicExampleSignalTest.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f482e16b3f9f44a5909d1ed00d4ee71a 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Samples~/Basic/Scripts/CustomSerializedStructSignal.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) 2019 Supyrb. All rights reserved. 4 | // 5 | // 6 | // Johannes Deml 7 | // send@johannesdeml.com 8 | // 9 | // -------------------------------------------------------------------------------------------------------------------- 10 | 11 | 12 | namespace Supyrb 13 | { 14 | public struct CustomStruct 15 | { 16 | public int Integer; 17 | public string String; 18 | } 19 | 20 | public class CustomSerializedStructSignal : Signal 21 | { 22 | } 23 | } -------------------------------------------------------------------------------- /Samples~/Basic/Scripts/CustomSerializedStructSignal.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 28363087193a30b41a6c8a1b5738021c 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Samples~/Basic/Scripts/GameObjectDispatcher.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) Supyrb. All rights reserved. 4 | // 5 | // 6 | // Johannes Deml 7 | // send@johannesdeml.com 8 | // 9 | // -------------------------------------------------------------------------------------------------------------------- 10 | 11 | using System.Collections; 12 | using UnityEngine; 13 | 14 | namespace Supyrb 15 | { 16 | public class GameObjectDispatcher : MonoBehaviour 17 | { 18 | private IEnumerator Start() 19 | { 20 | yield return new WaitForSeconds(1f); 21 | Signals.Get().Dispatch(gameObject); 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /Samples~/Basic/Scripts/GameObjectDispatcher.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ccae69a6eaef2ff46b28a1258f39c18c -------------------------------------------------------------------------------- /Samples~/Basic/Scripts/GameObjectListener.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) Supyrb. All rights reserved. 4 | // 5 | // 6 | // Johannes Deml 7 | // send@johannesdeml.com 8 | // 9 | // -------------------------------------------------------------------------------------------------------------------- 10 | 11 | using UnityEngine; 12 | 13 | namespace Supyrb 14 | { 15 | public class GameObjectListener : MonoBehaviour 16 | { 17 | private void OnEnable() 18 | { 19 | Signals.Get().AddListener(OnSignalFired); 20 | } 21 | 22 | private void OnDisable() 23 | { 24 | Signals.Get().RemoveListener(OnSignalFired); 25 | } 26 | 27 | private void OnSignalFired(GameObject go) 28 | { 29 | Debug.Log("Received signal with game object: " + go.name); 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /Samples~/Basic/Scripts/GameObjectListener.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e407053b9621ea04eb5288a0ace28424 -------------------------------------------------------------------------------- /Samples~/Basic/Scripts/GameObjectSignal.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) 2019 Supyrb. All rights reserved. 4 | // 5 | // 6 | // Johannes Deml 7 | // send@johannesdeml.com 8 | // 9 | // -------------------------------------------------------------------------------------------------------------------- 10 | 11 | 12 | using UnityEngine; 13 | 14 | namespace Supyrb 15 | { 16 | public class GameObjectSignal : Signal 17 | { 18 | } 19 | } -------------------------------------------------------------------------------- /Samples~/Basic/Scripts/GameObjectSignal.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e3bfba7caf0045046a3ca56eb188b4cb -------------------------------------------------------------------------------- /Samples~/Basic/Scripts/UnusedSignal.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) 2019 Supyrb. All rights reserved. 4 | // 5 | // 6 | // Johannes Deml 7 | // send@johannesdeml.com 8 | // 9 | // -------------------------------------------------------------------------------------------------------------------- 10 | 11 | namespace Supyrb 12 | { 13 | /// 14 | /// Signal that is not referenced by any other code. 15 | /// Shows how [RequireDerived] can be used to prevent the signal from being stripped by the linker. 16 | /// 17 | public class UnusedSignal : Signal 18 | { 19 | } 20 | } -------------------------------------------------------------------------------- /Samples~/Basic/Scripts/UnusedSignal.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e7514828b1573b34db5d2369147f348d -------------------------------------------------------------------------------- /Samples~/Basic/SignalWithParameter.unity: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!29 &1 4 | OcclusionCullingSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 2 7 | m_OcclusionBakeSettings: 8 | smallestOccluder: 5 9 | smallestHole: 0.25 10 | backfaceThreshold: 100 11 | m_SceneGUID: 00000000000000000000000000000000 12 | m_OcclusionCullingData: {fileID: 0} 13 | --- !u!104 &2 14 | RenderSettings: 15 | m_ObjectHideFlags: 0 16 | serializedVersion: 10 17 | m_Fog: 0 18 | m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} 19 | m_FogMode: 3 20 | m_FogDensity: 0.01 21 | m_LinearFogStart: 0 22 | m_LinearFogEnd: 300 23 | m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} 24 | m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} 25 | m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} 26 | m_AmbientIntensity: 1 27 | m_AmbientMode: 0 28 | m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} 29 | m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0} 30 | m_HaloStrength: 0.5 31 | m_FlareStrength: 1 32 | m_FlareFadeSpeed: 3 33 | m_HaloTexture: {fileID: 0} 34 | m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} 35 | m_DefaultReflectionMode: 0 36 | m_DefaultReflectionResolution: 128 37 | m_ReflectionBounces: 1 38 | m_ReflectionIntensity: 1 39 | m_CustomReflection: {fileID: 0} 40 | m_Sun: {fileID: 705507994} 41 | m_UseRadianceAmbientProbe: 0 42 | --- !u!157 &3 43 | LightmapSettings: 44 | m_ObjectHideFlags: 0 45 | serializedVersion: 13 46 | m_BakeOnSceneLoad: 0 47 | m_GISettings: 48 | serializedVersion: 2 49 | m_BounceScale: 1 50 | m_IndirectOutputScale: 1 51 | m_AlbedoBoost: 1 52 | m_EnvironmentLightingMode: 0 53 | m_EnableBakedLightmaps: 1 54 | m_EnableRealtimeLightmaps: 1 55 | m_LightmapEditorSettings: 56 | serializedVersion: 12 57 | m_Resolution: 2 58 | m_BakeResolution: 40 59 | m_AtlasSize: 1024 60 | m_AO: 0 61 | m_AOMaxDistance: 1 62 | m_CompAOExponent: 1 63 | m_CompAOExponentDirect: 0 64 | m_ExtractAmbientOcclusion: 0 65 | m_Padding: 2 66 | m_LightmapParameters: {fileID: 0} 67 | m_LightmapsBakeMode: 1 68 | m_TextureCompression: 1 69 | m_ReflectionCompression: 2 70 | m_MixedBakeMode: 2 71 | m_BakeBackend: 1 72 | m_PVRSampling: 1 73 | m_PVRDirectSampleCount: 32 74 | m_PVRSampleCount: 500 75 | m_PVRBounces: 2 76 | m_PVREnvironmentSampleCount: 500 77 | m_PVREnvironmentReferencePointCount: 2048 78 | m_PVRFilteringMode: 2 79 | m_PVRDenoiserTypeDirect: 0 80 | m_PVRDenoiserTypeIndirect: 0 81 | m_PVRDenoiserTypeAO: 0 82 | m_PVRFilterTypeDirect: 0 83 | m_PVRFilterTypeIndirect: 0 84 | m_PVRFilterTypeAO: 0 85 | m_PVREnvironmentMIS: 0 86 | m_PVRCulling: 1 87 | m_PVRFilteringGaussRadiusDirect: 1 88 | m_PVRFilteringGaussRadiusIndirect: 5 89 | m_PVRFilteringGaussRadiusAO: 2 90 | m_PVRFilteringAtrousPositionSigmaDirect: 0.5 91 | m_PVRFilteringAtrousPositionSigmaIndirect: 2 92 | m_PVRFilteringAtrousPositionSigmaAO: 1 93 | m_ExportTrainingData: 0 94 | m_TrainingDataDestination: TrainingData 95 | m_LightProbeSampleCountMultiplier: 4 96 | m_LightingDataAsset: {fileID: 112000000, guid: fd1dcd6c731cf0b46b4ccb20753e3a0e, 97 | type: 2} 98 | m_LightingSettings: {fileID: 4890085278179872738, guid: f72233b95c0c65c40861c0b755e31573, 99 | type: 2} 100 | --- !u!196 &4 101 | NavMeshSettings: 102 | serializedVersion: 2 103 | m_ObjectHideFlags: 0 104 | m_BuildSettings: 105 | serializedVersion: 3 106 | agentTypeID: 0 107 | agentRadius: 0.5 108 | agentHeight: 2 109 | agentSlope: 45 110 | agentClimb: 0.4 111 | ledgeDropHeight: 0 112 | maxJumpAcrossDistance: 0 113 | minRegionArea: 2 114 | manualCellSize: 0 115 | cellSize: 0.16666667 116 | manualTileSize: 0 117 | tileSize: 256 118 | buildHeightMesh: 0 119 | maxJobWorkers: 0 120 | preserveTilesOutsideBounds: 0 121 | debug: 122 | m_Flags: 0 123 | m_NavMeshData: {fileID: 0} 124 | --- !u!1 &705507993 125 | GameObject: 126 | m_ObjectHideFlags: 0 127 | m_CorrespondingSourceObject: {fileID: 0} 128 | m_PrefabInstance: {fileID: 0} 129 | m_PrefabAsset: {fileID: 0} 130 | serializedVersion: 6 131 | m_Component: 132 | - component: {fileID: 705507995} 133 | - component: {fileID: 705507994} 134 | m_Layer: 0 135 | m_Name: Directional Light 136 | m_TagString: Untagged 137 | m_Icon: {fileID: 0} 138 | m_NavMeshLayer: 0 139 | m_StaticEditorFlags: 0 140 | m_IsActive: 1 141 | --- !u!108 &705507994 142 | Light: 143 | m_ObjectHideFlags: 0 144 | m_CorrespondingSourceObject: {fileID: 0} 145 | m_PrefabInstance: {fileID: 0} 146 | m_PrefabAsset: {fileID: 0} 147 | m_GameObject: {fileID: 705507993} 148 | m_Enabled: 1 149 | serializedVersion: 11 150 | m_Type: 1 151 | m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1} 152 | m_Intensity: 1 153 | m_Range: 10 154 | m_SpotAngle: 30 155 | m_InnerSpotAngle: 21.80208 156 | m_CookieSize: 10 157 | m_Shadows: 158 | m_Type: 2 159 | m_Resolution: -1 160 | m_CustomResolution: -1 161 | m_Strength: 1 162 | m_Bias: 0.05 163 | m_NormalBias: 0.4 164 | m_NearPlane: 0.2 165 | m_CullingMatrixOverride: 166 | e00: 1 167 | e01: 0 168 | e02: 0 169 | e03: 0 170 | e10: 0 171 | e11: 1 172 | e12: 0 173 | e13: 0 174 | e20: 0 175 | e21: 0 176 | e22: 1 177 | e23: 0 178 | e30: 0 179 | e31: 0 180 | e32: 0 181 | e33: 1 182 | m_UseCullingMatrixOverride: 0 183 | m_Cookie: {fileID: 0} 184 | m_DrawHalo: 0 185 | m_Flare: {fileID: 0} 186 | m_RenderMode: 0 187 | m_CullingMask: 188 | serializedVersion: 2 189 | m_Bits: 4294967295 190 | m_RenderingLayerMask: 1 191 | m_Lightmapping: 1 192 | m_LightShadowCasterMode: 0 193 | m_AreaSize: {x: 1, y: 1} 194 | m_BounceIntensity: 1 195 | m_ColorTemperature: 6570 196 | m_UseColorTemperature: 0 197 | m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} 198 | m_UseBoundingSphereOverride: 0 199 | m_UseViewFrustumForShadowCasterCull: 1 200 | m_ForceVisible: 0 201 | m_ShadowRadius: 0 202 | m_ShadowAngle: 0 203 | m_LightUnit: 1 204 | m_LuxAtDistance: 1 205 | m_EnableSpotReflector: 1 206 | --- !u!4 &705507995 207 | Transform: 208 | m_ObjectHideFlags: 0 209 | m_CorrespondingSourceObject: {fileID: 0} 210 | m_PrefabInstance: {fileID: 0} 211 | m_PrefabAsset: {fileID: 0} 212 | m_GameObject: {fileID: 705507993} 213 | serializedVersion: 2 214 | m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261} 215 | m_LocalPosition: {x: 0, y: 3, z: 0} 216 | m_LocalScale: {x: 1, y: 1, z: 1} 217 | m_ConstrainProportionsScale: 0 218 | m_Children: [] 219 | m_Father: {fileID: 0} 220 | m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0} 221 | --- !u!1 &963194225 222 | GameObject: 223 | m_ObjectHideFlags: 0 224 | m_CorrespondingSourceObject: {fileID: 0} 225 | m_PrefabInstance: {fileID: 0} 226 | m_PrefabAsset: {fileID: 0} 227 | serializedVersion: 6 228 | m_Component: 229 | - component: {fileID: 963194228} 230 | - component: {fileID: 963194227} 231 | - component: {fileID: 963194226} 232 | m_Layer: 0 233 | m_Name: Main Camera 234 | m_TagString: MainCamera 235 | m_Icon: {fileID: 0} 236 | m_NavMeshLayer: 0 237 | m_StaticEditorFlags: 0 238 | m_IsActive: 1 239 | --- !u!81 &963194226 240 | AudioListener: 241 | m_ObjectHideFlags: 0 242 | m_CorrespondingSourceObject: {fileID: 0} 243 | m_PrefabInstance: {fileID: 0} 244 | m_PrefabAsset: {fileID: 0} 245 | m_GameObject: {fileID: 963194225} 246 | m_Enabled: 1 247 | --- !u!20 &963194227 248 | Camera: 249 | m_ObjectHideFlags: 0 250 | m_CorrespondingSourceObject: {fileID: 0} 251 | m_PrefabInstance: {fileID: 0} 252 | m_PrefabAsset: {fileID: 0} 253 | m_GameObject: {fileID: 963194225} 254 | m_Enabled: 1 255 | serializedVersion: 2 256 | m_ClearFlags: 1 257 | m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} 258 | m_projectionMatrixMode: 1 259 | m_GateFitMode: 2 260 | m_FOVAxisMode: 0 261 | m_Iso: 200 262 | m_ShutterSpeed: 0.005 263 | m_Aperture: 16 264 | m_FocusDistance: 10 265 | m_FocalLength: 50 266 | m_BladeCount: 5 267 | m_Curvature: {x: 2, y: 11} 268 | m_BarrelClipping: 0.25 269 | m_Anamorphism: 0 270 | m_SensorSize: {x: 36, y: 24} 271 | m_LensShift: {x: 0, y: 0} 272 | m_NormalizedViewPortRect: 273 | serializedVersion: 2 274 | x: 0 275 | y: 0 276 | width: 1 277 | height: 1 278 | near clip plane: 0.3 279 | far clip plane: 1000 280 | field of view: 60 281 | orthographic: 0 282 | orthographic size: 5 283 | m_Depth: -1 284 | m_CullingMask: 285 | serializedVersion: 2 286 | m_Bits: 4294967295 287 | m_RenderingPath: -1 288 | m_TargetTexture: {fileID: 0} 289 | m_TargetDisplay: 0 290 | m_TargetEye: 3 291 | m_HDR: 1 292 | m_AllowMSAA: 1 293 | m_AllowDynamicResolution: 0 294 | m_ForceIntoRT: 0 295 | m_OcclusionCulling: 1 296 | m_StereoConvergence: 10 297 | m_StereoSeparation: 0.022 298 | --- !u!4 &963194228 299 | Transform: 300 | m_ObjectHideFlags: 0 301 | m_CorrespondingSourceObject: {fileID: 0} 302 | m_PrefabInstance: {fileID: 0} 303 | m_PrefabAsset: {fileID: 0} 304 | m_GameObject: {fileID: 963194225} 305 | serializedVersion: 2 306 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 307 | m_LocalPosition: {x: 0, y: 1, z: -10} 308 | m_LocalScale: {x: 1, y: 1, z: 1} 309 | m_ConstrainProportionsScale: 0 310 | m_Children: [] 311 | m_Father: {fileID: 0} 312 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 313 | --- !u!1 &1442905279 314 | GameObject: 315 | m_ObjectHideFlags: 0 316 | m_CorrespondingSourceObject: {fileID: 0} 317 | m_PrefabInstance: {fileID: 0} 318 | m_PrefabAsset: {fileID: 0} 319 | serializedVersion: 6 320 | m_Component: 321 | - component: {fileID: 1442905281} 322 | - component: {fileID: 1442905280} 323 | m_Layer: 0 324 | m_Name: GameObjectListener 325 | m_TagString: Untagged 326 | m_Icon: {fileID: 0} 327 | m_NavMeshLayer: 0 328 | m_StaticEditorFlags: 0 329 | m_IsActive: 1 330 | --- !u!114 &1442905280 331 | MonoBehaviour: 332 | m_ObjectHideFlags: 0 333 | m_CorrespondingSourceObject: {fileID: 0} 334 | m_PrefabInstance: {fileID: 0} 335 | m_PrefabAsset: {fileID: 0} 336 | m_GameObject: {fileID: 1442905279} 337 | m_Enabled: 1 338 | m_EditorHideFlags: 0 339 | m_Script: {fileID: 11500000, guid: e407053b9621ea04eb5288a0ace28424, type: 3} 340 | m_Name: 341 | m_EditorClassIdentifier: 342 | --- !u!4 &1442905281 343 | Transform: 344 | m_ObjectHideFlags: 0 345 | m_CorrespondingSourceObject: {fileID: 0} 346 | m_PrefabInstance: {fileID: 0} 347 | m_PrefabAsset: {fileID: 0} 348 | m_GameObject: {fileID: 1442905279} 349 | serializedVersion: 2 350 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 351 | m_LocalPosition: {x: 0, y: 0, z: 0} 352 | m_LocalScale: {x: 1, y: 1, z: 1} 353 | m_ConstrainProportionsScale: 0 354 | m_Children: [] 355 | m_Father: {fileID: 0} 356 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 357 | --- !u!1 &1579911208 358 | GameObject: 359 | m_ObjectHideFlags: 0 360 | m_CorrespondingSourceObject: {fileID: 0} 361 | m_PrefabInstance: {fileID: 0} 362 | m_PrefabAsset: {fileID: 0} 363 | serializedVersion: 6 364 | m_Component: 365 | - component: {fileID: 1579911210} 366 | - component: {fileID: 1579911209} 367 | m_Layer: 0 368 | m_Name: GameObjectDispatcher 2 369 | m_TagString: Untagged 370 | m_Icon: {fileID: 0} 371 | m_NavMeshLayer: 0 372 | m_StaticEditorFlags: 0 373 | m_IsActive: 1 374 | --- !u!114 &1579911209 375 | MonoBehaviour: 376 | m_ObjectHideFlags: 0 377 | m_CorrespondingSourceObject: {fileID: 0} 378 | m_PrefabInstance: {fileID: 0} 379 | m_PrefabAsset: {fileID: 0} 380 | m_GameObject: {fileID: 1579911208} 381 | m_Enabled: 1 382 | m_EditorHideFlags: 0 383 | m_Script: {fileID: 11500000, guid: ccae69a6eaef2ff46b28a1258f39c18c, type: 3} 384 | m_Name: 385 | m_EditorClassIdentifier: 386 | --- !u!4 &1579911210 387 | Transform: 388 | m_ObjectHideFlags: 0 389 | m_CorrespondingSourceObject: {fileID: 0} 390 | m_PrefabInstance: {fileID: 0} 391 | m_PrefabAsset: {fileID: 0} 392 | m_GameObject: {fileID: 1579911208} 393 | serializedVersion: 2 394 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 395 | m_LocalPosition: {x: 0, y: 0, z: 0} 396 | m_LocalScale: {x: 1, y: 1, z: 1} 397 | m_ConstrainProportionsScale: 0 398 | m_Children: [] 399 | m_Father: {fileID: 0} 400 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 401 | --- !u!1 &1759305268 402 | GameObject: 403 | m_ObjectHideFlags: 0 404 | m_CorrespondingSourceObject: {fileID: 0} 405 | m_PrefabInstance: {fileID: 0} 406 | m_PrefabAsset: {fileID: 0} 407 | serializedVersion: 6 408 | m_Component: 409 | - component: {fileID: 1759305270} 410 | - component: {fileID: 1759305269} 411 | m_Layer: 0 412 | m_Name: GameObjectDispatcher 413 | m_TagString: Untagged 414 | m_Icon: {fileID: 0} 415 | m_NavMeshLayer: 0 416 | m_StaticEditorFlags: 0 417 | m_IsActive: 1 418 | --- !u!114 &1759305269 419 | MonoBehaviour: 420 | m_ObjectHideFlags: 0 421 | m_CorrespondingSourceObject: {fileID: 0} 422 | m_PrefabInstance: {fileID: 0} 423 | m_PrefabAsset: {fileID: 0} 424 | m_GameObject: {fileID: 1759305268} 425 | m_Enabled: 1 426 | m_EditorHideFlags: 0 427 | m_Script: {fileID: 11500000, guid: ccae69a6eaef2ff46b28a1258f39c18c, type: 3} 428 | m_Name: 429 | m_EditorClassIdentifier: 430 | --- !u!4 &1759305270 431 | Transform: 432 | m_ObjectHideFlags: 0 433 | m_CorrespondingSourceObject: {fileID: 0} 434 | m_PrefabInstance: {fileID: 0} 435 | m_PrefabAsset: {fileID: 0} 436 | m_GameObject: {fileID: 1759305268} 437 | serializedVersion: 2 438 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 439 | m_LocalPosition: {x: 0, y: 0, z: 0} 440 | m_LocalScale: {x: 1, y: 1, z: 1} 441 | m_ConstrainProportionsScale: 0 442 | m_Children: [] 443 | m_Father: {fileID: 0} 444 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 445 | --- !u!1660057539 &9223372036854775807 446 | SceneRoots: 447 | m_ObjectHideFlags: 0 448 | m_Roots: 449 | - {fileID: 963194228} 450 | - {fileID: 705507995} 451 | - {fileID: 1759305270} 452 | - {fileID: 1579911210} 453 | - {fileID: 1442905281} 454 | -------------------------------------------------------------------------------- /Samples~/Basic/SignalWithParameter.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 11f29b187d80a3845bca4e1c0415a1b9 3 | DefaultImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Samples~/StressTest.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: af5d700c84dd2864f8199a5aeb4d67f4 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Samples~/StressTest/Scripts.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 787b9af0472a39f40804b98f42aa461b 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Samples~/StressTest/Scripts/DebugListener.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) 2019 Supyrb. All rights reserved. 4 | // 5 | // 6 | // Johannes Deml 7 | // public@deml.io 8 | // 9 | // -------------------------------------------------------------------------------------------------------------------- 10 | 11 | using System; 12 | using UnityEngine; 13 | 14 | namespace Supyrb 15 | { 16 | public class DebugListener 17 | { 18 | private readonly int order; 19 | private bool subscribed; 20 | private bool verbose; 21 | private readonly Signal signal; 22 | 23 | // Cache action in order to avoid additional garbage every subscribe/unsubscribe 24 | private readonly Action onSignalAction; 25 | 26 | public DebugListener(int order, Signal signal, bool verbose) 27 | { 28 | this.order = order; 29 | this.signal = signal; 30 | this.verbose = verbose; 31 | this.onSignalAction = OnSignal; 32 | this.subscribed = false; 33 | } 34 | 35 | public void Subscribe() 36 | { 37 | if (subscribed) 38 | { 39 | return; 40 | } 41 | 42 | if (verbose && order % 1000 == 0) 43 | { 44 | Debug.LogFormat("Subscribe Listener with order {0}", order); 45 | } 46 | 47 | signal.AddListener(onSignalAction, order); 48 | subscribed = true; 49 | } 50 | 51 | public void Unsubscribe() 52 | { 53 | if (!subscribed) 54 | { 55 | return; 56 | } 57 | 58 | if (verbose && order % 1000 == 0) 59 | { 60 | Debug.LogFormat("Unsubscribe Listener with order {0}", order); 61 | } 62 | 63 | signal.RemoveListener(onSignalAction); 64 | subscribed = false; 65 | } 66 | 67 | private void OnSignal() 68 | { 69 | if (verbose && order % 1000 == 0) 70 | { 71 | Debug.LogFormat("Listener with order {0} has received the signal", order); 72 | } 73 | } 74 | } 75 | } -------------------------------------------------------------------------------- /Samples~/StressTest/Scripts/DebugListener.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 609a08d59ed14645876e67651dbbfe5b 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Samples~/StressTest/Scripts/SignalStressTest.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) Supyrb. All rights reserved. 4 | // 5 | // 6 | // Johannes Deml 7 | // public@deml.io 8 | // 9 | // -------------------------------------------------------------------------------------------------------------------- 10 | 11 | using System.Collections.Generic; 12 | using UnityEngine; 13 | using UnityEngine.Profiling; 14 | 15 | namespace Supyrb 16 | { 17 | public class SignalStressTest : MonoBehaviour 18 | { 19 | [SerializeField] 20 | private int numListener = 10000; 21 | 22 | [SerializeField] 23 | private bool dispatchEveryUpdate = true; 24 | 25 | [Tooltip("Toggle Debug Logging")] 26 | [SerializeField] 27 | private bool verbose = true; 28 | 29 | private List listeners = null; 30 | 31 | private StressTestSignal signal; 32 | private void Awake() 33 | { 34 | Signals.Get(out signal); 35 | 36 | listeners = new List(); 37 | for (int i = 0; i < numListener; i++) 38 | { 39 | listeners.Add(new DebugListener(i, signal, verbose)); 40 | } 41 | SubscribeListeners(); 42 | } 43 | 44 | private void Update() 45 | { 46 | if (!dispatchEveryUpdate) 47 | { 48 | return; 49 | } 50 | 51 | DispatchSignal(); 52 | } 53 | 54 | private void OnDestroy() 55 | { 56 | UnsubscribeListeners(); 57 | } 58 | 59 | private void SubscribeListeners() 60 | { 61 | Profiler.BeginSample("SubscribeListeners"); 62 | for (int i = 0; i < listeners.Count; i++) 63 | { 64 | var listener = listeners[i]; 65 | listener.Subscribe(); 66 | } 67 | Profiler.EndSample(); 68 | } 69 | 70 | private void UnsubscribeListeners() 71 | { 72 | Profiler.BeginSample("UnsubscribeListeners"); 73 | for (int i = 0; i < listeners.Count; i++) 74 | { 75 | var listener = listeners[i]; 76 | listener.Unsubscribe(); 77 | } 78 | Profiler.EndSample(); 79 | } 80 | 81 | [ContextMenu("DispatchSignal")] 82 | public void DispatchSignal() 83 | { 84 | if (verbose) 85 | { 86 | Debug.LogFormat("Dispatching stress signal with {0} listeners", signal.ListenerCount); 87 | } 88 | 89 | Profiler.BeginSample("DispatchSignal"); 90 | { 91 | signal.Dispatch(); 92 | } 93 | Profiler.EndSample(); 94 | } 95 | } 96 | } -------------------------------------------------------------------------------- /Samples~/StressTest/Scripts/SignalStressTest.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 296c835d67bb498ca421fe2694dafd92 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Samples~/StressTest/Scripts/StressTestSignal.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) 2019 Supyrb. All rights reserved. 4 | // 5 | // 6 | // Johannes Deml 7 | // public@deml.io 8 | // 9 | // -------------------------------------------------------------------------------------------------------------------- 10 | 11 | namespace Supyrb 12 | { 13 | public class StressTestSignal : Signal 14 | { 15 | // Override invoke to make sure that the derived signal class shows up in the stacktrace 16 | protected override void Invoke(int index) 17 | { 18 | base.Invoke(index); 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /Samples~/StressTest/Scripts/StressTestSignal.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 73a7cbb38f7e4d05998af7d4ce7d8f25 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Samples~/StressTest/StressTest.unity: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!29 &1 4 | OcclusionCullingSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 2 7 | m_OcclusionBakeSettings: 8 | smallestOccluder: 5 9 | smallestHole: 0.25 10 | backfaceThreshold: 100 11 | m_SceneGUID: 00000000000000000000000000000000 12 | m_OcclusionCullingData: {fileID: 0} 13 | --- !u!104 &2 14 | RenderSettings: 15 | m_ObjectHideFlags: 0 16 | serializedVersion: 10 17 | m_Fog: 0 18 | m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} 19 | m_FogMode: 3 20 | m_FogDensity: 0.01 21 | m_LinearFogStart: 0 22 | m_LinearFogEnd: 300 23 | m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} 24 | m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} 25 | m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} 26 | m_AmbientIntensity: 1 27 | m_AmbientMode: 0 28 | m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} 29 | m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0} 30 | m_HaloStrength: 0.5 31 | m_FlareStrength: 1 32 | m_FlareFadeSpeed: 3 33 | m_HaloTexture: {fileID: 0} 34 | m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} 35 | m_DefaultReflectionMode: 0 36 | m_DefaultReflectionResolution: 128 37 | m_ReflectionBounces: 1 38 | m_ReflectionIntensity: 1 39 | m_CustomReflection: {fileID: 0} 40 | m_Sun: {fileID: 705507994} 41 | m_UseRadianceAmbientProbe: 0 42 | --- !u!157 &3 43 | LightmapSettings: 44 | m_ObjectHideFlags: 0 45 | serializedVersion: 13 46 | m_BakeOnSceneLoad: 1 47 | m_GISettings: 48 | serializedVersion: 2 49 | m_BounceScale: 1 50 | m_IndirectOutputScale: 1 51 | m_AlbedoBoost: 1 52 | m_EnvironmentLightingMode: 0 53 | m_EnableBakedLightmaps: 1 54 | m_EnableRealtimeLightmaps: 1 55 | m_LightmapEditorSettings: 56 | serializedVersion: 12 57 | m_Resolution: 2 58 | m_BakeResolution: 40 59 | m_AtlasSize: 1024 60 | m_AO: 0 61 | m_AOMaxDistance: 1 62 | m_CompAOExponent: 1 63 | m_CompAOExponentDirect: 0 64 | m_ExtractAmbientOcclusion: 0 65 | m_Padding: 2 66 | m_LightmapParameters: {fileID: 0} 67 | m_LightmapsBakeMode: 1 68 | m_TextureCompression: 1 69 | m_ReflectionCompression: 2 70 | m_MixedBakeMode: 2 71 | m_BakeBackend: 1 72 | m_PVRSampling: 1 73 | m_PVRDirectSampleCount: 32 74 | m_PVRSampleCount: 500 75 | m_PVRBounces: 2 76 | m_PVREnvironmentSampleCount: 500 77 | m_PVREnvironmentReferencePointCount: 2048 78 | m_PVRFilteringMode: 2 79 | m_PVRDenoiserTypeDirect: 0 80 | m_PVRDenoiserTypeIndirect: 0 81 | m_PVRDenoiserTypeAO: 0 82 | m_PVRFilterTypeDirect: 0 83 | m_PVRFilterTypeIndirect: 0 84 | m_PVRFilterTypeAO: 0 85 | m_PVREnvironmentMIS: 0 86 | m_PVRCulling: 1 87 | m_PVRFilteringGaussRadiusDirect: 1 88 | m_PVRFilteringGaussRadiusIndirect: 5 89 | m_PVRFilteringGaussRadiusAO: 2 90 | m_PVRFilteringAtrousPositionSigmaDirect: 0.5 91 | m_PVRFilteringAtrousPositionSigmaIndirect: 2 92 | m_PVRFilteringAtrousPositionSigmaAO: 1 93 | m_ExportTrainingData: 0 94 | m_TrainingDataDestination: TrainingData 95 | m_LightProbeSampleCountMultiplier: 4 96 | m_LightingDataAsset: {fileID: 0} 97 | m_LightingSettings: {fileID: 713917818} 98 | --- !u!196 &4 99 | NavMeshSettings: 100 | serializedVersion: 2 101 | m_ObjectHideFlags: 0 102 | m_BuildSettings: 103 | serializedVersion: 3 104 | agentTypeID: 0 105 | agentRadius: 0.5 106 | agentHeight: 2 107 | agentSlope: 45 108 | agentClimb: 0.4 109 | ledgeDropHeight: 0 110 | maxJumpAcrossDistance: 0 111 | minRegionArea: 2 112 | manualCellSize: 0 113 | cellSize: 0.16666667 114 | manualTileSize: 0 115 | tileSize: 256 116 | buildHeightMesh: 0 117 | maxJobWorkers: 0 118 | preserveTilesOutsideBounds: 0 119 | debug: 120 | m_Flags: 0 121 | m_NavMeshData: {fileID: 0} 122 | --- !u!1 &705507993 123 | GameObject: 124 | m_ObjectHideFlags: 0 125 | m_CorrespondingSourceObject: {fileID: 0} 126 | m_PrefabInstance: {fileID: 0} 127 | m_PrefabAsset: {fileID: 0} 128 | serializedVersion: 6 129 | m_Component: 130 | - component: {fileID: 705507995} 131 | - component: {fileID: 705507994} 132 | m_Layer: 0 133 | m_Name: Directional Light 134 | m_TagString: Untagged 135 | m_Icon: {fileID: 0} 136 | m_NavMeshLayer: 0 137 | m_StaticEditorFlags: 0 138 | m_IsActive: 1 139 | --- !u!108 &705507994 140 | Light: 141 | m_ObjectHideFlags: 0 142 | m_CorrespondingSourceObject: {fileID: 0} 143 | m_PrefabInstance: {fileID: 0} 144 | m_PrefabAsset: {fileID: 0} 145 | m_GameObject: {fileID: 705507993} 146 | m_Enabled: 1 147 | serializedVersion: 11 148 | m_Type: 1 149 | m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1} 150 | m_Intensity: 1 151 | m_Range: 10 152 | m_SpotAngle: 30 153 | m_InnerSpotAngle: 21.80208 154 | m_CookieSize: 10 155 | m_Shadows: 156 | m_Type: 2 157 | m_Resolution: -1 158 | m_CustomResolution: -1 159 | m_Strength: 1 160 | m_Bias: 0.05 161 | m_NormalBias: 0.4 162 | m_NearPlane: 0.2 163 | m_CullingMatrixOverride: 164 | e00: 1 165 | e01: 0 166 | e02: 0 167 | e03: 0 168 | e10: 0 169 | e11: 1 170 | e12: 0 171 | e13: 0 172 | e20: 0 173 | e21: 0 174 | e22: 1 175 | e23: 0 176 | e30: 0 177 | e31: 0 178 | e32: 0 179 | e33: 1 180 | m_UseCullingMatrixOverride: 0 181 | m_Cookie: {fileID: 0} 182 | m_DrawHalo: 0 183 | m_Flare: {fileID: 0} 184 | m_RenderMode: 0 185 | m_CullingMask: 186 | serializedVersion: 2 187 | m_Bits: 4294967295 188 | m_RenderingLayerMask: 1 189 | m_Lightmapping: 1 190 | m_LightShadowCasterMode: 0 191 | m_AreaSize: {x: 1, y: 1} 192 | m_BounceIntensity: 1 193 | m_ColorTemperature: 6570 194 | m_UseColorTemperature: 0 195 | m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} 196 | m_UseBoundingSphereOverride: 0 197 | m_UseViewFrustumForShadowCasterCull: 1 198 | m_ForceVisible: 0 199 | m_ShadowRadius: 0 200 | m_ShadowAngle: 0 201 | m_LightUnit: 1 202 | m_LuxAtDistance: 1 203 | m_EnableSpotReflector: 1 204 | --- !u!4 &705507995 205 | Transform: 206 | m_ObjectHideFlags: 0 207 | m_CorrespondingSourceObject: {fileID: 0} 208 | m_PrefabInstance: {fileID: 0} 209 | m_PrefabAsset: {fileID: 0} 210 | m_GameObject: {fileID: 705507993} 211 | serializedVersion: 2 212 | m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261} 213 | m_LocalPosition: {x: 0, y: 3, z: 0} 214 | m_LocalScale: {x: 1, y: 1, z: 1} 215 | m_ConstrainProportionsScale: 0 216 | m_Children: [] 217 | m_Father: {fileID: 0} 218 | m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0} 219 | --- !u!850595691 &713917818 220 | LightingSettings: 221 | m_ObjectHideFlags: 0 222 | m_CorrespondingSourceObject: {fileID: 0} 223 | m_PrefabInstance: {fileID: 0} 224 | m_PrefabAsset: {fileID: 0} 225 | m_Name: Settings.lighting 226 | serializedVersion: 9 227 | m_EnableBakedLightmaps: 1 228 | m_EnableRealtimeLightmaps: 1 229 | m_RealtimeEnvironmentLighting: 1 230 | m_BounceScale: 1 231 | m_AlbedoBoost: 1 232 | m_IndirectOutputScale: 1 233 | m_UsingShadowmask: 1 234 | m_BakeBackend: 1 235 | m_LightmapMaxSize: 1024 236 | m_LightmapSizeFixed: 0 237 | m_UseMipmapLimits: 1 238 | m_BakeResolution: 40 239 | m_Padding: 2 240 | m_LightmapCompression: 3 241 | m_AO: 0 242 | m_AOMaxDistance: 1 243 | m_CompAOExponent: 1 244 | m_CompAOExponentDirect: 0 245 | m_ExtractAO: 0 246 | m_MixedBakeMode: 2 247 | m_LightmapsBakeMode: 1 248 | m_FilterMode: 1 249 | m_LightmapParameters: {fileID: 15204, guid: 0000000000000000f000000000000000, type: 0} 250 | m_ExportTrainingData: 0 251 | m_EnableWorkerProcessBaking: 1 252 | m_TrainingDataDestination: TrainingData 253 | m_RealtimeResolution: 2 254 | m_ForceWhiteAlbedo: 0 255 | m_ForceUpdates: 0 256 | m_PVRCulling: 1 257 | m_PVRSampling: 1 258 | m_PVRDirectSampleCount: 32 259 | m_PVRSampleCount: 512 260 | m_PVREnvironmentSampleCount: 512 261 | m_PVREnvironmentReferencePointCount: 2048 262 | m_LightProbeSampleCountMultiplier: 4 263 | m_PVRBounces: 2 264 | m_PVRMinBounces: 2 265 | m_PVREnvironmentImportanceSampling: 0 266 | m_PVRFilteringMode: 2 267 | m_PVRDenoiserTypeDirect: 0 268 | m_PVRDenoiserTypeIndirect: 0 269 | m_PVRDenoiserTypeAO: 0 270 | m_PVRFilterTypeDirect: 0 271 | m_PVRFilterTypeIndirect: 0 272 | m_PVRFilterTypeAO: 0 273 | m_PVRFilteringGaussRadiusDirect: 1 274 | m_PVRFilteringGaussRadiusIndirect: 5 275 | m_PVRFilteringGaussRadiusAO: 2 276 | m_PVRFilteringAtrousPositionSigmaDirect: 0.5 277 | m_PVRFilteringAtrousPositionSigmaIndirect: 2 278 | m_PVRFilteringAtrousPositionSigmaAO: 1 279 | m_RespectSceneVisibilityWhenBakingGI: 0 280 | --- !u!1 &963194225 281 | GameObject: 282 | m_ObjectHideFlags: 0 283 | m_CorrespondingSourceObject: {fileID: 0} 284 | m_PrefabInstance: {fileID: 0} 285 | m_PrefabAsset: {fileID: 0} 286 | serializedVersion: 6 287 | m_Component: 288 | - component: {fileID: 963194228} 289 | - component: {fileID: 963194227} 290 | - component: {fileID: 963194226} 291 | m_Layer: 0 292 | m_Name: Main Camera 293 | m_TagString: MainCamera 294 | m_Icon: {fileID: 0} 295 | m_NavMeshLayer: 0 296 | m_StaticEditorFlags: 0 297 | m_IsActive: 1 298 | --- !u!81 &963194226 299 | AudioListener: 300 | m_ObjectHideFlags: 0 301 | m_CorrespondingSourceObject: {fileID: 0} 302 | m_PrefabInstance: {fileID: 0} 303 | m_PrefabAsset: {fileID: 0} 304 | m_GameObject: {fileID: 963194225} 305 | m_Enabled: 1 306 | --- !u!20 &963194227 307 | Camera: 308 | m_ObjectHideFlags: 0 309 | m_CorrespondingSourceObject: {fileID: 0} 310 | m_PrefabInstance: {fileID: 0} 311 | m_PrefabAsset: {fileID: 0} 312 | m_GameObject: {fileID: 963194225} 313 | m_Enabled: 1 314 | serializedVersion: 2 315 | m_ClearFlags: 1 316 | m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} 317 | m_projectionMatrixMode: 1 318 | m_GateFitMode: 2 319 | m_FOVAxisMode: 0 320 | m_Iso: 200 321 | m_ShutterSpeed: 0.005 322 | m_Aperture: 16 323 | m_FocusDistance: 10 324 | m_FocalLength: 50 325 | m_BladeCount: 5 326 | m_Curvature: {x: 2, y: 11} 327 | m_BarrelClipping: 0.25 328 | m_Anamorphism: 0 329 | m_SensorSize: {x: 36, y: 24} 330 | m_LensShift: {x: 0, y: 0} 331 | m_NormalizedViewPortRect: 332 | serializedVersion: 2 333 | x: 0 334 | y: 0 335 | width: 1 336 | height: 1 337 | near clip plane: 0.3 338 | far clip plane: 1000 339 | field of view: 60 340 | orthographic: 0 341 | orthographic size: 5 342 | m_Depth: -1 343 | m_CullingMask: 344 | serializedVersion: 2 345 | m_Bits: 4294967295 346 | m_RenderingPath: -1 347 | m_TargetTexture: {fileID: 0} 348 | m_TargetDisplay: 0 349 | m_TargetEye: 3 350 | m_HDR: 1 351 | m_AllowMSAA: 1 352 | m_AllowDynamicResolution: 0 353 | m_ForceIntoRT: 0 354 | m_OcclusionCulling: 1 355 | m_StereoConvergence: 10 356 | m_StereoSeparation: 0.022 357 | --- !u!4 &963194228 358 | Transform: 359 | m_ObjectHideFlags: 0 360 | m_CorrespondingSourceObject: {fileID: 0} 361 | m_PrefabInstance: {fileID: 0} 362 | m_PrefabAsset: {fileID: 0} 363 | m_GameObject: {fileID: 963194225} 364 | serializedVersion: 2 365 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 366 | m_LocalPosition: {x: 0, y: 1, z: -10} 367 | m_LocalScale: {x: 1, y: 1, z: 1} 368 | m_ConstrainProportionsScale: 0 369 | m_Children: [] 370 | m_Father: {fileID: 0} 371 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 372 | --- !u!1 &1590173387 373 | GameObject: 374 | m_ObjectHideFlags: 0 375 | m_CorrespondingSourceObject: {fileID: 0} 376 | m_PrefabInstance: {fileID: 0} 377 | m_PrefabAsset: {fileID: 0} 378 | serializedVersion: 6 379 | m_Component: 380 | - component: {fileID: 1590173389} 381 | - component: {fileID: 1590173388} 382 | m_Layer: 0 383 | m_Name: StressTest 384 | m_TagString: Untagged 385 | m_Icon: {fileID: 0} 386 | m_NavMeshLayer: 0 387 | m_StaticEditorFlags: 0 388 | m_IsActive: 1 389 | --- !u!114 &1590173388 390 | MonoBehaviour: 391 | m_ObjectHideFlags: 0 392 | m_CorrespondingSourceObject: {fileID: 0} 393 | m_PrefabInstance: {fileID: 0} 394 | m_PrefabAsset: {fileID: 0} 395 | m_GameObject: {fileID: 1590173387} 396 | m_Enabled: 1 397 | m_EditorHideFlags: 0 398 | m_Script: {fileID: 11500000, guid: 296c835d67bb498ca421fe2694dafd92, type: 3} 399 | m_Name: 400 | m_EditorClassIdentifier: 401 | numListener: 10000 402 | dispatchEveryUpdate: 1 403 | verbose: 1 404 | --- !u!4 &1590173389 405 | Transform: 406 | m_ObjectHideFlags: 0 407 | m_CorrespondingSourceObject: {fileID: 0} 408 | m_PrefabInstance: {fileID: 0} 409 | m_PrefabAsset: {fileID: 0} 410 | m_GameObject: {fileID: 1590173387} 411 | serializedVersion: 2 412 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 413 | m_LocalPosition: {x: 0, y: 0, z: 0} 414 | m_LocalScale: {x: 1, y: 1, z: 1} 415 | m_ConstrainProportionsScale: 0 416 | m_Children: [] 417 | m_Father: {fileID: 0} 418 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 419 | --- !u!1660057539 &9223372036854775807 420 | SceneRoots: 421 | m_ObjectHideFlags: 0 422 | m_Roots: 423 | - {fileID: 963194228} 424 | - {fileID: 705507995} 425 | - {fileID: 1590173389} 426 | -------------------------------------------------------------------------------- /Samples~/StressTest/StressTest.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8c0e1100d839a3743addd5e7ff268d06 3 | DefaultImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Samples~/UPMExport.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e6ef45e0369056c43a1d152a0fc8ac6b 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Samples~/UPMExport/Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ec8d8620ccaf8474fb9192897b2e2795 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Samples~/UPMExport/Editor/CopyExamplesFolder.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!114 &11400000 4 | MonoBehaviour: 5 | m_ObjectHideFlags: 0 6 | m_CorrespondingSourceObject: {fileID: 0} 7 | m_PrefabInstance: {fileID: 0} 8 | m_PrefabAsset: {fileID: 0} 9 | m_GameObject: {fileID: 0} 10 | m_Enabled: 1 11 | m_EditorHideFlags: 0 12 | m_Script: {fileID: 11500000, guid: a9ae3df7852e4d0b842f2f8d26bf39a4, type: 3} 13 | m_Name: CopyExamplesFolder 14 | m_EditorClassIdentifier: 15 | sourceFolder: Assets/SignalSamples 16 | targetFolder: Assets/Signals/Samples~ 17 | replace: 1 18 | -------------------------------------------------------------------------------- /Samples~/UPMExport/Editor/CopyExamplesFolder.asset.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0fd7549178442ae4e89ba71b62921d6c 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 11400000 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Samples~/UPMExport/Editor/ExportSignalSamples.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!114 &11400000 4 | MonoBehaviour: 5 | m_ObjectHideFlags: 0 6 | m_CorrespondingSourceObject: {fileID: 0} 7 | m_PrefabInstance: {fileID: 0} 8 | m_PrefabAsset: {fileID: 0} 9 | m_GameObject: {fileID: 0} 10 | m_Enabled: 1 11 | m_EditorHideFlags: 0 12 | m_Script: {fileID: 11500000, guid: 27c29ed6e3c24f93865b4bc2df8b9c73, type: 3} 13 | m_Name: ExportSignalSamples 14 | m_EditorClassIdentifier: 15 | assetPaths: 16 | - Assets/SignalSamples 17 | exportOptions: 2 18 | targetFile: Builds/SignalSamples-{Version}.unitypackage 19 | zipFile: 0 20 | -------------------------------------------------------------------------------- /Samples~/UPMExport/Editor/ExportSignalSamples.asset.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: db3d2322fb508f34f93d5e97cb94f1d5 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 11400000 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Samples~/UPMExport/Editor/ExportSignals.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!114 &11400000 4 | MonoBehaviour: 5 | m_ObjectHideFlags: 0 6 | m_CorrespondingSourceObject: {fileID: 0} 7 | m_PrefabInstance: {fileID: 0} 8 | m_PrefabAsset: {fileID: 0} 9 | m_GameObject: {fileID: 0} 10 | m_Enabled: 1 11 | m_EditorHideFlags: 0 12 | m_Script: {fileID: 11500000, guid: 27c29ed6e3c24f93865b4bc2df8b9c73, type: 3} 13 | m_Name: ExportSignals 14 | m_EditorClassIdentifier: 15 | assetPaths: 16 | - Assets/Signals/Scripts 17 | - Assets/Signals/README.md 18 | - Assets/Signals/LICENSE 19 | - Assets/Signals/package.json 20 | - Assets/Signals/CHANGELOG.md 21 | exportOptions: 2 22 | targetFile: Builds/Signals-{Version}.unitypackage 23 | zipFile: 0 24 | -------------------------------------------------------------------------------- /Samples~/UPMExport/Editor/ExportSignals.asset.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: deb9f7858095b604f89898576584ee34 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 11400000 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Scripts.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2aa8bada606de54418dad9b87a88e831 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Scripts/Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: dcf0f1a672b9a444cbc6d987a96bdad4 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Scripts/Editor/EditorSignalLog.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) 2022 Johannes Deml. All rights reserved. 4 | // 5 | // 6 | // Johannes Deml 7 | // public@deml.io 8 | // 9 | // -------------------------------------------------------------------------------------------------------------------- 10 | 11 | using System; 12 | using UnityEditor; 13 | using UnityEditor.Callbacks; 14 | using UnityEngine; 15 | 16 | namespace Supyrb 17 | { 18 | public class EditorSignalLog 19 | { 20 | [Flags] 21 | public enum ConsoleFlags 22 | { 23 | Collapse = 1 << 0, 24 | ClearOnPlay = 1 << 1, 25 | ClearOnBuild = 1 << 2, 26 | ClearOnRecompile = 1 << 3, 27 | } 28 | 29 | public Action OnClearLogs; 30 | public event SignalLog.LogDelegate OnNewSignalLog; 31 | 32 | private static EditorSignalLog _instance; 33 | private const string ConsoleFlagsEditorKey = "SignalConsoleFlags"; 34 | private int numSubscribers; 35 | private ConsoleFlags consoleFlags; 36 | 37 | public static EditorSignalLog Instance 38 | { 39 | get 40 | { 41 | if (_instance == null) 42 | { 43 | _instance = new EditorSignalLog(); 44 | } 45 | 46 | return _instance; 47 | } 48 | } 49 | 50 | [DidReloadScripts] 51 | private static void OnScriptsReloaded() { 52 | if (_instance != null) 53 | { 54 | Instance.OnRecompile(); 55 | } 56 | } 57 | 58 | [PostProcessBuild(1)] 59 | public static void OnPostprocessBuild(BuildTarget target, string pathToBuiltProject) { 60 | if (_instance != null) 61 | { 62 | Instance.OnBuildFinished(); 63 | } 64 | } 65 | 66 | private EditorSignalLog() 67 | { 68 | numSubscribers = 0; 69 | consoleFlags = (ConsoleFlags)EditorPrefs.GetInt(ConsoleFlagsEditorKey, (int)ConsoleFlags.ClearOnPlay); 70 | EditorApplication.playModeStateChanged += OnPlayModeStateChanged; 71 | 72 | } 73 | 74 | ~EditorSignalLog() 75 | { 76 | EditorApplication.playModeStateChanged -= OnPlayModeStateChanged; 77 | } 78 | 79 | public void Subscribe() 80 | { 81 | if (numSubscribers == 0) 82 | { 83 | SignalLog.Instance.Subscribe(); 84 | SignalLog.Instance.OnNewSignalLog += OnDispatchNewSignalLog; 85 | } 86 | 87 | numSubscribers++; 88 | } 89 | 90 | public void Unsubscribe() 91 | { 92 | numSubscribers--; 93 | if (numSubscribers == 0) 94 | { 95 | SignalLog.Instance.Unsubscribe(); 96 | SignalLog.Instance.OnNewSignalLog -= OnDispatchNewSignalLog; 97 | } 98 | } 99 | 100 | public bool HasFlag(ConsoleFlags flags) 101 | { 102 | return (consoleFlags & flags) != 0; 103 | } 104 | 105 | public void SetFlag(ConsoleFlags flags, bool val) 106 | { 107 | if (val) 108 | { 109 | consoleFlags |= flags; 110 | } 111 | else 112 | { 113 | consoleFlags &= ~flags; 114 | } 115 | 116 | EditorPrefs.SetInt(ConsoleFlagsEditorKey, (int)consoleFlags); 117 | } 118 | 119 | private void OnPlayModeStateChanged(PlayModeStateChange state) 120 | { 121 | if (state == PlayModeStateChange.ExitingEditMode) 122 | { 123 | if (HasFlag(ConsoleFlags.ClearOnPlay)) 124 | { 125 | Clear(); 126 | } 127 | 128 | SignalLog.Instance.Unsubscribe(); 129 | SignalLog.Instance.Subscribe(); 130 | } 131 | } 132 | 133 | private void OnRecompile() 134 | { 135 | if (HasFlag(ConsoleFlags.ClearOnRecompile)) 136 | { 137 | Clear(); 138 | } 139 | } 140 | 141 | private void OnBuildFinished() 142 | { 143 | if (HasFlag(ConsoleFlags.ClearOnBuild)) 144 | { 145 | Clear(); 146 | } 147 | } 148 | 149 | private void OnDispatchNewSignalLog(SignalLogEntry logEntry) 150 | { 151 | OnNewSignalLog?.Invoke(logEntry); 152 | } 153 | 154 | private void Clear() 155 | { 156 | SignalLog.Instance.Clear(); 157 | OnClearLogs?.Invoke(); 158 | } 159 | } 160 | } -------------------------------------------------------------------------------- /Scripts/Editor/EditorSignalLog.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3ef412d6a50a460e822b5262034dbd8d 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Editor/SignalEditorPlayModeHandler.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) 2020 Supyrb. All rights reserved. 4 | // 5 | // 6 | // Johannes Deml 7 | // public@deml.io 8 | // 9 | // -------------------------------------------------------------------------------------------------------------------- 10 | 11 | using UnityEditor; 12 | using UnityEngine; 13 | 14 | namespace Supyrb 15 | { 16 | /// 17 | /// Handler for exiting Playmode 18 | /// Resets the Signal hub to make sure the next Playmode will not reuse old signals. 19 | /// This is necessary for supporting the experimental enter Playmode introduced in Unity 2019.3 20 | /// 21 | public static class SignalEditorPlayModeHandler 22 | { 23 | [InitializeOnLoadMethod] 24 | private static void OnProjectLoadedInEditor() 25 | { 26 | EditorApplication.playModeStateChanged += OnPlayModeStateChanged; 27 | } 28 | 29 | private static void OnPlayModeStateChanged(PlayModeStateChange state) 30 | { 31 | if (state == PlayModeStateChange.EnteredEditMode) 32 | { 33 | OnEnterEditMode(); 34 | } 35 | } 36 | 37 | private static void OnEnterEditMode() 38 | { 39 | var resetSignals = EditorPrefs.GetBool("ResetSignalsInEditmode", true); 40 | if (resetSignals) 41 | { 42 | ResetSignalHub(); 43 | } 44 | } 45 | 46 | private static void ResetSignalHub() 47 | { 48 | Debug.LogFormat("Resetting signal hub with {0} registered signals", Signals.Count); 49 | Signals.Clear(); 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /Scripts/Editor/SignalEditorPlayModeHandler.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 13a19377caf641f6a0c0ef072d18a0f2 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Editor/SignalListenerViewDrawer.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) 2020 Supyrb. All rights reserved. 4 | // 5 | // 6 | // Johannes Deml 7 | // public@deml.io 8 | // 9 | // -------------------------------------------------------------------------------------------------------------------- 10 | 11 | using System; 12 | using System.Reflection; 13 | using UnityEditor; 14 | using UnityEngine; 15 | 16 | namespace Supyrb 17 | { 18 | public class SignalListenerViewDrawer 19 | { 20 | private static class Styles 21 | { 22 | internal static GUIStyle NumberLabel; 23 | 24 | internal static GUIStyle RunningLabel; 25 | internal static GUIStyle PausedLabel; 26 | internal static GUIStyle ConsumedLabel; 27 | 28 | static Styles() 29 | { 30 | NumberLabel = new GUIStyle(EditorStyles.label); 31 | NumberLabel.alignment = TextAnchor.MiddleRight; 32 | NumberLabel.fixedWidth = 50f; 33 | NumberLabel.padding.right = 8; 34 | 35 | RunningLabel = CreateLabelStyle("SignalRunningLabel", new Color(0.2f, 0.8f, 0.2f, 0.4f)); 36 | PausedLabel = CreateLabelStyle("SignalPausedLabel", new Color(0.8f, 0.8f, 0.2f, 0.6f)); 37 | ConsumedLabel = CreateLabelStyle("SignalConsumedLabel", new Color(0.8f, 0.2f, 0.2f, 0.4f)); 38 | } 39 | 40 | private static GUIStyle CreateLabelStyle(string name, Color color) 41 | { 42 | var style = new GUIStyle(EditorStyles.label); 43 | style.name = name; 44 | var backgroundTex = SignalsEditorUtilities.CreateColorTexture(color); 45 | backgroundTex.hideFlags = HideFlags.HideAndDontSave; 46 | style.normal.background = backgroundTex; 47 | return style; 48 | } 49 | } 50 | 51 | private FieldInfo listenersField; 52 | private SignalsTreeViewItem parent; 53 | private const int maxEntries = 100; 54 | 55 | public SignalListenerViewDrawer(SignalsTreeViewItem parent, Type baseType) 56 | { 57 | this.parent = parent; 58 | listenersField = baseType.GetField("listeners", BindingFlags.Instance | BindingFlags.NonPublic); 59 | } 60 | 61 | public void DrawListeners() 62 | { 63 | if (parent.Instance.ListenerCount == 0) 64 | { 65 | GUILayout.Label("No listeners subscribed"); 66 | return; 67 | } 68 | 69 | dynamic listeners = listenersField.GetValue(parent.Instance); 70 | 71 | var numEntries = listeners.Count; 72 | var cuttingList = false; 73 | if (numEntries > maxEntries) 74 | { 75 | numEntries = maxEntries; 76 | cuttingList = true; 77 | } 78 | 79 | for (var i = 0; i < numEntries; i++) 80 | { 81 | int sortOrder = listeners.GetSortOrderForIndex(i); 82 | var listener = listeners[i]; 83 | var target = listener.Target; 84 | Type targetType = target.GetType(); 85 | 86 | var style = GetStyleForIndex(i); 87 | GUILayout.BeginHorizontal(style); 88 | 89 | GUILayout.Label(i.ToString(), GUILayout.Width(30f)); 90 | GUILayout.Label(GetSortOrderString(sortOrder), Styles.NumberLabel); 91 | if (typeof(UnityEngine.Object).IsAssignableFrom(targetType)) 92 | { 93 | EditorGUILayout.ObjectField((UnityEngine.Object) target, targetType, true); 94 | } 95 | else 96 | { 97 | GUILayout.Label(target.ToString()); 98 | } 99 | 100 | GUILayout.Label("▶ " + listener.Method.Name); 101 | GUILayout.FlexibleSpace(); 102 | 103 | GUILayout.EndHorizontal(); 104 | } 105 | 106 | if (cuttingList) 107 | { 108 | var text = string.Format("Hiding {0} other entries", listeners.Count - maxEntries); 109 | GUILayout.Label(text); 110 | } 111 | } 112 | 113 | private GUIStyle GetStyleForIndex(int index) 114 | { 115 | if (parent.CurrentIndex != index || parent.State == ASignal.State.Idle) 116 | { 117 | return EditorStyles.label; 118 | } 119 | 120 | switch (parent.State) 121 | { 122 | case ASignal.State.Running: 123 | return Styles.RunningLabel; 124 | case ASignal.State.Paused: 125 | return Styles.PausedLabel; 126 | case ASignal.State.Consumed: 127 | return Styles.ConsumedLabel; 128 | default: 129 | throw new ArgumentOutOfRangeException(); 130 | } 131 | } 132 | 133 | private string GetSortOrderString(int sortOrder) 134 | { 135 | if (sortOrder == Int32.MinValue) 136 | { 137 | return "min"; 138 | } 139 | 140 | if (sortOrder == Int32.MaxValue) 141 | { 142 | return "max"; 143 | } 144 | 145 | return sortOrder.ToString(); 146 | } 147 | } 148 | } -------------------------------------------------------------------------------- /Scripts/Editor/SignalListenerViewDrawer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5e3b63be9a7d49a799f3ebed760af0aa 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Editor/SignalLogViewDrawer.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) 2020 Supyrb. All rights reserved. 4 | // 5 | // 6 | // Johannes Deml 7 | // public@deml.io 8 | // 9 | // -------------------------------------------------------------------------------------------------------------------- 10 | 11 | using System; 12 | using System.Collections.Generic; 13 | using UnityEngine; 14 | 15 | namespace Supyrb 16 | { 17 | internal class SignalLogViewDrawer 18 | { 19 | private static class Styles 20 | { 21 | internal static GUIStyle EvenEntry; 22 | internal static GUIStyle OddEntry; 23 | 24 | static Styles() 25 | { 26 | EvenEntry = new GUIStyle((GUIStyle) "CN EntryBackEven"); 27 | OddEntry = new GUIStyle((GUIStyle) "CN EntryBackOdd"); 28 | 29 | EvenEntry.padding.left = 0; 30 | OddEntry.padding.left = 0; 31 | 32 | } 33 | } 34 | 35 | private Type type; 36 | private List signalLog; 37 | private Vector2 scrollPos; 38 | private const float maxHeight = 200f; 39 | private const int maxEntries = 100; 40 | 41 | public SignalLogViewDrawer(Type type) 42 | { 43 | this.type = type; 44 | signalLog = new List(); 45 | scrollPos = new Vector2(0f, 0f); 46 | } 47 | 48 | public void Reset() 49 | { 50 | signalLog.Clear(); 51 | scrollPos.x = 0f; 52 | scrollPos.y = 0f; 53 | } 54 | 55 | public void Update() 56 | { 57 | var newEntries = SignalLog.Instance.GetLogEntriesForType(type, ref signalLog); 58 | if (newEntries) 59 | { 60 | scrollPos.y = Mathf.Max(0f, GetListContentHeight() - maxHeight); 61 | } 62 | } 63 | 64 | public void DrawLogsForCurrentType() 65 | { 66 | if (signalLog.Count == 0) 67 | { 68 | GUILayout.Label("No logs captured for this signal"); 69 | return; 70 | } 71 | 72 | var height = Mathf.Min(GetListContentHeight(), maxHeight); 73 | 74 | scrollPos = GUILayout.BeginScrollView(scrollPos, GUILayout.Height(height)); 75 | { 76 | var startIndex = 0; 77 | if (signalLog.Count > maxEntries) 78 | { 79 | startIndex = signalLog.Count - maxEntries; 80 | var style = GetStyleForIndex(startIndex - 1); 81 | var text = string.Format("Hiding {0} older entries", startIndex); 82 | 83 | GUILayout.Label(text, style); 84 | } 85 | 86 | for (var i = startIndex; i < signalLog.Count; i++) 87 | { 88 | var entry = signalLog[i]; 89 | var style = GetStyleForIndex(i); 90 | 91 | var text = $"[{entry.TimeStamp.DateTime:HH:mm:ss}] {i:000} " + 92 | $"from {entry.SourceFileName}:{entry.MemberName}:(Line {entry.SourceLineNumber})"; 93 | 94 | GUILayout.Label(text, style); 95 | } 96 | } 97 | GUILayout.EndScrollView(); 98 | } 99 | 100 | private static GUIStyle GetStyleForIndex(int index) 101 | { 102 | return index % 2 == 0 ? Styles.EvenEntry : Styles.OddEntry; 103 | } 104 | 105 | /// 106 | /// Get the editor height of the complete list with all entries 107 | /// 108 | /// Total list content height 109 | private float GetListContentHeight() 110 | { 111 | var entries = signalLog.Count; 112 | if (entries > maxEntries) 113 | { 114 | entries = maxEntries; 115 | } 116 | 117 | // TODO get values from elements instead of hardcoding them 118 | return 8f + entries * 28f; 119 | } 120 | } 121 | } -------------------------------------------------------------------------------- /Scripts/Editor/SignalLogViewDrawer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9abf16ad52bc4dd687da46d12a2d830a 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Editor/SignalReflectionHelper.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) 2020 Supyrb. All rights reserved. 4 | // 5 | // 6 | // Johannes Deml 7 | // public@deml.io 8 | // 9 | // -------------------------------------------------------------------------------------------------------------------- 10 | 11 | using System; 12 | using System.Collections.Generic; 13 | using System.Reflection; 14 | using UnityEngine; 15 | 16 | namespace Supyrb 17 | { 18 | public static class SignalReflectionHelper 19 | { 20 | public static void GetAllDerivedClasses(ref List list) where T : ISignal 21 | { 22 | var assemblies = AppDomain.CurrentDomain.GetAssemblies(); 23 | 24 | for (int i = 0; i < assemblies.Length; i++) 25 | { 26 | var assembly = assemblies[i]; 27 | if (!assembly.IsDynamic && !IsInProject(assembly.Location)) 28 | { 29 | continue; 30 | } 31 | 32 | // Ignore Microsoft.CodeAnalysis 33 | // see https://issuetracker.unity3d.com/issues/reflectiontypeloadexception-is-thrown-when-retrieving-assembly-types-in-project-that-contains-immediate-window-package 34 | if (assembly.FullName.StartsWith(("Microsoft.CodeAnalysis"))) 35 | { 36 | continue; 37 | } 38 | 39 | try 40 | { 41 | GetAllDerivedClasses(ref list, assembly); 42 | } 43 | catch (ReflectionTypeLoadException e) 44 | { 45 | Debug.LogWarningFormat("Error when getting types of {0}, ignoring this assembly\n{1}", 46 | assembly.FullName, e.Message); 47 | } 48 | } 49 | } 50 | 51 | private static bool IsInProject(string path) 52 | { 53 | var assetsPath = Application.dataPath; 54 | var projectPath = assetsPath.Substring(0, assetsPath.Length - "/Assets".Length); 55 | path = path.Replace('\\', '/'); 56 | return path.StartsWith(projectPath); 57 | } 58 | 59 | public static void GetAllDerivedClasses(ref List list, Assembly assembly) where T : ISignal 60 | { 61 | var types = assembly.GetTypes(); 62 | var baseType = typeof(T); 63 | 64 | for (int i = 0; i < types.Length; i++) 65 | { 66 | var type = types[i]; 67 | if (!type.IsClass || type.IsAbstract || !baseType.IsAssignableFrom(type) || type.ContainsGenericParameters) 68 | { 69 | continue; 70 | } 71 | 72 | list.Add(type); 73 | } 74 | } 75 | } 76 | } -------------------------------------------------------------------------------- /Scripts/Editor/SignalReflectionHelper.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 189a5bb7b4a13b34fb5ae81f32d6ef97 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Editor/SignalsAboutWindow.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) 2020 Supyrb. All rights reserved. 4 | // 5 | // 6 | // Johannes Deml 7 | // public@deml.io 8 | // 9 | // -------------------------------------------------------------------------------------------------------------------- 10 | 11 | using System; 12 | using System.IO; 13 | using UnityEditor; 14 | using UnityEngine; 15 | 16 | namespace Supyrb 17 | { 18 | public class SignalsAboutWindow : EditorWindow 19 | { 20 | [Serializable] 21 | private class UnityPackage 22 | { 23 | public string version; 24 | } 25 | 26 | private const string Headline = "Signals ({0})"; 27 | private static string version; 28 | private static class Styles 29 | { 30 | internal static GUIStyle HeaderLabel; 31 | internal static GUIStyle LinkLabel; 32 | 33 | static Styles() 34 | { 35 | HeaderLabel = new GUIStyle((GUIStyle) "AM MixerHeader"); 36 | HeaderLabel.alignment = TextAnchor.MiddleCenter; 37 | HeaderLabel.fixedHeight = 32; 38 | 39 | LinkLabel = new GUIStyle(EditorStyles.linkLabel); 40 | LinkLabel.alignment = TextAnchor.MiddleCenter; 41 | } 42 | } 43 | 44 | [MenuItem("Window/Signals/About")] 45 | public static void ShowWindow() 46 | { 47 | var window = ScriptableObject.CreateInstance(); 48 | version = window.GetPackageVersion(); 49 | window.titleContent = new GUIContent(string.Format(Headline, version)); 50 | window.position = new Rect(Screen.width / 2, Screen.height / 2, 250, 150); 51 | window.ShowModalUtility(); 52 | } 53 | 54 | private string GetPackageVersion() 55 | { 56 | MonoScript monoScript = MonoScript.FromScriptableObject(this); 57 | var assetPath = AssetDatabase.GetAssetPath(monoScript); 58 | DirectoryInfo projectDirectory = new DirectoryInfo(Application.dataPath).Parent; 59 | DirectoryInfo directory = new FileInfo(assetPath).Directory; 60 | while (directory.GetFiles("package.json").Length == 0 && directory != projectDirectory) 61 | { 62 | directory = directory.Parent; 63 | } 64 | 65 | if (directory == projectDirectory) 66 | { 67 | return null; 68 | } 69 | 70 | FileInfo fileInfo = directory.GetFiles("package.json")[0]; 71 | string packageContent = File.ReadAllText(fileInfo.FullName); 72 | UnityPackage package = JsonUtility.FromJson(packageContent); 73 | return package.version; 74 | } 75 | 76 | private void OnGUI() 77 | { 78 | GUILayout.Space(12); 79 | EditorGUILayout.LabelField(string.Format(Headline, version), Styles.HeaderLabel); 80 | GUILayout.Space(12); 81 | DrawLink("Github", "https://www.github.com/supyrb/signals"); 82 | DrawLink("OpenUPM", "https://openupm.com/packages/com.supyrb.signals/"); 83 | DrawLink("Create Issue", "https://github.com/supyrb/signals/issues/new"); 84 | DrawLink("Contact us", "mailto:pr@supyrb.com"); 85 | 86 | GUILayout.FlexibleSpace(); 87 | } 88 | 89 | private static void DrawLink(string text, string url) 90 | { 91 | EditorGUILayout.BeginHorizontal(); 92 | GUILayout.FlexibleSpace(); 93 | if (GUILayout.Button(text, Styles.LinkLabel)) 94 | { 95 | Application.OpenURL(url); 96 | } 97 | GUILayout.FlexibleSpace(); 98 | EditorGUILayout.EndHorizontal(); 99 | } 100 | } 101 | } -------------------------------------------------------------------------------- /Scripts/Editor/SignalsAboutWindow.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e543994c91214eccad0e5991167a8e50 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Editor/SignalsEditorConsoleWindow.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) 2022 Johannes Deml. All rights reserved. 4 | // 5 | // 6 | // Johannes Deml 7 | // public@deml.io 8 | // 9 | // -------------------------------------------------------------------------------------------------------------------- 10 | 11 | using System.Collections.Generic; 12 | using UnityEditor; 13 | using UnityEditor.IMGUI.Controls; 14 | using UnityEngine; 15 | 16 | namespace Supyrb 17 | { 18 | internal class SignalsEditorConsoleWindow : EditorWindow 19 | { 20 | [SerializeField] 21 | private TreeViewState treeViewState; 22 | 23 | [SerializeField] 24 | private List entries; 25 | 26 | private SignalLogEntry currentSelection; 27 | private SignalsLogTreeView treeView; 28 | private SearchField searchField; 29 | private SignalsTreeViewItem currentItem; 30 | 31 | private const float ToolbarHeight = 18f; 32 | private const float FooterHeight = 24f; 33 | 34 | private static class Styles 35 | { 36 | public static readonly GUIStyle FooterStyle; 37 | public static readonly GUIStyle ToolbarButton; 38 | public static readonly GUIContent Clear = EditorGUIUtility.TrTextContent("Clear", "Clear console entries"); 39 | public static readonly GUIContent ClearOnPlay = EditorGUIUtility.TrTextContent("Clear on Play"); 40 | public static readonly GUIContent ClearOnBuild = EditorGUIUtility.TrTextContent("Clear on Build"); 41 | public static readonly GUIContent ClearOnRecompile = EditorGUIUtility.TrTextContent("Clear on Recompile"); 42 | 43 | static Styles() 44 | { 45 | FooterStyle = new GUIStyle((GUIStyle) "ProjectBrowserBottomBarBg"); 46 | ToolbarButton = new GUIStyle((GUIStyle) "ToolbarButton"); 47 | } 48 | } 49 | 50 | [MenuItem("Window/Signals/Console")] 51 | private static void ShowWindow() 52 | { 53 | // Get existing open window or if none, make a new one: 54 | var window = GetWindow(); 55 | var titleContent = EditorGUIUtility.IconContent("Profiler.NetworkMessages"); 56 | titleContent.text = "Signals Console"; 57 | window.titleContent = titleContent; 58 | window.Show(); 59 | } 60 | 61 | private void OnEnable() 62 | { 63 | // Check if we already had a serialized view state 64 | // (state that survived assembly reloading) 65 | if (treeViewState == null) 66 | { 67 | treeViewState = new TreeViewState(); 68 | } 69 | 70 | if (entries == null) 71 | { 72 | entries = new List(); 73 | } 74 | 75 | 76 | treeView = new SignalsLogTreeView(treeViewState, entries); 77 | treeView.OnSelectionChanged += OnSelectionChanged; 78 | searchField = new SearchField(); 79 | searchField.downOrUpArrowKeyPressed += treeView.SetFocusAndEnsureSelectedItem; 80 | EditorSignalLog.Instance.Subscribe(); 81 | EditorSignalLog.Instance.OnNewSignalLog += OnNewSignalLog; 82 | EditorSignalLog.Instance.OnClearLogs += Clear; 83 | } 84 | 85 | private void OnDisable() 86 | { 87 | if (searchField != null) 88 | { 89 | searchField.downOrUpArrowKeyPressed -= treeView.SetFocusAndEnsureSelectedItem; 90 | } 91 | 92 | EditorSignalLog.Instance.Unsubscribe(); 93 | EditorSignalLog.Instance.OnNewSignalLog -= OnNewSignalLog; 94 | EditorSignalLog.Instance.OnClearLogs -= Clear; 95 | } 96 | 97 | private void OnInspectorUpdate() 98 | { 99 | this.Repaint(); 100 | } 101 | 102 | private void OnGUI() 103 | { 104 | var contentHeight = this.position.height - ToolbarHeight - FooterHeight; 105 | 106 | DoToolbar(); 107 | var rect = GUILayoutUtility.GetRect(0, this.position.width, 0, 100000); 108 | DoTreeView(rect); 109 | 110 | DoFooter(); 111 | } 112 | 113 | private void DoToolbar() 114 | { 115 | GUILayout.BeginHorizontal(EditorStyles.toolbar, GUILayout.Width(this.position.width), 116 | GUILayout.Height(ToolbarHeight)); 117 | if (GUILayout.Button(Styles.Clear, Styles.ToolbarButton)) 118 | { 119 | Clear(); 120 | GUIUtility.keyboardControl = 0; 121 | } 122 | if (EditorGUILayout.DropdownButton(new GUIContent("Options"), FocusType.Passive, Styles.ToolbarButton)) 123 | { 124 | var clearOnPlay = HasFlag(EditorSignalLog.ConsoleFlags.ClearOnPlay); 125 | var clearOnBuild = HasFlag(EditorSignalLog.ConsoleFlags.ClearOnBuild); 126 | var clearOnRecompile = HasFlag(EditorSignalLog.ConsoleFlags.ClearOnRecompile); 127 | 128 | GenericMenu menu = new GenericMenu(); 129 | menu.AddItem(Styles.ClearOnPlay, clearOnPlay, () => { SetFlag(EditorSignalLog.ConsoleFlags.ClearOnPlay, !clearOnPlay); }); 130 | menu.AddItem(Styles.ClearOnBuild, clearOnBuild, () => { SetFlag(EditorSignalLog.ConsoleFlags.ClearOnBuild, !clearOnBuild); }); 131 | menu.AddItem(Styles.ClearOnRecompile, clearOnRecompile, () => { SetFlag(EditorSignalLog.ConsoleFlags.ClearOnRecompile, !clearOnRecompile); }); 132 | var rect = GUILayoutUtility.GetLastRect(); 133 | rect.y += EditorGUIUtility.singleLineHeight; 134 | menu.DropDown(rect); 135 | } 136 | 137 | 138 | GUILayout.Space(100); 139 | GUILayout.FlexibleSpace(); 140 | treeView.searchString = searchField.OnToolbarGUI(treeView.searchString); 141 | 142 | GUILayout.EndHorizontal(); 143 | } 144 | 145 | private void DoTreeView(Rect rect) 146 | { 147 | treeView.OnGUI(rect); 148 | } 149 | 150 | private void DoFooter() 151 | { 152 | GUILayout.BeginHorizontal(Styles.FooterStyle, 153 | GUILayout.Width(this.position.width), 154 | GUILayout.Height(FooterHeight)); 155 | 156 | var lastDispatchedSignal = SignalLog.Instance.GetLastEntry(); 157 | if (lastDispatchedSignal != null) 158 | { 159 | var signalText = string.Format("[{0:HH:mm:ss}] {1} - Dispatch Time: {2:0.000}", 160 | lastDispatchedSignal.TimeStamp.DateTime, 161 | lastDispatchedSignal.SignalType.Name, 162 | lastDispatchedSignal.PlayDispatchTime); 163 | GUILayout.Label(signalText); 164 | } 165 | 166 | GUILayout.FlexibleSpace(); 167 | GUILayout.EndHorizontal(); 168 | } 169 | 170 | private void Clear() 171 | { 172 | treeView.ClearLogs(); 173 | } 174 | 175 | private void OnNewSignalLog(SignalLogEntry logentry) 176 | { 177 | treeView.AddEntry(logentry); 178 | } 179 | 180 | private void OnSelectionChanged(SignalLogEntry selectedEntry) 181 | { 182 | currentSelection = selectedEntry; 183 | } 184 | 185 | private bool HasFlag(EditorSignalLog.ConsoleFlags flags) 186 | { 187 | return EditorSignalLog.Instance.HasFlag(flags); 188 | } 189 | 190 | private void SetFlag(EditorSignalLog.ConsoleFlags flags, bool val) 191 | { 192 | EditorSignalLog.Instance.SetFlag(flags, val); 193 | } 194 | } 195 | } -------------------------------------------------------------------------------- /Scripts/Editor/SignalsEditorConsoleWindow.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c24f3e1d54f447bab642aec509ebb666 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Editor/SignalsEditorDatabase.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) 2020 Supyrb. All rights reserved. 4 | // 5 | // 6 | // Johannes Deml 7 | // public@deml.io 8 | // 9 | // -------------------------------------------------------------------------------------------------------------------- 10 | 11 | using System; 12 | using System.Collections.Generic; 13 | using UnityEditor; 14 | using UnityEngine; 15 | 16 | namespace Supyrb 17 | { 18 | public class SignalsEditorDatabase : ScriptableObject 19 | { 20 | [SerializeField] 21 | private List signalTypes = new List(); 22 | 23 | public List SignalTypes 24 | { 25 | get 26 | { 27 | return signalTypes; 28 | } 29 | } 30 | 31 | private static SignalsEditorDatabase instance = null; 32 | 33 | public static SignalsEditorDatabase Instance 34 | { 35 | get 36 | { 37 | if (instance == null) 38 | { 39 | FindOrCreateInstance(); 40 | } 41 | 42 | return instance; 43 | } 44 | } 45 | 46 | private static void FindOrCreateInstance() 47 | { 48 | if (instance != null) 49 | { 50 | return; 51 | } 52 | 53 | instance = SignalsEditorUtilities.FindOrCreateEditorAsset("Signals", "SignalsEditorDatabase.asset", false); 54 | } 55 | 56 | [ContextMenu("UpdateDatabase")] 57 | public void UpdateDatabase() 58 | { 59 | try 60 | { 61 | EditorUtility.DisplayProgressBar("Update Signals List", "Find all signals in project", 0.1f); 62 | var types = new List(); 63 | SignalReflectionHelper.GetAllDerivedClasses(ref types); 64 | signalTypes.Clear(); 65 | EditorUtility.DisplayProgressBar("Update Signals List", string.Format("Serialize found signals ({0})", types.Count), 0.6f); 66 | for (int i = 0; i < types.Count; i++) 67 | { 68 | var type = types[i]; 69 | signalTypes.Add(new SerializableSystemType(type)); 70 | } 71 | signalTypes.Sort(); 72 | 73 | EditorUtility.DisplayProgressBar("Update Signals List", string.Format("Store found signals ({0})", types.Count), 0.9f); 74 | EditorUtility.SetDirty(this); 75 | AssetDatabase.SaveAssets(); 76 | } 77 | finally 78 | { 79 | EditorUtility.ClearProgressBar(); 80 | } 81 | 82 | } 83 | } 84 | } -------------------------------------------------------------------------------- /Scripts/Editor/SignalsEditorDatabase.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: be5374a0681c43e4946c559aae9efcaa 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Editor/SignalsEditorUtilities.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) 2020 Supyrb. All rights reserved. 4 | // 5 | // 6 | // Johannes Deml 7 | // public@deml.io 8 | // 9 | // -------------------------------------------------------------------------------------------------------------------- 10 | 11 | using System; 12 | using System.IO; 13 | using UnityEditor; 14 | using UnityEngine; 15 | using UnityEngine.Assertions; 16 | 17 | namespace Supyrb 18 | { 19 | public static class SignalsEditorUtilities 20 | { 21 | /// 22 | /// Get or Create a ScriptabelObject in the EditorDefaultResources folder. 23 | /// 24 | /// Type of the scriptable object 25 | /// Path to the asset relative to the EditorDefaultResources folder. e.g. QualityAssurace/Materials 26 | /// Name of the file including the extension, e.g. MaterialCollector.asset 27 | /// Whether the file should be searched in the complete project if no asset is found at the defined location 28 | /// The found or created asset 29 | public static T FindOrCreateEditorAsset(string folderPath, string fileName, bool searchOutsideResources) where T : ScriptableObject 30 | { 31 | if (folderPath == null) 32 | { 33 | folderPath = string.Empty; 34 | } 35 | 36 | var asset = EditorGUIUtility.Load(Path.Combine(folderPath, fileName)) as T; 37 | if (asset == null && searchOutsideResources) 38 | { 39 | var guids = AssetDatabase.FindAssets("t:" + typeof(T).FullName); 40 | if (guids.Length > 0) 41 | { 42 | if (guids.Length > 1) 43 | { 44 | Debug.LogWarningFormat("More than one Asset of the type {0} exists:", typeof(T).FullName); 45 | for (var i = 0; i < guids.Length; i++) 46 | { 47 | var path = AssetDatabase.GUIDToAssetPath(guids[i]); 48 | var assetAtPath = AssetDatabase.LoadAssetAtPath(path); 49 | Debug.Log(path, assetAtPath); 50 | } 51 | } 52 | 53 | var pathToFirstAsset = AssetDatabase.GUIDToAssetPath(guids[0]); 54 | asset = AssetDatabase.LoadAssetAtPath(pathToFirstAsset); 55 | } 56 | } 57 | 58 | if (asset == null) 59 | { 60 | asset = ScriptableObject.CreateInstance(); 61 | var assetRelativeFolderPath = "Assets/Editor Default Resources/" + folderPath; 62 | // Create folders if not not existent 63 | Directory.CreateDirectory(Path.GetFullPath(assetRelativeFolderPath)); 64 | var assetRelativeFilePath = Path.Combine(assetRelativeFolderPath, fileName); 65 | AssetDatabase.CreateAsset(asset, assetRelativeFilePath); 66 | } 67 | 68 | return asset; 69 | } 70 | 71 | /// 72 | /// Creates a new Texture2D with 1x1 pixels and a defined color. 73 | /// Easy solution for editor style background textures that should just be a color 74 | /// 75 | /// The color for the new texture 76 | /// A new 1x1 texture with the defined color 77 | public static Texture2D CreateColorTexture(Color col) 78 | { 79 | Texture2D result = new Texture2D(1, 1); 80 | result.SetPixel(0, 0, col); 81 | result.Apply(); 82 | 83 | return result; 84 | } 85 | 86 | /// 87 | /// Modify the color of a 1x1 texture 88 | /// 89 | /// Texture to modify 90 | /// New color 91 | public static void ChangeColorTexture(Texture2D tex, Color col) 92 | { 93 | Assert.IsTrue(tex.width == 1); 94 | Assert.IsTrue(tex.height == 1); 95 | 96 | tex.SetPixel(0, 0, col); 97 | tex.Apply(); 98 | } 99 | 100 | /// 101 | /// Similar to , but more flexible. 102 | /// Draws an editor field fitting to the type and returns the user value for that field. 103 | /// Supports 104 | /// * 105 | /// * 106 | /// * 107 | /// * 108 | /// * 109 | /// * 110 | /// * 111 | /// * 112 | /// * 113 | /// * 114 | /// * 115 | /// * 116 | /// * 117 | /// 118 | /// Optional label in front of the field 119 | /// Type of the value 120 | /// Current value for that field 121 | /// The new value set by the user 122 | public static object DrawFittingEditorField(string label, Type type, object value) 123 | { 124 | if (typeof(UnityEngine.Object).IsAssignableFrom(type)) 125 | { 126 | return EditorGUILayout.ObjectField(label, (UnityEngine.Object) value, type, true); 127 | } 128 | 129 | if (type == typeof(AnimationCurve)) 130 | { 131 | return EditorGUILayout.CurveField(label, (AnimationCurve) value); 132 | } 133 | 134 | if (type == typeof(Gradient)) 135 | { 136 | return EditorGUILayout.GradientField(label, (Gradient) value); 137 | } 138 | 139 | if (type == typeof(string)) 140 | { 141 | return EditorGUILayout.TextField(label, (string) value); 142 | } 143 | 144 | if (type.IsEnum) 145 | { 146 | int enumValue = 0; 147 | if (value != null) 148 | { 149 | enumValue = (int) value; 150 | } 151 | 152 | return EditorGUILayout.EnumPopup(label, (Enum) Enum.ToObject(type, enumValue)); 153 | } 154 | 155 | if (type == typeof(bool)) 156 | { 157 | var boolValue = false; 158 | if (value != null) 159 | { 160 | boolValue = (bool) value; 161 | } 162 | 163 | return EditorGUILayout.Toggle(label, boolValue); 164 | } 165 | 166 | if (type == typeof(int)) 167 | { 168 | var intValue = 0; 169 | if (value != null) 170 | { 171 | intValue = (int) value; 172 | } 173 | 174 | return EditorGUILayout.IntField(label, (int) intValue); 175 | } 176 | 177 | if (type == typeof(long)) 178 | { 179 | var longValue = 0L; 180 | if (value != null) 181 | { 182 | longValue = (long) value; 183 | } 184 | 185 | return EditorGUILayout.LongField(label, longValue); 186 | } 187 | 188 | if (type == typeof(float)) 189 | { 190 | var floatValue = 0f; 191 | if (value != null) 192 | { 193 | floatValue = (float) value; 194 | } 195 | 196 | return EditorGUILayout.FloatField(label, floatValue); 197 | } 198 | 199 | if (type == typeof(Vector2)) 200 | { 201 | var vectorValue = Vector2.zero; 202 | if (value != null) 203 | { 204 | vectorValue = (Vector2) value; 205 | } 206 | 207 | return EditorGUILayout.Vector2Field(label, vectorValue); 208 | } 209 | 210 | if (type == typeof(Vector3)) 211 | { 212 | var vectorValue = Vector3.zero; 213 | if (value != null) 214 | { 215 | vectorValue = (Vector3) value; 216 | } 217 | 218 | return EditorGUILayout.Vector3Field(label, vectorValue); 219 | } 220 | 221 | if (type == typeof(Vector4)) 222 | { 223 | var vectorValue = Vector4.zero; 224 | if (value != null) 225 | { 226 | vectorValue = (Vector4) value; 227 | } 228 | 229 | return EditorGUILayout.Vector4Field(label, vectorValue); 230 | } 231 | 232 | if (type == typeof(Color)) 233 | { 234 | var colorValue = Color.black; 235 | if (value != null) 236 | { 237 | colorValue = (Color) value; 238 | } 239 | 240 | return EditorGUILayout.ColorField(label, colorValue); 241 | } 242 | 243 | GUILayout.Label(string.Format("Field Type {0} not supported", type.FullName)); 244 | return null; 245 | } 246 | } 247 | } -------------------------------------------------------------------------------- /Scripts/Editor/SignalsEditorUtilities.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8c160258a43c47aaa19ebfe5480e088b 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Editor/SignalsEditorWindow.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) 2020 Supyrb. All rights reserved. 4 | // 5 | // 6 | // Johannes Deml 7 | // public@deml.io 8 | // 9 | // -------------------------------------------------------------------------------------------------------------------- 10 | 11 | using UnityEditor; 12 | using UnityEditor.IMGUI.Controls; 13 | using UnityEngine; 14 | 15 | namespace Supyrb 16 | { 17 | /// 18 | /// General signals editor window showing all available signals in the project 19 | /// Can be used to debug and dispatch signals in the editor 20 | /// 21 | internal class SignalsEditorWindow : EditorWindow 22 | { 23 | [SerializeField] 24 | private TreeViewState treeViewState; 25 | 26 | private SignalsTreeView treeView; 27 | private SearchField searchField; 28 | private SignalsTreeViewItems items; 29 | private SerializableSystemType currentSelection; 30 | private SignalsTreeViewItem currentItem; 31 | private GUIContent refreshSignalListGuiContent; 32 | private GUIContent aboutSignalsGuiContent; 33 | private Vector2 detailScrollPosition = Vector2.zero; 34 | 35 | private const float HierarchyWidth = 250f; 36 | private const float ToolbarHeight = 18f; 37 | private const float FooterHeight = 24f; 38 | 39 | private static class Styles 40 | { 41 | public static GUIStyle HierarchyStyle; 42 | public static GUIStyle FooterStyle; 43 | public static GUIStyle IconButton; 44 | 45 | static Styles() 46 | { 47 | HierarchyStyle = new GUIStyle((GUIStyle) "OL box"); 48 | FooterStyle = new GUIStyle((GUIStyle) "ProjectBrowserBottomBarBg"); 49 | IconButton = new GUIStyle((GUIStyle) "IconButton"); 50 | IconButton.margin.top = 3; 51 | } 52 | } 53 | 54 | [MenuItem("Window/Signals/Signals")] 55 | private static void ShowWindow() 56 | { 57 | // Get existing open window or if none, make a new one: 58 | var window = GetWindow(); 59 | var titleContent = EditorGUIUtility.IconContent("Profiler.NetworkMessages"); 60 | titleContent.text = "Signals"; 61 | window.titleContent = titleContent; 62 | window.Show(); 63 | } 64 | 65 | private void OnEnable() 66 | { 67 | // Check if we already had a serialized view state 68 | // (state that survived assembly reloading) 69 | if (treeViewState == null) 70 | { 71 | treeViewState = new TreeViewState(); 72 | } 73 | 74 | items = new SignalsTreeViewItems(); 75 | treeView = new SignalsTreeView(treeViewState); 76 | treeView.OnSelectionChanged += OnSelectionChanged; 77 | searchField = new SearchField(); 78 | searchField.downOrUpArrowKeyPressed += treeView.SetFocusAndEnsureSelectedItem; 79 | 80 | refreshSignalListGuiContent = EditorGUIUtility.IconContent("Refresh"); 81 | refreshSignalListGuiContent.tooltip = "Refresh Signal list"; 82 | 83 | aboutSignalsGuiContent = EditorGUIUtility.IconContent("_Help"); 84 | aboutSignalsGuiContent.tooltip = "About"; 85 | 86 | EditorSignalLog.Instance.Subscribe(); 87 | EditorSignalLog.Instance.OnClearLogs += Clear; 88 | } 89 | 90 | private void OnDisable() 91 | { 92 | if (searchField != null) 93 | { 94 | searchField.downOrUpArrowKeyPressed -= treeView.SetFocusAndEnsureSelectedItem; 95 | } 96 | 97 | EditorSignalLog.Instance.Unsubscribe(); 98 | EditorSignalLog.Instance.OnClearLogs -= Clear; 99 | } 100 | 101 | private void OnInspectorUpdate() 102 | { 103 | this.Repaint(); 104 | } 105 | 106 | private void Clear() 107 | { 108 | items.Reset(); 109 | } 110 | 111 | private void OnGUI() 112 | { 113 | var contentHeight = this.position.height - ToolbarHeight - FooterHeight; 114 | 115 | DoToolbar(); 116 | EditorGUILayout.BeginHorizontal(GUILayout.Height(contentHeight)); 117 | 118 | 119 | EditorGUILayout.BeginVertical(Styles.HierarchyStyle, GUILayout.Width(HierarchyWidth)); 120 | var rect = GUILayoutUtility.GetRect(0, HierarchyWidth, 0, 100000); 121 | DoTreeView(rect); 122 | EditorGUILayout.EndVertical(); 123 | 124 | var detailWidth = this.position.width - HierarchyWidth; 125 | detailScrollPosition = GUILayout.BeginScrollView(detailScrollPosition, GUILayout.Width(detailWidth), GUILayout.Height(contentHeight)); 126 | { 127 | DoDetailView(); 128 | GUILayout.Space(EditorGUIUtility.standardVerticalSpacing * 4f); 129 | } 130 | GUILayout.EndScrollView(); 131 | 132 | EditorGUILayout.EndHorizontal(); 133 | 134 | DoFooter(); 135 | } 136 | 137 | private void DoToolbar() 138 | { 139 | GUILayout.BeginHorizontal(EditorStyles.toolbar, 140 | GUILayout.Width(this.position.width), 141 | GUILayout.Height(ToolbarHeight)); 142 | GUILayout.Space(100); 143 | GUILayout.FlexibleSpace(); 144 | treeView.searchString = searchField.OnToolbarGUI(treeView.searchString); 145 | if (GUILayout.Button(aboutSignalsGuiContent, Styles.IconButton)) 146 | { 147 | SignalsAboutWindow.ShowWindow(); 148 | } 149 | 150 | GUILayout.EndHorizontal(); 151 | } 152 | 153 | private void DoTreeView(Rect rect) 154 | { 155 | treeView.OnGUI(rect); 156 | } 157 | 158 | private void DoDetailView() 159 | { 160 | if (currentSelection == null || currentSelection.SystemType == null) 161 | { 162 | GUILayout.Label("Nothing selected"); 163 | return; 164 | } 165 | 166 | if (currentItem == null) 167 | { 168 | currentItem = items.Get(currentSelection.SystemType); 169 | } 170 | 171 | currentItem.DrawSignalDetailView(); 172 | } 173 | 174 | private void DoFooter() 175 | { 176 | GUILayout.BeginHorizontal(Styles.FooterStyle, 177 | GUILayout.Width(this.position.width), 178 | GUILayout.Height(FooterHeight)); 179 | 180 | var lastDispatchedSignal = SignalLog.Instance.GetLastEntry(); 181 | if (lastDispatchedSignal != null) 182 | { 183 | var signalText = string.Format("[{0:HH:mm:ss}] {1} - Dispatch Time: {2:0.000}", 184 | lastDispatchedSignal.TimeStamp.DateTime, 185 | lastDispatchedSignal.SignalType.Name, 186 | lastDispatchedSignal.PlayDispatchTime); 187 | GUILayout.Label(signalText); 188 | } 189 | 190 | GUILayout.FlexibleSpace(); 191 | if (GUILayout.Button(refreshSignalListGuiContent, Styles.IconButton)) 192 | { 193 | treeView.UpdateSignalData(); 194 | items.Clear(); 195 | } 196 | 197 | GUILayout.EndHorizontal(); 198 | } 199 | 200 | private void OnSelectionChanged(SerializableSystemType selectedtype) 201 | { 202 | currentSelection = selectedtype; 203 | currentItem = items.Get(currentSelection.SystemType); 204 | detailScrollPosition.x = 0f; 205 | detailScrollPosition.y = 0f; 206 | } 207 | } 208 | } -------------------------------------------------------------------------------- /Scripts/Editor/SignalsEditorWindow.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 48be0bbd0a83e6547837cdeef12265f2 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Editor/SignalsLogTreeView.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) 2022 Johannes Deml. All rights reserved. 4 | // 5 | // 6 | // Johannes Deml 7 | // public@deml.io 8 | // 9 | // -------------------------------------------------------------------------------------------------------------------- 10 | 11 | using System.Collections.Generic; 12 | using UnityEditor; 13 | using UnityEditor.IMGUI.Controls; 14 | 15 | namespace Supyrb 16 | { 17 | internal class SignalsLogTreeView : TreeView 18 | { 19 | public delegate void SelectionChangedDelegate(SignalLogEntry selectedEntry); 20 | 21 | public event SelectionChangedDelegate OnSelectionChanged; 22 | 23 | private List treeItems; 24 | private List entries; 25 | private TreeViewItem root; 26 | 27 | public SignalsLogTreeView(TreeViewState treeViewState, List entries) 28 | : base(treeViewState) 29 | { 30 | rowHeight = EditorGUIUtility.singleLineHeight * 2f; 31 | showAlternatingRowBackgrounds = true; 32 | this.entries = entries; 33 | treeItems = new List(); 34 | root = new TreeViewItem {id = -1, depth = -1, displayName = "Root"}; 35 | Reload(); 36 | } 37 | 38 | public void ClearLogs() 39 | { 40 | entries.Clear(); 41 | treeItems.Clear(); 42 | Reload(); 43 | } 44 | 45 | public void AddEntry(SignalLogEntry entry) 46 | { 47 | entries.Add(entry); 48 | Reload(); 49 | } 50 | 51 | protected override TreeViewItem BuildRoot() 52 | { 53 | for (int i = treeItems.Count; i < entries.Count; i++) 54 | { 55 | var entry = entries[i]; 56 | var signalText = $"[{entry.TimeStamp.DateTime:HH:mm:ss}] {entry.SignalType.Name} - " + 57 | $"Dispatch Time: {entry.PlayDispatchTime:0.000}\n" + 58 | $"{entry.SourceFileName}:{entry.MemberName} (at {entry.SourceFilePath}:{entry.SourceLineNumber}"; 59 | treeItems.Add(new TreeViewItem(i, 0, signalText)); 60 | } 61 | 62 | // Utility method that initializes the TreeViewItem.children and -parent for all items. 63 | SetupParentsAndChildrenFromDepths(root, treeItems); 64 | 65 | // Return root of the tree 66 | return root; 67 | } 68 | 69 | protected override void SelectionChanged(IList selectedIds) 70 | { 71 | base.SelectionChanged(selectedIds); 72 | if (OnSelectionChanged == null) 73 | { 74 | return; 75 | } 76 | if (selectedIds.Count == 0 || entries.Count == 0) 77 | { 78 | OnSelectionChanged(null); 79 | } 80 | else 81 | { 82 | OnSelectionChanged(entries[selectedIds[0]]); 83 | } 84 | } 85 | } 86 | } -------------------------------------------------------------------------------- /Scripts/Editor/SignalsLogTreeView.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b5d5bebffc5a49c0899767a4c18bf4cb 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Editor/SignalsTreeView.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) 2020 Supyrb. All rights reserved. 4 | // 5 | // 6 | // Johannes Deml 7 | // public@deml.io 8 | // 9 | // -------------------------------------------------------------------------------------------------------------------- 10 | 11 | using System; 12 | using System.Collections.Generic; 13 | using UnityEditor.IMGUI.Controls; 14 | 15 | namespace Supyrb 16 | { 17 | internal class SignalsTreeView : TreeView 18 | { 19 | public delegate void SelectionChangedDelegate(SerializableSystemType selectedType); 20 | 21 | public event SelectionChangedDelegate OnSelectionChanged; 22 | 23 | private List signals; 24 | private List signalTypes; 25 | 26 | public SignalsTreeView(TreeViewState treeViewState) 27 | : base(treeViewState) 28 | { 29 | signals = new List(); 30 | signalTypes = SignalsEditorDatabase.Instance.SignalTypes; 31 | Reload(); 32 | } 33 | 34 | protected override TreeViewItem BuildRoot() 35 | { 36 | signals.Clear(); 37 | var root = new TreeViewItem {id = -1, depth = -1, displayName = "Root"}; 38 | for (int i = 0; i < signalTypes.Count; i++) 39 | { 40 | var signalType = signalTypes[i]; 41 | signals.Add(new TreeViewItem(i, 0, signalType.Name)); 42 | } 43 | 44 | // Utility method that initializes the TreeViewItem.children and -parent for all items. 45 | SetupParentsAndChildrenFromDepths(root, signals); 46 | 47 | // Return root of the tree 48 | return root; 49 | } 50 | 51 | public void UpdateSignalData() 52 | { 53 | SignalsEditorDatabase.Instance.UpdateDatabase(); 54 | this.Reload(); 55 | } 56 | 57 | protected override void SelectionChanged(IList selectedIds) 58 | { 59 | base.SelectionChanged(selectedIds); 60 | if (OnSelectionChanged == null) 61 | { 62 | return; 63 | } 64 | if (selectedIds.Count == 0) 65 | { 66 | OnSelectionChanged(null); 67 | } 68 | else 69 | { 70 | OnSelectionChanged(signalTypes[selectedIds[0]]); 71 | } 72 | } 73 | } 74 | } -------------------------------------------------------------------------------- /Scripts/Editor/SignalsTreeView.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 026f9c545aa136e48a30b42c73ac83f3 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Editor/SignalsTreeViewItem.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) 2020 Supyrb. All rights reserved. 4 | // 5 | // 6 | // Johannes Deml 7 | // public@deml.io 8 | // 9 | // -------------------------------------------------------------------------------------------------------------------- 10 | 11 | using System; 12 | using System.Reflection; 13 | using System.Runtime.CompilerServices; 14 | using UnityEditor; 15 | using UnityEngine; 16 | 17 | namespace Supyrb 18 | { 19 | public class SignalsTreeViewItem 20 | { 21 | static class Styles 22 | { 23 | internal static GUIStyle HeaderLabel; 24 | 25 | static Styles() 26 | { 27 | HeaderLabel = new GUIStyle((GUIStyle)"AM MixerHeader"); 28 | HeaderLabel.margin.left = 4; 29 | } 30 | } 31 | 32 | private const int NumDispatchDefaultArguments = 3; 33 | private readonly Type type; 34 | private readonly Type baseType; 35 | private readonly Type[] argumentTypes; 36 | 37 | private ASignal instance; 38 | private object[] argumentValues; 39 | private MethodInfo dispatchMethod; 40 | private FieldInfo currentIndexField; 41 | private FieldInfo stateField; 42 | private int currentIndex; 43 | private ASignal.State state; 44 | 45 | private SignalLogViewDrawer logViewDrawer; 46 | private SignalListenerViewDrawer listenerViewDrawer; 47 | 48 | private bool foldoutListeners = true; 49 | private bool foldoutLog = true; 50 | 51 | public ASignal Instance 52 | { 53 | get { return instance; } 54 | } 55 | 56 | public int CurrentIndex 57 | { 58 | get { return currentIndex; } 59 | } 60 | 61 | public ASignal.State State 62 | { 63 | get { return state; } 64 | } 65 | 66 | public SignalsTreeViewItem(Type type) 67 | { 68 | this.type = type; 69 | 70 | baseType = this.type.BaseType; 71 | if (baseType == null || baseType == typeof(ASignal)) 72 | { 73 | baseType = this.type; 74 | } 75 | 76 | argumentTypes = baseType.GetGenericArguments(); 77 | argumentValues = new object[argumentTypes.Length + NumDispatchDefaultArguments]; 78 | 79 | 80 | dispatchMethod = this.type.GetMethod("Dispatch", BindingFlags.Instance | BindingFlags.Public); 81 | currentIndexField = typeof(ASignal).GetField("currentIndex", BindingFlags.Instance | BindingFlags.NonPublic); 82 | stateField = typeof(ASignal).GetField("state", BindingFlags.Instance | BindingFlags.NonPublic); 83 | 84 | logViewDrawer = new SignalLogViewDrawer(type); 85 | listenerViewDrawer = new SignalListenerViewDrawer(this, baseType); 86 | } 87 | 88 | public void DrawSignalDetailView() 89 | { 90 | GUILayout.BeginVertical(); 91 | 92 | if (instance == null) 93 | { 94 | instance = Signals.Get(type) as ASignal; 95 | 96 | if (instance == null) 97 | { 98 | GUILayout.Label("Only signals derived from ASignal supported"); 99 | return; 100 | } 101 | } 102 | 103 | var indexObject = currentIndexField.GetValue(instance); 104 | currentIndex = indexObject is int ? (int) indexObject : 0; 105 | var stateObject = stateField.GetValue(instance); 106 | state = stateObject is ASignal.State ? (ASignal.State) stateObject : ASignal.State.Idle; 107 | 108 | DrawHeader(); 109 | GUILayout.Space(24f); 110 | 111 | DrawDispatchPropertyFields(); 112 | DrawButtons(); 113 | 114 | GUILayout.Space(24f); 115 | DrawLogs(); 116 | 117 | GUILayout.Space(24f); 118 | DrawListeners(); 119 | 120 | GUILayout.EndVertical(); 121 | } 122 | 123 | private void DrawHeader() 124 | { 125 | GUILayout.Label(string.Format(type.Name), Styles.HeaderLabel); 126 | } 127 | 128 | private void DrawDispatchPropertyFields() 129 | { 130 | for (var i = 0; i < argumentTypes.Length; i++) 131 | { 132 | var argumentType = argumentTypes[i]; 133 | var argumentValue = argumentValues[i]; 134 | argumentValues[i] = SignalsEditorUtilities.DrawFittingEditorField(argumentType.Name, argumentType, argumentValue); 135 | } 136 | } 137 | 138 | private void DrawButtons() 139 | { 140 | GUILayout.BeginHorizontal(); 141 | if (GUILayout.Button("Dispatch")) 142 | { 143 | DispatchSignalFromEditor(); 144 | } 145 | 146 | GUI.enabled = state == ASignal.State.Running || state == ASignal.State.Paused; 147 | if (GUILayout.Button("Consume")) 148 | { 149 | instance.Consume(); 150 | } 151 | 152 | GUILayout.EndHorizontal(); 153 | 154 | GUILayout.BeginHorizontal(); 155 | GUI.enabled = state == ASignal.State.Paused; 156 | if (GUILayout.Button("Continue")) 157 | { 158 | instance.Continue(); 159 | } 160 | 161 | GUI.enabled = state == ASignal.State.Running; 162 | if (GUILayout.Button("Pause")) 163 | { 164 | instance.Pause(); 165 | } 166 | 167 | GUILayout.EndHorizontal(); 168 | GUI.enabled = true; 169 | } 170 | 171 | private void DispatchSignalFromEditor() 172 | { 173 | DispatchSignalViaReflection(); 174 | } 175 | 176 | private void DispatchSignalViaReflection([CallerMemberName] string memberName = "", 177 | [CallerFilePath] string sourceFilePath = "", 178 | [CallerLineNumber] int sourceLineNumber = 0) 179 | { 180 | argumentValues[argumentTypes.Length] = memberName; 181 | argumentValues[argumentTypes.Length + 1] = sourceFilePath; 182 | argumentValues[argumentTypes.Length + 2] = sourceLineNumber; 183 | dispatchMethod.Invoke(instance, argumentValues); 184 | } 185 | 186 | private void DrawLogs() 187 | { 188 | foldoutLog = EditorGUILayout.Foldout(foldoutLog, "Log"); 189 | if (!foldoutLog) 190 | { 191 | return; 192 | } 193 | logViewDrawer.Update(); 194 | logViewDrawer.DrawLogsForCurrentType(); 195 | } 196 | 197 | private void DrawListeners() 198 | { 199 | foldoutListeners = EditorGUILayout.Foldout(foldoutListeners, $"Listeners ({instance.ListenerCount})"); 200 | if (!foldoutListeners) 201 | { 202 | return; 203 | } 204 | 205 | listenerViewDrawer.DrawListeners(); 206 | } 207 | 208 | public void Reset() 209 | { 210 | instance = null; 211 | logViewDrawer.Reset(); 212 | } 213 | } 214 | } -------------------------------------------------------------------------------- /Scripts/Editor/SignalsTreeViewItem.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: effe311f902c0044fa9de85b8c115988 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Editor/SignalsTreeViewItems.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) 2020 Supyrb. All rights reserved. 4 | // 5 | // 6 | // Johannes Deml 7 | // public@deml.io 8 | // 9 | // -------------------------------------------------------------------------------------------------------------------- 10 | 11 | using System; 12 | using System.Collections.Generic; 13 | 14 | namespace Supyrb 15 | { 16 | public class SignalsTreeViewItems 17 | { 18 | private Dictionary items; 19 | 20 | public SignalsTreeViewItems() 21 | { 22 | items = new Dictionary(); 23 | } 24 | 25 | public SignalsTreeViewItem Get(Type type) 26 | { 27 | SignalsTreeViewItem item; 28 | if (items.TryGetValue(type, out item)) 29 | { 30 | return item; 31 | } 32 | 33 | item = new SignalsTreeViewItem(type); 34 | items[type] = item; 35 | return item; 36 | } 37 | 38 | public void Clear() 39 | { 40 | items.Clear(); 41 | } 42 | 43 | public void Reset() 44 | { 45 | foreach (var item in items) 46 | { 47 | item.Value.Reset(); 48 | } 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /Scripts/Editor/SignalsTreeViewItems.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 075ce2e1eb5042c786303f363de7966b 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Editor/Supyrb.Signals.Editor.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Supyrb.Signals.Editor", 3 | "rootNamespace": "", 4 | "references": [ 5 | "GUID:16f55dfd49f3b694bab70fdad220587f", 6 | "GUID:a93bee54bb381744cbdd02ee23fe7a67" 7 | ], 8 | "includePlatforms": [ 9 | "Editor" 10 | ], 11 | "excludePlatforms": [], 12 | "allowUnsafeCode": false, 13 | "overrideReferences": false, 14 | "precompiledReferences": [], 15 | "autoReferenced": true, 16 | "defineConstraints": [], 17 | "versionDefines": [], 18 | "noEngineReferences": false 19 | } -------------------------------------------------------------------------------- /Scripts/Editor/Supyrb.Signals.Editor.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: fde15bbe6bcce8b4089124e561b4b80e 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Scripts/Runtime.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4388b6961472dab4d975d3c8b0be4221 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Scripts/Runtime/ASignal.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) 2019 Supyrb. All rights reserved. 4 | // 5 | // 6 | // Johannes Deml 7 | // public@deml.io 8 | // 9 | // -------------------------------------------------------------------------------------------------------------------- 10 | 11 | #if ENABLE_MONO || ENABLE_IL2CPP 12 | using UnityEngine.Profiling; 13 | using UnityEngine.Scripting; 14 | #endif 15 | 16 | namespace Supyrb 17 | { 18 | /// 19 | /// The base implementation for a signal which defines all interfaces the signal should have 20 | /// This is also a non-generics version that can be easily referenced. 21 | /// Implementations with generics should take as their base class 22 | /// 23 | #if ENABLE_MONO || ENABLE_IL2CPP 24 | [RequireDerived] 25 | #endif 26 | public abstract class ASignal : ISignal 27 | { 28 | public enum State 29 | { 30 | /// 31 | /// Signal was never called or is finished 32 | /// 33 | Idle, 34 | /// 35 | /// Signal is currently active and processing listener at 36 | /// 37 | Running, 38 | /// 39 | /// Signal is paused and can be continued at the next index by calling 40 | /// 41 | Paused, 42 | /// 43 | /// Signal was consumed at 44 | /// 45 | Consumed 46 | } 47 | 48 | /// 49 | /// Number of registered listeners 50 | /// 51 | public abstract int ListenerCount { get; } 52 | 53 | private int currentIndex; 54 | private State state; 55 | 56 | 57 | protected ASignal() 58 | { 59 | this.currentIndex = 0; 60 | this.state = State.Idle; 61 | } 62 | 63 | /// 64 | /// Pause dispatching 65 | /// Dispatching can be continued by calling 66 | /// 67 | public void Pause() 68 | { 69 | this.state = State.Paused; 70 | } 71 | 72 | /// 73 | /// Continue dispatching 74 | /// Only applicable if was called before 75 | /// 76 | public void Continue() 77 | { 78 | if (state != State.Paused) 79 | { 80 | return; 81 | } 82 | 83 | BeginSignalProfilerSample("Continue Signal"); 84 | 85 | currentIndex++; 86 | state = State.Running; 87 | Run(); 88 | 89 | EndSignalProfilerSample(); 90 | } 91 | 92 | /// 93 | /// Consume the signal, no further listener will receive the dispatched signal 94 | /// 95 | public void Consume() 96 | { 97 | state = State.Consumed; 98 | } 99 | 100 | protected void StartDispatch() 101 | { 102 | currentIndex = 0; 103 | state = State.Running; 104 | 105 | Run(); 106 | } 107 | 108 | private void Run() 109 | { 110 | while (true) 111 | { 112 | if (currentIndex >= ListenerCount) 113 | { 114 | OnFinish(); 115 | return; 116 | } 117 | 118 | Invoke(currentIndex); 119 | 120 | if (state != State.Running) 121 | { 122 | return; 123 | } 124 | currentIndex++; 125 | } 126 | } 127 | 128 | protected void AddListenerAt(int index) 129 | { 130 | if (state == State.Idle) 131 | { 132 | return; 133 | } 134 | 135 | if (currentIndex >= index) 136 | { 137 | currentIndex++; 138 | } 139 | } 140 | 141 | protected void RemoveListenerAt(int index) 142 | { 143 | if (state == State.Idle) 144 | { 145 | return; 146 | } 147 | 148 | if (currentIndex >= index) 149 | { 150 | currentIndex--; 151 | } 152 | } 153 | 154 | protected virtual void OnFinish() 155 | { 156 | state = State.Idle; 157 | } 158 | 159 | protected void BeginSignalProfilerSample(string sampleName) 160 | { 161 | #if ENABLE_MONO || ENABLE_IL2CPP 162 | Profiler.BeginSample(sampleName); 163 | Profiler.BeginSample(this.GetType().FullName); 164 | #endif 165 | } 166 | 167 | protected void EndSignalProfilerSample() 168 | { 169 | #if ENABLE_MONO || ENABLE_IL2CPP 170 | Profiler.EndSample(); 171 | Profiler.EndSample(); 172 | #endif 173 | } 174 | 175 | /// 176 | public override string ToString() 177 | { 178 | 179 | return string.Format("Signal {0}: {1} Listeners, State {2}, Index {3}", 180 | this.GetType().Name, ListenerCount, state, currentIndex); 181 | } 182 | 183 | /// 184 | /// Removes all registered listeners 185 | /// 186 | public abstract void Clear(); 187 | 188 | protected abstract void Invoke(int index); 189 | } 190 | } -------------------------------------------------------------------------------- /Scripts/Runtime/ASignal.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a25069632bb34a01810e1d75fc101f3a 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Runtime/ASignalAction.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) 2023 Supyrb. All rights reserved. 4 | // 5 | // 6 | // Johannes Deml 7 | // public@deml.io 8 | // 9 | // -------------------------------------------------------------------------------------------------------------------- 10 | 11 | using System; 12 | 13 | namespace Supyrb 14 | { 15 | public abstract class ASignalAction : ASignal 16 | where TAction : Delegate 17 | { 18 | protected readonly OrderedList listeners; 19 | 20 | /// 21 | public override int ListenerCount 22 | { 23 | get { return listeners.Count; } 24 | } 25 | 26 | public ASignalAction() : base() 27 | { 28 | this.listeners = new OrderedList(true); 29 | } 30 | 31 | /// 32 | public override void Clear() 33 | { 34 | listeners.Clear(); 35 | } 36 | 37 | /// 38 | /// Add a listener for that signal 39 | /// 40 | /// Listener Method to call 41 | /// Lower order values will be called first 42 | /// 43 | /// True, if the listener was added successfully 44 | /// False, if the listener was already subscribed 45 | /// 46 | public bool AddListener(TAction listener, int order = 0) 47 | { 48 | #if UNITY_EDITOR 49 | UnityEngine.Debug.Assert(listener.Method.GetCustomAttributes(typeof(System.Runtime.CompilerServices.CompilerGeneratedAttribute), false).Length == 0, 50 | "Adding anonymous delegates as Signal callbacks is not supported (you wouldn't be able to unregister them later)."); 51 | #endif 52 | var index = listeners.Add(order, listener); 53 | if (index < 0) 54 | { 55 | return false; 56 | } 57 | 58 | AddListenerAt(index); 59 | return true; 60 | } 61 | 62 | /// 63 | /// Remove a listener from that signal 64 | /// 65 | /// Subscribed listener method 66 | /// 67 | /// True, if the signal was removed successfully 68 | /// False, if the listener was not subscribed 69 | /// 70 | public bool RemoveListener(TAction listener) 71 | { 72 | var index = listeners.Remove(listener); 73 | if (index < 0) 74 | { 75 | return false; 76 | } 77 | 78 | RemoveListenerAt(index); 79 | return true; 80 | } 81 | } 82 | } -------------------------------------------------------------------------------- /Scripts/Runtime/ASignalAction.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0e7ea59c6d755024f8a86fa89752b2d0 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Runtime/ISignal.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) 2020 Supyrb. All rights reserved. 4 | // 5 | // 6 | // Johannes Deml 7 | // public@deml.io 8 | // 9 | // -------------------------------------------------------------------------------------------------------------------- 10 | 11 | namespace Supyrb 12 | { 13 | public interface ISignal 14 | { 15 | } 16 | } -------------------------------------------------------------------------------- /Scripts/Runtime/ISignal.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 262ca18371642794a9760ef724fc1245 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Runtime/Logging.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f4aac8b2f3f7af748b03b4bc95e777bc 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Scripts/Runtime/Logging/Libraries.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 89ee562f7630c5546bbfc504308b4418 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Scripts/Runtime/Logging/Libraries/SerializableDateTime.cs: -------------------------------------------------------------------------------- 1 | // Simple helper class that allows you to serialize System.Type objects. 2 | // Use it however you like, but crediting or even just contacting the author would be appreciated (Always 3 | // nice to see people using your stuff!) 4 | // 5 | // Written by Bryan Keiren (http://www.bryankeiren.com) 6 | 7 | using System; 8 | using UnityEngine; 9 | 10 | namespace Supyrb 11 | { 12 | [System.Serializable] 13 | public class SerializableDateTime : IComparable 14 | { 15 | [SerializeField] 16 | private long m_ticks; 17 | 18 | private bool initialized; 19 | private DateTime m_dateTime; 20 | public DateTime DateTime 21 | { 22 | get 23 | { 24 | if (!initialized) 25 | { 26 | m_dateTime = new DateTime(m_ticks); 27 | initialized = true; 28 | } 29 | 30 | return m_dateTime; 31 | } 32 | } 33 | 34 | public SerializableDateTime(DateTime dateTime) 35 | { 36 | m_ticks = dateTime.Ticks; 37 | m_dateTime = dateTime; 38 | initialized = true; 39 | } 40 | 41 | public int CompareTo(SerializableDateTime other) 42 | { 43 | if (other == null) 44 | { 45 | return 1; 46 | } 47 | return m_ticks.CompareTo(other.m_ticks); 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /Scripts/Runtime/Logging/Libraries/SerializableDateTime.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: dbe6ce54ab6a477598f306824958eb15 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Runtime/Logging/Libraries/SerializableSystemType.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) 2022 Johannes Deml. All rights reserved. 4 | // 5 | // 6 | // Johannes Deml 7 | // public@deml.io 8 | // 9 | // -------------------------------------------------------------------------------------------------------------------- 10 | 11 | using System; 12 | using UnityEngine; 13 | 14 | namespace Supyrb 15 | { 16 | [System.Serializable] 17 | public class SerializableSystemType : IComparable 18 | { 19 | [SerializeField] private string m_Name; 20 | 21 | public string Name 22 | { 23 | get { return m_Name; } 24 | } 25 | 26 | [SerializeField] private string m_AssemblyQualifiedName; 27 | 28 | public string AssemblyQualifiedName 29 | { 30 | get { return m_AssemblyQualifiedName; } 31 | } 32 | 33 | [SerializeField] private string m_AssemblyName; 34 | 35 | public string AssemblyName 36 | { 37 | get { return m_AssemblyName; } 38 | } 39 | 40 | private System.Type m_SystemType; 41 | 42 | public System.Type SystemType 43 | { 44 | get 45 | { 46 | if (m_SystemType == null) 47 | { 48 | GetSystemType(); 49 | } 50 | 51 | return m_SystemType; 52 | } 53 | } 54 | 55 | private void GetSystemType() 56 | { 57 | m_SystemType = System.Type.GetType(m_AssemblyQualifiedName); 58 | } 59 | 60 | public SerializableSystemType(System.Type systemType) 61 | { 62 | m_SystemType = systemType; 63 | m_Name = systemType.Name; 64 | m_AssemblyQualifiedName = systemType.AssemblyQualifiedName; 65 | m_AssemblyName = systemType.Assembly.FullName; 66 | } 67 | 68 | public int CompareTo(SerializableSystemType other) 69 | { 70 | if (m_Name == null) 71 | { 72 | if (other == null || other.m_Name == null) 73 | { 74 | return 0; 75 | } 76 | 77 | return -1; 78 | } 79 | 80 | if (other == null || other.m_Name == null) 81 | { 82 | return 1; 83 | } 84 | 85 | return String.Compare(m_Name, other.m_Name, StringComparison.Ordinal); 86 | } 87 | } 88 | } -------------------------------------------------------------------------------- /Scripts/Runtime/Logging/Libraries/SerializableSystemType.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ae8c4ebf93c39364794b7c6671fd7df8 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Runtime/Logging/SignalLog.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) 2020 Supyrb. All rights reserved. 4 | // 5 | // 6 | // Johannes Deml 7 | // public@deml.io 8 | // 9 | // -------------------------------------------------------------------------------------------------------------------- 10 | 11 | using System; 12 | using System.Collections.Generic; 13 | using UnityEngine.Assertions; 14 | 15 | namespace Supyrb 16 | { 17 | public class SignalLog 18 | { 19 | public delegate void LogDelegate(SignalLogEntry logEntry); 20 | public event LogDelegate OnNewSignalLog; 21 | 22 | private bool subscribed; 23 | private readonly List log; 24 | private readonly Dictionary lastDispatch; 25 | 26 | private static SignalLog _instance; 27 | 28 | public static SignalLog Instance 29 | { 30 | get 31 | { 32 | if (_instance == null) 33 | { 34 | _instance = new SignalLog(); 35 | } 36 | 37 | return _instance; 38 | } 39 | } 40 | 41 | private SignalLog() 42 | { 43 | log = new List(); 44 | lastDispatch = new Dictionary(); 45 | subscribed = false; 46 | } 47 | 48 | public void Subscribe() 49 | { 50 | if (subscribed) 51 | { 52 | return; 53 | } 54 | 55 | Signals.OnSignalDispatch += OnSignalDispatch; 56 | subscribed = true; 57 | } 58 | 59 | public void Unsubscribe() 60 | { 61 | if (!subscribed) 62 | { 63 | return; 64 | } 65 | 66 | Signals.OnSignalDispatch -= OnSignalDispatch; 67 | subscribed = false; 68 | } 69 | 70 | public SignalLogEntry GetLastOccurenceOf(Type type) 71 | { 72 | return lastDispatch.TryGetValue(type, out SignalLogEntry item) ? item : null; 73 | } 74 | 75 | public SignalLogEntry GetLastEntry() 76 | { 77 | if (log.Count == 0) 78 | { 79 | return null; 80 | } 81 | 82 | return log[log.Count - 1]; 83 | } 84 | 85 | public void Clear() 86 | { 87 | log.Clear(); 88 | lastDispatch.Clear(); 89 | } 90 | 91 | private void OnSignalDispatch(ASignal signal, string memberName, string sourceFilePath, int sourceLineNumber) 92 | { 93 | var signalLogItem = new SignalLogEntry(signal, memberName, sourceFilePath, sourceLineNumber); 94 | log.Add(signalLogItem); 95 | lastDispatch[signalLogItem.SignalType.SystemType] = signalLogItem; 96 | 97 | if (OnNewSignalLog != null) 98 | { 99 | OnNewSignalLog(signalLogItem); 100 | } 101 | } 102 | 103 | public bool GetLogEntriesForType(Type type, ref List signalLog) 104 | { 105 | if (!lastDispatch.ContainsKey(type)) 106 | { 107 | return false; 108 | } 109 | 110 | var lastLogEntry = lastDispatch[type]; 111 | SignalLogEntry lastListEntry = null; 112 | if (signalLog.Count > 0) 113 | { 114 | lastListEntry = signalLog[signalLog.Count - 1]; 115 | } 116 | 117 | if (lastListEntry == lastLogEntry) 118 | { 119 | return false; 120 | } 121 | 122 | var startProcessingIndex = 0; 123 | if (lastListEntry != null) 124 | { 125 | startProcessingIndex = log.IndexOf(lastListEntry) + 1; 126 | Assert.IsTrue(startProcessingIndex > 0); 127 | } 128 | 129 | for (var i = startProcessingIndex; i < log.Count; i++) 130 | { 131 | var entry = log[i]; 132 | if (entry.SignalType.SystemType == type) 133 | { 134 | signalLog.Add(entry); 135 | } 136 | } 137 | 138 | return true; 139 | } 140 | } 141 | } -------------------------------------------------------------------------------- /Scripts/Runtime/Logging/SignalLog.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f332f918c07049d89ef83b7116fed6b3 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Runtime/Logging/SignalLogEntry.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) 2022 Johannes Deml. All rights reserved. 4 | // 5 | // 6 | // Johannes Deml 7 | // public@deml.io 8 | // 9 | // -------------------------------------------------------------------------------------------------------------------- 10 | 11 | using System; 12 | using System.IO; 13 | using UnityEngine; 14 | 15 | namespace Supyrb 16 | { 17 | /// 18 | /// A log entry for a dispatched signal 19 | /// This class is fully compatible with Unity's serialization system and can therefore survive script reloads 20 | /// Can be used in the editor and in builds 21 | /// 22 | [Serializable] 23 | public class SignalLogEntry 24 | { 25 | [SerializeField] 26 | public SerializableDateTime TimeStamp; 27 | [SerializeField] 28 | public float PlayDispatchTime; 29 | [SerializeField] 30 | public SerializableSystemType SignalType; 31 | [SerializeField] 32 | public string MemberName; 33 | [SerializeField] 34 | public string SourceFilePath; 35 | [SerializeField] 36 | public string SourceFileName; 37 | [SerializeField] 38 | public int SourceLineNumber; 39 | 40 | public SignalLogEntry(ASignal signalInstance, string memberName, string sourceFilePath, int sourceLineNumber) 41 | { 42 | TimeStamp = new SerializableDateTime(DateTime.Now); 43 | PlayDispatchTime = Time.time; 44 | SignalType = new SerializableSystemType(signalInstance.GetType()); 45 | MemberName = memberName; 46 | SourceFilePath = GetAssetSourceFilePath(sourceFilePath); 47 | SourceFileName = Path.GetFileNameWithoutExtension(SourceFilePath); 48 | SourceLineNumber = sourceLineNumber; 49 | } 50 | 51 | private string GetAssetSourceFilePath(string fullPath) 52 | { 53 | #if UNITY_EDITOR 54 | return fullPath.Substring(Application.dataPath.Length - "Assets".Length); 55 | #else 56 | return fullPath; 57 | #endif 58 | 59 | } 60 | } 61 | } -------------------------------------------------------------------------------- /Scripts/Runtime/Logging/SignalLogEntry.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e7cbc8665e7440069adac1bfb440eed4 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Runtime/Logging/Supyrb.Signals.Logging.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Supyrb.Signals.Logging", 3 | "rootNamespace": "", 4 | "references": [ 5 | "GUID:16f55dfd49f3b694bab70fdad220587f" 6 | ], 7 | "includePlatforms": [], 8 | "excludePlatforms": [], 9 | "allowUnsafeCode": false, 10 | "overrideReferences": false, 11 | "precompiledReferences": [], 12 | "autoReferenced": true, 13 | "defineConstraints": [], 14 | "versionDefines": [], 15 | "noEngineReferences": false 16 | } -------------------------------------------------------------------------------- /Scripts/Runtime/Logging/Supyrb.Signals.Logging.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a93bee54bb381744cbdd02ee23fe7a67 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Scripts/Runtime/OrderedList.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) 2019 Supyrb. All rights reserved. 4 | // 5 | // 6 | // Johannes Deml 7 | // send@johannesdeml.com 8 | // 9 | // -------------------------------------------------------------------------------------------------------------------- 10 | 11 | using System.Collections.Generic; 12 | 13 | namespace Supyrb 14 | { 15 | public class OrderedList 16 | { 17 | private readonly List sortedOrders; 18 | private readonly List values; 19 | private readonly bool uniqueValuesOnly; 20 | private readonly int defaultOrderValue; 21 | private int defaultOrderNextIndex; 22 | 23 | public OrderedList(bool uniqueValuesOnly) : this(uniqueValuesOnly, 0) 24 | {} 25 | 26 | /// 27 | /// Ordered list with an order value that does not have to be unique and a value can be unique 28 | /// 29 | /// If values should be unique 30 | /// default sorting value - does not need search when adding value 31 | public OrderedList(bool uniqueValuesOnly, int defaultOder) 32 | { 33 | this.uniqueValuesOnly = uniqueValuesOnly; 34 | this.sortedOrders = new List(); 35 | this.values = new List(); 36 | this.defaultOrderValue = defaultOder; 37 | this.defaultOrderNextIndex = 0; 38 | } 39 | 40 | public int Count 41 | { 42 | get { return values.Count; } 43 | } 44 | 45 | public T this[int index] 46 | { 47 | get { return values[index]; } 48 | set { values[index] = value; } 49 | } 50 | 51 | public int GetSortOrderForIndex(int index) 52 | { 53 | return sortedOrders[index]; 54 | } 55 | 56 | /// 57 | /// Add an item to the ordered list with order 58 | /// 59 | /// Value to be added 60 | /// The index at which the value was added, or -1 if the value was already in the list and only unique values are allowed 61 | public int Add(T value) 62 | { 63 | return Add(defaultOrderValue, value); 64 | } 65 | 66 | /// 67 | /// Add an item to the ordered list 68 | /// 69 | /// Value after which the list is sorted (Ascending) 70 | /// Value to be added 71 | /// The index at which the value was added, or -1 if the value was already in the list and only unique values are allowed 72 | public int Add(int order, T value) 73 | { 74 | if (uniqueValuesOnly && Contains(value)) 75 | { 76 | return -1; 77 | } 78 | 79 | var index = order == defaultOrderValue ? defaultOrderNextIndex : GetSortedIndexFor(order); 80 | sortedOrders.Insert(index, order); 81 | values.Insert(index, value); 82 | if(order <= defaultOrderNextIndex) 83 | { 84 | defaultOrderNextIndex++; 85 | } 86 | return index; 87 | } 88 | 89 | /// 90 | /// Remove an item from the ordered list 91 | /// 92 | /// Item to remove 93 | /// The index at which the item was removed, or -1 if the list didn't contain the item 94 | public int Remove(T value) 95 | { 96 | var index = IndexOf(value); 97 | if (index == -1) 98 | { 99 | return -1; 100 | } 101 | 102 | sortedOrders.RemoveAt(index); 103 | values.RemoveAt(index); 104 | if(index < defaultOrderNextIndex) 105 | { 106 | defaultOrderNextIndex--; 107 | } 108 | return index; 109 | } 110 | 111 | public int IndexOf(T value) 112 | { 113 | return values.IndexOf(value); 114 | } 115 | 116 | public void Clear() 117 | { 118 | sortedOrders.Clear(); 119 | values.Clear(); 120 | defaultOrderNextIndex = 0; 121 | } 122 | 123 | public bool Contains(T item) 124 | { 125 | return IndexOf(item) != -1; 126 | } 127 | 128 | /// 129 | /// Returns the index after the last value of order 130 | /// This way new entries with the same order value will be added at the end of the entries 131 | /// 132 | /// Order value to search for 133 | /// 134 | private int GetSortedIndexFor(int order) 135 | { 136 | var low = 0; 137 | var high = this.sortedOrders.Count; 138 | while (low < high) 139 | { 140 | var mid = (low + high) >> 1; 141 | if (this.sortedOrders[mid] > order) 142 | { 143 | high = mid; 144 | } 145 | else 146 | { 147 | low = mid + 1; 148 | } 149 | } 150 | 151 | return low; 152 | } 153 | 154 | public IEnumerator GetEnumerator() 155 | { 156 | return values.GetEnumerator(); 157 | } 158 | } 159 | } -------------------------------------------------------------------------------- /Scripts/Runtime/OrderedList.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 84763a5442b046eeb40a7f1e81edef21 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Runtime/Signal.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) 2019 Supyrb. All rights reserved. 4 | // 5 | // 6 | // Johannes Deml 7 | // public@deml.io 8 | // 9 | // -------------------------------------------------------------------------------------------------------------------- 10 | 11 | using System; 12 | using System.Runtime.CompilerServices; 13 | 14 | namespace Supyrb 15 | { 16 | public class Signal : ASignalAction 17 | { 18 | 19 | /// 20 | /// Dispatch the signal to the listeners in their defined order until the signal 21 | /// is consumed () or paused () 22 | /// 23 | public void Dispatch([CallerMemberName] string memberName = "", 24 | [CallerFilePath] string sourceFilePath = "", 25 | [CallerLineNumber] int sourceLineNumber = 0) 26 | { 27 | BeginSignalProfilerSample("Dispatch Signal"); 28 | 29 | Signals.LogSignalDispatch(this, memberName, sourceFilePath, sourceLineNumber); 30 | StartDispatch(); 31 | 32 | EndSignalProfilerSample(); 33 | } 34 | 35 | protected override void Invoke(int index) 36 | { 37 | listeners[index].Invoke(); 38 | } 39 | } 40 | 41 | public class Signal : ASignalAction> 42 | { 43 | private T context0; 44 | 45 | /// 46 | /// Dispatch the signal to the listeners in their defined order until the signal 47 | /// is consumed () or paused () 48 | /// 49 | public void Dispatch(T context0, 50 | [CallerMemberName] string memberName = "", 51 | [CallerFilePath] string sourceFilePath = "", 52 | [CallerLineNumber] int sourceLineNumber = 0) 53 | { 54 | BeginSignalProfilerSample("Dispatch Signal"); 55 | 56 | this.context0 = context0; 57 | Signals.LogSignalDispatch(this, memberName, sourceFilePath, sourceLineNumber); 58 | StartDispatch(); 59 | 60 | EndSignalProfilerSample(); 61 | } 62 | 63 | protected override void Invoke(int index) 64 | { 65 | listeners[index].Invoke(context0); 66 | } 67 | 68 | protected override void OnFinish() 69 | { 70 | base.OnFinish(); 71 | context0 = default(T); 72 | } 73 | } 74 | 75 | public class Signal : ASignalAction> 76 | { 77 | private T context0; 78 | private U context1; 79 | 80 | /// 81 | /// Dispatch the signal to the listeners in their defined order until the signal 82 | /// is consumed () or paused () 83 | /// 84 | public void Dispatch(T context0, U context1, 85 | [CallerMemberName] string memberName = "", 86 | [CallerFilePath] string sourceFilePath = "", 87 | [CallerLineNumber] int sourceLineNumber = 0) 88 | { 89 | BeginSignalProfilerSample("Dispatch Signal"); 90 | 91 | this.context0 = context0; 92 | this.context1 = context1; 93 | Signals.LogSignalDispatch(this, memberName, sourceFilePath, sourceLineNumber); 94 | StartDispatch(); 95 | 96 | EndSignalProfilerSample(); 97 | } 98 | 99 | protected override void Invoke(int index) 100 | { 101 | listeners[index].Invoke(context0, context1); 102 | } 103 | 104 | protected override void OnFinish() 105 | { 106 | base.OnFinish(); 107 | context0 = default(T); 108 | context1 = default(U); 109 | } 110 | } 111 | 112 | public class Signal : ASignalAction> 113 | { 114 | private T context0; 115 | private U context1; 116 | private V context2; 117 | 118 | /// 119 | /// Dispatch the signal to the listeners in their defined order until the signal 120 | /// is consumed () or paused () 121 | /// 122 | public void Dispatch(T context0, U context1, V context2, 123 | [CallerMemberName] string memberName = "", 124 | [CallerFilePath] string sourceFilePath = "", 125 | [CallerLineNumber] int sourceLineNumber = 0) 126 | { 127 | BeginSignalProfilerSample("Dispatch Signal"); 128 | 129 | this.context0 = context0; 130 | this.context1 = context1; 131 | this.context2 = context2; 132 | Signals.LogSignalDispatch(this, memberName, sourceFilePath, sourceLineNumber); 133 | StartDispatch(); 134 | 135 | EndSignalProfilerSample(); 136 | } 137 | 138 | protected override void Invoke(int index) 139 | { 140 | listeners[index].Invoke(context0, context1, context2); 141 | } 142 | 143 | protected override void OnFinish() 144 | { 145 | base.OnFinish(); 146 | context0 = default(T); 147 | context1 = default(U); 148 | context2 = default(V); 149 | } 150 | } 151 | } -------------------------------------------------------------------------------- /Scripts/Runtime/Signal.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: cff5c035f3f69f541a821d81c47636f0 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Runtime/Signals.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) 2019 Supyrb. All rights reserved. 4 | // 5 | // 6 | // Johannes Deml 7 | // public@deml.io 8 | // 9 | // 10 | // Yanko Oliveira 11 | // https://github.com/yankooliveira 12 | // 13 | // 14 | // Inspired by 15 | // Signals by Yanko Oliveira 16 | // https://github.com/yankooliveira/signals 17 | // and 18 | // JS-Signas by Miller Medeiros 19 | // https://github.com/millermedeiros/js-signals 20 | // 31 | /// Global Signal hub, this is the most common access point to retrieve a signal instance 32 | /// 33 | public static class Signals 34 | { 35 | public delegate void SignalDelegate(ASignal signal, string memberName, string sourceFilePath, int sourceLineNumber); 36 | public static event SignalDelegate OnSignalDispatch; 37 | private static readonly SignalHub signalHub = new SignalHub(); 38 | 39 | /// 40 | /// Get the Signal for a certain class. If the signal is not yet registered in the hub it will be created. 41 | /// 42 | /// Type of the Signal to retrieve 43 | /// An instance of the Signal of type T 44 | public static T Get() where T : ISignal 45 | { 46 | return signalHub.Get(); 47 | } 48 | 49 | /// 50 | /// Get the Signal for a certain class. If the signal is not yet registered in the hub it will be created. 51 | /// 52 | /// Type of the Signal to retrieve 53 | /// An instance of the Signal of type signalType 54 | public static ISignal Get(Type signalType) 55 | { 56 | return signalHub.Get(signalType); 57 | } 58 | 59 | /// 60 | /// Get the Signal for a certain class. If the signal is not yet registered in the hub it will be created. 61 | /// 62 | /// The output argument for which the reference will be set 63 | /// The signal type to retrieve 64 | public static void Get(out T reference) where T : ISignal 65 | { 66 | reference = Get(); 67 | } 68 | 69 | /// 70 | /// The number of registered signals 71 | /// 72 | public static int Count 73 | { 74 | get { return signalHub.Count; } 75 | } 76 | 77 | /// 78 | /// Removes all registered signals 79 | /// 80 | public static void Clear() 81 | { 82 | signalHub.Clear(); 83 | OnSignalDispatch = null; 84 | } 85 | 86 | [Conditional("SIGNALS_DEBUG"), Conditional("UNITY_EDITOR")] 87 | internal static void LogSignalDispatch(ASignal signal, string memberName, string sourceFilePath, int sourceLineNumber) 88 | { 89 | Profiler.BeginSample("LogDispatchSignal"); 90 | OnSignalDispatch?.Invoke(signal, memberName, sourceFilePath, sourceLineNumber); 91 | Profiler.EndSample(); 92 | } 93 | } 94 | 95 | public class SignalHub 96 | { 97 | private readonly Dictionary signals = new Dictionary(); 98 | 99 | /// 100 | /// Getter for a signal of a given type 101 | /// 102 | /// Type of the Signal to retrieve 103 | /// The proper signal binding 104 | public ISignal Get(Type signalType) 105 | { 106 | ISignal signal; 107 | 108 | if (signals.TryGetValue(signalType, out signal)) 109 | { 110 | return signal; 111 | } 112 | 113 | return Bind(signalType); 114 | } 115 | 116 | /// 117 | /// Getter for a signal of a given type 118 | /// 119 | /// Type of signal 120 | /// The proper signal binding 121 | public T Get() where T : ISignal 122 | { 123 | var signalType = typeof(T); 124 | return (T) Get(signalType); 125 | } 126 | 127 | /// 128 | /// The number of registered signals in the hub 129 | /// 130 | public int Count 131 | { 132 | get { return signals.Count; } 133 | } 134 | 135 | /// 136 | /// Removes all signals from the hub 137 | /// 138 | public void Clear() 139 | { 140 | signals.Clear(); 141 | } 142 | 143 | private ISignal Bind(Type signalType) 144 | { 145 | ISignal signal = (ISignal) Activator.CreateInstance(signalType); 146 | signals.Add(signalType, signal); 147 | return signal; 148 | } 149 | } 150 | } -------------------------------------------------------------------------------- /Scripts/Runtime/Signals.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 35327fca3bc946d7a15805d3ad33cca9 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Runtime/Supyrb.Signals.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Supyrb.Signals", 3 | "references": [], 4 | "optionalUnityReferences": [], 5 | "includePlatforms": [], 6 | "excludePlatforms": [], 7 | "allowUnsafeCode": false, 8 | "overrideReferences": false, 9 | "precompiledReferences": [], 10 | "autoReferenced": true, 11 | "defineConstraints": [], 12 | "versionDefines": [] 13 | } -------------------------------------------------------------------------------- /Scripts/Runtime/Supyrb.Signals.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 16f55dfd49f3b694bab70fdad220587f 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Tests.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: deea80fc10d15864b9af908dc1578fcd 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Tests/NoArgumentSignalTests.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) 2020 Supyrb. All rights reserved. 4 | // 5 | // 6 | // Johannes Deml 7 | // public@deml.io 8 | // 9 | // -------------------------------------------------------------------------------------------------------------------- 10 | 11 | using NUnit.Framework; 12 | 13 | namespace Supyrb.Tests 14 | { 15 | [TestFixture] 16 | public class NoArgumentSignalTests : ASignalTests 17 | { 18 | protected override void Dispatch() 19 | { 20 | signal.Dispatch(); 21 | } 22 | 23 | protected override void AddListenerA(int order = 0) 24 | { 25 | signal.AddListener(OnListenerAWrapper, order); 26 | } 27 | 28 | protected override void RemoveListenerA() 29 | { 30 | signal.RemoveListener(OnListenerAWrapper); 31 | } 32 | 33 | protected override void AddListenerB(int order = 0) 34 | { 35 | signal.AddListener(OnListenerBWrapper, order); 36 | } 37 | 38 | protected override void RemoveListenerB() 39 | { 40 | signal.RemoveListener(OnListenerBWrapper); 41 | } 42 | 43 | protected override void AddListenerC(int order = 0) 44 | { 45 | signal.AddListener(OnListenerCWrapper, order); 46 | } 47 | 48 | protected override void RemoveListenerC() 49 | { 50 | signal.RemoveListener(OnListenerCWrapper); 51 | } 52 | 53 | protected override void AddPauseListener(int order = 0) 54 | { 55 | signal.AddListener(OnPauseListenerWrapper, order); 56 | } 57 | 58 | protected override void AddConsumeListener(int order = 0) 59 | { 60 | signal.AddListener(OnConsumeListenerWrapper, order); 61 | } 62 | 63 | protected override void AddUnsubscribeSelfListener(int order = 0) 64 | { 65 | signal.AddListener(OnUnsubscribeSelfListener, order); 66 | } 67 | 68 | protected override void AddListenerAOnCallAtMinusTen(int order = 0) 69 | { 70 | signal.AddListener(OnAddListenerAAtMinusTen, order); 71 | } 72 | 73 | protected override void RemoveListenerAOnCall(int order = 0) 74 | { 75 | signal.AddListener(OnRemoveListenerA, order); 76 | } 77 | 78 | protected override void AddListenerBOnCallAtZero(int order = 0) 79 | { 80 | signal.AddListener(OnAddListenerBAtZero, order); 81 | } 82 | 83 | protected override void RemoveListenerBOnCall(int order = 0) 84 | { 85 | signal.AddListener(OnRemoveListenerB, order); 86 | } 87 | 88 | private void OnListenerAWrapper() 89 | { 90 | OnListenerA(); 91 | } 92 | 93 | private void OnListenerBWrapper() 94 | { 95 | OnListenerB(); 96 | } 97 | 98 | private void OnListenerCWrapper() 99 | { 100 | OnListenerC(); 101 | } 102 | 103 | private void OnPauseListenerWrapper() 104 | { 105 | OnPauseListener(); 106 | } 107 | 108 | private void OnConsumeListenerWrapper() 109 | { 110 | OnConsumeListener(); 111 | } 112 | 113 | private void OnUnsubscribeSelfListener() 114 | { 115 | signal.RemoveListener(OnUnsubscribeSelfListener); 116 | } 117 | 118 | 119 | private void OnAddListenerAAtMinusTen() 120 | { 121 | signal.AddListener(OnListenerAWrapper, -10); 122 | } 123 | 124 | private void OnAddListenerBAtZero() 125 | { 126 | signal.AddListener(OnListenerBWrapper, 0); 127 | } 128 | 129 | private void OnRemoveListenerA() 130 | { 131 | signal.RemoveListener(OnListenerAWrapper); 132 | } 133 | 134 | private void OnRemoveListenerB() 135 | { 136 | signal.RemoveListener(OnListenerBWrapper); 137 | } 138 | } 139 | } -------------------------------------------------------------------------------- /Tests/NoArgumentSignalTests.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9a61402b2d314578bb747b874ad192ee 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Tests/OneArgumentSignalTests.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) 2020 Supyrb. All rights reserved. 4 | // 5 | // 6 | // Johannes Deml 7 | // public@deml.io 8 | // 9 | // -------------------------------------------------------------------------------------------------------------------- 10 | 11 | using NUnit.Framework; 12 | 13 | namespace Supyrb.Tests 14 | { 15 | [TestFixture] 16 | public class OneArgumentSignalTests : ASignalTests 17 | { 18 | private const int SignalDispatchValue = 0; 19 | 20 | protected override void Dispatch() 21 | { 22 | signal.Dispatch(SignalDispatchValue); 23 | } 24 | 25 | protected override void AddListenerA(int order = 0) 26 | { 27 | signal.AddListener(OnListenerAWrapper, order); 28 | } 29 | 30 | protected override void RemoveListenerA() 31 | { 32 | signal.RemoveListener(OnListenerAWrapper); 33 | } 34 | 35 | protected override void AddListenerB(int order = 0) 36 | { 37 | signal.AddListener(OnListenerBWrapper, order); 38 | } 39 | 40 | protected override void RemoveListenerB() 41 | { 42 | signal.RemoveListener(OnListenerBWrapper); 43 | } 44 | 45 | protected override void AddListenerC(int order = 0) 46 | { 47 | signal.AddListener(OnListenerCWrapper, order); 48 | } 49 | 50 | protected override void RemoveListenerC() 51 | { 52 | signal.RemoveListener(OnListenerCWrapper); 53 | } 54 | 55 | protected override void AddPauseListener(int order = 0) 56 | { 57 | signal.AddListener(OnPauseListenerWrapper, order); 58 | } 59 | 60 | protected override void AddConsumeListener(int order = 0) 61 | { 62 | signal.AddListener(OnConsumeListenerWrapper, order); 63 | } 64 | 65 | protected override void AddUnsubscribeSelfListener(int order = 0) 66 | { 67 | signal.AddListener(OnUnsubscribeSelfListener, order); 68 | } 69 | 70 | protected override void AddListenerAOnCallAtMinusTen(int order = 0) 71 | { 72 | signal.AddListener(OnAddListenerAAtMinusTen, order); 73 | } 74 | 75 | protected override void RemoveListenerAOnCall(int order = 0) 76 | { 77 | signal.AddListener(OnRemoveListenerA, order); 78 | } 79 | 80 | protected override void AddListenerBOnCallAtZero(int order = 0) 81 | { 82 | signal.AddListener(OnAddListenerBAtZero, order); 83 | } 84 | 85 | protected override void RemoveListenerBOnCall(int order = 0) 86 | { 87 | signal.AddListener(OnRemoveListenerB, order); 88 | } 89 | 90 | private void OnListenerAWrapper(int signalValue) 91 | { 92 | OnListenerA(); 93 | } 94 | 95 | private void OnListenerBWrapper(int signalValue) 96 | { 97 | OnListenerB(); 98 | } 99 | 100 | private void OnPauseListenerWrapper(int signalValue) 101 | { 102 | OnPauseListener(); 103 | } 104 | 105 | private void OnConsumeListenerWrapper(int signalValue) 106 | { 107 | OnConsumeListener(); 108 | } 109 | 110 | private void OnListenerCWrapper(int signalValue) 111 | { 112 | OnListenerC(); 113 | } 114 | 115 | private void OnUnsubscribeSelfListener(int signalValue) 116 | { 117 | signal.RemoveListener(OnUnsubscribeSelfListener); 118 | } 119 | 120 | 121 | private void OnAddListenerAAtMinusTen(int signalValue) 122 | { 123 | signal.AddListener(OnListenerAWrapper, -10); 124 | } 125 | 126 | private void OnAddListenerBAtZero(int signalValue) 127 | { 128 | signal.AddListener(OnListenerBWrapper, 0); 129 | } 130 | 131 | private void OnRemoveListenerA(int signalValue) 132 | { 133 | signal.RemoveListener(OnListenerAWrapper); 134 | } 135 | 136 | private void OnRemoveListenerB(int signalValue) 137 | { 138 | signal.RemoveListener(OnListenerBWrapper); 139 | } 140 | } 141 | } -------------------------------------------------------------------------------- /Tests/OneArgumentSignalTests.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ba2640c5acaa4400802a0ccb57044290 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Tests/OrderedListTests.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) 2023 Supyrb. All rights reserved. 4 | // 5 | // 6 | // Johannes Deml 7 | // public@deml.io 8 | // 9 | // -------------------------------------------------------------------------------------------------------------------- 10 | 11 | using NUnit.Framework; 12 | 13 | namespace Supyrb.Tests 14 | { 15 | [TestFixture] 16 | [Category("Signals")] 17 | public class OrderedListTests 18 | { 19 | [Test] 20 | public void OrderedListDefaultValueAdd() 21 | { 22 | var orderedList = new OrderedList(false, 0); 23 | 24 | Assert.AreEqual(0, orderedList.Add(0, "firstDefault")); 25 | Assert.AreEqual(1, orderedList.Add(0, "secondDefault")); 26 | Assert.AreEqual(0, orderedList.Add(-10, "priorityItem")); 27 | Assert.AreEqual(3, orderedList.Add(0, "thirdDefault")); 28 | Assert.AreEqual(4, orderedList.Add(10, "lateItem")); 29 | Assert.AreEqual(4, orderedList.Add(0, "forthDefault")); 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /Tests/OrderedListTests.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9dd46606331e4dd41bb9d80a5a5f1c87 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Tests/SignalRegistryTests.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) 2019 Supyrb. All rights reserved. 4 | // 5 | // 6 | // Johannes Deml 7 | // public@deml.io 8 | // 9 | // -------------------------------------------------------------------------------------------------------------------- 10 | 11 | using NUnit.Framework; 12 | 13 | namespace Supyrb.Tests 14 | { 15 | /// 16 | /// Tests the functionality of class Signals 17 | /// 18 | [TestFixture] 19 | [Category("Signal Registry")] 20 | public class SignalRegistryTests 21 | { 22 | [SetUp] 23 | [OneTimeTearDown] 24 | public void Setup() 25 | { 26 | Signals.Clear(); 27 | } 28 | 29 | [Test] 30 | public void GetSignalFromRegistryTest() 31 | { 32 | TestSignal testSignal; 33 | Signals.Get(out testSignal); 34 | Assert.NotNull(testSignal); 35 | } 36 | 37 | [Test] 38 | public void SignalRegistryClearTest() 39 | { 40 | Signals.Get(); 41 | Assert.IsTrue(Signals.Count == 1); 42 | Signals.Clear(); 43 | Assert.IsTrue(Signals.Count == 0); 44 | } 45 | 46 | [Test] 47 | public void SignalRegistryCountTest() 48 | { 49 | Signals.Clear(); 50 | Signals.Get(); 51 | Assert.IsTrue(Signals.Count == 1); 52 | Signals.Get(); 53 | Assert.IsTrue(Signals.Count == 1); 54 | Signals.Get(); 55 | Assert.IsTrue(Signals.Count == 2); 56 | } 57 | 58 | [Test] 59 | public void SignalRegistryGetMethodsTest() 60 | { 61 | Signals.Clear(); 62 | TestSignal testSignal0; 63 | TestSignal testSignal1; 64 | TestSignal testSignal2; 65 | 66 | testSignal0 = Signals.Get(); 67 | Signals.Get(out testSignal1); 68 | testSignal2 = (TestSignal) Signals.Get(typeof(TestSignal)); 69 | 70 | Assert.IsTrue(testSignal0 == testSignal1); 71 | Assert.IsTrue(testSignal0 == testSignal2); 72 | } 73 | } 74 | } -------------------------------------------------------------------------------- /Tests/SignalRegistryTests.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1fe33fc3e0264b93b384b30271f72e22 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Tests/SignalTests.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) 2019 Supyrb. All rights reserved. 4 | // 5 | // 6 | // Johannes Deml 7 | // public@deml.io 8 | // 9 | // -------------------------------------------------------------------------------------------------------------------- 10 | 11 | using System; 12 | using System.Collections.Generic; 13 | using NUnit.Framework; 14 | 15 | namespace Supyrb.Tests 16 | { 17 | /// 18 | /// Tests the functionality of class Signal 19 | /// 20 | [TestFixture] 21 | [Category("Signals")] 22 | public abstract class ASignalTests where T: ASignal 23 | { 24 | protected T signal; 25 | private readonly List callLog = new List(); 26 | 27 | [OneTimeSetUp] 28 | public void InitialSetup() 29 | { 30 | callLog.Clear(); 31 | Signals.Clear(); 32 | Signals.Get(out signal); 33 | } 34 | 35 | [OneTimeTearDown] 36 | public void FinalTearDown() 37 | { 38 | Signals.Clear(); 39 | } 40 | 41 | [TearDown] 42 | public void TearDown() 43 | { 44 | callLog.Clear(); 45 | signal.Clear(); 46 | } 47 | 48 | [Test] 49 | public void ListenerOrderTest() 50 | { 51 | AddListenerA(-10); 52 | AddListenerB(0); 53 | AddListenerC(10); 54 | 55 | Dispatch(); 56 | 57 | Assert.AreEqual("A,B,C", string.Join(",", callLog)); 58 | Assert.AreEqual(3, signal.ListenerCount); 59 | } 60 | 61 | [Test] 62 | public void RemoveListenerTest() 63 | { 64 | AddListenerA(-10); 65 | AddListenerB(0); 66 | AddListenerC(10); 67 | 68 | RemoveListenerA(); 69 | Dispatch(); 70 | RemoveListenerB(); 71 | Dispatch(); 72 | 73 | Assert.AreEqual("B,C,C", string.Join(",", callLog)); 74 | Assert.AreEqual(1, signal.ListenerCount); 75 | } 76 | 77 | [Test] 78 | public void PauseContinueSignalTest() 79 | { 80 | AddListenerA(-10); 81 | AddPauseListener(0); 82 | AddListenerB(10); 83 | 84 | Dispatch(); 85 | 86 | Assert.IsTrue(callLog.Contains("A")); 87 | Assert.IsFalse(callLog.Contains("B")); 88 | 89 | ContinueSignal(); 90 | 91 | Assert.AreEqual("A,Pause,Continue,B", string.Join(",", callLog)); 92 | } 93 | 94 | [Test] 95 | public void InvalidContinueSignalTest() 96 | { 97 | AddListenerA(-10); 98 | AddListenerB(0); 99 | 100 | ContinueSignal(); 101 | 102 | Assert.IsFalse(callLog.Contains("A")); 103 | Assert.IsFalse(callLog.Contains("B")); 104 | } 105 | 106 | [Test] 107 | public void ConsumeSignalTest() 108 | { 109 | AddListenerA(-10); 110 | AddConsumeListener(0); 111 | AddListenerB(10); 112 | 113 | Dispatch(); 114 | 115 | Assert.IsTrue(callLog.Contains("A")); 116 | Assert.IsFalse(callLog.Contains("B")); 117 | } 118 | 119 | [Test] 120 | public void RemoveCurrentListenerWhileDispatching() 121 | { 122 | AddListenerA(-10); 123 | AddUnsubscribeSelfListener(0); 124 | AddListenerB(10); 125 | 126 | Dispatch(); 127 | 128 | Assert.AreEqual("A,B", string.Join(",", callLog)); 129 | Assert.AreEqual(2, signal.ListenerCount); 130 | } 131 | 132 | [Test] 133 | public void RemovePreviousListenerWhileDispatching() 134 | { 135 | AddListenerA(-10); 136 | RemoveListenerAOnCall(0); 137 | AddListenerB(10); 138 | 139 | Dispatch(); 140 | 141 | Assert.AreEqual("A,B", string.Join(",", callLog)); 142 | Assert.AreEqual(2, signal.ListenerCount); 143 | } 144 | 145 | [Test] 146 | public void RemoveNextListenerWhileDispatching() 147 | { 148 | AddListenerA(-10); 149 | RemoveListenerBOnCall(0); 150 | AddListenerB(10); 151 | 152 | Dispatch(); 153 | 154 | Assert.IsTrue(callLog.Contains("A")); 155 | Assert.IsFalse(callLog.Contains("B")); 156 | Assert.AreEqual(2, signal.ListenerCount); 157 | } 158 | 159 | [Test] 160 | public void RemoveNotExistingListener() 161 | { 162 | RemoveListenerA(); 163 | Dispatch(); 164 | 165 | Assert.AreEqual(0, signal.ListenerCount); 166 | } 167 | 168 | [Test] 169 | public void AddListenerTwice() 170 | { 171 | AddListenerA(-10); 172 | // Should be ignored 173 | AddListenerA(0); 174 | Dispatch(); 175 | 176 | Assert.AreEqual("A", string.Join(",", callLog)); 177 | Assert.AreEqual(1, signal.ListenerCount); 178 | } 179 | 180 | /// 181 | /// Listener with same priority should be added at the end of the list of that priority 182 | /// Therefore it should be called when added at the same priority right away 183 | /// 184 | [Test] 185 | public void AddSameOrderListenerWhileDispatching() 186 | { 187 | AddListenerAOnCallAtMinusTen(-10); 188 | AddListenerB(0); 189 | Dispatch(); 190 | 191 | Assert.AreEqual("A,B", string.Join(",", callLog)); 192 | Assert.AreEqual(3, signal.ListenerCount); 193 | 194 | Dispatch(); 195 | 196 | Assert.AreEqual("A,B,A,B", string.Join(",", callLog)); 197 | Assert.AreEqual(3, signal.ListenerCount); 198 | } 199 | 200 | [Test] 201 | public void AddLowerOrderListenerWhileDispatching() 202 | { 203 | AddListenerAOnCallAtMinusTen(-5); 204 | AddListenerB(0); 205 | Dispatch(); 206 | 207 | Assert.AreEqual("B", string.Join(",", callLog)); 208 | Assert.AreEqual(3, signal.ListenerCount); 209 | 210 | Dispatch(); 211 | 212 | Assert.AreEqual("B,A,B", string.Join(",", callLog)); 213 | Assert.AreEqual(3, signal.ListenerCount); 214 | } 215 | 216 | [Test] 217 | public void AddHigherOrderListenerWhileDispatching() 218 | { 219 | AddListenerA(-10); 220 | AddListenerBOnCallAtZero(-5); 221 | Dispatch(); 222 | 223 | Assert.AreEqual("A,B", string.Join(",", callLog)); 224 | Assert.IsTrue(signal.ListenerCount == 3); 225 | } 226 | 227 | protected abstract void Dispatch(); 228 | protected abstract void AddListenerA(int order = 0); 229 | protected abstract void RemoveListenerA(); 230 | protected abstract void AddListenerB(int order = 0); 231 | protected abstract void RemoveListenerB(); 232 | protected abstract void AddListenerC(int order = 0); 233 | protected abstract void RemoveListenerC(); 234 | protected abstract void AddPauseListener(int order = 0); 235 | protected abstract void AddConsumeListener(int order = 0); 236 | 237 | protected abstract void AddUnsubscribeSelfListener(int order = 0); 238 | 239 | protected abstract void AddListenerAOnCallAtMinusTen(int order = 0); 240 | protected abstract void RemoveListenerAOnCall(int order = 0); 241 | 242 | protected abstract void AddListenerBOnCallAtZero(int order = 0); 243 | protected abstract void RemoveListenerBOnCall(int order = 0); 244 | 245 | protected void OnListenerA() 246 | { 247 | callLog.Add("A"); 248 | } 249 | 250 | protected void OnListenerB() 251 | { 252 | callLog.Add("B"); 253 | } 254 | 255 | protected void OnListenerC() 256 | { 257 | callLog.Add("C"); 258 | } 259 | 260 | protected void OnConsumeListener() 261 | { 262 | callLog.Add("Consume"); 263 | signal.Consume(); 264 | } 265 | 266 | protected void OnPauseListener() 267 | { 268 | callLog.Add("Pause"); 269 | signal.Pause(); 270 | } 271 | 272 | private void ContinueSignal() 273 | { 274 | callLog.Add("Continue"); 275 | signal.Continue(); 276 | } 277 | } 278 | } -------------------------------------------------------------------------------- /Tests/SignalTests.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 13c7eefde8004bec9a46957167ded801 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Tests/Signals.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ca19139c76994c93a1463e5a04e49a2c 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Tests/Signals/TestSignal.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) 2019 Supyrb. All rights reserved. 4 | // 5 | // 6 | // Johannes Deml 7 | // public@deml.io 8 | // 9 | // -------------------------------------------------------------------------------------------------------------------- 10 | 11 | namespace Supyrb 12 | { 13 | public class TestSignal : Signal 14 | { 15 | } 16 | } -------------------------------------------------------------------------------- /Tests/Signals/TestSignal.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 688fc94f45f843119ac9e8571e9f9f43 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Tests/Signals/TestSignalInt.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) 2019 Supyrb. All rights reserved. 4 | // 5 | // 6 | // Johannes Deml 7 | // public@deml.io 8 | // 9 | // -------------------------------------------------------------------------------------------------------------------- 10 | 11 | namespace Supyrb 12 | { 13 | public class TestSignalInt : Signal 14 | { 15 | } 16 | } -------------------------------------------------------------------------------- /Tests/Signals/TestSignalInt.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 16888026e40d4063aa336b0714ae1f3a 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Tests/Signals/TestSignalObjectStringInt.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) 2019 Supyrb. All rights reserved. 4 | // 5 | // 6 | // Johannes Deml 7 | // public@deml.io 8 | // 9 | // -------------------------------------------------------------------------------------------------------------------- 10 | 11 | namespace Supyrb 12 | { 13 | public class TestSignalObjectStringInt : Signal 14 | { 15 | } 16 | } -------------------------------------------------------------------------------- /Tests/Signals/TestSignalObjectStringInt.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 36ebdbe5f57f4249a220bcffa7b4e3d1 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Tests/Signals/TestSignalStringInt.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) 2019 Supyrb. All rights reserved. 4 | // 5 | // 6 | // Johannes Deml 7 | // public@deml.io 8 | // 9 | // -------------------------------------------------------------------------------------------------------------------- 10 | 11 | namespace Supyrb 12 | { 13 | public class TestSignalStringInt : Signal 14 | { 15 | } 16 | } -------------------------------------------------------------------------------- /Tests/Signals/TestSignalStringInt.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 85a69f3f63194bc0b4bc374b4b533ef0 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Tests/Supyrb.Signals.Tests.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Supyrb.Signals.Tests", 3 | "references": [ 4 | "Supyrb.Signals" 5 | ], 6 | "optionalUnityReferences": [ 7 | "TestAssemblies" 8 | ], 9 | "includePlatforms": [ 10 | "Editor" 11 | ], 12 | "excludePlatforms": [] 13 | } -------------------------------------------------------------------------------- /Tests/Supyrb.Signals.Tests.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d13a736a28e39234c9fb8852890a4976 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Tests/ThreeArgumentSignalTests.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) 2020 Supyrb. All rights reserved. 4 | // 5 | // 6 | // Johannes Deml 7 | // public@deml.io 8 | // 9 | // -------------------------------------------------------------------------------------------------------------------- 10 | 11 | using NUnit.Framework; 12 | 13 | namespace Supyrb.Tests 14 | { 15 | [TestFixture] 16 | public class ThreeArgumentSignalTests : ASignalTests 17 | { 18 | private const object SignalDispatchContext0 = null; 19 | private const string SignalDispatchContext1 = "Value"; 20 | private const int SignalDispatchContext2 = 0; 21 | 22 | protected override void Dispatch() 23 | { 24 | signal.Dispatch(SignalDispatchContext0, SignalDispatchContext1, SignalDispatchContext2); 25 | } 26 | 27 | protected override void AddListenerA(int order = 0) 28 | { 29 | signal.AddListener(OnListenerAWrapper, order); 30 | } 31 | 32 | protected override void RemoveListenerA() 33 | { 34 | signal.RemoveListener(OnListenerAWrapper); 35 | } 36 | 37 | protected override void AddListenerB(int order = 0) 38 | { 39 | signal.AddListener(OnListenerBWrapper, order); 40 | } 41 | 42 | protected override void RemoveListenerB() 43 | { 44 | signal.RemoveListener(OnListenerBWrapper); 45 | } 46 | 47 | protected override void AddListenerC(int order = 0) 48 | { 49 | signal.AddListener(OnListenerCWrapper, order); 50 | } 51 | 52 | protected override void RemoveListenerC() 53 | { 54 | signal.RemoveListener(OnListenerCWrapper); 55 | } 56 | 57 | protected override void AddPauseListener(int order = 0) 58 | { 59 | signal.AddListener(OnPauseListenerWrapper, order); 60 | } 61 | 62 | protected override void AddConsumeListener(int order = 0) 63 | { 64 | signal.AddListener(OnConsumeListenerWrapper, order); 65 | } 66 | 67 | protected override void AddUnsubscribeSelfListener(int order = 0) 68 | { 69 | signal.AddListener(OnUnsubscribeSelfListener, order); 70 | } 71 | 72 | protected override void AddListenerAOnCallAtMinusTen(int order = 0) 73 | { 74 | signal.AddListener(OnAddListenerAAtMinusTen, order); 75 | } 76 | 77 | protected override void RemoveListenerAOnCall(int order = 0) 78 | { 79 | signal.AddListener(OnRemoveListenerA, order); 80 | } 81 | 82 | protected override void AddListenerBOnCallAtZero(int order = 0) 83 | { 84 | signal.AddListener(OnAddListenerBAtZero, order); 85 | } 86 | 87 | protected override void RemoveListenerBOnCall(int order = 0) 88 | { 89 | signal.AddListener(OnRemoveListenerB, order); 90 | } 91 | 92 | private void OnListenerAWrapper(object c0, string c1, int c2) 93 | { 94 | OnListenerA(); 95 | } 96 | 97 | private void OnListenerBWrapper(object c0, string c1, int c2) 98 | { 99 | OnListenerB(); 100 | } 101 | 102 | private void OnListenerCWrapper(object c0, string c1, int c2) 103 | { 104 | OnListenerC(); 105 | } 106 | 107 | private void OnPauseListenerWrapper(object c0, string c1, int c2) 108 | { 109 | OnPauseListener(); 110 | } 111 | 112 | private void OnConsumeListenerWrapper(object c0, string c1, int c2) 113 | { 114 | OnConsumeListener(); 115 | } 116 | 117 | private void OnUnsubscribeSelfListener(object c0, string c1, int c2) 118 | { 119 | signal.RemoveListener(OnUnsubscribeSelfListener); 120 | } 121 | 122 | 123 | private void OnAddListenerAAtMinusTen(object c0, string c1, int c2) 124 | { 125 | signal.AddListener(OnListenerAWrapper, -10); 126 | } 127 | 128 | private void OnAddListenerBAtZero(object c0, string c1, int c2) 129 | { 130 | signal.AddListener(OnListenerBWrapper, 0); 131 | } 132 | 133 | private void OnRemoveListenerA(object c0, string c1, int c2) 134 | { 135 | signal.RemoveListener(OnListenerAWrapper); 136 | } 137 | 138 | private void OnRemoveListenerB(object c0, string c1, int c2) 139 | { 140 | signal.RemoveListener(OnListenerBWrapper); 141 | } 142 | } 143 | } -------------------------------------------------------------------------------- /Tests/ThreeArgumentSignalTests.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ea43b3f305ac49a78ec49ca9084fb9dc 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Tests/TwoArgumentSignalTests.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) 2020 Supyrb. All rights reserved. 4 | // 5 | // 6 | // Johannes Deml 7 | // public@deml.io 8 | // 9 | // -------------------------------------------------------------------------------------------------------------------- 10 | 11 | using NUnit.Framework; 12 | 13 | namespace Supyrb.Tests 14 | { 15 | [TestFixture] 16 | public class TwoArgumentSignalTests : ASignalTests 17 | { 18 | private const string SignalDispatchContext0 = "Value"; 19 | private const int SignalDispatchContext1 = 0; 20 | 21 | protected override void Dispatch() 22 | { 23 | signal.Dispatch(SignalDispatchContext0, SignalDispatchContext1); 24 | } 25 | 26 | protected override void AddListenerA(int order = 0) 27 | { 28 | signal.AddListener(OnListenerAWrapper, order); 29 | } 30 | 31 | protected override void RemoveListenerA() 32 | { 33 | signal.RemoveListener(OnListenerAWrapper); 34 | } 35 | 36 | protected override void AddListenerB(int order = 0) 37 | { 38 | signal.AddListener(OnListenerBWrapper, order); 39 | } 40 | 41 | protected override void RemoveListenerB() 42 | { 43 | signal.RemoveListener(OnListenerBWrapper); 44 | } 45 | 46 | protected override void AddListenerC(int order = 0) 47 | { 48 | signal.AddListener(OnListenerCWrapper, order); 49 | } 50 | 51 | protected override void RemoveListenerC() 52 | { 53 | signal.RemoveListener(OnListenerCWrapper); 54 | } 55 | 56 | protected override void AddPauseListener(int order = 0) 57 | { 58 | signal.AddListener(OnPauseListenerWrapper, order); 59 | } 60 | 61 | protected override void AddConsumeListener(int order = 0) 62 | { 63 | signal.AddListener(OnConsumeListenerWrapper, order); 64 | } 65 | 66 | protected override void AddUnsubscribeSelfListener(int order = 0) 67 | { 68 | signal.AddListener(OnUnsubscribeSelfListener, order); 69 | } 70 | 71 | protected override void AddListenerAOnCallAtMinusTen(int order = 0) 72 | { 73 | signal.AddListener(OnAddListenerAAtMinusTen, order); 74 | } 75 | 76 | protected override void RemoveListenerAOnCall(int order = 0) 77 | { 78 | signal.AddListener(OnRemoveListenerA, order); 79 | } 80 | 81 | protected override void AddListenerBOnCallAtZero(int order = 0) 82 | { 83 | signal.AddListener(OnAddListenerBAtZero, order); 84 | } 85 | 86 | protected override void RemoveListenerBOnCall(int order = 0) 87 | { 88 | signal.AddListener(OnRemoveListenerB, order); 89 | } 90 | 91 | private void OnListenerAWrapper(string c0, int c1) 92 | { 93 | OnListenerA(); 94 | } 95 | 96 | private void OnListenerBWrapper(string c0, int c1) 97 | { 98 | OnListenerB(); 99 | } 100 | 101 | private void OnPauseListenerWrapper(string c0, int c1) 102 | { 103 | OnPauseListener(); 104 | } 105 | 106 | private void OnConsumeListenerWrapper(string c0, int c1) 107 | { 108 | OnConsumeListener(); 109 | } 110 | 111 | private void OnListenerCWrapper(string c0, int c1) 112 | { 113 | OnListenerC(); 114 | } 115 | 116 | private void OnUnsubscribeSelfListener(string c0, int c1) 117 | { 118 | signal.RemoveListener(OnUnsubscribeSelfListener); 119 | } 120 | 121 | 122 | private void OnAddListenerAAtMinusTen(string c0, int c1) 123 | { 124 | signal.AddListener(OnListenerAWrapper, -10); 125 | } 126 | 127 | private void OnAddListenerBAtZero(string c0, int c1) 128 | { 129 | signal.AddListener(OnListenerBWrapper, 0); 130 | } 131 | 132 | private void OnRemoveListenerA(string c0, int c1) 133 | { 134 | signal.RemoveListener(OnListenerAWrapper); 135 | } 136 | 137 | private void OnRemoveListenerB(string c0, int c1) 138 | { 139 | signal.RemoveListener(OnListenerBWrapper); 140 | } 141 | } 142 | } -------------------------------------------------------------------------------- /Tests/TwoArgumentSignalTests.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 929362cb3453417c93874c96e403419a 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "com.supyrb.signals", 3 | "author": "Johannes Deml", 4 | "displayName": "Signals ❇", 5 | "description": "Signals is a powerful, lightweight messaging system that provides sortable, consumable and pausable signals. Comes with an editor window for easy access to the signals.", 6 | "keywords": [ 7 | "Signal", 8 | "Signals", 9 | "Events", 10 | "Messaging", 11 | "Decoupled" 12 | ], 13 | "license": "MIT", 14 | "category": "Utility", 15 | "version": "1.1.0", 16 | "unity": "2018.1", 17 | "dependencies": { 18 | 19 | }, 20 | "samples": [ 21 | { 22 | "displayName": "Basic", 23 | "description": "Simple example with one listener showing the basic usage of order and consuming signals", 24 | "path": "Samples~/Basic" 25 | }, 26 | { 27 | "displayName": "StressTest", 28 | "description": "Dispatch every frame to 10000 listeners", 29 | "path": "Samples~/StressTest" 30 | } 31 | ] 32 | } -------------------------------------------------------------------------------- /package.json.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 13e877f89b5a29e40bfde3f3cccb87a9 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | --------------------------------------------------------------------------------