Add TouchDelegateArea property. 35/245935/9
authorJoogab Yun <joogab.yun@samsung.com>
Tue, 20 Oct 2020 06:46:19 +0000 (15:46 +0900)
committerjoogab yun <joogab.yun@samsung.com>
Thu, 22 Oct 2020 01:29:02 +0000 (01:29 +0000)
TouchDelegateArea can reset the actor's touchable area.
This is usefull when the actor is small, but it should have a larger touch area.

for example

      Actor actor = Actor::New();
      actor.SetProperty(Actor::Property::SIZE, Vector2(10.0f, 10.0f));
      actor.SetProperty(DevelActor::Property::TOUCH_DELEGATE_AREA, Vector2(200.0f, 200.0f));
      actor.TouchedSignal().Connect(OnTouchCallback);

The actor is small, If you want to set the touch area to a larger area,
you can use the TOUCH_DELEGATE_AREA property.

Change-Id: Ic4e3683e09d1636bc61719ea1e83bcd05a1c4153

automated-tests/src/dali/utc-Dali-Actor.cpp [changed mode: 0644->0755]
automated-tests/src/dali/utc-Dali-TouchProcessing.cpp
dali/devel-api/actors/actor-devel.h
dali/internal/event/actors/actor-impl.cpp
dali/internal/event/actors/actor-impl.h
dali/internal/event/actors/actor-property-handler.cpp [changed mode: 0644->0755]
dali/internal/event/events/ray-test.cpp [changed mode: 0644->0755]

old mode 100644 (file)
new mode 100755 (executable)
index 0b2a35b..d161892
@@ -7926,6 +7926,43 @@ int UtcDaliActorCaptureAllTouchAfterStartPropertyN(void)
   END_TEST;
 }
 
+int UtcDaliActorTouchDelegateAreaPropertyP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Vector2 touchDelegateArea = actor.GetProperty(DevelActor::Property::TOUCH_DELEGATE_AREA).Get<Vector2>();
+  DALI_TEST_EQUALS(touchDelegateArea, Vector2::ZERO, TEST_LOCATION);
+  actor.SetProperty(DevelActor::Property::TOUCH_DELEGATE_AREA, Vector2(10.f, 10.f));
+  touchDelegateArea = actor.GetProperty(DevelActor::Property::TOUCH_DELEGATE_AREA).Get<Vector2>();
+  DALI_TEST_EQUALS(touchDelegateArea, Vector2(10.f, 10.f), TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliActorTouchDelegateAreaPropertyN(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  // Make sure setting invalid types does not cause a crash
+  try
+  {
+    actor.SetProperty(DevelActor::Property::TOUCH_DELEGATE_AREA, 1.0f);
+    actor.SetProperty(DevelActor::Property::TOUCH_DELEGATE_AREA, Vector2::ONE);
+    actor.SetProperty(DevelActor::Property::TOUCH_DELEGATE_AREA, Vector3::ONE);
+    actor.SetProperty(DevelActor::Property::TOUCH_DELEGATE_AREA, Vector4::ONE);
+    actor.SetProperty(DevelActor::Property::TOUCH_DELEGATE_AREA, Property::Map());
+    actor.SetProperty(DevelActor::Property::TOUCH_DELEGATE_AREA, Property::Array());
+    tet_result(TET_PASS);
+  }
+  catch(...)
+  {
+    tet_result(TET_FAIL);
+  }
+  END_TEST;
+}
+
 int UtcDaliActorLowerBelowNegative(void)
 {
   TestApplication application;
index 3c01346..e0c7b80 100755 (executable)
@@ -2121,3 +2121,66 @@ int UtcDaliTouchEventIntercept(void)
   END_TEST;
 }
 
+int UtcDaliTouchDelegateArea(void)
+{
+  TestApplication application;
+
+  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);
+  data.Reset();
+
+  // set a bigger touch delegate area
+  actor.SetProperty(DevelActor::Property::TOUCH_DELEGATE_AREA, Vector2(200.0f, 200.0f));
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Emit a down signal
+  application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(110.0f, 110.0f)));
+  // The actor touched signal is called because the touch area is inside touchDelegateArea.
+  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();
+
+  // set a smaller touch delegate area
+  actor.SetProperty(DevelActor::Property::TOUCH_DELEGATE_AREA, Vector2(50.0f, 50.0f));
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Emit a down signal
+  application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(80.0f, 80.0f)));
+  // The actor touched signal is not called because the touch area is outside touchDelegateArea.
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  data.Reset();
+
+  // Emit a down signal
+  application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(30.0f, 30.0f)));
+  // The actor touched signal is called because the touch area is inside touchDelegateArea.
+  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();
+
+  END_TEST;
+}
index cda374f..7b1b7d1 100755 (executable)
@@ -117,7 +117,21 @@ enum Type
     * @details Name "captureAllTouchAfterStart", type Property::BOOLEAN
     * @note Default is false, i.e. actor under touch event will receive the touch even if touch started on this actor
     */
-  CAPTURE_ALL_TOUCH_AFTER_START
+  CAPTURE_ALL_TOUCH_AFTER_START,
+
+  /**
+    * @brief If you set the TOUCH_DELEGATE_AREA on an actor, when you touch the actor, the delegate area is used rather than the size of the actor
+    * @details Name "touchDelegateArea", type Property::Vector2
+    * @note Default is Vector2::ZERO.
+    * @note for example
+    *  Actor actor = Actor::New();
+    *  actor.SetProperty(Actor::Property::SIZE, Vector2(10.0f, 10.0f));
+    *  actor.SetProperty(DevelActor::Property::TOUCH_DELEGATE_AREA, Vector2(200.0f, 200.0f));
+    *  actor.TouchedSignal().Connect(OnTouchCallback);
+    *
+    *  If you want to reset the touch area to an area different with the size of the actor, you can set this TOUCH_DELEGATE_AREA property.
+    */
+  TOUCH_DELEGATE_AREA
 };
 
 } // namespace Property
index 4fdf0c2..75ca77c 100755 (executable)
@@ -143,6 +143,7 @@ DALI_PROPERTY( "keyboardFocusable",         BOOLEAN,  true,  false, false, Dali:
 DALI_PROPERTY( "siblingOrder",              INTEGER,  true,  false, false, Dali::DevelActor::Property::SIBLING_ORDER )
 DALI_PROPERTY( "updateSizeHint",            VECTOR2,  true,  false, false, Dali::DevelActor::Property::UPDATE_SIZE_HINT )
 DALI_PROPERTY( "captureAllTouchAfterStart", BOOLEAN,  true,  false, false, Dali::DevelActor::Property::CAPTURE_ALL_TOUCH_AFTER_START )
+DALI_PROPERTY( "touchDelegateArea",         VECTOR2,  true,  false, false, Dali::DevelActor::Property::TOUCH_DELEGATE_AREA )
 DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX, ActorDefaultProperties )
 
 // Signals
@@ -1451,6 +1452,7 @@ Actor::Actor( DerivedType derivedType, const SceneGraph::Node& node )
   mTargetPosition( Vector3::ZERO ),
   mTargetScale( Vector3::ONE ),
   mAnimatedSize( Vector3::ZERO ),
+  mTouchDelegateArea( Vector2::ZERO ),
   mName(),
   mSortedDepth( 0u ),
   mDepth( 0u ),
index a982904..4404718 100755 (executable)
@@ -1382,6 +1382,25 @@ public:
     return mCaptureAllTouchAfterStart;
   }
 
+  /**
+   * Sets the touch delegate area of an actor.
+   * @param [in] area The new area.
+   */
+  void SetTouchDelegateArea(Vector2 area)
+  {
+    mTouchDelegateArea = area;
+  }
+
+  /**
+   * Retrieve the Actor's touch delegate area.
+   * @return The Actor's touch delegate area.
+   */
+  const Vector2& GetTouchDelegateArea() const
+  {
+    return mTouchDelegateArea;
+  }
+
+
   // Gestures
 
   /**
@@ -2026,6 +2045,7 @@ protected:
   Vector3         mTargetPosition;    ///< Event-side storage for position (not a pointer as most actors will have a position)
   Vector3         mTargetScale;       ///< Event-side storage for scale
   Vector3         mAnimatedSize;      ///< Event-side storage for size animation
+  Vector2         mTouchDelegateArea; ///< touch delegate area
 
   std::string     mName;              ///< Name of the actor
   uint32_t        mSortedDepth;       ///< The sorted depth index. A combination of tree traversal and sibling order.
old mode 100644 (file)
new mode 100755 (executable)
index 099466e..415f637
@@ -574,6 +574,17 @@ void Actor::PropertyHandler::SetDefaultProperty( Internal::Actor& actor, Propert
       break;
     }
 
+    case Dali::DevelActor::Property::TOUCH_DELEGATE_AREA:
+    {
+      Vector2 vec2Value;
+      if( property.Get( vec2Value ) )
+      {
+        actor.SetTouchDelegateArea( vec2Value );
+      }
+      break;
+    }
+
+
     default:
     {
       // this can happen in the case of a non-animatable default property so just do nothing
@@ -1603,6 +1614,12 @@ bool Actor::PropertyHandler::GetCachedPropertyValue(const Internal::Actor& actor
       break;
     }
 
+    case Dali::DevelActor::Property::TOUCH_DELEGATE_AREA:
+    {
+      value = actor.GetTouchDelegateArea();
+      break;
+    }
+
     default:
     {
       // Must be a scene-graph only property
old mode 100644 (file)
new mode 100755 (executable)
index cee959d..112c03a
@@ -156,7 +156,7 @@ bool RayTest::ActorTest(const Internal::Actor& actor, const Vector4& rayOrigin,
       // Ray travels distance * rayDirLocal to intersect with plane.
       distance = a / b;
 
-      const Vector3& size = node.GetSize(EventThreadServices::Get().GetEventBufferIndex());
+      const Vector2& size = actor.GetTouchDelegateArea() == Vector2::ZERO ? Vector2(node.GetSize(EventThreadServices::Get().GetEventBufferIndex())) : actor.GetTouchDelegateArea();
       hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f;
       hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f;