├── LICENSE
├── README.md
├── README_ru.md
├── docs
└── AUTHORS.rst
└── src
└── ControllersTree
├── .idea
└── .idea.ControllersTree.dir
│ └── .idea
│ ├── .gitignore
│ └── encodings.xml
├── Core.meta
├── Core
├── AssemblyInfo.cs
├── AssemblyInfo.cs.meta
├── Attributes.meta
├── Attributes
│ ├── DebugMethodAttribute.cs
│ └── DebugMethodAttribute.cs.meta
├── Contracts.meta
├── Contracts
│ ├── EmptyControllerArg.cs
│ ├── EmptyControllerArg.cs.meta
│ ├── EmptyControllerResult.cs
│ └── EmptyControllerResult.cs.meta
├── Controllers.meta
├── Controllers
│ ├── ControllerBase.Debug.cs
│ ├── ControllerBase.Debug.cs.meta
│ ├── ControllerBase.Editor.cs
│ ├── ControllerBase.Editor.cs.meta
│ ├── ControllerBase.Execute.cs
│ ├── ControllerBase.Execute.cs.meta
│ ├── ControllerBase.ExecuteAndWaitResultAsync.cs
│ ├── ControllerBase.ExecuteAndWaitResultAsync.cs.meta
│ ├── ControllerBase.Profiler.cs
│ ├── ControllerBase.Profiler.cs.meta
│ ├── ControllerBase.cs
│ ├── ControllerBase.cs.meta
│ ├── ControllerBase`1.cs
│ ├── ControllerBase`1.cs.meta
│ ├── ControllerWithResultBase.cs
│ ├── ControllerWithResultBase.cs.meta
│ ├── ControllerWithResultBase`1.cs
│ ├── ControllerWithResultBase`1.cs.meta
│ ├── ControllerWithResultBase`2.Editor.cs
│ ├── ControllerWithResultBase`2.Editor.cs.meta
│ ├── ControllerWithResultBase`2.cs
│ ├── ControllerWithResultBase`2.cs.meta
│ ├── RootController.Profiler.cs
│ ├── RootController.Profiler.cs.meta
│ ├── RootController.cs
│ └── RootController.cs.meta
├── Interfaces.meta
├── Interfaces
│ ├── IController.cs
│ ├── IController.cs.meta
│ ├── IControllerDebugInfo.cs
│ ├── IControllerDebugInfo.cs.meta
│ ├── IControllerFactory.cs
│ ├── IControllerFactory.cs.meta
│ ├── IControllerWithResult.cs
│ └── IControllerWithResult.cs.meta
├── Playtika.Controllers.asmdef
├── Playtika.Controllers.asmdef.meta
├── Profiler.meta
├── Profiler
│ ├── FixedString.cs
│ ├── FixedString.cs.meta
│ ├── Helper.cs
│ └── Helper.cs.meta
├── States.meta
├── States
│ ├── ControllerState.cs
│ ├── ControllerState.cs.meta
│ ├── ControllerWithResultState.cs
│ └── ControllerWithResultState.cs.meta
├── Utils.meta
└── Utils
│ ├── ControllerCompositeDisposable.cs
│ ├── ControllerCompositeDisposable.cs.meta
│ ├── DisposableToken.cs
│ └── DisposableToken.cs.meta
├── Editor.meta
├── Editor
├── ControllersHierarchy.meta
├── ControllersHierarchy
│ ├── ControllerTabData.cs
│ ├── ControllerTabData.cs.meta
│ ├── ControllerTreeView.cs
│ ├── ControllerTreeView.cs.meta
│ ├── ControllersHierarchy.cs
│ ├── ControllersHierarchy.cs.meta
│ ├── ControllersHierarchyView.cs
│ ├── ControllersHierarchyView.cs.meta
│ ├── ControllersInfoView.cs
│ ├── ControllersInfoView.cs.meta
│ ├── ControllersMethodsView.cs
│ ├── ControllersMethodsView.cs.meta
│ ├── ControllersTabBarDrawer.cs
│ ├── ControllersTabBarDrawer.cs.meta
│ ├── ControllersTreeHelper.cs
│ ├── ControllersTreeHelper.cs.meta
│ ├── ControllersTreeViewItem.cs
│ ├── ControllersTreeViewItem.cs.meta
│ ├── ControllersTreeViewModel.cs
│ ├── ControllersTreeViewModel.cs.meta
│ ├── FieldsDrawers.meta
│ ├── FieldsDrawers
│ │ ├── ControllersActionFieldDrawer.cs
│ │ ├── ControllersActionFieldDrawer.cs.meta
│ │ ├── ControllersBaseFieldDrawer.cs
│ │ ├── ControllersBaseFieldDrawer.cs.meta
│ │ ├── ControllersBooleanFieldDrawer.cs
│ │ ├── ControllersBooleanFieldDrawer.cs.meta
│ │ ├── ControllersCollectionFieldDrawer.cs
│ │ ├── ControllersCollectionFieldDrawer.cs.meta
│ │ ├── ControllersFieldsFactory.cs
│ │ ├── ControllersFieldsFactory.cs.meta
│ │ ├── ControllersIntegerFieldDrawer.cs
│ │ ├── ControllersIntegerFieldDrawer.cs.meta
│ │ ├── ControllersLabelFieldDrawer.cs
│ │ ├── ControllersLabelFieldDrawer.cs.meta
│ │ ├── ControllersParentObjectFieldDrawer.cs
│ │ ├── ControllersParentObjectFieldDrawer.cs.meta
│ │ ├── ControllersStringFieldDrawer.cs
│ │ ├── ControllersStringFieldDrawer.cs.meta
│ │ ├── ControllersUnityObjectFieldDrawer.cs
│ │ └── ControllersUnityObjectFieldDrawer.cs.meta
│ ├── Playtika.Controllers.Editor.asmdef
│ └── Playtika.Controllers.Editor.asmdef.meta
├── ControllersProfiler.meta
└── ControllersProfiler
│ ├── ControllerData.cs
│ ├── ControllerData.cs.meta
│ ├── ControllerLiveData.cs
│ ├── ControllerLiveData.cs.meta
│ ├── ControllersProfilerModule.cs
│ ├── ControllersProfilerModule.cs.meta
│ ├── ControllersProfilerModuleViewController.cs
│ ├── ControllersProfilerModuleViewController.cs.meta
│ ├── CreatedAndDestroyedControllersListView.cs
│ ├── CreatedAndDestroyedControllersListView.cs.meta
│ ├── LiveControllersListView.cs
│ ├── LiveControllersListView.cs.meta
│ ├── Playtika.ControllersProfiler.Editor.asmdef
│ └── Playtika.ControllersProfiler.Editor.asmdef.meta
├── Substitute.meta
├── Substitute
├── Runtime.meta
├── Runtime
│ ├── Playtika.Controllers.Substitute.asmdef
│ ├── Playtika.Controllers.Substitute.asmdef.meta
│ ├── SubstituteController.cs
│ ├── SubstituteController.cs.meta
│ ├── SubstituteControllerFactory.cs
│ ├── SubstituteControllerFactory.cs.meta
│ ├── SubstituteControllerWithResult.cs
│ ├── SubstituteControllerWithResult.cs.meta
│ ├── TestRootController.cs
│ └── TestRootController.cs.meta
├── Tests.meta
└── Tests
│ ├── Playtika.Controllers.Substitute.Tests.asmdef
│ ├── Playtika.Controllers.Substitute.Tests.asmdef.meta
│ ├── SubstituteControllerFactoryTests.cs
│ ├── SubstituteControllerFactoryTests.cs.meta
│ ├── TestRootControllerWithSubstituteFactoryTests.cs
│ ├── TestRootControllerWithSubstituteFactoryTests.cs.meta
│ ├── TypesForTest.cs
│ └── TypesForTest.cs.meta
├── Tests.meta
├── Tests
├── Controllers.meta
├── Controllers
│ ├── ControllersBase.meta
│ ├── ControllersBase
│ │ ├── ActionModelTestControllerBase.cs
│ │ └── ActionModelTestControllerBase.cs.meta
│ ├── ControllersWithResult.meta
│ └── ControllersWithResult
│ │ ├── ActionModelTestControllerWithResult.cs
│ │ ├── ActionModelTestControllerWithResult.cs.meta
│ │ ├── ActionModelTestControllerWithResult_CompleteAfterOnFlowAsync.cs
│ │ ├── ActionModelTestControllerWithResult_CompleteAfterOnFlowAsync.cs.meta
│ │ ├── ActionModelTestControllerWithResult_CompleteOnFlowAsync.cs
│ │ ├── ActionModelTestControllerWithResult_CompleteOnFlowAsync.cs.meta
│ │ ├── ActionModelTestControllerWithResult_CompleteOnStart.cs
│ │ ├── ActionModelTestControllerWithResult_CompleteOnStart.cs.meta
│ │ ├── ActionModelTestControllerWithResult_FailInDispose.cs
│ │ ├── ActionModelTestControllerWithResult_FailInDispose.cs.meta
│ │ ├── ActionModelTestControllerWithResult_FailOnFlowAsync.cs
│ │ ├── ActionModelTestControllerWithResult_FailOnFlowAsync.cs.meta
│ │ ├── ActionModelTestControllerWithResult_FailOnStart.cs
│ │ ├── ActionModelTestControllerWithResult_FailOnStart.cs.meta
│ │ ├── ActionModelTestControllerWithResult_FailOnStop.cs
│ │ ├── ActionModelTestControllerWithResult_FailOnStop.cs.meta
│ │ ├── ActionModelTestControllerWithResult_ThrowAfterOnFlowAsync.cs
│ │ ├── ActionModelTestControllerWithResult_ThrowAfterOnFlowAsync.cs.meta
│ │ ├── Childs.meta
│ │ └── Childs
│ │ ├── ActionModelTestChildControllerWithResult.cs
│ │ ├── ActionModelTestChildControllerWithResult.cs.meta
│ │ ├── ActionModelTestControllerWithResultAndChildControllers.cs
│ │ ├── ActionModelTestControllerWithResultAndChildControllers.cs.meta
│ │ ├── ActionModelTestControllerWithResultAndChildControllers_FailOnFlowAsync.cs
│ │ └── ActionModelTestControllerWithResultAndChildControllers_FailOnFlowAsync.cs.meta
├── ControllersBaseTests.cs
├── ControllersBaseTests.cs.meta
├── ControllersWithResultBaseTests.ChildControllers.cs
├── ControllersWithResultBaseTests.ChildControllers.cs.meta
├── ControllersWithResultBaseTests.FlowAsync.cs
├── ControllersWithResultBaseTests.FlowAsync.cs.meta
├── ControllersWithResultBaseTests.cs
├── ControllersWithResultBaseTests.cs.meta
├── Playtika.Controllers.Tests.asmdef
├── Playtika.Controllers.Tests.asmdef.meta
├── TestChildControllerArgs.cs
├── TestChildControllerArgs.cs.meta
├── TestChildControllersActionModel.cs
├── TestChildControllersActionModel.cs.meta
├── TestControllerArgs.cs
├── TestControllerArgs.cs.meta
├── TestControllersActionModel.cs
├── TestControllersActionModel.cs.meta
├── TestControllersException.cs
├── TestControllersException.cs.meta
├── TestControllersMethodsNamesConsts.cs
├── TestControllersMethodsNamesConsts.cs.meta
├── TestControllersUtils.cs
├── TestControllersUtils.cs.meta
├── TestEmptyControllerResult.cs
├── TestEmptyControllerResult.cs.meta
├── TestRootControllerLauncher.cs
└── TestRootControllerLauncher.cs.meta
├── package.json
└── package.json.meta
/docs/AUTHORS.rst:
--------------------------------------------------------------------------------
1 | ============
2 | Project Authors
3 | ============
4 | We thank the following people for their contributions (in alphabetical order):
5 |
6 | - Aleksei Borisov
7 | - Aleksey Lukoyanichev
8 | - Alex Kniazkin
9 | - Alexey Merzlikin
10 | - Aliaksandr Hurynovich
11 | - Aliaksandr Krauchuk
12 | - Aliaksandr Maisak
13 | - Aliaksandr Shchamialiou
14 | - Andrei Batseka
15 | - Andrei Navoichyk
16 | - Andrew Chaiko
17 | - Andrey Makarevich
18 | - Artem Svirid
19 | - Artur Sushkov
20 | - Daniil Kondrashov
21 | - Dmitry Novitsky
22 | - Dzmitry Chubryk
23 | - Dzmitry Kharko
24 | - Dzmitry Malchykau
25 | - Egor Zhingerovsky
26 | - Eldar Huseinau
27 | - Evgeny Pikta
28 | - Grigory Perepechko
29 | - Igor Perepechenko
30 | - Ivan Kovalchuk
31 | - Ivan Voinyi
32 | - Ivan Zhdanov
33 | - Leonid Hromyko
34 | - Maksim Shabanets
35 | - Maxim Bozbey
36 | - Maxim Gulik
37 | - Mihail Podshivadlov
38 | - Mikhail Gvozdev
39 | - Nikita Markianov
40 | - Nikita Anufriev
41 | - Nikita Barkun
42 | - Nikolai Karnovskii
43 | - Oleg Ilyin
44 | - Polina Freydlina
45 | - Roman Shevchik
46 | - Ruslan Panteleev
47 | - Sergey Efremov
48 | - Sergey Greshnov
49 | - Sergey Khalandachev
50 | - Sergey Ladychin
51 | - Sergey Metlov
52 | - Shilo Olga
53 | - Siarhei Rydkin
54 | - Stepan Shamashov
55 | - Uladzislau Navaselski
56 | - Viachaslau Burlo
57 | - Vitaliy Kaymachnikov
58 | - Vitaly Kolesnikov
59 | - Vlad Larin
60 | - Vyacheslav Alferov
61 | - Yahor Remshanka
62 | - Yaraslau Shabanets
63 |
64 | If you contributed and don't see your name here, please submit a pull request to add yourself!
65 |
--------------------------------------------------------------------------------
/src/ControllersTree/.idea/.idea.ControllersTree.dir/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # Rider ignored files
5 | /modules.xml
6 | /projectSettingsUpdater.xml
7 | /.idea.ControllersTree.iml
8 | /contentModel.xml
9 | # Editor-based HTTP Client requests
10 | /httpRequests/
11 | # Datasource local storage ignored files
12 | /dataSources/
13 | /dataSources.local.xml
14 |
--------------------------------------------------------------------------------
/src/ControllersTree/.idea/.idea.ControllersTree.dir/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/src/ControllersTree/Core.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 9bfa0cfab11f63344bf36ef374030d5b
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/src/ControllersTree/Core/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 |
3 | [assembly: AssemblyTitle("Controllers tree")]
4 | [assembly: AssemblyDescription("Controllers tree base classes.")]
5 |
6 | // internal should be visible to Substitute
7 | [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("DynamicProxyGenAssembly2")]
8 | [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Playtika.Controllers.Editor")]
9 |
10 | [assembly: AssemblyVersion("1.0.0")]
11 |
--------------------------------------------------------------------------------
/src/ControllersTree/Core/AssemblyInfo.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: dbdd90e2624b748879ec7f05b82bd0a9
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/src/ControllersTree/Core/Attributes.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: d70bab7ded4a435086fa7ddfa8a37648
3 | timeCreated: 1706189464
--------------------------------------------------------------------------------
/src/ControllersTree/Core/Attributes/DebugMethodAttribute.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using UnityEngine.Scripting;
3 |
4 | namespace Playtika.Controllers
5 | {
6 | [AttributeUsage(AttributeTargets.Method)]
7 | public sealed class DebugMethodAttribute :
8 | #if UNITY_EDITOR || DEVELOPMENT_BUILD || UNITY_BUILDTYPE_DEV
9 | PreserveAttribute
10 | #else
11 | Attribute
12 | #endif
13 | {
14 | public readonly string Name;
15 | public DebugMethodAttribute()
16 | {
17 | }
18 |
19 | public DebugMethodAttribute(string name)
20 | {
21 | Name = name;
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/ControllersTree/Core/Attributes/DebugMethodAttribute.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 01ea8bb24cc2049f1addbb91a9ade90e
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/src/ControllersTree/Core/Contracts.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 09766dab6c294cb2a92961ce3780d829
3 | timeCreated: 1706189503
--------------------------------------------------------------------------------
/src/ControllersTree/Core/Contracts/EmptyControllerArg.cs:
--------------------------------------------------------------------------------
1 | namespace Playtika.Controllers
2 | {
3 | public readonly struct EmptyControllerArg
4 | {
5 | }
6 | }
--------------------------------------------------------------------------------
/src/ControllersTree/Core/Contracts/EmptyControllerArg.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 99487367fb7994829806d6bd9cf4d6e5
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/src/ControllersTree/Core/Contracts/EmptyControllerResult.cs:
--------------------------------------------------------------------------------
1 | namespace Playtika.Controllers
2 | {
3 | public readonly struct EmptyControllerResult
4 | {
5 | }
6 | }
--------------------------------------------------------------------------------
/src/ControllersTree/Core/Contracts/EmptyControllerResult.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: c53d574ef7226431b8166d0e31a475a2
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/src/ControllersTree/Core/Controllers.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: becdf090793f424d9d9f70dd34c709d4
3 | timeCreated: 1706189522
--------------------------------------------------------------------------------
/src/ControllersTree/Core/Controllers/ControllerBase.Debug.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using UnityEngine.Pool;
3 |
4 | namespace Playtika.Controllers
5 | {
6 | public partial class ControllerBase
7 | {
8 | ///
9 | /// Generates a string representation of the controller tree.
10 | /// Used for debug or error handling purposes.
11 | ///
12 | /// A string representation of the controller tree.
13 | protected string Dump()
14 | {
15 | using var controllersTreePooledObject = ListPool.Get(out var controllersTree);
16 | ((IController)this).ScanTree(controllersTree, string.Empty);
17 | return string.Join("\n", controllersTree);
18 | }
19 |
20 | void IController.ScanTree(List controllersTree, string prefix)
21 | {
22 | controllersTree.Add($"{prefix}{this}");
23 | foreach (var child in _childControllers)
24 | {
25 | child.ScanTree(controllersTree, $" {prefix}");
26 | }
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/ControllersTree/Core/Controllers/ControllerBase.Debug.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 5577f91e517834a109f65d113df90b5b
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/src/ControllersTree/Core/Controllers/ControllerBase.Editor.cs:
--------------------------------------------------------------------------------
1 | #if UNITY_EDITOR
2 | using System.Collections;
3 | using System.Collections.Generic;
4 | using System.Threading;
5 | using UnityEngine;
6 |
7 | namespace Playtika.Controllers
8 | {
9 | public partial class ControllerBase : IControllerDebugInfo
10 | {
11 | IEnumerator IEnumerable.GetEnumerator()
12 | {
13 | return ((IEnumerable)this).GetEnumerator();
14 | }
15 |
16 | IEnumerator IEnumerable.GetEnumerator()
17 | {
18 | foreach (var childController in _childControllers)
19 | {
20 | yield return (IControllerDebugInfo)childController;
21 | }
22 | }
23 |
24 | string IControllerDebugInfo.ControllerType => ControllerTypeInternal();
25 | string IControllerDebugInfo.StateName => StateNameInternal();
26 | Color IControllerDebugInfo.StateColor => StateColorInternal();
27 | string IControllerDebugInfo.ScopeName => _controllerFactory?.ToString();
28 |
29 | protected virtual string ControllerTypeInternal() =>
30 | nameof(ControllerBase);
31 |
32 | protected virtual string StateNameInternal() =>
33 | _state.ToString();
34 |
35 | protected virtual Color StateColorInternal() =>
36 | _state switch
37 | {
38 | ControllerState.Created => new Color(0.09f, 0.52f, 0.87f),
39 | ControllerState.Initialized => new Color(0.07f, 0.84f, 0.85f),
40 | ControllerState.Running => new Color(0.13f, 0.8f, 0f),
41 | ControllerState.Stopped => new Color(1f, 0.86f, 0f),
42 | ControllerState.Disposed => new Color(1f, 0.26f, 0.12f),
43 | _ => Color.magenta
44 | };
45 | }
46 | }
47 | #endif
48 |
--------------------------------------------------------------------------------
/src/ControllersTree/Core/Controllers/ControllerBase.Editor.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: ac02a3c99bbc747e099c5edef1a1560c
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/src/ControllersTree/Core/Controllers/ControllerBase.Execute.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using System.Linq;
4 | using System.Runtime.CompilerServices;
5 | using System.Threading;
6 |
7 | namespace Playtika.Controllers
8 | {
9 | public abstract partial class ControllerBase
10 | {
11 | ///
12 | /// Executes a controller of type T.
13 | /// This method creates an instance of the controller and starts it.
14 | ///
15 | /// The type of the controller to execute. Must implement IController.
16 | protected void Execute()
17 | where T : class, IController
18 | {
19 | ThrowIfControllerWithResult();
20 | ExecuteInternal(null, default);
21 | }
22 |
23 | ///
24 | /// Executes a controller of type T that requires an argument of type TArg.
25 | /// This method creates an instance of the controller, sets the argument, and starts the controller.
26 | ///
27 | /// The type of the controller to execute. Must implement IController and IController<TArg>.
28 | /// The type of the argument required by the controller.
29 | /// The argument to pass to the controller.
30 | protected void Execute(TArg arg)
31 | where T : class, IController, IController
32 | {
33 | ThrowIfControllerWithResult();
34 | ExecuteInternal(arg, null, default);
35 | }
36 |
37 | ///
38 | /// Executes a controller of type T using a specified controller factory.
39 | /// This method creates an instance of the controller and starts it.
40 | ///
41 | /// The type of the controller to execute. Must implement IController.
42 | /// The factory to use when creating the controller.
43 | protected void Execute(IControllerFactory factory)
44 | where T : class, IController
45 | {
46 | ThrowIfControllerWithResult();
47 | ExecuteInternal(factory, default);
48 | }
49 |
50 | ///
51 | /// Executes a controller of type T that requires an argument of type TArg using a specified controller factory.
52 | /// This method creates an instance of the controller, sets the argument, and starts the controller.
53 | ///
54 | /// The type of the controller to execute. Must implement IController and IController<TArg>.
55 | /// The type of the argument required by the controller.
56 | /// The argument to pass to the controller.
57 | /// The factory to use when creating the controller.
58 | protected void Execute(TArg arg,
59 | IControllerFactory factory)
60 | where T : class, IController, IController
61 | {
62 | ThrowIfControllerWithResult();
63 | ExecuteInternal(arg, factory, default);
64 | }
65 |
66 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
67 | private IController ExecuteInternal(
68 | IControllerFactory factory,
69 | CancellationToken cancellationToken)
70 | where T : class, IController
71 | {
72 | cancellationToken.ThrowIfCancellationRequested();
73 | ThrowIfControllerHasIncorrectState();
74 | var controller = Create(factory);
75 | Start(controller, cancellationToken);
76 | return controller;
77 | }
78 |
79 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
80 | private IController ExecuteInternal(
81 | TArg arg,
82 | IControllerFactory factory,
83 | CancellationToken cancellationToken)
84 | where T : class, IController, IController
85 | {
86 | cancellationToken.ThrowIfCancellationRequested();
87 | ThrowIfControllerHasIncorrectState();
88 | var controller = Create(factory);
89 | ((IController)controller).SetArgInternal(arg);
90 | Start(controller, cancellationToken);
91 | return controller;
92 | }
93 |
94 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
95 | private IController Create(IControllerFactory factory)
96 | where T : class, IController
97 | {
98 | factory ??= _controllerFactory;
99 | var controller = factory.Create();
100 | return controller;
101 | }
102 |
103 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
104 | private void Start(IController controller, CancellationToken token)
105 | {
106 | controller.Initialize(token, CancellationToken);
107 |
108 | AddChild(controller);
109 |
110 | try
111 | {
112 | controller.Start();
113 | }
114 | catch (Exception exception)
115 | {
116 | using (controller)
117 | {
118 | controller.Stop(exception);
119 | RemoveChild(controller);
120 | }
121 |
122 | throw;
123 | }
124 | }
125 |
126 | [Conditional("UNITY_EDITOR")]
127 | private static void ThrowIfControllerWithResult()
128 | {
129 | var controllerType = typeof(T);
130 | var controllerWithResultBaseInterface = typeof(IControllerWithResult<>);
131 | var interfaces = controllerType.GetInterfaces();
132 | if (interfaces.Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == controllerWithResultBaseInterface))
133 | {
134 | throw new Exception(
135 | $"{controllerType.Name}: ControllerWithResult cannot be started with {nameof(Execute)}");
136 | }
137 | }
138 |
139 | [Conditional("UNITY_EDITOR")]
140 | private void ThrowIfControllerHasIncorrectState()
141 | {
142 | if (_state != ControllerState.Running)
143 | {
144 | throw new InvalidOperationException($"{Name} Can't Execute from {_state} state.");
145 | }
146 | }
147 | }
148 | }
--------------------------------------------------------------------------------
/src/ControllersTree/Core/Controllers/ControllerBase.Execute.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 31e13c00f1b794ebc9a5628a5ba45da4
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/src/ControllersTree/Core/Controllers/ControllerBase.ExecuteAndWaitResultAsync.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: e9bda3a0dd00a47ee8c17d96572f2ce3
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/src/ControllersTree/Core/Controllers/ControllerBase.Profiler.cs:
--------------------------------------------------------------------------------
1 | #if UNITY_CONTROLLERS_PROFILER
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.Linq;
5 | using System.Threading;
6 | using Unity.Collections;
7 | using UnityEngine.Profiling;
8 |
9 | namespace Playtika.Controllers
10 | {
11 | public partial class ControllerBase
12 | {
13 | protected static int _totalCount;
14 | protected static int _activeCount;
15 | protected static int _createdThisFrameCount;
16 |
17 | internal int _instanceId;
18 | internal long _startTimeMSec;
19 | private readonly Stopwatch _stopwatch = Stopwatch.StartNew();
20 |
21 | internal List ChildControllers => _childControllers;
22 | internal string ScopeName => _controllerFactory?.ToString();
23 |
24 | internal long GetLifetime() => _stopwatch.ElapsedMilliseconds;
25 | private HashSet _savedNames = new HashSet();
26 |
27 | partial void ProfileOnCreated()
28 | {
29 | ++_totalCount;
30 | ++_activeCount;
31 | ++_createdThisFrameCount;
32 | }
33 |
34 | partial void ProfileOnStart()
35 | {
36 | _startTimeMSec = _stopwatch.ElapsedMilliseconds;
37 | PushCreateControllerToProfilerStream(Name, _startTimeMSec);
38 | _stopwatch.Restart();
39 | }
40 |
41 | partial void ProfileOnStop()
42 | {
43 | --_activeCount;
44 | var elapsedMilliseconds = _stopwatch.ElapsedMilliseconds;
45 | PushStopControllerToProfilerStream(Name, elapsedMilliseconds);
46 | }
47 |
48 | private void PushCreateControllerToProfilerStream(
49 | string name,
50 | long startTimeMSec)
51 | {
52 | if (!Profiler.enabled || string.IsNullOrEmpty(name))
53 | {
54 | return;
55 | }
56 |
57 | var nameHash = name.GetHashCode();
58 | var data = new NativeArray(1, Allocator.Persistent);
59 | data[0] = new CreateControllerFrameData()
60 | {
61 | NameHash = nameHash,
62 | StartTimeMSec = startTimeMSec
63 | };
64 |
65 | Profiler.EmitFrameMetaData(Helper.ControllerProfilerGuid, Helper.ControllerStartTag, data);
66 | data.Dispose();
67 |
68 | if (_savedNames.Contains(nameHash))
69 | {
70 | return;
71 | }
72 |
73 | var nameData = new NativeArray(1, Allocator.Persistent);
74 | nameData[0] = new NameSessionData()
75 | {
76 | NameHash = nameHash,
77 | Name = name
78 | };
79 | Profiler.EmitSessionMetaData(Helper.ControllerProfilerGuid, Helper.ControllerNameTag, nameData);
80 | nameData.Dispose();
81 | _savedNames.Add(nameHash);
82 | }
83 |
84 | private static void PushStopControllerToProfilerStream(string name, long elapsedMilliseconds)
85 | {
86 | if (!Profiler.enabled || string.IsNullOrEmpty(name))
87 | {
88 | return;
89 | }
90 |
91 | var data = new NativeArray(1, Allocator.Persistent);
92 | data[0] = new StopControllerFrameData()
93 | {
94 | NameHash = name.GetHashCode(),
95 | ElapsedMilliseconds = elapsedMilliseconds
96 | };
97 |
98 | Profiler.EmitFrameMetaData(Helper.ControllerProfilerGuid, Helper.ControllerStopTag, data);
99 | data.Dispose();
100 | }
101 | }
102 | }
103 | #endif
104 |
--------------------------------------------------------------------------------
/src/ControllersTree/Core/Controllers/ControllerBase.Profiler.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: a8c38b6fa86b9495d8e36f4a95f11791
--------------------------------------------------------------------------------
/src/ControllersTree/Core/Controllers/ControllerBase.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Threading;
4 | using System.Linq;
5 | using UnityEngine.Pool;
6 |
7 | namespace Playtika.Controllers
8 | {
9 | public abstract partial class ControllerBase : IController, IDisposable
10 | {
11 | private readonly List _childControllers;
12 | private readonly ControllerCompositeDisposable _compositeDisposables = new ();
13 | private readonly IControllerFactory _controllerFactory;
14 | private CancellationToken _lifetimeToken;
15 | private CancellationTokenSource _lifetimeTokenSource;
16 | private ControllerState _state;
17 |
18 | public string Name => GetType().Name;
19 | protected CancellationToken CancellationToken => _lifetimeToken;
20 |
21 | CancellationToken IController.CancellationToken => _lifetimeToken;
22 |
23 | partial void ProfileOnCreated();
24 | partial void ProfileOnStart();
25 | partial void ProfileOnStop();
26 |
27 | protected ControllerBase(IControllerFactory controllerFactory)
28 | {
29 | _controllerFactory = controllerFactory;
30 | _childControllers = ListPool.Get();
31 | _state = ControllerState.Created;
32 | }
33 |
34 | public void AddDisposable(IDisposable disposable)
35 | {
36 | _compositeDisposables.Add(disposable);
37 | }
38 |
39 | public void AddDisposables(IEnumerable collection)
40 | {
41 | _compositeDisposables.AddRange(collection);
42 | }
43 |
44 | protected virtual void OnStart()
45 | {
46 | }
47 |
48 | protected virtual void OnStop()
49 | {
50 | }
51 |
52 | void IController.Initialize(
53 | CancellationToken externalCancellationToken,
54 | CancellationToken parentCancellationToken)
55 | {
56 | switch (_state)
57 | {
58 | case ControllerState.Created:
59 | {
60 | _lifetimeTokenSource = CancellationTokenSource.CreateLinkedTokenSource(externalCancellationToken, parentCancellationToken);
61 | AddDisposable(_lifetimeTokenSource);
62 | _lifetimeToken = _lifetimeTokenSource.Token;
63 | _lifetimeToken.ThrowIfCancellationRequested();
64 | _state = ControllerState.Initialized;
65 | ProfileOnCreated();
66 | break;
67 | }
68 | default:
69 | throw new InvalidOperationException($"{Name} Initialized called from non-'Created' state. Current state: {_state}");
70 | }
71 | }
72 |
73 | void IController.Start()
74 | {
75 | switch (_state)
76 | {
77 | case ControllerState.Initialized:
78 | {
79 | _state = ControllerState.Running;
80 | OnStart();
81 | ProfileOnStart();
82 | break;
83 | }
84 | default:
85 | throw new InvalidOperationException($"{Name} Controller should be initialized before adding. Current state: {_state}");
86 | }
87 | }
88 |
89 | void IDisposable.Dispose()
90 | {
91 | try
92 | {
93 | ((IController)this).Stop();
94 | }
95 | finally
96 | {
97 | DisposeInternal();
98 | }
99 | }
100 |
101 | void IController.Stop()
102 | {
103 | switch (_state)
104 | {
105 | case ControllerState.Created:
106 | case ControllerState.Initialized:
107 | case ControllerState.Running:
108 | StopChildrenAndSelf();
109 | ProfileOnStop();
110 | break;
111 | case ControllerState.Stopped:
112 | case ControllerState.Disposed:
113 | break;
114 | default:
115 | throw new InvalidOperationException($"{Name} Controller can not be stopped from current state: {_state}");
116 | }
117 | }
118 |
119 | void IController.Stop(Exception rootCauseException)
120 | {
121 | try
122 | {
123 | ((IController)this).Stop();
124 | }
125 | catch (Exception exception)
126 | {
127 | throw new AggregateException(rootCauseException, exception);
128 | }
129 | }
130 |
131 | private void DisposeInternal()
132 | {
133 | switch (_state)
134 | {
135 | case ControllerState.Initialized:
136 | case ControllerState.Running:
137 | case ControllerState.Stopped:
138 | {
139 | _lifetimeTokenSource?.Cancel();
140 | _compositeDisposables.Dispose();
141 | ListPool.Release(_childControllers);
142 | _state = ControllerState.Disposed;
143 | break;
144 | }
145 |
146 | case ControllerState.Disposed:
147 | break;
148 |
149 | default:
150 | throw new InvalidOperationException($"{Name} Controller can not be disposed from current state: {_state}");
151 | }
152 | }
153 |
154 | private void AddChild(IController controller)
155 | {
156 | _childControllers.Add(controller);
157 | }
158 |
159 | private void RemoveChild(IController controller)
160 | {
161 | _childControllers.Remove(controller);
162 | }
163 |
164 | private void StopChildrenAndSelf()
165 | {
166 | using var poolToken = ListPool.Get(out var exceptions);
167 | var childControllers = _childControllers.ToArray();
168 | foreach (var child in childControllers)
169 | {
170 | try
171 | {
172 | child.Stop();
173 | }
174 | catch (Exception exception)
175 | {
176 | exceptions.Add(exception);
177 | }
178 | }
179 |
180 | AddDisposables(_childControllers);
181 | _state = ControllerState.Stopped;
182 |
183 | try
184 | {
185 | OnStop();
186 | }
187 | catch (Exception exception)
188 | {
189 | if (exceptions.Any())
190 | {
191 | exceptions.Add(exception);
192 | }
193 | else
194 | {
195 | throw;
196 | }
197 | }
198 |
199 | if (exceptions.Any())
200 | {
201 | throw new AggregateException(exceptions);
202 | }
203 | }
204 |
205 | public override string ToString()
206 | {
207 | return _state switch
208 | {
209 | ControllerState.Running => Name,
210 | _ => $"{Name} : {_state}"
211 | };
212 | }
213 | }
214 | }
215 |
--------------------------------------------------------------------------------
/src/ControllersTree/Core/Controllers/ControllerBase.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: ab6a76801e6a39c469cb1d918b84af4f
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/src/ControllersTree/Core/Controllers/ControllerBase`1.cs:
--------------------------------------------------------------------------------
1 | namespace Playtika.Controllers
2 | {
3 | public class ControllerBase : ControllerBase, IController
4 | {
5 | protected TArg Args { get; private set; } = default;
6 |
7 | protected ControllerBase(IControllerFactory controllerFactory)
8 | : base(controllerFactory)
9 | {
10 | }
11 |
12 | void IController.SetArgInternal(TArg arg)
13 | {
14 | Args = arg;
15 | }
16 | }
17 | }
--------------------------------------------------------------------------------
/src/ControllersTree/Core/Controllers/ControllerBase`1.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 7d7143ae0ea3c4487bf7e04bca18574b
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/src/ControllersTree/Core/Controllers/ControllerWithResultBase.cs:
--------------------------------------------------------------------------------
1 | namespace Playtika.Controllers
2 | {
3 | public abstract class ControllerWithResultBase : ControllerWithResultBase
4 | {
5 | protected ControllerWithResultBase(IControllerFactory controllerFactory)
6 | : base(controllerFactory)
7 | {
8 | }
9 |
10 | ///
11 | /// Complete controller with default result.
12 | ///
13 | protected void Complete()
14 | {
15 | Complete(default);
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/ControllersTree/Core/Controllers/ControllerWithResultBase.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 40de3ed3419927f44af9908eb7674092
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/src/ControllersTree/Core/Controllers/ControllerWithResultBase`1.cs:
--------------------------------------------------------------------------------
1 | namespace Playtika.Controllers
2 | {
3 | public abstract class ControllerWithResultBase : ControllerWithResultBase, IControllerWithResult
4 | {
5 | protected ControllerWithResultBase(IControllerFactory controllerFactory)
6 | : base(controllerFactory)
7 | {
8 | }
9 | }
10 | }
--------------------------------------------------------------------------------
/src/ControllersTree/Core/Controllers/ControllerWithResultBase`1.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: b7b77d4e4b51546649fd0e649c62b4c2
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/src/ControllersTree/Core/Controllers/ControllerWithResultBase`2.Editor.cs:
--------------------------------------------------------------------------------
1 | #if UNITY_EDITOR
2 | using UnityEngine;
3 |
4 | namespace Playtika.Controllers
5 | {
6 | public partial class ControllerWithResultBase : ControllerBase, IControllerDebugInfo
7 | {
8 | private bool _inFlowAsyncCompleted;
9 |
10 | protected override string ControllerTypeInternal() =>
11 | nameof(ControllerWithResultBase);
12 |
13 | protected override string StateNameInternal()
14 | {
15 | switch (_withResultState)
16 | {
17 | case ControllerWithResultState.WaitForResultAsync:
18 | return _inFlowAsyncCompleted
19 | ? ControllerWithResultState.WaitForResultAsync.ToString()
20 | : "await OnFlowAsync()";
21 | default:
22 | return base.StateNameInternal();
23 | }
24 | }
25 |
26 | protected override Color StateColorInternal()
27 | {
28 | switch (_withResultState)
29 | {
30 | case ControllerWithResultState.None:
31 | return Color.white;
32 | case ControllerWithResultState.WaitForResultAsync:
33 | return _inFlowAsyncCompleted
34 | ? new Color(0.25f, 0.65f, 0.75f, 1.0f)
35 | : new Color(1.0f, 0.647f, 0.0f, 1.0f);
36 | case ControllerWithResultState.Completed:
37 | return new Color(0.13f, 0.9f, 0f);
38 | case ControllerWithResultState.Failed:
39 | return Color.red;
40 | default:
41 | return Color.magenta;
42 | }
43 | }
44 | }
45 | }
46 | #endif
47 |
--------------------------------------------------------------------------------
/src/ControllersTree/Core/Controllers/ControllerWithResultBase`2.Editor.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 014a8fc6ff08142a48aaa67fbd2e459e
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/src/ControllersTree/Core/Controllers/ControllerWithResultBase`2.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading;
3 | using Cysharp.Threading.Tasks;
4 |
5 | namespace Playtika.Controllers
6 | {
7 | public abstract partial class ControllerWithResultBase : ControllerBase, IControllerWithResult
8 | {
9 | private readonly UniTaskCompletionSource _resultSource = new UniTaskCompletionSource();
10 | private ControllerWithResultState _withResultState;
11 |
12 | protected ControllerWithResultBase(IControllerFactory controllerFactory)
13 | : base(controllerFactory)
14 | {
15 | }
16 |
17 | async UniTask IControllerWithResult.FlowAsync(CancellationToken cancellationToken)
18 | {
19 | switch (_withResultState)
20 | {
21 | case ControllerWithResultState.None:
22 | {
23 | await OnFlowAsync(cancellationToken);
24 | #if UNITY_EDITOR
25 | _inFlowAsyncCompleted = true;
26 | #endif
27 | break;
28 | }
29 | case ControllerWithResultState.Completed:
30 | case ControllerWithResultState.Failed:
31 | break;
32 | default:
33 | throw new InvalidOperationException(
34 | $"{Name} Flow async called from incorrect state. Current state: {_withResultState}");
35 | }
36 | }
37 |
38 | async UniTask IControllerWithResult.GetResult(CancellationToken token)
39 | {
40 | switch (_withResultState)
41 | {
42 | case ControllerWithResultState.None:
43 | break;
44 | case ControllerWithResultState.WaitForResultAsync:
45 | throw new InvalidOperationException(
46 | $"{Name} ControllerWithResult awaited from incorrect state: {_withResultState}");
47 | case ControllerWithResultState.Completed:
48 | case ControllerWithResultState.Failed:
49 | break;
50 | }
51 |
52 | _withResultState = ControllerWithResultState.WaitForResultAsync;
53 | await using (token.Register(Cancel, true))
54 | {
55 | return await _resultSource.Task;
56 | }
57 | }
58 |
59 | void IControllerWithResult.FailInternal(Exception exception)
60 | {
61 | Fail(exception);
62 | }
63 |
64 | ///
65 | /// Override this for controller async flow.
66 | /// Started automatically after execute controller.
67 | ///
68 | /// Cancellation token.
69 | ///
70 | protected virtual UniTask OnFlowAsync(CancellationToken cancellationToken)
71 | {
72 | return UniTask.CompletedTask;
73 | }
74 |
75 | ///
76 | /// Complete controller with result.
77 | ///
78 | /// Controller result.
79 | protected void Complete(TResult result)
80 | {
81 | _withResultState = ControllerWithResultState.Completed;
82 | _resultSource.TrySetResult(result);
83 | }
84 |
85 | ///
86 | /// Complete controller with result.
87 | ///
88 | /// Exception that caused the controller to stop operating.
89 | protected void Fail(Exception exception)
90 | {
91 | _withResultState = ControllerWithResultState.Failed;
92 | _resultSource.TrySetException(exception);
93 | }
94 |
95 | private void Cancel()
96 | {
97 | _withResultState = ControllerWithResultState.Failed;
98 | _resultSource.TrySetCanceled();
99 | }
100 |
101 | public override string ToString()
102 | {
103 | return _withResultState switch
104 | {
105 | ControllerWithResultState.WaitForResultAsync => $"{Name} : {_withResultState}",
106 | _ => base.ToString()
107 | };
108 | }
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/src/ControllersTree/Core/Controllers/ControllerWithResultBase`2.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 311fc035b77fb460c97ad2b41478fec0
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/src/ControllersTree/Core/Controllers/RootController.Profiler.cs:
--------------------------------------------------------------------------------
1 | #if UNITY_CONTROLLERS_PROFILER
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.Threading;
5 | using Cysharp.Threading.Tasks;
6 | using Unity.Collections;
7 | using Unity.Profiling;
8 | using UnityEngine.Profiling;
9 |
10 | namespace Playtika.Controllers
11 | {
12 | public partial class RootController
13 | {
14 | private static readonly ProfilerCategory ControllerProfilerCategory = ProfilerCategory.Scripts;
15 |
16 | private static readonly ProfilerCounterValue TotalControllersCount =
17 | new ProfilerCounterValue(
18 | ControllerProfilerCategory, Helper.TotalControllersCount,
19 | ProfilerMarkerDataUnit.Count, ProfilerCounterOptions.FlushOnEndOfFrame);
20 |
21 | private static readonly ProfilerCounterValue ActiveControllersCount =
22 | new ProfilerCounterValue(
23 | ControllerProfilerCategory, Helper.ActiveControllersCount,
24 | ProfilerMarkerDataUnit.Count, ProfilerCounterOptions.FlushOnEndOfFrame);
25 |
26 | private static readonly ProfilerCounterValue CreateThisFrameControllersCount =
27 | new ProfilerCounterValue(
28 | ControllerProfilerCategory, Helper.CreateThisFrameControllersCount,
29 | ProfilerMarkerDataUnit.Count, ProfilerCounterOptions.FlushOnEndOfFrame);
30 | private HashSet _savedNames = new HashSet();
31 |
32 | partial void ProfileOnStart()
33 | {
34 | MadeSnapshot(CancellationToken).Forget();
35 | }
36 |
37 | private async UniTaskVoid MadeSnapshot(CancellationToken cancellationToken)
38 | {
39 | while (!cancellationToken.IsCancellationRequested)
40 | {
41 | await UniTask.Yield(PlayerLoopTiming.LastUpdate);
42 | PushToProfilerStream();
43 | }
44 | }
45 |
46 | private void PushToProfilerStream()
47 | {
48 | if (!Profiler.enabled)
49 | {
50 | return;
51 | }
52 |
53 | TotalControllersCount.Value = _totalCount;
54 | ActiveControllersCount.Value = _activeCount;
55 | CreateThisFrameControllersCount.Value = _createdThisFrameCount;
56 | _createdThisFrameCount = 0;
57 |
58 | var count = _activeCount;
59 | var frameData = new NativeArray(count, Allocator.Persistent);
60 | var frameDataIndex = 0;
61 | ProfilerDumpTree((ControllerBase) this, frameData, ref frameDataIndex, 0);
62 | Profiler.EmitFrameMetaData(Helper.ControllerProfilerGuid, Helper.ControllerRunTag, frameData);
63 | frameData.Dispose();
64 | }
65 |
66 | private void ProfilerDumpTree(
67 | ControllerBase controllerBase,
68 | NativeArray frameData,
69 | ref int frameDataIndex,
70 | int level)
71 | {
72 | var scopeName = controllerBase.ScopeName;
73 | frameData[frameDataIndex] = new RunControllerFrameData()
74 | {
75 | NameHash = controllerBase.Name.GetHashCode(),
76 | ScopeHash = scopeName.GetHashCode(),
77 | InstanceId = controllerBase._instanceId,
78 | Level = level,
79 | StartTimeMSec = controllerBase._startTimeMSec,
80 | ElapsedMilliseconds = controllerBase.GetLifetime(),
81 | };
82 |
83 | ++frameDataIndex;
84 |
85 | var nameHash = scopeName.GetHashCode();
86 | if (!_savedNames.Contains(nameHash))
87 | {
88 | PushScopeNameToStream(scopeName, nameHash);
89 | _savedNames.Add(nameHash);
90 | }
91 |
92 | foreach (var child in controllerBase.ChildControllers)
93 | {
94 | ProfilerDumpTree((ControllerBase) child, frameData, ref frameDataIndex, level + 2);
95 | }
96 | }
97 |
98 | private static void PushScopeNameToStream(string name, int nameHash)
99 | {
100 | var nameData = new NativeArray(1, Allocator.Persistent);
101 | nameData[0] = new NameSessionData()
102 | {
103 | NameHash = nameHash,
104 | Name = name
105 | };
106 | Profiler.EmitSessionMetaData(Helper.ControllerProfilerGuid, Helper.ScopeNameTag, nameData);
107 | nameData.Dispose();
108 | }
109 | }
110 | }
111 | #endif
112 |
--------------------------------------------------------------------------------
/src/ControllersTree/Core/Controllers/RootController.Profiler.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: db2b7a8e2d894400cb9af017be93308f
--------------------------------------------------------------------------------
/src/ControllersTree/Core/Controllers/RootController.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using System.Threading;
4 |
5 | namespace Playtika.Controllers
6 | {
7 | public abstract partial class RootController : ControllerBase
8 | {
9 | protected RootController(IControllerFactory controllerFactory)
10 | : base(controllerFactory)
11 | {
12 | }
13 |
14 | partial void ProfileOnStart();
15 |
16 | ///
17 | /// Launches the execution of the controller tree.
18 | /// This method initializes the root controller with the provided cancellation token, starts it, and registers a callback to stop the root controller when the cancellation token is cancelled.
19 | ///
20 | /// A cancellation token that can be used to cancel the operation.
21 | public void LaunchTree(CancellationToken cancellationToken)
22 | {
23 | var registration = cancellationToken.Register(StopRootController, true);
24 | AddDisposable(registration);
25 | ((IController)this).Initialize(cancellationToken, CancellationToken.None);
26 | ((IController)this).Start();
27 | }
28 |
29 | private void StopRootController()
30 | {
31 | ((IDisposable)this).Dispose();
32 | }
33 |
34 | protected override void OnStart()
35 | {
36 | SetRootController(this);
37 | ProfileOnStart();
38 | }
39 |
40 | protected override void OnStop()
41 | {
42 | SetRootController(null);
43 | }
44 |
45 | public string DumpControllersTree()
46 | {
47 | return Dump();
48 | }
49 |
50 | [Conditional("UNITY_EDITOR"), Conditional("DEVELOPMENT_BUILD"), Conditional("UNITY_BUILDTYPE_DEV")]
51 | private static void SetRootController(ControllerBase controller)
52 | {
53 | #if UNITY_EDITOR || DEVELOPMENT_BUILD || UNITY_BUILDTYPE_DEV
54 | Instance = controller;
55 | #endif
56 | }
57 |
58 | #if UNITY_EDITOR || DEVELOPMENT_BUILD || UNITY_BUILDTYPE_DEV
59 | public static ControllerBase Instance { get; private set; }
60 | #endif
61 | }
62 | }
--------------------------------------------------------------------------------
/src/ControllersTree/Core/Controllers/RootController.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: b1826eeb44b304979a6de21b70e9d057
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/src/ControllersTree/Core/Interfaces.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: b4497a84772143bdb2f4b06a0c085dcd
3 | timeCreated: 1706189428
--------------------------------------------------------------------------------
/src/ControllersTree/Core/Interfaces/IController.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Threading;
4 |
5 | namespace Playtika.Controllers
6 | {
7 | public interface IController : IDisposable
8 | {
9 | string Name { get; }
10 | internal CancellationToken CancellationToken { get; }
11 | void AddDisposable(IDisposable disposable);
12 | void AddDisposables(IEnumerable collection);
13 | internal void Initialize(CancellationToken externalCancellationToken, CancellationToken parentCancellationToken);
14 | internal void Start();
15 | internal void Stop();
16 | internal void Stop(Exception rootCauseException);
17 | internal void ScanTree(List controllersTree, string prefix);
18 | }
19 |
20 | public interface IController
21 | {
22 | internal void SetArgInternal(TArg arg);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/ControllersTree/Core/Interfaces/IController.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: f707ca318eab4550af85ab3e874ab913
3 | timeCreated: 1631522012
--------------------------------------------------------------------------------
/src/ControllersTree/Core/Interfaces/IControllerDebugInfo.cs:
--------------------------------------------------------------------------------
1 | #if UNITY_EDITOR
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Threading;
5 | using UnityEngine;
6 |
7 | namespace Playtika.Controllers
8 | {
9 | internal interface IControllerDebugInfo : IEnumerable
10 | {
11 | internal string ControllerType { get; }
12 | internal string StateName { get; }
13 | internal Color StateColor { get; }
14 | internal string ScopeName { get; }
15 | void AddDisposable(IDisposable disposable);
16 | }
17 | }
18 | #endif
19 |
--------------------------------------------------------------------------------
/src/ControllersTree/Core/Interfaces/IControllerDebugInfo.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: f743a087b4e74810b7087504e1edf1d8
3 | timeCreated: 1711475460
--------------------------------------------------------------------------------
/src/ControllersTree/Core/Interfaces/IControllerFactory.cs:
--------------------------------------------------------------------------------
1 | namespace Playtika.Controllers
2 | {
3 | public interface IControllerFactory
4 | {
5 | IController Create() where T : class, IController;
6 | }
7 | }
--------------------------------------------------------------------------------
/src/ControllersTree/Core/Interfaces/IControllerFactory.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 0fe30bb0aea44f62a4d6a3a2ec0fa5dc
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/src/ControllersTree/Core/Interfaces/IControllerWithResult.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading;
3 | using Cysharp.Threading.Tasks;
4 |
5 | namespace Playtika.Controllers
6 | {
7 | public interface IControllerWithResult : IController
8 | {
9 | internal UniTask FlowAsync(CancellationToken cancellationToken);
10 | internal UniTask GetResult(CancellationToken token);
11 | internal void FailInternal(Exception exception);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/ControllersTree/Core/Interfaces/IControllerWithResult.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 718afbf6fb9448dc9eb8753ca7eaf06b
3 | timeCreated: 1631610958
--------------------------------------------------------------------------------
/src/ControllersTree/Core/Playtika.Controllers.asmdef:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Playtika.Controllers",
3 | "rootNamespace": "",
4 | "references": [
5 | "UniTask",
6 | "Unity.Profiling.Core"
7 | ],
8 | "includePlatforms": [],
9 | "excludePlatforms": [],
10 | "allowUnsafeCode": true,
11 | "overrideReferences": false,
12 | "precompiledReferences": [],
13 | "autoReferenced": true,
14 | "defineConstraints": [],
15 | "versionDefines": [],
16 | "noEngineReferences": false
17 | }
--------------------------------------------------------------------------------
/src/ControllersTree/Core/Playtika.Controllers.asmdef.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 79674ce12bb9f467aada6ac5d6ba8345
3 | AssemblyDefinitionImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/src/ControllersTree/Core/Profiler.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: d1c738452f0be498ead055c104ebb697
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/src/ControllersTree/Core/Profiler/FixedString.cs:
--------------------------------------------------------------------------------
1 | #if UNITY_CONTROLLERS_PROFILER
2 | using System;
3 | using System.Runtime.InteropServices;
4 |
5 | namespace Playtika.Controllers
6 | {
7 | [StructLayout(LayoutKind.Sequential)]
8 | public struct FixedString
9 | {
10 | public unsafe fixed byte Data[128];
11 |
12 | public override unsafe string ToString()
13 | {
14 | fixed (byte* dataPtr = Data)
15 | {
16 | return GetStringFromFixedBytes(dataPtr);
17 | }
18 | }
19 |
20 | private unsafe void Set(string value)
21 | {
22 | fixed (byte* dataPtr = Data)
23 | {
24 | CopyToFixedBytes(value, dataPtr, 128);
25 | }
26 | }
27 |
28 | private static unsafe void CopyToFixedBytes(string source, byte* destination, int maxLength)
29 | {
30 | if (source == null)
31 | {
32 | destination[0] = 0;
33 | return;
34 | }
35 |
36 | var bytes = System.Text.Encoding.UTF8.GetBytes(source);
37 | var bytesToCopy = Math.Min(bytes.Length, maxLength - 1);
38 |
39 | for (int i = 0; i < bytesToCopy; i++)
40 | {
41 | destination[i] = bytes[i];
42 | }
43 |
44 | destination[bytesToCopy] = 0;
45 | }
46 |
47 | private static unsafe string GetStringFromFixedBytes(byte* source)
48 | {
49 | var byteLength = 0;
50 | while (source[byteLength] != 0)
51 | {
52 | byteLength++;
53 | }
54 |
55 | return System.Text.Encoding.UTF8.GetString(source, byteLength);
56 | }
57 |
58 | public static implicit operator FixedString(string value)
59 | {
60 | var result = new FixedString();
61 | result.Set(value);
62 | return result;
63 | }
64 |
65 | public static implicit operator string(FixedString value)
66 | {
67 | return value.ToString();
68 | }
69 | }
70 | }
71 | #endif
--------------------------------------------------------------------------------
/src/ControllersTree/Core/Profiler/FixedString.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: ec5b5a8e7e364a50bf6786a3cc1bf0ac
3 | timeCreated: 1744622484
--------------------------------------------------------------------------------
/src/ControllersTree/Core/Profiler/Helper.cs:
--------------------------------------------------------------------------------
1 | #if UNITY_CONTROLLERS_PROFILER
2 | using System;
3 | using System.Runtime.InteropServices;
4 | using UnityEngine;
5 |
6 | namespace Playtika.Controllers
7 | {
8 | [StructLayout(LayoutKind.Sequential)]
9 | public struct NameSessionData
10 | {
11 | public int NameHash;
12 | public FixedString Name;
13 | }
14 |
15 | [StructLayout(LayoutKind.Sequential)]
16 | public struct CreateControllerFrameData
17 | {
18 | public int NameHash;
19 | public long StartTimeMSec;
20 | }
21 |
22 | [StructLayout(LayoutKind.Sequential)]
23 | public struct StopControllerFrameData
24 | {
25 | public int NameHash;
26 | public long ElapsedMilliseconds;
27 | }
28 |
29 | [StructLayout(LayoutKind.Sequential)]
30 | public struct RunControllerFrameData
31 | {
32 | public int NameHash;
33 | public int ScopeHash;
34 | public int InstanceId;
35 | public int Level;
36 | public long StartTimeMSec;
37 | public long ElapsedMilliseconds;
38 | }
39 |
40 | public static class Helper
41 | {
42 | public static readonly Guid ControllerProfilerGuid = new Guid("3E26292C-09A6-4DFD-8EC7-9BF7E5E3B837");
43 | public const int ControllerNameTag = 0;
44 | public const int ControllerStartTag = 1;
45 | public const int ControllerStopTag = 2;
46 | public const int ControllerRunTag = 3;
47 | public const int ScopeNameTag = 4;
48 |
49 | public const string TotalControllersCount = "Total Controllers Count";
50 | public const string ActiveControllersCount = "Active Controllers Count";
51 | public const string CreateThisFrameControllersCount = "Create This Frame Controllers Count";
52 | }
53 | }
54 | #endif
55 |
--------------------------------------------------------------------------------
/src/ControllersTree/Core/Profiler/Helper.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: c0bb821e372a46ffa78aa989720102a1
3 | timeCreated: 1743081058
--------------------------------------------------------------------------------
/src/ControllersTree/Core/States.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 15d96f2194aa442eb2701a500f877e3e
3 | timeCreated: 1706189482
--------------------------------------------------------------------------------
/src/ControllersTree/Core/States/ControllerState.cs:
--------------------------------------------------------------------------------
1 | namespace Playtika.Controllers
2 | {
3 | internal enum ControllerState
4 | {
5 | Created,
6 | Initialized,
7 | Running,
8 | Stopped,
9 | Disposed
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/ControllersTree/Core/States/ControllerState.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: bceb95e723a47694797c3b728e00dc19
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/src/ControllersTree/Core/States/ControllerWithResultState.cs:
--------------------------------------------------------------------------------
1 | namespace Playtika.Controllers
2 | {
3 | internal enum ControllerWithResultState
4 | {
5 | None,
6 | WaitForResultAsync,
7 | Completed,
8 | Failed
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/ControllersTree/Core/States/ControllerWithResultState.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: e3fc17be28c94e7797ad0ccb8155bfab
3 | timeCreated: 1704819390
--------------------------------------------------------------------------------
/src/ControllersTree/Core/Utils.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 637847f6504343d48e60eb687c5cca56
3 | timeCreated: 1710341916
--------------------------------------------------------------------------------
/src/ControllersTree/Core/Utils/ControllerCompositeDisposable.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using UnityEngine.Pool;
5 |
6 | namespace Playtika.Controllers
7 | {
8 | ///
9 | /// Component of controller that keeps related disposable object that must be disposed together with the running controller.
10 | ///
11 | public class ControllerCompositeDisposable : IDisposable
12 | {
13 | private readonly List _disposables = ListPool.Get();
14 |
15 | ///
16 | /// Adds a disposable object to the internal list of disposables.
17 | ///
18 | /// The disposable object to add to the list.
19 | public void Add(IDisposable disposable)
20 | {
21 | _disposables.Add(disposable);
22 | }
23 |
24 | ///
25 | /// Adds a collection of disposable objects to the internal list of disposables.
26 | ///
27 | /// The collection of disposable objects to add to the list.
28 | public void AddRange(IEnumerable collection)
29 | {
30 | _disposables.AddRange(collection);
31 | }
32 |
33 | public void Dispose()
34 | {
35 | using var pooledObject = ListPool.Get(out var exceptionList);
36 |
37 | foreach (var disposable in _disposables)
38 | {
39 | try
40 | {
41 | disposable.Dispose();
42 | }
43 | catch (Exception e)
44 | {
45 | exceptionList.Add(e);
46 | }
47 | }
48 |
49 | _disposables.Clear();
50 |
51 | ListPool.Release(_disposables);
52 |
53 | if (exceptionList.Any())
54 | {
55 | throw new AggregateException(exceptionList);
56 | }
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/ControllersTree/Core/Utils/ControllerCompositeDisposable.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 8d1d3b5672824a1fbf3d2534b352533d
3 | timeCreated: 1710339163
--------------------------------------------------------------------------------
/src/ControllersTree/Core/Utils/DisposableToken.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using JetBrains.Annotations;
3 |
4 | namespace Playtika.Controllers
5 | {
6 | ///
7 | /// Disposable Token for keeping action to be executed on dispose.
8 | ///
9 | public class DisposableToken : IDisposable
10 | {
11 | private readonly Action _disposeAction;
12 |
13 | public DisposableToken([NotNull] Action disposeAction)
14 | {
15 | _disposeAction = disposeAction ?? throw new ArgumentNullException(nameof(disposeAction));
16 | }
17 |
18 | public void Dispose()
19 | {
20 | _disposeAction.Invoke();
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/ControllersTree/Core/Utils/DisposableToken.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: bcda0a257ec74610986d22dc2b97f120
3 | timeCreated: 1734556610
--------------------------------------------------------------------------------
/src/ControllersTree/Editor.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 91c30646bd904d30a970932115182228
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/src/ControllersTree/Editor/ControllersHierarchy.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 729195b0ebc81484bb1a2e1c6ec317a7
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/src/ControllersTree/Editor/ControllersHierarchy/ControllerTabData.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using UnityEngine;
3 |
4 | namespace Playtika.Controllers.Editor
5 | {
6 | public readonly struct ControllerTabData
7 | {
8 | public readonly string TabName;
9 | public readonly GUIContent TabContent;
10 |
11 | public readonly bool IsClosable;
12 | public readonly Action TabDrawCallback;
13 | public readonly Action TabReloadCallback;
14 | public readonly Action TabOnCallback;
15 | public readonly Action TabOffCallback;
16 |
17 | public ControllerTabData(
18 | string tabName,
19 | string tabTooltip,
20 | bool isClosable,
21 | Action tabDrawCallback,
22 | Action tabReloadCallback,
23 | Action tabOnCallback = null,
24 | Action tabOffCallback = null)
25 | {
26 | TabName = tabName;
27 | TabContent = new GUIContent(TabName, tabTooltip);
28 |
29 | IsClosable = isClosable;
30 | TabDrawCallback = tabDrawCallback;
31 | TabReloadCallback = tabReloadCallback;
32 | TabOnCallback = tabOnCallback;
33 | TabOffCallback = tabOffCallback;
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/ControllersTree/Editor/ControllersHierarchy/ControllerTabData.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: e9fc7c13a94c4476a167ff3e2305e00c
3 | timeCreated: 1643136125
--------------------------------------------------------------------------------
/src/ControllersTree/Editor/ControllersHierarchy/ControllerTreeView.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 76778fe942284e418d3a85fa138b203d
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/src/ControllersTree/Editor/ControllersHierarchy/ControllersHierarchy.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 66e269b1075343b791d569fd24d50ff9
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/src/ControllersTree/Editor/ControllersHierarchy/ControllersHierarchyView.cs:
--------------------------------------------------------------------------------
1 | using UnityEditor;
2 | using UnityEngine;
3 |
4 | namespace Playtika.Controllers.Editor
5 | {
6 | internal class ControllersHierarchyView
7 | {
8 | private readonly ControllerTreeView _controllerTreeView;
9 | private readonly ControllersTreeViewModel _model;
10 |
11 | private string _searchString;
12 | private Vector3 _scrollPos;
13 |
14 | internal ControllersHierarchyView(ControllerTreeView controllerTreeView, ControllersTreeViewModel model)
15 | {
16 | _model = model;
17 | _controllerTreeView = controllerTreeView;
18 | }
19 |
20 | internal void Draw()
21 | {
22 | using var verticalScope = new GUILayout.VerticalScope();
23 | using (new GUILayout.HorizontalScope())
24 | {
25 | using (var vertScope = new EditorGUILayout.VerticalScope(
26 | GUI.skin.box, GUILayout.Width(_model.HierarchyWidth), GUILayout.Height(_model.TopPanelHeight)))
27 | {
28 | using (new GUILayout.HorizontalScope())
29 | {
30 | GUILayout.Space(4f);
31 | var searchString = GUILayout.TextField(_searchString, _model.SearchStyle, GUILayout.ExpandWidth(true));
32 | if (searchString != _searchString)
33 | {
34 | _searchString = searchString;
35 | _controllerTreeView.searchString = _searchString;
36 | _controllerTreeView.Reload();
37 | }
38 |
39 | if (GUILayout.Button("", _model.CancelSearchStyle))
40 | {
41 | _searchString = null;
42 | _controllerTreeView.searchString = _searchString;
43 | _controllerTreeView.Reload();
44 | }
45 |
46 | GUILayout.Space(2f);
47 | }
48 |
49 | GUILayout.Space(-36);
50 |
51 | using (var scrollScope = new GUILayout.ScrollViewScope(_scrollPos))
52 | {
53 | _scrollPos = scrollScope.scrollPosition;
54 | var rect = vertScope.rect;
55 | rect.width -= 8f;
56 | rect.height -= 26f;
57 | _controllerTreeView.OnGUI(rect);
58 | }
59 | }
60 |
61 | if (_model.IsRightPanelVisible)
62 | {
63 | var style = new GUIStyle(GUI.skin.textArea);
64 | style.padding.left = 2;
65 | style.padding.right = 2;
66 | using (var vertScope = new EditorGUILayout.VerticalScope(
67 | style, GUILayout.Width(ControllersTreeViewModel.SEPARATOR_SIZE), GUILayout.ExpandHeight(true)))
68 | {
69 | _model.SetVerticalSeparatorRect(vertScope.rect);
70 | EditorGUI.DrawRect(vertScope.rect, ControllersTreeHelper.DividingLineColor);
71 | }
72 | }
73 |
74 | _controllerTreeView.DrawRightPanel();
75 | }
76 |
77 | DrawBottom();
78 | }
79 |
80 | private void DrawBottom()
81 | {
82 | using var verticalScope = new GUILayout.VerticalScope(GUILayout.Height(_model.BottomPanelHeight));
83 | if (_model.IsBottomPanelVisible)
84 | {
85 | var style = new GUIStyle(GUI.skin.textArea);
86 | style.padding.top = 2;
87 | style.padding.bottom = 2;
88 | using var horizontalScope = new EditorGUILayout.HorizontalScope(
89 | style, GUILayout.Height(ControllersTreeViewModel.SEPARATOR_SIZE), GUILayout.ExpandWidth(true));
90 | _model.SetHorizontalSeparatorRect(horizontalScope.rect);
91 | EditorGUI.DrawRect(horizontalScope.rect, ControllersTreeHelper.DividingLineColor);
92 | }
93 |
94 | _controllerTreeView.DrawBottomPanel();
95 | }
96 |
97 | internal void Reload()
98 | {
99 | _controllerTreeView.Reload();
100 | }
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/src/ControllersTree/Editor/ControllersHierarchy/ControllersHierarchyView.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: f88cea12561c4c5383caa9529afe7666
3 | timeCreated: 1643196344
--------------------------------------------------------------------------------
/src/ControllersTree/Editor/ControllersHierarchy/ControllersInfoView.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using Playtika.Controllers;
3 | using UnityEditor;
4 | using UnityEngine;
5 |
6 | namespace Playtika.Controllers.Editor
7 | {
8 | internal class ControllersInfoView
9 | {
10 | private readonly ControllersTreeViewModel _model;
11 |
12 | private List _staticFields;
13 | private List _otherFields;
14 | private object _target;
15 | private Vector2 _scrollPosition;
16 |
17 | internal ControllersInfoView(ControllersTreeViewModel model)
18 | {
19 | _model = model;
20 | }
21 |
22 | internal void SelectedController(object target)
23 | {
24 | _target = target;
25 | if (target == null)
26 | {
27 | _staticFields = null;
28 | _otherFields = null;
29 | return;
30 | }
31 |
32 | _staticFields = new List();
33 | _otherFields = new List();
34 |
35 | var fieldsInfo = ControllersFieldsFactory.GetFields(target);
36 | foreach (var info in fieldsInfo)
37 | {
38 | if (info.IsStatic)
39 | {
40 | _staticFields.Add(ControllersFieldsFactory.CreateFieldDrawer(info, _target));
41 | }
42 | else
43 | {
44 | _otherFields.Add(ControllersFieldsFactory.CreateFieldDrawer(info, _target));
45 | }
46 | }
47 | }
48 |
49 | internal void DrawInfos()
50 | {
51 | if (!_model.IsBottomPanelVisible)
52 | {
53 | return;
54 | }
55 |
56 | using var verticalScope = new GUILayout.VerticalScope(GUI.skin.box, GUILayout.Height(_model.BottomPanelHeight));
57 | using var scrollScope = new GUILayout.ScrollViewScope(_scrollPosition);
58 | _scrollPosition = scrollScope.scrollPosition;
59 | GUILayout.Space(4);
60 | if (_target != null)
61 | {
62 | TryDrawFieldsPart(_staticFields, "Static or Const fields", Color.red, true);
63 | TryDrawFieldsPart(_otherFields, "Simple fields", Color.yellow);
64 | }
65 | else
66 | {
67 | EditorGUILayout.HelpBox("Controller not selected", MessageType.None);
68 | }
69 | }
70 |
71 | private void TryDrawFieldsPart(
72 | List drawers,
73 | string label,
74 | Color color,
75 | bool disabled = false)
76 | {
77 | var backgroundColor = GUI.backgroundColor;
78 | GUI.backgroundColor = color;
79 | using (new EditorGUI.DisabledScope(disabled))
80 | using (new GUILayout.VerticalScope(GUI.skin.box))
81 | {
82 | GUI.backgroundColor = backgroundColor;
83 |
84 | GUILayout.Label(label);
85 | if (drawers != null && drawers.Count > 0)
86 | {
87 | drawers.ForEach(f => f.Draw());
88 | }
89 | else
90 | {
91 | EditorGUILayout.HelpBox("Fields not found", MessageType.None);
92 | }
93 | }
94 | }
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/src/ControllersTree/Editor/ControllersHierarchy/ControllersInfoView.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: b82abebbe43d49e7bb720bc28b4f2231
3 | timeCreated: 1645778310
--------------------------------------------------------------------------------
/src/ControllersTree/Editor/ControllersHierarchy/ControllersMethodsView.cs:
--------------------------------------------------------------------------------
1 | using System.Collections;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Reflection;
5 | using Playtika.Controllers;
6 | using UnityEditor;
7 | using UnityEngine;
8 |
9 | namespace Playtika.Controllers.Editor
10 | {
11 | internal class ControllersMethodsView
12 | {
13 | private readonly ControllersTreeViewModel _model;
14 |
15 | private List _debugMethods;
16 | private List _simpleMethods;
17 | private List _disabledMethods;
18 |
19 | private Vector2 _scrollPosition;
20 | private object _invokeObject;
21 |
22 | internal ControllersMethodsView(ControllersTreeViewModel model)
23 | {
24 | _model = model;
25 | _debugMethods = new List();
26 | _simpleMethods = new List();
27 | _disabledMethods = new List();
28 | }
29 |
30 | internal void SelectedController(object invokeObject)
31 | {
32 | _debugMethods.Clear();
33 | _simpleMethods.Clear();
34 | _disabledMethods.Clear();
35 | _invokeObject = invokeObject;
36 |
37 | if (_invokeObject == null)
38 | {
39 | return;
40 | }
41 |
42 | var methods = invokeObject.GetType().GetMethods(BindingFlags.Public | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Instance);
43 | foreach (var method in methods)
44 | {
45 | var attribute = method.GetCustomAttributes(typeof(DebugMethodAttribute), true).SingleOrDefault();
46 | if (attribute != null)
47 | {
48 | _debugMethods.Add(method);
49 | }
50 | else if (method.GetParameters().Length == 0 && !((IList) _model.IgnoredMethods).Contains(method.Name))
51 | {
52 | _simpleMethods.Add(method);
53 | }
54 | else
55 | {
56 | _disabledMethods.Add(method);
57 | }
58 | }
59 | }
60 |
61 | internal void DrawMethods()
62 | {
63 | if (_model.IsRightPanelVisible)
64 | {
65 | using (new GUILayout.VerticalScope(GUI.skin.box, GUILayout.Width(_model.RightPanelWidth)))
66 | {
67 | using (var scrollScope = new GUILayout.ScrollViewScope(_scrollPosition))
68 | {
69 | _scrollPosition = scrollScope.scrollPosition;
70 | GUILayout.Space(4);
71 | DrawMethodsBlock(_debugMethods, "Debug methods:", Color.green);
72 | DrawMethodsBlock(_simpleMethods, "Available methods:", Color.yellow);
73 | DrawMethodsBlock(_disabledMethods, "Disabled methods:", Color.red, true);
74 | }
75 | }
76 | }
77 | }
78 |
79 | private void DrawMethodsBlock(
80 | List methods,
81 | string label,
82 | Color color,
83 | bool disabled = false)
84 | {
85 | var backgroundColor = GUI.backgroundColor;
86 | GUI.backgroundColor = color;
87 | using (new EditorGUI.DisabledScope(disabled))
88 | using (new GUILayout.VerticalScope(GUI.skin.box))
89 | {
90 | GUI.backgroundColor = backgroundColor;
91 |
92 | GUILayout.Label(label);
93 | if (methods.Count <= 0)
94 | {
95 | EditorGUILayout.HelpBox("Methods not found", MessageType.None);
96 | return;
97 | }
98 |
99 | foreach (var method in methods)
100 | {
101 | if (GUILayout.Button(method.Name))
102 | {
103 | method.Invoke(_invokeObject, null);
104 | }
105 | }
106 | }
107 | }
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/src/ControllersTree/Editor/ControllersHierarchy/ControllersMethodsView.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: ebf77e3da4d240f59c42782d5998f331
3 | timeCreated: 1645776674
--------------------------------------------------------------------------------
/src/ControllersTree/Editor/ControllersHierarchy/ControllersTabBarDrawer.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using UnityEditor;
3 | using UnityEngine;
4 |
5 | namespace Playtika.Controllers.Editor
6 | {
7 | public class ControllersTabBarDrawer
8 | {
9 | private readonly ControllersTreeViewModel _model;
10 |
11 | private List _tabData;
12 | private int _index = 0;
13 | private int? _removeIndex;
14 | private Vector2 _scrollPosition;
15 |
16 | public ControllersTabBarDrawer(ControllersTreeViewModel model, ControllerTabData rootTabData)
17 | {
18 | _model = model;
19 | SetData(rootTabData);
20 | }
21 |
22 | private void SetData(ControllerTabData rootTabData)
23 | {
24 | _tabData = new List();
25 | _tabData.Add(rootTabData);
26 | Select(_index);
27 | }
28 |
29 | public void AddData(ControllerTabData tabData)
30 | {
31 | _tabData.Add(tabData);
32 | }
33 |
34 | private void RemoveData(int index)
35 | {
36 | if (_index >= index)
37 | {
38 | --_index;
39 | }
40 |
41 | _removeIndex = index;
42 | }
43 |
44 | private void Select(int index)
45 | {
46 | _index = Mathf.Clamp(index, 0, _tabData?.Count - 1 ?? 0);
47 | }
48 |
49 | public void Draw()
50 | {
51 | if (_tabData == null || _tabData.Count == 0)
52 | {
53 | return;
54 | }
55 |
56 | using (var changeScope = new EditorGUI.ChangeCheckScope())
57 | {
58 | var index = _index;
59 |
60 | DrawTabBar();
61 |
62 | if (changeScope.changed)
63 | {
64 | _tabData[index].TabOffCallback?.Invoke();
65 | _tabData[_index].TabOnCallback?.Invoke();
66 | }
67 |
68 | _tabData[_index].TabDrawCallback?.Invoke();
69 | }
70 |
71 | if (_removeIndex.HasValue)
72 | {
73 | _tabData.RemoveAt(_removeIndex.Value);
74 | _removeIndex = null;
75 | }
76 | }
77 |
78 | public void Reload()
79 | {
80 | if (_tabData == null || _tabData.Count == 0 || _removeIndex.HasValue)
81 | {
82 | return;
83 | }
84 |
85 | _tabData[_index].TabReloadCallback();
86 | }
87 |
88 | private void DrawTabBar()
89 | {
90 | using var scrollScope = new EditorGUILayout.ScrollViewScope(_scrollPosition, GUIStyle.none, GUIStyle.none, GUILayout.ExpandHeight(false));
91 | _scrollPosition = scrollScope.scrollPosition;
92 |
93 | using var scope = new EditorGUILayout.HorizontalScope();
94 | for (int i = 0; i < _tabData.Count; ++i)
95 | {
96 | DrawTabButton(i);
97 | }
98 | }
99 |
100 | private void DrawTabButton(int index)
101 | {
102 | using var scope = new GUILayout.HorizontalScope(GUI.skin.box);
103 | var color = GUI.backgroundColor;
104 | GUI.backgroundColor = Color.clear;
105 |
106 | if (GUILayout.Button(_tabData[index].TabContent, GUI.skin.box, GUILayout.Height(20), GUILayout.Width(128)))
107 | {
108 | _index = index;
109 | }
110 |
111 | GUI.backgroundColor = color;
112 |
113 | if (_tabData[index].IsClosable)
114 | {
115 | using var verticalScope = new GUILayout.VerticalScope(GUILayout.Height(22), GUILayout.Width(20));
116 | GUILayout.Space(4);
117 | if (GUILayout.Button("", _model.CloseButtonStyle))
118 | {
119 | RemoveData(index);
120 | }
121 | }
122 |
123 | var colorRect = _index == index
124 | ? ControllersTreeHelper.SelectedColor
125 | : ControllersTreeHelper.UnselectedColor;
126 | var rect = GUILayoutUtility.GetLastRect();
127 | var lineRect = rect;
128 | lineRect.height = 2;
129 | var center = lineRect.center;
130 | center.y += rect.height;
131 | lineRect.center = center;
132 |
133 | if (rect.Contains(Event.current.mousePosition))
134 | {
135 | colorRect = ControllersTreeHelper.FocusedColor;
136 | }
137 |
138 | EditorGUI.DrawRect(lineRect, colorRect);
139 | }
140 | }
141 | }
142 |
--------------------------------------------------------------------------------
/src/ControllersTree/Editor/ControllersHierarchy/ControllersTabBarDrawer.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: ff87ca77c6a84bcc962e4507fe783eaa
3 | timeCreated: 1643130942
--------------------------------------------------------------------------------
/src/ControllersTree/Editor/ControllersHierarchy/ControllersTreeHelper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Playtika.Controllers;
3 | using UnityEditor.Graphs;
4 | using UnityEngine;
5 |
6 | namespace Playtika.Controllers.Editor
7 | {
8 | internal class ControllersTreeHelper
9 | {
10 | internal static readonly Color FocusedColor = new Color(0f, 0.66f, 1f);
11 | internal static readonly Color SelectedColor = new Color(0f, 0.66f, 1f);
12 | internal static readonly Color UnselectedColor = new Color(0.87f, 0.99f, 1f);
13 | internal static readonly Color DividingLineColor = new Color(0.13f, 0.13f, 0.13f, 0.75f);
14 | internal static readonly Color DarkGrayColor = new Color(0.13f, 0.13f, 0.13f, 0.25f);
15 | }
16 | }
--------------------------------------------------------------------------------
/src/ControllersTree/Editor/ControllersHierarchy/ControllersTreeHelper.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 4c98a4c164b543038abc32999b7407b7
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/src/ControllersTree/Editor/ControllersHierarchy/ControllersTreeViewItem.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using System.Reflection;
4 | using Playtika.Controllers;
5 | using UnityEditor.IMGUI.Controls;
6 |
7 | namespace Playtika.Controllers.Editor
8 | {
9 | internal class ControllersTreeViewItem : TreeViewItem
10 | {
11 | private readonly WeakReference _controllerWeakReference;
12 |
13 | internal IControllerDebugInfo ControllerDebugInfo
14 | {
15 | get
16 | {
17 | if (_controllerWeakReference.IsAlive)
18 | {
19 | return (IControllerDebugInfo)_controllerWeakReference.Target;
20 | }
21 |
22 | return null;
23 | }
24 | }
25 |
26 | internal ControllersTreeViewItem(
27 | int id,
28 | int depth,
29 | IControllerDebugInfo controllerDebugInfo)
30 | : base(id, depth, controllerDebugInfo.ToString())
31 | {
32 | _controllerWeakReference = new WeakReference(controllerDebugInfo);
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/ControllersTree/Editor/ControllersHierarchy/ControllersTreeViewItem.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 6df563f44a6343cb81b62048f962605a
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/src/ControllersTree/Editor/ControllersHierarchy/ControllersTreeViewModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Playtika.Controllers;
3 | using UnityEditor;
4 | using UnityEngine;
5 |
6 | namespace Playtika.Controllers.Editor
7 | {
8 | public class ControllersTreeViewModel
9 | {
10 | internal const float SEPARATOR_SIZE = 4f;
11 |
12 | private const float INTERNAL_SEPARATOR_SIZE = SEPARATOR_SIZE * 5;
13 | private const float WINDOW_HEIGHT_ADJUSTMENT = 75;
14 |
15 | internal event Action CreateNewTreeTab;
16 |
17 | internal GUIStyle ToolbarStyle { get; private set; }
18 | internal GUIStyle SearchStyle { get; private set; }
19 | internal GUIStyle CancelSearchStyle { get; private set; }
20 | internal GUIStyle CloseButtonStyle { get; private set; }
21 |
22 | internal bool IsBottomPanelVisible { get; private set; }
23 | internal bool IsRightPanelVisible { get; private set; }
24 | internal float HierarchyWidth => _windowSize.x * _hierarchyPanelWidthPercent;
25 | internal float RightPanelWidth => _windowSize.x * _rightPanelWidthPercent;
26 | internal float TopPanelHeight => _windowSize.y * _topPanelHeightPercent;
27 | internal float BottomPanelHeight => _windowSize.y * _bottomPanelHeightPercent;
28 | internal string[] IgnoredMethods { get; private set; }
29 |
30 | private Vector2 _windowSize;
31 | private bool _isDraggable;
32 | private bool _isHorizontal;
33 | private float _hierarchyPanelWidthPercent;
34 | private float _rightPanelWidthPercent;
35 | private float _topPanelHeightPercent;
36 | private float _bottomPanelHeightPercent;
37 |
38 | internal void LoadGuiSkin()
39 | {
40 | SearchStyle = EditorGUIUtility.GetBuiltinSkin(EditorSkin.Inspector).FindStyle("ToolbarSearchTextField");
41 | CancelSearchStyle = EditorGUIUtility.GetBuiltinSkin(EditorSkin.Inspector).FindStyle("ToolbarSearchCancelButton");
42 | if (SearchStyle == null || CancelSearchStyle == null)
43 | {
44 | // support for Unity versions with bug
45 | SearchStyle = EditorGUIUtility.GetBuiltinSkin(EditorSkin.Inspector).FindStyle("ToolbarSeachTextField");
46 | CancelSearchStyle = EditorGUIUtility.GetBuiltinSkin(EditorSkin.Inspector).FindStyle("ToolbarSeachCancelButton");
47 | }
48 | ToolbarStyle = EditorGUIUtility.GetBuiltinSkin(EditorSkin.Inspector).FindStyle("Toolbar");
49 | CloseButtonStyle = EditorGUIUtility.GetBuiltinSkin(EditorSkin.Inspector).FindStyle("WinBtnCloseMac");
50 | }
51 |
52 | internal void InvokeCreateNewTreeTab(IControllerDebugInfo controller)
53 | {
54 | CreateNewTreeTab?.Invoke(controller);
55 | }
56 |
57 | internal void SwitchRightPanelState()
58 | {
59 | IsRightPanelVisible = !IsRightPanelVisible;
60 | }
61 |
62 | internal void SwitchBottomPanelState()
63 | {
64 | IsBottomPanelVisible = !IsBottomPanelVisible;
65 | }
66 |
67 | internal void SetWindowSize(Vector2 size)
68 | {
69 | _windowSize = size - Vector2.up * WINDOW_HEIGHT_ADJUSTMENT;
70 | if (IsRightPanelVisible)
71 | {
72 | if (RightPanelWidth <= 0)
73 | {
74 | var percent = 0.75f - INTERNAL_SEPARATOR_SIZE / size.x;
75 | _hierarchyPanelWidthPercent = percent;
76 | _rightPanelWidthPercent = 1f - percent;
77 | }
78 | else
79 | {
80 | _hierarchyPanelWidthPercent = 1f - _rightPanelWidthPercent - INTERNAL_SEPARATOR_SIZE / size.x;
81 | }
82 | }
83 | else
84 | {
85 | _hierarchyPanelWidthPercent = 0;
86 | }
87 |
88 | if (IsBottomPanelVisible)
89 | {
90 | if (BottomPanelHeight <= 0)
91 | {
92 | _topPanelHeightPercent = 0.75f;
93 | _bottomPanelHeightPercent = 0.25f;
94 | }
95 | }
96 | else
97 | {
98 | _topPanelHeightPercent = 0;
99 | }
100 | }
101 |
102 | internal void SetVerticalSeparatorRect(Rect verticalSeparatorRect)
103 | {
104 | EditorGUIUtility.AddCursorRect(verticalSeparatorRect, MouseCursor.ResizeHorizontal);
105 | var newMousePosition = Event.current.mousePosition;
106 |
107 | if (Event.current.type == EventType.MouseDown && verticalSeparatorRect.Contains(newMousePosition))
108 | {
109 | _isDraggable = true;
110 | _isHorizontal = false;
111 | }
112 |
113 | if (_isDraggable && !_isHorizontal)
114 | {
115 | var percent = Mathf.Clamp(Event.current.mousePosition.x / _windowSize.x, 0.25f, 0.75f) - INTERNAL_SEPARATOR_SIZE / _windowSize.x;
116 | _hierarchyPanelWidthPercent = percent;
117 | _rightPanelWidthPercent = 1f - percent;
118 | }
119 |
120 | if (Event.current.type == EventType.MouseUp)
121 | {
122 | _isDraggable = false;
123 | }
124 | }
125 |
126 | internal void SetHorizontalSeparatorRect(Rect horizontalSeparatorRect)
127 | {
128 | EditorGUIUtility.AddCursorRect(horizontalSeparatorRect, MouseCursor.ResizeVertical);
129 | var newMousePosition = Event.current.mousePosition;
130 |
131 | if (Event.current.type == EventType.MouseDown && horizontalSeparatorRect.Contains(newMousePosition))
132 | {
133 | _isDraggable = true;
134 | _isHorizontal = true;
135 | }
136 |
137 | if (_isDraggable && _isHorizontal)
138 | {
139 | var percent = Mathf.Clamp(Event.current.mousePosition.y / _windowSize.y, 0.25f, 0.75f) - INTERNAL_SEPARATOR_SIZE / _windowSize.y;
140 | _topPanelHeightPercent = percent;
141 | _bottomPanelHeightPercent = 1f - percent;
142 | }
143 |
144 | if (Event.current.type == EventType.MouseUp)
145 | {
146 | _isDraggable = false;
147 | }
148 | }
149 |
150 | internal void SetIgnoredMethods(string[] ignoredMethods)
151 | {
152 | IgnoredMethods = ignoredMethods;
153 | }
154 | }
155 | }
156 |
--------------------------------------------------------------------------------
/src/ControllersTree/Editor/ControllersHierarchy/ControllersTreeViewModel.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 526e47a4418c4422b9bc1f618d968348
3 | timeCreated: 1643129982
--------------------------------------------------------------------------------
/src/ControllersTree/Editor/ControllersHierarchy/FieldsDrawers.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: a815ec5067ae48d885d35ca155913e86
3 | timeCreated: 1646040783
--------------------------------------------------------------------------------
/src/ControllersTree/Editor/ControllersHierarchy/FieldsDrawers/ControllersActionFieldDrawer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Reflection;
3 | using UnityEngine;
4 |
5 | namespace Playtika.Controllers.Editor
6 | {
7 | public class ControllersActionFieldDrawer : ControllersBaseFieldDrawer
8 | {
9 | public ControllersActionFieldDrawer(
10 | FieldInfo fieldInfo,
11 | object target)
12 | : base(fieldInfo, target)
13 | {
14 | }
15 |
16 | protected override void OnDraw()
17 | {
18 | using (new GUILayout.HorizontalScope())
19 | {
20 | GUILayout.Label(FieldInfo.Name);
21 | GUILayout.FlexibleSpace();
22 | if (GUILayout.Button("Invoke"))
23 | {
24 | if (FieldInfo.GetValue(Target) is Action action)
25 | {
26 | action?.Invoke();
27 | }
28 | }
29 | }
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/ControllersTree/Editor/ControllersHierarchy/FieldsDrawers/ControllersActionFieldDrawer.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 142fec94f5504b6d8d580ef832506202
3 | timeCreated: 1646131426
--------------------------------------------------------------------------------
/src/ControllersTree/Editor/ControllersHierarchy/FieldsDrawers/ControllersBaseFieldDrawer.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using UnityEditor;
3 | using UnityEngine;
4 |
5 | namespace Playtika.Controllers.Editor
6 | {
7 | public abstract class ControllersBaseFieldDrawer
8 | {
9 | protected const string NULL_VALUE = "NULL";
10 |
11 | protected readonly FieldInfo FieldInfo;
12 | protected readonly object Target;
13 |
14 | protected ControllersBaseFieldDrawer(FieldInfo fieldInfo, object target)
15 | {
16 | FieldInfo = fieldInfo;
17 | Target = target;
18 | }
19 |
20 | public void Draw()
21 | {
22 | try
23 | {
24 | EditorGUI.indentLevel += 1;
25 | var backgroundColor = GUI.backgroundColor;
26 | GUI.backgroundColor = Color.black;
27 | using (new GUILayout.VerticalScope(GUI.skin.box))
28 | {
29 | GUI.backgroundColor = backgroundColor;
30 | OnDraw();
31 | }
32 | }
33 | finally
34 | {
35 | EditorGUI.indentLevel -= 1;
36 | }
37 | }
38 |
39 | protected abstract void OnDraw();
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/ControllersTree/Editor/ControllersHierarchy/FieldsDrawers/ControllersBaseFieldDrawer.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 78649b1972244c519b61d621abb43a01
3 | timeCreated: 1646040809
--------------------------------------------------------------------------------
/src/ControllersTree/Editor/ControllersHierarchy/FieldsDrawers/ControllersBooleanFieldDrawer.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using UnityEditor;
3 | using UnityEngine;
4 |
5 | namespace Playtika.Controllers.Editor
6 | {
7 | public class ControllersBooleanFieldDrawer : ControllersBaseFieldDrawer
8 | {
9 | public ControllersBooleanFieldDrawer(
10 | FieldInfo fieldInfo,
11 | object target)
12 | : base(fieldInfo, target)
13 | {
14 | }
15 |
16 | protected override void OnDraw()
17 | {
18 | using (new GUILayout.HorizontalScope())
19 | {
20 | GUILayout.Label(FieldInfo.Name);
21 | GUILayout.FlexibleSpace();
22 | using (var scope = new EditorGUI.ChangeCheckScope())
23 | {
24 | if (FieldInfo.GetValue(Target) is bool value)
25 | {
26 | value = GUILayout.Toggle(value, "");
27 | if (scope.changed)
28 | {
29 | FieldInfo.SetValue(Target, value);
30 | }
31 | }
32 | }
33 | }
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/ControllersTree/Editor/ControllersHierarchy/FieldsDrawers/ControllersBooleanFieldDrawer.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: f3854c2d6a8944a0807d6463c37a51ca
3 | timeCreated: 1646133631
--------------------------------------------------------------------------------
/src/ControllersTree/Editor/ControllersHierarchy/FieldsDrawers/ControllersCollectionFieldDrawer.cs:
--------------------------------------------------------------------------------
1 | using System.Collections;
2 | using System.Reflection;
3 | using UnityEngine;
4 |
5 | namespace Playtika.Controllers.Editor
6 | {
7 | public class ControllersCollectionFieldDrawer : ControllersBaseFieldDrawer
8 | {
9 | private bool _foldout;
10 |
11 | public ControllersCollectionFieldDrawer(
12 | FieldInfo fieldInfo,
13 | object target)
14 | : base(fieldInfo, target)
15 | {
16 | }
17 |
18 | protected override void OnDraw()
19 | {
20 | using (new GUILayout.HorizontalScope())
21 | {
22 | GUILayout.Label(FieldInfo.Name);
23 | GUILayout.FlexibleSpace();
24 | GUILayout.Label(FieldInfo.GetValue(Target)?.ToString() ?? NULL_VALUE);
25 |
26 | if (GUILayout.Button(_foldout ? "-" : "+"))
27 | {
28 | _foldout = !_foldout;
29 | }
30 | }
31 |
32 | if (_foldout && FieldInfo.GetValue(Target) is ICollection collection)
33 | {
34 | using (new GUILayout.VerticalScope())
35 | {
36 | var index = 0;
37 | foreach (var value in collection)
38 | {
39 | using (new GUILayout.HorizontalScope())
40 | {
41 | GUILayout.Label(index.ToString("D3"));
42 | GUILayout.FlexibleSpace();
43 | GUILayout.Label(value?.ToString() ?? NULL_VALUE);
44 | ++index;
45 | }
46 | }
47 | }
48 | }
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/ControllersTree/Editor/ControllersHierarchy/FieldsDrawers/ControllersCollectionFieldDrawer.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: c320ed31153144ad9a2a91ab990a3df5
3 | timeCreated: 1646126641
--------------------------------------------------------------------------------
/src/ControllersTree/Editor/ControllersHierarchy/FieldsDrawers/ControllersFieldsFactory.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections;
3 | using System.Reflection;
4 |
5 | namespace Playtika.Controllers.Editor
6 | {
7 | public class ControllersFieldsFactory
8 | {
9 | public static FieldInfo[] GetFields(object target)
10 | {
11 | return target.GetType().GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Instance);
12 | }
13 |
14 | public static ControllersBaseFieldDrawer CreateFieldDrawer(FieldInfo fieldInfo, object target)
15 | {
16 | if (fieldInfo.IsStatic)
17 | {
18 | return new ControllersLabelFieldDrawer(fieldInfo, target);
19 | }
20 |
21 | var value = fieldInfo.GetValue(target);
22 |
23 | switch (value)
24 | {
25 | case string _:
26 | return new ControllersStringFieldDrawer(fieldInfo, target);
27 | case int _:
28 | return new ControllersIntegerFieldDrawer(fieldInfo, target);
29 | case bool _:
30 | return new ControllersBooleanFieldDrawer(fieldInfo, target);
31 | case ICollection _:
32 | return new ControllersCollectionFieldDrawer(fieldInfo, target);
33 | case Action _:
34 | return new ControllersActionFieldDrawer(fieldInfo, target);
35 | case UnityEngine.Object _:
36 | return new ControllersUnityObjectFieldDrawer(fieldInfo, target);
37 | }
38 |
39 | return new ControllersParentObjectFieldDrawer(fieldInfo, target);
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/ControllersTree/Editor/ControllersHierarchy/FieldsDrawers/ControllersFieldsFactory.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 4b5b74fee88f43c1a5fc5884927707b2
3 | timeCreated: 1646048299
--------------------------------------------------------------------------------
/src/ControllersTree/Editor/ControllersHierarchy/FieldsDrawers/ControllersIntegerFieldDrawer.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using UnityEditor;
3 | using UnityEngine;
4 |
5 | namespace Playtika.Controllers.Editor
6 | {
7 | public class ControllersIntegerFieldDrawer : ControllersBaseFieldDrawer
8 | {
9 | public ControllersIntegerFieldDrawer(
10 | FieldInfo fieldInfo,
11 | object target)
12 | : base(fieldInfo, target)
13 | {
14 | }
15 |
16 | protected override void OnDraw()
17 | {
18 | using (new GUILayout.HorizontalScope())
19 | {
20 | GUILayout.Label(FieldInfo.Name);
21 | GUILayout.FlexibleSpace();
22 | using (var scope = new EditorGUI.ChangeCheckScope())
23 | {
24 | var value = FieldInfo.GetValue(Target) is int
25 | ? (int) FieldInfo.GetValue(Target)
26 | : 0;
27 | value = EditorGUILayout.IntField(value);
28 | if (scope.changed)
29 | {
30 | FieldInfo.SetValue(Target, value);
31 | }
32 | }
33 | }
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/ControllersTree/Editor/ControllersHierarchy/FieldsDrawers/ControllersIntegerFieldDrawer.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: ce073ee5fbaa454788789fa07d647e68
3 | timeCreated: 1646126317
--------------------------------------------------------------------------------
/src/ControllersTree/Editor/ControllersHierarchy/FieldsDrawers/ControllersLabelFieldDrawer.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using UnityEditor;
3 | using UnityEngine;
4 |
5 | namespace Playtika.Controllers.Editor
6 | {
7 | public class ControllersLabelFieldDrawer : ControllersBaseFieldDrawer
8 | {
9 | public ControllersLabelFieldDrawer(
10 | FieldInfo fieldInfo,
11 | object target)
12 | : base(fieldInfo, target)
13 | {
14 | }
15 |
16 | protected override void OnDraw()
17 | {
18 | using (new GUILayout.HorizontalScope())
19 | {
20 | GUILayout.Label(FieldInfo.Name);
21 | GUILayout.FlexibleSpace();
22 | GUILayout.Label(FieldInfo.GetValue(Target)?.ToString() ?? NULL_VALUE);
23 | }
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/ControllersTree/Editor/ControllersHierarchy/FieldsDrawers/ControllersLabelFieldDrawer.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 8b9b1176ea244b35b192db6d4f1791bd
3 | timeCreated: 1646051705
--------------------------------------------------------------------------------
/src/ControllersTree/Editor/ControllersHierarchy/FieldsDrawers/ControllersParentObjectFieldDrawer.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Reflection;
3 | using UnityEditor;
4 | using UnityEngine;
5 |
6 | namespace Playtika.Controllers.Editor
7 | {
8 | public class ControllersParentObjectFieldDrawer : ControllersBaseFieldDrawer
9 | {
10 | private List _staticChildren;
11 | private List _simpleChildren;
12 | private object _childTarget;
13 | private string _value;
14 |
15 | public ControllersParentObjectFieldDrawer(
16 | FieldInfo fieldInfo,
17 | object target)
18 | : base(
19 | fieldInfo,
20 | target)
21 | {
22 | }
23 |
24 | protected override void OnDraw()
25 | {
26 | using (new GUILayout.HorizontalScope())
27 | {
28 | _value = FieldInfo.GetValue(Target)?.ToString() ?? NULL_VALUE;
29 |
30 | GUILayout.Label(FieldInfo.Name);
31 | GUILayout.FlexibleSpace();
32 | GUILayout.Label(_value);
33 |
34 | using (new EditorGUI.DisabledScope(_value == NULL_VALUE))
35 | {
36 | if (_simpleChildren == null && _staticChildren == null)
37 | {
38 | if (GUILayout.Button("+"))
39 | {
40 | InitializeChildren();
41 | }
42 | }
43 | else
44 | {
45 | if (GUILayout.Button("-"))
46 | {
47 | RemoveChildren();
48 | }
49 | }
50 | }
51 | }
52 |
53 | TryDrawChildrenFields();
54 | }
55 |
56 | private void TryDrawChildrenFields()
57 | {
58 | if (_staticChildren != null)
59 | {
60 | DrawFieldsPart(_staticChildren, "Static or Const fields", Color.red);
61 | }
62 |
63 | if (_simpleChildren != null)
64 | {
65 | DrawFieldsPart(_simpleChildren, "Simple fields", Color.yellow);
66 | }
67 | }
68 |
69 | private void DrawFieldsPart(
70 | List drawers,
71 | string label,
72 | Color color)
73 | {
74 | var backgroundColor = GUI.backgroundColor;
75 | GUI.backgroundColor = color;
76 | using (new GUILayout.VerticalScope(GUI.skin.box))
77 | {
78 | GUI.backgroundColor = backgroundColor;
79 |
80 | GUILayout.Label(label);
81 | if (drawers.Count > 0)
82 | {
83 | drawers.ForEach(f => f.Draw());
84 | }
85 | else
86 | {
87 | EditorGUILayout.HelpBox("Fields not found", MessageType.None);
88 | }
89 | }
90 | }
91 |
92 | private void InitializeChildren()
93 | {
94 | _childTarget = FieldInfo.GetValue(Target);
95 | var childInfos = ControllersFieldsFactory.GetFields(_childTarget);
96 | if (childInfos != null)
97 | {
98 | _simpleChildren = new List();
99 | _staticChildren = new List();
100 | foreach (var item in childInfos)
101 | {
102 | var fieldInfo = ControllersFieldsFactory.CreateFieldDrawer(item, _childTarget);
103 | if (fieldInfo != null)
104 | {
105 | if (item.IsStatic)
106 | {
107 | _staticChildren.Add(fieldInfo);
108 | }
109 | else
110 | {
111 | _simpleChildren.Add(fieldInfo);
112 | }
113 | }
114 | }
115 | }
116 | }
117 |
118 | private void RemoveChildren()
119 | {
120 | _childTarget = null;
121 | _simpleChildren = null;
122 | _staticChildren = null;
123 | }
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/src/ControllersTree/Editor/ControllersHierarchy/FieldsDrawers/ControllersParentObjectFieldDrawer.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 18521e608dd64d94ae96c0c953505abe
3 | timeCreated: 1646042779
--------------------------------------------------------------------------------
/src/ControllersTree/Editor/ControllersHierarchy/FieldsDrawers/ControllersStringFieldDrawer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Reflection;
3 | using UnityEditor;
4 | using UnityEngine;
5 |
6 | namespace Playtika.Controllers.Editor
7 | {
8 | public class ControllersStringFieldDrawer : ControllersBaseFieldDrawer
9 | {
10 | public ControllersStringFieldDrawer(
11 | FieldInfo fieldInfo,
12 | object target)
13 | : base(fieldInfo, target)
14 | {
15 | }
16 |
17 | protected override void OnDraw()
18 | {
19 | using (new GUILayout.HorizontalScope())
20 | {
21 | GUILayout.Label(FieldInfo.Name);
22 | GUILayout.FlexibleSpace();
23 | using (var scope = new EditorGUI.ChangeCheckScope())
24 | {
25 | var text = GUILayout.TextArea(FieldInfo.GetValue(Target)?.ToString() ?? NULL_VALUE);
26 | if (scope.changed)
27 | {
28 | FieldInfo.SetValue(Target, text);
29 | }
30 | }
31 | }
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/ControllersTree/Editor/ControllersHierarchy/FieldsDrawers/ControllersStringFieldDrawer.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 1a8a19df09ee4bc690b5a78bba07d22c
3 | timeCreated: 1646059735
--------------------------------------------------------------------------------
/src/ControllersTree/Editor/ControllersHierarchy/FieldsDrawers/ControllersUnityObjectFieldDrawer.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using UnityEditor;
3 | using UnityEngine;
4 |
5 | namespace Playtika.Controllers.Editor
6 | {
7 | public class ControllersUnityObjectFieldDrawer: ControllersBaseFieldDrawer
8 | {
9 | public ControllersUnityObjectFieldDrawer(
10 | FieldInfo fieldInfo,
11 | object target)
12 | : base(fieldInfo, target)
13 | {
14 | }
15 |
16 | protected override void OnDraw()
17 | {
18 | using (new GUILayout.HorizontalScope())
19 | {
20 | GUILayout.Label(FieldInfo.Name);
21 | GUILayout.FlexibleSpace();
22 | var obj = FieldInfo.GetValue(Target);
23 | if (obj == null)
24 | {
25 | GUILayout.Label(NULL_VALUE);
26 | }
27 | else
28 | {
29 | EditorGUILayout.ObjectField((Object) obj, typeof(Object), true);
30 | }
31 | }
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/ControllersTree/Editor/ControllersHierarchy/FieldsDrawers/ControllersUnityObjectFieldDrawer.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 347f95dc6fd54cdb9f1a25cade9ec4e1
3 | timeCreated: 1647092654
--------------------------------------------------------------------------------
/src/ControllersTree/Editor/ControllersHierarchy/Playtika.Controllers.Editor.asmdef:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Playtika.Controllers.Editor",
3 | "references": [
4 | "Playtika.Controllers"
5 | ],
6 | "optionalUnityReferences": [],
7 | "includePlatforms": [
8 | "Editor"
9 | ],
10 | "excludePlatforms": [],
11 | "allowUnsafeCode": false
12 | }
--------------------------------------------------------------------------------
/src/ControllersTree/Editor/ControllersHierarchy/Playtika.Controllers.Editor.asmdef.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: b0fee331efa9941619d7591163ee90c7
3 | AssemblyDefinitionImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/src/ControllersTree/Editor/ControllersProfiler.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: e93af593fe6f245d294b5246fbaa0e6f
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/src/ControllersTree/Editor/ControllersProfiler/ControllerData.cs:
--------------------------------------------------------------------------------
1 | #if UNITY_CONTROLLERS_PROFILER
2 | namespace Modules.Controller.Editor
3 | {
4 | internal sealed class ControllerData
5 | {
6 | public string ControllerName;
7 | public string TimeData;
8 | }
9 | }
10 | #endif
--------------------------------------------------------------------------------
/src/ControllersTree/Editor/ControllersProfiler/ControllerData.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: ee5f7ac6df3345bab739de63878866cd
3 | timeCreated: 1748442516
--------------------------------------------------------------------------------
/src/ControllersTree/Editor/ControllersProfiler/ControllerLiveData.cs:
--------------------------------------------------------------------------------
1 | #if UNITY_CONTROLLERS_PROFILER
2 | using UnityEngine;
3 |
4 | namespace Modules.Controller.Editor
5 | {
6 | internal sealed class ControllerLiveData
7 | {
8 | public string ControllerName;
9 | public Color ControllerColor;
10 | public string ScopeName;
11 | public Color ScopeColor;
12 | public long StartTimeMSec;
13 | public long LifeTimeMSec;
14 | }
15 | }
16 | #endif
--------------------------------------------------------------------------------
/src/ControllersTree/Editor/ControllersProfiler/ControllerLiveData.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: c8f905aff9bd4b5ea7038a0fcda0016c
3 | timeCreated: 1748442524
--------------------------------------------------------------------------------
/src/ControllersTree/Editor/ControllersProfiler/ControllersProfilerModule.cs:
--------------------------------------------------------------------------------
1 | #if UNITY_CONTROLLERS_PROFILER
2 | using Playtika.Controllers;
3 | using Unity.Profiling;
4 | using Unity.Profiling.Editor;
5 |
6 | namespace Modules.Controller.Editor
7 | {
8 | [System.Serializable]
9 | [ProfilerModuleMetadata("Controllers profiler")]
10 | public class ControllersProfilerModule : ProfilerModule
11 | {
12 | private static readonly ProfilerCounterDescriptor[] Counters = new ProfilerCounterDescriptor[]
13 | {
14 | new ProfilerCounterDescriptor(Helper.ActiveControllersCount, ProfilerCategory.Scripts),
15 | new ProfilerCounterDescriptor(Helper.TotalControllersCount, ProfilerCategory.Scripts),
16 | new ProfilerCounterDescriptor(Helper.CreateThisFrameControllersCount, ProfilerCategory.Scripts),
17 | };
18 |
19 | public ControllersProfilerModule()
20 | : base(Counters)
21 | {
22 | }
23 |
24 | public override ProfilerModuleViewController CreateDetailsViewController()
25 | {
26 | return new ControllersProfilerModuleViewController(ProfilerWindow);
27 | }
28 | }
29 | }
30 | #endif
--------------------------------------------------------------------------------
/src/ControllersTree/Editor/ControllersProfiler/ControllersProfilerModule.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 1ab8eaed533094bada3f001bedfe374d
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/src/ControllersTree/Editor/ControllersProfiler/ControllersProfilerModuleViewController.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: b7eae78773b514119ba1faeed2fd5ec6
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/src/ControllersTree/Editor/ControllersProfiler/CreatedAndDestroyedControllersListView.cs:
--------------------------------------------------------------------------------
1 | #if UNITY_CONTROLLERS_PROFILER
2 | using System.Collections.Generic;
3 | using UnityEngine.UIElements;
4 |
5 | namespace Modules.Controller.Editor
6 | {
7 | internal class CreatedAndDestroyedControllersListView : ListView
8 | {
9 | private const float ItemHeight = 16f;
10 |
11 | internal CreatedAndDestroyedControllersListView(List controllers)
12 | : base()
13 | {
14 | itemsSource = controllers;
15 | Setup();
16 | Rebuild();
17 | }
18 |
19 | private void Setup()
20 | {
21 | fixedItemHeight = ItemHeight;
22 | makeItem = MakeStartStopListItem;
23 | bindItem = BindItem;
24 | style.flexGrow = 1.0f;
25 | }
26 |
27 | private void BindItem(VisualElement row, int index)
28 | {
29 | if (itemsSource == null || index >= itemsSource.Count)
30 | {
31 | return;
32 | }
33 |
34 | var controllerNameLabel = row[0] as Label;
35 | var timeDataLabel = row[1] as Label;
36 |
37 | var item = itemsSource[index] as ControllerData;
38 |
39 | controllerNameLabel.text = item.ControllerName;
40 | timeDataLabel.text = item.TimeData;
41 | }
42 |
43 | private static VisualElement MakeStartStopListItem()
44 | {
45 | var row = new VisualElement();
46 | row.style.flexDirection = FlexDirection.Row;
47 | row.style.paddingTop = 2;
48 | row.style.paddingBottom = 2;
49 |
50 | var col1 = new Label();
51 | col1.style.flexGrow = 1;
52 | col1.style.marginRight = 4;
53 | col1.style.overflow = Overflow.Hidden;
54 | col1.style.whiteSpace = WhiteSpace.NoWrap;
55 |
56 | var col2 = new Label();
57 | col2.style.width = 60;
58 | col2.style.marginRight = 4;
59 | row.Add(col1);
60 | row.Add(col2);
61 |
62 | return row;
63 | }
64 | }
65 | }
66 | #endif
--------------------------------------------------------------------------------
/src/ControllersTree/Editor/ControllersProfiler/CreatedAndDestroyedControllersListView.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: c23222482baf496ab19990ba6dc65682
3 | timeCreated: 1748442412
--------------------------------------------------------------------------------
/src/ControllersTree/Editor/ControllersProfiler/LiveControllersListView.cs:
--------------------------------------------------------------------------------
1 | #if UNITY_CONTROLLERS_PROFILER
2 | using System;
3 | using System.Collections.Generic;
4 | using UnityEngine.UIElements;
5 | using UnityEngine;
6 |
7 | namespace Modules.Controller.Editor
8 | {
9 | internal class LiveControllersListView : ListView
10 | {
11 | private const float ItemHeight = 16f;
12 |
13 | internal LiveControllersListView(List controllers)
14 | : base()
15 | {
16 | itemsSource = controllers;
17 | Setup();
18 | Rebuild();
19 | }
20 |
21 | internal static VisualElement FillLifetimeListHeader()
22 | {
23 | var row = MakeLifetimeListItem();
24 | row.style.height = ItemHeight * 2;
25 | var controllerNameLabel = row[0] as Label;
26 | var scopeNameLabel = row[1] as Label;
27 | var onStartTimeLabel = row[2] as Label;
28 | var lifetimeLabel = row[3] as Label;
29 |
30 | controllerNameLabel.text = "Controller name";
31 | ApplyLabelStyle(controllerNameLabel);
32 | scopeNameLabel.text = "Scope name";
33 | ApplyLabelStyle(scopeNameLabel);
34 | onStartTimeLabel.text = "OnStart\n(MSec)";
35 | ApplyLabelStyle(onStartTimeLabel);
36 | onStartTimeLabel.style.unityTextAlign = TextAnchor.MiddleLeft;
37 | lifetimeLabel.text = "Lifetime\n(MSec)";
38 | ApplyLabelStyle(lifetimeLabel);
39 | lifetimeLabel.style.unityTextAlign = TextAnchor.MiddleLeft;
40 | lifetimeLabel.style.width = 74;
41 |
42 | return row;
43 | }
44 |
45 | private void Setup()
46 | {
47 | fixedItemHeight = ItemHeight;
48 | makeItem = MakeLifetimeListItem;
49 | bindItem = BindItem;
50 | style.flexGrow = 1.0f;
51 | }
52 |
53 | private static VisualElement MakeLifetimeListItem()
54 | {
55 | var row = new VisualElement();
56 | row.style.flexDirection = FlexDirection.Row;
57 | row.style.paddingTop = 2;
58 | row.style.paddingBottom = 2;
59 |
60 | var col1 = new Label();
61 | col1.style.flexGrow = 1;
62 | col1.style.marginRight = 4;
63 | col1.style.overflow = Overflow.Hidden;
64 | col1.style.whiteSpace = WhiteSpace.NoWrap;
65 |
66 | var col2 = new Label();
67 | col2.style.width = 150;
68 | col2.style.unityTextAlign = TextAnchor.MiddleCenter;
69 | col2.style.marginRight = 4;
70 | col2.style.overflow = Overflow.Hidden;
71 | col2.style.whiteSpace = WhiteSpace.NoWrap;
72 |
73 | var col3 = new Label();
74 | col3.style.width = 60;
75 | col3.style.marginRight = 4;
76 |
77 | var col4 = new Label();
78 | col4.style.width = 60;
79 |
80 | row.Add(col1);
81 | row.Add(col2);
82 | row.Add(col3);
83 | row.Add(col4);
84 |
85 | return row;
86 | }
87 |
88 | private void BindItem(VisualElement row, int index)
89 | {
90 | if (itemsSource == null || index >= itemsSource.Count)
91 | {
92 | return;
93 | }
94 |
95 | var controllerNameLabel = row[0] as Label;
96 | var scopeNameLabel = row[1] as Label;
97 | var onStartTimeLabel = row[2] as Label;
98 | var lifetimeLabel = row[3] as Label;
99 |
100 | var item = itemsSource[index] as ControllerLiveData;
101 |
102 | controllerNameLabel.text = item.ControllerName;
103 | controllerNameLabel.style.color = item.ControllerColor;
104 |
105 | scopeNameLabel.text = item.ScopeName;
106 | scopeNameLabel.style.backgroundColor = item.ScopeColor;
107 |
108 | var startTime = item.StartTimeMSec;
109 | onStartTimeLabel.text = startTime.ToString();
110 | onStartTimeLabel.style.color = startTime > 0
111 | ? Color.red
112 | : Color.gray;
113 |
114 | lifetimeLabel.text = item.LifeTimeMSec.ToString();
115 | }
116 |
117 | private static void ApplyLabelStyle(Label label)
118 | {
119 | label.style.color = Color.white;
120 | label.style.unityFontStyleAndWeight = FontStyle.Bold;
121 | label.style.unityTextAlign = TextAnchor.MiddleCenter;
122 | label.style.height = ItemHeight * 2f;
123 | label.style.alignSelf = Align.Center;
124 | label.style.justifyContent = Justify.Center;
125 | }
126 | }
127 | }
128 | #endif
129 |
--------------------------------------------------------------------------------
/src/ControllersTree/Editor/ControllersProfiler/LiveControllersListView.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: c3b2c0960855640f78116e6b1c566ae9
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/src/ControllersTree/Editor/ControllersProfiler/Playtika.ControllersProfiler.Editor.asmdef:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Playtika.ControllersProfiler.Editor",
3 | "rootNamespace": "",
4 | "references": [
5 | "Playtika.Controllers"
6 | ],
7 | "includePlatforms": [
8 | "Editor"
9 | ],
10 | "excludePlatforms": [],
11 | "allowUnsafeCode": false,
12 | "overrideReferences": false,
13 | "precompiledReferences": [],
14 | "autoReferenced": true,
15 | "defineConstraints": [],
16 | "versionDefines": [],
17 | "noEngineReferences": false
18 | }
--------------------------------------------------------------------------------
/src/ControllersTree/Editor/ControllersProfiler/Playtika.ControllersProfiler.Editor.asmdef.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 2a65724b6c4f446c3b79830c77ccd24e
3 | AssemblyDefinitionImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/src/ControllersTree/Substitute.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: ec1f86e2d0dd74811b4056809246fee6
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/src/ControllersTree/Substitute/Runtime.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: d2e78271553f84e35880ece99f778081
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/src/ControllersTree/Substitute/Runtime/Playtika.Controllers.Substitute.asmdef:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Playtika.Controllers.Substitute",
3 | "rootNamespace": "",
4 | "references": [
5 | "UniTask",
6 | "Playtika.Controllers"
7 | ],
8 | "includePlatforms": [],
9 | "excludePlatforms": [],
10 | "allowUnsafeCode": false,
11 | "overrideReferences": false,
12 | "precompiledReferences": [],
13 | "autoReferenced": true,
14 | "versionDefines": [],
15 | "noEngineReferences": false,
16 | "testAssemblies": true
17 | }
--------------------------------------------------------------------------------
/src/ControllersTree/Substitute/Runtime/Playtika.Controllers.Substitute.asmdef.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: cfbcd2ac455cc4b8aa305c6452bcdb48
3 | AssemblyDefinitionImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/src/ControllersTree/Substitute/Runtime/SubstituteController.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Playtika.Controllers.Substitute
4 | {
5 | ///
6 | /// Controller Stub for tests.
7 | ///
8 | public class SubstituteController : ControllerBase
9 | {
10 | public SubstituteController()
11 | : base(null)
12 | {
13 | }
14 | }
15 |
16 | ///
17 | /// Generic Controller Stub for tests with ability to define fake behaviour.
18 | ///
19 | ///
20 | public class SubstituteController : ControllerBase
21 | {
22 | private readonly ControllerBehaviour _behaviour;
23 | private readonly Exception _exception;
24 | public SubstituteController(ControllerBehaviour behaviour, Exception exception)
25 | : base(null)
26 | {
27 | _behaviour = behaviour;
28 | _exception = exception;
29 | }
30 |
31 | protected override void OnStart()
32 | {
33 | base.OnStart();
34 | if (_behaviour == ControllerBehaviour.FailOnStart)
35 | {
36 | throw _exception;
37 | }
38 | }
39 | }
40 | }
--------------------------------------------------------------------------------
/src/ControllersTree/Substitute/Runtime/SubstituteController.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 5344acf8deef94b59af6ab4fcb2facc0
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/src/ControllersTree/Substitute/Runtime/SubstituteControllerFactory.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 |
5 | namespace Playtika.Controllers.Substitute
6 | {
7 | ///
8 | /// Variants of fake controller behavior.
9 | ///
10 | public enum ControllerBehaviour
11 | {
12 | CompleteOnStart,
13 | CompleteOnFlowAsync,
14 | NeverComplete,
15 | FailOnStart,
16 | FailOnFlowAsync,
17 | }
18 |
19 | ///
20 | /// Override controller factory for testing.
21 | ///
22 | public class SubstituteControllerFactory : IControllerFactory
23 | {
24 | private readonly Dictionary _instances = new();
25 | private readonly Dictionary _results = new();
26 | private readonly Dictionary _received = new();
27 | private readonly Dictionary _behaviours = new();
28 | private readonly Dictionary _exceptions = new();
29 |
30 | public IController Create() where T : class, IController
31 | {
32 | var type = typeof(T);
33 | if (_instances.TryGetValue(type, out var instance))
34 | {
35 | WriteReceived();
36 | return instance;
37 | }
38 |
39 | if (TryCreateStubControllerWithResult(type, out var controllerWithResult))
40 | {
41 | return controllerWithResult;
42 | }
43 |
44 | if (TryCreateStubControllerBase(type, out var controllerBase))
45 | {
46 | return controllerBase;
47 | }
48 |
49 | throw new Exception($"Unhandled type {type.Name}");
50 | }
51 |
52 | public SubstituteControllerFactory AddInstance(T instance)
53 | where T : IController
54 | {
55 | var type = typeof(T);
56 | _instances[type] = instance;
57 | return this;
58 | }
59 |
60 | public SubstituteControllerFactory AddResultFor(object result)
61 | where T : IController
62 | {
63 | var type = typeof(T);
64 | _results[type] = result;
65 | _behaviours[type] = ControllerBehaviour.CompleteOnStart;
66 | return this;
67 | }
68 |
69 | public SubstituteControllerFactory AddExceptionFor(Exception exception)
70 | where T : IController
71 | {
72 | var type = typeof(T);
73 | _exceptions[type] = exception;
74 | _behaviours[type] = ControllerBehaviour.FailOnStart;
75 | return this;
76 | }
77 |
78 | public SubstituteControllerFactory SetBehaviourFor(ControllerBehaviour behaviour)
79 | {
80 | var type = typeof(T);
81 | _behaviours[type] = behaviour;
82 | return this;
83 | }
84 |
85 | public int Received()
86 | {
87 | _received.TryGetValue(typeof(T), out var count);
88 | return count;
89 | }
90 |
91 | private bool TryCreateStubControllerWithResult(Type type, out IController controller)
92 | where T : class, IController
93 | {
94 | controller = null;
95 | var interfaces = type.GetInterfaces();
96 | var interfaceType = interfaces.FirstOrDefault(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IControllerWithResult<>));
97 |
98 | if (interfaceType != null)
99 | {
100 | var argumentType = typeof(EmptyControllerArg);
101 | var interfaceForArgument = interfaces.FirstOrDefault(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IController<>));
102 |
103 | if (interfaceForArgument != null)
104 | {
105 | argumentType = interfaceForArgument.GetGenericArguments()[0];
106 | }
107 |
108 | var resultType = interfaceType.GetGenericArguments()[0];
109 | var substituteType = typeof(SubstituteControllerWithResult<,>).MakeGenericType(argumentType, resultType);
110 |
111 | WriteReceived();
112 |
113 | var obj = Activator.CreateInstance(substituteType, GetResult(), GetBehaviour(), GetException());
114 | controller = obj as IController;
115 | return true;
116 | }
117 |
118 | return false;
119 | }
120 |
121 | private bool TryCreateStubControllerBase(Type type, out IController controller)
122 | where T : class, IController
123 | {
124 | controller = null;
125 | var interfaces = type.GetInterfaces();
126 | var interfaceType = interfaces.FirstOrDefault(x => x == typeof(IController));
127 |
128 | if (interfaceType != null)
129 | {
130 | WriteReceived();
131 |
132 | var interfaceForArgument = interfaces.FirstOrDefault(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IController<>));
133 |
134 | if (interfaceForArgument == null)
135 | {
136 | controller = new SubstituteController();
137 | return true;
138 | }
139 |
140 | var argumentType = interfaceForArgument.GetGenericArguments()[0];
141 | var substituteType = typeof(SubstituteController<>).MakeGenericType(argumentType);
142 |
143 | var obj = Activator.CreateInstance(substituteType, GetBehaviour(), GetException());
144 | controller = obj as IController;
145 | return true;
146 | }
147 |
148 | return false;
149 | }
150 |
151 | private object GetResult()
152 | {
153 | _results.TryGetValue(typeof(T), out var result);
154 | return result;
155 | }
156 |
157 | private ControllerBehaviour GetBehaviour()
158 | {
159 | return _behaviours.GetValueOrDefault(typeof(T), ControllerBehaviour.CompleteOnStart);
160 | }
161 |
162 | private Exception GetException()
163 | {
164 | return _exceptions.GetValueOrDefault(typeof(T), new Exception("Mock controller fail"));
165 | }
166 |
167 | private void WriteReceived()
168 | {
169 | var type = typeof(T);
170 | _received.TryAdd(type, 0);
171 | _received[type]++;
172 | }
173 | }
174 | }
--------------------------------------------------------------------------------
/src/ControllersTree/Substitute/Runtime/SubstituteControllerFactory.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 22cc8dbce4f7b48419acd84b054f70d0
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/src/ControllersTree/Substitute/Runtime/SubstituteControllerWithResult.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading;
3 | using Cysharp.Threading.Tasks;
4 |
5 | namespace Playtika.Controllers.Substitute
6 | {
7 | ///
8 | /// Controller With Result Stub for tests with ability to define fake behaviour.
9 | ///
10 | ///
11 | ///
12 | public class SubstituteControllerWithResult : ControllerWithResultBase
13 | {
14 | private readonly ControllerBehaviour _behaviour;
15 | private readonly TResult _result;
16 | private readonly Exception _exception;
17 |
18 | public SubstituteControllerWithResult(TResult result, ControllerBehaviour behaviour, Exception exception)
19 | : base(null)
20 | {
21 | _result = result;
22 | _behaviour = behaviour;
23 | _exception = exception;
24 | }
25 |
26 | protected override void OnStart()
27 | {
28 | base.OnStart();
29 | switch (_behaviour)
30 | {
31 | case ControllerBehaviour.CompleteOnStart:
32 | Complete(_result);
33 | break;
34 | case ControllerBehaviour.FailOnStart:
35 | throw _exception;
36 | }
37 | }
38 |
39 | protected override async UniTask OnFlowAsync(CancellationToken cancellationToken)
40 | {
41 | await base.OnFlowAsync(cancellationToken);
42 | cancellationToken.ThrowIfCancellationRequested();
43 |
44 | await UniTask.Yield(cancellationToken);
45 | cancellationToken.ThrowIfCancellationRequested();
46 |
47 | switch (_behaviour)
48 | {
49 | case ControllerBehaviour.CompleteOnFlowAsync:
50 | Complete(_result);
51 | break;
52 | case ControllerBehaviour.FailOnFlowAsync:
53 | throw _exception;
54 | }
55 | }
56 | }
57 | }
--------------------------------------------------------------------------------
/src/ControllersTree/Substitute/Runtime/SubstituteControllerWithResult.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: a24256132aa394ad6bdec62a1ff35503
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/src/ControllersTree/Substitute/Runtime/TestRootController.cs:
--------------------------------------------------------------------------------
1 | using System.Threading;
2 | using Cysharp.Threading.Tasks;
3 |
4 | namespace Playtika.Controllers.Substitute
5 | {
6 | ///
7 | /// Root controller for testing.
8 | ///
9 | public sealed class TestRootController : RootController
10 | {
11 | public TestRootController(IControllerFactory controllerFactory)
12 | : base(controllerFactory)
13 | {
14 | }
15 |
16 | public new void Execute()
17 | where T : class, IController
18 | {
19 | base.Execute();
20 | }
21 |
22 | public new void Execute(TArg arg)
23 | where T : class, IController, IController
24 | {
25 | base.Execute(arg);
26 | }
27 |
28 | public new UniTask ExecuteAndWaitResultAsync(
29 | CancellationToken cancellationToken)
30 | where T : class, IControllerWithResult, IController
31 | {
32 | return base.ExecuteAndWaitResultAsync(cancellationToken);
33 | }
34 |
35 | public new UniTask ExecuteAndWaitResultAsync(
36 | CancellationToken cancellationToken)
37 | where T : class, IControllerWithResult, IController
38 | {
39 | return base.ExecuteAndWaitResultAsync(cancellationToken);
40 | }
41 |
42 | public new UniTask ExecuteAndWaitResultAsync(
43 | TArg arg,
44 | CancellationToken cancellationToken)
45 | where T : class, IControllerWithResult, IController
46 | {
47 | return base.ExecuteAndWaitResultAsync(
48 | arg,
49 | cancellationToken);
50 | }
51 |
52 | public new UniTask ExecuteAndWaitResultAsync(
53 | TArg arg,
54 | CancellationToken cancellationToken)
55 | where T : class, IControllerWithResult, IController
56 | {
57 | return base.ExecuteAndWaitResultAsync(
58 | arg,
59 | cancellationToken);
60 | }
61 | }
62 | }
--------------------------------------------------------------------------------
/src/ControllersTree/Substitute/Runtime/TestRootController.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 551bf98303c3a45a6bd658fe7d817b07
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/src/ControllersTree/Substitute/Tests.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: dc89fcc6770e14c0da26f877d0599fab
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/src/ControllersTree/Substitute/Tests/Playtika.Controllers.Substitute.Tests.asmdef:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Playtika.Controllers.Substitute.Tests",
3 | "references": [
4 | "Playtika.Controllers",
5 | "Playtika.Controllers.Substitute",
6 | "UniTask"
7 | ],
8 | "optionalUnityReferences": [],
9 | "includePlatforms": [
10 | "Editor"
11 | ],
12 | "excludePlatforms": [],
13 | "allowUnsafeCode": false,
14 | "testAssemblies": true
15 | }
--------------------------------------------------------------------------------
/src/ControllersTree/Substitute/Tests/Playtika.Controllers.Substitute.Tests.asmdef.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 3827430749b67472cb8bfd06137e11de
3 | AssemblyDefinitionImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/src/ControllersTree/Substitute/Tests/SubstituteControllerFactoryTests.cs:
--------------------------------------------------------------------------------
1 | using NUnit.Framework;
2 |
3 | namespace Playtika.Controllers.Substitute.Tests
4 | {
5 | [TestFixture]
6 | public class SubstituteControllerFactoryTests
7 | {
8 | [Test]
9 | public void CreateControllerBaseByInterface_ControllerIsCorrectType()
10 | {
11 | var factory = new SubstituteControllerFactory();
12 | var controller = factory.Create();
13 | Assert.That(controller, Is.Not.Null);
14 | Assert.That(controller, Is.TypeOf());
15 | }
16 |
17 | [Test]
18 | public void CreateControllerBaseByClass_ControllerIsCorrectType()
19 | {
20 | var factory = new SubstituteControllerFactory();
21 | var controller = factory.Create();
22 | Assert.That(controller, Is.Not.Null);
23 | Assert.That(controller, Is.TypeOf());
24 | }
25 |
26 | [Test]
27 | public void CreateControllerBaseWithArgsByInterface_ControllerIsCorrectType()
28 | {
29 | var factory = new SubstituteControllerFactory();
30 | var controller = factory.Create();
31 | Assert.That(controller, Is.Not.Null);
32 | Assert.That(controller, Is.TypeOf>());
33 | }
34 |
35 | [Test]
36 | public void CreateControllerBaseWithArgsByClass_ControllerIsCorrectType()
37 | {
38 | var factory = new SubstituteControllerFactory();
39 | var controller = factory.Create();
40 | Assert.That(controller, Is.Not.Null);
41 | Assert.That(controller, Is.TypeOf>());
42 | }
43 |
44 | [Test]
45 | public void CreateControllerWithResultBaseByInterface_ControllerIsCorrectType()
46 | {
47 | var factory = new SubstituteControllerFactory();
48 | var controller = factory.Create();
49 | Assert.That(controller, Is.Not.Null);
50 | Assert.That(controller, Is.TypeOf>());
51 | }
52 |
53 | [Test]
54 | public void CreateControllerWithResultBaseTByClass_ControllerIsCorrectType()
55 | {
56 | var factory = new SubstituteControllerFactory();
57 | var controller = factory.Create();
58 | Assert.That(controller, Is.Not.Null);
59 | Assert.That(controller, Is.TypeOf>());
60 | }
61 |
62 | [Test]
63 | public void CreateControllerWithResultBaseTByInterface_ControllerIsCorrectType()
64 | {
65 | var factory = new SubstituteControllerFactory();
66 | var controller = factory.Create();
67 | Assert.That(controller, Is.Not.Null);
68 | Assert.That(controller, Is.TypeOf>());
69 | }
70 |
71 | [Test]
72 | public void CreateControllerWithResultBaseByClass_ControllerIsCorrectType()
73 | {
74 | var factory = new SubstituteControllerFactory();
75 | var controller = factory.Create();
76 | Assert.That(controller, Is.Not.Null);
77 | Assert.That(controller, Is.TypeOf>());
78 | }
79 |
80 | [Test]
81 | public void CreateControllerWithResultBaseWithArgsByInterface_ControllerIsCorrectType()
82 | {
83 | var factory = new SubstituteControllerFactory();
84 | var controller = factory.Create();
85 | Assert.That(controller, Is.Not.Null);
86 | Assert.That(controller, Is.TypeOf>());
87 | }
88 |
89 | [Test]
90 | public void CreateControllerWithResultTBaseWithArgsByInterface_ControllerIsCorrectType()
91 | {
92 | var factory = new SubstituteControllerFactory();
93 | var controller = factory.Create();
94 | Assert.That(controller, Is.Not.Null);
95 | Assert.That(controller, Is.TypeOf>());
96 | }
97 |
98 | [Test]
99 | public void CreateControllerWithResultTBaseWithArgsByClass_ControllerIsCorrectType()
100 | {
101 | var factory = new SubstituteControllerFactory();
102 | var controller = factory.Create();
103 | Assert.That(controller, Is.Not.Null);
104 | Assert.That(controller, Is.TypeOf>());
105 | }
106 |
107 | [Test]
108 | public void CreateControllerWithResultBaseGenericByInterface_ControllerIsCorrectType()
109 | {
110 | var factory = new SubstituteControllerFactory();
111 | var controller = factory.Create>();
112 | Assert.That(controller, Is.Not.Null);
113 | Assert.That(controller, Is.TypeOf>());
114 | }
115 |
116 | [Test]
117 | public void CreateControllerWithResultBaseGenericByClass_ControllerIsCorrectType()
118 | {
119 | var factory = new SubstituteControllerFactory();
120 | var controller = factory.Create>();
121 | Assert.That(controller, Is.Not.Null);
122 | Assert.That(controller, Is.TypeOf>());
123 | }
124 |
125 | [Test]
126 | public void CreateControllerWithResultBaseGenericWithArgsGenericByInterface_ControllerIsCorrectType()
127 | {
128 | var factory = new SubstituteControllerFactory();
129 | var controller = factory.Create>();
130 | Assert.That(controller, Is.Not.Null);
131 | Assert.That(controller, Is.TypeOf>());
132 | }
133 |
134 | [Test]
135 | public void CreateControllerWithResultBaseGenericWithArgsGenericByClass_ControllerIsCorrectType()
136 | {
137 | var factory = new SubstituteControllerFactory();
138 | var controller = factory.Create>();
139 | Assert.That(controller, Is.Not.Null);
140 | Assert.That(controller, Is.TypeOf>());
141 | }
142 |
143 | [Test]
144 | public void Create2IdenticalControllers_ControllersAreNotEquals()
145 | {
146 | var factory = new SubstituteControllerFactory();
147 | var c1 = factory.Create();
148 | var c2 = factory.Create();
149 |
150 | Assert.That(c1, Is.Not.SameAs(c2));
151 | }
152 | }
153 | }
--------------------------------------------------------------------------------
/src/ControllersTree/Substitute/Tests/SubstituteControllerFactoryTests.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 93996a419f2064b32810862ba7c41ece
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/src/ControllersTree/Substitute/Tests/TestRootControllerWithSubstituteFactoryTests.cs:
--------------------------------------------------------------------------------
1 | using System.Threading;
2 | using System.Threading.Tasks;
3 | using NUnit.Framework;
4 |
5 | namespace Playtika.Controllers.Substitute.Tests
6 | {
7 | [TestFixture]
8 | public class TestRootControllerWithSubstituteFactoryTests
9 | {
10 | private interface ITestInstanceController : IController
11 | {
12 | }
13 |
14 | private class TestInstanceController : ControllerBase, ITestInstanceController
15 | {
16 | public bool StartWasCalled;
17 |
18 | public TestInstanceController()
19 | : base(null)
20 | {
21 | }
22 |
23 | protected override void OnStart()
24 | {
25 | base.OnStart();
26 | StartWasCalled = true;
27 | }
28 | }
29 |
30 | [Test]
31 | public void ExecuteByInterface_NotThrowException()
32 | {
33 | using var cts = new CancellationTokenSource();
34 | var factory = new SubstituteControllerFactory();
35 | var rootController = new TestRootController(factory);
36 | rootController.LaunchTree(cts.Token);
37 |
38 | rootController.Execute();
39 | }
40 |
41 | [Test]
42 | public void ExecuteByClass_NotThrowException()
43 | {
44 | using var cts = new CancellationTokenSource();
45 | var factory = new SubstituteControllerFactory();
46 | var rootController = new TestRootController(factory);
47 | rootController.LaunchTree(cts.Token);
48 |
49 | rootController.Execute();
50 | }
51 |
52 | [Test]
53 | public async Task ExecuteAndWaitResultByInterface_NoThrowException()
54 | {
55 | using var cts = new CancellationTokenSource();
56 | var factory = new SubstituteControllerFactory();
57 | var rootController = new TestRootController(factory);
58 | rootController.LaunchTree(cts.Token);
59 |
60 | await rootController.ExecuteAndWaitResultAsync(cts.Token);
61 | }
62 |
63 | [Test]
64 | public async Task ExecuteAndWaitResultByClass_NoThrowException()
65 | {
66 | using var cts = new CancellationTokenSource();
67 | var factory = new SubstituteControllerFactory();
68 | var rootController = new TestRootController(factory);
69 | rootController.LaunchTree(cts.Token);
70 |
71 | await rootController.ExecuteAndWaitResultAsync(cts.Token);
72 | }
73 |
74 | [Test]
75 | public async Task ExecuteAndWaitResultGenericWithArgGenericByInterface_DoNotThrowException()
76 | {
77 | using var cts = new CancellationTokenSource();
78 | var factory = new SubstituteControllerFactory();
79 | var rootController = new TestRootController(factory);
80 | rootController.LaunchTree(cts.Token);
81 | await rootController.ExecuteAndWaitResultAsync, string, float>(
82 | string.Empty, cts.Token);
83 | }
84 |
85 | [Test]
86 | public async Task CreateAndWaitResultGenericWithArgGenericByClass_DoNotThrowException()
87 | {
88 | using var cts = new CancellationTokenSource();
89 | var factory = new SubstituteControllerFactory();
90 | var rootController = new TestRootController(factory);
91 | rootController.LaunchTree(cts.Token);
92 | await rootController.ExecuteAndWaitResultAsync, string, float>(
93 | string.Empty, cts.Token);
94 | }
95 |
96 | [Test]
97 | public void AddInstance_InstanceWasStarted()
98 | {
99 | using var cts = new CancellationTokenSource();
100 |
101 | var controllerInstance = new TestInstanceController();
102 |
103 | var factory = new SubstituteControllerFactory()
104 | .AddInstance(controllerInstance);
105 |
106 | var rootController = new TestRootController(factory);
107 | rootController.LaunchTree(cts.Token);
108 |
109 | rootController.Execute();
110 |
111 | Assert.That(controllerInstance.StartWasCalled, Is.True);
112 | }
113 |
114 | [Test]
115 | public void AddInstanceAsInterface_InstanceWasStarted()
116 | {
117 | using var cts = new CancellationTokenSource();
118 |
119 | var controllerInstance = new TestInstanceController();
120 |
121 | var factory = new SubstituteControllerFactory()
122 | .AddInstance(controllerInstance);
123 |
124 | var rootController = new TestRootController(factory);
125 | rootController.LaunchTree(cts.Token);
126 |
127 | rootController.Execute();
128 |
129 | Assert.That(controllerInstance.StartWasCalled, Is.True);
130 | }
131 |
132 | [Test]
133 | public async Task AddResultFor_ResultIsCorrect()
134 | {
135 | using var cts = new CancellationTokenSource();
136 | var factory = new SubstituteControllerFactory()
137 | .AddResultFor>(45);
138 |
139 | var rootController = new TestRootController(factory);
140 | rootController.LaunchTree(cts.Token);
141 | var result = await rootController.ExecuteAndWaitResultAsync, float>(cts.Token);
142 |
143 | Assert.That(result, Is.EqualTo(45));
144 | }
145 |
146 | [Test]
147 | public Task ExecuteOneController_ReceivedReturn1()
148 | {
149 | using var cts = new CancellationTokenSource();
150 | var factory = new SubstituteControllerFactory();
151 |
152 | var rootController = new TestRootController(factory);
153 | rootController.LaunchTree(cts.Token);
154 | rootController.Execute();
155 |
156 | Assert.That(factory.Received(), Is.EqualTo(1));
157 | return Task.CompletedTask;
158 | }
159 |
160 | [Test]
161 | public Task ExecuteControllerTwice_ReceivedReturn2()
162 | {
163 | using var cts = new CancellationTokenSource();
164 | var factory = new SubstituteControllerFactory();
165 |
166 | var rootController = new TestRootController(factory);
167 | rootController.LaunchTree(cts.Token);
168 | rootController.Execute();
169 | rootController.Execute();
170 |
171 | Assert.That(factory.Received(), Is.EqualTo(2));
172 | return Task.CompletedTask;
173 | }
174 |
175 | [Test]
176 | public Task ExecuteTwoController_Received1PerEachController()
177 | {
178 | using var cts = new CancellationTokenSource();
179 | var factory = new SubstituteControllerFactory();
180 |
181 | var rootController = new TestRootController(factory);
182 | rootController.LaunchTree(cts.Token);
183 | rootController.Execute();
184 | rootController.ExecuteAndWaitResultAsync(cts.Token);
185 |
186 | Assert.That(factory.Received(), Is.EqualTo(1));
187 | Assert.That(factory.Received(), Is.EqualTo(1));
188 | return Task.CompletedTask;
189 | }
190 | }
191 | }
--------------------------------------------------------------------------------
/src/ControllersTree/Substitute/Tests/TestRootControllerWithSubstituteFactoryTests.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: e97bda49527674048bd3312dc30706db
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/src/ControllersTree/Substitute/Tests/TypesForTest.cs:
--------------------------------------------------------------------------------
1 | namespace Playtika.Controllers.Substitute.Tests
2 | {
3 | internal class TypesForTest
4 | {
5 | public interface ITestController : IController
6 | {
7 | }
8 |
9 | public interface ITestControllerWithArgs : IController, IController
10 | {
11 | }
12 |
13 | public interface ITestControllerWithResult : IControllerWithResult, IController
14 | {
15 | }
16 |
17 | public interface ITestControllerWithResultWithArgs : IControllerWithResult, IController
18 | {
19 |
20 | }
21 |
22 | public interface ITestControllerWithResultGeneric : IControllerWithResult, IController
23 | {
24 |
25 | }
26 |
27 | public interface ITestControllerWithResultTWithArgs : IControllerWithResult, IController
28 | {
29 |
30 | }
31 |
32 | public interface ITestControllerWithResultGenericWithArgsGeneric : IControllerWithResult, IController
33 | {
34 |
35 | }
36 |
37 | public interface ITestControllerWithResultT : IControllerWithResult
38 | {
39 | }
40 |
41 | public class TestController : ControllerBase
42 | {
43 | public TestController(IControllerFactory controllerFactory)
44 | : base(controllerFactory)
45 | {
46 | }
47 | }
48 |
49 | public class TestControllerWithArgs : ControllerBase
50 | {
51 | public TestControllerWithArgs(IControllerFactory controllerFactory)
52 | : base(controllerFactory)
53 | {
54 | }
55 | }
56 |
57 | public class TestControllerWithResult : ControllerWithResultBase
58 | {
59 | public TestControllerWithResult(IControllerFactory controllerFactory)
60 | : base(controllerFactory)
61 | {
62 | }
63 | }
64 |
65 | public class TestControllerWithResultT : ControllerWithResultBase
66 | {
67 | public TestControllerWithResultT(IControllerFactory controllerFactory)
68 | : base(controllerFactory)
69 | {
70 | }
71 | }
72 |
73 | public class TestControllerWithResultGeneric : ControllerWithResultBase
74 | {
75 | public TestControllerWithResultGeneric(IControllerFactory controllerFactory)
76 | : base(controllerFactory)
77 | {
78 | }
79 | }
80 |
81 | public class TestControllerWithResultWithArg : ControllerWithResultBase
82 | {
83 | public TestControllerWithResultWithArg(IControllerFactory controllerFactory)
84 | : base(controllerFactory)
85 | {
86 | }
87 | }
88 |
89 | public class TestControllerWithResultGenericWithArgsGeneric : ControllerWithResultBase
90 | {
91 | public TestControllerWithResultGenericWithArgsGeneric(IControllerFactory controllerFactory)
92 | : base(controllerFactory)
93 | {
94 | }
95 | }
96 | }
97 | }
--------------------------------------------------------------------------------
/src/ControllersTree/Substitute/Tests/TypesForTest.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 935260ac74ad743139ea6435361d871a
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/src/ControllersTree/Tests.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: ba4befc67a834995b7edf9eb80ff76b3
3 | timeCreated: 1734555003
--------------------------------------------------------------------------------
/src/ControllersTree/Tests/Controllers.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 4d247d315000a4d9391bbfe12b88cc30
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/src/ControllersTree/Tests/Controllers/ControllersBase.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 3d96a1d58a337418e94b99d40a7a3954
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/src/ControllersTree/Tests/Controllers/ControllersBase/ActionModelTestControllerBase.cs:
--------------------------------------------------------------------------------
1 | using Playtika.Controllers;
2 |
3 | namespace UnitTests.Controllers
4 | {
5 | public class ActionModelTestControllerBase : ControllerBase
6 | {
7 | private readonly TestControllersActionModel _testControllersActionModel;
8 |
9 | internal ActionModelTestControllerBase(
10 | IControllerFactory controllerFactory,
11 | TestControllersActionModel testControllersControllersModel)
12 | : base(controllerFactory)
13 | {
14 | _testControllersActionModel = testControllersControllersModel;
15 | }
16 |
17 | protected override void OnStart()
18 | {
19 | base.OnStart();
20 | AddDisposable(new DisposableToken(() =>
21 | {
22 | _testControllersActionModel.TriggerDispose();
23 | }));
24 | _testControllersActionModel.Args = Args.InputString;
25 | _testControllersActionModel.TriggerStart();
26 | }
27 |
28 | protected override void OnStop()
29 | {
30 | base.OnStop();
31 | _testControllersActionModel.TriggerStop();
32 | }
33 | }
34 | }
--------------------------------------------------------------------------------
/src/ControllersTree/Tests/Controllers/ControllersBase/ActionModelTestControllerBase.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 9c10f9e8d9b474d4f9eb6de9e3ad313d
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/src/ControllersTree/Tests/Controllers/ControllersWithResult.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 42e0bbb0ad9744967afd243c9c631324
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/src/ControllersTree/Tests/Controllers/ControllersWithResult/ActionModelTestControllerWithResult.cs:
--------------------------------------------------------------------------------
1 | using System.Threading;
2 | using Playtika.Controllers;
3 | using Cysharp.Threading.Tasks;
4 |
5 | namespace UnitTests.Controllers
6 | {
7 | internal class ActionModelTestControllerWithResult : ControllerWithResultBase
8 | {
9 | protected readonly TestControllersActionModel TestControllersActionModel;
10 |
11 | internal ActionModelTestControllerWithResult(
12 | IControllerFactory controllerFactory,
13 | TestControllersActionModel testControllersActionModel)
14 | : base(controllerFactory)
15 | {
16 | TestControllersActionModel = testControllersActionModel;
17 | }
18 |
19 | protected override void OnStart()
20 | {
21 | base.OnStart();
22 | AddDisposable(new DisposableToken(() =>
23 | {
24 | TestControllersActionModel.TriggerDispose();
25 | }));
26 | TestControllersActionModel.Args = Args.InputString;
27 | TestControllersActionModel.TriggerStart();
28 | }
29 |
30 | protected override async UniTask OnFlowAsync(CancellationToken cancellationToken)
31 | {
32 | base.OnFlowAsync(cancellationToken);
33 |
34 | await UniTask.Delay(10, cancellationToken: cancellationToken);
35 | TestControllersActionModel.TriggerFlow();
36 | await UniTask.Delay(10, cancellationToken: cancellationToken);
37 | }
38 |
39 | protected override void OnStop()
40 | {
41 | TestControllersActionModel.TriggerStop();
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/ControllersTree/Tests/Controllers/ControllersWithResult/ActionModelTestControllerWithResult.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 6eca80c908d9438b988305a7ccb6c25d
3 | timeCreated: 1705426757
--------------------------------------------------------------------------------
/src/ControllersTree/Tests/Controllers/ControllersWithResult/ActionModelTestControllerWithResult_CompleteAfterOnFlowAsync.cs:
--------------------------------------------------------------------------------
1 | using System.Threading;
2 | using Playtika.Controllers;
3 | using Cysharp.Threading.Tasks;
4 |
5 | namespace UnitTests.Controllers
6 | {
7 | internal class ActionModelTestControllerWithResult_CompleteAfterOnFlowAsync : ActionModelTestControllerWithResult
8 | {
9 | internal ActionModelTestControllerWithResult_CompleteAfterOnFlowAsync(
10 | IControllerFactory controllerFactory,
11 | TestControllersActionModel testControllersActionModel)
12 | : base(controllerFactory, testControllersActionModel)
13 | {
14 | }
15 |
16 | protected override async UniTask OnFlowAsync(CancellationToken cancellationToken)
17 | {
18 | await base.OnFlowAsync(cancellationToken);
19 | AfterFlowAsync(cancellationToken).Forget();
20 | }
21 |
22 | private async UniTask AfterFlowAsync(CancellationToken cancellationToken)
23 | {
24 | await UniTask.Delay(10, cancellationToken: cancellationToken);
25 | Complete(new TestEmptyControllerResult(Args.InputString));
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/ControllersTree/Tests/Controllers/ControllersWithResult/ActionModelTestControllerWithResult_CompleteAfterOnFlowAsync.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: d0d8b891dadc4df38ee4e04433932e0c
3 | timeCreated: 1705426715
--------------------------------------------------------------------------------
/src/ControllersTree/Tests/Controllers/ControllersWithResult/ActionModelTestControllerWithResult_CompleteOnFlowAsync.cs:
--------------------------------------------------------------------------------
1 | using System.Threading;
2 | using Playtika.Controllers;
3 | using Cysharp.Threading.Tasks;
4 |
5 | namespace UnitTests.Controllers
6 | {
7 | internal class ActionModelTestControllerWithResult_CompleteOnFlowAsync : ActionModelTestControllerWithResult
8 | {
9 | public ActionModelTestControllerWithResult_CompleteOnFlowAsync(
10 | IControllerFactory controllerFactory,
11 | TestControllersActionModel testControllersActionModel)
12 | : base(controllerFactory, testControllersActionModel)
13 | {
14 | }
15 |
16 | protected override async UniTask OnFlowAsync(CancellationToken cancellationToken)
17 | {
18 | await base.OnFlowAsync(cancellationToken);
19 | Complete(new TestEmptyControllerResult(Args.InputString));
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/ControllersTree/Tests/Controllers/ControllersWithResult/ActionModelTestControllerWithResult_CompleteOnFlowAsync.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: e629ed978239447cbf05c9e8e0e67fb7
3 | timeCreated: 1705426703
--------------------------------------------------------------------------------
/src/ControllersTree/Tests/Controllers/ControllersWithResult/ActionModelTestControllerWithResult_CompleteOnStart.cs:
--------------------------------------------------------------------------------
1 | using Playtika.Controllers;
2 |
3 | namespace UnitTests.Controllers
4 | {
5 | internal class ActionModelTestControllerWithResult_CompleteOnStart : ActionModelTestControllerWithResult
6 | {
7 | internal ActionModelTestControllerWithResult_CompleteOnStart(
8 | IControllerFactory controllerFactory,
9 | TestControllersActionModel testControllersActionModel)
10 | : base(controllerFactory, testControllersActionModel)
11 | {
12 | }
13 |
14 | protected override void OnStart()
15 | {
16 | base.OnStart();
17 | Complete(new TestEmptyControllerResult(Args.InputString));
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/ControllersTree/Tests/Controllers/ControllersWithResult/ActionModelTestControllerWithResult_CompleteOnStart.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 1b6dcda5096644c79f78018703d6badc
3 | timeCreated: 1705426697
--------------------------------------------------------------------------------
/src/ControllersTree/Tests/Controllers/ControllersWithResult/ActionModelTestControllerWithResult_FailInDispose.cs:
--------------------------------------------------------------------------------
1 | using Playtika.Controllers;
2 |
3 | namespace UnitTests.Controllers
4 | {
5 | internal class ActionModelTestControllerWithResult_FailInDispose : ActionModelTestControllerWithResult
6 | {
7 | internal ActionModelTestControllerWithResult_FailInDispose(
8 | IControllerFactory controllerFactory,
9 | TestControllersActionModel testControllersControllersModel)
10 | : base(controllerFactory, testControllersControllersModel)
11 | {
12 | }
13 |
14 | protected override void OnStart()
15 | {
16 | AddDisposable(new DisposableToken(() =>
17 | {
18 | Fail(new TestControllersException(TestControllersMethodsNamesConsts.DisposeMethodName));
19 | }));
20 | TestControllersActionModel.Args = Args.InputString;
21 | TestControllersActionModel.TriggerStart();
22 |
23 | Complete(new TestEmptyControllerResult(Args.InputString));
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/ControllersTree/Tests/Controllers/ControllersWithResult/ActionModelTestControllerWithResult_FailInDispose.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 656bfdaf5cf0e48938948fce833bcf8d
3 | timeCreated: 1705941216
--------------------------------------------------------------------------------
/src/ControllersTree/Tests/Controllers/ControllersWithResult/ActionModelTestControllerWithResult_FailOnFlowAsync.cs:
--------------------------------------------------------------------------------
1 | using System.Threading;
2 | using Playtika.Controllers;
3 | using Cysharp.Threading.Tasks;
4 |
5 | namespace UnitTests.Controllers
6 | {
7 | internal class ActionModelTestControllerWithResult_FailOnFlowAsync : ActionModelTestControllerWithResult
8 | {
9 | internal ActionModelTestControllerWithResult_FailOnFlowAsync(
10 | IControllerFactory controllerFactory,
11 | TestControllersActionModel testControllersControllersModel)
12 | : base(controllerFactory, testControllersControllersModel)
13 | {
14 | }
15 |
16 | protected override UniTask OnFlowAsync(CancellationToken cancellationToken)
17 | {
18 | Fail(new TestControllersException(TestControllersMethodsNamesConsts.OnFlowAsyncMethodName));
19 | return UniTask.CompletedTask;
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/ControllersTree/Tests/Controllers/ControllersWithResult/ActionModelTestControllerWithResult_FailOnFlowAsync.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 62c5f36d99feb40ce9434be4c862999a
3 | timeCreated: 1705941216
--------------------------------------------------------------------------------
/src/ControllersTree/Tests/Controllers/ControllersWithResult/ActionModelTestControllerWithResult_FailOnStart.cs:
--------------------------------------------------------------------------------
1 | using Playtika.Controllers;
2 |
3 | namespace UnitTests.Controllers
4 | {
5 | internal class ActionModelTestControllerWithResult_FailOnStart : ActionModelTestControllerWithResult
6 | {
7 | internal ActionModelTestControllerWithResult_FailOnStart(
8 | IControllerFactory controllerFactory,
9 | TestControllersActionModel testControllersControllersModel)
10 | : base(controllerFactory, testControllersControllersModel)
11 | {
12 | }
13 |
14 | protected override void OnStart()
15 | {
16 | base.OnStart();
17 | Fail(new TestControllersException(TestControllersMethodsNamesConsts.FailMethodName));
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/ControllersTree/Tests/Controllers/ControllersWithResult/ActionModelTestControllerWithResult_FailOnStart.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 290e50c6c8164effb7470cfc66c64139
3 | timeCreated: 1705941216
--------------------------------------------------------------------------------
/src/ControllersTree/Tests/Controllers/ControllersWithResult/ActionModelTestControllerWithResult_FailOnStop.cs:
--------------------------------------------------------------------------------
1 | using Playtika.Controllers;
2 |
3 | namespace UnitTests.Controllers
4 | {
5 | internal class ActionModelTestControllerWithResult_FailOnStop : ActionModelTestControllerWithResult
6 | {
7 | internal ActionModelTestControllerWithResult_FailOnStop(
8 | IControllerFactory controllerFactory,
9 | TestControllersActionModel testControllersControllersModel)
10 | : base(controllerFactory, testControllersControllersModel)
11 | {
12 | }
13 |
14 | protected override void OnStart()
15 | {
16 | base.OnStart();
17 | Complete(new TestEmptyControllerResult(Args.InputString));
18 | }
19 |
20 | protected override void OnStop()
21 | {
22 | base.OnStop();
23 | Fail(new TestControllersException(TestControllersMethodsNamesConsts.FailMethodName));
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/ControllersTree/Tests/Controllers/ControllersWithResult/ActionModelTestControllerWithResult_FailOnStop.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 567ccb5392f5440bfadc805ffa08dbc8
3 | timeCreated: 1705941216
--------------------------------------------------------------------------------
/src/ControllersTree/Tests/Controllers/ControllersWithResult/ActionModelTestControllerWithResult_ThrowAfterOnFlowAsync.cs:
--------------------------------------------------------------------------------
1 | using System.Threading;
2 | using Playtika.Controllers;
3 | using Cysharp.Threading.Tasks;
4 |
5 | namespace UnitTests.Controllers
6 | {
7 | internal class ActionModelTestControllerWithResult_ThrowAfterOnFlowAsync : ActionModelTestControllerWithResult
8 | {
9 | internal ActionModelTestControllerWithResult_ThrowAfterOnFlowAsync(
10 | IControllerFactory controllerFactory,
11 | TestControllersActionModel testControllersActionModel)
12 | : base(controllerFactory, testControllersActionModel)
13 | {
14 | }
15 |
16 | protected override async UniTask OnFlowAsync(CancellationToken cancellationToken)
17 | {
18 | await base.OnFlowAsync(cancellationToken);
19 | ThrowAfterFlowAsync(cancellationToken).Forget();
20 | }
21 |
22 | private async UniTask ThrowAfterFlowAsync(CancellationToken cancellationToken)
23 | {
24 | await UniTask.Delay(10, cancellationToken: cancellationToken);
25 | throw new TestControllersException(TestControllersMethodsNamesConsts.CompleteMethodName);
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/ControllersTree/Tests/Controllers/ControllersWithResult/ActionModelTestControllerWithResult_ThrowAfterOnFlowAsync.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: c794687638b04901bb400edad7296168
3 | timeCreated: 1705426751
--------------------------------------------------------------------------------
/src/ControllersTree/Tests/Controllers/ControllersWithResult/Childs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 1187863d0f10b4c9296c3d13c04eeb28
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/src/ControllersTree/Tests/Controllers/ControllersWithResult/Childs/ActionModelTestChildControllerWithResult.cs:
--------------------------------------------------------------------------------
1 | using System.Threading;
2 | using System.Threading.Tasks;
3 | using Playtika.Controllers;
4 | using Cysharp.Threading.Tasks;
5 |
6 | namespace UnitTests.Controllers
7 | {
8 | internal class ActionModelTestChildControllerWithResult : ControllerWithResultBase
9 | {
10 | protected readonly TestChildControllersActionModel TestChildControllersActionModel;
11 | protected string TestControllerGuid => Args;
12 |
13 | public ActionModelTestChildControllerWithResult(
14 | IControllerFactory controllerFactory,
15 | TestChildControllersActionModel testChildControllersModel)
16 | : base(controllerFactory)
17 | {
18 | TestChildControllersActionModel = testChildControllersModel;
19 | }
20 |
21 | protected override void OnStart()
22 | {
23 | base.OnStart();
24 | AddDisposable(new DisposableToken(() =>
25 | {
26 | TestChildControllersActionModel.TriggerChildDispose(TestControllerGuid);
27 | }));
28 | TestChildControllersActionModel.TriggerChildStart(TestControllerGuid);
29 | }
30 |
31 | protected override async UniTask OnFlowAsync(CancellationToken cancellationToken)
32 | {
33 | base.OnFlowAsync(cancellationToken);
34 | await Task.Delay(50, cancellationToken).ConfigureAwait(false);
35 |
36 | TestChildControllersActionModel.TriggerChildFlow(TestControllerGuid);
37 |
38 | await Task.Delay(50, cancellationToken).ConfigureAwait(false);
39 |
40 | Complete(default);
41 | }
42 |
43 | protected override void OnStop()
44 | {
45 | TestChildControllersActionModel.TriggerChildStop(TestControllerGuid);
46 | }
47 | }
48 |
49 | internal class ActionModelTestChildControllerWithResult1 : ActionModelTestChildControllerWithResult
50 | {
51 | public ActionModelTestChildControllerWithResult1(
52 | IControllerFactory controllerFactory,
53 | TestChildControllersActionModel testChildControllersModel)
54 | : base(controllerFactory, testChildControllersModel)
55 | {
56 | }
57 | }
58 |
59 | internal class ActionModelTestChildControllerWithResult2 : ActionModelTestChildControllerWithResult
60 | {
61 | public ActionModelTestChildControllerWithResult2(
62 | IControllerFactory controllerFactory,
63 | TestChildControllersActionModel testChildControllersModel)
64 | : base(controllerFactory, testChildControllersModel)
65 | {
66 | }
67 | }
68 | internal class ActionModelTestChildControllerWithResult3 : ActionModelTestChildControllerWithResult
69 | {
70 | public ActionModelTestChildControllerWithResult3(
71 | IControllerFactory controllerFactory,
72 | TestChildControllersActionModel testChildControllersModel)
73 | : base(controllerFactory, testChildControllersModel)
74 | {
75 | }
76 | }
77 | internal class ActionModelTestChildControllerWithResult4 : ActionModelTestChildControllerWithResult
78 | {
79 | public ActionModelTestChildControllerWithResult4(
80 | IControllerFactory controllerFactory,
81 | TestChildControllersActionModel testChildControllersModel)
82 | : base(controllerFactory, testChildControllersModel)
83 | {
84 | }
85 | }
86 | internal class ActionModelTestChildControllerWithResult5 : ActionModelTestChildControllerWithResult
87 | {
88 | public ActionModelTestChildControllerWithResult5(
89 | IControllerFactory controllerFactory,
90 | TestChildControllersActionModel testChildControllersModel)
91 | : base(controllerFactory, testChildControllersModel)
92 | {
93 | }
94 | }
95 | }
--------------------------------------------------------------------------------
/src/ControllersTree/Tests/Controllers/ControllersWithResult/Childs/ActionModelTestChildControllerWithResult.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 23adbfb3f8e6144e790c433c545090f2
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/src/ControllersTree/Tests/Controllers/ControllersWithResult/Childs/ActionModelTestControllerWithResultAndChildControllers.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Threading;
4 | using Playtika.Controllers;
5 | using Cysharp.Threading.Tasks;
6 | using UnityEngine.Assertions;
7 |
8 | namespace UnitTests.Controllers
9 | {
10 | internal class ActionModelTestControllerWithResultAndChildControllers : ControllerWithResultBase
11 | {
12 | protected readonly TestControllersActionModel TestControllersActionModel;
13 |
14 | internal ActionModelTestControllerWithResultAndChildControllers(
15 | IControllerFactory controllerFactory,
16 | TestControllersActionModel testControllersActionModel)
17 | : base(controllerFactory)
18 | {
19 | TestControllersActionModel = testControllersActionModel;
20 | }
21 |
22 | protected override void OnStart()
23 | {
24 | base.OnStart();
25 | AddDisposable(new DisposableToken(() =>
26 | {
27 | TestControllersActionModel.TriggerDispose();
28 | }));
29 | TestControllersActionModel.Args = Args.InputString;
30 | TestControllersActionModel.TriggerStart();
31 | }
32 |
33 | protected override async UniTask OnFlowAsync(CancellationToken cancellationToken)
34 | {
35 | TestControllersActionModel.TriggerFlow();
36 |
37 | await StartChildControllersAsync(cancellationToken);
38 | cancellationToken.ThrowIfCancellationRequested();
39 |
40 | Complete(new TestEmptyControllerResult(Args.InputString));
41 | }
42 |
43 | protected async UniTask StartChildControllersAsync(CancellationToken cancellationToken)
44 | {
45 | var launchers = GetAsyncLaunchers();
46 | Assert.AreEqual(Args.ChildControllersGuids.Count, launchers.Count);
47 | var i = 0;
48 | foreach (var childControllerGuid in Args.ChildControllersGuids)
49 | {
50 | var launcher = launchers[i];
51 | await launcher(childControllerGuid, cancellationToken);
52 | cancellationToken.ThrowIfCancellationRequested();
53 | i++;
54 | }
55 | }
56 |
57 | protected override void OnStop()
58 | {
59 | TestControllersActionModel.TriggerStop();
60 | }
61 |
62 | private List> GetAsyncLaunchers()
63 | {
64 | return new List>
65 | {
66 | StartChildControllersAsync1,
67 | StartChildControllersAsync2,
68 | StartChildControllersAsync3,
69 | StartChildControllersAsync4,
70 | StartChildControllersAsync5,
71 | };
72 | }
73 |
74 | private async UniTask StartChildControllersAsync1(string childControllerGuid, CancellationToken cancellationToken)
75 | {
76 | await ExecuteAndWaitResultAsync(childControllerGuid, cancellationToken);
77 | }
78 |
79 | private async UniTask StartChildControllersAsync2(string childControllerGuid, CancellationToken cancellationToken)
80 | {
81 | await ExecuteAndWaitResultAsync(childControllerGuid, cancellationToken);
82 | }
83 |
84 | private async UniTask StartChildControllersAsync3(string childControllerGuid, CancellationToken cancellationToken)
85 | {
86 | await ExecuteAndWaitResultAsync(childControllerGuid, cancellationToken);
87 | }
88 |
89 | private async UniTask StartChildControllersAsync4(string childControllerGuid, CancellationToken cancellationToken)
90 | {
91 | await ExecuteAndWaitResultAsync(childControllerGuid, cancellationToken);
92 | }
93 |
94 | private async UniTask StartChildControllersAsync5(string childControllerGuid, CancellationToken cancellationToken)
95 | {
96 | await ExecuteAndWaitResultAsync(childControllerGuid, cancellationToken);
97 | }
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/src/ControllersTree/Tests/Controllers/ControllersWithResult/Childs/ActionModelTestControllerWithResultAndChildControllers.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 7d5e3ddc08e934d9a8dc86154c0f706d
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/src/ControllersTree/Tests/Controllers/ControllersWithResult/Childs/ActionModelTestControllerWithResultAndChildControllers_FailOnFlowAsync.cs:
--------------------------------------------------------------------------------
1 | using System.Threading;
2 | using Playtika.Controllers;
3 | using Cysharp.Threading.Tasks;
4 |
5 | namespace UnitTests.Controllers
6 | {
7 | internal class ActionModelTestControllerWithResultAndChildControllers_FailOnFlowAsync : ActionModelTestControllerWithResultAndChildControllers
8 | {
9 | internal ActionModelTestControllerWithResultAndChildControllers_FailOnFlowAsync(
10 | IControllerFactory controllerFactory,
11 | TestControllersActionModel testControllersActionModel)
12 | : base(controllerFactory, testControllersActionModel)
13 | {
14 | }
15 |
16 | protected override async UniTask OnFlowAsync(CancellationToken cancellationToken)
17 | {
18 | TestControllersActionModel.TriggerFlow();
19 |
20 | await StartChildControllersAsync(cancellationToken);
21 | throw new TestControllersException(TestControllersMethodsNamesConsts.OnFlowAsyncMethodName);
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/ControllersTree/Tests/Controllers/ControllersWithResult/Childs/ActionModelTestControllerWithResultAndChildControllers_FailOnFlowAsync.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 304b326d630eb485f842129b1492bd9f
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/src/ControllersTree/Tests/ControllersBaseTests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading;
3 | using Playtika.Controllers;
4 | using NUnit.Framework;
5 | using Playtika.Controllers.Substitute;
6 |
7 | namespace UnitTests.Controllers
8 | {
9 | [TestFixture]
10 | public class ControllersBaseTests
11 | {
12 | private IControllerFactory _controllerFactory;
13 | private TestControllersActionModel _testControllersActionModel;
14 | private CancellationTokenSource _cancellationTokenSource;
15 | private CancellationToken CancellationToken => _cancellationTokenSource.Token;
16 |
17 | [SetUp]
18 | public void SetUp()
19 | {
20 | var substituteControllerFactory = new SubstituteControllerFactory();
21 | _testControllersActionModel = new TestControllersActionModel();
22 | substituteControllerFactory.AddInstance(
23 | new ActionModelTestControllerBase(
24 | substituteControllerFactory,
25 | _testControllersActionModel));
26 |
27 | _cancellationTokenSource = new CancellationTokenSource();
28 | _controllerFactory = substituteControllerFactory;
29 | }
30 |
31 | [TearDown]
32 | public void TearDown()
33 | {
34 | _controllerFactory = null;
35 | _testControllersActionModel = null;
36 | _cancellationTokenSource.Cancel();
37 | _cancellationTokenSource.Dispose();
38 | }
39 |
40 | [OneTimeTearDown]
41 | public void OneTimeTearDown()
42 | {
43 | _controllerFactory = null;
44 | _cancellationTokenSource = null;
45 | }
46 |
47 | [Test]
48 | public void ControllerBase_NoFails_CorrectArguments()
49 | {
50 | // Arrange
51 | var startTriggered = false;
52 | var stopTriggered = false;
53 | var disposeTriggered = false;
54 |
55 | var testGuid = TestControllersUtils.GenerateTestGuid();
56 | var args = new TestControllerArgs(testGuid);
57 | _testControllersActionModel.StartTriggered += () => startTriggered = true;
58 | _testControllersActionModel.StopTriggered += () => stopTriggered = true;
59 | _testControllersActionModel.DisposeTriggered += () => disposeTriggered = true;
60 |
61 | Assert.DoesNotThrow(
62 | () =>
63 | {
64 | // Act
65 | TestRootControllerLauncher.Launch(
66 | args,
67 | _controllerFactory, CancellationToken);
68 |
69 | _cancellationTokenSource.Cancel();
70 |
71 | // Assert
72 | Assert.AreEqual(args.InputString, _testControllersActionModel.Args, "Args are not equal");
73 | Assert.True(startTriggered, "OnStart is not triggered");
74 | Assert.True(stopTriggered, "OnStop is not triggered");
75 | Assert.True(disposeTriggered, "Dispose is not triggered");
76 | });
77 | }
78 |
79 | [Test]
80 | public void ControllerBase_OnStartThrowsException_StopAndDisposeAreTriggered()
81 | {
82 | // Arrange
83 | var stopTriggered = false;
84 | var disposeTriggered = false;
85 |
86 | var testGuid = TestControllersUtils.GenerateTestGuid();
87 | var args = new TestControllerArgs(testGuid);
88 | _testControllersActionModel.StartTriggered += () => throw new TestControllersException(TestControllersMethodsNamesConsts.OnStartMethodName);
89 | _testControllersActionModel.StopTriggered += () => stopTriggered = true;
90 | _testControllersActionModel.DisposeTriggered += () => disposeTriggered = true;
91 |
92 | Assert.Throws(
93 | () =>
94 | {
95 | // Act
96 | TestRootControllerLauncher.Launch(
97 | args,
98 | _controllerFactory, CancellationToken);
99 |
100 | _cancellationTokenSource.Cancel();
101 | });
102 |
103 | // Assert
104 | Assert.True(stopTriggered, "OnStop is not triggered");
105 | Assert.True(disposeTriggered, "Dispose is not triggered");
106 | }
107 |
108 | [Test]
109 | public void ControllerBase_OnStopThrowsException_OnStartAndOnDisposeAreTriggered()
110 | {
111 | var startTriggered = false;
112 | var disposeTriggered = false;
113 |
114 | var testGuid = TestControllersUtils.GenerateTestGuid();
115 | var args = new TestControllerArgs(testGuid);
116 | _testControllersActionModel.StartTriggered += () => startTriggered = true;
117 | _testControllersActionModel.StopTriggered += () => throw new TestControllersException(TestControllersMethodsNamesConsts.OnStopMethodName);
118 | _testControllersActionModel.DisposeTriggered += () => disposeTriggered = true;
119 |
120 | Assert.Throws(
121 | () =>
122 | {
123 | // Act
124 | TestRootControllerLauncher.Launch(
125 | args,
126 | _controllerFactory, CancellationToken);
127 |
128 | _cancellationTokenSource.Cancel();
129 | });
130 |
131 | // Assert
132 | Assert.True(startTriggered, "OnStart is not triggered");
133 | Assert.True(disposeTriggered, "Dispose is not triggered");
134 | }
135 |
136 | [Test]
137 | public void ControllerBase_OnDisposeThrowsException_OnStartAndOnStopAreTriggered()
138 | {
139 | // Arrange
140 | var startTriggered = false;
141 | var stopTriggered = false;
142 |
143 | var testGuid = TestControllersUtils.GenerateTestGuid();
144 | var args = new TestControllerArgs(testGuid);
145 | _testControllersActionModel.StartTriggered += () => startTriggered = true;
146 | _testControllersActionModel.StopTriggered += () => stopTriggered = true;
147 | _testControllersActionModel.DisposeTriggered += () => throw new TestControllersException(TestControllersMethodsNamesConsts.DisposeMethodName);
148 |
149 | Assert.Throws(
150 | () =>
151 | {
152 | // Act
153 | TestRootControllerLauncher.Launch(
154 | args,
155 | _controllerFactory, CancellationToken);
156 |
157 | _cancellationTokenSource.Cancel();
158 | });
159 |
160 | // Assert
161 | Assert.True(startTriggered, "OnStart is not triggered");
162 | Assert.True(stopTriggered, "OnStop has been triggered");
163 | }
164 |
165 | [Test]
166 | public void ControllerBase_OnStartTokenCancelled_OnStopAndOnDisposeAreTriggered()
167 | {
168 | // Arrange
169 | var stopTriggered = false;
170 | var disposeTriggered = false;
171 |
172 | var testGuid = TestControllersUtils.GenerateTestGuid();
173 | var args = new TestControllerArgs(testGuid);
174 | _testControllersActionModel.StartTriggered += () => _cancellationTokenSource.Cancel();
175 | _testControllersActionModel.StopTriggered += () => stopTriggered = true;
176 | _testControllersActionModel.DisposeTriggered += () => disposeTriggered = true;
177 |
178 | Assert.DoesNotThrow(
179 | () =>
180 | {
181 | // Act
182 | TestRootControllerLauncher.Launch(
183 | args,
184 | _controllerFactory, CancellationToken);
185 |
186 | // Assert
187 | Assert.True(stopTriggered, "OnStop is not triggered");
188 | Assert.True(disposeTriggered, "Dispose is not triggered");
189 | Assert.True(CancellationToken.IsCancellationRequested, "Cancellation token should be cancelled");
190 | });
191 | }
192 | }
193 | }
--------------------------------------------------------------------------------
/src/ControllersTree/Tests/ControllersBaseTests.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: ac1f85185945b40f7b73fe43e0cb785c
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/src/ControllersTree/Tests/ControllersWithResultBaseTests.ChildControllers.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Linq;
3 | using System.Threading.Tasks;
4 | using NUnit.Framework;
5 |
6 | namespace UnitTests.Controllers
7 | {
8 | public partial class ControllersWithResultBaseTests
9 | {
10 | [Test]
11 | public async Task ControllerWithResultBase_Complete_Parent()
12 | {
13 | // Arrange
14 | var testGuid = TestControllersUtils.GenerateTestGuid();
15 | var childControllersGuids = Enumerable.Range(0, 5)
16 | .Select( number => TestControllersUtils.GenerateTestGuid())
17 | .ToList();
18 |
19 | var args = new TestChildControllerArgs(testGuid, childControllersGuids);
20 |
21 | var startTriggeredCallers = new List();
22 | var flowTriggeredCallers = new List();
23 | var stopTriggeredCallers = new List();
24 | var disposeTriggeredCallers = new List();
25 |
26 | _testChildControllersActionModel.StartTriggered += caller => startTriggeredCallers.Add(caller);
27 | _testChildControllersActionModel.FlowTriggered += caller => flowTriggeredCallers.Add(caller);
28 | _testChildControllersActionModel.StopTriggered += caller => stopTriggeredCallers.Add(caller);
29 | _testChildControllersActionModel.DisposeTriggered += caller => disposeTriggeredCallers.Add(caller);
30 |
31 | var result = await TestRootControllerLauncher
32 | .LaunchAsync(
33 | args, _controllerFactory, CancellationToken);
34 |
35 | // Assert
36 | AssertTriggerCallers(startTriggeredCallers, childControllersGuids, "Expected callers doesn't contain Start caller id");
37 | AssertTriggerCallers(flowTriggeredCallers, childControllersGuids, "Expected callers doesn't contain Flow caller id");
38 | AssertTriggerCallers(stopTriggeredCallers, childControllersGuids, "Expected callers doesn't contain Stop caller id");
39 | AssertTriggerCallers(disposeTriggeredCallers, childControllersGuids, "Expected callers doesn't contain Dispose caller id");
40 | Assert.IsNotNull(result, "Result shouldn't be null");
41 | var resultCorrect = string.Equals(args.InputString, result.ResultString);
42 | Assert.True(resultCorrect, "Result is incorrect");
43 | }
44 |
45 | private void AssertTriggerCallers(
46 | List callers,
47 | List