2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
4 // Licensed under the Flora License, Version 1.0 (the License);
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
8 // http://floralicense.org/license/
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an AS IS BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
18 #include <dali/internal/event/events/gesture-processor.h>
21 #include <dali/integration-api/debug.h>
22 #include <dali/internal/event/actors/actor-impl.h>
23 #include <dali/internal/event/render-tasks/render-task-impl.h>
24 #include <dali/internal/event/events/hit-test-algorithm-impl.h>
32 GestureProcessor::GestureProcessor()
33 : mCurrentGesturedActor( NULL ),
34 mGesturedActorDisconnected(false)
38 GestureProcessor::~GestureProcessor()
43 void GestureProcessor::GetGesturedActor( Dali::Actor& actor, const GestureDetectorContainer& connectedDetectors, std::vector<GestureDetector*>& gestureDetectors, Functor& functor )
47 Actor* actorImpl( &GetImplementation(actor) );
49 // Check if our hit actor or any of its parents are attached to any registered detector.
50 // Find all detectors that have the actor attached.
51 for ( GestureDetectorContainer::const_iterator iter = connectedDetectors.begin(), endIter = connectedDetectors.end(); iter != endIter; ++iter )
53 GestureDetector* current(*iter);
55 // Check whether the actor is attached to the gesture detector and then call the functor to
56 // check whether the gesture detector satisfies the current gesture's parameters.
57 if ( current->IsAttached( *actorImpl ) && functor( current, actorImpl ) )
59 gestureDetectors.push_back(current);
63 // The hit actor or one of the parents is a gestured actor, break out.
64 if ( !gestureDetectors.empty() )
69 // No match, we should now check the hit actor's parent.
70 actor = actor.GetParent();
74 void GestureProcessor::ProcessAndEmit( const HitTestAlgorithm::Results& hitTestResults, const GestureDetectorContainer& connectedDetectors, Functor& functor )
76 Dali::Actor actor( hitTestResults.actor );
80 std::vector<GestureDetector*> gestureDetectors;
82 GetGesturedActor( actor, connectedDetectors, gestureDetectors, functor );
84 if ( actor && !gestureDetectors.empty() )
86 // We have a match but check if the hit point is within the gestured actor's bounds.
87 // If it is not then continue up the actor hierarchy.
89 if ( actor == hitTestResults.actor )
91 // Our gesture detector's attached actor WAS the hit actor so we can call the emitting functor.
92 functor( actor, gestureDetectors, hitTestResults.actorCoordinates );
93 break; // We have found AND emitted a signal on the gestured actor, break out.
97 if ( GetImplementation(actor).IsHittable() )
99 const Vector3 size( actor.GetCurrentSize() );
101 if ( ( size.x > 0.0f ) && ( size.y > 0.0f ) )
103 // Ensure tap is within the actor's area
104 Actor& actorImpl = GetImplementation(actor);
105 if ( actorImpl.RaySphereTest( hitTestResults.rayOrigin, hitTestResults.rayDirection ) ) // Quick check
107 Vector4 hitPointLocal;
108 float distance( 0.0f );
109 if( actorImpl.RayActorTest( hitTestResults.rayOrigin, hitTestResults.rayDirection, hitPointLocal, distance ) )
111 // One of the hit actor's parents was the gestured actor so call the emitting functor.
112 functor( actor, gestureDetectors, Vector2( hitPointLocal.x, hitPointLocal.y ) );
113 break; // We have found AND emitted a signal on the gestured actor, break out.
121 // Continue up hierarchy to see if any of the parents require this gesture.
124 actor = actor.GetParent();
129 bool GestureProcessor::HitTest(
131 Vector2 screenCoordinates,
132 HitTestAlgorithm::Results& hitTestResults)
136 HitTestAlgorithm::HitTest( stage, screenCoordinates, hitTestResults );
137 if( hitTestResults.renderTask && hitTestResults.actor )
139 if( ! GetImplementation( hitTestResults.renderTask ).IsSystemLevel() )
145 DALI_LOG_ERROR( "Gesture not possible in SystemOverlay" );
151 void GestureProcessor::SetActor( Dali::Actor actor )
153 if ( actor && actor != mCurrentGesturedActor )
157 mCurrentGesturedActor = &GetImplementation( actor );
158 mCurrentGesturedActor->AddObserver( *this );
160 mGesturedActorDisconnected = false;
163 void GestureProcessor::ResetActor()
165 if ( mCurrentGesturedActor )
167 mCurrentGesturedActor->RemoveObserver( *this );
168 mCurrentGesturedActor = NULL;
169 mGesturedActorDisconnected = false;
173 Actor* GestureProcessor::GetCurrentGesturedActor()
175 return mGesturedActorDisconnected ? NULL : mCurrentGesturedActor;
178 void GestureProcessor::SceneObjectRemoved(ProxyObject& proxy)
180 if ( mCurrentGesturedActor == &proxy &&
181 !mGesturedActorDisconnected )
183 // Inform deriving classes.
184 OnGesturedActorStageDisconnection();
186 // do not call proxy.RemoveObserver here, proxy is currently iterating through observers... you wouldnt want to upset proxy now would you?
187 mGesturedActorDisconnected = true;
191 void GestureProcessor::ProxyDestroyed(ProxyObject& proxy)
193 if ( mCurrentGesturedActor == &proxy )
195 // Inform deriving classes.
196 OnGesturedActorStageDisconnection();
198 mCurrentGesturedActor = NULL;
202 } // namespace Internal