This is similar to how Android works.
1. Events are propagated based on geometry.
2. TouchEvent
- If there is an actor who consumes, only the actor who consumes will receive the event that comes after.
3. Gesture will be a way for apps to receive and recognize touch events in the future.
Change-Id: Iac58129b729446d3dffa54ad0aacc8d5e8135f19
utc-Dali-FrameCallbackInterface.cpp
utc-Dali-FreeList.cpp
utc-Dali-Geometry.cpp
+ utc-Dali-GeoHitTestAlgorithm.cpp
+ utc-Dali-GeoHoverProcessing.cpp
+ utc-Dali-GeoTouchProcessing.cpp
utc-Dali-GestureDetector.cpp
utc-Dali-Handle.cpp
utc-Dali-Hash.cpp
gTouchCallBackCalled3 = false;
}
+static void ResetTouchCallbacks(TestApplication& application)
+{
+ // reset touch
+ Dali::Integration::Point point;
+ point.SetDeviceId(1);
+ point.SetState(PointState::UP);
+ point.SetScreenPosition(Vector2(10.f, 10.f));
+ Dali::Integration::TouchEvent touchEvent;
+ touchEvent.AddPoint(point);
+ application.ProcessEvent(touchEvent);
+
+ ResetTouchCallbacks();
+}
+
static bool TestCallback3(Actor actor, const HoverEvent& event)
{
gHoverCallBackCalled = true;
END_TEST;
}
+int UtcDaliActorGeoTouchedSignal(void)
+{
+ TestApplication application;
+
+ application.GetScene().SetGeometryHittestEnabled(true);
+ ResetTouchCallbacks(application);
+
+ // get the root layer
+ Actor actor = application.GetScene().GetRootLayer();
+ DALI_TEST_CHECK(gTouchCallBackCalled == false);
+
+ application.SendNotification();
+ application.Render();
+
+ // connect to its touch signal
+ actor.TouchedSignal().Connect(TestTouchCallback);
+
+ // simulate a touch event in the middle of the screen
+ Vector2 touchPoint(application.GetScene().GetSize() * 0.5);
+ Dali::Integration::Point point;
+ point.SetDeviceId(1);
+ point.SetState(PointState::DOWN);
+ point.SetScreenPosition(Vector2(touchPoint.x, touchPoint.y));
+ Dali::Integration::TouchEvent touchEvent;
+ touchEvent.AddPoint(point);
+ application.ProcessEvent(touchEvent);
+
+ DALI_TEST_CHECK(gTouchCallBackCalled == true);
+ END_TEST;
+}
+
int UtcDaliActorHoveredSignal(void)
{
TestApplication application;
END_TEST;
}
+int UtcDaliActorGeoHitTest(void)
+{
+ struct HitTestData
+ {
+ public:
+ HitTestData(const Vector3& scale, const Vector2& touchPoint, bool result)
+ : mScale(scale),
+ mTouchPoint(touchPoint),
+ mResult(result)
+ {
+ }
+
+ Vector3 mScale;
+ Vector2 mTouchPoint;
+ bool mResult;
+ };
+
+ TestApplication application;
+ tet_infoline(" UtcDaliActorHitTest");
+
+ // Fill a vector with different hit tests.
+ struct HitTestData* hitTestData[] = {
+ // scale touch point result
+ new HitTestData(Vector3(100.f, 100.f, 1.f), Vector2(289.f, 400.f), true), // touch point close to the right edge (inside)
+ new HitTestData(Vector3(100.f, 100.f, 1.f), Vector2(291.f, 400.f), false), // touch point close to the right edge (outside)
+ new HitTestData(Vector3(110.f, 100.f, 1.f), Vector2(291.f, 400.f), true), // same point as above with a wider scale. Should be inside.
+ new HitTestData(Vector3(100.f, 100.f, 1.f), Vector2(200.f, 451.f), false), // touch point close to the down edge (outside)
+ new HitTestData(Vector3(100.f, 110.f, 1.f), Vector2(200.f, 451.f), true), // same point as above with a wider scale. Should be inside.
+ NULL,
+ };
+
+ // get the root layer
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ actor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+
+ application.GetScene().Add(actor);
+ application.GetScene().SetGeometryHittestEnabled(true);
+
+ ResetTouchCallbacks(application);
+
+ unsigned int index = 0;
+ while(NULL != hitTestData[index])
+ {
+ actor.SetProperty(Actor::Property::SIZE, Vector2(1.f, 1.f));
+ actor.SetProperty(Actor::Property::SCALE, Vector3(hitTestData[index]->mScale.x, hitTestData[index]->mScale.y, hitTestData[index]->mScale.z));
+
+ // flush the queue and render once
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_CHECK(!gTouchCallBackCalled);
+
+ // connect to its touch signal
+ actor.TouchedSignal().Connect(TestTouchCallback);
+
+ Dali::Integration::Point point;
+ point.SetState(PointState::DOWN);
+ point.SetScreenPosition(Vector2(hitTestData[index]->mTouchPoint.x, hitTestData[index]->mTouchPoint.y));
+ Dali::Integration::TouchEvent event;
+ event.AddPoint(point);
+
+ // flush the queue and render once
+ application.SendNotification();
+ application.Render();
+ application.ProcessEvent(event);
+
+ DALI_TEST_CHECK(gTouchCallBackCalled == hitTestData[index]->mResult);
+
+ if(gTouchCallBackCalled != hitTestData[index]->mResult)
+ tet_printf("Test failed:\nScale %f %f %f\nTouchPoint %f, %f\nResult %d\n",
+ hitTestData[index]->mScale.x,
+ hitTestData[index]->mScale.y,
+ hitTestData[index]->mScale.z,
+ hitTestData[index]->mTouchPoint.x,
+ hitTestData[index]->mTouchPoint.y,
+ hitTestData[index]->mResult);
+
+ ResetTouchCallbacks(application);
+ ++index;
+ }
+ END_TEST;
+}
+
int UtcDaliActorSetDrawMode(void)
{
TestApplication application;
END_TEST;
}
+int UtcDaliActorGeoTouchRaiseLower(void)
+{
+ tet_infoline("UtcDaliActor Raise and Lower test\n");
+
+ TestApplication application;
+
+ Debug::Filter::SetGlobalLogLevel(Debug::Verbose);
+ Debug::Filter::EnableGlobalTrace();
+
+ Integration::Scene stage(application.GetScene());
+
+ Actor actorA = Actor::New();
+ Actor actorB = Actor::New();
+ Actor actorC = Actor::New();
+
+ actorA.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ actorA.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+
+ actorB.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ actorB.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+
+ actorC.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ actorC.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+
+ actorA.SetProperty(Actor::Property::WIDTH_RESIZE_POLICY, "FILL_TO_PARENT");
+ actorA.SetProperty(Actor::Property::HEIGHT_RESIZE_POLICY, "FILL_TO_PARENT");
+
+ actorB.SetProperty(Actor::Property::WIDTH_RESIZE_POLICY, "FILL_TO_PARENT");
+ actorB.SetProperty(Actor::Property::HEIGHT_RESIZE_POLICY, "FILL_TO_PARENT");
+
+ actorC.SetProperty(Actor::Property::WIDTH_RESIZE_POLICY, "FILL_TO_PARENT");
+ actorC.SetProperty(Actor::Property::HEIGHT_RESIZE_POLICY, "FILL_TO_PARENT");
+
+ stage.Add(actorA);
+ stage.Add(actorB);
+ stage.Add(actorC);
+
+ application.GetScene().SetGeometryHittestEnabled(true);
+ ResetTouchCallbacks(application);
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled2, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION);
+
+ // connect to actor touch signals, will use touch callbacks to determine which actor is on top.
+ // Only top actor will get touched.
+ actorA.TouchedSignal().Connect(TestTouchCallback);
+ actorB.TouchedSignal().Connect(TestTouchCallback2);
+ actorC.TouchedSignal().Connect(TestTouchCallback3);
+
+ // Connect ChildOrderChangedSignal
+ bool orderChangedSignal(false);
+ Actor orderChangedActor;
+ ChildOrderChangedFunctor f(orderChangedSignal, orderChangedActor);
+ DevelActor::ChildOrderChangedSignal(stage.GetRootLayer()).Connect(&application, f);
+
+ Dali::Integration::Point point;
+ point.SetDeviceId(1);
+ point.SetState(PointState::DOWN);
+ point.SetScreenPosition(Vector2(10.f, 10.f));
+ Dali::Integration::TouchEvent touchEvent;
+ touchEvent.AddPoint(point);
+
+ application.ProcessEvent(touchEvent);
+
+ DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled2, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled3, true, TEST_LOCATION);
+
+ ResetTouchCallbacks(application);
+
+ tet_printf("Testing Raising of Actor\n");
+
+ int preActorOrder(0);
+ int postActorOrder(0);
+
+ Property::Value value = actorB.GetProperty(Dali::DevelActor::Property::SIBLING_ORDER);
+ value.Get(preActorOrder);
+
+ DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
+ actorB.Raise();
+ DALI_TEST_EQUALS(orderChangedSignal, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(orderChangedActor, actorB, TEST_LOCATION);
+
+ // Ensure sort order is calculated before next touch event
+ application.SendNotification();
+
+ value = actorB.GetProperty(Dali::DevelActor::Property::SIBLING_ORDER);
+ value.Get(postActorOrder);
+
+ tet_printf("Raised ActorB from (%d) to (%d) \n", preActorOrder, postActorOrder);
+
+ application.ProcessEvent(touchEvent);
+
+ DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled2, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION);
+
+ ResetTouchCallbacks(application);
+
+ tet_printf("Testing Lowering of Actor\n");
+
+ value = actorB.GetProperty(Dali::DevelActor::Property::SIBLING_ORDER);
+ value.Get(preActorOrder);
+
+ orderChangedSignal = false;
+
+ DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
+ actorB.Lower();
+ DALI_TEST_EQUALS(orderChangedSignal, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(orderChangedActor, actorB, TEST_LOCATION);
+
+ application.SendNotification(); // ensure sort order calculated before next touch event
+
+ value = actorB.GetProperty(Dali::DevelActor::Property::SIBLING_ORDER);
+ value.Get(postActorOrder);
+
+ tet_printf("Lowered ActorB from (%d) to (%d) \n", preActorOrder, postActorOrder);
+
+ application.ProcessEvent(touchEvent);
+
+ DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled2, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled3, true, TEST_LOCATION);
+
+ ResetTouchCallbacks(application);
+
+ Debug::Filter::DisableGlobalTrace();
+ Debug::Filter::SetGlobalLogLevel(Debug::NoLogging);
+
+ END_TEST;
+}
+
int UtcDaliActorRaiseToTopLowerToBottom(void)
{
tet_infoline("UtcDaliActorRaiseToTop and LowerToBottom test \n");
END_TEST;
}
-int UtcDaliActorRaiseAbove(void)
+int UtcDaliActorGeoTouchRaiseToTopLowerToBottom(void)
{
- tet_infoline("UtcDaliActor RaiseToAbove test \n");
+ tet_infoline("UtcDaliActorRaiseToTop and LowerToBottom test \n");
TestApplication application;
Actor actorB = Actor::New();
Actor actorC = Actor::New();
- actorA.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
- actorA.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
-
- actorB.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ // Set up renderers to add to Actors, float value 1, 2, 3 assigned to each
+ // enables checking of which actor the uniform is assigned too
+ Shader shaderA = CreateShader();
+ shaderA.RegisterProperty("uRendererColor", 1.f);
+
+ Shader shaderB = CreateShader();
+ shaderB.RegisterProperty("uRendererColor", 2.f);
+
+ Shader shaderC = CreateShader();
+ shaderC.RegisterProperty("uRendererColor", 3.f);
+
+ Geometry geometry = CreateQuadGeometry();
+
+ // Add renderers to Actors so ( uRendererColor, 1 ) is A, ( uRendererColor, 2 ) is B, and ( uRendererColor, 3 ) is C,
+ Renderer rendererA = Renderer::New(geometry, shaderA);
+ actorA.AddRenderer(rendererA);
+
+ Renderer rendererB = Renderer::New(geometry, shaderB);
+ actorB.AddRenderer(rendererB);
+
+ Renderer rendererC = Renderer::New(geometry, shaderC);
+ actorC.AddRenderer(rendererC);
+
+ actorA.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ actorA.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+
+ actorB.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
actorB.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
actorC.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
stage.Add(actorB);
stage.Add(actorC);
- ResetTouchCallbacks();
+ application.GetScene().SetGeometryHittestEnabled(true);
+ ResetTouchCallbacks(application);
+
+ // Connect ChildOrderChangedSignal
+ bool orderChangedSignal(false);
+ Actor orderChangedActor;
+ ChildOrderChangedFunctor f(orderChangedSignal, orderChangedActor);
+ DevelActor::ChildOrderChangedSignal(stage.GetRootLayer()).Connect(&application, f);
+
+ // Set up gl abstraction trace so can query the set uniform order
+ TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+ glAbstraction.EnableSetUniformCallTrace(true);
+ glAbstraction.ResetSetUniformCallStack();
+
+ TraceCallStack& glSetUniformStack = glAbstraction.GetSetUniformTrace();
application.SendNotification();
application.Render();
+ tet_printf("Trace Output:%s \n", glSetUniformStack.GetTraceString().c_str());
+
+ // Test order of uniforms in stack
+ int indexC = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "3.000000");
+ int indexB = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "2.000000");
+ int indexA = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "1.000000");
+
+ bool CBA = (indexC > indexB) && (indexB > indexA);
+
+ DALI_TEST_EQUALS(CBA, true, TEST_LOCATION);
+
DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION);
DALI_TEST_EQUALS(gTouchCallBackCalled2, false, TEST_LOCATION);
DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION);
actorB.TouchedSignal().Connect(TestTouchCallback2);
actorC.TouchedSignal().Connect(TestTouchCallback3);
- bool orderChangedSignal(false);
- Actor orderChangedActor;
- ChildOrderChangedFunctor f(orderChangedSignal, orderChangedActor);
- DevelActor::ChildOrderChangedSignal(stage.GetRootLayer()).Connect(&application, f);
-
Dali::Integration::Point point;
point.SetDeviceId(1);
point.SetState(PointState::DOWN);
DALI_TEST_EQUALS(gTouchCallBackCalled2, false, TEST_LOCATION);
DALI_TEST_EQUALS(gTouchCallBackCalled3, true, TEST_LOCATION);
- ResetTouchCallbacks();
+ ResetTouchCallbacks(application);
- tet_printf("Raise actor B Above Actor C\n");
+ tet_printf("RaiseToTop ActorA\n");
DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
- actorB.RaiseAbove(actorC);
+ actorA.RaiseToTop();
DALI_TEST_EQUALS(orderChangedSignal, true, TEST_LOCATION);
- DALI_TEST_EQUALS(orderChangedActor, actorB, TEST_LOCATION);
+ DALI_TEST_EQUALS(orderChangedActor, actorA, TEST_LOCATION);
+
+ application.SendNotification(); // ensure sorting order is calculated before next touch event
+
+ application.ProcessEvent(touchEvent);
+
+ glSetUniformStack.Reset();
- // Ensure sorting happens at end of Core::ProcessEvents() before next touch
application.SendNotification();
+ application.Render();
+
+ tet_printf("Trace:%s \n", glSetUniformStack.GetTraceString().c_str());
+
+ // Test order of uniforms in stack
+ indexC = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "3.000000");
+ indexB = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "2.000000");
+ indexA = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "1.000000");
+
+ tet_infoline("Testing A above C and B at bottom\n");
+ bool ACB = (indexA > indexC) && (indexC > indexB);
+
+ DALI_TEST_EQUALS(ACB, true, TEST_LOCATION);
+
+ DALI_TEST_EQUALS(gTouchCallBackCalled, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled2, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION);
+
+ ResetTouchCallbacks(application);
+
+ tet_printf("RaiseToTop ActorB\n");
+
+ orderChangedSignal = false;
+
+ DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
+ actorB.RaiseToTop();
+ DALI_TEST_EQUALS(orderChangedSignal, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(orderChangedActor, actorB, TEST_LOCATION);
+
+ application.SendNotification(); // Ensure sort order is calculated before next touch event
+
application.ProcessEvent(touchEvent);
+ glSetUniformStack.Reset();
+
+ application.SendNotification();
+ application.Render();
+
+ tet_printf("Trace:%s \n", glSetUniformStack.GetTraceString().c_str());
+
+ // Test order of uniforms in stack
+ indexC = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "3.000000");
+ indexB = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "2.000000");
+ indexA = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "1.000000");
+
+ tet_infoline("Testing B above A and C at bottom\n");
+ bool BAC = (indexB > indexA) && (indexA > indexC);
+
+ DALI_TEST_EQUALS(BAC, true, TEST_LOCATION);
+
DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION);
DALI_TEST_EQUALS(gTouchCallBackCalled2, true, TEST_LOCATION);
DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION);
- ResetTouchCallbacks();
+ ResetTouchCallbacks(application);
- tet_printf("Raise actor A Above Actor B\n");
+ tet_printf("LowerToBottom ActorA then ActorB leaving Actor C at Top\n");
orderChangedSignal = false;
DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
- actorA.RaiseAbove(actorB);
+ actorA.LowerToBottom();
DALI_TEST_EQUALS(orderChangedSignal, true, TEST_LOCATION);
DALI_TEST_EQUALS(orderChangedActor, actorA, TEST_LOCATION);
- // Ensure sorting happens at end of Core::ProcessEvents() before next touch
application.SendNotification();
+ application.Render();
- application.ProcessEvent(touchEvent); // process a touch event on ordered actors.
+ orderChangedSignal = false;
- DALI_TEST_EQUALS(gTouchCallBackCalled, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
+ actorB.LowerToBottom();
+ DALI_TEST_EQUALS(orderChangedSignal, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(orderChangedActor, actorB, TEST_LOCATION);
+
+ application.SendNotification();
+ application.Render();
+
+ application.ProcessEvent(touchEvent);
+
+ glSetUniformStack.Reset();
+
+ application.SendNotification();
+ application.Render();
+
+ tet_printf("Trace:%s \n", glSetUniformStack.GetTraceString().c_str());
+
+ // Test order of uniforms in stack
+ indexC = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "3.000000");
+ indexB = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "2.000000");
+ indexA = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "1.000000");
+
+ tet_infoline("Testing C above A and B at bottom\n");
+ bool CAB = (indexC > indexA) && (indexA > indexB);
+
+ DALI_TEST_EQUALS(CAB, true, TEST_LOCATION);
+
+ DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION);
DALI_TEST_EQUALS(gTouchCallBackCalled2, false, TEST_LOCATION);
- DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled3, true, TEST_LOCATION);
- ResetTouchCallbacks();
+ ResetTouchCallbacks(application);
END_TEST;
}
-int UtcDaliActorRaiseAbove2(void)
+int UtcDaliActorRaiseAbove(void)
{
- tet_infoline("UtcDaliActor RaiseToAbove test using SIBLING_ORDER property\n");
+ tet_infoline("UtcDaliActor RaiseToAbove test \n");
TestApplication application;
tet_printf("Raise actor B Above Actor C\n");
DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
- int newOrder = actorC[DevelActor::Property::SIBLING_ORDER];
- actorB[DevelActor::Property::SIBLING_ORDER] = newOrder;
+ actorB.RaiseAbove(actorC);
DALI_TEST_EQUALS(orderChangedSignal, true, TEST_LOCATION);
DALI_TEST_EQUALS(orderChangedActor, actorB, TEST_LOCATION);
orderChangedSignal = false;
DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
- newOrder = actorB[DevelActor::Property::SIBLING_ORDER];
- actorA[DevelActor::Property::SIBLING_ORDER] = newOrder;
+ actorA.RaiseAbove(actorB);
DALI_TEST_EQUALS(orderChangedSignal, true, TEST_LOCATION);
DALI_TEST_EQUALS(orderChangedActor, actorA, TEST_LOCATION);
END_TEST;
}
-int UtcDaliActorLowerBelow(void)
+int UtcDaliActorGeoTouchRaiseAbove(void)
{
- tet_infoline("UtcDaliActor LowerBelow test \n");
+ tet_infoline("UtcDaliActor RaiseToAbove test \n");
TestApplication application;
Integration::Scene stage(application.GetScene());
- // Set up renderers to add to Actors, float value 1, 2, 3 assigned to each
- // enables checking of which actor the uniform is assigned too
- Shader shaderA = CreateShader();
- shaderA.RegisterProperty("uRendererColor", 1.f);
-
- Shader shaderB = CreateShader();
- shaderB.RegisterProperty("uRendererColor", 2.f);
-
- Shader shaderC = CreateShader();
- shaderC.RegisterProperty("uRendererColor", 3.f);
-
Actor actorA = Actor::New();
Actor actorB = Actor::New();
Actor actorC = Actor::New();
- // Add renderers to Actors so ( uRendererColor, 1 ) is A, ( uRendererColor, 2 ) is B, and ( uRendererColor, 3 ) is C,
- Geometry geometry = CreateQuadGeometry();
-
- Renderer rendererA = Renderer::New(geometry, shaderA);
- actorA.AddRenderer(rendererA);
-
- Renderer rendererB = Renderer::New(geometry, shaderB);
- actorB.AddRenderer(rendererB);
-
- Renderer rendererC = Renderer::New(geometry, shaderC);
- actorC.AddRenderer(rendererC);
-
actorA.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
actorA.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
actorC.SetProperty(Actor::Property::WIDTH_RESIZE_POLICY, "FILL_TO_PARENT");
actorC.SetProperty(Actor::Property::HEIGHT_RESIZE_POLICY, "FILL_TO_PARENT");
- Actor container = Actor::New();
- container.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
- container.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
- stage.Add(container);
-
- container.Add(actorA);
- container.Add(actorB);
- container.Add(actorC);
-
- ResetTouchCallbacks();
-
- // Connect ChildOrderChangedSignal
- bool orderChangedSignal(false);
- Actor orderChangedActor;
- ChildOrderChangedFunctor f(orderChangedSignal, orderChangedActor);
- DevelActor::ChildOrderChangedSignal(container).Connect(&application, f);
-
- // Set up gl abstraction trace so can query the set uniform order
- TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
- glAbstraction.EnableSetUniformCallTrace(true);
- glAbstraction.ResetSetUniformCallStack();
- TraceCallStack& glSetUniformStack = glAbstraction.GetSetUniformTrace();
+ stage.Add(actorA);
+ stage.Add(actorB);
+ stage.Add(actorC);
- glAbstraction.ResetSetUniformCallStack();
+ application.GetScene().SetGeometryHittestEnabled(true);
+ ResetTouchCallbacks(application);
application.SendNotification();
application.Render();
- tet_printf("Trace:%s \n", glSetUniformStack.GetTraceString().c_str());
-
- // Test order of uniforms in stack
- int indexC = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "3.000000");
- int indexB = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "2.000000");
- int indexA = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "1.000000");
-
- tet_infoline("Testing C above B and A at bottom\n");
- bool CBA = (indexC > indexB) && (indexB > indexA);
-
- DALI_TEST_EQUALS(CBA, true, TEST_LOCATION);
-
DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION);
DALI_TEST_EQUALS(gTouchCallBackCalled2, false, TEST_LOCATION);
DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION);
actorB.TouchedSignal().Connect(TestTouchCallback2);
actorC.TouchedSignal().Connect(TestTouchCallback3);
+ bool orderChangedSignal(false);
+ Actor orderChangedActor;
+ ChildOrderChangedFunctor f(orderChangedSignal, orderChangedActor);
+ DevelActor::ChildOrderChangedSignal(stage.GetRootLayer()).Connect(&application, f);
+
Dali::Integration::Point point;
point.SetDeviceId(1);
point.SetState(PointState::DOWN);
Dali::Integration::TouchEvent touchEvent;
touchEvent.AddPoint(point);
- tet_infoline("UtcDaliActor Test Set up completed \n");
-
application.ProcessEvent(touchEvent);
DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION);
DALI_TEST_EQUALS(gTouchCallBackCalled2, false, TEST_LOCATION);
DALI_TEST_EQUALS(gTouchCallBackCalled3, true, TEST_LOCATION);
- ResetTouchCallbacks();
+ ResetTouchCallbacks(application);
- tet_printf("Lower actor C below Actor B ( actor B and A on same level due to insertion order) so C is below both \n");
+ tet_printf("Raise actor B Above Actor C\n");
DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
- actorC.LowerBelow(actorB);
+ actorB.RaiseAbove(actorC);
DALI_TEST_EQUALS(orderChangedSignal, true, TEST_LOCATION);
- DALI_TEST_EQUALS(orderChangedActor, actorC, TEST_LOCATION);
+ DALI_TEST_EQUALS(orderChangedActor, actorB, TEST_LOCATION);
// Ensure sorting happens at end of Core::ProcessEvents() before next touch
application.SendNotification();
- application.Render();
+ application.ProcessEvent(touchEvent);
- application.ProcessEvent(touchEvent); // touch event
+ DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled2, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION);
- glSetUniformStack.Reset();
+ ResetTouchCallbacks(application);
- application.SendNotification();
- application.Render();
+ tet_printf("Raise actor A Above Actor B\n");
- tet_printf("Trace:%s \n", glSetUniformStack.GetTraceString().c_str());
+ orderChangedSignal = false;
- // Test order of uniforms in stack
- indexC = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "3.000000");
- indexB = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "2.000000");
- indexA = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "1.000000");
+ DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
+ actorA.RaiseAbove(actorB);
+ DALI_TEST_EQUALS(orderChangedSignal, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(orderChangedActor, actorA, TEST_LOCATION);
- tet_infoline("Testing render order is A, C, B");
- DALI_TEST_EQUALS(indexC > indexA, true, TEST_LOCATION);
- DALI_TEST_EQUALS(indexB > indexC, true, TEST_LOCATION);
+ // Ensure sorting happens at end of Core::ProcessEvents() before next touch
+ application.SendNotification();
+
+ application.ProcessEvent(touchEvent); // process a touch event on ordered actors.
+
+ DALI_TEST_EQUALS(gTouchCallBackCalled, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled2, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION);
+
+ ResetTouchCallbacks(application);
+
+ END_TEST;
+}
+
+
+int UtcDaliActorRaiseAbove2(void)
+{
+ tet_infoline("UtcDaliActor RaiseToAbove test using SIBLING_ORDER property\n");
+
+ TestApplication application;
+
+ Integration::Scene stage(application.GetScene());
+
+ Actor actorA = Actor::New();
+ Actor actorB = Actor::New();
+ Actor actorC = Actor::New();
+
+ actorA.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ actorA.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+
+ actorB.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ actorB.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+
+ actorC.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ actorC.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+
+ actorA.SetProperty(Actor::Property::WIDTH_RESIZE_POLICY, "FILL_TO_PARENT");
+ actorA.SetProperty(Actor::Property::HEIGHT_RESIZE_POLICY, "FILL_TO_PARENT");
+
+ actorB.SetProperty(Actor::Property::WIDTH_RESIZE_POLICY, "FILL_TO_PARENT");
+ actorB.SetProperty(Actor::Property::HEIGHT_RESIZE_POLICY, "FILL_TO_PARENT");
+
+ actorC.SetProperty(Actor::Property::WIDTH_RESIZE_POLICY, "FILL_TO_PARENT");
+ actorC.SetProperty(Actor::Property::HEIGHT_RESIZE_POLICY, "FILL_TO_PARENT");
+
+ stage.Add(actorA);
+ stage.Add(actorB);
+ stage.Add(actorC);
+
+ ResetTouchCallbacks();
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled2, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION);
+
+ // connect to actor touch signals, will use touch callbacks to determine which actor is on top.
+ // Only top actor will get touched.
+ actorA.TouchedSignal().Connect(TestTouchCallback);
+ actorB.TouchedSignal().Connect(TestTouchCallback2);
+ actorC.TouchedSignal().Connect(TestTouchCallback3);
+
+ bool orderChangedSignal(false);
+ Actor orderChangedActor;
+ ChildOrderChangedFunctor f(orderChangedSignal, orderChangedActor);
+ DevelActor::ChildOrderChangedSignal(stage.GetRootLayer()).Connect(&application, f);
+
+ Dali::Integration::Point point;
+ point.SetDeviceId(1);
+ point.SetState(PointState::DOWN);
+ point.SetScreenPosition(Vector2(10.f, 10.f));
+ Dali::Integration::TouchEvent touchEvent;
+ touchEvent.AddPoint(point);
+
+ application.ProcessEvent(touchEvent);
+
+ DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled2, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled3, true, TEST_LOCATION);
+
+ ResetTouchCallbacks();
+
+ tet_printf("Raise actor B Above Actor C\n");
+
+ DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
+ int newOrder = actorC[DevelActor::Property::SIBLING_ORDER];
+ actorB[DevelActor::Property::SIBLING_ORDER] = newOrder;
+ DALI_TEST_EQUALS(orderChangedSignal, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(orderChangedActor, actorB, TEST_LOCATION);
+
+ // Ensure sorting happens at end of Core::ProcessEvents() before next touch
+ application.SendNotification();
+ application.ProcessEvent(touchEvent);
DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION);
DALI_TEST_EQUALS(gTouchCallBackCalled2, true, TEST_LOCATION);
ResetTouchCallbacks();
- tet_printf("Lower actor C below Actor A leaving B on top\n");
+ tet_printf("Raise actor A Above Actor B\n");
orderChangedSignal = false;
DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
- actorC.LowerBelow(actorA);
+ newOrder = actorB[DevelActor::Property::SIBLING_ORDER];
+ actorA[DevelActor::Property::SIBLING_ORDER] = newOrder;
DALI_TEST_EQUALS(orderChangedSignal, true, TEST_LOCATION);
- DALI_TEST_EQUALS(orderChangedActor, actorC, TEST_LOCATION);
+ DALI_TEST_EQUALS(orderChangedActor, actorA, TEST_LOCATION);
// Ensure sorting happens at end of Core::ProcessEvents() before next touch
application.SendNotification();
+
+ application.ProcessEvent(touchEvent); // process a touch event on ordered actors.
+
+ DALI_TEST_EQUALS(gTouchCallBackCalled, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled2, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION);
+
+ ResetTouchCallbacks();
+
+ END_TEST;
+}
+
+int UtcDaliActorGeoTouchRaiseAbove2(void)
+{
+ tet_infoline("UtcDaliActor RaiseToAbove test using SIBLING_ORDER property\n");
+
+ TestApplication application;
+
+ Integration::Scene stage(application.GetScene());
+
+ Actor actorA = Actor::New();
+ Actor actorB = Actor::New();
+ Actor actorC = Actor::New();
+
+ actorA.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ actorA.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+
+ actorB.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ actorB.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+
+ actorC.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ actorC.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+
+ actorA.SetProperty(Actor::Property::WIDTH_RESIZE_POLICY, "FILL_TO_PARENT");
+ actorA.SetProperty(Actor::Property::HEIGHT_RESIZE_POLICY, "FILL_TO_PARENT");
+
+ actorB.SetProperty(Actor::Property::WIDTH_RESIZE_POLICY, "FILL_TO_PARENT");
+ actorB.SetProperty(Actor::Property::HEIGHT_RESIZE_POLICY, "FILL_TO_PARENT");
+
+ actorC.SetProperty(Actor::Property::WIDTH_RESIZE_POLICY, "FILL_TO_PARENT");
+ actorC.SetProperty(Actor::Property::HEIGHT_RESIZE_POLICY, "FILL_TO_PARENT");
+
+ stage.Add(actorA);
+ stage.Add(actorB);
+ stage.Add(actorC);
+
+ application.GetScene().SetGeometryHittestEnabled(true);
+ ResetTouchCallbacks(application);
+
+ application.SendNotification();
application.Render();
+ DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled2, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION);
+
+ // connect to actor touch signals, will use touch callbacks to determine which actor is on top.
+ // Only top actor will get touched.
+ actorA.TouchedSignal().Connect(TestTouchCallback);
+ actorB.TouchedSignal().Connect(TestTouchCallback2);
+ actorC.TouchedSignal().Connect(TestTouchCallback3);
+
+ bool orderChangedSignal(false);
+ Actor orderChangedActor;
+ ChildOrderChangedFunctor f(orderChangedSignal, orderChangedActor);
+ DevelActor::ChildOrderChangedSignal(stage.GetRootLayer()).Connect(&application, f);
+
+ Dali::Integration::Point point;
+ point.SetDeviceId(1);
+ point.SetState(PointState::DOWN);
+ point.SetScreenPosition(Vector2(10.f, 10.f));
+ Dali::Integration::TouchEvent touchEvent;
+ touchEvent.AddPoint(point);
+
application.ProcessEvent(touchEvent);
- glSetUniformStack.Reset();
+ DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled2, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled3, true, TEST_LOCATION);
- application.Render();
- tet_printf("Trace:%s \n", glSetUniformStack.GetTraceString().c_str());
+ ResetTouchCallbacks(application);
- // Test order of uniforms in stack
- indexC = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "3.000000");
- indexB = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "2.000000");
- indexA = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "1.000000");
+ tet_printf("Raise actor B Above Actor C\n");
- DALI_TEST_EQUALS(indexA > indexC, true, TEST_LOCATION);
- DALI_TEST_EQUALS(indexB > indexA, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
+ int newOrder = actorC[DevelActor::Property::SIBLING_ORDER];
+ actorB[DevelActor::Property::SIBLING_ORDER] = newOrder;
+ DALI_TEST_EQUALS(orderChangedSignal, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(orderChangedActor, actorB, TEST_LOCATION);
+
+ // Ensure sorting happens at end of Core::ProcessEvents() before next touch
+ application.SendNotification();
+ application.ProcessEvent(touchEvent);
DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION);
DALI_TEST_EQUALS(gTouchCallBackCalled2, true, TEST_LOCATION);
DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION);
- ResetTouchCallbacks();
+ ResetTouchCallbacks(application);
- tet_printf("Lower actor B below Actor C leaving A on top\n");
+ tet_printf("Raise actor A Above Actor B\n");
orderChangedSignal = false;
DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
- actorB.LowerBelow(actorC);
+ newOrder = actorB[DevelActor::Property::SIBLING_ORDER];
+ actorA[DevelActor::Property::SIBLING_ORDER] = newOrder;
DALI_TEST_EQUALS(orderChangedSignal, true, TEST_LOCATION);
- DALI_TEST_EQUALS(orderChangedActor, actorB, TEST_LOCATION);
+ DALI_TEST_EQUALS(orderChangedActor, actorA, TEST_LOCATION);
// Ensure sorting happens at end of Core::ProcessEvents() before next touch
application.SendNotification();
- application.Render();
-
- application.ProcessEvent(touchEvent);
-
- glSetUniformStack.Reset();
- application.Render();
- tet_printf("Trace:%s \n", glSetUniformStack.GetTraceString().c_str());
+ application.ProcessEvent(touchEvent); // process a touch event on ordered actors.
- // Test order of uniforms in stack
- indexC = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "3.000000");
- indexB = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "2.000000");
- indexA = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "1.000000");
+ DALI_TEST_EQUALS(gTouchCallBackCalled, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled2, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION);
- DALI_TEST_EQUALS(indexC > indexB, true, TEST_LOCATION);
- DALI_TEST_EQUALS(indexA > indexC, true, TEST_LOCATION);
+ ResetTouchCallbacks(application);
END_TEST;
}
-int UtcDaliActorLowerBelow2(void)
+int UtcDaliActorLowerBelow(void)
{
- tet_infoline("UtcDaliActor LowerBelow test using SIBLING_ORDER property\n");
+ tet_infoline("UtcDaliActor LowerBelow test \n");
TestApplication application;
tet_printf("Lower actor C below Actor B ( actor B and A on same level due to insertion order) so C is below both \n");
DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
- actorC[DevelActor::Property::SIBLING_ORDER] = 1;
+ actorC.LowerBelow(actorB);
DALI_TEST_EQUALS(orderChangedSignal, true, TEST_LOCATION);
DALI_TEST_EQUALS(orderChangedActor, actorC, TEST_LOCATION);
orderChangedSignal = false;
DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
- actorC[DevelActor::Property::SIBLING_ORDER] = 0;
+ actorC.LowerBelow(actorA);
DALI_TEST_EQUALS(orderChangedSignal, true, TEST_LOCATION);
DALI_TEST_EQUALS(orderChangedActor, actorC, TEST_LOCATION);
orderChangedSignal = false;
DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
- actorB[DevelActor::Property::SIBLING_ORDER] = 0;
+ actorB.LowerBelow(actorC);
DALI_TEST_EQUALS(orderChangedSignal, true, TEST_LOCATION);
DALI_TEST_EQUALS(orderChangedActor, actorB, TEST_LOCATION);
END_TEST;
}
-int UtcDaliActorRaiseAboveDifferentParentsN(void)
+int UtcDaliActorGeoTouchLowerBelow(void)
{
- tet_infoline("UtcDaliActor RaiseToAbove test with actor and target actor having different parents \n");
+ tet_infoline("UtcDaliActor LowerBelow test \n");
TestApplication application;
Integration::Scene stage(application.GetScene());
- Actor parentA = Actor::New();
- Actor parentB = Actor::New();
- parentA.SetProperty(Actor::Property::WIDTH_RESIZE_POLICY, "FILL_TO_PARENT");
- parentA.SetProperty(Actor::Property::HEIGHT_RESIZE_POLICY, "FILL_TO_PARENT");
- parentB.SetProperty(Actor::Property::WIDTH_RESIZE_POLICY, "FILL_TO_PARENT");
- parentB.SetProperty(Actor::Property::HEIGHT_RESIZE_POLICY, "FILL_TO_PARENT");
+ // Set up renderers to add to Actors, float value 1, 2, 3 assigned to each
+ // enables checking of which actor the uniform is assigned too
+ Shader shaderA = CreateShader();
+ shaderA.RegisterProperty("uRendererColor", 1.f);
- parentA.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
- parentA.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+ Shader shaderB = CreateShader();
+ shaderB.RegisterProperty("uRendererColor", 2.f);
+
+ Shader shaderC = CreateShader();
+ shaderC.RegisterProperty("uRendererColor", 3.f);
+
+ Actor actorA = Actor::New();
+ Actor actorB = Actor::New();
+ Actor actorC = Actor::New();
+
+ // Add renderers to Actors so ( uRendererColor, 1 ) is A, ( uRendererColor, 2 ) is B, and ( uRendererColor, 3 ) is C,
+ Geometry geometry = CreateQuadGeometry();
+
+ Renderer rendererA = Renderer::New(geometry, shaderA);
+ actorA.AddRenderer(rendererA);
+
+ Renderer rendererB = Renderer::New(geometry, shaderB);
+ actorB.AddRenderer(rendererB);
+
+ Renderer rendererC = Renderer::New(geometry, shaderC);
+ actorC.AddRenderer(rendererC);
+
+ actorA.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ actorA.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+
+ actorB.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ actorB.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+
+ actorC.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ actorC.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+
+ actorA.SetProperty(Actor::Property::WIDTH_RESIZE_POLICY, "FILL_TO_PARENT");
+ actorA.SetProperty(Actor::Property::HEIGHT_RESIZE_POLICY, "FILL_TO_PARENT");
+
+ actorB.SetProperty(Actor::Property::WIDTH_RESIZE_POLICY, "FILL_TO_PARENT");
+ actorB.SetProperty(Actor::Property::HEIGHT_RESIZE_POLICY, "FILL_TO_PARENT");
+
+ actorC.SetProperty(Actor::Property::WIDTH_RESIZE_POLICY, "FILL_TO_PARENT");
+ actorC.SetProperty(Actor::Property::HEIGHT_RESIZE_POLICY, "FILL_TO_PARENT");
+
+ Actor container = Actor::New();
+ container.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+ container.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
+ stage.Add(container);
+
+ container.Add(actorA);
+ container.Add(actorB);
+ container.Add(actorC);
+
+ application.GetScene().SetGeometryHittestEnabled(true);
+ ResetTouchCallbacks(application);
+
+ // Connect ChildOrderChangedSignal
+ bool orderChangedSignal(false);
+ Actor orderChangedActor;
+ ChildOrderChangedFunctor f(orderChangedSignal, orderChangedActor);
+ DevelActor::ChildOrderChangedSignal(container).Connect(&application, f);
+
+ // Set up gl abstraction trace so can query the set uniform order
+ TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+ glAbstraction.EnableSetUniformCallTrace(true);
+ glAbstraction.ResetSetUniformCallStack();
+ TraceCallStack& glSetUniformStack = glAbstraction.GetSetUniformTrace();
+
+ glAbstraction.ResetSetUniformCallStack();
+
+ application.SendNotification();
+ application.Render();
+
+ tet_printf("Trace:%s \n", glSetUniformStack.GetTraceString().c_str());
+
+ // Test order of uniforms in stack
+ int indexC = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "3.000000");
+ int indexB = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "2.000000");
+ int indexA = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "1.000000");
+
+ tet_infoline("Testing C above B and A at bottom\n");
+ bool CBA = (indexC > indexB) && (indexB > indexA);
+
+ DALI_TEST_EQUALS(CBA, true, TEST_LOCATION);
+
+ DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled2, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION);
+
+ // connect to actor touch signals, will use touch callbacks to determine which actor is on top.
+ // Only top actor will get touched.
+ actorA.TouchedSignal().Connect(TestTouchCallback);
+ actorB.TouchedSignal().Connect(TestTouchCallback2);
+ actorC.TouchedSignal().Connect(TestTouchCallback3);
+
+ Dali::Integration::Point point;
+ point.SetDeviceId(1);
+ point.SetState(PointState::DOWN);
+ point.SetScreenPosition(Vector2(10.f, 10.f));
+ Dali::Integration::TouchEvent touchEvent;
+ touchEvent.AddPoint(point);
+
+ tet_infoline("UtcDaliActor Test Set up completed \n");
+
+ application.ProcessEvent(touchEvent);
+
+ DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled2, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled3, true, TEST_LOCATION);
+
+ ResetTouchCallbacks(application);
+
+ tet_printf("Lower actor C below Actor B ( actor B and A on same level due to insertion order) so C is below both \n");
+
+ DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
+ actorC.LowerBelow(actorB);
+ DALI_TEST_EQUALS(orderChangedSignal, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(orderChangedActor, actorC, TEST_LOCATION);
+
+ // Ensure sorting happens at end of Core::ProcessEvents() before next touch
+ application.SendNotification();
+ application.Render();
+
+ application.ProcessEvent(touchEvent); // touch event
+
+ glSetUniformStack.Reset();
+
+ application.SendNotification();
+ application.Render();
+
+ tet_printf("Trace:%s \n", glSetUniformStack.GetTraceString().c_str());
+
+ // Test order of uniforms in stack
+ indexC = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "3.000000");
+ indexB = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "2.000000");
+ indexA = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "1.000000");
+
+ tet_infoline("Testing render order is A, C, B");
+ DALI_TEST_EQUALS(indexC > indexA, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(indexB > indexC, true, TEST_LOCATION);
+
+ DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled2, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION);
+
+ ResetTouchCallbacks(application);
+
+ tet_printf("Lower actor C below Actor A leaving B on top\n");
+
+ orderChangedSignal = false;
+
+ DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
+ actorC.LowerBelow(actorA);
+ DALI_TEST_EQUALS(orderChangedSignal, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(orderChangedActor, actorC, TEST_LOCATION);
+
+ // Ensure sorting happens at end of Core::ProcessEvents() before next touch
+ application.SendNotification();
+ application.Render();
+
+ application.ProcessEvent(touchEvent);
+
+ glSetUniformStack.Reset();
+
+ application.Render();
+ tet_printf("Trace:%s \n", glSetUniformStack.GetTraceString().c_str());
+
+ // Test order of uniforms in stack
+ indexC = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "3.000000");
+ indexB = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "2.000000");
+ indexA = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "1.000000");
+
+ DALI_TEST_EQUALS(indexA > indexC, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(indexB > indexA, true, TEST_LOCATION);
+
+ DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled2, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION);
+
+ ResetTouchCallbacks(application);
+
+ tet_printf("Lower actor B below Actor C leaving A on top\n");
+
+ orderChangedSignal = false;
+
+ DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
+ actorB.LowerBelow(actorC);
+ DALI_TEST_EQUALS(orderChangedSignal, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(orderChangedActor, actorB, TEST_LOCATION);
+
+ // Ensure sorting happens at end of Core::ProcessEvents() before next touch
+ application.SendNotification();
+ application.Render();
+
+ application.ProcessEvent(touchEvent);
+
+ glSetUniformStack.Reset();
+
+ application.Render();
+ tet_printf("Trace:%s \n", glSetUniformStack.GetTraceString().c_str());
+
+ // Test order of uniforms in stack
+ indexC = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "3.000000");
+ indexB = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "2.000000");
+ indexA = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "1.000000");
+
+ DALI_TEST_EQUALS(indexC > indexB, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(indexA > indexC, true, TEST_LOCATION);
+
+ END_TEST;
+}
+
+int UtcDaliActorLowerBelow2(void)
+{
+ tet_infoline("UtcDaliActor LowerBelow test using SIBLING_ORDER property\n");
+
+ TestApplication application;
+
+ Integration::Scene stage(application.GetScene());
+
+ // Set up renderers to add to Actors, float value 1, 2, 3 assigned to each
+ // enables checking of which actor the uniform is assigned too
+ Shader shaderA = CreateShader();
+ shaderA.RegisterProperty("uRendererColor", 1.f);
+
+ Shader shaderB = CreateShader();
+ shaderB.RegisterProperty("uRendererColor", 2.f);
+
+ Shader shaderC = CreateShader();
+ shaderC.RegisterProperty("uRendererColor", 3.f);
+
+ Actor actorA = Actor::New();
+ Actor actorB = Actor::New();
+ Actor actorC = Actor::New();
+
+ // Add renderers to Actors so ( uRendererColor, 1 ) is A, ( uRendererColor, 2 ) is B, and ( uRendererColor, 3 ) is C,
+ Geometry geometry = CreateQuadGeometry();
+
+ Renderer rendererA = Renderer::New(geometry, shaderA);
+ actorA.AddRenderer(rendererA);
+
+ Renderer rendererB = Renderer::New(geometry, shaderB);
+ actorB.AddRenderer(rendererB);
+
+ Renderer rendererC = Renderer::New(geometry, shaderC);
+ actorC.AddRenderer(rendererC);
+
+ actorA.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ actorA.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+
+ actorB.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ actorB.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+
+ actorC.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ actorC.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+
+ actorA.SetProperty(Actor::Property::WIDTH_RESIZE_POLICY, "FILL_TO_PARENT");
+ actorA.SetProperty(Actor::Property::HEIGHT_RESIZE_POLICY, "FILL_TO_PARENT");
+
+ actorB.SetProperty(Actor::Property::WIDTH_RESIZE_POLICY, "FILL_TO_PARENT");
+ actorB.SetProperty(Actor::Property::HEIGHT_RESIZE_POLICY, "FILL_TO_PARENT");
+
+ actorC.SetProperty(Actor::Property::WIDTH_RESIZE_POLICY, "FILL_TO_PARENT");
+ actorC.SetProperty(Actor::Property::HEIGHT_RESIZE_POLICY, "FILL_TO_PARENT");
+
+ Actor container = Actor::New();
+ container.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+ container.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
+ stage.Add(container);
+
+ container.Add(actorA);
+ container.Add(actorB);
+ container.Add(actorC);
+
+ ResetTouchCallbacks();
+
+ // Connect ChildOrderChangedSignal
+ bool orderChangedSignal(false);
+ Actor orderChangedActor;
+ ChildOrderChangedFunctor f(orderChangedSignal, orderChangedActor);
+ DevelActor::ChildOrderChangedSignal(container).Connect(&application, f);
+
+ // Set up gl abstraction trace so can query the set uniform order
+ TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+ glAbstraction.EnableSetUniformCallTrace(true);
+ glAbstraction.ResetSetUniformCallStack();
+ TraceCallStack& glSetUniformStack = glAbstraction.GetSetUniformTrace();
+
+ glAbstraction.ResetSetUniformCallStack();
+
+ application.SendNotification();
+ application.Render();
+
+ tet_printf("Trace:%s \n", glSetUniformStack.GetTraceString().c_str());
+
+ // Test order of uniforms in stack
+ int indexC = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "3.000000");
+ int indexB = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "2.000000");
+ int indexA = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "1.000000");
+
+ tet_infoline("Testing C above B and A at bottom\n");
+ bool CBA = (indexC > indexB) && (indexB > indexA);
+
+ DALI_TEST_EQUALS(CBA, true, TEST_LOCATION);
+
+ DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled2, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION);
+
+ // connect to actor touch signals, will use touch callbacks to determine which actor is on top.
+ // Only top actor will get touched.
+ actorA.TouchedSignal().Connect(TestTouchCallback);
+ actorB.TouchedSignal().Connect(TestTouchCallback2);
+ actorC.TouchedSignal().Connect(TestTouchCallback3);
+
+ Dali::Integration::Point point;
+ point.SetDeviceId(1);
+ point.SetState(PointState::DOWN);
+ point.SetScreenPosition(Vector2(10.f, 10.f));
+ Dali::Integration::TouchEvent touchEvent;
+ touchEvent.AddPoint(point);
+
+ tet_infoline("UtcDaliActor Test Set up completed \n");
+
+ application.ProcessEvent(touchEvent);
+
+ DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled2, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled3, true, TEST_LOCATION);
+
+ ResetTouchCallbacks();
+
+ tet_printf("Lower actor C below Actor B ( actor B and A on same level due to insertion order) so C is below both \n");
+
+ DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
+ actorC[DevelActor::Property::SIBLING_ORDER] = 1;
+ DALI_TEST_EQUALS(orderChangedSignal, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(orderChangedActor, actorC, TEST_LOCATION);
+
+ // Ensure sorting happens at end of Core::ProcessEvents() before next touch
+ application.SendNotification();
+ application.Render();
+
+ application.ProcessEvent(touchEvent); // touch event
+
+ glSetUniformStack.Reset();
+
+ application.SendNotification();
+ application.Render();
+
+ tet_printf("Trace:%s \n", glSetUniformStack.GetTraceString().c_str());
+
+ // Test order of uniforms in stack
+ indexC = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "3.000000");
+ indexB = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "2.000000");
+ indexA = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "1.000000");
+
+ tet_infoline("Testing render order is A, C, B");
+ DALI_TEST_EQUALS(indexC > indexA, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(indexB > indexC, true, TEST_LOCATION);
+
+ DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled2, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION);
+
+ ResetTouchCallbacks();
+
+ tet_printf("Lower actor C below Actor A leaving B on top\n");
+
+ orderChangedSignal = false;
+
+ DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
+ actorC[DevelActor::Property::SIBLING_ORDER] = 0;
+ DALI_TEST_EQUALS(orderChangedSignal, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(orderChangedActor, actorC, TEST_LOCATION);
+
+ // Ensure sorting happens at end of Core::ProcessEvents() before next touch
+ application.SendNotification();
+ application.Render();
+
+ application.ProcessEvent(touchEvent);
+
+ glSetUniformStack.Reset();
+
+ application.Render();
+ tet_printf("Trace:%s \n", glSetUniformStack.GetTraceString().c_str());
+
+ // Test order of uniforms in stack
+ indexC = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "3.000000");
+ indexB = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "2.000000");
+ indexA = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "1.000000");
+
+ DALI_TEST_EQUALS(indexA > indexC, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(indexB > indexA, true, TEST_LOCATION);
+
+ DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled2, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION);
+
+ ResetTouchCallbacks();
+
+ tet_printf("Lower actor B below Actor C leaving A on top\n");
+
+ orderChangedSignal = false;
+
+ DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
+ actorB[DevelActor::Property::SIBLING_ORDER] = 0;
+ DALI_TEST_EQUALS(orderChangedSignal, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(orderChangedActor, actorB, TEST_LOCATION);
+
+ // Ensure sorting happens at end of Core::ProcessEvents() before next touch
+ application.SendNotification();
+ application.Render();
+
+ application.ProcessEvent(touchEvent);
+
+ glSetUniformStack.Reset();
+
+ application.Render();
+ tet_printf("Trace:%s \n", glSetUniformStack.GetTraceString().c_str());
+
+ // Test order of uniforms in stack
+ indexC = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "3.000000");
+ indexB = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "2.000000");
+ indexA = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "1.000000");
+
+ DALI_TEST_EQUALS(indexC > indexB, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(indexA > indexC, true, TEST_LOCATION);
+
+ END_TEST;
+}
+
+int UtcDaliActorGeoTouchLowerBelow2(void)
+{
+ tet_infoline("UtcDaliActor LowerBelow test using SIBLING_ORDER property\n");
+
+ TestApplication application;
+
+ Integration::Scene stage(application.GetScene());
+
+ // Set up renderers to add to Actors, float value 1, 2, 3 assigned to each
+ // enables checking of which actor the uniform is assigned too
+ Shader shaderA = CreateShader();
+ shaderA.RegisterProperty("uRendererColor", 1.f);
+
+ Shader shaderB = CreateShader();
+ shaderB.RegisterProperty("uRendererColor", 2.f);
+
+ Shader shaderC = CreateShader();
+ shaderC.RegisterProperty("uRendererColor", 3.f);
+
+ Actor actorA = Actor::New();
+ Actor actorB = Actor::New();
+ Actor actorC = Actor::New();
+
+ // Add renderers to Actors so ( uRendererColor, 1 ) is A, ( uRendererColor, 2 ) is B, and ( uRendererColor, 3 ) is C,
+ Geometry geometry = CreateQuadGeometry();
+
+ Renderer rendererA = Renderer::New(geometry, shaderA);
+ actorA.AddRenderer(rendererA);
+
+ Renderer rendererB = Renderer::New(geometry, shaderB);
+ actorB.AddRenderer(rendererB);
+
+ Renderer rendererC = Renderer::New(geometry, shaderC);
+ actorC.AddRenderer(rendererC);
+
+ actorA.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ actorA.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+
+ actorB.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ actorB.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+
+ actorC.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ actorC.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+
+ actorA.SetProperty(Actor::Property::WIDTH_RESIZE_POLICY, "FILL_TO_PARENT");
+ actorA.SetProperty(Actor::Property::HEIGHT_RESIZE_POLICY, "FILL_TO_PARENT");
+
+ actorB.SetProperty(Actor::Property::WIDTH_RESIZE_POLICY, "FILL_TO_PARENT");
+ actorB.SetProperty(Actor::Property::HEIGHT_RESIZE_POLICY, "FILL_TO_PARENT");
+
+ actorC.SetProperty(Actor::Property::WIDTH_RESIZE_POLICY, "FILL_TO_PARENT");
+ actorC.SetProperty(Actor::Property::HEIGHT_RESIZE_POLICY, "FILL_TO_PARENT");
+
+ Actor container = Actor::New();
+ container.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+ container.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
+ stage.Add(container);
+
+ container.Add(actorA);
+ container.Add(actorB);
+ container.Add(actorC);
+
+ application.GetScene().SetGeometryHittestEnabled(true);
+ ResetTouchCallbacks(application);
+
+ // Connect ChildOrderChangedSignal
+ bool orderChangedSignal(false);
+ Actor orderChangedActor;
+ ChildOrderChangedFunctor f(orderChangedSignal, orderChangedActor);
+ DevelActor::ChildOrderChangedSignal(container).Connect(&application, f);
+
+ // Set up gl abstraction trace so can query the set uniform order
+ TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+ glAbstraction.EnableSetUniformCallTrace(true);
+ glAbstraction.ResetSetUniformCallStack();
+ TraceCallStack& glSetUniformStack = glAbstraction.GetSetUniformTrace();
+
+ glAbstraction.ResetSetUniformCallStack();
+
+ application.SendNotification();
+ application.Render();
+
+ tet_printf("Trace:%s \n", glSetUniformStack.GetTraceString().c_str());
+
+ // Test order of uniforms in stack
+ int indexC = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "3.000000");
+ int indexB = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "2.000000");
+ int indexA = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "1.000000");
+
+ tet_infoline("Testing C above B and A at bottom\n");
+ bool CBA = (indexC > indexB) && (indexB > indexA);
+
+ DALI_TEST_EQUALS(CBA, true, TEST_LOCATION);
+
+ DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled2, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION);
+
+ // connect to actor touch signals, will use touch callbacks to determine which actor is on top.
+ // Only top actor will get touched.
+ actorA.TouchedSignal().Connect(TestTouchCallback);
+ actorB.TouchedSignal().Connect(TestTouchCallback2);
+ actorC.TouchedSignal().Connect(TestTouchCallback3);
+
+ Dali::Integration::Point point;
+ point.SetDeviceId(1);
+ point.SetState(PointState::DOWN);
+ point.SetScreenPosition(Vector2(10.f, 10.f));
+ Dali::Integration::TouchEvent touchEvent;
+ touchEvent.AddPoint(point);
+
+ tet_infoline("UtcDaliActor Test Set up completed \n");
+
+ application.ProcessEvent(touchEvent);
+
+ DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled2, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled3, true, TEST_LOCATION);
+
+ ResetTouchCallbacks(application);
+
+ tet_printf("Lower actor C below Actor B ( actor B and A on same level due to insertion order) so C is below both \n");
+
+ DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
+ actorC[DevelActor::Property::SIBLING_ORDER] = 1;
+ DALI_TEST_EQUALS(orderChangedSignal, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(orderChangedActor, actorC, TEST_LOCATION);
+
+ // Ensure sorting happens at end of Core::ProcessEvents() before next touch
+ application.SendNotification();
+ application.Render();
+
+ application.ProcessEvent(touchEvent); // touch event
+
+ glSetUniformStack.Reset();
+
+ application.SendNotification();
+ application.Render();
+
+ tet_printf("Trace:%s \n", glSetUniformStack.GetTraceString().c_str());
+
+ // Test order of uniforms in stack
+ indexC = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "3.000000");
+ indexB = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "2.000000");
+ indexA = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "1.000000");
+
+ tet_infoline("Testing render order is A, C, B");
+ DALI_TEST_EQUALS(indexC > indexA, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(indexB > indexC, true, TEST_LOCATION);
+
+ DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled2, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION);
+
+ ResetTouchCallbacks(application);
+
+ tet_printf("Lower actor C below Actor A leaving B on top\n");
+
+ orderChangedSignal = false;
+
+ DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
+ actorC[DevelActor::Property::SIBLING_ORDER] = 0;
+ DALI_TEST_EQUALS(orderChangedSignal, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(orderChangedActor, actorC, TEST_LOCATION);
+
+ // Ensure sorting happens at end of Core::ProcessEvents() before next touch
+ application.SendNotification();
+ application.Render();
+
+ application.ProcessEvent(touchEvent);
+
+ glSetUniformStack.Reset();
+
+ application.Render();
+ tet_printf("Trace:%s \n", glSetUniformStack.GetTraceString().c_str());
+
+ // Test order of uniforms in stack
+ indexC = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "3.000000");
+ indexB = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "2.000000");
+ indexA = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "1.000000");
+
+ DALI_TEST_EQUALS(indexA > indexC, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(indexB > indexA, true, TEST_LOCATION);
+
+ DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled2, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION);
+
+ ResetTouchCallbacks(application);
+
+ tet_printf("Lower actor B below Actor C leaving A on top\n");
+
+ orderChangedSignal = false;
+
+ DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
+ actorB[DevelActor::Property::SIBLING_ORDER] = 0;
+ DALI_TEST_EQUALS(orderChangedSignal, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(orderChangedActor, actorB, TEST_LOCATION);
+
+ // Ensure sorting happens at end of Core::ProcessEvents() before next touch
+ application.SendNotification();
+ application.Render();
+
+ application.ProcessEvent(touchEvent);
+
+ glSetUniformStack.Reset();
+
+ application.Render();
+ tet_printf("Trace:%s \n", glSetUniformStack.GetTraceString().c_str());
+
+ // Test order of uniforms in stack
+ indexC = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "3.000000");
+ indexB = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "2.000000");
+ indexA = glSetUniformStack.FindIndexFromMethodAndParams("uRendererColor", "1.000000");
+
+ DALI_TEST_EQUALS(indexC > indexB, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(indexA > indexC, true, TEST_LOCATION);
+
+ END_TEST;
+}
+
+int UtcDaliActorRaiseAboveDifferentParentsN(void)
+{
+ tet_infoline("UtcDaliActor RaiseToAbove test with actor and target actor having different parents \n");
+
+ TestApplication application;
+
+ Integration::Scene stage(application.GetScene());
+
+ Actor parentA = Actor::New();
+ Actor parentB = Actor::New();
+ parentA.SetProperty(Actor::Property::WIDTH_RESIZE_POLICY, "FILL_TO_PARENT");
+ parentA.SetProperty(Actor::Property::HEIGHT_RESIZE_POLICY, "FILL_TO_PARENT");
+ parentB.SetProperty(Actor::Property::WIDTH_RESIZE_POLICY, "FILL_TO_PARENT");
+ parentB.SetProperty(Actor::Property::HEIGHT_RESIZE_POLICY, "FILL_TO_PARENT");
+
+ parentA.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ parentA.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+
+ parentB.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ parentB.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+
+ stage.Add(parentA);
+ stage.Add(parentB);
+
+ Actor actorA = Actor::New();
+ Actor actorB = Actor::New();
+ Actor actorC = Actor::New();
+
+ parentA.Add(actorA);
+ parentA.Add(actorB);
+
+ tet_printf("Actor C added to different parent from A and B \n");
+ parentB.Add(actorC);
+
+ actorA.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ actorA.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+
+ actorB.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ actorB.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+
+ actorC.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ actorC.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+
+ actorA.SetProperty(Actor::Property::WIDTH_RESIZE_POLICY, "FILL_TO_PARENT");
+ actorA.SetProperty(Actor::Property::HEIGHT_RESIZE_POLICY, "FILL_TO_PARENT");
+
+ actorB.SetProperty(Actor::Property::WIDTH_RESIZE_POLICY, "FILL_TO_PARENT");
+ actorB.SetProperty(Actor::Property::HEIGHT_RESIZE_POLICY, "FILL_TO_PARENT");
+
+ actorC.SetProperty(Actor::Property::WIDTH_RESIZE_POLICY, "FILL_TO_PARENT");
+ actorC.SetProperty(Actor::Property::HEIGHT_RESIZE_POLICY, "FILL_TO_PARENT");
+
+ ResetTouchCallbacks();
+
+ // Connect ChildOrderChangedSignal
+ bool orderChangedSignal(false);
+ Actor orderChangedActor;
+ ChildOrderChangedFunctor f(orderChangedSignal, orderChangedActor);
+ DevelActor::ChildOrderChangedSignal(stage.GetRootLayer()).Connect(&application, f);
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled2, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION);
+
+ // connect to actor touch signals, will use touch callbacks to determine which actor is on top.
+ // Only top actor will get touched.
+ actorA.TouchedSignal().Connect(TestTouchCallback);
+ actorB.TouchedSignal().Connect(TestTouchCallback2);
+ actorC.TouchedSignal().Connect(TestTouchCallback3);
+
+ Dali::Integration::Point point;
+ point.SetDeviceId(1);
+ point.SetState(PointState::DOWN);
+ point.SetScreenPosition(Vector2(10.f, 10.f));
+ Dali::Integration::TouchEvent touchEvent;
+ touchEvent.AddPoint(point);
+
+ application.ProcessEvent(touchEvent);
+
+ DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled2, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled3, true, TEST_LOCATION);
+
+ ResetTouchCallbacks();
+
+ tet_printf("Raise actor A Above Actor C which have different parents\n");
+
+ DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
+ actorA.RaiseAbove(actorC);
+ DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
+
+ // Ensure sorting happens at end of Core::ProcessEvents() before next touch
+ application.SendNotification();
+
+ application.ProcessEvent(touchEvent); // touch event
+
+ DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled2, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled3, true, TEST_LOCATION);
+
+ ResetTouchCallbacks();
+
+ END_TEST;
+}
+
+int UtcDaliActorGeoTouchRaiseAboveDifferentParentsN(void)
+{
+ tet_infoline("UtcDaliActor RaiseToAbove test with actor and target actor having different parents \n");
+
+ TestApplication application;
+
+ Integration::Scene stage(application.GetScene());
+
+ Actor parentA = Actor::New();
+ Actor parentB = Actor::New();
+ parentA.SetProperty(Actor::Property::WIDTH_RESIZE_POLICY, "FILL_TO_PARENT");
+ parentA.SetProperty(Actor::Property::HEIGHT_RESIZE_POLICY, "FILL_TO_PARENT");
+ parentB.SetProperty(Actor::Property::WIDTH_RESIZE_POLICY, "FILL_TO_PARENT");
+ parentB.SetProperty(Actor::Property::HEIGHT_RESIZE_POLICY, "FILL_TO_PARENT");
+
+ parentA.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ parentA.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+
+ parentB.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ parentB.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+
+ stage.Add(parentA);
+ stage.Add(parentB);
+
+ Actor actorA = Actor::New();
+ Actor actorB = Actor::New();
+ Actor actorC = Actor::New();
+
+ parentA.Add(actorA);
+ parentA.Add(actorB);
+
+ tet_printf("Actor C added to different parent from A and B \n");
+ parentB.Add(actorC);
+
+ actorA.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ actorA.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+
+ actorB.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ actorB.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+
+ actorC.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ actorC.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+
+ actorA.SetProperty(Actor::Property::WIDTH_RESIZE_POLICY, "FILL_TO_PARENT");
+ actorA.SetProperty(Actor::Property::HEIGHT_RESIZE_POLICY, "FILL_TO_PARENT");
+
+ actorB.SetProperty(Actor::Property::WIDTH_RESIZE_POLICY, "FILL_TO_PARENT");
+ actorB.SetProperty(Actor::Property::HEIGHT_RESIZE_POLICY, "FILL_TO_PARENT");
+
+ actorC.SetProperty(Actor::Property::WIDTH_RESIZE_POLICY, "FILL_TO_PARENT");
+ actorC.SetProperty(Actor::Property::HEIGHT_RESIZE_POLICY, "FILL_TO_PARENT");
+
+ application.GetScene().SetGeometryHittestEnabled(true);
+ ResetTouchCallbacks(application);
+
+ // Connect ChildOrderChangedSignal
+ bool orderChangedSignal(false);
+ Actor orderChangedActor;
+ ChildOrderChangedFunctor f(orderChangedSignal, orderChangedActor);
+ DevelActor::ChildOrderChangedSignal(stage.GetRootLayer()).Connect(&application, f);
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled2, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION);
+
+ // connect to actor touch signals, will use touch callbacks to determine which actor is on top.
+ // Only top actor will get touched.
+ actorA.TouchedSignal().Connect(TestTouchCallback);
+ actorB.TouchedSignal().Connect(TestTouchCallback2);
+ actorC.TouchedSignal().Connect(TestTouchCallback3);
+
+ Dali::Integration::Point point;
+ point.SetDeviceId(1);
+ point.SetState(PointState::DOWN);
+ point.SetScreenPosition(Vector2(10.f, 10.f));
+ Dali::Integration::TouchEvent touchEvent;
+ touchEvent.AddPoint(point);
+
+ application.ProcessEvent(touchEvent);
+
+ DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled2, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled3, true, TEST_LOCATION);
+
+ ResetTouchCallbacks(application);
+
+ tet_printf("Raise actor A Above Actor C which have different parents\n");
+
+ DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
+ actorA.RaiseAbove(actorC);
+ DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
+
+ // Ensure sorting happens at end of Core::ProcessEvents() before next touch
+ application.SendNotification();
+
+ application.ProcessEvent(touchEvent); // touch event
+
+ DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled2, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled3, true, TEST_LOCATION);
- parentB.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
- parentB.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+ ResetTouchCallbacks(application);
- stage.Add(parentA);
- stage.Add(parentB);
+ END_TEST;
+}
+
+int UtcDaliActorRaiseLowerWhenUnparentedTargetN(void)
+{
+ tet_infoline("UtcDaliActor Test raiseAbove and lowerBelow api when target Actor has no parent \n");
+
+ TestApplication application;
+
+ Integration::Scene stage(application.GetScene());
Actor actorA = Actor::New();
Actor actorB = Actor::New();
Actor actorC = Actor::New();
- parentA.Add(actorA);
- parentA.Add(actorB);
+ actorA.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ actorA.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
- tet_printf("Actor C added to different parent from A and B \n");
- parentB.Add(actorC);
+ actorB.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ actorB.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+
+ actorC.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ actorC.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+
+ actorA.SetProperty(Actor::Property::WIDTH_RESIZE_POLICY, "FILL_TO_PARENT");
+ actorA.SetProperty(Actor::Property::HEIGHT_RESIZE_POLICY, "FILL_TO_PARENT");
+
+ actorB.SetProperty(Actor::Property::WIDTH_RESIZE_POLICY, "FILL_TO_PARENT");
+ actorB.SetProperty(Actor::Property::HEIGHT_RESIZE_POLICY, "FILL_TO_PARENT");
+
+ actorC.SetProperty(Actor::Property::WIDTH_RESIZE_POLICY, "FILL_TO_PARENT");
+ actorC.SetProperty(Actor::Property::HEIGHT_RESIZE_POLICY, "FILL_TO_PARENT");
+
+ ResetTouchCallbacks();
+
+ // Connect ChildOrderChangedSignal
+ bool orderChangedSignal(false);
+ Actor orderChangedActor;
+ ChildOrderChangedFunctor f(orderChangedSignal, orderChangedActor);
+ DevelActor::ChildOrderChangedSignal(stage.GetRootLayer()).Connect(&application, f);
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled2, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION);
+
+ // connect to actor touch signals, will use touch callbacks to determine which actor is on top.
+ // Only top actor will get touched.
+ actorA.TouchedSignal().Connect(TestTouchCallback);
+ actorB.TouchedSignal().Connect(TestTouchCallback2);
+ actorC.TouchedSignal().Connect(TestTouchCallback3);
+
+ Dali::Integration::Point point;
+ point.SetDeviceId(1);
+ point.SetState(PointState::DOWN);
+ point.SetScreenPosition(Vector2(10.f, 10.f));
+ Dali::Integration::TouchEvent touchEvent;
+ touchEvent.AddPoint(point);
+
+ tet_printf("Raise actor A Above Actor C which have no parents\n");
+
+ DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
+ actorA.RaiseAbove(actorC);
+ DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
+
+ // Ensure sorting happens at end of Core::ProcessEvents() before next touch
+ application.SendNotification();
+
+ application.ProcessEvent(touchEvent);
+
+ tet_printf("Not parented so RaiseAbove should show no effect\n");
+
+ DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled2, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION);
+
+ ResetTouchCallbacks();
+
+ orderChangedSignal = false;
+
+ stage.Add(actorB);
+ tet_printf("Lower actor A below Actor C when only A is not on stage \n");
+
+ DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
+ actorA.LowerBelow(actorC);
+ DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
+
+ // Ensure sorting happens at end of Core::ProcessEvents() before next touch
+ application.SendNotification();
+ application.Render();
+
+ application.ProcessEvent(touchEvent);
+
+ tet_printf("Actor A not parented so LowerBelow should show no effect\n");
+ DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled2, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION);
+
+ ResetTouchCallbacks();
+
+ orderChangedSignal = false;
+
+ tet_printf("Adding Actor A to stage, will be on top\n");
+
+ stage.Add(actorA);
+ application.SendNotification();
+ application.Render();
+
+ tet_printf("Raise actor B Above Actor C when only B has a parent\n");
+
+ DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
+ actorB.RaiseAbove(actorC);
+ DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
+
+ // Ensure sorting happens at end of Core::ProcessEvents() before next touch
+ application.SendNotification();
+
+ application.ProcessEvent(touchEvent);
+
+ tet_printf("C not parented so RaiseAbove should show no effect\n");
+ DALI_TEST_EQUALS(gTouchCallBackCalled, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled2, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION);
+
+ ResetTouchCallbacks();
+
+ orderChangedSignal = false;
+
+ tet_printf("Lower actor A below Actor C when only A has a parent\n");
+
+ DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
+ actorA.LowerBelow(actorC);
+ DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
+
+ // Ensure sorting happens at end of Core::ProcessEvents() before next touch
+ application.SendNotification();
+
+ application.ProcessEvent(touchEvent);
+
+ tet_printf("C not parented so LowerBelow should show no effect\n");
+ DALI_TEST_EQUALS(gTouchCallBackCalled, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled2, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION);
+
+ ResetTouchCallbacks();
+
+ orderChangedSignal = false;
+
+ stage.Add(actorC);
+
+ DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
+ actorA.RaiseAbove(actorC);
+ DALI_TEST_EQUALS(orderChangedSignal, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(orderChangedActor, actorA, TEST_LOCATION);
+
+ // Ensure sorting happens at end of Core::ProcessEvents() before next touch
+ application.SendNotification();
+ application.Render();
+
+ application.ProcessEvent(touchEvent);
+
+ tet_printf("Raise actor A Above Actor C, now both have same parent \n");
+ DALI_TEST_EQUALS(gTouchCallBackCalled, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled2, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION);
+
+ END_TEST;
+}
+
+int UtcDaliActorGeoTouchRaiseLowerWhenUnparentedTargetN(void)
+{
+ tet_infoline("UtcDaliActor Test raiseAbove and lowerBelow api when target Actor has no parent \n");
+
+ TestApplication application;
+
+ Integration::Scene stage(application.GetScene());
+
+ Actor actorA = Actor::New();
+ Actor actorB = Actor::New();
+ Actor actorC = Actor::New();
actorA.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
actorA.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
actorC.SetProperty(Actor::Property::WIDTH_RESIZE_POLICY, "FILL_TO_PARENT");
actorC.SetProperty(Actor::Property::HEIGHT_RESIZE_POLICY, "FILL_TO_PARENT");
- ResetTouchCallbacks();
+ application.GetScene().SetGeometryHittestEnabled(true);
+ ResetTouchCallbacks(application);
+
+ // Connect ChildOrderChangedSignal
+ bool orderChangedSignal(false);
+ Actor orderChangedActor;
+ ChildOrderChangedFunctor f(orderChangedSignal, orderChangedActor);
+ DevelActor::ChildOrderChangedSignal(stage.GetRootLayer()).Connect(&application, f);
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled2, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION);
+
+ // connect to actor touch signals, will use touch callbacks to determine which actor is on top.
+ // Only top actor will get touched.
+ actorA.TouchedSignal().Connect(TestTouchCallback);
+ actorB.TouchedSignal().Connect(TestTouchCallback2);
+ actorC.TouchedSignal().Connect(TestTouchCallback3);
+
+ Dali::Integration::Point point;
+ point.SetDeviceId(1);
+ point.SetState(PointState::DOWN);
+ point.SetScreenPosition(Vector2(10.f, 10.f));
+ Dali::Integration::TouchEvent touchEvent;
+ touchEvent.AddPoint(point);
+
+ tet_printf("Raise actor A Above Actor C which have no parents\n");
+
+ DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
+ actorA.RaiseAbove(actorC);
+ DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
+
+ // Ensure sorting happens at end of Core::ProcessEvents() before next touch
+ application.SendNotification();
+
+ application.ProcessEvent(touchEvent);
+
+ tet_printf("Not parented so RaiseAbove should show no effect\n");
+
+ DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled2, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION);
+
+ ResetTouchCallbacks(application);
+
+ orderChangedSignal = false;
+
+ stage.Add(actorB);
+ tet_printf("Lower actor A below Actor C when only A is not on stage \n");
+
+ DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
+ actorA.LowerBelow(actorC);
+ DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
+
+ // Ensure sorting happens at end of Core::ProcessEvents() before next touch
+ application.SendNotification();
+ application.Render();
+
+ application.ProcessEvent(touchEvent);
+
+ tet_printf("Actor A not parented so LowerBelow should show no effect\n");
+ DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled2, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION);
+
+ ResetTouchCallbacks(application);
+
+ orderChangedSignal = false;
+
+ tet_printf("Adding Actor A to stage, will be on top\n");
+
+ stage.Add(actorA);
+ application.SendNotification();
+ application.Render();
+
+ tet_printf("Raise actor B Above Actor C when only B has a parent\n");
- // Connect ChildOrderChangedSignal
- bool orderChangedSignal(false);
- Actor orderChangedActor;
- ChildOrderChangedFunctor f(orderChangedSignal, orderChangedActor);
- DevelActor::ChildOrderChangedSignal(stage.GetRootLayer()).Connect(&application, f);
+ DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
+ actorB.RaiseAbove(actorC);
+ DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
+ // Ensure sorting happens at end of Core::ProcessEvents() before next touch
application.SendNotification();
- application.Render();
- DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION);
+ application.ProcessEvent(touchEvent);
+
+ tet_printf("C not parented so RaiseAbove should show no effect\n");
+ DALI_TEST_EQUALS(gTouchCallBackCalled, true, TEST_LOCATION);
DALI_TEST_EQUALS(gTouchCallBackCalled2, false, TEST_LOCATION);
DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION);
- // connect to actor touch signals, will use touch callbacks to determine which actor is on top.
- // Only top actor will get touched.
- actorA.TouchedSignal().Connect(TestTouchCallback);
- actorB.TouchedSignal().Connect(TestTouchCallback2);
- actorC.TouchedSignal().Connect(TestTouchCallback3);
+ ResetTouchCallbacks(application);
- Dali::Integration::Point point;
- point.SetDeviceId(1);
- point.SetState(PointState::DOWN);
- point.SetScreenPosition(Vector2(10.f, 10.f));
- Dali::Integration::TouchEvent touchEvent;
- touchEvent.AddPoint(point);
+ orderChangedSignal = false;
+
+ tet_printf("Lower actor A below Actor C when only A has a parent\n");
+
+ DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
+ actorA.LowerBelow(actorC);
+ DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
+
+ // Ensure sorting happens at end of Core::ProcessEvents() before next touch
+ application.SendNotification();
application.ProcessEvent(touchEvent);
- DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION);
+ tet_printf("C not parented so LowerBelow should show no effect\n");
+ DALI_TEST_EQUALS(gTouchCallBackCalled, true, TEST_LOCATION);
DALI_TEST_EQUALS(gTouchCallBackCalled2, false, TEST_LOCATION);
- DALI_TEST_EQUALS(gTouchCallBackCalled3, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION);
- ResetTouchCallbacks();
+ ResetTouchCallbacks(application);
- tet_printf("Raise actor A Above Actor C which have different parents\n");
+ orderChangedSignal = false;
+
+ stage.Add(actorC);
DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
actorA.RaiseAbove(actorC);
- DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(orderChangedSignal, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(orderChangedActor, actorA, TEST_LOCATION);
// Ensure sorting happens at end of Core::ProcessEvents() before next touch
application.SendNotification();
+ application.Render();
- application.ProcessEvent(touchEvent); // touch event
+ application.ProcessEvent(touchEvent);
- DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION);
+ tet_printf("Raise actor A Above Actor C, now both have same parent \n");
+ DALI_TEST_EQUALS(gTouchCallBackCalled, true, TEST_LOCATION);
DALI_TEST_EQUALS(gTouchCallBackCalled2, false, TEST_LOCATION);
- DALI_TEST_EQUALS(gTouchCallBackCalled3, true, TEST_LOCATION);
-
- ResetTouchCallbacks();
+ DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION);
END_TEST;
}
-int UtcDaliActorRaiseLowerWhenUnparentedTargetN(void)
+int UtcDaliActorTestAllAPIwhenActorNotParented(void)
{
- tet_infoline("UtcDaliActor Test raiseAbove and lowerBelow api when target Actor has no parent \n");
+ tet_infoline("UtcDaliActor Test all raise/lower api when actor has no parent \n");
TestApplication application;
ChildOrderChangedFunctor f(orderChangedSignal, orderChangedActor);
DevelActor::ChildOrderChangedSignal(stage.GetRootLayer()).Connect(&application, f);
- application.SendNotification();
- application.Render();
-
- DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION);
- DALI_TEST_EQUALS(gTouchCallBackCalled2, false, TEST_LOCATION);
- DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION);
-
// connect to actor touch signals, will use touch callbacks to determine which actor is on top.
// Only top actor will get touched.
actorA.TouchedSignal().Connect(TestTouchCallback);
Dali::Integration::TouchEvent touchEvent;
touchEvent.AddPoint(point);
- tet_printf("Raise actor A Above Actor C which have no parents\n");
+ stage.Add(actorA);
+ tet_printf("Raise actor B Above Actor C but B not parented\n");
DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
- actorA.RaiseAbove(actorC);
+ actorB.Raise();
DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
- // Ensure sorting happens at end of Core::ProcessEvents() before next touch
application.SendNotification();
+ application.Render();
application.ProcessEvent(touchEvent);
tet_printf("Not parented so RaiseAbove should show no effect\n");
- DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled, true, TEST_LOCATION);
DALI_TEST_EQUALS(gTouchCallBackCalled2, false, TEST_LOCATION);
DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION);
+ tet_printf("Raise actor B Above Actor C but B not parented\n");
ResetTouchCallbacks();
orderChangedSignal = false;
- stage.Add(actorB);
- tet_printf("Lower actor A below Actor C when only A is not on stage \n");
-
DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
- actorA.LowerBelow(actorC);
+ actorC.Lower();
DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
- // Ensure sorting happens at end of Core::ProcessEvents() before next touch
+ // Sort actor tree before next touch event
application.SendNotification();
application.Render();
application.ProcessEvent(touchEvent);
- tet_printf("Actor A not parented so LowerBelow should show no effect\n");
- DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION);
- DALI_TEST_EQUALS(gTouchCallBackCalled2, true, TEST_LOCATION);
- DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION);
+ tet_printf("Not parented so RaiseAbove should show no effect\n");
+ DALI_TEST_EQUALS(gTouchCallBackCalled, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled2, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION);
ResetTouchCallbacks();
orderChangedSignal = false;
- tet_printf("Adding Actor A to stage, will be on top\n");
-
- stage.Add(actorA);
- application.SendNotification();
- application.Render();
-
- tet_printf("Raise actor B Above Actor C when only B has a parent\n");
+ tet_printf("Lower actor C below B but C not parented\n");
DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
- actorB.RaiseAbove(actorC);
+ actorB.Lower();
DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
- // Ensure sorting happens at end of Core::ProcessEvents() before next touch
+ // Sort actor tree before next touch event
application.SendNotification();
+ application.Render();
application.ProcessEvent(touchEvent);
- tet_printf("C not parented so RaiseAbove should show no effect\n");
+ tet_printf("Not parented so Lower should show no effect\n");
+
DALI_TEST_EQUALS(gTouchCallBackCalled, true, TEST_LOCATION);
DALI_TEST_EQUALS(gTouchCallBackCalled2, false, TEST_LOCATION);
DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION);
-
ResetTouchCallbacks();
orderChangedSignal = false;
- tet_printf("Lower actor A below Actor C when only A has a parent\n");
+ tet_printf("Raise actor B to top\n");
DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
- actorA.LowerBelow(actorC);
+ actorB.RaiseToTop();
DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
- // Ensure sorting happens at end of Core::ProcessEvents() before next touch
+ // Sort actor tree before next touch event
application.SendNotification();
+ application.Render();
application.ProcessEvent(touchEvent);
- tet_printf("C not parented so LowerBelow should show no effect\n");
+ tet_printf("Not parented so RaiseToTop should show no effect\n");
+
DALI_TEST_EQUALS(gTouchCallBackCalled, true, TEST_LOCATION);
DALI_TEST_EQUALS(gTouchCallBackCalled2, false, TEST_LOCATION);
DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION);
-
ResetTouchCallbacks();
orderChangedSignal = false;
- stage.Add(actorC);
+ tet_printf("Add ActorB to stage so only Actor C not parented\n");
+
+ stage.Add(actorB);
+
+ tet_printf("Lower actor C to Bottom, B stays at top\n");
DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
- actorA.RaiseAbove(actorC);
- DALI_TEST_EQUALS(orderChangedSignal, true, TEST_LOCATION);
- DALI_TEST_EQUALS(orderChangedActor, actorA, TEST_LOCATION);
+ actorC.LowerToBottom();
+ DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
- // Ensure sorting happens at end of Core::ProcessEvents() before next touch
application.SendNotification();
application.Render();
application.ProcessEvent(touchEvent);
- tet_printf("Raise actor A Above Actor C, now both have same parent \n");
- DALI_TEST_EQUALS(gTouchCallBackCalled, true, TEST_LOCATION);
- DALI_TEST_EQUALS(gTouchCallBackCalled2, false, TEST_LOCATION);
+ tet_printf("Not parented so LowerToBottom should show no effect\n");
+
+ DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled2, true, TEST_LOCATION);
DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION);
+ ResetTouchCallbacks();
END_TEST;
}
-int UtcDaliActorTestAllAPIwhenActorNotParented(void)
+int UtcDaliActorGeoTouchTestAllAPIwhenActorNotParented(void)
{
tet_infoline("UtcDaliActor Test all raise/lower api when actor has no parent \n");
actorC.SetProperty(Actor::Property::WIDTH_RESIZE_POLICY, "FILL_TO_PARENT");
actorC.SetProperty(Actor::Property::HEIGHT_RESIZE_POLICY, "FILL_TO_PARENT");
- ResetTouchCallbacks();
+ application.GetScene().SetGeometryHittestEnabled(true);
+ ResetTouchCallbacks(application);
// Connect ChildOrderChangedSignal
bool orderChangedSignal(false);
DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION);
tet_printf("Raise actor B Above Actor C but B not parented\n");
- ResetTouchCallbacks();
+ ResetTouchCallbacks(application);
orderChangedSignal = false;
DALI_TEST_EQUALS(gTouchCallBackCalled, true, TEST_LOCATION);
DALI_TEST_EQUALS(gTouchCallBackCalled2, false, TEST_LOCATION);
DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION);
- ResetTouchCallbacks();
+ ResetTouchCallbacks(application);
orderChangedSignal = false;
DALI_TEST_EQUALS(gTouchCallBackCalled, true, TEST_LOCATION);
DALI_TEST_EQUALS(gTouchCallBackCalled2, false, TEST_LOCATION);
DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION);
- ResetTouchCallbacks();
+ ResetTouchCallbacks(application);
orderChangedSignal = false;
DALI_TEST_EQUALS(gTouchCallBackCalled, true, TEST_LOCATION);
DALI_TEST_EQUALS(gTouchCallBackCalled2, false, TEST_LOCATION);
DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION);
- ResetTouchCallbacks();
+ ResetTouchCallbacks(application);
orderChangedSignal = false;
DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION);
DALI_TEST_EQUALS(gTouchCallBackCalled2, true, TEST_LOCATION);
DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION);
- ResetTouchCallbacks();
+ ResetTouchCallbacks(application);
END_TEST;
}
END_TEST;
}
+int UtcDaliActorGeoTouchRaiseAboveActorAndTargetTheSameN(void)
+{
+ tet_infoline("UtcDaliActor RaiseToAbove and test with actor provided as target resulting in a no operation \n");
+
+ TestApplication application;
+
+ Integration::Scene stage(application.GetScene());
+
+ Actor actorA = Actor::New();
+ Actor actorB = Actor::New();
+ Actor actorC = Actor::New();
+
+ actorA.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ actorA.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+
+ actorB.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ actorB.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+
+ actorC.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ actorC.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+
+ actorA.SetProperty(Actor::Property::WIDTH_RESIZE_POLICY, "FILL_TO_PARENT");
+ actorA.SetProperty(Actor::Property::HEIGHT_RESIZE_POLICY, "FILL_TO_PARENT");
+
+ actorB.SetProperty(Actor::Property::WIDTH_RESIZE_POLICY, "FILL_TO_PARENT");
+ actorB.SetProperty(Actor::Property::HEIGHT_RESIZE_POLICY, "FILL_TO_PARENT");
+
+ actorC.SetProperty(Actor::Property::WIDTH_RESIZE_POLICY, "FILL_TO_PARENT");
+ actorC.SetProperty(Actor::Property::HEIGHT_RESIZE_POLICY, "FILL_TO_PARENT");
+
+ stage.Add(actorA);
+ stage.Add(actorB);
+ stage.Add(actorC);
+
+ // connect to actor touch signals, will use touch callbacks to determine which actor is on top.
+ // Only top actor will get touched.
+ actorA.TouchedSignal().Connect(TestTouchCallback);
+ actorB.TouchedSignal().Connect(TestTouchCallback2);
+ actorC.TouchedSignal().Connect(TestTouchCallback3);
+
+ application.GetScene().SetGeometryHittestEnabled(true);
+ ResetTouchCallbacks(application);
+
+ // Connect ChildOrderChangedSignal
+ bool orderChangedSignal(false);
+ Actor orderChangedActor;
+ ChildOrderChangedFunctor f(orderChangedSignal, orderChangedActor);
+ DevelActor::ChildOrderChangedSignal(stage.GetRootLayer()).Connect(&application, f);
+
+ application.SendNotification();
+ application.Render();
+
+ Dali::Integration::Point point;
+ point.SetDeviceId(1);
+ point.SetState(PointState::DOWN);
+ point.SetScreenPosition(Vector2(10.f, 10.f));
+ Dali::Integration::TouchEvent touchEvent;
+ touchEvent.AddPoint(point);
+
+ application.ProcessEvent(touchEvent);
+
+ DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled2, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled3, true, TEST_LOCATION);
+
+ ResetTouchCallbacks(application);
+
+ tet_infoline("Raise actor A Above Actor A which is the same actor!!\n");
+
+ DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
+ actorA.RaiseAbove(actorA);
+ DALI_TEST_EQUALS(orderChangedSignal, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(orderChangedActor, actorA, TEST_LOCATION);
+
+ application.SendNotification();
+ application.Render();
+
+ application.ProcessEvent(touchEvent);
+
+ tet_infoline("No target is source Actor so RaiseAbove should show no effect\n");
+
+ DALI_TEST_EQUALS(gTouchCallBackCalled, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled2, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled3, true, TEST_LOCATION);
+
+ ResetTouchCallbacks(application);
+
+ orderChangedSignal = false;
+
+ DALI_TEST_EQUALS(orderChangedSignal, false, TEST_LOCATION);
+ actorA.RaiseAbove(actorC);
+ DALI_TEST_EQUALS(orderChangedSignal, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(orderChangedActor, actorA, TEST_LOCATION);
+
+ application.SendNotification();
+ application.Render();
+
+ application.ProcessEvent(touchEvent);
+
+ tet_infoline("Raise actor A Above Actor C which will now be successful \n");
+ DALI_TEST_EQUALS(gTouchCallBackCalled, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled2, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(gTouchCallBackCalled3, false, TEST_LOCATION);
+
+ END_TEST;
+}
+
int UtcDaliActorGetScreenPosition(void)
{
tet_infoline("UtcDaliActorGetScreenPosition Get screen coordinates of Actor \n");
--- /dev/null
+/*
+ * Copyright (c) 2023 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali-test-suite-utils.h>
+#include <dali/devel-api/actors/actor-devel.h>
+#include <dali/devel-api/events/hit-test-algorithm.h>
+#include <dali/integration-api/events/touch-event-integ.h>
+#include <dali/public-api/dali-core.h>
+#include <stdlib.h>
+
+#include <iostream>
+
+using namespace Dali;
+
+namespace
+{
+
+/**
+ * The functor to be used in the hit-test algorithm to check whether the actor is hittable.
+ */
+bool IsActorHittableFunction(Actor actor, Dali::HitTestAlgorithm::TraverseType type)
+{
+ bool hittable = false;
+
+ switch(type)
+ {
+ case Dali::HitTestAlgorithm::CHECK_ACTOR:
+ {
+ // Check whether the actor is visible and not fully transparent.
+ if(actor.GetCurrentProperty<bool>(Actor::Property::VISIBLE) && actor.GetCurrentProperty<Vector4>(Actor::Property::WORLD_COLOR).a > 0.01f) // not FULLY_TRANSPARENT
+ {
+ // Check whether the actor has the specific name "HittableActor"
+ if(actor.GetProperty<std::string>(Actor::Property::NAME) == "HittableActor")
+ {
+ hittable = true;
+ }
+ }
+ break;
+ }
+ case Dali::HitTestAlgorithm::DESCEND_ACTOR_TREE:
+ {
+ if(actor.GetCurrentProperty<bool>(Actor::Property::VISIBLE)) // Actor is visible, if not visible then none of its children are visible.
+ {
+ hittable = true;
+ }
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+
+ return hittable;
+};
+
+bool DefaultIsActorTouchableFunction(Dali::Actor actor, Dali::HitTestAlgorithm::TraverseType type)
+{
+ bool hittable = false;
+
+ switch(type)
+ {
+ case Dali::HitTestAlgorithm::CHECK_ACTOR:
+ {
+ if(actor.GetCurrentProperty<bool>(Actor::Property::VISIBLE) &&
+ actor.GetProperty<bool>(Actor::Property::SENSITIVE) &&
+ actor.GetCurrentProperty<Vector4>(Actor::Property::WORLD_COLOR).a > 0.01f)
+ {
+ hittable = true;
+ }
+ break;
+ }
+ case Dali::HitTestAlgorithm::DESCEND_ACTOR_TREE:
+ {
+ if(actor.GetCurrentProperty<bool>(Actor::Property::VISIBLE) && // Actor is visible, if not visible then none of its children are visible.
+ actor.GetProperty<bool>(Actor::Property::SENSITIVE)) // Actor is sensitive, if insensitive none of its children should be hittable either.
+ {
+ hittable = true;
+ }
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+
+ return hittable;
+};
+
+} // anonymous namespace
+
+// Positive test case for a method
+int UtcDaliGeoHitTestAlgorithmWithFunctor(void)
+{
+ TestApplication application;
+ tet_infoline("Testing Dali::HitTestAlgorithm functor");
+
+ application.GetScene().SetGeometryHittestEnabled(true);
+
+ Stage stage = Stage::GetCurrent();
+
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ actor.SetProperty(Actor::Property::NAME, "NonHittableActor");
+ stage.Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ Vector2 screenCoordinates(10.0f, 10.0f);
+ Vector2 localCoordinates;
+ actor.ScreenToLocal(localCoordinates.x, localCoordinates.y, screenCoordinates.x, screenCoordinates.y);
+
+ // Perform a hit-test at the given screen coordinates
+ Dali::HitTestAlgorithm::Results results;
+ Dali::HitTestAlgorithm::HitTest(stage, screenCoordinates, results, IsActorHittableFunction, true);
+ DALI_TEST_CHECK(results.actor != actor);
+
+ actor.SetProperty(Actor::Property::NAME, "HittableActor");
+
+ results.actor = Actor();
+ results.actorCoordinates = Vector2::ZERO;
+
+ // Perform a hit-test at the given screen coordinates
+ Dali::HitTestAlgorithm::HitTest(stage, screenCoordinates, results, IsActorHittableFunction, true);
+ DALI_TEST_CHECK(results.actor == actor);
+ DALI_TEST_EQUALS(localCoordinates, results.actorCoordinates, 0.1f, TEST_LOCATION);
+ END_TEST;
+}
+
+int UtcDaliGeoHitTestAlgorithmOrtho01(void)
+{
+ TestApplication application;
+ tet_infoline("Testing Dali::HitTestAlgorithm with parallel Ortho camera()");
+
+ application.GetScene().SetGeometryHittestEnabled(true);
+
+ Stage stage = Stage::GetCurrent();
+ RenderTaskList renderTaskList = stage.GetRenderTaskList();
+ RenderTask defaultRenderTask = renderTaskList.GetTask(0u);
+ Dali::CameraActor cameraActor = defaultRenderTask.GetCameraActor();
+
+ Vector2 stageSize(stage.GetSize());
+ cameraActor.SetOrthographicProjection(stageSize);
+ cameraActor.SetProperty(Actor::Property::POSITION, Vector3(0.0f, 0.0f, 1600.0f));
+
+ Vector2 actorSize(stageSize * 0.5f);
+ // Create two actors with half the size of the stage and set them to be partially overlapping
+ Actor blue = Actor::New();
+ blue.SetProperty(Actor::Property::NAME, "Blue");
+ blue.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ blue.SetProperty(Actor::Property::PARENT_ORIGIN, Vector3(1.0f / 3.0f, 1.0f / 3.0f, 0.5f));
+ blue.SetProperty(Actor::Property::SIZE, actorSize);
+ blue.SetProperty(Actor::Property::POSITION_Z, 30.0f);
+
+ Actor green = Actor::New();
+ green.SetProperty(Actor::Property::NAME, "Green");
+ green.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ green.SetProperty(Actor::Property::PARENT_ORIGIN, Vector3(2.0f / 3.0f, 2.0f / 3.0f, 0.5f));
+ green.SetProperty(Actor::Property::SIZE, actorSize);
+
+ // Add the actors to the view
+ stage.Add(blue);
+ stage.Add(green);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render(0);
+ application.Render(10);
+
+ HitTestAlgorithm::Results results;
+ HitTest(stage, stageSize / 2.0f, results, &DefaultIsActorTouchableFunction, true);
+ DALI_TEST_CHECK(results.actor == green);
+ DALI_TEST_EQUALS(results.actorCoordinates, actorSize * 1.0f / 6.0f, TEST_LOCATION);
+
+ HitTest(stage, stageSize / 3.0f, results, &DefaultIsActorTouchableFunction, true);
+ DALI_TEST_CHECK(results.actor == blue);
+ DALI_TEST_EQUALS(results.actorCoordinates, actorSize * 0.5f, TEST_LOCATION);
+
+ HitTest(stage, stageSize * 2.0f / 3.0f, results, &DefaultIsActorTouchableFunction, true);
+ DALI_TEST_CHECK(results.actor == green);
+ DALI_TEST_EQUALS(results.actorCoordinates, actorSize * 0.5f, TEST_LOCATION);
+ END_TEST;
+}
+
+int UtcDaliGeoHitTestAlgorithmOrtho02(void)
+{
+ TestApplication application;
+ tet_infoline("Testing Dali::HitTestAlgorithm with offset Ortho camera()");
+
+ application.GetScene().SetGeometryHittestEnabled(true);
+
+ Stage stage = Stage::GetCurrent();
+ RenderTaskList renderTaskList = stage.GetRenderTaskList();
+ RenderTask defaultRenderTask = renderTaskList.GetTask(0u);
+ Dali::CameraActor cameraActor = defaultRenderTask.GetCameraActor();
+
+ Vector2 stageSize(stage.GetSize());
+ cameraActor.SetOrthographicProjection(stageSize);
+ cameraActor.SetNearClippingPlane(800.0f);
+ cameraActor.SetFarClippingPlane(4895.0f);
+
+ // Move camera not centered position.
+ cameraActor.SetProperty(Actor::Property::POSITION, Vector3(stageSize.x * 0.2f, stageSize.y * 0.2f, 1600.0f));
+
+ Vector2 actorSize(stageSize * 0.5f);
+ // Create two actors with half the size of the stage and set them to be partially overlapping
+ Actor blue = Actor::New();
+ blue.SetProperty(Actor::Property::NAME, "Blue");
+ blue.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ blue.SetProperty(Actor::Property::PARENT_ORIGIN, Vector3(0.2f, 0.2f, 0.5f));
+ blue.SetProperty(Actor::Property::SIZE, actorSize);
+ blue.SetProperty(Actor::Property::POSITION_Z, 30.0f);
+
+ Actor green = Actor::New();
+ green.SetProperty(Actor::Property::NAME, "Green");
+ green.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ green.SetProperty(Actor::Property::PARENT_ORIGIN, Vector3(0.4f, 0.4f, 0.5f));
+ green.SetProperty(Actor::Property::SIZE, actorSize);
+
+ // Add the actors to the view
+ stage.Add(blue);
+ stage.Add(green);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render(0);
+ application.Render(10);
+
+ {
+ HitTestAlgorithm::Results results;
+ HitTest(stage, Vector2(240.0f, 400.0f), results, &DefaultIsActorTouchableFunction, true);
+ DALI_TEST_CHECK(results.actor == green);
+ DALI_TEST_EQUALS(results.actorCoordinates, actorSize * 0.6f, 0.01f, TEST_LOCATION);
+ }
+
+ {
+ HitTestAlgorithm::Results results;
+ HitTest(stage, Vector2(0.001f, 0.001f), results, &DefaultIsActorTouchableFunction, true);
+ DALI_TEST_CHECK(results.actor == blue);
+ DALI_TEST_EQUALS(results.actorCoordinates, Vector2(0.001f, 0.001f), 0.001f, TEST_LOCATION);
+ }
+
+ {
+ HitTestAlgorithm::Results results;
+ HitTest(stage, stageSize, results, &DefaultIsActorTouchableFunction, true);
+ DALI_TEST_CHECK(!results.actor);
+ DALI_TEST_EQUALS(results.actorCoordinates, Vector2::ZERO, TEST_LOCATION);
+ }
+
+ // Just inside green
+ {
+ HitTestAlgorithm::Results results;
+ HitTest(stage, stageSize * 0.69f, results, &DefaultIsActorTouchableFunction, true);
+ DALI_TEST_CHECK(results.actor == green);
+ DALI_TEST_EQUALS(results.actorCoordinates, actorSize * 0.98f, 0.01f, TEST_LOCATION);
+ }
+
+ END_TEST;
+}
+
+int UtcDaliGeoHitTestAlgorithmClippingActor(void)
+{
+ TestApplication application;
+ tet_infoline("Testing Dali::HitTestAlgorithm with a stencil");
+
+ application.GetScene().SetGeometryHittestEnabled(true);
+
+ Stage stage = Stage::GetCurrent();
+ Actor rootLayer = stage.GetRootLayer();
+ rootLayer.SetProperty(Actor::Property::NAME, "RootLayer");
+
+ // Create a layer
+ Layer layer = Layer::New();
+ layer.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ layer.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
+ layer.SetProperty(Actor::Property::NAME, "layer");
+ stage.Add(layer);
+
+ // Create a clipping actor and add it to the layer.
+ Actor clippingActor = CreateRenderableActor();
+ clippingActor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ clippingActor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
+ clippingActor.SetProperty(Actor::Property::SIZE, Vector2(50.0f, 50.0f));
+ clippingActor.SetProperty(Actor::Property::CLIPPING_MODE, ClippingMode::CLIP_CHILDREN);
+ clippingActor.SetProperty(Actor::Property::NAME, "clippingActor");
+ layer.Add(clippingActor);
+
+ // Create a renderable actor and add it to the clipping actor.
+ Actor childActor = CreateRenderableActor();
+ childActor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ childActor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ childActor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
+ childActor.SetProperty(Actor::Property::NAME, "childActor");
+ clippingActor.Add(childActor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Hit within clippingActor and childActor.
+ HitTestAlgorithm::Results results;
+ HitTest(stage, Vector2(10.0f, 10.0f), results, &DefaultIsActorTouchableFunction, true);
+ DALI_TEST_CHECK(results.actor == childActor);
+ tet_printf("Hit: %s\n", (results.actor ? results.actor.GetProperty<std::string>(Actor::Property::NAME).c_str() : "NULL"));
+
+ // Hit within childActor but outside of clippingActor, should hit the root-layer instead.
+ HitTest(stage, Vector2(60.0f, 60.0f), results, &DefaultIsActorTouchableFunction, true);
+ DALI_TEST_CHECK(results.actor == rootLayer);
+ tet_printf("Hit: %s\n", (results.actor ? results.actor.GetProperty<std::string>(Actor::Property::NAME).c_str() : "NULL"));
+
+ END_TEST;
+}
+
+int UtcDaliGeoHitTestAlgorithmClippingActorStress(void)
+{
+ TestApplication application;
+ tet_infoline("Testing Dali::HitTestAlgorithm with many many stencil");
+
+ application.GetScene().SetGeometryHittestEnabled(true);
+
+ Stage stage = Stage::GetCurrent();
+ Actor rootLayer = stage.GetRootLayer();
+ rootLayer.SetProperty(Actor::Property::NAME, "RootLayer");
+
+ // Create a layer
+ Layer layer = Layer::New();
+ layer.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ layer.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
+ layer.SetProperty(Actor::Property::NAME, "layer");
+ stage.Add(layer);
+
+ // Create a clipping actor and add it to the layer.
+ Actor clippingActor = CreateRenderableActor();
+ clippingActor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ clippingActor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
+ clippingActor.SetProperty(Actor::Property::SIZE, Vector2(220.0f, 220.0f));
+ clippingActor.SetProperty(Actor::Property::CLIPPING_MODE, ClippingMode::CLIP_TO_BOUNDING_BOX);
+ clippingActor.SetProperty(Actor::Property::NAME, "clippingActor");
+ layer.Add(clippingActor);
+
+ // Create a renderable actor and add it to the clipping actor.
+ Actor latestActor = clippingActor;
+ const int depthMax = 100;
+ for(int i = 0; i < depthMax; i++)
+ {
+ char tmp[29];
+ sprintf(tmp, "depth%03d", i);
+
+ Actor childActor = CreateRenderableActor();
+ childActor.SetProperty(Actor::Property::SIZE, Vector2(220.0f, 220.0f));
+ childActor.SetProperty(Actor::Property::POSITION, Vector2(200.0f / depthMax, 200.0f / depthMax));
+ childActor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ childActor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
+ childActor.SetProperty(Actor::Property::CLIPPING_MODE, ClippingMode::CLIP_TO_BOUNDING_BOX);
+ childActor.SetProperty(Actor::Property::NAME, tmp);
+
+ latestActor.Add(childActor);
+ latestActor = childActor;
+ }
+ // NOTE : latestActor's TOP_LEFT position become 200.f, 200.0f
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Hit within clippingActor and latestActor.
+ HitTestAlgorithm::Results results;
+ HitTest(stage, Vector2(201.0f, 201.0f), results, &DefaultIsActorTouchableFunction, true);
+ tet_printf("Hit: %s\n", (results.actor ? results.actor.GetProperty<std::string>(Actor::Property::NAME).c_str() : "NULL"));
+ DALI_TEST_CHECK(results.actor == latestActor);
+
+ // Hit within childActor but outside of clippingActor, should hit the root-layer instead.
+ HitTest(stage, Vector2(221.0f, 221.0f), results, &DefaultIsActorTouchableFunction, true);
+ tet_printf("Hit: %s\n", (results.actor ? results.actor.GetProperty<std::string>(Actor::Property::NAME).c_str() : "NULL"));
+ DALI_TEST_CHECK(results.actor == rootLayer);
+
+ END_TEST;
+}
+
+int UtcDaliGeoHitTestAlgorithmOverlay(void)
+{
+ TestApplication application;
+ tet_infoline("Testing Dali::HitTestAlgorithm with overlay actors");
+
+ application.GetScene().SetGeometryHittestEnabled(true);
+
+ Stage stage = Stage::GetCurrent();
+ RenderTaskList renderTaskList = stage.GetRenderTaskList();
+ RenderTask defaultRenderTask = renderTaskList.GetTask(0u);
+ Dali::CameraActor cameraActor = defaultRenderTask.GetCameraActor();
+
+ Vector2 stageSize(stage.GetSize());
+ cameraActor.SetOrthographicProjection(stageSize);
+ cameraActor.SetProperty(Actor::Property::POSITION, Vector3(0.0f, 0.0f, 1600.0f));
+
+ Vector2 actorSize(stageSize * 0.5f);
+ // Create two actors with half the size of the stage and set them to be partially overlapping
+ Actor blue = Actor::New();
+ blue.SetProperty(Actor::Property::DRAW_MODE, DrawMode::OVERLAY_2D);
+ blue.SetProperty(Actor::Property::NAME, "Blue");
+ blue.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ blue.SetProperty(Actor::Property::PARENT_ORIGIN, Vector3(1.0f / 3.0f, 1.0f / 3.0f, 0.5f));
+ blue.SetProperty(Actor::Property::SIZE, actorSize);
+ blue.SetProperty(Actor::Property::POSITION_Z, 30.0f);
+
+ Actor green = Actor::New();
+ green.SetProperty(Actor::Property::NAME, "Green");
+ green.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ green.SetProperty(Actor::Property::PARENT_ORIGIN, Vector3(2.0f / 3.0f, 2.0f / 3.0f, 0.5f));
+ green.SetProperty(Actor::Property::SIZE, actorSize);
+
+ // Add the actors to the view
+ stage.Add(blue);
+ stage.Add(green);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render(0);
+ application.Render(10);
+
+ HitTestAlgorithm::Results results;
+
+ //Hit in the intersection. Should pick the blue actor since it is an overlay.
+ HitTest(stage, stageSize / 2.0f, results, &DefaultIsActorTouchableFunction, true);
+ DALI_TEST_CHECK(results.actor == blue);
+ DALI_TEST_EQUALS(results.actorCoordinates, actorSize * 5.0f / 6.0f, TEST_LOCATION);
+
+ //Hit in the blue actor
+ HitTest(stage, stageSize / 3.0f, results, &DefaultIsActorTouchableFunction, true);
+ DALI_TEST_CHECK(results.actor == blue);
+ DALI_TEST_EQUALS(results.actorCoordinates, actorSize * 0.5f, TEST_LOCATION);
+
+ //Hit in the green actor
+ HitTest(stage, stageSize * 2.0f / 3.0f, results, &DefaultIsActorTouchableFunction, true);
+ DALI_TEST_CHECK(results.actor == green);
+ DALI_TEST_EQUALS(results.actorCoordinates, actorSize * 0.5f, TEST_LOCATION);
+
+ // Create new actor child as blue. It will be shown over the blue, and green.
+ Actor red = Actor::New();
+ red.SetProperty(Actor::Property::NAME, "Red");
+ red.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ red.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+ red.SetProperty(Actor::Property::POSITION, Vector2(actorSize.x * 5.0f / 6.0f, -actorSize.y * 1.0f / 6.0f));
+ red.SetProperty(Actor::Property::SIZE, actorSize);
+
+ blue.Add(red);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render(0);
+ application.Render(10);
+
+ //Hit in the intersection red, green, blue. Should pick the red actor since it is an child of overlay.
+ HitTest(stage, Vector2(stageSize.x * 13.0f / 24.0f, stageSize.y * 11.0f / 24.0f), results, &DefaultIsActorTouchableFunction, true);
+ tet_printf("%d %d %d , %f %f\n", results.actor == red ? 1 : 0, results.actor == green ? 1 : 0, results.actor == blue ? 1 : 0, results.actorCoordinates.x, results.actorCoordinates.y);
+ DALI_TEST_CHECK(results.actor == red);
+ DALI_TEST_EQUALS(results.actorCoordinates, Vector2(actorSize.x * 1.0f / 12.0f, actorSize.y * 11.0f / 12.0f), TEST_LOCATION);
+
+ //Hit in the intersection red, blue. Should pick the red actor since it is an child of blue.
+ HitTest(stage, Vector2(stageSize.x * 13.0f / 24.0f, stageSize.y * 9.0f / 24.0f), results, &DefaultIsActorTouchableFunction, true);
+ tet_printf("%d %d %d , %f %f\n", results.actor == red ? 1 : 0, results.actor == green ? 1 : 0, results.actor == blue ? 1 : 0, results.actorCoordinates.x, results.actorCoordinates.y);
+ DALI_TEST_CHECK(results.actor == red);
+ DALI_TEST_EQUALS(results.actorCoordinates, Vector2(actorSize.x * 1.0f / 12.0f, actorSize.y * 9.0f / 12.0f), TEST_LOCATION);
+
+ //Hit in the intersection red, green. Should pick the green actor since red is outside the scope of its parent.
+ HitTest(stage, Vector2(stageSize.x * 15.0f / 24.0f, stageSize.y * 11.0f / 24.0f), results, &DefaultIsActorTouchableFunction, true);
+ tet_printf("%d %d %d , %f %f\n", results.actor == red ? 1 : 0, results.actor == green ? 1 : 0, results.actor == blue ? 1 : 0, results.actorCoordinates.x, results.actorCoordinates.y);
+ DALI_TEST_CHECK(results.actor == green);
+ DALI_TEST_EQUALS(results.actorCoordinates, Vector2(actorSize.x * 5.0f / 12.0f, actorSize.y * 1.0f / 12.0f), TEST_LOCATION);
+
+ //Hit in the intersection blue, green. Should pick the blue actor since it is an overlay.
+ HitTest(stage, Vector2(stageSize.x * 11.0f / 24.0f, stageSize.y * 13.0f / 24.0f), results, &DefaultIsActorTouchableFunction, true);
+ tet_printf("%d %d %d , %f %f\n", results.actor == red ? 1 : 0, results.actor == green ? 1 : 0, results.actor == blue ? 1 : 0, results.actorCoordinates.x, results.actorCoordinates.y);
+ DALI_TEST_CHECK(results.actor == blue);
+ DALI_TEST_EQUALS(results.actorCoordinates, Vector2(actorSize.x * 9.0f / 12.0f, actorSize.y * 11.0f / 12.0f), TEST_LOCATION);
+
+ // Change blue's draw mode as normal. now blue < red < green
+ blue.SetProperty(Actor::Property::DRAW_MODE, DrawMode::NORMAL);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render(0);
+ application.Render(10);
+
+ //Hit in the intersection red, green, blue. Should pick the green actor since it is latest ordered actor.
+ HitTest(stage, Vector2(stageSize.x * 13.0f / 24.0f, stageSize.y * 11.0f / 24.0f), results, &DefaultIsActorTouchableFunction, true);
+ tet_printf("%d %d %d , %f %f\n", results.actor == red ? 1 : 0, results.actor == green ? 1 : 0, results.actor == blue ? 1 : 0, results.actorCoordinates.x, results.actorCoordinates.y);
+ DALI_TEST_CHECK(results.actor == green);
+ DALI_TEST_EQUALS(results.actorCoordinates, Vector2(actorSize.x * 3.0f / 12.0f, actorSize.y * 1.0f / 12.0f), TEST_LOCATION);
+
+ //Hit in the intersection red, blue. Should pick the red actor since it is an child of blue.
+ HitTest(stage, Vector2(stageSize.x * 13.0f / 24.0f, stageSize.y * 9.0f / 24.0f), results, &DefaultIsActorTouchableFunction, true);
+ tet_printf("%d %d %d , %f %f\n", results.actor == red ? 1 : 0, results.actor == green ? 1 : 0, results.actor == blue ? 1 : 0, results.actorCoordinates.x, results.actorCoordinates.y);
+ DALI_TEST_CHECK(results.actor == red);
+ DALI_TEST_EQUALS(results.actorCoordinates, Vector2(actorSize.x * 1.0f / 12.0f, actorSize.y * 9.0f / 12.0f), TEST_LOCATION);
+
+ //Hit in the intersection red, green. Should pick the green actor since it is latest ordered actor.
+ HitTest(stage, Vector2(stageSize.x * 15.0f / 24.0f, stageSize.y * 11.0f / 24.0f), results, &DefaultIsActorTouchableFunction, true);
+ tet_printf("%d %d %d , %f %f\n", results.actor == red ? 1 : 0, results.actor == green ? 1 : 0, results.actor == blue ? 1 : 0, results.actorCoordinates.x, results.actorCoordinates.y);
+ DALI_TEST_CHECK(results.actor == green);
+ DALI_TEST_EQUALS(results.actorCoordinates, Vector2(actorSize.x * 5.0f / 12.0f, actorSize.y * 1.0f / 12.0f), TEST_LOCATION);
+
+ //Hit in the intersection blue, green. Should pick the green actor since it is latest ordered actor.
+ HitTest(stage, Vector2(stageSize.x * 11.0f / 24.0f, stageSize.y * 13.0f / 24.0f), results, &DefaultIsActorTouchableFunction, true);
+ tet_printf("%d %d %d , %f %f\n", results.actor == red ? 1 : 0, results.actor == green ? 1 : 0, results.actor == blue ? 1 : 0, results.actorCoordinates.x, results.actorCoordinates.y);
+ DALI_TEST_CHECK(results.actor == green);
+ DALI_TEST_EQUALS(results.actorCoordinates, Vector2(actorSize.x * 1.0f / 12.0f, actorSize.y * 3.0f / 12.0f), TEST_LOCATION);
+ END_TEST;
+}
+
+int UtcDaliGeoHitTestAlgorithmOrder(void)
+{
+ TestApplication application;
+ tet_infoline("Testing Dali::HitTestAlgorithm between On/Off render task");
+
+ application.GetScene().SetGeometryHittestEnabled(true);
+
+ Stage stage = Stage::GetCurrent();
+ Vector2 stageSize(stage.GetSize());
+
+ Actor blue = Actor::New();
+ blue[Dali::Actor::Property::NAME] = "Blue";
+ blue[Dali::Actor::Property::ANCHOR_POINT] = AnchorPoint::CENTER;
+ blue[Dali::Actor::Property::PARENT_ORIGIN] = ParentOrigin::CENTER;
+ blue[Dali::Actor::Property::WIDTH_RESIZE_POLICY] = ResizePolicy::FILL_TO_PARENT;
+ blue[Dali::Actor::Property::HEIGHT_RESIZE_POLICY] = ResizePolicy::FILL_TO_PARENT;
+
+ Actor green = Actor::New();
+ green[Dali::Actor::Property::NAME] = "Green";
+ green[Dali::Actor::Property::ANCHOR_POINT] = AnchorPoint::CENTER;
+ green[Dali::Actor::Property::PARENT_ORIGIN] = ParentOrigin::CENTER;
+ green[Dali::Actor::Property::WIDTH_RESIZE_POLICY] = ResizePolicy::FILL_TO_PARENT;
+ green[Dali::Actor::Property::HEIGHT_RESIZE_POLICY] = ResizePolicy::FILL_TO_PARENT;
+
+ stage.Add(blue);
+ stage.Add(green);
+
+ RenderTaskList renderTaskList = stage.GetRenderTaskList();
+ RenderTask offRenderTask = renderTaskList.CreateTask();
+
+ Dali::CameraActor cameraActor = Dali::CameraActor::New(stageSize);
+ cameraActor[Dali::Actor::Property::ANCHOR_POINT] = AnchorPoint::CENTER;
+ cameraActor[Dali::Actor::Property::PARENT_ORIGIN] = ParentOrigin::CENTER;
+ stage.Add(cameraActor);
+
+ offRenderTask.SetExclusive(true);
+ offRenderTask.SetInputEnabled(true);
+ offRenderTask.SetCameraActor(cameraActor);
+ offRenderTask.SetSourceActor(green);
+ offRenderTask.SetScreenToFrameBufferMappingActor(green);
+
+ Dali::Texture texture = Dali::Texture::New(TextureType::TEXTURE_2D, Pixel::RGB888, unsigned(stageSize.width), unsigned(stageSize.height));
+ FrameBuffer renderTarget = FrameBuffer::New(stageSize.width, stageSize.height, FrameBuffer::Attachment::DEPTH);
+ renderTarget.AttachColorTexture(texture);
+ offRenderTask.SetFrameBuffer(renderTarget);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render(10);
+
+ HitTestAlgorithm::Results results;
+ HitTest(stage, stageSize / 2.0f, results, &DefaultIsActorTouchableFunction, true);
+ DALI_TEST_CHECK(results.actor == green);
+
+ END_TEST;
+}
+
+int UtcDaliGeoHitTestAlgorithmExclusiveMultiple(void)
+{
+ TestApplication application;
+ tet_infoline("Testing Dali::HitTestAlgorithm between On/Off render task with multiple exclusived");
+
+ application.GetScene().SetGeometryHittestEnabled(true);
+
+ Stage stage = Stage::GetCurrent();
+ Vector2 stageSize(stage.GetSize());
+
+ Actor blue = Actor::New();
+ blue[Dali::Actor::Property::NAME] = "Blue";
+ blue[Dali::Actor::Property::ANCHOR_POINT] = AnchorPoint::CENTER;
+ blue[Dali::Actor::Property::PARENT_ORIGIN] = ParentOrigin::CENTER;
+ blue[Dali::Actor::Property::WIDTH_RESIZE_POLICY] = ResizePolicy::FILL_TO_PARENT;
+ blue[Dali::Actor::Property::HEIGHT_RESIZE_POLICY] = ResizePolicy::FILL_TO_PARENT;
+
+ Actor green = Actor::New();
+ green[Dali::Actor::Property::NAME] = "Green";
+ green[Dali::Actor::Property::ANCHOR_POINT] = AnchorPoint::CENTER;
+ green[Dali::Actor::Property::PARENT_ORIGIN] = ParentOrigin::CENTER;
+ green[Dali::Actor::Property::WIDTH_RESIZE_POLICY] = ResizePolicy::FILL_TO_PARENT;
+ green[Dali::Actor::Property::HEIGHT_RESIZE_POLICY] = ResizePolicy::FILL_TO_PARENT;
+
+ stage.Add(blue);
+ stage.Add(green);
+
+ RenderTaskList renderTaskList = stage.GetRenderTaskList();
+ RenderTask offRenderTask = renderTaskList.CreateTask();
+ RenderTask offRenderTask2 = renderTaskList.CreateTask();
+
+ Dali::CameraActor cameraActor = Dali::CameraActor::New(stageSize);
+ cameraActor[Dali::Actor::Property::ANCHOR_POINT] = AnchorPoint::CENTER;
+ cameraActor[Dali::Actor::Property::PARENT_ORIGIN] = ParentOrigin::CENTER;
+ stage.Add(cameraActor);
+
+ offRenderTask.SetExclusive(true);
+ offRenderTask.SetInputEnabled(true);
+ offRenderTask.SetCameraActor(cameraActor);
+ offRenderTask.SetSourceActor(green);
+ offRenderTask.SetScreenToFrameBufferMappingActor(green);
+
+ Dali::Texture texture = Dali::Texture::New(TextureType::TEXTURE_2D, Pixel::RGB888, unsigned(stageSize.width), unsigned(stageSize.height));
+ FrameBuffer renderTarget = FrameBuffer::New(stageSize.width, stageSize.height, FrameBuffer::Attachment::DEPTH);
+ renderTarget.AttachColorTexture(texture);
+ offRenderTask.SetFrameBuffer(renderTarget);
+
+ offRenderTask2.SetExclusive(true);
+ offRenderTask2.SetInputEnabled(true);
+ offRenderTask2.SetCameraActor(cameraActor);
+ offRenderTask2.SetSourceActor(green);
+ offRenderTask2.SetScreenToFrameBufferMappingActor(green);
+ offRenderTask2.SetFrameBuffer(renderTarget);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render(10);
+
+ HitTestAlgorithm::Results results;
+ HitTest(stage, stageSize / 2.0f, results, &DefaultIsActorTouchableFunction, true);
+ DALI_TEST_CHECK(results.actor == green);
+
+ END_TEST;
+}
+
+int UtcDaliGeoHitTestAlgorithmBuildPickingRay01(void)
+{
+ TestApplication application;
+ tet_infoline("Testing Dali::HitTestAlgorithm::BuildPickingRay positive test");
+
+ application.GetScene().SetGeometryHittestEnabled(true);
+
+ Stage stage = Stage::GetCurrent();
+ RenderTaskList renderTaskList = stage.GetRenderTaskList();
+ RenderTask defaultRenderTask = renderTaskList.GetTask(0u);
+ Dali::CameraActor cameraActor = defaultRenderTask.GetCameraActor();
+
+ Vector2 stageSize(stage.GetSize());
+
+ Vector2 actorSize(stageSize * 0.5f);
+ // Create two actors with half the size of the stage and set them to be overlapping
+ Actor blue = Actor::New();
+ blue.SetProperty(Actor::Property::NAME, "Blue");
+ blue.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ blue.SetProperty(Actor::Property::PARENT_ORIGIN, AnchorPoint::CENTER);
+ blue.SetProperty(Actor::Property::SIZE, actorSize);
+
+ Actor green = Actor::New();
+ green.SetProperty(Actor::Property::NAME, "Green");
+ green.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ green.SetProperty(Actor::Property::PARENT_ORIGIN, AnchorPoint::CENTER);
+ green.SetProperty(Actor::Property::SIZE, actorSize);
+
+ // Add the actors to the view
+ stage.Add(blue);
+ stage.Add(green);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render(0);
+
+ Vector2 screenCoords(stageSize * 0.5f); // touch center of screen
+ Vector3 origin;
+ Vector3 direction;
+ bool built = HitTestAlgorithm::BuildPickingRay(defaultRenderTask, screenCoords, origin, direction);
+
+ Vector3 camPos = cameraActor[Actor::Property::POSITION];
+ DALI_TEST_EQUALS(built, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(camPos, origin, TEST_LOCATION);
+ direction.Normalize();
+ DALI_TEST_EQUALS(direction, -Vector3::ZAXIS, 0.01f, TEST_LOCATION);
+
+ screenCoords.x = stageSize.width * 0.75f;
+ built = HitTestAlgorithm::BuildPickingRay(defaultRenderTask, screenCoords, origin, direction);
+ DALI_TEST_EQUALS(built, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(camPos, origin, TEST_LOCATION);
+ direction.Normalize();
+ DALI_TEST_EQUALS(direction, Vector3(0.075f, 0.0f, -1.0f), 0.01f, TEST_LOCATION);
+
+ screenCoords.x = 0.0f;
+ screenCoords.y = 0.0f;
+ built = HitTestAlgorithm::BuildPickingRay(defaultRenderTask, screenCoords, origin, direction);
+ DALI_TEST_EQUALS(built, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(camPos, origin, TEST_LOCATION);
+ direction.Normalize();
+ DALI_TEST_EQUALS(direction, Vector3(-0.144f, -0.24f, -0.96f), 0.01f, TEST_LOCATION);
+
+ screenCoords.x = stageSize.width;
+ screenCoords.y = stageSize.height;
+ built = HitTestAlgorithm::BuildPickingRay(defaultRenderTask, screenCoords, origin, direction);
+ DALI_TEST_EQUALS(built, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(camPos, origin, TEST_LOCATION);
+ direction.Normalize();
+ DALI_TEST_EQUALS(direction, Vector3(0.144f, 0.24f, -0.96f), 0.01f, TEST_LOCATION);
+
+ END_TEST;
+}
+
+int UtcDaliGeoHitTestAlgorithmBuildPickingRay02(void)
+{
+ TestApplication application;
+ tet_infoline("Testing Dali::HitTestAlgorithm::BuildPickingRay positive test for offscreen");
+
+ application.GetScene().SetGeometryHittestEnabled(true);
+
+ Stage stage = Stage::GetCurrent();
+ RenderTaskList renderTaskList = stage.GetRenderTaskList();
+ RenderTask defaultRenderTask = renderTaskList.GetTask(0u);
+ RenderTask offRenderTask = renderTaskList.CreateTask();
+
+ Dali::CameraActor defaultCameraActor = defaultRenderTask.GetCameraActor();
+
+ Vector2 stageSize(stage.GetSize());
+
+ Vector2 actorSize(stageSize * 0.5f);
+ Vector2 offscreenSize(1920.0f, 1080.0f); // Quit big size.
+
+ // Create two actors with half the size of the stage and set them to be partial-overlapping
+ Actor blue = Actor::New();
+ blue.SetProperty(Actor::Property::NAME, "Blue");
+ blue.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ blue.SetProperty(Actor::Property::PARENT_ORIGIN, AnchorPoint::CENTER);
+ blue.SetProperty(Actor::Property::SIZE, actorSize);
+ blue.SetProperty(Actor::Property::POSITION, -actorSize * 0.25f);
+
+ Actor green = Actor::New();
+ green.SetProperty(Actor::Property::NAME, "Green");
+ green.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ green.SetProperty(Actor::Property::PARENT_ORIGIN, AnchorPoint::CENTER);
+ green.SetProperty(Actor::Property::SIZE, actorSize);
+ green.SetProperty(Actor::Property::POSITION, actorSize * 0.25f);
+
+ Actor red = Actor::New();
+ red.SetProperty(Actor::Property::NAME, "Red");
+ red.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ red.SetProperty(Actor::Property::PARENT_ORIGIN, AnchorPoint::CENTER);
+ red.SetProperty(Actor::Property::SIZE, offscreenSize * 0.5f);
+
+ Dali::CameraActor offscreenCameraActor = Dali::CameraActor::New(offscreenSize);
+ offscreenCameraActor[Dali::Actor::Property::ANCHOR_POINT] = AnchorPoint::CENTER;
+ offscreenCameraActor[Dali::Actor::Property::PARENT_ORIGIN] = ParentOrigin::CENTER;
+ stage.Add(offscreenCameraActor);
+
+ offRenderTask.SetExclusive(true);
+ offRenderTask.SetInputEnabled(true);
+ offRenderTask.SetCameraActor(offscreenCameraActor);
+ offRenderTask.SetSourceActor(red);
+ offRenderTask.SetScreenToFrameBufferMappingActor(green);
+
+ Dali::Texture texture = Dali::Texture::New(TextureType::TEXTURE_2D, Pixel::RGBA8888, unsigned(actorSize.width), unsigned(actorSize.height));
+ FrameBuffer renderTarget = FrameBuffer::New(actorSize.width, actorSize.height, FrameBuffer::Attachment::DEPTH_STENCIL);
+ renderTarget.AttachColorTexture(texture);
+ offRenderTask.SetFrameBuffer(renderTarget);
+
+ // Add the actors to the view
+ stage.Add(blue);
+ stage.Add(green);
+ stage.Add(red);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render(0);
+
+ Vector2 screenCoords(stageSize * 0.5f); // touch center of screen
+ Vector3 origin;
+ Vector3 direction;
+ bool built = HitTestAlgorithm::BuildPickingRay(defaultRenderTask, screenCoords, origin, direction);
+
+ Vector3 camPos = defaultCameraActor[Actor::Property::POSITION];
+ DALI_TEST_EQUALS(built, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(camPos, origin, TEST_LOCATION);
+ direction.Normalize();
+ DALI_TEST_EQUALS(direction, -Vector3::ZAXIS, 0.01f, TEST_LOCATION);
+
+ screenCoords.x = stageSize.width * 0.75f;
+ built = HitTestAlgorithm::BuildPickingRay(defaultRenderTask, screenCoords, origin, direction);
+ DALI_TEST_EQUALS(built, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(camPos, origin, TEST_LOCATION);
+ direction.Normalize();
+ DALI_TEST_EQUALS(direction, Vector3(0.075f, 0.0f, -1.0f), 0.01f, TEST_LOCATION);
+
+ screenCoords.x = 0.0f;
+ screenCoords.y = 0.0f;
+ built = HitTestAlgorithm::BuildPickingRay(defaultRenderTask, screenCoords, origin, direction);
+ DALI_TEST_EQUALS(built, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(camPos, origin, TEST_LOCATION);
+ direction.Normalize();
+ DALI_TEST_EQUALS(direction, Vector3(-0.144f, -0.24f, -0.96f), 0.01f, TEST_LOCATION);
+
+ screenCoords.x = stageSize.width;
+ screenCoords.y = stageSize.height;
+ built = HitTestAlgorithm::BuildPickingRay(defaultRenderTask, screenCoords, origin, direction);
+ DALI_TEST_EQUALS(built, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(camPos, origin, TEST_LOCATION);
+ direction.Normalize();
+ DALI_TEST_EQUALS(direction, Vector3(0.144f, 0.24f, -0.96f), 0.01f, TEST_LOCATION);
+
+ // For offscreen picking ray
+ camPos = Vector3(offscreenCameraActor[Actor::Property::POSITION]);
+
+ const float ELLIPSION = 0.001f; ///< tiny margin to avoid non-hitting cases
+
+ // Center of green
+ screenCoords = stageSize * 0.5f + actorSize * 0.25f;
+ built = HitTestAlgorithm::BuildPickingRay(offRenderTask, screenCoords, origin, direction);
+
+ DALI_TEST_EQUALS(built, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(camPos, origin, TEST_LOCATION);
+ direction.Normalize();
+ DALI_TEST_EQUALS(direction, -Vector3::ZAXIS, 0.01f, TEST_LOCATION);
+
+ // Center right of green
+ screenCoords.x = stageSize.width * 0.5f + actorSize.width * 0.75f - ELLIPSION;
+ built = HitTestAlgorithm::BuildPickingRay(offRenderTask, screenCoords, origin, direction);
+ DALI_TEST_EQUALS(built, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(camPos, origin, TEST_LOCATION);
+ direction.Normalize();
+ DALI_TEST_EQUALS(direction, Vector3(0.242533f, 0.0f, -0.970143f), 0.01f, TEST_LOCATION);
+
+ // Top left of green
+ screenCoords = stageSize * 0.5f - actorSize * 0.25f + Vector2(ELLIPSION, ELLIPSION);
+ built = HitTestAlgorithm::BuildPickingRay(offRenderTask, screenCoords, origin, direction);
+ DALI_TEST_EQUALS(built, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(camPos, origin, TEST_LOCATION);
+ direction.Normalize();
+ DALI_TEST_EQUALS(direction, Vector3(-0.240308f, -0.135174f, -0.961239f), 0.01f, TEST_LOCATION);
+
+ // Bottom right of green
+ screenCoords = stageSize * 0.5f + actorSize * 0.75f - Vector2(ELLIPSION, ELLIPSION);
+ built = HitTestAlgorithm::BuildPickingRay(offRenderTask, screenCoords, origin, direction);
+ DALI_TEST_EQUALS(built, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(camPos, origin, TEST_LOCATION);
+ direction.Normalize();
+ DALI_TEST_EQUALS(direction, Vector3(0.240308f, 0.135174f, -0.961239f), 0.01f, TEST_LOCATION);
+
+ // Rotate green
+ green.SetProperty(Actor::Property::ORIENTATION, Quaternion(Radian(Degree(90.0f)), Vector3::ZAXIS));
+
+ // Render and notify
+ application.SendNotification();
+ application.Render(0);
+
+ // Top left of green, but ray directoin is bottom left
+ screenCoords.x = stageSize.width * 0.5f + actorSize.width * 0.25f - actorSize.height * 0.5f + ELLIPSION;
+ screenCoords.y = stageSize.height * 0.5f + actorSize.height * 0.25f - actorSize.width * 0.5f + ELLIPSION;
+ built = HitTestAlgorithm::BuildPickingRay(offRenderTask, screenCoords, origin, direction);
+ DALI_TEST_EQUALS(built, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(camPos, origin, TEST_LOCATION);
+ direction.Normalize();
+ DALI_TEST_EQUALS(direction, Vector3(-0.240308f, 0.135174f, -0.961239f), 0.01f, TEST_LOCATION);
+
+ // Bottom right of green, but ray direction is top right
+ screenCoords.x = stageSize.width * 0.5f + actorSize.width * 0.25f + actorSize.height * 0.5f - ELLIPSION;
+ screenCoords.y = stageSize.height * 0.5f + actorSize.height * 0.25f + actorSize.width * 0.5f - ELLIPSION;
+ built = HitTestAlgorithm::BuildPickingRay(offRenderTask, screenCoords, origin, direction);
+ DALI_TEST_EQUALS(built, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(camPos, origin, TEST_LOCATION);
+ direction.Normalize();
+ DALI_TEST_EQUALS(direction, Vector3(0.240308f, -0.135174f, -0.961239f), 0.01f, TEST_LOCATION);
+
+ // Out of green. BuildPickingRay failed.
+ screenCoords = stageSize * 0.5f - actorSize * 0.5f;
+ built = HitTestAlgorithm::BuildPickingRay(offRenderTask, screenCoords, origin, direction);
+ DALI_TEST_EQUALS(built, false, TEST_LOCATION);
+
+ END_TEST;
+}
--- /dev/null
+/*
+ * Copyright (c) 2023 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali-test-suite-utils.h>
+#include <dali/devel-api/actors/actor-devel.h>
+#include <dali/devel-api/events/hover-event-devel.h>
+#include <dali/integration-api/events/hover-event-integ.h>
+#include <dali/integration-api/events/touch-integ.h>
+#include <dali/integration-api/render-task-list-integ.h>
+#include <dali/public-api/dali-core.h>
+#include <stdlib.h>
+
+#include <iostream>
+
+using namespace Dali;
+
+void utc_dali_geo_hover_processing_startup(void)
+{
+ test_return_value = TET_UNDEF;
+}
+
+void utc_dali_geo_hover_processing_cleanup(void)
+{
+ test_return_value = TET_PASS;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+namespace
+{
+// Stores data that is populated in the callback and will be read by the TET cases
+struct SignalData
+{
+ SignalData()
+ : functorCalled(false),
+ hoverEvent(),
+ hoveredActor()
+ {
+ }
+
+ void Reset()
+ {
+ functorCalled = false;
+ hoverEvent.Reset();
+ hoveredActor.Reset();
+ }
+
+ bool functorCalled;
+ HoverEvent hoverEvent;
+ Actor hoveredActor;
+};
+
+// Functor that sets the data when called
+struct HoverEventFunctor
+{
+ /**
+ * Constructor.
+ * @param[in] data Reference to the data to store callback information.
+ * @param[in] returnValue What the functor should return.
+ */
+ HoverEventFunctor(SignalData& data, bool returnValue = true)
+ : signalData(data),
+ returnValue(returnValue)
+ {
+ }
+
+ bool operator()(Actor actor, const HoverEvent& hoverEvent)
+ {
+ signalData.functorCalled = true;
+ signalData.hoveredActor = actor;
+ signalData.hoverEvent = hoverEvent;
+
+ return returnValue;
+ }
+
+ SignalData& signalData;
+ bool returnValue;
+};
+
+// Functor that removes the actor when called.
+struct RemoveActorFunctor : public HoverEventFunctor
+{
+ /**
+ * Constructor.
+ * @param[in] data Reference to the data to store callback information.
+ * @param[in] returnValue What the functor should return.
+ */
+ RemoveActorFunctor(SignalData& data, bool returnValue = true)
+ : HoverEventFunctor(data, returnValue)
+ {
+ }
+
+ bool operator()(Actor actor, const HoverEvent& hoverEvent)
+ {
+ Actor parent(actor.GetParent());
+ if(parent)
+ {
+ parent.Remove(actor);
+ }
+
+ return HoverEventFunctor::operator()(actor, hoverEvent);
+ }
+};
+
+Integration::HoverEvent GenerateSingleHover(PointState::Type state, const Vector2& screenPosition)
+{
+ Integration::HoverEvent hoverEvent;
+ Integration::Point point;
+ point.SetState(state);
+ point.SetScreenPosition(screenPosition);
+ hoverEvent.points.push_back(point);
+ return hoverEvent;
+}
+
+} // namespace
+
+///////////////////////////////////////////////////////////////////////////////
+
+int UtcDaliGeoHoverNormalProcessing(void)
+{
+ TestApplication application;
+ application.GetScene().SetGeometryHittestEnabled(true);
+
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ application.GetScene().Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's hovered signal
+ SignalData data;
+ HoverEventFunctor functor(data);
+ actor.HoveredSignal().Connect(&application, functor);
+
+ Vector2 screenCoordinates(10.0f, 10.0f);
+ Vector2 localCoordinates;
+ actor.ScreenToLocal(localCoordinates.x, localCoordinates.y, screenCoordinates.x, screenCoordinates.y);
+
+ // Emit a started signal
+ application.ProcessEvent(GenerateSingleHover(PointState::STARTED, screenCoordinates));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(1u, data.hoverEvent.GetPointCount(), TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::STARTED, data.hoverEvent.GetState(0), TEST_LOCATION);
+ DALI_TEST_EQUALS(screenCoordinates, data.hoverEvent.GetScreenPosition(0), TEST_LOCATION);
+ DALI_TEST_EQUALS(localCoordinates, data.hoverEvent.GetLocalPosition(0), 0.1f, TEST_LOCATION);
+ DALI_TEST_EQUALS(0, data.hoverEvent.GetDeviceId(0), TEST_LOCATION);
+ DALI_TEST_EQUALS(0u, data.hoverEvent.GetTime(), TEST_LOCATION);
+ DALI_TEST_EQUALS(actor, data.hoverEvent.GetHitActor(0), TEST_LOCATION);
+ DALI_TEST_EQUALS(-1, data.hoverEvent.GetDeviceId(1), TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::FINISHED, data.hoverEvent.GetState(1), TEST_LOCATION);
+ DALI_TEST_EQUALS(Vector2::ZERO, data.hoverEvent.GetScreenPosition(1), 0.1f, TEST_LOCATION);
+ DALI_TEST_EQUALS(Vector2::ZERO, data.hoverEvent.GetLocalPosition(1), 0.1f, TEST_LOCATION);
+ DALI_TEST_EQUALS(Dali::Actor(), data.hoverEvent.GetHitActor(1), TEST_LOCATION);
+ data.Reset();
+
+ // Emit a motion signal
+ screenCoordinates.x = screenCoordinates.y = 11.0f;
+ actor.ScreenToLocal(localCoordinates.x, localCoordinates.y, screenCoordinates.x, screenCoordinates.y);
+ application.ProcessEvent(GenerateSingleHover(PointState::MOTION, screenCoordinates));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(1u, data.hoverEvent.GetPointCount(), TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::MOTION, data.hoverEvent.GetState(0), TEST_LOCATION);
+ DALI_TEST_EQUALS(screenCoordinates, data.hoverEvent.GetScreenPosition(0), TEST_LOCATION);
+ DALI_TEST_EQUALS(localCoordinates, data.hoverEvent.GetLocalPosition(0), 0.1f, TEST_LOCATION);
+ DALI_TEST_EQUALS(0, data.hoverEvent.GetDeviceId(0), TEST_LOCATION);
+ DALI_TEST_EQUALS(0u, data.hoverEvent.GetTime(), TEST_LOCATION);
+ DALI_TEST_EQUALS(actor, data.hoverEvent.GetHitActor(0), TEST_LOCATION);
+ DALI_TEST_EQUALS(-1, data.hoverEvent.GetDeviceId(1), TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::FINISHED, data.hoverEvent.GetState(1), TEST_LOCATION);
+ DALI_TEST_EQUALS(Vector2::ZERO, data.hoverEvent.GetScreenPosition(1), 0.1f, TEST_LOCATION);
+ DALI_TEST_EQUALS(Vector2::ZERO, data.hoverEvent.GetLocalPosition(1), 0.1f, TEST_LOCATION);
+ DALI_TEST_EQUALS(Dali::Actor(), data.hoverEvent.GetHitActor(1), TEST_LOCATION);
+ data.Reset();
+
+ // Emit a finished signal
+ screenCoordinates.x = screenCoordinates.y = 12.0f;
+ actor.ScreenToLocal(localCoordinates.x, localCoordinates.y, screenCoordinates.x, screenCoordinates.y);
+ application.ProcessEvent(GenerateSingleHover(PointState::FINISHED, screenCoordinates));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(1u, data.hoverEvent.GetPointCount(), TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::FINISHED, data.hoverEvent.GetState(0), TEST_LOCATION);
+ DALI_TEST_EQUALS(screenCoordinates, data.hoverEvent.GetScreenPosition(0), TEST_LOCATION);
+ DALI_TEST_EQUALS(localCoordinates, data.hoverEvent.GetLocalPosition(0), 0.1f, TEST_LOCATION);
+ DALI_TEST_EQUALS(0, data.hoverEvent.GetDeviceId(0), TEST_LOCATION);
+ DALI_TEST_EQUALS(0u, data.hoverEvent.GetTime(), TEST_LOCATION);
+ DALI_TEST_EQUALS(actor, data.hoverEvent.GetHitActor(0), TEST_LOCATION);
+ DALI_TEST_EQUALS(-1, data.hoverEvent.GetDeviceId(1), TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::FINISHED, data.hoverEvent.GetState(1), TEST_LOCATION);
+ DALI_TEST_EQUALS(Vector2::ZERO, data.hoverEvent.GetScreenPosition(1), 0.1f, TEST_LOCATION);
+ DALI_TEST_EQUALS(Vector2::ZERO, data.hoverEvent.GetLocalPosition(1), 0.1f, TEST_LOCATION);
+ DALI_TEST_EQUALS(Dali::Actor(), data.hoverEvent.GetHitActor(1), TEST_LOCATION);
+ data.Reset();
+
+ // Emit a started signal where the actor is not present
+ screenCoordinates.x = screenCoordinates.y = 200.0f;
+ application.ProcessEvent(GenerateSingleHover(PointState::STARTED, screenCoordinates));
+ DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_CHECK(!data.hoverEvent);
+
+ END_TEST;
+}
+
+int UtcDaliGeoHoverOutsideCameraNearFarPlanes(void)
+{
+ TestApplication application;
+ application.GetScene().SetGeometryHittestEnabled(true);
+
+ Integration::Scene stage = application.GetScene();
+ Vector2 stageSize = stage.GetSize();
+
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ actor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+ stage.Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Get the camera's near and far planes
+ RenderTaskList taskList = stage.GetRenderTaskList();
+ Dali::RenderTask task = taskList.GetTask(0);
+ CameraActor camera = task.GetCameraActor();
+ float nearPlane = camera.GetNearClippingPlane();
+ float farPlane = camera.GetFarClippingPlane();
+
+ // Calculate the current distance of the actor from the camera
+ float tanHalfFov = tanf(camera.GetFieldOfView() * 0.5f);
+ float distance = (stageSize.y * 0.5f) / tanHalfFov;
+
+ // Connect to actor's hovered signal
+ SignalData data;
+ HoverEventFunctor functor(data);
+ actor.HoveredSignal().Connect(&application, functor);
+
+ Vector2 screenCoordinates(stageSize.x * 0.5f, stageSize.y * 0.5f);
+
+ // Emit a started signal
+ application.ProcessEvent(GenerateSingleHover(PointState::STARTED, screenCoordinates));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ data.Reset();
+
+ // Emit a started signal where actor is just at the camera's near plane
+ actor.SetProperty(Actor::Property::POSITION_Z, distance - nearPlane);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ application.ProcessEvent(GenerateSingleHover(PointState::STARTED, screenCoordinates));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ data.Reset();
+
+ // Emit a started signal where actor is closer than the camera's near plane
+ actor.SetProperty(Actor::Property::POSITION_Z, (distance - nearPlane) + 1.0f);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // When hover event leave outside of actor, the actor receive a Leave event
+ application.ProcessEvent(GenerateSingleHover(PointState::STARTED, screenCoordinates));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::LEAVE, data.hoverEvent.GetState(0), TEST_LOCATION);
+ data.Reset();
+
+ // Emit a started signal where actor is just at the camera's far plane
+ actor.SetProperty(Actor::Property::POSITION_Z, distance - farPlane);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ application.ProcessEvent(GenerateSingleHover(PointState::STARTED, screenCoordinates));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ data.Reset();
+
+ // Emit a started signal where actor is further than the camera's far plane
+ actor.SetProperty(Actor::Property::POSITION_Z, (distance - farPlane) - 1.0f);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // When hover event leave outside of actor, the actor receive a Leave event
+ application.ProcessEvent(GenerateSingleHover(PointState::STARTED, screenCoordinates));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::LEAVE, data.hoverEvent.GetState(0), TEST_LOCATION);
+ data.Reset();
+ END_TEST;
+}
+
+int UtcDaliGeoHoverEmitEmpty(void)
+{
+ TestApplication application;
+ application.GetScene().SetGeometryHittestEnabled(true);
+
+ try
+ {
+ // Emit an empty HoverEvent
+ Integration::HoverEvent event;
+ application.ProcessEvent(event);
+ tet_result(TET_FAIL);
+ }
+ catch(Dali::DaliException& e)
+ {
+ DALI_TEST_ASSERT(e, "!event.points.empty()", TEST_LOCATION);
+ }
+ END_TEST;
+}
+
+int UtcDaliGeoHoverInterrupted(void)
+{
+ TestApplication application;
+ application.GetScene().SetGeometryHittestEnabled(true);
+
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ application.GetScene().Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's hovered signal
+ SignalData data;
+ HoverEventFunctor functor(data);
+ actor.HoveredSignal().Connect(&application, functor);
+
+ // Emit a started signal
+ application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::STARTED, data.hoverEvent.GetState(0), TEST_LOCATION);
+ data.Reset();
+
+ // Emit an interrupted signal, we should be signalled regardless of whether there is a hit or not.
+ application.ProcessEvent(GenerateSingleHover(PointState::INTERRUPTED, Vector2(200.0f, 200.0f /* Outside actor */)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::INTERRUPTED, data.hoverEvent.GetState(0), TEST_LOCATION);
+ data.Reset();
+
+ // Emit another interrupted signal, our signal handler should not be called.
+ application.ProcessEvent(GenerateSingleHover(PointState::INTERRUPTED, Vector2(200.0f, 200.0f)));
+ DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+ END_TEST;
+}
+
+int UtcDaliGeoHoverParentConsumer(void)
+{
+ TestApplication application;
+ application.GetScene().SetGeometryHittestEnabled(true);
+ Actor rootActor(application.GetScene().GetRootLayer());
+
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ application.GetScene().Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's hovered signal
+ SignalData data;
+ HoverEventFunctor functor(data, false);
+ actor.HoveredSignal().Connect(&application, functor);
+
+ // Connect to root actor's hovered signal
+ SignalData rootData;
+ HoverEventFunctor rootFunctor(rootData); // Consumes signal
+ rootActor.HoveredSignal().Connect(&application, rootFunctor);
+
+ Vector2 screenCoordinates(10.0f, 10.0f);
+ Vector2 actorCoordinates, rootCoordinates;
+ actor.ScreenToLocal(actorCoordinates.x, actorCoordinates.y, screenCoordinates.x, screenCoordinates.y);
+ rootActor.ScreenToLocal(rootCoordinates.x, rootCoordinates.y, screenCoordinates.x, screenCoordinates.y);
+
+ // Emit a started signal
+ application.ProcessEvent(GenerateSingleHover(PointState::STARTED, screenCoordinates));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(true, rootData.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(1u, data.hoverEvent.GetPointCount(), TEST_LOCATION);
+ DALI_TEST_EQUALS(1u, rootData.hoverEvent.GetPointCount(), TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::STARTED, data.hoverEvent.GetState(0), TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::STARTED, rootData.hoverEvent.GetState(0), TEST_LOCATION);
+ DALI_TEST_EQUALS(screenCoordinates, data.hoverEvent.GetScreenPosition(0), TEST_LOCATION);
+ DALI_TEST_EQUALS(screenCoordinates, rootData.hoverEvent.GetScreenPosition(0), TEST_LOCATION);
+ DALI_TEST_EQUALS(actorCoordinates, data.hoverEvent.GetLocalPosition(0), 0.1f, TEST_LOCATION);
+ DALI_TEST_EQUALS(rootCoordinates, rootData.hoverEvent.GetLocalPosition(0), 0.1f, TEST_LOCATION);
+ DALI_TEST_CHECK(actor == data.hoverEvent.GetHitActor(0));
+ DALI_TEST_CHECK(actor == rootData.hoverEvent.GetHitActor(0));
+ data.Reset();
+ rootData.Reset();
+
+ // Emit a motion signal
+ screenCoordinates.x = screenCoordinates.y = 11.0f;
+ actor.ScreenToLocal(actorCoordinates.x, actorCoordinates.y, screenCoordinates.x, screenCoordinates.y);
+ rootActor.ScreenToLocal(rootCoordinates.x, rootCoordinates.y, screenCoordinates.x, screenCoordinates.y);
+ application.ProcessEvent(GenerateSingleHover(PointState::MOTION, screenCoordinates));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(true, rootData.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(1u, data.hoverEvent.GetPointCount(), TEST_LOCATION);
+ DALI_TEST_EQUALS(1u, rootData.hoverEvent.GetPointCount(), TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::MOTION, data.hoverEvent.GetState(0), TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::MOTION, rootData.hoverEvent.GetState(0), TEST_LOCATION);
+ DALI_TEST_EQUALS(screenCoordinates, data.hoverEvent.GetScreenPosition(0), TEST_LOCATION);
+ DALI_TEST_EQUALS(screenCoordinates, rootData.hoverEvent.GetScreenPosition(0), TEST_LOCATION);
+ DALI_TEST_EQUALS(actorCoordinates, data.hoverEvent.GetLocalPosition(0), 0.1f, TEST_LOCATION);
+ DALI_TEST_EQUALS(rootCoordinates, rootData.hoverEvent.GetLocalPosition(0), 0.1f, TEST_LOCATION);
+ DALI_TEST_CHECK(actor == data.hoverEvent.GetHitActor(0));
+ DALI_TEST_CHECK(actor == rootData.hoverEvent.GetHitActor(0));
+ data.Reset();
+ rootData.Reset();
+
+ // Emit a finished signal
+ screenCoordinates.x = screenCoordinates.y = 12.0f;
+ actor.ScreenToLocal(actorCoordinates.x, actorCoordinates.y, screenCoordinates.x, screenCoordinates.y);
+ rootActor.ScreenToLocal(rootCoordinates.x, rootCoordinates.y, screenCoordinates.x, screenCoordinates.y);
+ application.ProcessEvent(GenerateSingleHover(PointState::FINISHED, screenCoordinates));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(true, rootData.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(1u, data.hoverEvent.GetPointCount(), TEST_LOCATION);
+ DALI_TEST_EQUALS(1u, rootData.hoverEvent.GetPointCount(), TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::FINISHED, data.hoverEvent.GetState(0), TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::FINISHED, rootData.hoverEvent.GetState(0), TEST_LOCATION);
+ DALI_TEST_EQUALS(screenCoordinates, data.hoverEvent.GetScreenPosition(0), TEST_LOCATION);
+ DALI_TEST_EQUALS(screenCoordinates, rootData.hoverEvent.GetScreenPosition(0), TEST_LOCATION);
+ DALI_TEST_EQUALS(actorCoordinates, data.hoverEvent.GetLocalPosition(0), 0.1f, TEST_LOCATION);
+ DALI_TEST_EQUALS(rootCoordinates, rootData.hoverEvent.GetLocalPosition(0), 0.1f, TEST_LOCATION);
+ DALI_TEST_CHECK(actor == data.hoverEvent.GetHitActor(0));
+ DALI_TEST_CHECK(actor == rootData.hoverEvent.GetHitActor(0));
+ data.Reset();
+ rootData.Reset();
+
+ // Emit a started signal where the actor is not present, will hit the root actor though
+ screenCoordinates.x = screenCoordinates.y = 200.0f;
+ rootActor.ScreenToLocal(rootCoordinates.x, rootCoordinates.y, screenCoordinates.x, screenCoordinates.y);
+ application.ProcessEvent(GenerateSingleHover(PointState::STARTED, screenCoordinates));
+ DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(true, rootData.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(1u, rootData.hoverEvent.GetPointCount(), TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::STARTED, rootData.hoverEvent.GetState(0), TEST_LOCATION);
+ DALI_TEST_EQUALS(screenCoordinates, rootData.hoverEvent.GetScreenPosition(0), TEST_LOCATION);
+ DALI_TEST_EQUALS(rootCoordinates, rootData.hoverEvent.GetLocalPosition(0), 0.1f, TEST_LOCATION);
+ DALI_TEST_CHECK(rootActor == rootData.hoverEvent.GetHitActor(0));
+ END_TEST;
+}
+
+int UtcDaliGeoHoverInterruptedParentConsumer(void)
+{
+ TestApplication application;
+ application.GetScene().SetGeometryHittestEnabled(true);
+ Actor rootActor(application.GetScene().GetRootLayer());
+
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ application.GetScene().Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's hovered signal
+ SignalData data;
+ HoverEventFunctor functor(data, false);
+ actor.HoveredSignal().Connect(&application, functor);
+
+ // Connect to root actor's hovered signal
+ SignalData rootData;
+ HoverEventFunctor rootFunctor(rootData); // Consumes signal
+ rootActor.HoveredSignal().Connect(&application, rootFunctor);
+
+ // Emit a started signal
+ application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(true, rootData.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::STARTED, data.hoverEvent.GetState(0), TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::STARTED, rootData.hoverEvent.GetState(0), TEST_LOCATION);
+ DALI_TEST_CHECK(actor == data.hoverEvent.GetHitActor(0));
+ DALI_TEST_CHECK(actor == rootData.hoverEvent.GetHitActor(0));
+ data.Reset();
+ rootData.Reset();
+
+ // Emit an interrupted signal
+ application.ProcessEvent(GenerateSingleHover(PointState::INTERRUPTED, Vector2(200.0f, 200.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(true, rootData.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::INTERRUPTED, data.hoverEvent.GetState(0), TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::INTERRUPTED, rootData.hoverEvent.GetState(0), TEST_LOCATION);
+ DALI_TEST_CHECK(actor == data.hoverEvent.GetHitActor(0));
+ DALI_TEST_CHECK(actor == rootData.hoverEvent.GetHitActor(0));
+ data.Reset();
+ rootData.Reset();
+
+ // Emit another started signal
+ application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(true, rootData.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::STARTED, data.hoverEvent.GetState(0), TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::STARTED, rootData.hoverEvent.GetState(0), TEST_LOCATION);
+ data.Reset();
+ rootData.Reset();
+
+ // Remove actor from Stage
+ application.GetScene().Remove(actor);
+ data.Reset();
+ rootData.Reset();
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Emit an interrupted signal, only root actor's signal should be called.
+ application.ProcessEvent(GenerateSingleHover(PointState::INTERRUPTED, Vector2(200.0f, 200.0f /* Outside actor */)));
+ DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(true, rootData.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::INTERRUPTED, rootData.hoverEvent.GetState(0), TEST_LOCATION);
+ DALI_TEST_CHECK(rootActor == rootData.hoverEvent.GetHitActor(0));
+ data.Reset();
+ rootData.Reset();
+
+ // Emit another interrupted state, none of the signal's should be called.
+ application.ProcessEvent(GenerateSingleHover(PointState::INTERRUPTED, Vector2(200.0f, 200.0f)));
+ DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(false, rootData.functorCalled, TEST_LOCATION);
+ END_TEST;
+}
+
+int UtcDaliGeoHoverLeave(void)
+{
+ TestApplication application;
+ application.GetScene().SetGeometryHittestEnabled(true);
+
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ application.GetScene().Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's hovered signal
+ SignalData data;
+ HoverEventFunctor functor(data);
+ actor.HoveredSignal().Connect(&application, functor);
+
+ // Emit a started signal
+ application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::STARTED, data.hoverEvent.GetState(0), TEST_LOCATION);
+ data.Reset();
+
+ // Emit a motion signal outside of actor, should be signalled with a Leave
+ application.ProcessEvent(GenerateSingleHover(PointState::MOTION, Vector2(200.0f, 200.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::LEAVE, data.hoverEvent.GetState(0), TEST_LOCATION);
+ data.Reset();
+
+ // Another motion outside of actor, no signalling
+ application.ProcessEvent(GenerateSingleHover(PointState::MOTION, Vector2(201.0f, 201.0f)));
+ DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+ data.Reset();
+
+ // Another motion event inside actor, signalled with start. This is because a new hover event was started on that actor.
+ application.ProcessEvent(GenerateSingleHover(PointState::MOTION, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::STARTED, data.hoverEvent.GetState(0), TEST_LOCATION);
+ data.Reset();
+
+ END_TEST;
+}
+
+int UtcDaliGeoHoverLeaveParentConsumer(void)
+{
+ TestApplication application;
+ application.GetScene().SetGeometryHittestEnabled(true);
+ Actor rootActor(application.GetScene().GetRootLayer());
+
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ application.GetScene().Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's hovered signal
+ SignalData data;
+ HoverEventFunctor functor(data, false);
+ actor.HoveredSignal().Connect(&application, functor);
+
+ // Connect to root actor's hovered signal
+ SignalData rootData;
+ HoverEventFunctor rootFunctor(rootData); // Consumes signal
+ rootActor.HoveredSignal().Connect(&application, rootFunctor);
+
+ // Set actor to require leave events
+ actor.SetProperty(Actor::Property::LEAVE_REQUIRED, true);
+ rootActor.SetProperty(Actor::Property::LEAVE_REQUIRED, true);
+
+ // Emit a started signal
+ application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(true, rootData.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::STARTED, data.hoverEvent.GetState(0), TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::STARTED, rootData.hoverEvent.GetState(0), TEST_LOCATION);
+ DALI_TEST_CHECK(actor == data.hoverEvent.GetHitActor(0));
+ DALI_TEST_CHECK(actor == rootData.hoverEvent.GetHitActor(0));
+ data.Reset();
+ rootData.Reset();
+
+ // Emit a motion signal outside of actor, should be signalled with a Leave
+ application.ProcessEvent(GenerateSingleHover(PointState::MOTION, Vector2(200.0f, 200.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(true, rootData.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::LEAVE, data.hoverEvent.GetState(0), TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::MOTION, rootData.hoverEvent.GetState(0), TEST_LOCATION);
+ DALI_TEST_CHECK(actor == data.hoverEvent.GetHitActor(0));
+ DALI_TEST_CHECK(rootActor == rootData.hoverEvent.GetHitActor(0));
+ data.Reset();
+ rootData.Reset();
+
+ // Another motion outside of actor, only rootActor signalled
+ application.ProcessEvent(GenerateSingleHover(PointState::MOTION, Vector2(201.0f, 201.0f)));
+ DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(true, rootData.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::MOTION, rootData.hoverEvent.GetState(0), TEST_LOCATION);
+ DALI_TEST_CHECK(rootActor == rootData.hoverEvent.GetHitActor(0));
+ data.Reset();
+ rootData.Reset();
+
+ // Another motion event inside actor, signalled with start. This is because a new hover event was started on that actor.
+ application.ProcessEvent(GenerateSingleHover(PointState::MOTION, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(true, rootData.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::STARTED, data.hoverEvent.GetState(0), TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::MOTION, rootData.hoverEvent.GetState(0), TEST_LOCATION);
+ DALI_TEST_CHECK(actor == data.hoverEvent.GetHitActor(0));
+ DALI_TEST_CHECK(actor == rootData.hoverEvent.GetHitActor(0));
+ data.Reset();
+ rootData.Reset();
+
+ END_TEST;
+}
+
+int UtcDaliGeoHoverActorBecomesInsensitive(void)
+{
+ TestApplication application;
+ application.GetScene().SetGeometryHittestEnabled(true);
+
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ application.GetScene().Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's hovered signal
+ SignalData data;
+ HoverEventFunctor functor(data);
+ actor.HoveredSignal().Connect(&application, functor);
+
+ // Emit a started signal
+ application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::STARTED, data.hoverEvent.GetState(0), TEST_LOCATION);
+ data.Reset();
+
+ // Change actor to insensitive
+ actor.SetProperty(Actor::Property::SENSITIVE, false);
+
+ // Emit a motion signal, signalled with an interrupted
+ application.ProcessEvent(GenerateSingleHover(PointState::MOTION, Vector2(200.0f, 200.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::INTERRUPTED, data.hoverEvent.GetState(0), TEST_LOCATION);
+ data.Reset();
+ END_TEST;
+}
+
+int UtcDaliGeoHoverActorBecomesInsensitiveParentConsumer(void)
+{
+ TestApplication application;
+ application.GetScene().SetGeometryHittestEnabled(true);
+ Actor rootActor(application.GetScene().GetRootLayer());
+
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ application.GetScene().Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's hovered signal
+ SignalData data;
+ HoverEventFunctor functor(data, false);
+ actor.HoveredSignal().Connect(&application, functor);
+
+ // Connect to root actor's hovered signal
+ SignalData rootData;
+ HoverEventFunctor rootFunctor(rootData, false);
+ rootActor.HoveredSignal().Connect(&application, rootFunctor);
+
+ // Emit a started signal
+ application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(true, rootData.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::STARTED, data.hoverEvent.GetState(0), TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::STARTED, rootData.hoverEvent.GetState(0), TEST_LOCATION);
+ DALI_TEST_CHECK(actor == data.hoverEvent.GetHitActor(0));
+ DALI_TEST_CHECK(actor == rootData.hoverEvent.GetHitActor(0));
+ data.Reset();
+ rootData.Reset();
+
+ // Remove actor from Stage
+ application.GetScene().Remove(actor);
+
+ // Because it was removed, it gets interrupted.
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::INTERRUPTED, data.hoverEvent.GetState(0), TEST_LOCATION);
+ data.Reset();
+ rootData.Reset();
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Make root actor insensitive
+ rootActor.SetProperty(Actor::Property::SENSITIVE, false);
+
+ // Because it is insensitive, it does not receive the event.
+ application.ProcessEvent(GenerateSingleHover(PointState::MOTION, Vector2(200.0f, 200.0f)));
+ DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(false, rootData.functorCalled, TEST_LOCATION);
+ data.Reset();
+ rootData.Reset();
+
+ END_TEST;
+}
+
+int UtcDaliGeoHoverActorBecomesUserInteractionDisabled(void)
+{
+ TestApplication application;
+ application.GetScene().SetGeometryHittestEnabled(true);
+
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ application.GetScene().Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's hovered signal
+ SignalData data;
+ HoverEventFunctor functor(data);
+ actor.HoveredSignal().Connect(&application, functor);
+
+ // Emit a started signal
+ application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::STARTED, data.hoverEvent.GetState(0), TEST_LOCATION);
+ data.Reset();
+
+ // Change actor to disable user interaction.
+ actor.SetProperty(DevelActor::Property::USER_INTERACTION_ENABLED, false);
+
+ // Emit a motion signal, signalled with an interrupted
+ application.ProcessEvent(GenerateSingleHover(PointState::MOTION, Vector2(200.0f, 200.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::INTERRUPTED, data.hoverEvent.GetState(0), TEST_LOCATION);
+ data.Reset();
+ END_TEST;
+}
+
+int UtcDaliGeoHoverMultipleLayers(void)
+{
+ TestApplication application;
+ application.GetScene().SetGeometryHittestEnabled(true);
+ Actor rootActor(application.GetScene().GetRootLayer());
+
+ // Connect to actor's hovered signal
+ SignalData data;
+ HoverEventFunctor functor(data);
+
+ Layer layer1(Layer::New());
+ layer1.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ layer1.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ application.GetScene().Add(layer1);
+
+ Actor actor1(Actor::New());
+ actor1.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor1.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ actor1.SetProperty(Actor::Property::POSITION_Z, 1.0f); // Should hit actor1 in this layer
+ layer1.Add(actor1);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to layer1 and actor1
+ layer1.HoveredSignal().Connect(&application, functor);
+ actor1.HoveredSignal().Connect(&application, functor);
+
+ // Hit in hittable area, actor1 should be hit
+ application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_CHECK(data.hoveredActor == actor1);
+ data.Reset();
+
+ // Make layer1 insensitive, nothing should be hit
+ layer1.SetProperty(Actor::Property::SENSITIVE, false);
+ application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+ data.Reset();
+
+ // Make layer1 sensitive again, again actor1 will be hit
+ layer1.SetProperty(Actor::Property::SENSITIVE, true);
+ application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_CHECK(data.hoveredActor == actor1);
+ data.Reset();
+
+ // Make rootActor insensitive, nothing should be hit
+ rootActor.SetProperty(Actor::Property::SENSITIVE, false);
+ application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+ data.Reset();
+
+ // Make rootActor sensitive
+ rootActor.SetProperty(Actor::Property::SENSITIVE, true);
+
+ // Add another layer
+ Layer layer2(Layer::New());
+ layer2.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ layer2.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ layer2.SetProperty(Actor::Property::POSITION_Z, 10.0f); // Should hit layer2 in this layer rather than actor2
+ application.GetScene().Add(layer2);
+
+ Actor actor2(Actor::New());
+ actor2.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor2.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ layer2.Add(actor2);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to layer2 and actor2
+ layer2.HoveredSignal().Connect(&application, functor);
+ actor2.HoveredSignal().Connect(&application, functor);
+
+ // Emit an event, should hit layer2
+ application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ //DALI_TEST_CHECK( data.hoveredActor == layer2 ); // TODO: Uncomment this after removing renderable hack!
+ data.Reset();
+
+ // Make layer2 insensitive, should hit actor1
+ layer2.SetProperty(Actor::Property::SENSITIVE, false);
+ application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_CHECK(data.hoveredActor == actor1);
+ data.Reset();
+
+ // Make layer2 sensitive again, should hit layer2
+ layer2.SetProperty(Actor::Property::SENSITIVE, true);
+ application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ //DALI_TEST_CHECK( data.hoveredActor == layer2 ); // TODO: Uncomment this after removing renderable hack!
+ data.Reset();
+
+ // Make layer2 invisible, render and notify
+ layer2.SetProperty(Actor::Property::VISIBLE, false);
+ application.SendNotification();
+ application.Render();
+
+ // Should hit actor1
+ application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_CHECK(data.hoveredActor == actor1);
+ data.Reset();
+
+ // Make rootActor invisible, render and notify
+ rootActor.SetProperty(Actor::Property::VISIBLE, false);
+
+ // Because visible became false, we receive interrupted
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::INTERRUPTED, data.hoverEvent.GetState(0), TEST_LOCATION);
+ data.Reset();
+
+ application.SendNotification();
+ application.Render();
+
+ // Should not hit anything
+ application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+ data.Reset();
+ END_TEST;
+}
+
+int UtcDaliGeoHoverMultipleRenderTasks(void)
+{
+ TestApplication application;
+ application.GetScene().SetGeometryHittestEnabled(true);
+ Integration::Scene stage(application.GetScene());
+ Vector2 stageSize(stage.GetSize());
+
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ stage.Add(actor);
+
+ // Create render task
+ Viewport viewport(stageSize.width * 0.5f, stageSize.height * 0.5f, stageSize.width * 0.5f, stageSize.height * 0.5f);
+ RenderTask renderTask(application.GetScene().GetRenderTaskList().CreateTask());
+ renderTask.SetViewport(viewport);
+ renderTask.SetInputEnabled(true);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's hovered signal
+ SignalData data;
+ HoverEventFunctor functor(data);
+ actor.HoveredSignal().Connect(&application, functor);
+
+ // Emit a started signal
+ application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ data.Reset();
+
+ // Ensure renderTask actor can be hit too.
+ application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(viewport.x + 5.0f, viewport.y + 5.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ data.Reset();
+
+ // Disable input on renderTask, should not be hittable
+ renderTask.SetInputEnabled(false);
+ application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(viewport.x + 5.0f, viewport.y + 5.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::LEAVE, data.hoverEvent.GetState(0), TEST_LOCATION);
+ data.Reset();
+ END_TEST;
+}
+
+int UtcDaliGeoHoverMultipleRenderTasksWithChildLayer(void)
+{
+ TestApplication application;
+ application.GetScene().SetGeometryHittestEnabled(true);
+ Integration::Scene stage(application.GetScene());
+ Vector2 stageSize(stage.GetSize());
+
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ stage.Add(actor);
+
+ Layer layer = Layer::New();
+ layer.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ layer.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ actor.Add(layer);
+
+ // Create render task
+ Viewport viewport(stageSize.width * 0.5f, stageSize.height * 0.5f, stageSize.width * 0.5f, stageSize.height * 0.5f);
+ RenderTask renderTask(application.GetScene().GetRenderTaskList().CreateTask());
+ renderTask.SetViewport(viewport);
+ renderTask.SetInputEnabled(true);
+ renderTask.SetSourceActor(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to layer's hovered signal
+ SignalData data;
+ HoverEventFunctor functor(data);
+ actor.HoveredSignal().Connect(&application, functor);
+ layer.HoveredSignal().Connect(&application, functor);
+
+ // Emit a started signal
+ application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ data.Reset();
+
+ // Ensure renderTask actor can be hit too.
+ application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(viewport.x + 5.0f, viewport.y + 5.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ data.Reset();
+
+ // Disable input on renderTask, should not be hittable
+ renderTask.SetInputEnabled(false);
+ application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(viewport.x + 5.0f, viewport.y + 5.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::LEAVE, data.hoverEvent.GetState(0), TEST_LOCATION);
+ data.Reset();
+ END_TEST;
+}
+
+int UtcDaliGeoHoverOffscreenRenderTasks(void)
+{
+ TestApplication application;
+ application.GetScene().SetGeometryHittestEnabled(true);
+ Integration::Scene stage(application.GetScene());
+ Vector2 stageSize(stage.GetSize());
+
+ // FrameBufferImage for offscreen RenderTask
+ FrameBuffer frameBuffer = FrameBuffer::New(stageSize.width, stageSize.height);
+
+ // Create a renderable actor to display the FrameBufferImage
+ Actor renderableActor = CreateRenderableActor(frameBuffer.GetColorTexture());
+ renderableActor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+ renderableActor.SetProperty(Actor::Property::SIZE, Vector2(stageSize.x, stageSize.y));
+ renderableActor.ScaleBy(Vector3(1.0f, -1.0f, 1.0f)); // FIXME
+ stage.Add(renderableActor);
+
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ stage.Add(actor);
+ application.GetGlAbstraction().SetCheckFramebufferStatusResult(GL_FRAMEBUFFER_COMPLETE); // Ensure framebuffer connects
+
+ stage.GetRenderTaskList().GetTask(0u).SetScreenToFrameBufferFunction(RenderTask::FULLSCREEN_FRAMEBUFFER_FUNCTION);
+
+ // Create a RenderTask
+ RenderTask renderTask = stage.GetRenderTaskList().CreateTask();
+ renderTask.SetSourceActor(actor);
+ renderTask.SetFrameBuffer(frameBuffer);
+ renderTask.SetInputEnabled(true);
+
+ // Create another RenderTask
+ RenderTask renderTask2(stage.GetRenderTaskList().CreateTask());
+ renderTask2.SetInputEnabled(true);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's hovered signal
+ SignalData data;
+ HoverEventFunctor functor(data);
+ actor.HoveredSignal().Connect(&application, functor);
+
+ // Emit a started signal
+ application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ data.Reset();
+ END_TEST;
+}
+
+int UtcDaliGeoHoverMultipleRenderableActors(void)
+{
+ TestApplication application;
+ application.GetScene().SetGeometryHittestEnabled(true);
+ Integration::Scene stage(application.GetScene());
+ Vector2 stageSize(stage.GetSize());
+
+ Actor parent = CreateRenderableActor();
+ parent.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ parent.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ stage.Add(parent);
+
+ Actor actor = CreateRenderableActor();
+ actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ parent.Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to layer's hovered signal
+ SignalData data;
+ HoverEventFunctor functor(data);
+ parent.HoveredSignal().Connect(&application, functor);
+ actor.HoveredSignal().Connect(&application, functor);
+
+ // Emit a started signal
+ application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_CHECK(actor == data.hoveredActor);
+ END_TEST;
+}
+
+int UtcDaliGeoHoverActorRemovedInSignal(void)
+{
+ TestApplication application;
+ application.GetScene().SetGeometryHittestEnabled(true);
+
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ application.GetScene().Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's hovered signal
+ SignalData data;
+ RemoveActorFunctor functor(data);
+ actor.HoveredSignal().Connect(&application, functor);
+
+ // Register for leave events
+ actor.SetProperty(Actor::Property::LEAVE_REQUIRED, true);
+
+ // Emit a started signal
+ application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ data.Reset();
+
+ // Re-add, render and notify
+ application.GetScene().Add(actor);
+ application.SendNotification();
+ application.Render();
+
+ // Emit another signal outside of actor's area, should not get anything as the scene has changed.
+ application.ProcessEvent(GenerateSingleHover(PointState::MOTION, Vector2(210.0f, 210.0f)));
+ DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+ data.Reset();
+
+ // Emit a started signal
+ application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ data.Reset();
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Emit another signal outside of actor's area, should not get anything as the scene has changed.
+ application.ProcessEvent(GenerateSingleHover(PointState::MOTION, Vector2(210.0f, 210.0f)));
+ DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+ data.Reset();
+
+ // Re-add actor back to stage, render and notify
+ application.GetScene().Add(actor);
+ application.SendNotification();
+ application.Render();
+
+ // Emit another started event
+ application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ data.Reset();
+
+ // Completely delete the actor
+ actor.Reset();
+
+ // Emit event, should not crash and should not receive an event.
+ application.ProcessEvent(GenerateSingleHover(PointState::MOTION, Vector2(210.0f, 210.0f)));
+ DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+ END_TEST;
+}
+
+int UtcDaliGeoHoverActorSignalNotConsumed(void)
+{
+ TestApplication application;
+ application.GetScene().SetGeometryHittestEnabled(true);
+
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ application.GetScene().Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's hovered signal
+ SignalData data;
+ HoverEventFunctor functor(data, false);
+ actor.HoveredSignal().Connect(&application, functor);
+
+ // Emit a started signal
+ application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ END_TEST;
+}
+
+int UtcDaliGeoHoverActorUnStaged(void)
+{
+ TestApplication application;
+ application.GetScene().SetGeometryHittestEnabled(true);
+
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ application.GetScene().Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's hovered signal
+ SignalData data;
+ HoverEventFunctor functor(data);
+ actor.HoveredSignal().Connect(&application, functor);
+
+ // Emit a started signal
+ application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ data.Reset();
+
+ // Remove actor from stage
+ application.GetScene().Remove(actor);
+
+ // Interrupted is received because the actor receiving the event removed.
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::INTERRUPTED, data.hoverEvent.GetState(0), TEST_LOCATION);
+ data.Reset();
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Emit a move at the same point, we should not be signalled.
+ application.ProcessEvent(GenerateSingleHover(PointState::MOTION, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+ data.Reset();
+ END_TEST;
+}
+
+int UtcDaliGeoHoverLeaveActorReadded(void)
+{
+ TestApplication application;
+ application.GetScene().SetGeometryHittestEnabled(true);
+ Integration::Scene stage = application.GetScene();
+
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ stage.Add(actor);
+
+ // Set actor to receive hover-events
+ actor.SetProperty(Actor::Property::LEAVE_REQUIRED, true);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's hovered signal
+ SignalData data;
+ HoverEventFunctor functor(data);
+ actor.HoveredSignal().Connect(&application, functor);
+
+ // Emit a started and motion
+ application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
+ application.ProcessEvent(GenerateSingleHover(PointState::MOTION, Vector2(11.0f, 10.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ data.Reset();
+
+ // Remove actor from stage and add again
+ stage.Remove(actor);
+ stage.Add(actor);
+
+ // Emit a motion within the actor's bounds
+ application.ProcessEvent(GenerateSingleHover(PointState::MOTION, Vector2(12.0f, 10.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ data.Reset();
+
+ // Emit a motion outside the actor's bounds
+ application.ProcessEvent(GenerateSingleHover(PointState::MOTION, Vector2(200.0f, 200.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::LEAVE, data.hoverEvent.GetState(0), TEST_LOCATION);
+ data.Reset();
+
+ END_TEST;
+}
+
+int UtcDaliGeoHoverClippingActor(void)
+{
+ TestApplication application;
+ application.GetScene().SetGeometryHittestEnabled(true);
+ Integration::Scene stage = application.GetScene();
+
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ stage.Add(actor);
+
+ Actor clippingActor = Actor::New();
+ clippingActor.SetProperty(Actor::Property::SIZE, Vector2(50.0f, 50.0f));
+ clippingActor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ clippingActor.SetProperty(Actor::Property::CLIPPING_MODE, ClippingMode::CLIP_CHILDREN);
+ stage.Add(clippingActor);
+
+ // Add a child to the clipped region.
+ Actor clippingChild = Actor::New();
+ clippingChild.SetProperty(Actor::Property::SIZE, Vector2(50.0f, 50.0f));
+ clippingChild.SetProperty(Actor::Property::POSITION, Vector2(25.0f, 25.0f));
+ clippingChild.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ clippingActor.Add(clippingChild);
+
+ // Render and notify.
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's hovered signal.
+ SignalData data;
+ HoverEventFunctor functor(data);
+ actor.HoveredSignal().Connect(&application, functor);
+
+ // Emit an event within clipped area - we should have a hit.
+ application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ data.Reset();
+
+ // Emit an event outside the clipped area but within the actor area, we should have a hit.
+ application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(60.0f, 60.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ data.Reset();
+
+ clippingChild.HoveredSignal().Connect(&application, functor);
+
+ // Emit an event inside part of the child which is within the clipped area, we should have a hit.
+ application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(30.0f, 30.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ data.Reset();
+
+ END_TEST;
+}
+
+int UtcDaliGeoHoverActorHide(void)
+{
+ TestApplication application;
+ application.GetScene().SetGeometryHittestEnabled(true);
+ Integration::Scene stage = application.GetScene();
+
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ stage.Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's hovered signal
+ SignalData data;
+ HoverEventFunctor functor(data);
+ actor.HoveredSignal().Connect(&application, functor);
+
+ // Emit a started
+ application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ data.Reset();
+
+ actor.SetProperty(Actor::Property::VISIBLE, false);
+
+ // flush the queue and render once
+ application.SendNotification();
+ application.Render();
+
+ // Interrupted is received because the actor receiving the event hides.
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::INTERRUPTED, data.hoverEvent.GetState(0), TEST_LOCATION);
+ data.Reset();
+
+ END_TEST;
+}
--- /dev/null
+/*
+ * Copyright (c) 2023 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali-test-suite-utils.h>
+#include <dali/devel-api/actors/actor-devel.h>
+#include <dali/integration-api/events/touch-event-integ.h>
+#include <dali/integration-api/events/touch-integ.h>
+#include <dali/integration-api/render-task-list-integ.h>
+#include <dali/public-api/dali-core.h>
+#include <stdlib.h>
+
+#include <iostream>
+
+using namespace Dali;
+
+void utc_dali_geo_touch_processing_startup(void)
+{
+ test_return_value = TET_UNDEF;
+}
+
+void utc_dali_geo_touch_processing_cleanup(void)
+{
+ test_return_value = TET_PASS;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+namespace
+{
+struct TestPoint
+{
+ int32_t deviceId{-1};
+ PointState::Type state{PointState::FINISHED};
+ Actor hitActor;
+ Vector2 local;
+ Vector2 screen;
+ float radius{0};
+ Vector2 ellipseRadius;
+ float pressure{0};
+ Degree angle;
+ Device::Class::Type deviceClass{Device::Class::NONE};
+ Device::Subclass::Type deviceSubclass{Device::Subclass::NONE};
+
+ TestPoint() = default;
+ static const TestPoint ZERO;
+};
+
+const TestPoint TestPoint::ZERO;
+
+// Stores data that is populated in the callback and will be read by the TET cases
+struct SignalData
+{
+ SignalData()
+ : functorCalled(false),
+ receivedTouch(),
+ touchedActor()
+ {
+ }
+
+ struct TestTouchEvent
+ {
+ unsigned long time;
+ std::vector<TestPoint> points;
+
+ const TestPoint& GetPoint(size_t i)
+ {
+ if(i < points.size())
+ {
+ return points[i];
+ }
+ return TestPoint::ZERO;
+ }
+ size_t GetPointCount()
+ {
+ return points.size();
+ }
+ };
+
+ void Reset()
+ {
+ functorCalled = false;
+
+ receivedTouch.time = 0u;
+ receivedTouch.points.clear();
+
+ touchedActor.Reset();
+ }
+
+ bool functorCalled;
+ TestTouchEvent receivedTouch;
+ Actor touchedActor;
+};
+
+// Functor that sets the data when called
+struct TouchEventFunctor
+{
+ /**
+ * Constructor.
+ * @param[in] data Reference to the data to store callback information.
+ * @param[in] returnValue What the functor should return.
+ */
+ TouchEventFunctor(SignalData& data, bool returnValue = true)
+ : signalData(data),
+ returnValue(returnValue)
+ {
+ }
+
+ bool operator()(Actor actor, const TouchEvent& touch)
+ {
+ signalData.functorCalled = true;
+ signalData.touchedActor = actor;
+
+ signalData.receivedTouch.time = touch.GetTime();
+ signalData.receivedTouch.points.clear();
+
+ for(size_t i = 0; i < touch.GetPointCount(); ++i)
+ {
+ TestPoint p;
+ p.deviceId = touch.GetDeviceId(i);
+ p.state = touch.GetState(i);
+ p.hitActor = touch.GetHitActor(i);
+ p.local = touch.GetLocalPosition(i);
+ p.screen = touch.GetScreenPosition(i);
+ p.radius = touch.GetRadius(i);
+ p.ellipseRadius = touch.GetEllipseRadius(i);
+ p.pressure = touch.GetPressure(i);
+ p.angle = touch.GetAngle(i);
+ p.deviceClass = touch.GetDeviceClass(i);
+ p.deviceSubclass = touch.GetDeviceSubclass(i);
+ signalData.receivedTouch.points.push_back(p);
+ }
+
+ return returnValue;
+ }
+
+ SignalData& signalData;
+ bool returnValue;
+};
+
+struct HandleData
+{
+ bool signalReceived;
+ TouchEvent receivedTouchHandle;
+
+ HandleData()
+ : signalReceived(false)
+ {
+ }
+};
+
+struct TouchEventHandleFunctor
+{
+ /**
+ * Constructor.
+ * @param[in] data Reference to the data to store callback information.
+ * @param[in] returnValue What the functor should return.
+ */
+ TouchEventHandleFunctor(HandleData& handleData, bool returnValue = true)
+ : handleData(handleData),
+ returnValue(returnValue)
+ {
+ }
+
+ bool operator()(Actor actor, const TouchEvent& someTouchEvent)
+ {
+ handleData.signalReceived = true;
+ handleData.receivedTouchHandle = someTouchEvent;
+ return returnValue;
+ }
+
+ HandleData& handleData;
+ bool returnValue;
+};
+
+// Functor that removes the actor when called.
+struct RemoveActorFunctor : public TouchEventFunctor
+{
+ /**
+ * Constructor.
+ * @param[in] data Reference to the data to store callback information.
+ * @param[in] returnValue What the functor should return.
+ */
+ RemoveActorFunctor(SignalData& data, bool returnValue = true)
+ : TouchEventFunctor(data, returnValue)
+ {
+ }
+
+ bool operator()(Actor actor, const TouchEvent& touch)
+ {
+ Actor parent(actor.GetParent());
+ if(parent)
+ {
+ parent.Remove(actor);
+ }
+
+ return TouchEventFunctor::operator()(actor, touch);
+ }
+};
+
+struct OutOfBoundsData
+{
+ TestPoint point;
+ bool functorCalled;
+
+ OutOfBoundsData()
+ : functorCalled(false)
+ {
+ }
+};
+
+// Functor that reads out of bounds data when called
+struct OutOfBoundsFunctor
+{
+ /**
+ * Constructor.
+ * @param[in] data Reference to the data to store callback information.
+ * @param[in] returnValue What the functor should return.
+ */
+ OutOfBoundsFunctor(OutOfBoundsData& data, bool returnValue = true)
+ : outOfBoundsData(data),
+ returnValue(returnValue)
+ {
+ }
+
+ bool operator()(Actor actor, const TouchEvent& touch)
+ {
+ outOfBoundsData.functorCalled = true;
+ size_t count = touch.GetPointCount();
+
+ // Read out of bounds data
+ outOfBoundsData.point.deviceId = touch.GetDeviceId(count + 1);
+ outOfBoundsData.point.state = touch.GetState(count + 1);
+ outOfBoundsData.point.hitActor = touch.GetHitActor(count + 1);
+ outOfBoundsData.point.local = touch.GetLocalPosition(count + 1);
+ outOfBoundsData.point.screen = touch.GetScreenPosition(count + 1);
+
+ return returnValue;
+ }
+
+ OutOfBoundsData& outOfBoundsData;
+ bool returnValue;
+};
+
+Integration::TouchEvent GenerateSingleTouch(PointState::Type state, const Vector2& screenPosition)
+{
+ Integration::TouchEvent touchEvent;
+ Integration::Point point;
+ point.SetState(state);
+ point.SetScreenPosition(screenPosition);
+ point.SetDeviceClass(Device::Class::TOUCH);
+ point.SetDeviceSubclass(Device::Subclass::NONE);
+ touchEvent.points.push_back(point);
+ return touchEvent;
+}
+
+} // namespace
+
+///////////////////////////////////////////////////////////////////////////////
+
+int UtcDaliGeoTouchEventNormalProcessing01(void)
+{
+ TestApplication application;
+
+ application.GetScene().SetGeometryHittestEnabled(true);
+
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ application.GetScene().Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's touch signal
+ SignalData data;
+ TouchEventFunctor functor(data);
+ actor.TouchedSignal().Connect(&application, functor);
+
+ Vector2 screenCoordinates(10.0f, 10.0f);
+ Vector2 localCoordinates;
+ actor.ScreenToLocal(localCoordinates.x, localCoordinates.y, screenCoordinates.x, screenCoordinates.y);
+
+ // Emit a down signal
+ application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, screenCoordinates));
+ const TestPoint* point1 = &data.receivedTouch.GetPoint(0);
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(1u, data.receivedTouch.GetPointCount(), TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::DOWN, point1->state, TEST_LOCATION);
+ DALI_TEST_EQUALS(screenCoordinates, point1->screen, TEST_LOCATION);
+ DALI_TEST_EQUALS(localCoordinates, point1->local, 0.1f, TEST_LOCATION);
+ data.Reset();
+
+ // Emit a motion signal
+ screenCoordinates.x = screenCoordinates.y = 11.0f;
+ actor.ScreenToLocal(localCoordinates.x, localCoordinates.y, screenCoordinates.x, screenCoordinates.y);
+ application.ProcessEvent(GenerateSingleTouch(PointState::MOTION, screenCoordinates));
+ const TestPoint* point2 = &data.receivedTouch.GetPoint(0);
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(1u, data.receivedTouch.GetPointCount(), TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::MOTION, point2->state, TEST_LOCATION);
+ DALI_TEST_EQUALS(screenCoordinates, point2->screen, TEST_LOCATION);
+ DALI_TEST_EQUALS(localCoordinates, point2->local, 0.1f, TEST_LOCATION);
+ data.Reset();
+
+ // Emit an up signal
+ screenCoordinates.x = screenCoordinates.y = 12.0f;
+ actor.ScreenToLocal(localCoordinates.x, localCoordinates.y, screenCoordinates.x, screenCoordinates.y);
+ application.ProcessEvent(GenerateSingleTouch(PointState::UP, screenCoordinates));
+ const TestPoint* point3 = &data.receivedTouch.GetPoint(0);
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(1u, data.receivedTouch.GetPointCount(), TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::UP, point3->state, TEST_LOCATION);
+ DALI_TEST_EQUALS(screenCoordinates, point3->screen, TEST_LOCATION);
+ DALI_TEST_EQUALS(localCoordinates, point3->local, 0.1f, TEST_LOCATION);
+ data.Reset();
+
+ // Emit a down signal where the actor is not present
+ screenCoordinates.x = screenCoordinates.y = 200.0f;
+ application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, screenCoordinates));
+ DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+ END_TEST;
+}
+
+int UtcDaliGeoTouchEventNormalProcessing02(void)
+{
+ TestApplication application;
+
+ application.GetScene().SetGeometryHittestEnabled(true);
+
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ application.GetScene().Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's touched signal
+ HandleData handleData;
+ TouchEventHandleFunctor functor(handleData);
+ actor.TouchedSignal().Connect(&application, functor);
+
+ Vector2 screenCoordinates(10.0f, 10.0f);
+ Vector2 localCoordinates;
+ actor.ScreenToLocal(localCoordinates.x, localCoordinates.y, screenCoordinates.x, screenCoordinates.y);
+
+ // Emit a down signal
+ application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, screenCoordinates));
+ DALI_TEST_EQUALS(true, handleData.signalReceived, TEST_LOCATION);
+ DALI_TEST_EQUALS(1u, handleData.receivedTouchHandle.GetPointCount(), TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::DOWN, handleData.receivedTouchHandle.GetState(0), TEST_LOCATION);
+ DALI_TEST_EQUALS(screenCoordinates, handleData.receivedTouchHandle.GetScreenPosition(0), TEST_LOCATION);
+ DALI_TEST_EQUALS(localCoordinates, handleData.receivedTouchHandle.GetLocalPosition(0), 0.1f, TEST_LOCATION);
+
+ END_TEST;
+}
+
+int UtcDaliGeoTouchEventAPINegative(void)
+{
+ TestApplication application;
+
+ application.GetScene().SetGeometryHittestEnabled(true);
+
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ application.GetScene().Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's touched signal
+ OutOfBoundsData data;
+ OutOfBoundsFunctor functor(data, true);
+ actor.TouchedSignal().Connect(&application, functor);
+
+ Vector2 screenCoordinates(10.0f, 10.0f);
+ Vector2 localCoordinates;
+ actor.ScreenToLocal(localCoordinates.x, localCoordinates.y, screenCoordinates.x, screenCoordinates.y);
+
+ // Emit a down signal
+ application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, screenCoordinates));
+
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(-1, data.point.deviceId, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::FINISHED, data.point.state, TEST_LOCATION);
+ DALI_TEST_EQUALS(Vector2::ZERO, data.point.screen, TEST_LOCATION);
+ DALI_TEST_EQUALS(Vector2::ZERO, data.point.local, 0.1f, TEST_LOCATION);
+ DALI_TEST_CHECK(!data.point.hitActor);
+
+ END_TEST;
+}
+
+int UtcDaliGeoTouchEventOutsideCameraNearFarPlanes(void)
+{
+ TestApplication application;
+
+ application.GetScene().SetGeometryHittestEnabled(true);
+
+ Integration::Scene scene = application.GetScene();
+ Vector2 sceneSize = scene.GetSize();
+
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ actor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+ scene.Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Get the camera's near and far planes
+ RenderTaskList taskList = scene.GetRenderTaskList();
+ Dali::RenderTask task = taskList.GetTask(0);
+ CameraActor camera = task.GetCameraActor();
+ float nearPlane = camera.GetNearClippingPlane();
+ float farPlane = camera.GetFarClippingPlane();
+
+ // Calculate the current distance of the actor from the camera
+ float tanHalfFov = tanf(camera.GetFieldOfView() * 0.5f);
+ float distance = (sceneSize.y * 0.5f) / tanHalfFov;
+
+ // Connect to actor's touched signal
+ SignalData data;
+ TouchEventFunctor functor(data);
+ actor.TouchedSignal().Connect(&application, functor);
+
+ Vector2 screenCoordinates(sceneSize.x * 0.5f, sceneSize.y * 0.5f);
+
+ // Emit a down signal
+ application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, screenCoordinates));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ application.ProcessEvent(GenerateSingleTouch(PointState::UP, screenCoordinates));
+ data.Reset();
+
+ // Emit a down signal where actor is just at the camera's near plane
+ actor.SetProperty(Actor::Property::POSITION_Z, distance - nearPlane);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, screenCoordinates));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ application.ProcessEvent(GenerateSingleTouch(PointState::UP, screenCoordinates));
+ data.Reset();
+
+ // Emit a down signal where actor is closer than the camera's near plane
+ actor.SetProperty(Actor::Property::POSITION_Z, (distance - nearPlane) + 1.0f);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, screenCoordinates));
+ DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+ application.ProcessEvent(GenerateSingleTouch(PointState::UP, screenCoordinates));
+ data.Reset();
+
+ // Emit a down signal where actor is just at the camera's far plane
+ actor.SetProperty(Actor::Property::POSITION_Z, distance - farPlane);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, screenCoordinates));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ application.ProcessEvent(GenerateSingleTouch(PointState::UP, screenCoordinates));
+ data.Reset();
+
+ // Emit a down signal where actor is further than the camera's far plane
+ actor.SetProperty(Actor::Property::POSITION_Z, (distance - farPlane) - 1.0f);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, screenCoordinates));
+ DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+ application.ProcessEvent(GenerateSingleTouch(PointState::UP, screenCoordinates));
+ data.Reset();
+ END_TEST;
+}
+
+int UtcDaliGeoTouchEventEmitEmpty(void)
+{
+ TestApplication application;
+
+ application.GetScene().SetGeometryHittestEnabled(true);
+
+ try
+ {
+ // Emit an empty TouchEvent
+ Integration::TouchEvent event;
+ application.ProcessEvent(event);
+ tet_result(TET_FAIL);
+ }
+ catch(Dali::DaliException& e)
+ {
+ DALI_TEST_ASSERT(e, "!event.points.empty()", TEST_LOCATION);
+ }
+ END_TEST;
+}
+
+int UtcDaliGeoTouchEventInterrupted(void)
+{
+ TestApplication application;
+
+ application.GetScene().SetGeometryHittestEnabled(true);
+
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ application.GetScene().Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's touched signal
+ SignalData data;
+ TouchEventFunctor functor(data);
+ actor.TouchedSignal().Connect(&application, functor);
+
+ // Emit a down signal
+ application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::DOWN, data.receivedTouch.points[0].state, TEST_LOCATION);
+ data.Reset();
+
+ // Emit an interrupted signal, we should be signalled regardless of whether there is a hit or not.
+ application.ProcessEvent(GenerateSingleTouch(PointState::INTERRUPTED, Vector2(200.0f, 200.0f /* Outside actor */)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::INTERRUPTED, data.receivedTouch.points[0].state, TEST_LOCATION);
+ data.Reset();
+
+ // Emit another interrupted signal, our signal handler should not be called.
+ application.ProcessEvent(GenerateSingleTouch(PointState::INTERRUPTED, Vector2(200.0f, 200.0f)));
+ DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+ END_TEST;
+}
+
+int UtcDaliGeoTouchEventParentConsumer(void)
+{
+ TestApplication application;
+
+ application.GetScene().SetGeometryHittestEnabled(true);
+
+ Actor rootActor(application.GetScene().GetRootLayer());
+
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ application.GetScene().Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's touched signal
+ SignalData data;
+ TouchEventFunctor functor(data, false);
+ actor.TouchedSignal().Connect(&application, functor);
+
+ // Connect to root actor's touched signal
+ SignalData rootData;
+ TouchEventFunctor rootFunctor(rootData); // Consumes signal
+ rootActor.TouchedSignal().Connect(&application, rootFunctor);
+
+ Vector2 screenCoordinates(10.0f, 10.0f);
+ Vector2 actorCoordinates, rootCoordinates;
+ actor.ScreenToLocal(actorCoordinates.x, actorCoordinates.y, screenCoordinates.x, screenCoordinates.y);
+ rootActor.ScreenToLocal(rootCoordinates.x, rootCoordinates.y, screenCoordinates.x, screenCoordinates.y);
+
+ // Emit a down signal
+ application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, screenCoordinates));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(true, rootData.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(1u, data.receivedTouch.GetPointCount(), TEST_LOCATION);
+ DALI_TEST_EQUALS(1u, rootData.receivedTouch.GetPointCount(), TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::DOWN, data.receivedTouch.points[0].state, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::DOWN, rootData.receivedTouch.points[0].state, TEST_LOCATION);
+ DALI_TEST_EQUALS(screenCoordinates, data.receivedTouch.points[0].screen, TEST_LOCATION);
+ DALI_TEST_EQUALS(screenCoordinates, rootData.receivedTouch.points[0].screen, TEST_LOCATION);
+ DALI_TEST_EQUALS(actorCoordinates, data.receivedTouch.points[0].local, 0.1f, TEST_LOCATION);
+ DALI_TEST_EQUALS(rootCoordinates, rootData.receivedTouch.points[0].local, 0.1f, TEST_LOCATION);
+ DALI_TEST_CHECK(actor == data.receivedTouch.points[0].hitActor);
+ DALI_TEST_CHECK(actor == rootData.receivedTouch.points[0].hitActor);
+ data.Reset();
+ rootData.Reset();
+
+ // Emit a motion signal
+ screenCoordinates.x = screenCoordinates.y = 11.0f;
+ actor.ScreenToLocal(actorCoordinates.x, actorCoordinates.y, screenCoordinates.x, screenCoordinates.y);
+ rootActor.ScreenToLocal(rootCoordinates.x, rootCoordinates.y, screenCoordinates.x, screenCoordinates.y);
+ application.ProcessEvent(GenerateSingleTouch(PointState::MOTION, screenCoordinates));
+ DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(true, rootData.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(1u, rootData.receivedTouch.GetPointCount(), TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::MOTION, rootData.receivedTouch.points[0].state, TEST_LOCATION);
+ DALI_TEST_EQUALS(screenCoordinates, rootData.receivedTouch.points[0].screen, TEST_LOCATION);
+ DALI_TEST_EQUALS(rootCoordinates, rootData.receivedTouch.points[0].local, 0.1f, TEST_LOCATION);
+ DALI_TEST_CHECK(rootActor == rootData.receivedTouch.points[0].hitActor);
+ data.Reset();
+ rootData.Reset();
+
+ // Emit an up signal
+ screenCoordinates.x = screenCoordinates.y = 12.0f;
+ actor.ScreenToLocal(actorCoordinates.x, actorCoordinates.y, screenCoordinates.x, screenCoordinates.y);
+ rootActor.ScreenToLocal(rootCoordinates.x, rootCoordinates.y, screenCoordinates.x, screenCoordinates.y);
+ application.ProcessEvent(GenerateSingleTouch(PointState::UP, screenCoordinates));
+ DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(true, rootData.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(1u, rootData.receivedTouch.GetPointCount(), TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::UP, rootData.receivedTouch.points[0].state, TEST_LOCATION);
+ DALI_TEST_EQUALS(screenCoordinates, rootData.receivedTouch.points[0].screen, TEST_LOCATION);
+ DALI_TEST_EQUALS(rootCoordinates, rootData.receivedTouch.points[0].local, 0.1f, TEST_LOCATION);
+ DALI_TEST_CHECK(rootActor == rootData.receivedTouch.points[0].hitActor);
+ data.Reset();
+ rootData.Reset();
+
+ // Emit a down signal where the actor is not present, will hit the root actor though
+ screenCoordinates.x = screenCoordinates.y = 200.0f;
+ rootActor.ScreenToLocal(rootCoordinates.x, rootCoordinates.y, screenCoordinates.x, screenCoordinates.y);
+ application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, screenCoordinates));
+ DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(true, rootData.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(1u, rootData.receivedTouch.GetPointCount(), TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::DOWN, rootData.receivedTouch.points[0].state, TEST_LOCATION);
+ DALI_TEST_EQUALS(screenCoordinates, rootData.receivedTouch.points[0].screen, TEST_LOCATION);
+ DALI_TEST_EQUALS(rootCoordinates, rootData.receivedTouch.points[0].local, 0.1f, TEST_LOCATION);
+ DALI_TEST_CHECK(rootActor == rootData.receivedTouch.points[0].hitActor);
+ END_TEST;
+}
+
+int UtcDaliGeoTouchEventInterruptedParentConsumer(void)
+{
+ TestApplication application;
+
+ application.GetScene().SetGeometryHittestEnabled(true);
+
+ Actor rootActor(application.GetScene().GetRootLayer());
+
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ application.GetScene().Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's touched signal
+ SignalData data;
+ TouchEventFunctor functor(data, false);
+ actor.TouchedSignal().Connect(&application, functor);
+
+ // Connect to root actor's touched signal
+ SignalData rootData;
+ TouchEventFunctor rootFunctor(rootData); // Consumes signal
+ rootActor.TouchedSignal().Connect(&application, rootFunctor);
+
+ // Emit a down signal
+ application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(true, rootData.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::DOWN, data.receivedTouch.points[0].state, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::DOWN, rootData.receivedTouch.points[0].state, TEST_LOCATION);
+ DALI_TEST_CHECK(actor == data.receivedTouch.points[0].hitActor);
+ DALI_TEST_CHECK(actor == rootData.receivedTouch.points[0].hitActor);
+ data.Reset();
+ rootData.Reset();
+
+ // Emit an interrupted signal
+ application.ProcessEvent(GenerateSingleTouch(PointState::INTERRUPTED, Vector2(200.0f, 200.0f)));
+ DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(true, rootData.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::INTERRUPTED, rootData.receivedTouch.points[0].state, TEST_LOCATION);
+ DALI_TEST_CHECK(rootActor == rootData.receivedTouch.points[0].hitActor);
+ data.Reset();
+ rootData.Reset();
+
+ // Emit another down signal
+ application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(true, rootData.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::DOWN, data.receivedTouch.points[0].state, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::DOWN, rootData.receivedTouch.points[0].state, TEST_LOCATION);
+ data.Reset();
+ rootData.Reset();
+
+ // Remove actor from scene
+ application.GetScene().Remove(actor);
+ data.Reset();
+ rootData.Reset();
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Emit an interrupted signal, only root actor's signal should be called.
+ application.ProcessEvent(GenerateSingleTouch(PointState::INTERRUPTED, Vector2(200.0f, 200.0f /* Outside actor */)));
+ DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(true, rootData.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::INTERRUPTED, rootData.receivedTouch.points[0].state, TEST_LOCATION);
+ DALI_TEST_CHECK(rootActor == rootData.receivedTouch.points[0].hitActor);
+ data.Reset();
+ rootData.Reset();
+
+ // Emit another interrupted state, none of the signal's should be called.
+ application.ProcessEvent(GenerateSingleTouch(PointState::INTERRUPTED, Vector2(200.0f, 200.0f)));
+ DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(false, rootData.functorCalled, TEST_LOCATION);
+ END_TEST;
+}
+
+int UtcDaliGeoTouchEventActorBecomesInsensitive(void)
+{
+ TestApplication application;
+
+ application.GetScene().SetGeometryHittestEnabled(true);
+
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ application.GetScene().Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's touched signal
+ SignalData data;
+ TouchEventFunctor functor(data);
+ actor.TouchedSignal().Connect(&application, functor);
+
+ // Emit a down signal
+ application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::DOWN, data.receivedTouch.points[0].state, TEST_LOCATION);
+ data.Reset();
+
+ // Change actor to insensitive
+ actor.SetProperty(Actor::Property::SENSITIVE, false);
+
+ // Emit a motion signal, signalled with an interrupted
+ application.ProcessEvent(GenerateSingleTouch(PointState::MOTION, Vector2(200.0f, 200.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::INTERRUPTED, data.receivedTouch.points[0].state, TEST_LOCATION);
+ data.Reset();
+ END_TEST;
+}
+
+int UtcDaliGeoTouchEventActorBecomesInsensitiveParentConsumer(void)
+{
+ TestApplication application;
+
+ application.GetScene().SetGeometryHittestEnabled(true);
+
+ Actor rootActor(application.GetScene().GetRootLayer());
+
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ application.GetScene().Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's touched signal
+ SignalData data;
+ TouchEventFunctor functor(data, false);
+ actor.TouchedSignal().Connect(&application, functor);
+
+ // Connect to root actor's touched signal
+ SignalData rootData;
+ TouchEventFunctor rootFunctor(rootData); // Consumes signal
+ rootActor.TouchedSignal().Connect(&application, rootFunctor);
+
+ // Emit a down signal
+ application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(true, rootData.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::DOWN, data.receivedTouch.points[0].state, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::DOWN, rootData.receivedTouch.points[0].state, TEST_LOCATION);
+ DALI_TEST_CHECK(actor == data.receivedTouch.points[0].hitActor);
+ DALI_TEST_CHECK(actor == rootData.receivedTouch.points[0].hitActor);
+ data.Reset();
+ rootData.Reset();
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Make root actor insensitive
+ rootActor.SetProperty(Actor::Property::SENSITIVE, false);
+
+ // Emit a motion signal, signalled with an interrupted (should get interrupted even if within root actor)
+ application.ProcessEvent(GenerateSingleTouch(PointState::MOTION, Vector2(200.0f, 200.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::INTERRUPTED, data.receivedTouch.points[0].state, TEST_LOCATION);
+ DALI_TEST_EQUALS(true, rootData.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::INTERRUPTED, rootData.receivedTouch.points[0].state, TEST_LOCATION);
+ END_TEST;
+}
+
+int UtcDaliGeoTouchEventActorBecomesUserInteractionDisabled(void)
+{
+ TestApplication application;
+
+ application.GetScene().SetGeometryHittestEnabled(true);
+
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ application.GetScene().Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's touched signal
+ SignalData data;
+ TouchEventFunctor functor(data);
+ actor.TouchedSignal().Connect(&application, functor);
+
+ // Emit a down signal
+ application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::DOWN, data.receivedTouch.points[0].state, TEST_LOCATION);
+ data.Reset();
+
+ // Change actor to disable user interaction.
+ actor.SetProperty(DevelActor::Property::USER_INTERACTION_ENABLED, false);
+
+ // Emit a motion signal, signalled with an interrupted
+ application.ProcessEvent(GenerateSingleTouch(PointState::MOTION, Vector2(200.0f, 200.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::INTERRUPTED, data.receivedTouch.points[0].state, TEST_LOCATION);
+ data.Reset();
+ END_TEST;
+}
+
+int UtcDaliGeoTouchEventMultipleLayers(void)
+{
+ TestApplication application;
+
+ application.GetScene().SetGeometryHittestEnabled(true);
+
+ Actor rootActor(application.GetScene().GetRootLayer());
+
+ // Connect to actor's touched signal
+ SignalData data;
+ TouchEventFunctor functor(data);
+
+ Layer layer1(Layer::New());
+ layer1.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ layer1.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ application.GetScene().Add(layer1);
+
+ Actor actor1(Actor::New());
+ actor1.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor1.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ actor1.SetProperty(Actor::Property::POSITION_Z, 1.0f); // Should hit actor1 in this layer
+ layer1.Add(actor1);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to layer1 and actor1
+ layer1.TouchedSignal().Connect(&application, functor);
+ actor1.TouchedSignal().Connect(&application, functor);
+
+ // Hit in hittable area, actor1 should be hit
+ application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_CHECK(data.touchedActor == actor1);
+ application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(10.0f, 10.0f)));
+ data.Reset();
+
+ // Make layer1 insensitive, nothing should be hit
+ layer1.SetProperty(Actor::Property::SENSITIVE, false);
+ application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+ application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(10.0f, 10.0f)));
+ data.Reset();
+
+ // Make layer1 sensitive again, again actor1 will be hit
+ layer1.SetProperty(Actor::Property::SENSITIVE, true);
+ application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_CHECK(data.touchedActor == actor1);
+ application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(10.0f, 10.0f)));
+ data.Reset();
+
+ // Make rootActor insensitive, nothing should be hit
+ rootActor.SetProperty(Actor::Property::SENSITIVE, false);
+ application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+ application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(10.0f, 10.0f)));
+ data.Reset();
+
+ // Make rootActor sensitive
+ rootActor.SetProperty(Actor::Property::SENSITIVE, true);
+
+ // Add another layer
+ Layer layer2(Layer::New());
+ layer2.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ layer2.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ layer2.SetProperty(Actor::Property::POSITION_Z, 10.0f); // Should hit layer2 in this layer rather than actor2
+ application.GetScene().Add(layer2);
+
+ Actor actor2(Actor::New());
+ actor2.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor2.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ layer2.Add(actor2);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to layer2 and actor2
+ layer2.TouchedSignal().Connect(&application, functor);
+ actor2.TouchedSignal().Connect(&application, functor);
+
+ // Emit an event, should hit layer2
+ application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ //DALI_TEST_CHECK( data.touchedActor == layer2 ); // TODO: Uncomment this after removing renderable hack!
+ application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(10.0f, 10.0f)));
+ data.Reset();
+
+ // Make layer2 insensitive, should hit actor1
+ layer2.SetProperty(Actor::Property::SENSITIVE, false);
+ application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_CHECK(data.touchedActor == actor1);
+ application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(10.0f, 10.0f)));
+ data.Reset();
+
+ // Make layer2 sensitive again, should hit layer2
+ layer2.SetProperty(Actor::Property::SENSITIVE, true);
+ application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ //DALI_TEST_CHECK( data.touchedActor == layer2 ); // TODO: Uncomment this after removing renderable hack!
+ application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(10.0f, 10.0f)));
+ data.Reset();
+
+ // Make layer2 invisible, render and notify
+ layer2.SetProperty(Actor::Property::VISIBLE, false);
+ application.SendNotification();
+ application.Render();
+
+ // Should hit actor1
+ application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_CHECK(data.touchedActor == actor1);
+ application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(10.0f, 10.0f)));
+ data.Reset();
+
+ // Make rootActor invisible, render and notify
+ rootActor.SetProperty(Actor::Property::VISIBLE, false);
+ application.SendNotification();
+ application.Render();
+
+ // Should not hit anything
+ application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+ application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(10.0f, 10.0f)));
+ data.Reset();
+ END_TEST;
+}
+
+int UtcDaliGeoTouchEventMultipleRenderTasks(void)
+{
+ TestApplication application;
+
+ application.GetScene().SetGeometryHittestEnabled(true);
+
+
+ Integration::Scene scene(application.GetScene());
+ Vector2 sceneSize(scene.GetSize());
+
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ scene.Add(actor);
+
+ // Create render task
+ Viewport viewport(sceneSize.width * 0.5f, sceneSize.height * 0.5f, sceneSize.width * 0.5f, sceneSize.height * 0.5f);
+ RenderTask renderTask(application.GetScene().GetRenderTaskList().CreateTask());
+ renderTask.SetViewport(viewport);
+ renderTask.SetInputEnabled(true);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's touched signal
+ SignalData data;
+ TouchEventFunctor functor(data);
+ actor.TouchedSignal().Connect(&application, functor);
+
+ // Emit a down signal
+ application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(10.0f, 10.0f)));
+ data.Reset();
+
+ // Ensure renderTask actor can be hit too.
+ application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(viewport.x + 5.0f, viewport.y + 5.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(10.0f, 10.0f)));
+ data.Reset();
+
+ // Disable input on renderTask, should not be hittable
+ renderTask.SetInputEnabled(false);
+ application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(viewport.x + 5.0f, viewport.y + 5.0f)));
+ DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+ application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(10.0f, 10.0f)));
+ data.Reset();
+ END_TEST;
+}
+
+int UtcDaliGeoTouchEventMultipleRenderTasksWithChildLayer(void)
+{
+ TestApplication application;
+
+ application.GetScene().SetGeometryHittestEnabled(true);
+
+ Integration::Scene scene(application.GetScene());
+ Vector2 sceneSize(scene.GetSize());
+
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ scene.Add(actor);
+
+ Layer layer = Layer::New();
+ layer.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ layer.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ actor.Add(layer);
+
+ // Create render task
+ Viewport viewport(sceneSize.width * 0.5f, sceneSize.height * 0.5f, sceneSize.width * 0.5f, sceneSize.height * 0.5f);
+ RenderTask renderTask(application.GetScene().GetRenderTaskList().CreateTask());
+ renderTask.SetViewport(viewport);
+ renderTask.SetInputEnabled(true);
+ renderTask.SetSourceActor(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to layer's touched signal
+ SignalData data;
+ TouchEventFunctor functor(data);
+ actor.TouchedSignal().Connect(&application, functor);
+ layer.TouchedSignal().Connect(&application, functor);
+
+ // Emit a down signal
+ application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(10.0f, 10.0f)));
+ data.Reset();
+
+ // Ensure renderTask actor can be hit too.
+ application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(viewport.x + 5.0f, viewport.y + 5.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(10.0f, 10.0f)));
+ data.Reset();
+
+ // Disable input on renderTask, should not be hittable
+ renderTask.SetInputEnabled(false);
+ application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(viewport.x + 5.0f, viewport.y + 5.0f)));
+ DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+ application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(10.0f, 10.0f)));
+ data.Reset();
+ END_TEST;
+}
+
+int UtcDaliGeoTouchEventOffscreenRenderTasks(void)
+{
+ TestApplication application;
+
+ application.GetScene().SetGeometryHittestEnabled(true);
+
+ Integration::Scene scene(application.GetScene());
+ Vector2 sceneSize(scene.GetSize());
+
+ // FrameBufferImage for offscreen RenderTask
+ FrameBuffer frameBuffer = FrameBuffer::New(sceneSize.width, sceneSize.height);
+
+ // Create a renderable actor to display the FrameBufferImage
+ Actor renderableActor = CreateRenderableActor(frameBuffer.GetColorTexture());
+ renderableActor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+ renderableActor.SetProperty(Actor::Property::SIZE, Vector2(sceneSize.x, sceneSize.y));
+ renderableActor.ScaleBy(Vector3(1.0f, -1.0f, 1.0f)); // FIXME
+ scene.Add(renderableActor);
+
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ scene.Add(actor);
+ application.GetGlAbstraction().SetCheckFramebufferStatusResult(GL_FRAMEBUFFER_COMPLETE); // Ensure framebuffer connects
+
+ scene.GetRenderTaskList().GetTask(0u).SetScreenToFrameBufferFunction(RenderTask::FULLSCREEN_FRAMEBUFFER_FUNCTION);
+
+ // Create a RenderTask
+ RenderTask renderTask = scene.GetRenderTaskList().CreateTask();
+ renderTask.SetSourceActor(actor);
+ renderTask.SetFrameBuffer(frameBuffer);
+ renderTask.SetInputEnabled(true);
+
+ // Create another RenderTask
+ RenderTask renderTask2(scene.GetRenderTaskList().CreateTask());
+ renderTask2.SetInputEnabled(true);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's touched signal
+ SignalData data;
+ TouchEventFunctor functor(data);
+ actor.TouchedSignal().Connect(&application, functor);
+
+ // Emit a down signal
+ application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ data.Reset();
+ END_TEST;
+}
+
+int UtcDaliGeoTouchEventMultipleRenderableActors(void)
+{
+ TestApplication application;
+
+ application.GetScene().SetGeometryHittestEnabled(true);
+
+ Integration::Scene scene(application.GetScene());
+ Vector2 sceneSize(scene.GetSize());
+
+ Actor parent = CreateRenderableActor();
+ parent.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ parent.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ scene.Add(parent);
+
+ Actor actor = CreateRenderableActor();
+ actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ parent.Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to layer's touched signal
+ SignalData data;
+ TouchEventFunctor functor(data);
+ parent.TouchedSignal().Connect(&application, functor);
+ actor.TouchedSignal().Connect(&application, functor);
+
+ // Emit a down signal
+ application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_CHECK(actor == data.touchedActor);
+ END_TEST;
+}
+
+int UtcDaliGeoTouchEventActorRemovedInSignal(void)
+{
+ TestApplication application;
+
+ application.GetScene().SetGeometryHittestEnabled(true);
+
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ application.GetScene().Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's touched signal
+ SignalData data;
+ RemoveActorFunctor functor(data);
+ actor.TouchedSignal().Connect(&application, functor);
+
+ // Register for leave events
+ actor.SetProperty(Actor::Property::LEAVE_REQUIRED, true);
+
+ // Emit a down signal
+ application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ data.Reset();
+
+ // Re-add, render and notify
+ application.GetScene().Add(actor);
+ application.SendNotification();
+ application.Render();
+
+ // Emit another signal outside of actor's area, should not get anything as the scene has changed.
+ application.ProcessEvent(GenerateSingleTouch(PointState::MOTION, Vector2(210.0f, 210.0f)));
+ DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+ data.Reset();
+
+ // Emit a down signal
+ application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ data.Reset();
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Emit another signal outside of actor's area, should not get anything as the scene has changed.
+ application.ProcessEvent(GenerateSingleTouch(PointState::MOTION, Vector2(210.0f, 210.0f)));
+ DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+ data.Reset();
+
+ // Re-add actor back to scene, render and notify
+ application.GetScene().Add(actor);
+ application.SendNotification();
+ application.Render();
+
+ // Emit another down event
+ application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ data.Reset();
+
+ // Completely delete the actor
+ actor.Reset();
+
+ // Emit event, should not crash and should not receive an event.
+ application.ProcessEvent(GenerateSingleTouch(PointState::MOTION, Vector2(210.0f, 210.0f)));
+ DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+ END_TEST;
+}
+
+int UtcDaliGeoTouchEventActorSignalNotConsumed(void)
+{
+ TestApplication application;
+
+ application.GetScene().SetGeometryHittestEnabled(true);
+
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ application.GetScene().Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's touched signal
+ SignalData data;
+ TouchEventFunctor functor(data, false);
+ actor.TouchedSignal().Connect(&application, functor);
+
+ // Emit a down signal
+ application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ END_TEST;
+}
+
+int UtcDaliGeoTouchEventActorRemovedFromScene(void)
+{
+ TestApplication application;
+
+ application.GetScene().SetGeometryHittestEnabled(true);
+
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ application.GetScene().Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's touched signal
+ SignalData data;
+ TouchEventFunctor functor(data);
+ actor.TouchedSignal().Connect(&application, functor);
+
+ // Emit a down signal
+ application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ data.Reset();
+
+ // Remove actor from scene
+ application.GetScene().Remove(actor);
+ data.Reset();
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Emit a move at the same point, we should not be signalled.
+ application.ProcessEvent(GenerateSingleTouch(PointState::MOTION, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+ data.Reset();
+ END_TEST;
+}
+
+int UtcDaliGeoTouchEventLayerConsumesTouch(void)
+{
+ TestApplication application;
+
+ application.GetScene().SetGeometryHittestEnabled(true);
+
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ application.GetScene().Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's touched signal
+ SignalData data;
+ TouchEventFunctor functor(data);
+ actor.TouchedSignal().Connect(&application, functor);
+
+ // Add a layer to overlap the actor
+ Layer layer = Layer::New();
+ layer.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ layer.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ application.GetScene().Add(layer);
+ layer.RaiseToTop();
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Emit a few touch signals
+ application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(10.0f, 10.0f)));
+ application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ data.Reset();
+
+ // Set layer to consume all touch
+ layer.SetProperty(Layer::Property::CONSUMES_TOUCH, true);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Emit the same signals again, should not receive
+ application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(10.0f, 10.0f)));
+ application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+ data.Reset();
+
+ END_TEST;
+}
+
+int UtcDaliGeoTouchEventClippedActor(void)
+{
+ TestApplication application;
+ Integration::Scene scene = application.GetScene();
+
+ scene.SetGeometryHittestEnabled(true);
+
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ scene.Add(actor);
+
+ Actor clippingActor = Actor::New();
+ clippingActor.SetProperty(Actor::Property::SIZE, Vector2(50.0f, 50.0f));
+ clippingActor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ clippingActor.SetProperty(Actor::Property::CLIPPING_MODE, ClippingMode::CLIP_CHILDREN);
+ scene.Add(clippingActor);
+
+ // Add a child to the clipped region.
+ Actor clippingChild = Actor::New();
+ clippingChild.SetProperty(Actor::Property::SIZE, Vector2(50.0f, 50.0f));
+ clippingChild.SetProperty(Actor::Property::POSITION, Vector2(25.0f, 25.0f));
+ clippingChild.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ clippingActor.Add(clippingChild);
+
+ // Render and notify.
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's touch signal.
+ SignalData data;
+ TouchEventFunctor functor(data);
+ actor.TouchedSignal().Connect(&application, functor);
+
+ // Emit an event within clipped area - we should have a hit.
+ application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(10.0f, 10.0f)));
+ data.Reset();
+
+ // Emit an event within clipped child area - we should still have a hit.
+ application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(40.0f, 40.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(40.0f, 40.0f)));
+ data.Reset();
+
+ // Now connect to the clippingChild's touch signal
+ SignalData clippingChildData;
+ TouchEventFunctor clippingChildFunctor(clippingChildData);
+ clippingChild.TouchedSignal().Connect(&application, clippingChildFunctor);
+
+ // Emit an event within clipped child area - no hit on actor, but hit on clipped child.
+ application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(40.0f, 40.0f)));
+ DALI_TEST_EQUALS(true, clippingChildData.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+ application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(40.0f, 40.0f)));
+ data.Reset();
+ clippingChildData.Reset();
+
+ // Emit an event outside the clipped area but within the actor area, we should have a hit.
+ application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(60.0f, 60.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(60.0f, 60.0f)));
+ data.Reset();
+ clippingChildData.Reset();
+
+ // Emit an event inside part of the child which is within the clipped area, we should have a hit on the clipped child but not the actor.
+ application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(30.0f, 30.0f)));
+ DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(true, clippingChildData.functorCalled, TEST_LOCATION);
+ application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(30.0f, 30.0f)));
+ data.Reset();
+ clippingChildData.Reset();
+
+ END_TEST;
+}
+
+int UtcDaliGeoTouchEventActorUnparented(void)
+{
+ TestApplication application;
+
+ application.GetScene().SetGeometryHittestEnabled(true);
+
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ application.GetScene().Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's touched signal
+ SignalData data;
+ TouchEventFunctor functor(data);
+ actor.TouchedSignal().Connect(&application, functor);
+
+ // Emit a down signal
+ application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::DOWN, data.receivedTouch.points[0].state, TEST_LOCATION);
+ DALI_TEST_CHECK(actor == data.receivedTouch.points[0].hitActor);
+ data.Reset();
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Unparent the actor
+ actor.Unparent();
+
+ // Should receive an interrupted event
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::INTERRUPTED, data.receivedTouch.points[0].state, TEST_LOCATION);
+ END_TEST;
+}
+
+int UtcDaliGeoTouchEventParentRemovedFromScene(void)
+{
+ TestApplication application;
+
+ application.GetScene().SetGeometryHittestEnabled(true);
+
+ Actor parent = Actor::New();
+ parent.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ parent.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ application.GetScene().Add(parent);
+
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ parent.Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's touched signal
+ SignalData data;
+ TouchEventFunctor functor(data);
+ actor.TouchedSignal().Connect(&application, functor);
+
+ // Emit a down signal
+ application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::DOWN, data.receivedTouch.points[0].state, TEST_LOCATION);
+ DALI_TEST_CHECK(actor == data.receivedTouch.points[0].hitActor);
+ data.Reset();
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Unparent the parent of the touchable actor
+ parent.Unparent();
+
+ // Should receive an interrupted event
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::INTERRUPTED, data.receivedTouch.points[0].state, TEST_LOCATION);
+ END_TEST;
+}
+
+int UtcDaliGeoTouchEventActorRemovedFromSceneDifferentConsumer(void)
+{
+ TestApplication application;
+
+ application.GetScene().SetGeometryHittestEnabled(true);
+
+ Actor parent = Actor::New();
+ parent.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ parent.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ application.GetScene().Add(parent);
+
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ parent.Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's touched signal
+ SignalData data;
+ TouchEventFunctor functor(data, false /* Do not consume */);
+ actor.TouchedSignal().Connect(&application, functor);
+
+ // Connect to parent's touched signal
+ SignalData parentData;
+ TouchEventFunctor parentFunctor(parentData);
+ parent.TouchedSignal().Connect(&application, parentFunctor);
+
+ // Emit a down signal
+ application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::DOWN, data.receivedTouch.points[0].state, TEST_LOCATION);
+ DALI_TEST_CHECK(actor == data.receivedTouch.points[0].hitActor);
+ DALI_TEST_CHECK(actor == data.touchedActor);
+ DALI_TEST_EQUALS(true, parentData.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::DOWN, parentData.receivedTouch.points[0].state, TEST_LOCATION);
+ DALI_TEST_CHECK(actor == parentData.receivedTouch.points[0].hitActor);
+ DALI_TEST_CHECK(parent == parentData.touchedActor);
+ data.Reset();
+ parentData.Reset();
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Unparent the actor
+ actor.Unparent();
+
+ // Should receive an interrupted event for both actor & parent
+ DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(false, parentData.functorCalled, TEST_LOCATION);
+ data.Reset();
+ parentData.Reset();
+
+ // Readd actor to parent
+ parent.Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Emit a motion signal
+ application.ProcessEvent(GenerateSingleTouch(PointState::MOTION, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(true, parentData.functorCalled, TEST_LOCATION);
+ data.Reset();
+ parentData.Reset();
+
+ // Parent is now consumer, connect again to the touched signal of the actor so that it becomes the consumer
+ SignalData secondData;
+ TouchEventFunctor secondFunctor(secondData /* Consume */);
+ actor.TouchedSignal().Connect(&application, secondFunctor);
+
+ // Unparent the actor
+ actor.Unparent();
+
+ // Should receive an interrupted event for both actor functors & the parent as well as it was last consumer
+ DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(false, parentData.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(false, secondData.functorCalled, TEST_LOCATION);
+ data.Reset();
+ parentData.Reset();
+ secondData.Reset();
+
+ END_TEST;
+}
+
+int UtcDaliGeoTouchEventInterruptedDifferentConsumer(void)
+{
+ TestApplication application;
+
+ application.GetScene().SetGeometryHittestEnabled(true);
+
+ Actor rootActor(application.GetScene().GetRootLayer());
+
+ Actor parent = Actor::New();
+ parent.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ parent.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ application.GetScene().Add(parent);
+
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ parent.Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's touched signal
+ SignalData data;
+ TouchEventFunctor functor(data, false /* Do not consume */);
+ actor.TouchedSignal().Connect(&application, functor);
+
+ // Connect to parent's touched signal
+ SignalData parentData;
+ TouchEventFunctor parentFunctor(parentData, false /* Do not consume */);
+ parent.TouchedSignal().Connect(&application, parentFunctor);
+
+ // Connect to root's touched signal and consume
+ SignalData rootData;
+ TouchEventFunctor rootFunctor(rootData);
+ rootActor.TouchedSignal().Connect(&application, rootFunctor);
+
+ // Emit a down signal
+ application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::DOWN, data.receivedTouch.points[0].state, TEST_LOCATION);
+ DALI_TEST_CHECK(actor == data.receivedTouch.points[0].hitActor);
+ DALI_TEST_CHECK(actor == data.touchedActor);
+ DALI_TEST_EQUALS(true, parentData.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::DOWN, parentData.receivedTouch.points[0].state, TEST_LOCATION);
+ DALI_TEST_CHECK(actor == parentData.receivedTouch.points[0].hitActor);
+ DALI_TEST_CHECK(parent == parentData.touchedActor);
+ DALI_TEST_EQUALS(true, rootData.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::DOWN, rootData.receivedTouch.points[0].state, TEST_LOCATION);
+ DALI_TEST_CHECK(actor == rootData.receivedTouch.points[0].hitActor);
+ DALI_TEST_CHECK(rootActor == rootData.touchedActor);
+ data.Reset();
+ parentData.Reset();
+ rootData.Reset();
+
+ // Root is now consumer, connect to the touched signal of the parent so that it becomes the consumer
+ SignalData secondData;
+ TouchEventFunctor secondFunctor(secondData /* Consume */);
+ parent.TouchedSignal().Connect(&application, secondFunctor);
+
+ // Emit an interrupted signal, Since rootActor has already comsume, only rootActor gets INTERRUPTED.
+ application.ProcessEvent(GenerateSingleTouch(PointState::INTERRUPTED, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(false, parentData.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(true, rootData.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::INTERRUPTED, rootData.receivedTouch.points[0].state, TEST_LOCATION);
+ data.Reset();
+ parentData.Reset();
+ rootData.Reset();
+
+ END_TEST;
+}
+
+int UtcDaliGeoTouchEventGetRadius(void)
+{
+ TestApplication application;
+
+ application.GetScene().SetGeometryHittestEnabled(true);
+
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ application.GetScene().Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's touched signal
+ SignalData data;
+ TouchEventFunctor functor(data);
+ actor.TouchedSignal().Connect(&application, functor);
+
+ // Emit a down signal with an angle
+ Integration::TouchEvent touchEvent = GenerateSingleTouch(PointState::DOWN, Vector2(10.0f, 10.0f));
+ touchEvent.points[0].SetRadius(100.0f);
+ application.ProcessEvent(touchEvent);
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::DOWN, data.receivedTouch.points[0].state, TEST_LOCATION);
+ DALI_TEST_EQUALS(100.0f, data.receivedTouch.points[0].radius, TEST_LOCATION);
+ DALI_TEST_EQUALS(100.0f, data.receivedTouch.points[0].ellipseRadius.x, TEST_LOCATION);
+ DALI_TEST_EQUALS(100.0f, data.receivedTouch.points[0].ellipseRadius.y, TEST_LOCATION);
+
+ END_TEST;
+}
+
+int UtcDaliGeoTouchEventGetEllipseRadius(void)
+{
+ TestApplication application;
+
+ application.GetScene().SetGeometryHittestEnabled(true);
+
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ application.GetScene().Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's touched signal
+ SignalData data;
+ TouchEventFunctor functor(data);
+ actor.TouchedSignal().Connect(&application, functor);
+
+ // Emit a down signal with an angle
+ Integration::TouchEvent touchEvent = GenerateSingleTouch(PointState::DOWN, Vector2(10.0f, 10.0f));
+ touchEvent.points[0].SetRadius(100.0f, Vector2(20.0f, 10.0f));
+ application.ProcessEvent(touchEvent);
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::DOWN, data.receivedTouch.points[0].state, TEST_LOCATION);
+ DALI_TEST_EQUALS(100.0f, data.receivedTouch.points[0].radius, TEST_LOCATION);
+ DALI_TEST_EQUALS(20.0f, data.receivedTouch.points[0].ellipseRadius.x, TEST_LOCATION);
+ DALI_TEST_EQUALS(10.0f, data.receivedTouch.points[0].ellipseRadius.y, TEST_LOCATION);
+
+ END_TEST;
+}
+
+int UtcDaliGeoTouchEventGetAngle(void)
+{
+ TestApplication application;
+
+ application.GetScene().SetGeometryHittestEnabled(true);
+
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ application.GetScene().Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's touched signal
+ SignalData data;
+ TouchEventFunctor functor(data);
+ actor.TouchedSignal().Connect(&application, functor);
+
+ // Emit a down signal with an angle
+ Integration::TouchEvent touchEvent = GenerateSingleTouch(PointState::DOWN, Vector2(10.0f, 10.0f));
+ touchEvent.points[0].SetAngle(Degree(90.0f));
+ application.ProcessEvent(touchEvent);
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::DOWN, data.receivedTouch.points[0].state, TEST_LOCATION);
+ DALI_TEST_EQUALS(Degree(90.0f), data.receivedTouch.points[0].angle, TEST_LOCATION);
+
+ END_TEST;
+}
+
+int UtcDaliGeoTouchEventGetPressure(void)
+{
+ TestApplication application;
+
+ application.GetScene().SetGeometryHittestEnabled(true);
+
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ application.GetScene().Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's touched signal
+ SignalData data;
+ TouchEventFunctor functor(data);
+ actor.TouchedSignal().Connect(&application, functor);
+
+ // Emit a down signal with an angle
+ Integration::TouchEvent touchEvent = GenerateSingleTouch(PointState::DOWN, Vector2(10.0f, 10.0f));
+ touchEvent.points[0].SetPressure(10.0f);
+ application.ProcessEvent(touchEvent);
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::DOWN, data.receivedTouch.points[0].state, TEST_LOCATION);
+ DALI_TEST_EQUALS(10.0f, data.receivedTouch.points[0].pressure, TEST_LOCATION);
+
+ END_TEST;
+}
+
+int UtcDaliGeoTouchEventUsage(void)
+{
+ TestApplication application;
+
+ application.GetScene().SetGeometryHittestEnabled(true);
+
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ application.GetScene().Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's touched signal
+ SignalData data;
+ TouchEventFunctor functor(data);
+ actor.TouchedSignal().Connect(&application, functor);
+
+ // Emit a down signal with an angle
+ application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+
+ END_TEST;
+}
+
+int UtcDaliGeoTouchEventGetDeviceAPINegative(void)
+{
+ TestApplication application;
+
+ application.GetScene().SetGeometryHittestEnabled(true);
+
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ application.GetScene().Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's touched signal
+ HandleData handleData;
+ TouchEventHandleFunctor functor(handleData);
+ actor.TouchedSignal().Connect(&application, functor);
+
+ Vector2 screenCoordinates(10.0f, 10.0f);
+ Vector2 localCoordinates;
+ actor.ScreenToLocal(localCoordinates.x, localCoordinates.y, screenCoordinates.x, screenCoordinates.y);
+
+ // Emit a down signal
+ application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, screenCoordinates));
+
+ TouchEvent data = handleData.receivedTouchHandle;
+ DALI_TEST_EQUALS(data.GetDeviceClass(-1), Device::Class::NONE, TEST_LOCATION);
+ DALI_TEST_EQUALS(data.GetDeviceSubclass(-1), Device::Subclass::NONE, TEST_LOCATION);
+ END_TEST;
+}
+
+int UtcDaliGeoTouchEventGetMouseButtonPositive(void)
+{
+ TestApplication application;
+
+ application.GetScene().SetGeometryHittestEnabled(true);
+
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ application.GetScene().Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's touched signal
+ HandleData handleData;
+ TouchEventHandleFunctor functor(handleData);
+ actor.TouchedSignal().Connect(&application, functor);
+
+ // Emit a down signal with MouseButton
+ Integration::TouchEvent touchEvent = GenerateSingleTouch(PointState::DOWN, Vector2(10.0f, 10.0f));
+ touchEvent.points[0].SetMouseButton(static_cast<MouseButton::Type>(3));
+ application.ProcessEvent(touchEvent);
+
+ TouchEvent data = handleData.receivedTouchHandle;
+ DALI_TEST_EQUALS(data.GetMouseButton(0), MouseButton::SECONDARY, TEST_LOCATION);
+
+ END_TEST;
+}
+
+int UtcDaliGeoTouchEventGetMouseButtonNagative(void)
+{
+ TestApplication application;
+
+ application.GetScene().SetGeometryHittestEnabled(true);
+
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ application.GetScene().Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's touched signal
+ HandleData handleData;
+ TouchEventHandleFunctor functor(handleData);
+ actor.TouchedSignal().Connect(&application, functor);
+
+ // Emit a down signal with MouseButton
+ Integration::TouchEvent touchEvent = GenerateSingleTouch(PointState::DOWN, Vector2(10.0f, 10.0f));
+ touchEvent.points[0].SetMouseButton(static_cast<MouseButton::Type>(2));
+ application.ProcessEvent(touchEvent);
+
+ TouchEvent data = handleData.receivedTouchHandle;
+ DALI_TEST_EQUALS(data.GetMouseButton(0), MouseButton::TERTIARY, TEST_LOCATION);
+ DALI_TEST_EQUALS(data.GetMouseButton(3), MouseButton::INVALID, TEST_LOCATION);
+
+ END_TEST;
+}
+
+int UtcDaliGeoTouchEventCapturePropertySet(void)
+{
+ TestApplication application;
+
+ application.GetScene().SetGeometryHittestEnabled(true);
+
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ application.GetScene().Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's touched signal
+ SignalData data;
+ TouchEventFunctor functor(data);
+ actor.TouchedSignal().Connect(&application, functor);
+
+ // Emit a down signal
+ application.ProcessEvent(GenerateSingleTouch(PointState::STARTED, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ data.Reset();
+
+ // Now motion outside of actor, we now SHOULD receive the event
+ application.ProcessEvent(GenerateSingleTouch(PointState::MOTION, Vector2(110.0f, 110.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ data.Reset();
+
+ // Up event, we should receive it again, but as ended rather than interrupted
+ application.ProcessEvent(GenerateSingleTouch(PointState::FINISHED, Vector2(110.0f, 110.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(data.receivedTouch.GetPoint(0).state, PointState::FINISHED, TEST_LOCATION);
+
+ END_TEST;
+}
+
+int UtcDaliGeoTouchEventIntegNewTouchEvent(void)
+{
+ TestApplication application;
+ application.GetScene().SetGeometryHittestEnabled(true);
+ uint32_t timestamp = 92858u;
+ TouchPoint tp(1, PointState::STARTED, 34.4f, 123.89f, 5.0f, 7.0f);
+ Dali::TouchEvent touchEvent = Integration::NewTouchEvent(timestamp, tp);
+
+ DALI_TEST_EQUALS(touchEvent.GetPointCount(), 1u, TEST_LOCATION);
+ DALI_TEST_EQUALS(touchEvent.GetState(0), PointState::STARTED, TEST_LOCATION);
+ DALI_TEST_EQUALS(touchEvent.GetLocalPosition(0), Vector2(5.0f, 7.0f), TEST_LOCATION);
+ DALI_TEST_EQUALS(touchEvent.GetScreenPosition(0), Vector2(34.4f, 123.89f), TEST_LOCATION);
+
+ END_TEST;
+}
+
+int UtcDaliGeoTouchEventIntercept01(void)
+{
+ TestApplication application;
+
+ application.GetScene().SetGeometryHittestEnabled(true);
+
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ application.GetScene().Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's intercept touched signal
+ SignalData data;
+ TouchEventFunctor functor(data, false /* Do not consume */);
+ Dali::DevelActor::InterceptTouchedSignal(actor).Connect(&application, functor);
+
+ // Emit a down signal
+ application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(10.0f, 10.0f)));
+
+ // It should be able to receive touch events by registering only InterceptTouchEvent.
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::DOWN, data.receivedTouch.points[0].state, TEST_LOCATION);
+ DALI_TEST_CHECK(actor == data.receivedTouch.points[0].hitActor);
+ DALI_TEST_CHECK(actor == data.touchedActor);
+ data.Reset();
+
+ END_TEST;
+}
+
+int UtcDaliGeoTouchEventIntercept02(void)
+{
+ TestApplication application;
+
+ application.GetScene().SetGeometryHittestEnabled(true);
+
+ Actor parent = Actor::New();
+ parent.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ parent.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ application.GetScene().Add(parent);
+
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ parent.Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's touched signal
+ SignalData data;
+ TouchEventFunctor functor(data, false /* Do not consume */);
+ actor.TouchedSignal().Connect(&application, functor);
+
+ // Connect to parent's touched signal
+ SignalData parentData;
+ TouchEventFunctor parentFunctor(parentData, false /* Do not consume */);
+ parent.TouchedSignal().Connect(&application, parentFunctor);
+
+ // Emit a down signal
+ application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::DOWN, data.receivedTouch.points[0].state, TEST_LOCATION);
+
+ data.Reset();
+ parentData.Reset();
+
+ // Connect to parent's intercept touched signal
+ SignalData interceptData;
+ TouchEventFunctor interceptFunctor(interceptData, true /* Do intercept */);
+ Dali::DevelActor::InterceptTouchedSignal(parent).Connect(&application, interceptFunctor);
+
+ // Emit a down signal
+ application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(10.0f, 10.0f)));
+
+ // The actor gets interrupted. Because touch is intercepted by parent.
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::INTERRUPTED, data.receivedTouch.points[0].state, TEST_LOCATION);
+ DALI_TEST_EQUALS(true, interceptData.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::DOWN, interceptData.receivedTouch.points[0].state, TEST_LOCATION);
+ DALI_TEST_CHECK(actor == interceptData.receivedTouch.points[0].hitActor);
+ DALI_TEST_CHECK(parent == interceptData.touchedActor);
+ DALI_TEST_EQUALS(true, parentData.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::DOWN, parentData.receivedTouch.points[0].state, TEST_LOCATION);
+ DALI_TEST_CHECK(actor == parentData.receivedTouch.points[0].hitActor);
+ DALI_TEST_CHECK(parent == parentData.touchedActor);
+ data.Reset();
+ interceptData.Reset();
+ parentData.Reset();
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Emit a move signal
+ application.ProcessEvent(GenerateSingleTouch(PointState::MOTION, Vector2(20.0f, 20.0f)));
+
+ // Since InterceptTouchEvent is not called because it has already been intercepted by the parent, only the parent will receive the touchEvent.
+ DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(false, interceptData.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(true, parentData.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::MOTION, parentData.receivedTouch.points[0].state, TEST_LOCATION);
+ DALI_TEST_CHECK(actor == parentData.receivedTouch.points[0].hitActor);
+ DALI_TEST_CHECK(parent == parentData.touchedActor);
+ data.Reset();
+ interceptData.Reset();
+ parentData.Reset();
+
+
+ END_TEST;
+}
+
+int UtcDaliGeoTouchEventIntercept03(void)
+{
+ TestApplication application;
+
+ application.GetScene().SetGeometryHittestEnabled(true);
+
+ // Add a layer to overlap the actor
+ Layer layer = Layer::New();
+ layer.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ layer.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ application.GetScene().Add(layer);
+ layer.RaiseToTop();
+
+ // Set layer to consume all touch
+ layer.SetProperty(Layer::Property::CONSUMES_TOUCH, true);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ layer.Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ Actor rootActor(application.GetScene().GetRootLayer());
+
+ // Connect to root actor's intercept touched signal
+ SignalData sceneData;
+ TouchEventFunctor sceneFunctor(sceneData);
+ Dali::DevelActor::InterceptTouchedSignal(rootActor).Connect(&application, sceneFunctor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Emit a down signal
+ application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(10.0f, 10.0f)));
+
+ // Even if the layer is touch consumed, the root actor must be able to intercept touch.
+ DALI_TEST_EQUALS(true, sceneData.functorCalled, TEST_LOCATION);
+ sceneData.Reset();
+
+
+ END_TEST;
+}
+
+int UtcDaliGeoTouchAreaOffset(void)
+{
+ TestApplication application;
+
+ application.GetScene().SetGeometryHittestEnabled(true);
+
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+
+ application.GetScene().Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's touched signal
+ SignalData data;
+ TouchEventFunctor functor(data, false /* Do not consume */);
+ actor.TouchedSignal().Connect(&application, functor);
+
+ // Emit a down signal
+ application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(110.0f, 110.0f)));
+ // The actor touched signal is not called because the touch area is outside actor.
+ DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+ application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(110.0f, 110.0f)));
+ data.Reset();
+
+ // set a bigger touch area
+ actor.SetProperty(DevelActor::Property::TOUCH_AREA_OFFSET, Rect<int>(-70, 70, 70, -70)); // left, right, bottom, top
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Emit a down signal
+ application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(150.0f, 150.0f)));
+ // The actor touched signal is called because the touch area is inside touchArea.
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::DOWN, data.receivedTouch.points[0].state, TEST_LOCATION);
+ DALI_TEST_CHECK(actor == data.receivedTouch.points[0].hitActor);
+ application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(150.0f, 150.0f)));
+ data.Reset();
+
+ // set a offset touch area
+ actor.SetProperty(DevelActor::Property::TOUCH_AREA_OFFSET, Rect<int>(50, 100, -50, 0)); // left, right, bottom, top
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Emit a down signal
+ application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(190.0f, 25.0f)));
+ // The actor touched signal is called because the touch area is inside touchArea.
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::DOWN, data.receivedTouch.points[0].state, TEST_LOCATION);
+ DALI_TEST_CHECK(actor == data.receivedTouch.points[0].hitActor);
+ application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(190.0f, 25.0f)));
+ data.Reset();
+
+ // set a smaller touch area
+ actor.SetProperty(DevelActor::Property::TOUCH_AREA_OFFSET, Rect<int>(50, 0, 0, 50));
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Emit a down signal
+ application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(40.0f, 40.0f)));
+ // The actor touched signal is not called because the touch area is outside touchArea.
+ DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+ application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(40.0f, 40.0f)));
+ data.Reset();
+
+ // Emit a down signal
+ application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(90.0f, 90.0f)));
+ // The actor touched signal is called because the touch area is inside touchArea.
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::DOWN, data.receivedTouch.points[0].state, TEST_LOCATION);
+ DALI_TEST_CHECK(actor == data.receivedTouch.points[0].hitActor);
+ application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(90.0f, 90.0f)));
+ data.Reset();
+
+ END_TEST;
+}
+
+int UtcDaliGeoTouchEventAllowOnlyOwnTouchPropertySet(void)
+{
+ TestApplication application;
+
+ application.GetScene().SetGeometryHittestEnabled(true);
+
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ application.GetScene().Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's touched signal
+ SignalData data;
+ TouchEventFunctor functor(data);
+ actor.TouchedSignal().Connect(&application, functor);
+
+ // AllowOnlyOwnTouch is default. We don't turn this on/off.
+ // Now set the only allow own touch property
+ // actor.SetProperty(DevelActor::Property::ALLOW_ONLY_OWN_TOUCH, true);
+
+ // Emit a down signal outside of actor, we should not receive the event
+ application.ProcessEvent(GenerateSingleTouch(PointState::STARTED, Vector2(110.0f, 110.0f)));
+ DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+ data.Reset();
+
+ // Now motion inside of actor, we should NOT receive the event
+ application.ProcessEvent(GenerateSingleTouch(PointState::MOTION, Vector2(80.0f, 80.0f)));
+ DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+ data.Reset();
+
+ // Up event, should not receive the event
+ application.ProcessEvent(GenerateSingleTouch(PointState::FINISHED, Vector2(110.0f, 110.0f)));
+ DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+ data.Reset();
+
+ // Emit a down signal inside of actor, we should receive the event
+ application.ProcessEvent(GenerateSingleTouch(PointState::STARTED, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ data.Reset();
+
+ // Now motion inside of actor, we should receive the event
+ application.ProcessEvent(GenerateSingleTouch(PointState::MOTION, Vector2(80.0f, 80.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ data.Reset();
+
+ // Now motion outsize of actor, we should receive the event
+ // CAPTURE_ALL_TOUCH_AFTER_START is now the default policy. We don't turn this on/off.
+ // So, even though it is outside the actor, it receives the event.
+ application.ProcessEvent(GenerateSingleTouch(PointState::MOTION, Vector2(110.0f, 110.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ data.Reset();
+
+ // Up event, should receive an finished
+ application.ProcessEvent(GenerateSingleTouch(PointState::FINISHED, Vector2(110.0f, 110.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(data.receivedTouch.GetPoint(0).state, PointState::FINISHED, TEST_LOCATION);
+ data.Reset();
+
+ END_TEST;
+}
+
+int UtcDaliGeoTouchEventDispatchTouchMotionPropertySet(void)
+{
+ TestApplication application;
+
+ application.GetScene().SetGeometryHittestEnabled(true);
+
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ application.GetScene().Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's touched signal
+ SignalData data;
+ TouchEventFunctor functor(data);
+ actor.TouchedSignal().Connect(&application, functor);
+
+ // Emit a down signal actor, we should receive the event
+ application.ProcessEvent(GenerateSingleTouch(PointState::STARTED, Vector2(10.0f, 10.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(data.receivedTouch.GetPoint(0).state, PointState::STARTED, TEST_LOCATION);
+ data.Reset();
+
+ // Emit a motion signal actor, we should receive the event
+ application.ProcessEvent(GenerateSingleTouch(PointState::MOTION, Vector2(20.0f, 20.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(data.receivedTouch.GetPoint(0).state, PointState::MOTION, TEST_LOCATION);
+ data.Reset();
+
+ // Now set the dispatch touch motion property
+ actor.SetProperty(DevelActor::Property::DISPATCH_TOUCH_MOTION, false);
+
+ // Emit a motion signal actor, we should not receive the event
+ application.ProcessEvent(GenerateSingleTouch(PointState::MOTION, Vector2(30.0f, 30.0f)));
+ DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+ data.Reset();
+
+ // Up event, should receive the event
+ application.ProcessEvent(GenerateSingleTouch(PointState::FINISHED, Vector2(40.0f, 40.0f)));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(data.receivedTouch.GetPoint(0).state, PointState::FINISHED, TEST_LOCATION);
+ data.Reset();
+
+ data.Reset();
+
+ END_TEST;
+}
END_TEST;
}
+
+int UtcDaliSceneGeoTouchedEnabledDisabled(void)
+{
+ TestApplication application;
+ Dali::Integration::Scene scene = application.GetScene();
+ DALI_TEST_EQUALS(scene.IsGeometryHittestEnabled(), false, TEST_LOCATION);
+
+ TouchedSignalData data;
+ TouchFunctor functor(data);
+ scene.TouchedSignal().Connect(&application, functor);
+
+ // Render and notify.
+ application.SendNotification();
+ application.Render();
+
+ // Confirm functor not called before there has been any touch event.
+ DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+
+ // No actors, single touch, down, motion then up.
+ {
+ GenerateTouch(application, PointState::DOWN, Vector2(10.0f, 10.0f));
+
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_CHECK(data.receivedTouchEvent.GetPointCount() != 0u);
+ DALI_TEST_CHECK(!data.receivedTouchEvent.GetHitActor(0));
+
+ data.Reset();
+
+ // Confirm there is no signal when the touchpoint is only moved.
+ GenerateTouch(application, PointState::MOTION, Vector2(1200.0f, 10.0f)); // Some motion
+
+ DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+ data.Reset();
+
+ // Confirm a following up event generates a signal.
+ GenerateTouch(application, PointState::UP, Vector2(1200.0f, 10.0f));
+
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_CHECK(data.receivedTouchEvent.GetPointCount() != 0u);
+ DALI_TEST_CHECK(!data.receivedTouchEvent.GetHitActor(0));
+ data.Reset();
+ }
+
+ // Add an actor to the scene.
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ actor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
+ actor.TouchedSignal().Connect(&DummyTouchCallback);
+ scene.Add(actor);
+
+ // Render and notify.
+ application.SendNotification();
+ application.Render();
+
+ // Actor on scene, single touch, down in actor, motion, then up outside actor.
+ {
+ GenerateTouch(application, PointState::DOWN, Vector2(10.0f, 10.0f));
+
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_CHECK(data.receivedTouchEvent.GetPointCount() != 0u);
+ DALI_TEST_CHECK(data.receivedTouchEvent.GetHitActor(0) == actor);
+ data.Reset();
+
+ GenerateTouch(application, PointState::MOTION, Vector2(150.0f, 10.0f)); // Some motion
+
+ DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+ data.Reset();
+
+ GenerateTouch(application, PointState::UP, Vector2(150.0f, 10.0f)); // Some motion
+
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_CHECK(data.receivedTouchEvent.GetPointCount() != 0u);
+ DALI_TEST_CHECK(!data.receivedTouchEvent.GetHitActor(0));
+ data.Reset();
+ }
+
+ scene.SetGeometryHittestEnabled(true);
+ DALI_TEST_EQUALS(scene.IsGeometryHittestEnabled(), true, TEST_LOCATION);
+ {
+ GenerateTouch(application, PointState::DOWN, Vector2(10.0f, 10.0f));
+
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_CHECK(data.receivedTouchEvent.GetPointCount() != 0u);
+ DALI_TEST_CHECK(data.receivedTouchEvent.GetHitActor(0) == actor);
+ data.Reset();
+
+ GenerateTouch(application, PointState::MOTION, Vector2(150.0f, 10.0f)); // Some motion
+
+ DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+ data.Reset();
+
+ GenerateTouch(application, PointState::UP, Vector2(150.0f, 10.0f)); // Some motion
+
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_CHECK(data.receivedTouchEvent.GetPointCount() != 0u);
+ DALI_TEST_CHECK(data.receivedTouchEvent.GetHitActor(0) == actor);
+ data.Reset();
+ }
+
+ END_TEST;
+}
{
namespace HitTestAlgorithm
{
-bool HitTest(Stage stage, const Vector2& screenCoordinates, Results& results, HitTestFunction func)
+bool HitTest(Stage stage, const Vector2& screenCoordinates, Results& results, HitTestFunction func, bool isGeometry)
{
Internal::Stage& stageImpl = GetImplementation(stage);
- return Internal::HitTestAlgorithm::HitTest(stageImpl.GetSize(), stageImpl.GetRenderTaskList(), stageImpl.GetLayerList(), screenCoordinates, results, func);
+ return Internal::HitTestAlgorithm::HitTest(stageImpl.GetSize(), stageImpl.GetRenderTaskList(), stageImpl.GetLayerList(), screenCoordinates, results, func, isGeometry);
}
bool BuildPickingRay(RenderTask renderTask, const Vector2& screenCoordinates, Vector3& origin, Vector3& direction)
* @param[in] screenCoordinates The screen coordinates.
* @param[out] results The results of the hit-test, only modified if something is hit
* @param[in] func The function to use in the hit-test algorithm.
+ * @param[in] isGeometry If true, hittest works in a geometry way.
* @return true if something was hit
*/
-DALI_CORE_API bool HitTest(Stage stage, const Vector2& screenCoordinates, Results& results, HitTestFunction func);
+DALI_CORE_API bool HitTest(Stage stage, const Vector2& screenCoordinates, Results& results, HitTestFunction func, bool isGeometry = false);
/**
* @brief Given screen coordinates, this method returns the camera origin in world coordinates and the direction of the picking ray in world-space.
return GetImplementation(*this).IsPartialUpdateEnabled();
}
+void Scene::SetGeometryHittestEnabled(bool enabled)
+{
+ GetImplementation(*this).SetGeometryHittestEnabled(enabled);
+}
+
+bool Scene::IsGeometryHittestEnabled()
+{
+ return GetImplementation(*this).IsGeometryHittestEnabled();
+}
+
Scene::EventProcessingFinishedSignalType& Scene::EventProcessingFinishedSignal()
{
return GetImplementation(*this).EventProcessingFinishedSignal();
bool IsPartialUpdateEnabled() const;
/**
+ * @brief Sets whether the processes using geometry event propagation touch and hover events.
+ *
+ * @param[in] enabled True if the processes using geometry event propagation touch and hover events.
+ */
+ void SetGeometryHittestEnabled(bool enabled);
+
+ /**
+ * @brief Queries whether the scene using geometry event propagation touch and hover events.
+ *
+ * @return True if the scene using geometry event propagation touch and hover events.
+ */
+ bool IsGeometryHittestEnabled();
+
+ /**
* @brief This signal is emitted just after the event processing is finished.
*
* @return The signal to connect to
mDrawMode(DrawMode::NORMAL),
mColorMode(Node::DEFAULT_COLOR_MODE),
mClippingMode(ClippingMode::DISABLED),
+ mHoverState(PointState::FINISHED),
mBlendEquation(DevelBlendEquation::ADD)
{
}
return mDispatchHoverMotion;
}
+ /**
+ * @brief Sets the hover state of actor
+ * @param state The PointState
+ */
+ void SetHoverState(PointState::Type state)
+ {
+ mHoverState = state;
+ }
+
+ /**
+ * @brief Gets the hover state of actor
+ * @return PointState::Type
+ */
+ PointState::Type GetHoverState() const
+ {
+ return mHoverState;
+ }
// Gestures
/**
DrawMode::Type mDrawMode : 3; ///< Cached: How the actor and its children should be drawn
ColorMode mColorMode : 3; ///< Cached: Determines whether mWorldColor is inherited
ClippingMode::Type mClippingMode : 3; ///< Cached: Determines which clipping mode (if any) to use.
+ PointState::Type mHoverState : 3; ///< Stores the HoverEvent state of actor.
DevelBlendEquation::Type mBlendEquation : 16; ///< Cached: Determines which blend equation will be used to render renderers.
private:
mBackgroundColor(DEFAULT_BACKGROUND_COLOR),
mDepthTreeDirty(false),
mPartialUpdateEnabled(true),
+ mGeometryHittest(false),
mEventProcessor(*this, ThreadLocalStorage::GetInternal()->GetGestureEventProcessor()),
mSurfaceOrientation(0),
mScreenOrientation(0)
return mPartialUpdateEnabled;
}
+void Scene::SetGeometryHittestEnabled(bool enabled)
+{
+ mGeometryHittest = enabled;
+}
+
+bool Scene::IsGeometryHittestEnabled() const
+{
+ return mGeometryHittest;
+}
+
Integration::Scene::KeyEventSignalType& Scene::KeyEventSignal()
{
return mKeyEventSignal;
void SetSurfaceRenderTarget(const Graphics::RenderTargetCreateInfo& renderTargetCreateInfo);
/**
+ * @copydoc Dali::Integration::Scene::SetGeometryHittestEnabled
+ */
+ void SetGeometryHittestEnabled(bool enabled);
+
+ /**
+ * @copydoc Dali::Integration::Scene::IsGeometryHittestEnabled
+ */
+ bool IsGeometryHittestEnabled() const;
+
+ /**
* Used by the EventProcessor to emit key event signals.
* @param[in] event The key event.
*/
bool mDepthTreeDirty : 1; ///< True if the depth tree needs recalculating
bool mPartialUpdateEnabled : 1; ///< True if the partial update is enabled
+ bool mGeometryHittest : 1; ///< True if the geometry hittest is enabled
EventProcessor mEventProcessor;
return layer->IsTouchConsumed();
}
- bool ActorRequiresHitResultCheck(Actor* actor, Integration::Point point, Vector2 hitPointLocal, uint32_t timeStamp) override
+ bool ActorRequiresHitResultCheck(Actor* actor, Integration::Point point, Vector2 hitPointLocal, uint32_t timeStamp, bool isGeometry) override
{
return actor->EmitHitTestResultSignal(point, hitPointLocal, timeStamp);
}
return false;
}
- bool ActorRequiresHitResultCheck(Actor* actor, Integration::Point point, Vector2 hitPointLocal, uint32_t timeStamp) override
+ bool ActorRequiresHitResultCheck(Actor* actor, Integration::Point point, Vector2 hitPointLocal, uint32_t timeStamp, bool isGeometry) override
{
- return actor->EmitHitTestResultSignal(point, hitPointLocal, timeStamp);
+ // Geometry way does not require Hittest from the client.
+ if(!isGeometry)
+ {
+ return actor->EmitHitTestResultSignal(point, hitPointLocal, timeStamp);
+ }
+ return true;
}
Dali::HitTestAlgorithm::HitTestFunction mFunc;
return layer->IsTouchConsumed();
}
- bool ActorRequiresHitResultCheck(Actor* actor, Integration::Point point, Vector2 hitPointLocal, uint32_t timeStamp) override
+ bool ActorRequiresHitResultCheck(Actor* actor, Integration::Point point, Vector2 hitPointLocal, uint32_t timeStamp, bool isGeometry) override
{
- if(point.GetState() != PointState::STARTED && actor->IsAllowedOnlyOwnTouch() && ownActor != actor)
+ // The Geometry way behaves like AllowedOnlyOwnTouch is enabled.
+ if(point.GetState() != PointState::STARTED && (isGeometry || actor->IsAllowedOnlyOwnTouch()) && ownActor != actor)
{
return false;
}
- return actor->EmitHitTestResultSignal(point, hitPointLocal, timeStamp);
+ // Geometry way does not require Hittest from the client.
+ if(!isGeometry)
+ {
+ return actor->EmitHitTestResultSignal(point, hitPointLocal, timeStamp);
+ }
+ return true;
}
void SetOwnActor(const Actor* actor)
bool overlayedActor,
Actor& actor,
bool& overlayHit,
- HitActor& hit)
+ HitActor& hit,
+ bool isGeometry)
{
if(clippingActor || hitCheck.IsActorHittable(&actor))
{
}
// If the hit actor does not want to hit, the hit-test continues.
- if(hitCheck.ActorRequiresHitResultCheck(&actor, point, hitPointLocal, eventTime))
+ if(hitCheck.ActorRequiresHitResultCheck(&actor, point, hitPointLocal, eventTime, isGeometry))
{
hit.actor = &actor;
hit.hitPosition = hitPointLocal;
bool layerIs3d,
const RayTest& rayTest,
const Integration::Point& point,
- const uint32_t eventTime)
+ const uint32_t eventTime,
+ std::list<Dali::Internal::Actor*>& actorLists,
+ bool isGeometry)
{
HitActor hit;
bool overlayedActor = overlayed || actor.IsOverlay();
// If we are a clipping actor or hittable...
- HitTestActor(renderTask, rayOrigin, rayDir, nearClippingPlane, farClippingPlane, hitCheck, rayTest, point, eventTime, clippingActor, overlayedActor, actor, overlayHit, hit);
+ HitTestActor(renderTask, rayOrigin, rayDir, nearClippingPlane, farClippingPlane, hitCheck, rayTest, point, eventTime, clippingActor, overlayedActor, actor, overlayHit, hit, isGeometry);
// If current actor is clipping, and hit failed, We should not checkup child actors. Fast return
if(clippingActor && !(hit.actor))
{
return hit;
}
+ else if (isGeometry && hit.actor)
+ {
+ // Saves the actors that can be hit as a list
+ actorLists.push_back(hit.actor);
+ }
// Find a child hit, until we run out of actors in the current layer.
HitActor childHit;
if(actor.GetChildCount() > 0)
{
+ // If the child touches outside the parent's size boundary, it should not be hit.
+ if(isGeometry && !actor.IsLayer())
+ {
+ Vector2 hitPointLocal;
+ float distance;
+ if(!(rayTest.SphereTest(actor, rayOrigin, rayDir) &&
+ rayTest.ActorTest(actor, rayOrigin, rayDir, hitPointLocal, distance)))
+ {
+ return hit;
+ }
+ }
+
childHit.distance = std::numeric_limits<float>::max();
childHit.depth = std::numeric_limits<int32_t>::min();
ActorContainer& children = actor.GetChildrenInternal();
(hitCheck.DescendActorHierarchy((*iter).Get()))) // We can descend into child hierarchy
{
HitActor currentHit(HitTestWithinLayer((*iter->Get()),
- renderTask,
- exclusives,
- rayOrigin,
- rayDir,
- nearClippingPlane,
- farClippingPlane,
- hitCheck,
- overlayedActor,
- overlayHit,
- layerIs3d,
- rayTest,
- point,
- eventTime));
-
+ renderTask,
+ exclusives,
+ rayOrigin,
+ rayDir,
+ nearClippingPlane,
+ farClippingPlane,
+ hitCheck,
+ overlayedActor,
+ overlayHit,
+ layerIs3d,
+ rayTest,
+ point,
+ eventTime,
+ actorLists,
+ isGeometry));
// Make sure the set hit actor is actually hittable. This is usually required when we have some
// clipping as we need to hit-test all actors as we descend the tree regardless of whether they
// are hittable or not.
farClippingPlane = cameraActor->GetFarClippingPlane();
}
+void GeoHitTestRenderTask(const RenderTaskList::ExclusivesContainer& exclusives,
+ const Vector2& sceneSize,
+ LayerList& layers,
+ RenderTask& renderTask,
+ Vector2 screenCoordinates,
+ Results& results,
+ HitTestInterface& hitCheck,
+ const RayTest& rayTest)
+{
+ if(renderTask.IsHittable(screenCoordinates))
+ {
+ Viewport viewport;
+ renderTask.GetHittableViewport(viewport);
+
+ if(screenCoordinates.x < static_cast<float>(viewport.x) ||
+ screenCoordinates.x > static_cast<float>(viewport.x + viewport.width) ||
+ screenCoordinates.y < static_cast<float>(viewport.y) ||
+ screenCoordinates.y > static_cast<float>(viewport.y + viewport.height))
+ {
+ // The screen coordinate is outside the viewport of render task. The viewport clips all layers.
+ return;
+ }
+
+ float nearClippingPlane, farClippingPlane;
+ GetCameraClippingPlane(renderTask, nearClippingPlane, farClippingPlane);
+
+ // Determine the layer depth of the source actor
+ Actor* sourceActor(renderTask.GetSourceActor());
+ if(sourceActor)
+ {
+ Dali::Layer sourceLayer(sourceActor->GetLayer());
+ if(sourceLayer)
+ {
+ const uint32_t sourceActorDepth(sourceLayer.GetProperty<bool>(Dali::Layer::Property::DEPTH));
+ CameraActor* cameraActor = renderTask.GetCameraActor();
+ bool pickingPossible = cameraActor->BuildPickingRay(screenCoordinates,
+ viewport,
+ results.rayOrigin,
+ results.rayDirection);
+ if(!pickingPossible)
+ {
+ return;
+ }
+
+ // Hit test starting with the top layer, working towards the bottom layer.
+ bool overlayHit = false;
+
+ for(uint32_t i = 0; i < layers.GetLayerCount(); ++i)
+ {
+ Layer* layer(layers.GetLayer(i));
+ overlayHit = false;
+ HitActor hit;
+
+ // Ensure layer is touchable (also checks whether ancestors are also touchable)
+ if(IsActuallyHittable(*layer, screenCoordinates, sceneSize, hitCheck))
+ {
+ // Always hit-test the source actor; otherwise test whether the layer is below the source actor in the hierarchy
+ if(sourceActorDepth == i)
+ {
+ // Recursively hit test the source actor & children, without crossing into other layers.
+ hit = HitTestWithinLayer(*sourceActor,
+ renderTask,
+ exclusives,
+ results.rayOrigin,
+ results.rayDirection,
+ nearClippingPlane,
+ farClippingPlane,
+ hitCheck,
+ overlayHit,
+ overlayHit,
+ layer->GetBehavior() == Dali::Layer::LAYER_3D,
+ rayTest,
+ results.point,
+ results.eventTime,
+ results.actorLists,
+ true);
+ }
+ else if(IsWithinSourceActors(*sourceActor, *layer))
+ {
+ // Recursively hit test all the actors, without crossing into other layers.
+ hit = HitTestWithinLayer(*layer,
+ renderTask,
+ exclusives,
+ results.rayOrigin,
+ results.rayDirection,
+ nearClippingPlane,
+ farClippingPlane,
+ hitCheck,
+ overlayHit,
+ overlayHit,
+ layer->GetBehavior() == Dali::Layer::LAYER_3D,
+ rayTest,
+ results.point,
+ results.eventTime,
+ results.actorLists,
+ true);
+ }
+ }
+
+ if(hit.actor)
+ {
+ results.renderTask = RenderTaskPtr(&renderTask);
+ results.actor = Dali::Actor(hit.actor);
+ results.actorCoordinates = hit.hitPosition;
+ }
+ }
+ }
+ }
+ }
+ return;
+}
+
/**
* Hit test a RenderTask
*/
layer->GetBehavior() == Dali::Layer::LAYER_3D,
rayTest,
results.point,
- results.eventTime);
+ results.eventTime,
+ results.actorLists,
+ false);
}
else if(IsWithinSourceActors(*sourceActor, *layer))
{
layer->GetBehavior() == Dali::Layer::LAYER_3D,
rayTest,
results.point,
- results.eventTime);
+ results.eventTime,
+ results.actorLists,
+ false);
}
// If this layer is set to consume the hit, then do not check any layers behind it
* @param[in] taskList The list of render tasks
* @param[out] results Ray information calculated by the camera
* @param[in] hitCheck The hit testing interface object to use
+ * @param[in] isGeometry Whether the scene using geometry event propagation touch and hover events.
* @return True if we have a hit, false otherwise
*/
bool HitTestRenderTaskList(const Vector2& sceneSize,
RenderTaskList& taskList,
const Vector2& screenCoordinates,
Results& results,
- HitTestInterface& hitCheck)
+ HitTestInterface& hitCheck,
+ bool isGeometry)
{
- RenderTaskList::RenderTaskContainer& tasks = taskList.GetTasks();
- RenderTaskList::RenderTaskContainer::reverse_iterator endIter = tasks.rend();
- const auto& exclusives = taskList.GetExclusivesList();
- RayTest rayTest;
-
- // Hit test order should be reverse of draw order
- for(RenderTaskList::RenderTaskContainer::reverse_iterator iter = tasks.rbegin(); endIter != iter; ++iter)
+ if(isGeometry)
{
- RenderTask& renderTask = *iter->Get();
- if(HitTestRenderTask(exclusives, sceneSize, layers, renderTask, screenCoordinates, results, hitCheck, rayTest))
+ RenderTaskList::RenderTaskContainer& tasks = taskList.GetTasks();
+ RenderTaskList::RenderTaskContainer::iterator endIter = tasks.end();
+ const auto& exclusives = taskList.GetExclusivesList();
+ RayTest rayTest;
+
+ // Hit test order should be of draw order
+ for(RenderTaskList::RenderTaskContainer::iterator iter = tasks.begin(); endIter != iter; ++iter)
{
- // Return true when an actor is hit (or layer in our render-task consumes the hit)
- return true;
+ RenderTask& renderTask = *iter->Get();
+ GeoHitTestRenderTask(exclusives, sceneSize, layers, renderTask, screenCoordinates, results, hitCheck, rayTest);
}
+
+ return !results.actorLists.empty();
}
+ else
+ {
+ RenderTaskList::RenderTaskContainer& tasks = taskList.GetTasks();
+ RenderTaskList::RenderTaskContainer::reverse_iterator endIter = tasks.rend();
+ const auto& exclusives = taskList.GetExclusivesList();
+ RayTest rayTest;
- return false;
+ // Hit test order should be reverse of draw order
+ for(RenderTaskList::RenderTaskContainer::reverse_iterator iter = tasks.rbegin(); endIter != iter; ++iter)
+ {
+ RenderTask& renderTask = *iter->Get();
+ if(HitTestRenderTask(exclusives, sceneSize, layers, renderTask, screenCoordinates, results, hitCheck, rayTest))
+ {
+ // Return true when an actor is hit (or layer in our render-task consumes the hit)
+ return true;
+ }
+ }
+ return false;
+ }
}
/**
* @param[in] taskList The list of render tasks
* @param[out] results Ray information calculated by the camera
* @param[in] hitCheck The hit testing interface object to use
+ * @param[in] isGeometry Whether the scene using geometry event propagation touch and hover events.
* @return True if we have a hit, false otherwise
*/
bool HitTestForEachRenderTask(const Vector2& sceneSize,
RenderTaskList& taskList,
const Vector2& screenCoordinates,
Results& results,
- HitTestInterface& hitCheck)
+ HitTestInterface& hitCheck,
+ bool isGeometry)
{
bool result = false;
- if(HitTestRenderTaskList(sceneSize, layers, taskList, screenCoordinates, results, hitCheck))
+ if(HitTestRenderTaskList(sceneSize, layers, taskList, screenCoordinates, results, hitCheck, isGeometry))
{
// Found hit.
result = true;
HitTestInterface::~HitTestInterface() = default;
-bool HitTest(const Vector2& sceneSize, RenderTaskList& taskList, LayerList& layerList, const Vector2& screenCoordinates, Dali::HitTestAlgorithm::Results& results, Dali::HitTestAlgorithm::HitTestFunction func)
+bool HitTest(const Vector2& sceneSize, RenderTaskList& taskList, LayerList& layerList, const Vector2& screenCoordinates, Dali::HitTestAlgorithm::Results& results, Dali::HitTestAlgorithm::HitTestFunction func, bool isGeometry)
{
bool wasHit(false);
// Hit-test the regular on-scene actors
Results hitTestResults;
HitTestFunctionWrapper hitTestFunctionWrapper(func);
- if(HitTestForEachRenderTask(sceneSize, layerList, taskList, screenCoordinates, hitTestResults, hitTestFunctionWrapper))
+ if(HitTestForEachRenderTask(sceneSize, layerList, taskList, screenCoordinates, hitTestResults, hitTestFunctionWrapper, isGeometry))
{
results.actor = hitTestResults.actor;
results.actorCoordinates = hitTestResults.actorCoordinates;
return wasHit;
}
-bool HitTest(const Vector2& sceneSize, RenderTaskList& renderTaskList, LayerList& layerList, const Vector2& screenCoordinates, Results& results, HitTestInterface& hitTestInterface)
+bool HitTest(const Vector2& sceneSize, RenderTaskList& renderTaskList, LayerList& layerList, const Vector2& screenCoordinates, Results& results, HitTestInterface& hitTestInterface, bool isGeometry)
{
bool wasHit(false);
// Hit-test the regular on-scene actors
if(!wasHit)
{
- wasHit = HitTestForEachRenderTask(sceneSize, layerList, renderTaskList, screenCoordinates, results, hitTestInterface);
+ wasHit = HitTestForEachRenderTask(sceneSize, layerList, renderTaskList, screenCoordinates, results, hitTestInterface, isGeometry);
}
return wasHit;
}
-bool HitTest(const Vector2& sceneSize, RenderTaskList& renderTaskList, LayerList& layerList, const Vector2& screenCoordinates, Results& results, const Actor* ownActor)
+bool HitTest(const Vector2& sceneSize, RenderTaskList& renderTaskList, LayerList& layerList, const Vector2& screenCoordinates, Results& results, const Actor* ownActor, bool isGeometry)
{
ActorTouchableCheck actorTouchableCheck;
actorTouchableCheck.SetOwnActor(ownActor);
- return HitTest(sceneSize, renderTaskList, layerList, screenCoordinates, results, actorTouchableCheck);
+ return HitTest(sceneSize, renderTaskList, layerList, screenCoordinates, results, actorTouchableCheck, isGeometry);
}
} // namespace HitTestAlgorithm
{
struct Results
{
- RenderTaskPtr renderTask; ///< The render-task displaying the actor.
- Dali::Actor actor; ///< The hit actor.
- Vector2 actorCoordinates; ///< The actor coordinates.
- Vector4 rayOrigin; ///< The point of origin of the ray.
- Vector4 rayDirection; ///< The direction vector of the ray.
- Integration::Point point; ///< The point of event touched.
- uint32_t eventTime; ///< The time the event occurred.
+ RenderTaskPtr renderTask; ///< The render-task displaying the actor.
+ Dali::Actor actor; ///< The hit actor.
+ Vector2 actorCoordinates; ///< The actor coordinates.
+ Vector4 rayOrigin; ///< The point of origin of the ray.
+ Vector4 rayDirection; ///< The direction vector of the ray.
+ Integration::Point point; ///< The point of event touched.
+ uint32_t eventTime; ///< The time the event occurred.
+ std::list<Dali::Internal::Actor*> actorLists; ///< If the geometry hittest way is used, a list of actors that can be hit is stored.
};
/**
* @param[in] point The point of event touched.
* @param[in] hitPointLocal The hit point in the Actor's local reference system.
* @param[in] timeStamp The time the event occurred.
+ * @param[in] isGeometry If true, hittest works in a geometry way.
*
* @return true if the actor should be the hit, false otherwise.
*/
- virtual bool ActorRequiresHitResultCheck(Actor* actor, Integration::Point point, Vector2 hitPointLocal, uint32_t timeStamp) = 0;
+ virtual bool ActorRequiresHitResultCheck(Actor* actor, Integration::Point point, Vector2 hitPointLocal, uint32_t timeStamp, bool isGeometry) = 0;
protected:
/**
* @param[in] screenCoordinates The screen coordinates.
* @param[out] results The results of the hit-test.
* @param[in] func The function to use in the hit-test algorithm.
+ * @param[in] isGeometry If true, hittest works in a geometry way.
* @return true if something was hit
*
* @see HitTest(Stage&, const Vector2&, Results&, HitTestInterface&)
*/
-bool HitTest(const Vector2& sceneSize, RenderTaskList& renderTaskList, LayerList& layerList, const Vector2& screenCoordinates, Dali::HitTestAlgorithm::Results& results, Dali::HitTestAlgorithm::HitTestFunction func);
+bool HitTest(const Vector2& sceneSize, RenderTaskList& renderTaskList, LayerList& layerList, const Vector2& screenCoordinates, Dali::HitTestAlgorithm::Results& results, Dali::HitTestAlgorithm::HitTestFunction func, bool isGeometry = false);
/**
* Given screen coordinates, this method returns the hit actor & the local coordinates relative to the actor etc.
* @param[in] screenCoordinates The screen coordinates.
* @param[out] results The results of the hit-test.
* @param[in] hitTestInterface Used to determine whether the actor is hit or whether we walk down its hierarchy
+ * @param[in] isGeometry If true, hittest works in a geometry way.
* @return true if something was hit
*
* <h3>Hit Test Algorithm:</h3>
* @note Currently, we prefer a child hit over a parent (regardless of the distance from the
* camera) unless the parent is a RenderableActor but this is subject to change.
*/
-bool HitTest(const Vector2& sceneSize, RenderTaskList& renderTaskList, LayerList& layerList, const Vector2& screenCoordinates, Results& results, HitTestInterface& hitTestInterface);
+bool HitTest(const Vector2& sceneSize, RenderTaskList& renderTaskList, LayerList& layerList, const Vector2& screenCoordinates, Results& results, HitTestInterface& hitTestInterface, bool isGeometry = false);
/**
* Default HitTest where we check if a touch is required.
* @param[in] screenCoordinates The screen coordinates.
* @param[out] results The results of the hit-test.
* @param[in] ownActor The actor from which the touch down was started.
+ * @param[in] isGeometry If true, hittest works in a geometry way.
* @return true if something was hit
*
* @see HitTest(Stage&, const Vector2&, Results&, HitTestInterface&)
*/
-bool HitTest(const Vector2& sceneSize, RenderTaskList& renderTaskList, LayerList& layerList, const Vector2& screenCoordinates, Results& results, const Actor* ownActor = nullptr);
+bool HitTest(const Vector2& sceneSize, RenderTaskList& renderTaskList, LayerList& layerList, const Vector2& screenCoordinates, Results& results, const Actor* ownActor = nullptr, bool isGeometry = false);
} // namespace HitTestAlgorithm
return consumedActor;
}
+/**
+ * Recursively deliver events to the actor and its below actor, until the event is consumed or the stage is reached.
+ */
+Dali::Actor EmitGeoHoverSignals(std::list<Dali::Internal::Actor*>& actorLists, const Dali::HoverEvent& hoverEvent)
+{
+ Dali::Actor consumedActor;
+
+ std::list<Dali::Internal::Actor*>::reverse_iterator rIter = actorLists.rbegin();
+ for (; rIter != actorLists.rend(); rIter++)
+ {
+ Actor* actorImpl(*rIter);
+ // Only emit the signal if the actor's hover signal has connections (or derived actor implementation requires hover).
+ if(ShouldEmitHoverEvent(*actorImpl, hoverEvent))
+ {
+ DALI_TRACE_SCOPE(gTraceFilter, "DALI_EMIT_HOVER_EVENT_SIGNAL");
+ PointState::Type currentState = actorImpl->GetHoverState();
+ actorImpl->SetHoverState(hoverEvent.GetState(0));
+ // If hover event is newly entering the actor, update it to the started state.
+ if(hoverEvent.GetState(0) == PointState::MOTION &&
+ (currentState == PointState::FINISHED || currentState == PointState::INTERRUPTED || currentState == PointState::LEAVE))
+ {
+ HoverEventPtr newHoverEvent = HoverEvent::Clone(GetImplementation(hoverEvent));
+ newHoverEvent->GetPoint(0).SetState(PointState::STARTED);
+ actorImpl->SetHoverState(PointState::STARTED); //update state
+ if(actorImpl->EmitHoverEventSignal(Dali::HoverEvent(newHoverEvent.Get())))
+ {
+ // One of this actor's listeners has consumed the event so set this actor as the consumed actor.
+ consumedActor = Dali::Actor(actorImpl);
+ break;
+ }
+ }
+ else if(actorImpl->EmitHoverEventSignal(hoverEvent))
+ {
+ // One of this actor's listeners has consumed the event so set this actor as the consumed actor.
+ consumedActor = Dali::Actor(actorImpl);
+ break;
+ }
+ }
+ }
+ return consumedActor;
+}
+
+
Dali::Actor AllocAndEmitHoverSignals(unsigned long time, Dali::Actor actor, const Integration::Point& point)
{
HoverEventPtr hoverEvent(new HoverEvent(time));
return EmitHoverSignals(actor, hoverEventHandle);
}
+Dali::Actor GeoAllocAndEmitHoverSignals(std::list<Dali::Internal::Actor*>& actorLists, unsigned long time, const Integration::Point& point)
+{
+ HoverEventPtr hoverEvent(new HoverEvent(time));
+ Dali::HoverEvent hoverEventHandle(hoverEvent.Get());
+
+ hoverEvent->AddPoint(point);
+
+ return EmitGeoHoverSignals(actorLists, hoverEventHandle);
+}
+
+
/**
* Changes the state of the primary point to leave and emits the hover signals
*/
-Dali::Actor EmitHoverSignals(Actor* actor, RenderTask& renderTask, const HoverEventPtr& originalEvent, PointState::Type state)
+Dali::Actor EmitHoverSignals(Actor* actor, RenderTask& renderTask, const HoverEventPtr& originalEvent, PointState::Type state, bool isGeometry)
{
HoverEventPtr hoverEvent = HoverEvent::Clone(*originalEvent.Get());
DALI_ASSERT_DEBUG(NULL != actor && "NULL actor pointer");
+ Dali::Actor consumingActor;
if(actor)
{
Integration::Point& primaryPoint = hoverEvent->GetPoint(0);
primaryPoint.SetState(state);
}
- return EmitHoverSignals(Dali::Actor(actor), Dali::HoverEvent(hoverEvent.Get()));
+ if(isGeometry)
+ {
+ std::list<Dali::Internal::Actor*> actorLists;
+ actorLists.push_back(actor);
+ consumingActor = EmitGeoHoverSignals(actorLists, Dali::HoverEvent(hoverEvent.Get()));
+ }
+ else
+ {
+ consumingActor = EmitHoverSignals(Dali::Actor(actor), Dali::HoverEvent(hoverEvent.Get()));
+ }
+ return consumingActor;
}
/**
return layer->IsHoverConsumed();
}
- bool ActorRequiresHitResultCheck(Actor* actor, Integration::Point point, Vector2 hitPointLocal, uint32_t timeStamp) override
+ bool ActorRequiresHitResultCheck(Actor* actor, Integration::Point point, Vector2 hitPointLocal, uint32_t timeStamp, bool isGeometry) override
{
// Hover event is always hit.
return true;
Integration::Point point;
point.SetState(PointState::INTERRUPTED);
point.SetHitActor(Dali::Actor(actor));
- AllocAndEmitHoverSignals(GetMilliSeconds(), point.GetHitActor(), point);
+ if(mScene.IsGeometryHittestEnabled())
+ {
+ std::list<Dali::Internal::Actor*> actorLists;
+ actorLists.push_back(actor);
+ GeoAllocAndEmitHoverSignals(actorLists, 0, point);
+ }
+ else
+ {
+ AllocAndEmitHoverSignals(GetMilliSeconds(), point.GetHitActor(), point);
+ }
Clear();
}
}
DALI_TRACE_SCOPE(gTraceFilter, "DALI_PROCESS_HOVER_EVENT");
+ bool isGeometry = mScene.IsGeometryHittestEnabled();
+
// Copy so we can add the results of a hit-test.
HoverEventPtr hoverEvent(new HoverEvent(event.time));
{
Dali::Actor lastPrimaryHitActorHandle(lastPrimaryHitActor);
currentPoint.SetHitActor(lastPrimaryHitActorHandle);
- consumingActor = AllocAndEmitHoverSignals(event.time, lastPrimaryHitActorHandle, currentPoint);
+ if(isGeometry)
+ {
+ consumingActor = GeoAllocAndEmitHoverSignals(mCandidateActorLists, event.time, currentPoint);
+ }
+ else
+ {
+ consumingActor = AllocAndEmitHoverSignals(event.time, lastPrimaryHitActorHandle, currentPoint);
+ }
}
// If the last consumed actor was different to the primary hit actor then inform it as well (if it has not already been informed).
Actor* lastConsumedActor(mLastConsumedActor.GetActor());
if(lastConsumedActor &&
- lastConsumedActor != lastPrimaryHitActor &&
- lastConsumedActor != consumingActor)
+ lastConsumedActor != lastPrimaryHitActor &&
+ lastConsumedActor != consumingActor)
{
Dali::Actor lastConsumedActorHandle(lastConsumedActor);
currentPoint.SetHitActor(lastConsumedActorHandle);
- AllocAndEmitHoverSignals(event.time, lastConsumedActorHandle, currentPoint);
+ if(isGeometry)
+ {
+ std::list<Dali::Internal::Actor*> actorLists;
+ actorLists.push_back(lastConsumedActor);
+ GeoAllocAndEmitHoverSignals(actorLists, event.time, currentPoint);
+ }
+ else
+ {
+ AllocAndEmitHoverSignals(event.time, lastConsumedActorHandle, currentPoint);
+ }
}
// Tell the hover-start consuming actor as well, if required
Actor* hoverStartConsumedActor(mHoverStartConsumedActor.GetActor());
if(hoverStartConsumedActor &&
- hoverStartConsumedActor != lastPrimaryHitActor &&
- hoverStartConsumedActor != lastConsumedActor &&
- hoverStartConsumedActor != consumingActor)
+ hoverStartConsumedActor != lastPrimaryHitActor &&
+ hoverStartConsumedActor != lastConsumedActor &&
+ hoverStartConsumedActor != consumingActor)
{
Dali::Actor hoverStartConsumedActorHandle(hoverStartConsumedActor);
currentPoint.SetHitActor(hoverStartConsumedActorHandle);
- AllocAndEmitHoverSignals(event.time, hoverStartConsumedActorHandle, currentPoint);
+ if(isGeometry)
+ {
+ std::list<Dali::Internal::Actor*> actorLists;
+ actorLists.push_back(hoverStartConsumedActor);
+ GeoAllocAndEmitHoverSignals(actorLists, event.time, currentPoint);
+ }
+ else
+ {
+ AllocAndEmitHoverSignals(event.time, hoverStartConsumedActorHandle, currentPoint);
+ }
}
Clear();
{
HitTestAlgorithm::Results hitTestResults;
ActorHoverableCheck actorHoverableCheck;
- HitTestAlgorithm::HitTest(mScene.GetSize(), mScene.GetRenderTaskList(), mScene.GetLayerList(), currentPoint.GetScreenPosition(), hitTestResults, actorHoverableCheck);
+ HitTestAlgorithm::HitTest(mScene.GetSize(), mScene.GetRenderTaskList(), mScene.GetLayerList(), currentPoint.GetScreenPosition(), hitTestResults, actorHoverableCheck, isGeometry);
Integration::Point newPoint(currentPoint);
newPoint.SetHitActor(hitTestResults.actor);
{
firstPointParsed = true;
currentRenderTask = hitTestResults.renderTask;
+ mCandidateActorLists = hitTestResults.actorLists;
}
}
if(currentRenderTask)
{
Dali::Actor hitActor = hoverEvent->GetHitActor(0);
- // If the actor is hit first, the hover is started.
- if(hitActor &&
- mLastPrimaryHitActor.GetActor() != hitActor &&
- state == PointState::MOTION)
+
+ if(isGeometry)
+ {
+ consumedActor = EmitGeoHoverSignals(mCandidateActorLists, hoverEventHandle);
+ }
+ else
{
- Actor* hitActorImpl = &GetImplementation(hitActor);
- if(hitActorImpl->GetLeaveRequired())
+ // If the actor is hit first, the hover is started.
+ if(hitActor &&
+ mLastPrimaryHitActor.GetActor() != hitActor &&
+ state == PointState::MOTION)
{
- hoverEvent->GetPoint(0).SetState(PointState::STARTED);
+ Actor* hitActorImpl = &GetImplementation(hitActor);
+ if(hitActorImpl->GetLeaveRequired())
+ {
+ hoverEvent->GetPoint(0).SetState(PointState::STARTED);
+ }
}
+ consumedActor = EmitHoverSignals(hitActor, hoverEventHandle);
}
- consumedActor = EmitHoverSignals(hitActor, hoverEventHandle);
if(hoverEvent->GetPoint(0).GetState() != PointState::MOTION)
{
RenderTask& lastRenderTaskImpl = *mLastRenderTask.Get();
if(lastPrimaryHitActor &&
- lastPrimaryHitActor != primaryHitActor &&
- lastPrimaryHitActor != consumedActor)
+ lastPrimaryHitActor != primaryHitActor &&
+ lastPrimaryHitActor != consumedActor)
{
if(lastPrimaryHitActor->IsHittable() && IsActuallySensitive(lastPrimaryHitActor))
{
- if(lastPrimaryHitActor->GetLeaveRequired())
+ if(isGeometry)
+ {
+ // This is a situation where actors who received a hover event must leave.
+ // Compare the lastActorList that received the hover event and the CandidateActorList that can receive the new hover event
+ // If the hover event can no longer be received, Leave is sent.
+ std::list<Dali::Internal::Actor*>::reverse_iterator rLastIter = mLastActorLists.rbegin();
+ for(; rLastIter != mLastActorLists.rend(); rLastIter++)
+ {
+ bool find = false;
+ std::list<Dali::Internal::Actor*>::reverse_iterator rCandidateIter = mCandidateActorLists.rbegin();
+ for(; rCandidateIter != mCandidateActorLists.rend(); rCandidateIter++)
+ {
+ if(*rCandidateIter == *rLastIter)
+ {
+ find = true;
+ break;
+ }
+ }
+ if(!find)
+ {
+ DALI_LOG_RELEASE_INFO("LeaveActor(Hit): (%p) %d %s\n", reinterpret_cast<void*>(*rLastIter), (*rLastIter)->GetId(), (*rLastIter)->GetName().data());
+ leaveEventConsumer = EmitHoverSignals(*rLastIter, lastRenderTaskImpl, hoverEvent, PointState::LEAVE, isGeometry);
+ }
+ // If the actor has been consumed, you do not need to proceed.
+ if(*rLastIter == lastConsumedActor)
+ {
+ break;
+ }
+ }
+ }
+ else if(lastPrimaryHitActor->GetLeaveRequired())
{
+ // In the case of isGeometry, it is not propagated but only sent to actors who are not hittable.
DALI_LOG_RELEASE_INFO("LeaveActor(Hit): (%p) %d %s\n", reinterpret_cast<void*>(lastPrimaryHitActor), lastPrimaryHitActor->GetId(), lastPrimaryHitActor->GetName().data());
- leaveEventConsumer = EmitHoverSignals(mLastPrimaryHitActor.GetActor(), lastRenderTaskImpl, hoverEvent, PointState::LEAVE);
+ leaveEventConsumer = EmitHoverSignals(mLastPrimaryHitActor.GetActor(), lastRenderTaskImpl, hoverEvent, PointState::LEAVE, isGeometry);
}
}
else if(primaryPointState != PointState::STARTED)
// At this point mLastPrimaryHitActor was touchable and sensitive in the previous touch event process but is not in the current one.
// An interrupted event is send to allow some actors to go back to their original state (i.e. Button controls)
DALI_LOG_RELEASE_INFO("InterruptedActor(Hit): (%p) %d %s\n", reinterpret_cast<void*>(lastPrimaryHitActor), lastPrimaryHitActor->GetId(), lastPrimaryHitActor->GetName().data());
- leaveEventConsumer = EmitHoverSignals(mLastPrimaryHitActor.GetActor(), lastRenderTaskImpl, hoverEvent, PointState::INTERRUPTED);
+ leaveEventConsumer = EmitHoverSignals(mLastPrimaryHitActor.GetActor(), lastRenderTaskImpl, hoverEvent, PointState::INTERRUPTED, isGeometry);
}
}
// consumed actor's listeners may need to be informed (through a leave event).
// Further checks here to ensure we do not signal the same actor twice for the same event.
if(lastConsumedActor &&
- lastConsumedActor != consumedActor &&
- lastConsumedActor != lastPrimaryHitActor &&
- lastConsumedActor != primaryHitActor &&
- lastConsumedActor != leaveEventConsumer)
+ lastConsumedActor != consumedActor &&
+ lastConsumedActor != lastPrimaryHitActor &&
+ lastConsumedActor != primaryHitActor &&
+ lastConsumedActor != leaveEventConsumer)
{
if(lastConsumedActor->IsHittable() && IsActuallySensitive(lastConsumedActor))
{
- if(lastConsumedActor->GetLeaveRequired())
+ if(lastConsumedActor->GetLeaveRequired() && !isGeometry) // For geometry, we have already sent leave. There is no need to send leave repeatedly.
{
DALI_LOG_RELEASE_INFO("LeaveActor(Consume): (%p) %d %s\n", reinterpret_cast<void*>(lastConsumedActor), lastConsumedActor->GetId(), lastConsumedActor->GetName().data());
- EmitHoverSignals(lastConsumedActor, lastRenderTaskImpl, hoverEvent, PointState::LEAVE);
+ EmitHoverSignals(lastConsumedActor, lastRenderTaskImpl, hoverEvent, PointState::LEAVE, isGeometry);
}
}
else if(primaryPointState != PointState::STARTED)
// At this point mLastConsumedActor was touchable and sensitive in the previous touch event process but is not in the current one.
// An interrupted event is send to allow some actors to go back to their original state (i.e. Button controls)
DALI_LOG_RELEASE_INFO("InterruptedActor(Consume): (%p) %d %s\n", reinterpret_cast<void*>(lastConsumedActor), lastConsumedActor->GetId(), lastConsumedActor->GetName().data());
- EmitHoverSignals(mLastConsumedActor.GetActor(), lastRenderTaskImpl, hoverEvent, PointState::INTERRUPTED);
+ EmitHoverSignals(mLastConsumedActor.GetActor(), lastRenderTaskImpl, hoverEvent, PointState::INTERRUPTED, isGeometry);
}
}
}
}
mLastRenderTask = currentRenderTask;
+ mLastActorLists = mCandidateActorLists;
}
else
{
Integration::Point primaryPoint = hoverEvent->GetPoint(0);
primaryPoint.SetHitActor(hoverStartConsumedActorHandle);
primaryPoint.SetState(PointState::INTERRUPTED);
- AllocAndEmitHoverSignals(event.time, hoverStartConsumedActorHandle, primaryPoint);
+ if(isGeometry)
+ {
+ std::list<Dali::Internal::Actor*> actorLists;
+ actorLists.push_back(hoverStartConsumedActor);
+ GeoAllocAndEmitHoverSignals(actorLists, event.time, primaryPoint);
+ }
+ else
+ {
+ AllocAndEmitHoverSignals(event.time, hoverStartConsumedActorHandle, primaryPoint);
+ }
// Restore hover-event to original state
primaryPoint.SetHitActor(primaryHitActor);
mLastPrimaryHitActor.SetActor(nullptr);
mLastConsumedActor.SetActor(nullptr);
mLastRenderTask.Reset();
+ mLastActorLists.clear();
}
void HoverEventProcessor::OnObservedActorDisconnected(Dali::Internal::Actor* actor)
*/
void OnObservedActorDisconnected(Dali::Internal::Actor* actor);
- Scene& mScene; ///< Reference to the scene
- ActorObserver mLastPrimaryHitActor; ///< Stores the last primary point hit actor
- ActorObserver mLastConsumedActor; ///< Stores the last consumed actor
- ActorObserver mHoverStartConsumedActor; ///< Stores the hover-start consumed actor
- RenderTaskPtr mLastRenderTask; ///< The RenderTask used for the last hit actor
+ Scene& mScene; ///< Reference to the scene
+ ActorObserver mLastPrimaryHitActor; ///< Stores the last primary point hit actor
+ ActorObserver mLastConsumedActor; ///< Stores the last consumed actor
+ ActorObserver mHoverStartConsumedActor; ///< Stores the hover-start consumed actor
+ RenderTaskPtr mLastRenderTask; ///< The RenderTask used for the last hit actor
+ std::list<Dali::Internal::Actor*> mCandidateActorLists; ///< Stores a list of actors that can be touched, from leaf actor to root.
+ std::list<Dali::Internal::Actor*> mLastActorLists; ///< Stores a list of actors that can be touched, from leaf actor to root.
};
} // namespace Internal
return actorImpl.GetTouchRequired() && (state != PointState::MOTION || actorImpl.IsDispatchTouchMotion());
}
+// child -> parent
Dali::Actor EmitInterceptTouchSignals(Dali::Actor actor, const Dali::TouchEvent& touchEvent)
{
Dali::Actor interceptedActor;
}
}
}
+ return interceptedActor;
+}
+// geometry
+// child -> below
+Dali::Actor EmitGeoInterceptTouchSignals(std::list<Dali::Internal::Actor*>& actorLists, std::list<Dali::Internal::Actor*>& interceptActorList, const Dali::TouchEvent& touchEvent)
+{
+ interceptActorList.clear();
+ Dali::Actor interceptedActor;
+ for(auto&& actor : actorLists)
+ {
+ interceptActorList.push_back(actor);
+ if(ShouldEmitInterceptTouchEvent(*actor, touchEvent))
+ {
+ DALI_TRACE_SCOPE(gTraceFilter, "DALI_EMIT_INTERCEPT_TOUCH_EVENT_SIGNAL");
+ if(actor->EmitInterceptTouchEventSignal(touchEvent))
+ {
+ interceptedActor = Dali::Actor(actor);
+ break;
+ }
+ }
+ }
return interceptedActor;
}
return consumedActor;
}
+/**
+ * Recursively deliver events to the actor and its below actor, until the event is consumed or the stage is reached.
+ */
+Dali::Actor EmitGeoTouchSignals(std::list<Dali::Internal::Actor*>& actorLists, const Dali::TouchEvent& touchEvent)
+{
+ Dali::Actor consumedActor;
+
+ std::list<Dali::Internal::Actor*>::reverse_iterator rIter = actorLists.rbegin();
+ for (; rIter != actorLists.rend(); rIter++)
+ {
+ Actor* actorImpl(*rIter);
+ // Only emit the signal if the actor's touch signal has connections (or derived actor implementation requires touch).
+ if(ShouldEmitTouchEvent(*actorImpl, touchEvent))
+ {
+ DALI_TRACE_SCOPE(gTraceFilter, "DALI_EMIT_TOUCH_EVENT_SIGNAL");
+ if(actorImpl->EmitTouchEventSignal(touchEvent))
+ {
+ // One of this actor's listeners has consumed the event so set this actor as the consumed actor.
+ consumedActor = Dali::Actor(actorImpl);
+ break;
+ }
+ }
+ }
+ return consumedActor;
+}
+
Dali::Actor AllocAndEmitTouchSignals(unsigned long time, Dali::Actor actor, const Integration::Point& point, RenderTaskPtr renderTask)
{
TouchEventPtr touchEvent(new TouchEvent(time));
return EmitTouchSignals(actor, touchEventHandle);
}
+Dali::Actor GeoAllocAndEmitTouchSignals(std::list<Dali::Internal::Actor*>& actorLists, unsigned long time, const Integration::Point& point, RenderTaskPtr renderTask)
+{
+ TouchEventPtr touchEvent(new TouchEvent(time));
+ Dali::TouchEvent touchEventHandle(touchEvent.Get());
+
+ touchEvent->AddPoint(point);
+ touchEvent->SetRenderTask(Dali::RenderTask(renderTask.Get()));
+
+ return EmitGeoTouchSignals(actorLists, touchEventHandle);
+}
+
/**
* Changes the state of the primary point to leave and emits the touch signals
*/
-Dali::Actor EmitTouchSignals(Actor* actor, RenderTask& renderTask, const TouchEventPtr& originalTouchEvent, PointState::Type state)
+Dali::Actor EmitTouchSignals(Actor* actor, RenderTask& renderTask, const TouchEventPtr& originalTouchEvent, PointState::Type state, bool isGeometry)
{
Dali::Actor consumingActor;
primaryPoint.SetHitActor(Dali::Actor(actor));
primaryPoint.SetState(state);
- consumingActor = EmitTouchSignals(Dali::Actor(actor), Dali::TouchEvent(touchEventImpl.Get()));
+ if(isGeometry)
+ {
+ std::list<Dali::Internal::Actor*> actorLists;
+ actorLists.push_back(actor);
+ consumingActor = EmitGeoTouchSignals(actorLists, Dali::TouchEvent(touchEventImpl.Get()));
+ }
+ else
+ {
+ consumingActor = EmitTouchSignals(Dali::Actor(actor), Dali::TouchEvent(touchEventImpl.Get()));
+ }
}
return consumingActor;
* @param[in] lastRenderTask The last render task member
* @param[in] currentPoint The current point information
* @param[in] scene The scene that this touch is related to
+ * @param[in] actorLists The list of actors that can be touched, from leaf actor to root.
*/
void ParsePrimaryTouchPoint(
HitTestAlgorithm::Results& hitTestResults,
ActorObserver& ownTouchActorObserver,
const RenderTaskPtr& lastRenderTask,
const Integration::Point& currentPoint,
- const Internal::Scene& scene)
+ const Internal::Scene& scene,
+ std::list<Dali::Internal::Actor*>& actorLists)
{
Actor* capturingTouchActor = capturingTouchActorObserver.GetActor();
else
{
Actor* ownTouchActor = ownTouchActorObserver.GetActor();
- HitTestAlgorithm::HitTest(scene.GetSize(), scene.GetRenderTaskList(), scene.GetLayerList(), currentPoint.GetScreenPosition(), hitTestResults, ownTouchActor);
+ HitTestAlgorithm::HitTest(scene.GetSize(), scene.GetRenderTaskList(), scene.GetLayerList(), currentPoint.GetScreenPosition(), hitTestResults, ownTouchActor, scene.IsGeometryHittestEnabled());
if(currentPoint.GetState() == PointState::STARTED && hitTestResults.actor)
{
+ bool isGeometry = scene.IsGeometryHittestEnabled();
// If we've just started touch, then check whether the actor has requested to capture all touch events
Actor* hitActor = &GetImplementation(hitTestResults.actor);
- if(hitActor->CapturesAllTouchAfterStart())
+ if(hitActor->CapturesAllTouchAfterStart() || isGeometry)
{
capturingTouchActorObserver.SetActor(hitActor);
}
- if(hitActor->IsAllowedOnlyOwnTouch())
+ if(hitActor->IsAllowedOnlyOwnTouch() || isGeometry)
{
ownTouchActorObserver.SetActor(hitActor);
}
+ if(isGeometry)
+ {
+ actorLists = hitTestResults.actorLists;
+ }
}
}
}
DALI_TRACE_SCOPE(gTraceFilter, "DALI_PROCESS_TOUCH_EVENT");
+ bool isGeometry = mScene.IsGeometryHittestEnabled();
+
// 1) Check if it is an interrupted event - we should inform our last primary hit actor about this
// and emit the stage signal as well.
Dali::Actor consumingActor;
Integration::Point currentPoint(event.points[0]);
- Actor* lastPrimaryHitActor(mLastPrimaryHitActor.GetActor());
- if(lastPrimaryHitActor)
+ if(isGeometry)
{
- Dali::Actor lastPrimaryHitActorHandle(lastPrimaryHitActor);
- currentPoint.SetHitActor(lastPrimaryHitActorHandle);
+ // Since the geometry way only receives touch events from the consumed actor,
+ // it first searches for whether there is a consumed actor and then sends the event
+ Actor* touchConsumedActor(mLastConsumedActor.GetActor());
+ Actor* touchDownConsumedActor(mTouchDownConsumedActor.GetActor());
+ Actor* lastPrimaryHitActor(mLastPrimaryHitActor.GetActor());
+ if(touchConsumedActor)
+ {
+ Dali::Actor touchConsumedActorHandle(touchConsumedActor);
+ currentPoint.SetHitActor(touchConsumedActorHandle);
+ std::list<Dali::Internal::Actor*> actorLists;
+ actorLists.push_back(touchConsumedActor);
+ GeoAllocAndEmitTouchSignals(actorLists, event.time, currentPoint, mLastRenderTask);
+ }
+ else if(touchDownConsumedActor)
+ {
+ Dali::Actor touchDownConsumedActorHandle(touchDownConsumedActor);
+ currentPoint.SetHitActor(touchDownConsumedActorHandle);
+ std::list<Dali::Internal::Actor*> actorLists;
+ actorLists.push_back(touchDownConsumedActor);
+ GeoAllocAndEmitTouchSignals(actorLists, event.time, currentPoint, mLastRenderTask);
+ }
+ else if(lastPrimaryHitActor)
+ {
+ Dali::Actor lastPrimaryHitActorHandle(lastPrimaryHitActor);
+ currentPoint.SetHitActor(lastPrimaryHitActorHandle);
- consumingActor = AllocAndEmitTouchSignals(event.time, lastPrimaryHitActorHandle, currentPoint, mLastRenderTask);
+ GeoAllocAndEmitTouchSignals(mCandidateActorLists, event.time, currentPoint, mLastRenderTask);
+ }
}
-
- // If the last consumed actor was different to the primary hit actor then inform it as well (if it has not already been informed).
- Actor* lastConsumedActor(mLastConsumedActor.GetActor());
- if(lastConsumedActor &&
- lastConsumedActor != lastPrimaryHitActor &&
- lastConsumedActor != consumingActor)
+ else
{
- Dali::Actor lastConsumedActorHandle(lastConsumedActor);
- currentPoint.SetHitActor(lastConsumedActorHandle);
- AllocAndEmitTouchSignals(event.time, lastConsumedActorHandle, currentPoint, mLastRenderTask);
- }
+ Actor* lastPrimaryHitActor(mLastPrimaryHitActor.GetActor());
+ if(lastPrimaryHitActor)
+ {
+ Dali::Actor lastPrimaryHitActorHandle(lastPrimaryHitActor);
+ currentPoint.SetHitActor(lastPrimaryHitActorHandle);
- // Tell the touch-down consuming actor as well, if required
- Actor* touchDownConsumedActor(mTouchDownConsumedActor.GetActor());
- if(touchDownConsumedActor &&
- touchDownConsumedActor != lastPrimaryHitActor &&
- touchDownConsumedActor != lastConsumedActor &&
- touchDownConsumedActor != consumingActor)
- {
- Dali::Actor touchDownConsumedActorHandle(touchDownConsumedActor);
+ consumingActor = AllocAndEmitTouchSignals(event.time, lastPrimaryHitActorHandle, currentPoint, mLastRenderTask);
+ }
+
+ // If the last consumed actor was different to the primary hit actor then inform it as well (if it has not already been informed).
+ Actor* lastConsumedActor(mLastConsumedActor.GetActor());
+ if(lastConsumedActor &&
+ lastConsumedActor != lastPrimaryHitActor &&
+ lastConsumedActor != consumingActor)
+ {
+ Dali::Actor lastConsumedActorHandle(lastConsumedActor);
+ currentPoint.SetHitActor(lastConsumedActorHandle);
+ AllocAndEmitTouchSignals(event.time, lastConsumedActorHandle, currentPoint, mLastRenderTask);
+ }
- currentPoint.SetHitActor(touchDownConsumedActorHandle);
- AllocAndEmitTouchSignals(event.time, touchDownConsumedActorHandle, currentPoint, mLastRenderTask);
+ // Tell the touch-down consuming actor as well, if required
+ Actor* touchDownConsumedActor(mTouchDownConsumedActor.GetActor());
+ if(touchDownConsumedActor &&
+ touchDownConsumedActor != lastPrimaryHitActor &&
+ touchDownConsumedActor != lastConsumedActor &&
+ touchDownConsumedActor != consumingActor)
+ {
+ Dali::Actor touchDownConsumedActorHandle(touchDownConsumedActor);
+
+ currentPoint.SetHitActor(touchDownConsumedActorHandle);
+ AllocAndEmitTouchSignals(event.time, touchDownConsumedActorHandle, currentPoint, mLastRenderTask);
+ }
}
Clear();
if(!firstPointParsed)
{
firstPointParsed = true;
- ParsePrimaryTouchPoint(hitTestResults, mCapturingTouchActor, mOwnTouchActor, mLastRenderTask, currentPoint, mScene);
+ ParsePrimaryTouchPoint(hitTestResults, mCapturingTouchActor, mOwnTouchActor, mLastRenderTask, currentPoint, mScene, mCandidateActorLists);
// Only set the currentRenderTask for the primary hit actor.
currentRenderTask = hitTestResults.renderTask;
}
else
{
- HitTestAlgorithm::HitTest(mScene.GetSize(), mScene.GetRenderTaskList(), mScene.GetLayerList(), currentPoint.GetScreenPosition(), hitTestResults);
+ HitTestAlgorithm::HitTest(mScene.GetSize(), mScene.GetRenderTaskList(), mScene.GetLayerList(), currentPoint.GetScreenPosition(), hitTestResults, nullptr, isGeometry);
}
Integration::Point newPoint(currentPoint);
if(currentRenderTask)
{
- Actor* interceptedTouchActor(mInterceptedTouchActor.GetActor());
- if(interceptedTouchActor)
+ if(isGeometry)
{
- Dali::Actor interceptedTouchActorHandle(interceptedTouchActor);
- consumedActor = EmitTouchSignals(interceptedTouchActorHandle, touchEventHandle);
+ Actor* touchConsumedActor(mLastConsumedActor.GetActor());
+ Actor* interceptedTouchActor(mInterceptedTouchActor.GetActor());
+ if(touchConsumedActor) // If there is a consultative actor, send events only to the consultative actor.
+ {
+ RenderTask& currentRenderTaskImpl = *currentRenderTask.Get();
+ consumedActor = EmitTouchSignals(touchConsumedActor, currentRenderTaskImpl, touchEventImpl, primaryPointState, isGeometry);
+ }
+ else if(interceptedTouchActor) // If there is an intercepted actor, send a touch event starting from the intercepted actor.
+ {
+ Dali::Actor interceptedTouchActorHandle(interceptedTouchActor);
+ std::list<Dali::Internal::Actor*> interceptActorLists = mInterceptedActorLists;
+ consumedActor = EmitGeoTouchSignals(interceptActorLists, touchEventHandle);
+ }
+ else
+ {
+ Dali::Actor interceptedActor;
+ // Let's find out if there is an intercept actor.
+ interceptedActor = EmitGeoInterceptTouchSignals(mCandidateActorLists, mInterceptedActorLists, touchEventHandle);
+ if(interceptedActor)
+ {
+ mInterceptedTouchActor.SetActor(&GetImplementation(interceptedActor));
+
+ // If there is an interception, send an interrupted event to the last consumed actor or to the actor that hit previously.
+ if(mLastConsumedActor.GetActor() &&
+ mLastConsumedActor.GetActor() != interceptedActor &&
+ mLastRenderTask &&
+ mLastPrimaryPointState != PointState::FINISHED)
+ {
+ EmitTouchSignals(mLastConsumedActor.GetActor(), *mLastRenderTask.Get(), touchEventImpl, PointState::INTERRUPTED, isGeometry);
+ mTouchDownConsumedActor.SetActor(nullptr);
+ mLastConsumedActor.SetActor(nullptr);
+ }
+ else if(mLastPrimaryHitActor.GetActor() &&
+ mLastPrimaryHitActor.GetActor() != interceptedActor &&
+ mLastRenderTask &&
+ mLastPrimaryPointState != PointState::FINISHED)
+ {
+ std::list<Dali::Internal::Actor*> internalActorLists = mCandidateActorLists;
+ while(!internalActorLists.empty())
+ {
+ Actor* actorImpl = internalActorLists.back();
+ // Only emit the signal if the actor's touch signal has connections (or derived actor implementation requires touch).
+ if(actorImpl->GetTouchRequired())
+ {
+ EmitTouchSignals(actorImpl, *mLastRenderTask.Get(), touchEventImpl, PointState::INTERRUPTED, isGeometry);
+ }
+ internalActorLists.pop_back();
+ }
+ }
+ }
+
+ // Let's propagate touch events from the intercepted actor or start propagating touch events from the leaf actor.
+ consumedActor = EmitGeoTouchSignals(interceptedActor ? mInterceptedActorLists : mCandidateActorLists, touchEventHandle);
+ }
}
else
{
- // Emit the intercept touch signal
- Dali::Actor interceptedActor = EmitInterceptTouchSignals(primaryHitActor, touchEventHandle);
- if(interceptedActor)
+ Actor* interceptedTouchActor(mInterceptedTouchActor.GetActor());
+ if(interceptedTouchActor)
{
- mInterceptedTouchActor.SetActor(&GetImplementation(interceptedActor));
- // If the child is being touched, INTERRUPTED is sent.
- if(mLastPrimaryHitActor.GetActor() &&
- mLastPrimaryHitActor.GetActor() != interceptedActor &&
- mLastRenderTask &&
- mLastPrimaryPointState != PointState::FINISHED)
- {
- EmitTouchSignals(mLastPrimaryHitActor.GetActor(), *mLastRenderTask.Get(), touchEventImpl, PointState::INTERRUPTED);
- mTouchDownConsumedActor.SetActor(nullptr);
- }
- consumedActor = EmitTouchSignals(interceptedActor, touchEventHandle);
+ Dali::Actor interceptedTouchActorHandle(interceptedTouchActor);
+ consumedActor = EmitTouchSignals(interceptedTouchActorHandle, touchEventHandle);
}
else
{
- consumedActor = EmitTouchSignals(primaryHitActor, touchEventHandle);
+ // Emit the intercept touch signal
+ Dali::Actor interceptedActor = EmitInterceptTouchSignals(primaryHitActor, touchEventHandle);
+ if(interceptedActor)
+ {
+ mInterceptedTouchActor.SetActor(&GetImplementation(interceptedActor));
+ // If the child is being touched, INTERRUPTED is sent.
+ if(mLastPrimaryHitActor.GetActor() &&
+ mLastPrimaryHitActor.GetActor() != interceptedActor &&
+ mLastRenderTask &&
+ mLastPrimaryPointState != PointState::FINISHED)
+ {
+ EmitTouchSignals(mLastPrimaryHitActor.GetActor(), *mLastRenderTask.Get(), touchEventImpl, PointState::INTERRUPTED, isGeometry);
+ mTouchDownConsumedActor.SetActor(nullptr);
+ }
+ consumedActor = EmitTouchSignals(interceptedActor, touchEventHandle);
+ }
+ else
+ {
+ consumedActor = EmitTouchSignals(primaryHitActor, touchEventHandle);
+ }
}
}
+
consumed = consumedActor ? true : false;
if(primaryPointState == PointState::MOTION)
{
- DALI_LOG_INFO(gLogFilter, Debug::Concise, "PrimaryHitActor: (%p) id(%d), name(%s), state(%s), screenPosition(%f, %f)\n", primaryHitActor ? reinterpret_cast<void*>(&primaryHitActor.GetBaseObject()) : NULL, primaryHitActor ? primaryHitActor.GetProperty<int32_t>(Dali::Actor::Property::ID) : -1, primaryHitActor ? primaryHitActor.GetProperty<std::string>(Dali::Actor::Property::NAME).c_str() : "", TOUCH_POINT_STATE[primaryPointState], primaryPoint.GetScreenPosition().x, primaryPoint.GetScreenPosition().y);
- DALI_LOG_INFO(gLogFilter, Debug::Concise, "ConsumedActor: (%p) id(%d), name(%s), state(%s)\n", consumedActor ? reinterpret_cast<void*>(&consumedActor.GetBaseObject()) : NULL, consumedActor ? consumedActor.GetProperty<int32_t>(Dali::Actor::Property::ID) : -1, consumedActor ? consumedActor.GetProperty<std::string>(Dali::Actor::Property::NAME).c_str() : "", TOUCH_POINT_STATE[primaryPointState]);
+ DALI_LOG_INFO(gLogFilter, Debug::Concise, "PrimaryHitActor: (%p) id(%d), name(%s), state(%s), screenPosition(%f, %f), isGeo : %d \n", primaryHitActor ? reinterpret_cast<void*>(&primaryHitActor.GetBaseObject()) : NULL, primaryHitActor ? primaryHitActor.GetProperty<int32_t>(Dali::Actor::Property::ID) : -1, primaryHitActor ? primaryHitActor.GetProperty<std::string>(Dali::Actor::Property::NAME).c_str() : "", TOUCH_POINT_STATE[primaryPointState], primaryPoint.GetScreenPosition().x, primaryPoint.GetScreenPosition().y, isGeometry);
+ DALI_LOG_INFO(gLogFilter, Debug::Concise, "ConsumedActor: (%p) id(%d), name(%s), state(%s), isGeo : %d \n", consumedActor ? reinterpret_cast<void*>(&consumedActor.GetBaseObject()) : NULL, consumedActor ? consumedActor.GetProperty<int32_t>(Dali::Actor::Property::ID) : -1, consumedActor ? consumedActor.GetProperty<std::string>(Dali::Actor::Property::NAME).c_str() : "", TOUCH_POINT_STATE[primaryPointState], isGeometry);
}
else
{
- DALI_LOG_RELEASE_INFO("PrimaryHitActor:(%p), id(%d), name(%s), state(%s), screenPosition(%f, %f)\n", primaryHitActor ? reinterpret_cast<void*>(&primaryHitActor.GetBaseObject()) : NULL, primaryHitActor ? primaryHitActor.GetProperty<int32_t>(Dali::Actor::Property::ID) : -1, primaryHitActor ? primaryHitActor.GetProperty<std::string>(Dali::Actor::Property::NAME).c_str() : "", TOUCH_POINT_STATE[primaryPointState], primaryPoint.GetScreenPosition().x, primaryPoint.GetScreenPosition().y);
- DALI_LOG_RELEASE_INFO("ConsumedActor: (%p), id(%d), name(%s), state(%s)\n", consumedActor ? reinterpret_cast<void*>(&consumedActor.GetBaseObject()) : NULL, consumedActor ? consumedActor.GetProperty<int32_t>(Dali::Actor::Property::ID) : -1, consumedActor ? consumedActor.GetProperty<std::string>(Dali::Actor::Property::NAME).c_str() : "", TOUCH_POINT_STATE[primaryPointState]);
+ DALI_LOG_RELEASE_INFO("PrimaryHitActor:(%p), id(%d), name(%s), state(%s), screenPosition(%f, %f), isGeo : %d \n", primaryHitActor ? reinterpret_cast<void*>(&primaryHitActor.GetBaseObject()) : NULL, primaryHitActor ? primaryHitActor.GetProperty<int32_t>(Dali::Actor::Property::ID) : -1, primaryHitActor ? primaryHitActor.GetProperty<std::string>(Dali::Actor::Property::NAME).c_str() : "", TOUCH_POINT_STATE[primaryPointState], primaryPoint.GetScreenPosition().x, primaryPoint.GetScreenPosition().y, isGeometry);
+ DALI_LOG_RELEASE_INFO("ConsumedActor: (%p), id(%d), name(%s), state(%s), isGeo : %d \n", consumedActor ? reinterpret_cast<void*>(&consumedActor.GetBaseObject()) : NULL, consumedActor ? consumedActor.GetProperty<int32_t>(Dali::Actor::Property::ID) : -1, consumedActor ? consumedActor.GetProperty<std::string>(Dali::Actor::Property::NAME).c_str() : "", TOUCH_POINT_STATE[primaryPointState], isGeometry);
}
}
Dali::Actor leaveEventConsumer;
RenderTask& lastRenderTaskImpl = *mLastRenderTask.Get();
- if(lastPrimaryHitActor &&
- lastPrimaryHitActor != primaryHitActor &&
- lastPrimaryHitActor != consumedActor)
+ if(isGeometry)
{
- if(lastPrimaryHitActor->IsHittable() && IsActuallySensitive(lastPrimaryHitActor))
+ if(lastPrimaryHitActor)
{
- if(lastPrimaryHitActor->GetLeaveRequired())
+ if(!lastPrimaryHitActor->IsHittable() || !IsActuallySensitive(lastPrimaryHitActor))
{
- DALI_LOG_RELEASE_INFO("LeaveActor(Hit): (%p) %d %s\n", reinterpret_cast<void*>(lastPrimaryHitActor), lastPrimaryHitActor->GetId(), lastPrimaryHitActor->GetName().data());
- leaveEventConsumer = EmitTouchSignals(lastPrimaryHitActor, lastRenderTaskImpl, touchEventImpl, PointState::LEAVE);
+ // At this point mLastPrimaryHitActor was touchable and sensitive in the previous touch event process but is not in the current one.
+ // An interrupted event is send to allow some actors to go back to their original state (i.e. Button controls)
+ DALI_LOG_RELEASE_INFO("InterruptedActor(Hit): (%p) %s\n", reinterpret_cast<void*>(lastPrimaryHitActor), lastPrimaryHitActor->GetName().data());
+ leaveEventConsumer = EmitTouchSignals(lastPrimaryHitActor, lastRenderTaskImpl, touchEventImpl, PointState::INTERRUPTED, isGeometry);
}
}
- else
+
+ consumed |= leaveEventConsumer ? true : false;
+
+ // Check if the motion event has been consumed by another actor's listener. In this case, the previously
+ // consumed actor's listeners may need to be informed (through a leave event).
+ // Further checks here to ensure we do not signal the same actor twice for the same event.
+ if(lastConsumedActor &&
+ lastConsumedActor != lastPrimaryHitActor &&
+ lastConsumedActor != leaveEventConsumer)
{
- // At this point mLastPrimaryHitActor was touchable and sensitive in the previous touch event process but is not in the current one.
- // An interrupted event is send to allow some actors to go back to their original state (i.e. Button controls)
- DALI_LOG_RELEASE_INFO("InterruptedActor(Hit): (%p) %d %s\n", reinterpret_cast<void*>(lastPrimaryHitActor), lastPrimaryHitActor->GetId(), lastPrimaryHitActor->GetName().data());
- leaveEventConsumer = EmitTouchSignals(lastPrimaryHitActor, lastRenderTaskImpl, touchEventImpl, PointState::INTERRUPTED);
+ if(!lastConsumedActor->IsHittable() || !IsActuallySensitive(lastConsumedActor))
+ {
+ // At this point mLastConsumedActor was touchable and sensitive in the previous touch event process but is not in the current one.
+ // An interrupted event is send to allow some actors to go back to their original state (i.e. Button controls)
+ DALI_LOG_RELEASE_INFO("InterruptedActor(Consume): (%p) %s\n", reinterpret_cast<void*>(lastConsumedActor), lastConsumedActor->GetName().data());
+ EmitTouchSignals(mLastConsumedActor.GetActor(), lastRenderTaskImpl, touchEventImpl, PointState::INTERRUPTED, isGeometry);
+ }
}
}
-
- consumed |= leaveEventConsumer ? true : false;
-
- // Check if the motion event has been consumed by another actor's listener. In this case, the previously
- // consumed actor's listeners may need to be informed (through a leave event).
- // Further checks here to ensure we do not signal the same actor twice for the same event.
- if(lastConsumedActor &&
- lastConsumedActor != consumedActor &&
- lastConsumedActor != lastPrimaryHitActor &&
- lastConsumedActor != primaryHitActor &&
- lastConsumedActor != leaveEventConsumer)
+ else
{
- if(lastConsumedActor->IsHittable() && IsActuallySensitive(lastConsumedActor))
+ if(lastPrimaryHitActor &&
+ lastPrimaryHitActor != primaryHitActor &&
+ lastPrimaryHitActor != consumedActor)
{
- if(lastConsumedActor->GetLeaveRequired())
+ if(lastPrimaryHitActor->IsHittable() && IsActuallySensitive(lastPrimaryHitActor))
+ {
+ if(lastPrimaryHitActor->GetLeaveRequired())
+ {
+ DALI_LOG_RELEASE_INFO("LeaveActor(Hit): (%p) %d %s\n", reinterpret_cast<void*>(lastPrimaryHitActor), lastPrimaryHitActor->GetId(), lastPrimaryHitActor->GetName().data());
+ leaveEventConsumer = EmitTouchSignals(lastPrimaryHitActor, lastRenderTaskImpl, touchEventImpl, PointState::LEAVE, isGeometry);
+ }
+ }
+ else
{
- DALI_LOG_RELEASE_INFO("LeaveActor(Consume): (%p) %d %s\n", reinterpret_cast<void*>(lastConsumedActor), lastConsumedActor->GetId(), lastConsumedActor->GetName().data());
- EmitTouchSignals(lastConsumedActor, lastRenderTaskImpl, touchEventImpl, PointState::LEAVE);
+ // At this point mLastPrimaryHitActor was touchable and sensitive in the previous touch event process but is not in the current one.
+ // An interrupted event is send to allow some actors to go back to their original state (i.e. Button controls)
+ DALI_LOG_RELEASE_INFO("InterruptedActor(Hit): (%p) %d %s\n", reinterpret_cast<void*>(lastPrimaryHitActor), lastPrimaryHitActor->GetId(), lastPrimaryHitActor->GetName().data());
+ leaveEventConsumer = EmitTouchSignals(lastPrimaryHitActor, lastRenderTaskImpl, touchEventImpl, PointState::INTERRUPTED, isGeometry);
}
}
- else
+
+ consumed |= leaveEventConsumer ? true : false;
+
+ // Check if the motion event has been consumed by another actor's listener. In this case, the previously
+ // consumed actor's listeners may need to be informed (through a leave event).
+ // Further checks here to ensure we do not signal the same actor twice for the same event.
+ if(lastConsumedActor &&
+ lastConsumedActor != consumedActor &&
+ lastConsumedActor != lastPrimaryHitActor &&
+ lastConsumedActor != primaryHitActor &&
+ lastConsumedActor != leaveEventConsumer)
{
- // At this point mLastConsumedActor was touchable and sensitive in the previous touch event process but is not in the current one.
- // An interrupted event is send to allow some actors to go back to their original state (i.e. Button controls)
- DALI_LOG_RELEASE_INFO("InterruptedActor(Consume): (%p) %d %s\n", reinterpret_cast<void*>(lastConsumedActor), lastConsumedActor->GetId(), lastConsumedActor->GetName().data());
- EmitTouchSignals(mLastConsumedActor.GetActor(), lastRenderTaskImpl, touchEventImpl, PointState::INTERRUPTED);
+ if(lastConsumedActor->IsHittable() && IsActuallySensitive(lastConsumedActor))
+ {
+ if(lastConsumedActor->GetLeaveRequired())
+ {
+ DALI_LOG_RELEASE_INFO("LeaveActor(Consume): (%p) %d %s\n", reinterpret_cast<void*>(lastConsumedActor), lastConsumedActor->GetId(), lastConsumedActor->GetName().data());
+ EmitTouchSignals(lastConsumedActor, lastRenderTaskImpl, touchEventImpl, PointState::LEAVE, isGeometry);
+ }
+ }
+ else
+ {
+ // At this point mLastConsumedActor was touchable and sensitive in the previous touch event process but is not in the current one.
+ // An interrupted event is send to allow some actors to go back to their original state (i.e. Button controls)
+ DALI_LOG_RELEASE_INFO("InterruptedActor(Consume): (%p) %d %s\n", reinterpret_cast<void*>(lastConsumedActor), lastConsumedActor->GetId(), lastConsumedActor->GetName().data());
+ EmitTouchSignals(mLastConsumedActor.GetActor(), lastRenderTaskImpl, touchEventImpl, PointState::INTERRUPTED, isGeometry);
+ }
}
}
}
}
else
{
- mLastConsumedActor.SetActor(nullptr);
+ if(isGeometry)
+ {
+ if(lastConsumedActor && !lastConsumedActor->OnScene())
+ {
+ mLastConsumedActor.SetActor(nullptr);
+ }
+ }
+ else
+ {
+ mLastConsumedActor.SetActor(nullptr);
+ }
}
mLastRenderTask = currentRenderTask;
currentPoint.SetHitActor(touchDownConsumedActorHandle);
currentPoint.SetState(PointState::INTERRUPTED);
- AllocAndEmitTouchSignals(event.time, touchDownConsumedActorHandle, currentPoint, nullptr /* Not Required for this use case */);
+ if(isGeometry)
+ {
+ std::list<Dali::Internal::Actor*> actorLists;
+ actorLists.push_back(touchDownConsumedActor);
+ GeoAllocAndEmitTouchSignals(actorLists, event.time, currentPoint, nullptr /* Not Required for this use case */);
+ }
+ else
+ {
+ AllocAndEmitTouchSignals(event.time, touchDownConsumedActorHandle, currentPoint, nullptr /* Not Required for this use case */);
+ }
}
mTouchDownConsumedActor.SetActor(nullptr);
void TouchEventProcessor::OnObservedActorDisconnected(Actor* actor)
{
- if(actor == mLastPrimaryHitActor.GetActor())
+ if(mScene.IsGeometryHittestEnabled() && (actor == mLastConsumedActor.GetActor() || actor == mLastPrimaryHitActor.GetActor()))
{
Dali::Actor actorHandle(actor);
-
Integration::Point point;
point.SetState(PointState::INTERRUPTED);
point.SetHitActor(actorHandle);
-
- TouchEventPtr touchEventImpl(new TouchEvent);
- touchEventImpl->AddPoint(point);
- Dali::TouchEvent touchEventHandle(touchEventImpl.Get());
-
- Dali::Actor eventConsumer = EmitTouchSignals(actorHandle, touchEventHandle);
-
- if(mLastConsumedActor.GetActor() != eventConsumer)
+ if(actor == mLastConsumedActor.GetActor())
{
- EmitTouchSignals(Dali::Actor(mLastConsumedActor.GetActor()), touchEventHandle);
+ std::list<Dali::Internal::Actor*> actorLists;
+ actorLists.push_back(mLastConsumedActor.GetActor());
+ GeoAllocAndEmitTouchSignals(actorLists, 0, point, mLastRenderTask);
+ }
+ else if(!mLastConsumedActor.GetActor())
+ {
+ GeoAllocAndEmitTouchSignals(mCandidateActorLists, 0, point, mLastRenderTask);
}
-
// Do not set mLastPrimaryHitActor to NULL we may be iterating through its observers
-
mLastConsumedActor.SetActor(nullptr);
mLastRenderTask.Reset();
mLastPrimaryPointState = PointState::FINISHED;
}
+ else
+ {
+ if(actor == mLastPrimaryHitActor.GetActor())
+ {
+ Dali::Actor actorHandle(actor);
+ Integration::Point point;
+ point.SetState(PointState::INTERRUPTED);
+ point.SetHitActor(actorHandle);
+
+ TouchEventPtr touchEventImpl(new TouchEvent);
+ touchEventImpl->AddPoint(point);
+ Dali::TouchEvent touchEventHandle(touchEventImpl.Get());
+
+ Dali::Actor eventConsumer = EmitTouchSignals(actorHandle, touchEventHandle);
+ if(mLastConsumedActor.GetActor() != eventConsumer)
+ {
+ EmitTouchSignals(Dali::Actor(mLastConsumedActor.GetActor()), touchEventHandle);
+ }
+
+ // Do not set mLastPrimaryHitActor to NULL we may be iterating through its observers
+ mLastConsumedActor.SetActor(nullptr);
+ mLastRenderTask.Reset();
+ mLastPrimaryPointState = PointState::FINISHED;
+ }
+ }
+
}
} // namespace Internal
ActorObserver mInterceptedTouchActor; ///< Stores the intercepted actor
RenderTaskPtr mLastRenderTask; ///< The RenderTask used for the last hit actor
PointState::Type mLastPrimaryPointState; ///< Stores the last primary point state
+ std::list<Dali::Internal::Actor*> mInterceptedActorLists; ///< Stores the list from root to intercepted actors.
+ std::list<Dali::Internal::Actor*> mCandidateActorLists; ///< Stores a list of actors that can be touched, from leaf actor to root.
};
} // namespace Internal