/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include <dali/internal/event/actors/actor-impl.h>
#include <dali/internal/event/actors/layer-impl.h>
#include <dali/internal/event/common/scene-impl.h>
-#include <dali/internal/event/events/hit-test-algorithm-impl.h>
#include <dali/internal/event/events/actor-gesture-data.h>
+#include <dali/internal/event/events/hit-test-algorithm-impl.h>
+#include <dali/internal/event/events/ray-test.h>
#include <dali/internal/event/render-tasks/render-task-impl.h>
namespace Dali
{
-
namespace Internal
{
-
namespace
{
-
/**
* Functor to check whether an actor requires a particular gesture or not
*/
struct GestureHitTestCheck : public HitTestAlgorithm::HitTestInterface
{
- GestureHitTestCheck( GestureType::Value type )
- : mType( type )
+ GestureHitTestCheck(GestureType::Value type)
+ : mType(type)
{
}
- bool IsActorHittable( Actor* actor ) override
+ bool IsActorHittable(Actor* actor) override
{
- return actor->IsGestureRequired( mType ) && // Does the Application or derived actor type require the gesture?
- actor->IsHittable(); // Is actor sensitive, visible and on the scene?
+ return actor->IsGestureRequired(mType) && // Does the Application or derived actor type require the gesture?
+ actor->IsHittable(); // Is actor sensitive, visible and on the scene?
}
- bool DescendActorHierarchy( Actor* actor ) override
+ bool DescendActorHierarchy(Actor* actor) override
{
return actor->IsVisible() && // Actor is visible, if not visible then none of its children are visible.
actor->IsSensitive(); // Actor is sensitive, if insensitive none of its children should be hittable either.
}
- bool DoesLayerConsumeHit( Layer* layer ) override
+ bool DoesLayerConsumeHit(Layer* layer) override
{
return layer->IsTouchConsumed();
}
+ bool ActorRequiresHitResultCheck(Actor* actor, Integration::Point point, Vector2 hitPointLocal, uint32_t timeStamp) override
+ {
+ return actor->EmitHitTestResultSignal(point, hitPointLocal, timeStamp);
+ }
+
GestureType::Value mType;
};
} // unnamed namespace
-
-GestureProcessor::GestureProcessor( GestureType::Value type )
+GestureProcessor::GestureProcessor(GestureType::Value type)
: mGestureRecognizer(),
- mNeedsUpdate( false ),
- mType( type ),
- mCurrentGesturedActor( nullptr ),
- mGesturedActorDisconnected( false )
+ mNeedsUpdate(false),
+ mType(type),
+ mCurrentGesturedActor(nullptr),
+ mPoint(),
+ mEventTime(0u),
+ mGesturedActorDisconnected(false)
{
}
ResetActor();
}
-void GestureProcessor::ProcessTouch( Scene& scene, const Integration::TouchEvent& event )
+void GestureProcessor::ProcessTouch(Scene& scene, const Integration::TouchEvent& event)
{
- if( mGestureRecognizer )
+ if(mGestureRecognizer)
{
+ if(!event.points.empty())
+ {
+ mPoint = event.points[0];
+ mEventTime = event.time;
+ }
mGestureRecognizer->SendEvent(scene, event);
}
}
-void GestureProcessor::GetGesturedActor( Actor*& actor, GestureDetectorContainer& gestureDetectors )
+void GestureProcessor::GetGesturedActor(Actor*& actor, GestureDetectorContainer& gestureDetectors)
{
- while ( actor )
+ while(actor)
{
// We may be checking a parent so ensure the parent requires this gesture (and do not unintentionally create the gesture data for the parent)
- if ( actor->IsGestureRequired( mType ) )
+ if(actor->IsGestureRequired(mType))
{
// Retrieve the actor's detectors and check if they satisfy current gesture
- const GestureDetectorContainer& connectedDetectors( actor->GetGestureData().GetGestureDetectorContainer( mType ) );
- const GestureDetectorContainer::const_iterator endIter( connectedDetectors.end() );
- for ( GestureDetectorContainer::const_iterator iter = connectedDetectors.begin(); iter != endIter; ++iter )
+ const GestureDetectorContainer& connectedDetectors(actor->GetGestureData().GetGestureDetectorContainer(mType));
+ const GestureDetectorContainer::const_iterator endIter(connectedDetectors.end());
+ for(GestureDetectorContainer::const_iterator iter = connectedDetectors.begin(); iter != endIter; ++iter)
{
GestureDetector* current(*iter);
// Check deriving class for whether the current gesture satisfies the gesture detector's parameters.
- if ( CheckGestureDetector( current, actor ) )
+ if(CheckGestureDetector(current, actor))
{
gestureDetectors.push_back(current);
}
}
// The hit actor or one of the parents is a gestured actor, break out.
- if ( !gestureDetectors.empty() )
+ if(!gestureDetectors.empty())
{
break;
}
}
}
-void GestureProcessor::ProcessAndEmit( HitTestAlgorithm::Results& hitTestResults )
+void GestureProcessor::ProcessAndEmit(HitTestAlgorithm::Results& hitTestResults)
{
- if ( hitTestResults.actor )
+ if(hitTestResults.actor)
{
- Actor* hitTestActor( &GetImplementation( hitTestResults.actor ) );
- Actor* actor( hitTestActor );
+ Actor* hitTestActor(&GetImplementation(hitTestResults.actor));
+ Actor* actor(hitTestActor);
+ RayTest rayTest;
- while ( actor )
+ while(actor)
{
GestureDetectorContainer gestureDetectors;
- GetGesturedActor( actor, gestureDetectors );
+ GetGesturedActor(actor, gestureDetectors);
- if ( actor && !gestureDetectors.empty() )
+ if(actor && !gestureDetectors.empty())
{
// We have a match but check if the hit point is within the gestured actor's bounds.
// If it is not then continue up the actor hierarchy.
- if ( actor == hitTestActor )
+ if(actor == hitTestActor)
{
// Our gesture detector's attached actor WAS the hit actor so we can can emit the signal.
- EmitGestureSignal( actor, gestureDetectors, hitTestResults.actorCoordinates );
- break; // We have found AND emitted a signal on the gestured actor, break out.
+ EmitGestureSignal(actor, gestureDetectors, hitTestResults.actorCoordinates);
+ // If NeedGesturePropagation is true, it passes the gesture to the parent.
+ if(!actor->NeedGesturePropagation())
+ {
+ break; // We have found AND emitted a signal on the gestured actor, break out.
+ }
+ actor->SetNeedGesturePropagation(false);
}
else
{
- if ( actor->IsHittable() )
+ if(actor->IsHittable())
{
- const Vector3 size( actor->GetCurrentSize() );
+ const Vector3 size(actor->GetCurrentSize());
- if ( ( size.x > 0.0f ) && ( size.y > 0.0f ) )
+ if((size.x > 0.0f) && (size.y > 0.0f))
{
// Ensure tap is within the actor's area
- if ( actor->RaySphereTest( hitTestResults.rayOrigin, hitTestResults.rayDirection ) ) // Quick check
+ if(rayTest.SphereTest(*actor, hitTestResults.rayOrigin, hitTestResults.rayDirection)) // Quick check
{
Vector2 hitPointLocal;
- float distance( 0.0f );
- if( actor->RayActorTest( hitTestResults.rayOrigin, hitTestResults.rayDirection, hitPointLocal, distance ) )
+ float distance(0.0f);
+ if(rayTest.ActorTest(*actor, hitTestResults.rayOrigin, hitTestResults.rayDirection, hitPointLocal, distance))
{
// One of the parents was the gestured actor so we can emit the signal for that actor.
- EmitGestureSignal( actor, gestureDetectors, hitPointLocal );
- break; // We have found AND emitted a signal on the gestured actor, break out.
+ EmitGestureSignal(actor, gestureDetectors, hitPointLocal);
+ // If NeedGesturePropagation is true, it passes the gesture to the parent.
+ if(!actor->NeedGesturePropagation())
+ {
+ break; // We have found AND emitted a signal on the gestured actor, break out.
+ }
+ actor->SetNeedGesturePropagation(false);
}
}
}
}
// Continue up hierarchy to see if any of the parents require this gesture.
- if ( actor )
+ if(actor)
{
actor = actor->GetParent();
}
}
}
-bool GestureProcessor::HitTest( Scene& scene, Vector2 screenCoordinates, HitTestAlgorithm::Results& hitTestResults )
+bool GestureProcessor::HitTest(Scene& scene, Vector2 screenCoordinates, HitTestAlgorithm::Results& hitTestResults)
{
- GestureHitTestCheck hitCheck( mType );
- HitTestAlgorithm::HitTest( scene.GetSize(), scene.GetRenderTaskList(), scene.GetLayerList(), screenCoordinates, hitTestResults, hitCheck );
+ GestureHitTestCheck hitCheck(mType);
+ hitTestResults.point = mPoint;
+ hitTestResults.eventTime = mEventTime;
+ HitTestAlgorithm::HitTest(scene.GetSize(), scene.GetRenderTaskList(), scene.GetLayerList(), screenCoordinates, hitTestResults, hitCheck);
return hitTestResults.renderTask && hitTestResults.actor;
}
-void GestureProcessor::SetActor( Actor* actor )
+void GestureProcessor::SetActor(Actor* actor)
{
- if ( actor && actor != mCurrentGesturedActor )
+ if(actor && actor != mCurrentGesturedActor)
{
ResetActor();
mCurrentGesturedActor = actor;
- mCurrentGesturedActor->AddObserver( *this );
+ mCurrentGesturedActor->AddObserver(*this);
}
mGesturedActorDisconnected = false;
}
void GestureProcessor::ResetActor()
{
- if ( mCurrentGesturedActor )
+ if(mCurrentGesturedActor)
{
- mCurrentGesturedActor->RemoveObserver( *this );
- mCurrentGesturedActor = nullptr;
+ mCurrentGesturedActor->RemoveObserver(*this);
+ mCurrentGesturedActor = nullptr;
mGesturedActorDisconnected = false;
}
}
void GestureProcessor::SceneObjectRemoved(Object& object)
{
- if ( mCurrentGesturedActor == &object &&
- !mGesturedActorDisconnected )
+ if(mCurrentGesturedActor == &object &&
+ !mGesturedActorDisconnected)
{
// Inform deriving classes.
OnGesturedActorStageDisconnection();
void GestureProcessor::ObjectDestroyed(Object& object)
{
- if ( mCurrentGesturedActor == &object )
+ if(mCurrentGesturedActor == &object)
{
// Inform deriving classes.
OnGesturedActorStageDisconnection();