Tanoda
PostProcessProvider.cs
Go to the documentation of this file.
1/******************************************************************************
2 * Copyright (C) Ultraleap, Inc. 2011-2020. *
3 * *
4 * Use subject to the terms of the Apache License 2.0 available at *
5 * http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
6 * between Ultraleap and you, your company or other organization. *
7 ******************************************************************************/
8
9using UnityEngine;
11
12namespace Leap.Unity {
13
14 public abstract class PostProcessProvider : LeapProvider {
15
16 [Tooltip("The LeapProvider whose output hand data will be copied, modified, " +
17 "and output by this post-processing provider.")]
18 [SerializeField]
19 [OnEditorChange("inputLeapProvider")]
22 get { return _inputLeapProvider; }
23 set {
24 if (Application.isPlaying && _inputLeapProvider != null) {
25 _inputLeapProvider.OnFixedFrame -= processFixedFrame;
26 _inputLeapProvider.OnUpdateFrame -= processUpdateFrame;
27 }
28
29 _inputLeapProvider = value;
30 validateInput();
31
32 if (Application.isPlaying && _inputLeapProvider != null) {
33 _inputLeapProvider.OnFixedFrame -= processFixedFrame; // safeguard double-subscription
34 _inputLeapProvider.OnFixedFrame += processFixedFrame;
35 _inputLeapProvider.OnUpdateFrame -= processUpdateFrame; // safeguard double-subscription
36 _inputLeapProvider.OnUpdateFrame += processUpdateFrame;
37 }
38 }
39 }
40
41 public enum DataUpdateMode { UpdateOnly, FixedUpdateOnly, UpdateAndFixedUpdate }
42 [Tooltip("Whether this post-processing provider should process data received from " +
43 "Update frames, FixedUpdate frames, or both. Processing both kinds of " +
44 "frames is only recommended if your post-process is stateless.")]
46
50 protected virtual bool implementerHandlesDispatch { get { return false; }}
51
52 [Tooltip("When this setting is enabled, frame data is passed from this provider's "
53 + "input directly to its output without performing any post-processing.")]
54 public bool passthroughOnly = false;
55
56 private Frame _cachedUpdateFrame = new Frame();
57 private Frame _cachedFixedFrame = new Frame();
58
59 public override Frame CurrentFrame {
60 get {
61 #if UNITY_EDITOR
62 if (!Application.isPlaying && _inputLeapProvider != null) {
63 processUpdateFrame(_inputLeapProvider.CurrentFrame);
64 }
65 #endif
66 return _cachedUpdateFrame;
67 }
68 }
69
70 public override Frame CurrentFixedFrame {
71 get {
72 #if UNITY_EDITOR
73 if (!Application.isPlaying && _inputLeapProvider != null) {
74 processUpdateFrame(_inputLeapProvider.CurrentFixedFrame);
75 }
76 #endif
77 return _cachedFixedFrame;
78 }
79 }
80
81 protected virtual void OnEnable() {
82 // Bootstrap event subscription, handled in the input property setter.
84 }
85
86 protected virtual void OnValidate() {
87 validateInput();
88 }
89
90 public abstract void ProcessFrame(ref Frame inputFrame);
91
92 private void validateInput() {
93 if (detectCycle()) {
94 _inputLeapProvider = null;
95 Debug.LogError("The input to the post-process provider on " + gameObject.name
96 + " causes an infinite cycle, so its input has been set to null.");
97 }
98 }
99
100 private bool detectCycle() {
101 LeapProvider providerA = _inputLeapProvider, providerB = _inputLeapProvider;
102 while (providerA is PostProcessProvider) {
103 providerB = (providerB as PostProcessProvider).inputLeapProvider;
104 if (providerA == providerB) { return true; }
105 else if (!(providerB is PostProcessProvider)) { return false; }
106 providerA = (providerA as PostProcessProvider).inputLeapProvider;
107 providerB = (providerB as PostProcessProvider).inputLeapProvider;
108 if (!(providerB is PostProcessProvider)) { return false; }
109 }
110 return false;
111 }
112
113 private void processUpdateFrame(Frame inputFrame) {
114 if (dataUpdateMode == DataUpdateMode.FixedUpdateOnly) {
115 return;
116 }
117
118 _cachedUpdateFrame.CopyFrom(inputFrame);
119 if (!passthroughOnly) { ProcessFrame(ref _cachedUpdateFrame); }
121 DispatchUpdateFrameEvent(_cachedUpdateFrame);
122 }
123 }
124
125 private void processFixedFrame(Frame inputFrame) {
126 if (dataUpdateMode == DataUpdateMode.UpdateOnly) {
127 return;
128 }
129
130 _cachedFixedFrame.CopyFrom(inputFrame);
131 if (!passthroughOnly) { ProcessFrame(ref _cachedFixedFrame); }
133 DispatchFixedFrameEvent(_cachedFixedFrame);
134 }
135 }
136
137 }
138}
UnityEngine.Debug Debug
Definition: TanodaServer.cs:19
The Frame class represents a set of hand and finger tracking data detected in a single frame.
Definition: Frame.cs:24
Provides Frame object data to the Unity application by firing events as soon as Frame data is availab...
Definition: LeapProvider.cs:21
Action< Frame > OnFixedFrame
Definition: LeapProvider.cs:26
void DispatchUpdateFrameEvent(Frame frame)
Definition: LeapProvider.cs:49
Action< Frame > OnUpdateFrame
Definition: LeapProvider.cs:25
abstract Frame CurrentFrame
The current frame for this update cycle, in world space.
Definition: LeapProvider.cs:37
abstract Frame CurrentFixedFrame
The current frame for this fixed update cycle, in world space.
Definition: LeapProvider.cs:47
void DispatchFixedFrameEvent(Frame frame)
Definition: LeapProvider.cs:58
DataUpdateMode
virtual void OnEnable()
virtual void OnValidate()
override Frame CurrentFrame
virtual bool implementerHandlesDispatch
Override this as true to have your PostProcessProvider handle its own Dispatch timing....
LeapProvider _inputLeapProvider
DataUpdateMode dataUpdateMode
override Frame CurrentFixedFrame
abstract void ProcessFrame(ref Frame inputFrame)
LeapProvider inputLeapProvider
bool passthroughOnly