2 * Copyright (c) 2019 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.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://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <dali/internal/event/events/rotation-gesture/rotation-gesture-processor.h>
25 #include <dali/public-api/actors/actor.h>
26 #include <dali/public-api/math/vector2.h>
27 #include <dali/devel-api/events/gesture-devel.h>
28 #include <dali/internal/event/events/rotation-gesture/rotation-gesture-event.h>
29 #include <dali/integration-api/debug.h>
30 #include <dali/internal/event/common/scene-impl.h>
31 #include <dali/internal/event/render-tasks/render-task-impl.h>
32 #include <dali/internal/event/events/rotation-gesture/rotation-gesture-recognizer.h>
33 #include <dali/internal/event/events/gesture-requests.h>
34 #include <dali/devel-api/events/rotation-gesture.h>
46 * Creates a RotationGesture and asks the specified detector to emit its detected signal.
47 * @param[in] actor The actor that has been rotationed.
48 * @param[in] gestureDetectors The gesture detector container that should emit the signal.
49 * @param[in] rotationEvent The rotationEvent received from the adaptor.
50 * @param[in] localCenter Relative to the actor attached to the detector.
52 void EmitRotationSignal(
54 const GestureDetectorContainer& gestureDetectors,
55 const RotationGestureEvent& rotationEvent,
58 RotationGesture rotation(rotationEvent.state);
59 rotation.time = rotationEvent.time;
60 rotation.rotation = rotationEvent.rotation;
61 rotation.screenCenterPoint = rotationEvent.centerPoint;
62 rotation.localCenterPoint = localCenter;
64 Dali::Actor actorHandle( actor );
65 const GestureDetectorContainer::const_iterator endIter = gestureDetectors.end();
66 for ( GestureDetectorContainer::const_iterator iter = gestureDetectors.begin(); iter != endIter; ++iter )
68 static_cast< RotationGestureDetector* >( *iter )->EmitRotationGestureSignal( actorHandle, rotation );
73 * Functor which checks whether the specified actor is attached to the gesture detector.
74 * It returns true if it is no longer attached. This can be used in remove_if functions.
76 struct IsNotAttachedFunctor
80 * @param[in] actor The actor to check whether it is attached.
82 IsNotAttachedFunctor(Actor* actor)
88 * Returns true if not attached, false if it is still attached.
89 * @param[in] detector The detector to check.
90 * @return true, if not attached, false otherwise.
92 bool operator()(const GestureDetector* detector) const
94 return !detector->IsAttached(*actorToCheck);
97 Actor* actorToCheck; ///< The actor to check whether it is attached or not.
100 } // unnamed namespace
102 RotationGestureProcessor::RotationGestureProcessor()
103 : GestureProcessor( DevelGesture::Rotation ),
104 mRotationGestureDetectors(),
105 mCurrentRotationEmitters(),
106 mCurrentRotationEvent( nullptr )
110 void RotationGestureProcessor::Process( Scene& scene, const RotationGestureEvent& rotationEvent )
112 switch ( rotationEvent.state )
114 case Gesture::Started:
116 // The rotation gesture should only be sent to the gesture detector which first received it so that
117 // it can be told when the gesture ends as well.
119 mCurrentRotationEmitters.clear();
122 HitTestAlgorithm::Results hitTestResults;
123 if( HitTest( scene, rotationEvent.centerPoint, hitTestResults ) )
125 // Record the current render-task for Screen->Actor coordinate conversions
126 mCurrentRenderTask = hitTestResults.renderTask;
128 // Set mCurrentRotationEvent to use inside overridden methods called from ProcessAndEmit()
129 mCurrentRotationEvent = &rotationEvent;
130 ProcessAndEmit( hitTestResults );
131 mCurrentRotationEvent = NULL;
136 case Gesture::Continuing:
137 case Gesture::Finished:
138 case Gesture::Cancelled:
140 // Only send subsequent rotation gesture signals if we processed the rotation gesture when it started.
141 // Check if actor is still touchable.
143 Actor* currentGesturedActor = GetCurrentGesturedActor();
144 if ( currentGesturedActor )
146 if ( currentGesturedActor->IsHittable() && !mCurrentRotationEmitters.empty() && mCurrentRenderTask )
148 // Ensure actor is still attached to the emitters, if it is not then remove the emitter.
149 GestureDetectorContainer::iterator endIter = std::remove_if( mCurrentRotationEmitters.begin(), mCurrentRotationEmitters.end(), IsNotAttachedFunctor(currentGesturedActor) );
150 mCurrentRotationEmitters.erase( endIter, mCurrentRotationEmitters.end() );
152 if ( !mCurrentRotationEmitters.empty() )
155 RenderTask& renderTaskImpl( *mCurrentRenderTask.Get() );
156 currentGesturedActor->ScreenToLocal( renderTaskImpl, actorCoords.x, actorCoords.y, rotationEvent.centerPoint.x, rotationEvent.centerPoint.y );
158 EmitRotationSignal( currentGesturedActor, mCurrentRotationEmitters, rotationEvent, actorCoords );
162 // If we have no current emitters then clear rotated actor as well.
166 // Clear current emitters if rotation gesture has ended or been cancelled.
167 if ( rotationEvent.state == Gesture::Finished || rotationEvent.state == Gesture::Cancelled )
169 mCurrentRotationEmitters.clear();
175 mCurrentRotationEmitters.clear();
183 case Gesture::Possible:
191 void RotationGestureProcessor::AddGestureDetector( RotationGestureDetector* gestureDetector, Scene& /* scene */ )
193 bool createRecognizer(mRotationGestureDetectors.empty());
195 mRotationGestureDetectors.push_back(gestureDetector);
197 if (createRecognizer)
199 mGestureRecognizer = new RotationGestureRecognizer( *this );
203 void RotationGestureProcessor::RemoveGestureDetector( RotationGestureDetector* gestureDetector )
205 if ( !mCurrentRotationEmitters.empty() )
207 // Check if the removed detector was one that is currently being rotated and remove it from emitters.
208 GestureDetectorContainer::iterator endIter = std::remove( mCurrentRotationEmitters.begin(), mCurrentRotationEmitters.end(), gestureDetector );
209 mCurrentRotationEmitters.erase( endIter, mCurrentRotationEmitters.end() );
211 // If we no longer have any emitters, then we should clear mCurrentGesturedActor as well
212 if ( mCurrentRotationEmitters.empty() )
218 // Find the detector...
219 RotationGestureDetectorContainer::iterator endIter = std::remove( mRotationGestureDetectors.begin(), mRotationGestureDetectors.end(), gestureDetector );
220 DALI_ASSERT_DEBUG( endIter != mRotationGestureDetectors.end() );
223 mRotationGestureDetectors.erase(endIter, mRotationGestureDetectors.end());
225 if (mRotationGestureDetectors.empty())
227 mGestureRecognizer.Detach();
231 void RotationGestureProcessor::OnGesturedActorStageDisconnection()
233 mCurrentRotationEmitters.clear();
236 bool RotationGestureProcessor::CheckGestureDetector( GestureDetector* detector, Actor* actor )
238 // No special case required for rotation.
242 void RotationGestureProcessor::EmitGestureSignal( Actor* actor, const GestureDetectorContainer& gestureDetectors, Vector2 actorCoordinates )
244 DALI_ASSERT_DEBUG( mCurrentRotationEvent );
246 EmitRotationSignal( actor, gestureDetectors, *mCurrentRotationEvent, actorCoordinates );
248 if ( actor->OnStage() )
250 mCurrentRotationEmitters = gestureDetectors;
255 } // namespace Internal