/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
END_TEST;
}
+
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
}
END_TEST;
}
+
+namespace ComponentTest
+{
+void CheckComponentProperty(TestApplication& application, Actor& actor, Property::Index property)
+{
+ float value = actor.GetCurrentProperty<float>(property);
+
+ // Add a component 0 constraint
+ RelativeToConstraintFloat relativeConstraint(2.0f);
+ Constraint constraint = Constraint::New<float>(actor, property, relativeConstraint);
+ constraint.AddSource(Source{actor, property});
+ DALI_TEST_CHECK(constraint);
+ constraint.SetRemoveAction(Constraint::RemoveAction::DISCARD);
+ constraint.Apply();
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS(actor.GetCurrentProperty<float>(property), value * 2.0f, TEST_LOCATION);
+
+ constraint.Remove();
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS(actor.GetCurrentProperty<float>(property), value, TEST_LOCATION);
+}
+} // namespace ComponentTest
+
+int UtcDaliConstraintComponentTransformPropertyConstraintP(void)
+{
+ TestApplication application;
+
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::POSITION, Vector3(100.0f, 100.0f, 100.0f));
+ application.GetScene().Add(actor);
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS(actor.GetCurrentProperty<Vector3>(Actor::Property::POSITION), Vector3(100.0f, 100.0f, 100.0f), TEST_LOCATION);
+
+ ComponentTest::CheckComponentProperty(application, actor, Actor::Property::POSITION_X); // Component 0
+ ComponentTest::CheckComponentProperty(application, actor, Actor::Property::POSITION_Y); // Component 1
+ ComponentTest::CheckComponentProperty(application, actor, Actor::Property::POSITION_Z); // Component 2
+
+ END_TEST;
+}
+
+int UtcDaliConstraintComponentNonTransformPropertyConstraintP(void)
+{
+ TestApplication application;
+
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::COLOR, Vector4(0.25f, 0.25f, 0.25f, 0.25f));
+ application.GetScene().Add(actor);
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS(actor.GetCurrentProperty<Vector4>(Actor::Property::COLOR), Vector4(0.25f, 0.25f, 0.25f, 0.25f), TEST_LOCATION);
+
+ ComponentTest::CheckComponentProperty(application, actor, Actor::Property::COLOR_RED); // Component 0
+ ComponentTest::CheckComponentProperty(application, actor, Actor::Property::COLOR_GREEN); // Component 1
+ ComponentTest::CheckComponentProperty(application, actor, Actor::Property::COLOR_BLUE); // Component 2
+ ComponentTest::CheckComponentProperty(application, actor, Actor::Property::COLOR_ALPHA); // Component 3
+
+ END_TEST;
+}
\ No newline at end of file
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
using namespace Dali;
+namespace Test
+{
+void Doubler(float& current, const PropertyInputContainer& inputs)
+{
+ current = 2.0f * inputs[0]->GetFloat();
+}
+} // namespace Test
+
void custom_actor_test_startup(void)
{
test_return_value = TET_UNDEF;
END_TEST;
}
+
+int UtcDaliCustomActorComponentPropertyConstraintsP(void)
+{
+ TestApplication application; // Need the type registry
+
+ // register our base and add a property with default value for it
+ Dali::TypeRegistration typeRegistration(typeid(UnregisteredCustomActor), typeid(Dali::CustomActor), nullptr);
+
+ auto derived = DerivedCustomActor::New();
+ application.GetScene().Add(derived);
+
+ // should have all actor properties
+ auto actorHandle = Actor::New();
+ DALI_TEST_EQUALS(derived.GetPropertyCount(), actorHandle.GetPropertyCount(), TEST_LOCATION);
+
+ // add a property in base class
+ const Property::Index foobarIndex = ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX;
+ const Property::Index fooIndex = foobarIndex + 1;
+ const Property::Index barIndex = foobarIndex + 2;
+
+ AnimatablePropertyRegistration(typeRegistration, "Foobar", foobarIndex, Vector2(10.0f, 20.0f));
+ AnimatablePropertyComponentRegistration(typeRegistration, "Foobar.x", fooIndex, foobarIndex, 0);
+ AnimatablePropertyComponentRegistration(typeRegistration, "Foobar.y", barIndex, foobarIndex, 1);
+
+ tet_infoline("Test the default values of the registered property");
+ // should be more properties now
+ DALI_TEST_EQUALS(derived.GetPropertyCount(), actorHandle.GetPropertyCount() + 3, TEST_LOCATION);
+ // check that the default value is set for base class
+ DALI_TEST_EQUALS(UnregisteredCustomActor::New().GetProperty(foobarIndex).Get<Vector2>(), Vector2(10.f, 20.0f), 0.0001f, TEST_LOCATION);
+ // check that the default value is set for the derived instance as well
+ DALI_TEST_EQUALS(derived.GetProperty(foobarIndex).Get<Vector2>(), Vector2(10.f, 20.0f), 0.0001f, TEST_LOCATION);
+
+ tet_infoline("Test that the components of the registered property can be constrained");
+
+ // Try constraining the properties
+ Constraint fooCons = Constraint::New<float>(derived, fooIndex, &Test::Doubler);
+ fooCons.AddSource(LocalSource(Actor::Property::POSITION_X));
+ fooCons.Apply();
+ Constraint barCons = Constraint::New<float>(derived, barIndex, &Test::Doubler);
+ barCons.AddSource(LocalSource(fooIndex));
+ barCons.Apply();
+
+ for(int i = 1; i < 10; ++i)
+ {
+ derived[Actor::Property::POSITION_X] = i * 1.0f;
+ application.SendNotification();
+ application.Render();
+ DALI_TEST_EQUALS(derived.GetCurrentProperty(foobarIndex).Get<Vector2>(), Vector2(i * 2.0f, i * 4.0f), 0.0001f, TEST_LOCATION);
+ }
+
+ // Add a Vector3 property and its components for completeness
+ const Property::Index vec3PropIndex = barIndex + 1;
+ const Property::Index vec3xPropIndex = vec3PropIndex + 1;
+ const Property::Index vec3yPropIndex = vec3PropIndex + 2;
+ const Property::Index vec3zPropIndex = vec3PropIndex + 3;
+
+ AnimatablePropertyRegistration(typeRegistration, "vec3Prop", vec3PropIndex, Vector3(10.0f, 20.0f, 30.0f));
+ AnimatablePropertyComponentRegistration(typeRegistration, "vec3Prop.x", vec3xPropIndex, vec3PropIndex, 0);
+ AnimatablePropertyComponentRegistration(typeRegistration, "vec3Prop.y", vec3yPropIndex, vec3PropIndex, 1);
+ AnimatablePropertyComponentRegistration(typeRegistration, "vec3Prop.z", vec3zPropIndex, vec3PropIndex, 2);
+
+ tet_infoline("Test the default values of the registered vec3 property");
+ // should be more properties now
+ DALI_TEST_EQUALS(derived.GetPropertyCount(), actorHandle.GetPropertyCount() + 7, TEST_LOCATION);
+ // check that the default value is set for base class
+ DALI_TEST_EQUALS(UnregisteredCustomActor::New().GetProperty(vec3PropIndex).Get<Vector3>(), Vector3(10.f, 20.0f, 30.0f), 0.0001f, TEST_LOCATION);
+ // check that the default value is set for the derived instance as well
+ DALI_TEST_EQUALS(derived.GetProperty(vec3PropIndex).Get<Vector3>(), Vector3(10.f, 20.0f, 30.0f), 0.0001f, TEST_LOCATION);
+
+ tet_infoline("Test that the components of the registered property can be constrained");
+
+ // Try constraining the properties
+ Constraint vec3xConstraint = Constraint::New<float>(derived, vec3xPropIndex, &Test::Doubler);
+ vec3xConstraint.AddSource(LocalSource(Actor::Property::POSITION_X));
+ vec3xConstraint.Apply();
+ Constraint vec3yConstraint = Constraint::New<float>(derived, vec3yPropIndex, &Test::Doubler);
+ vec3yConstraint.AddSource(LocalSource(vec3xPropIndex));
+ vec3yConstraint.Apply();
+ Constraint vec3zConstraint = Constraint::New<float>(derived, vec3zPropIndex, &Test::Doubler);
+ vec3zConstraint.AddSource(LocalSource(vec3yPropIndex));
+ vec3zConstraint.Apply();
+
+ for(int i = 1; i < 10; ++i)
+ {
+ derived[Actor::Property::POSITION_X] = i * 1.0f;
+ application.SendNotification();
+ application.Render();
+ DALI_TEST_EQUALS(derived.GetCurrentProperty(vec3PropIndex).Get<Vector3>(), Vector3(i * 2.0f, i * 4.0f, i * 8.0f), 0.0001f, TEST_LOCATION);
+ }
+
+ END_TEST;
+}
#define DALI_INTERNAL_ACTIVE_CONSTRAINT_H
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
}
else
{
- // Expecting Vector2, Vector3 or Vector4 type
- if(PropertyTypes::Get<Vector2>() == targetProperty->GetType())
- {
- // Constrain float component of Vector2 property
- if(0 == componentIndex)
- {
- mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorX<Vector2> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
- }
- else if(1 == componentIndex)
- {
- mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorY<Vector2> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
- }
- resetterRequired = (mSceneGraphConstraint != nullptr);
- }
- else if(PropertyTypes::Get<Vector3>() == targetProperty->GetType())
- {
- // Constrain float component of Vector3 property
- if(targetProperty->IsTransformManagerProperty())
- {
- if(0 == componentIndex)
- {
- mSceneGraphConstraint = SceneGraph::Constraint<float, TransformManagerPropertyComponentAccessor<Vector3, 0> >::New(*targetProperty,
- propertyOwners,
- func,
- mRemoveAction);
- }
- else if(1 == componentIndex)
- {
- mSceneGraphConstraint = SceneGraph::Constraint<float, TransformManagerPropertyComponentAccessor<Vector3, 1> >::New(*targetProperty,
- propertyOwners,
- func,
- mRemoveAction);
- }
- else if(2 == componentIndex)
- {
- mSceneGraphConstraint = SceneGraph::Constraint<float, TransformManagerPropertyComponentAccessor<Vector3, 2> >::New(*targetProperty,
- propertyOwners,
- func,
- mRemoveAction);
- }
- // Do not create a resetter for transform manager property
- }
- else
- {
- if(0 == componentIndex)
- {
- mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorX<Vector3> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
- }
- else if(1 == componentIndex)
- {
- mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorY<Vector3> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
- }
- else if(2 == componentIndex)
- {
- mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorZ<Vector3> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
- }
- resetterRequired = (mSceneGraphConstraint != nullptr);
- }
- }
- else if(PropertyTypes::Get<Vector4>() == targetProperty->GetType())
- {
- // Constrain float component of Vector4 property
- if(0 == componentIndex)
- {
- mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorX<Vector4> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
- }
- else if(1 == componentIndex)
- {
- mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorY<Vector4> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
- }
- else if(2 == componentIndex)
- {
- mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorZ<Vector4> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
- }
- else if(3 == componentIndex)
- {
- mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorW<Vector4> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
- }
-
- resetterRequired = (mSceneGraphConstraint != nullptr);
- }
+ CreateComponentConstraint(targetProperty, componentIndex, propertyOwners, func, resetterRequired);
}
if(mSceneGraphConstraint)
{
return func;
}
+ /**
+ * Creates a component property constraint.
+ * @param[in] targetProperty The target property
+ * @param[in] componentIndex The index of the component
+ * @param[in] propertyOwners The owners of the property
+ * @param[in] func The constraint function
+ * @param[in/out] resetterRequired Set to true if a property resetter is required after creating this constraint
+ */
+ void CreateComponentConstraint(const SceneGraph::PropertyBase* targetProperty, const int32_t componentIndex, SceneGraph::PropertyOwnerContainer& propertyOwners, ConstraintFunctionPtr& func, bool& resetterRequired)
+ {
+ // Expecting Vector2, Vector3 or Vector4 type
+ if(PropertyTypes::Get<Vector2>() == targetProperty->GetType())
+ {
+ // Constrain float component of Vector2 property
+ if(0 == componentIndex)
+ {
+ mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorX<Vector2> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
+ }
+ else if(1 == componentIndex)
+ {
+ mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorY<Vector2> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
+ }
+ resetterRequired = (mSceneGraphConstraint != nullptr);
+ }
+ else if(PropertyTypes::Get<Vector3>() == targetProperty->GetType())
+ {
+ // Constrain float component of Vector3 property
+ if(targetProperty->IsTransformManagerProperty())
+ {
+ if(0 == componentIndex)
+ {
+ mSceneGraphConstraint = SceneGraph::Constraint<float, TransformManagerPropertyComponentAccessor<Vector3, 0> >::New(*targetProperty,
+ propertyOwners,
+ func,
+ mRemoveAction);
+ }
+ else if(1 == componentIndex)
+ {
+ mSceneGraphConstraint = SceneGraph::Constraint<float, TransformManagerPropertyComponentAccessor<Vector3, 1> >::New(*targetProperty,
+ propertyOwners,
+ func,
+ mRemoveAction);
+ }
+ else if(2 == componentIndex)
+ {
+ mSceneGraphConstraint = SceneGraph::Constraint<float, TransformManagerPropertyComponentAccessor<Vector3, 2> >::New(*targetProperty,
+ propertyOwners,
+ func,
+ mRemoveAction);
+ }
+ // Do not create a resetter for transform manager property
+ }
+ else
+ {
+ if(0 == componentIndex)
+ {
+ mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorX<Vector3> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
+ }
+ else if(1 == componentIndex)
+ {
+ mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorY<Vector3> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
+ }
+ else if(2 == componentIndex)
+ {
+ mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorZ<Vector3> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
+ }
+ resetterRequired = (mSceneGraphConstraint != nullptr);
+ }
+ }
+ else if(PropertyTypes::Get<Vector4>() == targetProperty->GetType())
+ {
+ // Constrain float component of Vector4 property
+ if(0 == componentIndex)
+ {
+ mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorX<Vector4> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
+ }
+ else if(1 == componentIndex)
+ {
+ mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorY<Vector4> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
+ }
+ else if(2 == componentIndex)
+ {
+ mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorZ<Vector4> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
+ }
+ else if(3 == componentIndex)
+ {
+ mSceneGraphConstraint = SceneGraph::Constraint<float, PropertyComponentAccessorW<Vector4> >::New(*targetProperty, propertyOwners, func, mRemoveAction);
+ }
+
+ resetterRequired = (mSceneGraphConstraint != nullptr);
+ }
+ }
+
protected:
ConstraintFunctionPtr mUserFunction;
};
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
}
}
+/// Helper to convert and then assign the property value
+template<typename PropertyType, typename Value>
+inline void SetValue(const Property::Value& propertyValue, Value& value)
+{
+ PropertyType convertedValue;
+ if(propertyValue.Get(convertedValue))
+ {
+ value = convertedValue;
+ }
+}
+
+/// Helper to check container property type and set appropriately
+template<typename ContainerType>
+inline void SetContainerValue(const ContainerType* containerPtr, Property::Value& value)
+{
+ if(containerPtr)
+ {
+ value = *containerPtr;
+ }
+}
} // unnamed namespace
void PropertyMetadata::SetPropertyValue(const Property::Value& propertyValue)
case Property::RECTANGLE:
{
- Rect<int32_t> convertedValue;
- if(propertyValue.Get(convertedValue))
- {
- value = convertedValue;
- }
+ SetValue<Rect<int32_t>>(propertyValue, value);
break;
}
case Property::STRING:
{
- std::string convertedValue;
- if(propertyValue.Get(convertedValue))
- {
- value = convertedValue;
- }
+ SetValue<std::string>(propertyValue, value);
break;
}
case Property::ARRAY:
{
- const Property::Array* array = propertyValue.GetArray();
- if(array)
- {
- value = *array;
- }
+ SetContainerValue(propertyValue.GetArray(), value);
break;
}
case Property::MAP:
{
- const Property::Map* map = propertyValue.GetMap();
- if(map)
- {
- value = *map;
- }
+ SetContainerValue(propertyValue.GetMap(), value);
break;
}
case Property::EXTENTS:
{
- Extents convertedValue;
- if(propertyValue.Get(convertedValue))
- {
- value = convertedValue;
- }
+ SetValue<Extents>(propertyValue, value);
break;
}
case Property::BOOLEAN:
{
- bool convertedValue;
- if(propertyValue.Get(convertedValue))
- {
- value = convertedValue;
- }
+ SetValue<bool>(propertyValue, value);
break;
}
case Property::INTEGER:
{
- int32_t convertedValue;
- if(propertyValue.Get(convertedValue))
- {
- value = convertedValue;
- }
+ SetValue<int32_t>(propertyValue, value);
break;
}
case Property::FLOAT:
{
- float convertedValue;
- if(propertyValue.Get(convertedValue))
- {
- value = convertedValue;
- }
+ SetValue<float>(propertyValue, value);
break;
}
case Property::ROTATION:
{
- Quaternion convertedValue;
- if(propertyValue.Get(convertedValue))
- {
- value = convertedValue;
- }
+ SetValue<Quaternion>(propertyValue, value);
break;
}
case Property::MATRIX:
{
- Matrix convertedValue;
- if(propertyValue.Get(convertedValue))
- {
- value = convertedValue;
- }
+ SetValue<Matrix>(propertyValue, value);
break;
}
case Property::MATRIX3:
{
- Matrix3 convertedValue;
- if(propertyValue.Get(convertedValue))
- {
- value = convertedValue;
- }
+ SetValue<Matrix3>(propertyValue, value);
break;
}
Vector2 vector2Value;
value.Get(vector2Value);
- if(componentIndex == 0)
- {
- vector2Value.x = propertyValue.Get<float>();
- }
- else if(componentIndex == 1)
+ switch(componentIndex)
{
- vector2Value.y = propertyValue.Get<float>();
- }
- else
- {
- propertyValue.Get(vector2Value);
+ case 0:
+ {
+ SetValue<float>(propertyValue, vector2Value.x);
+ break;
+ }
+
+ case 1:
+ {
+ SetValue<float>(propertyValue, vector2Value.y);
+ break;
+ }
+
+ default:
+ {
+ SetValue<Vector2>(propertyValue, vector2Value);
+ break;
+ }
}
value = vector2Value;
Vector3 vector3Value;
value.Get(vector3Value);
- if(componentIndex == 0)
- {
- vector3Value.x = propertyValue.Get<float>();
- }
- else if(componentIndex == 1)
+ switch(componentIndex)
{
- vector3Value.y = propertyValue.Get<float>();
- }
- else if(componentIndex == 2)
- {
- vector3Value.z = propertyValue.Get<float>();
- }
- else
- {
- propertyValue.Get(vector3Value);
+ case 0:
+ {
+ SetValue<float>(propertyValue, vector3Value.x);
+ break;
+ }
+
+ case 1:
+ {
+ SetValue<float>(propertyValue, vector3Value.y);
+ break;
+ }
+
+ case 2:
+ {
+ SetValue<float>(propertyValue, vector3Value.z);
+ break;
+ }
+
+ default:
+ {
+ SetValue<Vector3>(propertyValue, vector3Value);
+ break;
+ }
}
value = vector3Value;
Vector4 vector4Value;
value.Get(vector4Value);
- if(componentIndex == 0)
- {
- vector4Value.x = propertyValue.Get<float>();
- }
- else if(componentIndex == 1)
+ switch(componentIndex)
{
- vector4Value.y = propertyValue.Get<float>();
- }
- else if(componentIndex == 2)
- {
- vector4Value.z = propertyValue.Get<float>();
- }
- else if(componentIndex == 3)
- {
- vector4Value.w = propertyValue.Get<float>();
- }
- else
- {
- propertyValue.Get(vector4Value);
+ case 0:
+ {
+ SetValue<float>(propertyValue, vector4Value.x);
+ break;
+ }
+
+ case 1:
+ {
+ SetValue<float>(propertyValue, vector4Value.y);
+ break;
+ }
+
+ case 2:
+ {
+ SetValue<float>(propertyValue, vector4Value.z);
+ break;
+ }
+
+ case 3:
+ {
+ SetValue<float>(propertyValue, vector4Value.w);
+ break;
+ }
+
+ default:
+ {
+ SetValue<Vector4>(propertyValue, vector4Value);
+ break;
+ }
}
value = vector4Value;
}
/**
- * Recursively hit test all the actors, without crossing into other layers.
- * This algorithm performs a Depth-First-Search (DFS) on all Actors within Layer.
- * Hit-Testing each Actor, noting the distance from the Ray-Origin (3D origin
- * of touch vector). The closest Hit-Tested Actor is that which is returned.
- * Exceptions to this rule are:
- * - When comparing against renderable parents, if Actor is the same distance
- * or closer than it's renderable parent, then it takes priority.
+ * Hit tests the given actor and updates the in/out variables appropriately
*/
-HitActor HitTestWithinLayer(Actor& actor,
- const RenderTask& renderTask,
- const RenderTaskList::ExclusivesContainer& exclusives,
- const Vector4& rayOrigin,
- const Vector4& rayDir,
- const float& nearClippingPlane,
- const float& farClippingPlane,
- HitTestInterface& hitCheck,
- const bool& overlayed,
- bool& overlayHit,
- bool layerIs3d,
- const RayTest& rayTest,
- const Integration::Point& point,
- const uint32_t eventTime)
+void HitTestActor(const RenderTask& renderTask,
+ const Vector4& rayOrigin,
+ const Vector4& rayDir,
+ const float& nearClippingPlane,
+ const float& farClippingPlane,
+ HitTestInterface& hitCheck,
+ const RayTest& rayTest,
+ const Integration::Point& point,
+ const uint32_t eventTime,
+ bool clippingActor,
+ bool overlayedActor,
+ Actor& actor,
+ bool& overlayHit,
+ HitActor& hit)
{
- HitActor hit;
-
- if(IsActorExclusiveToAnotherRenderTask(actor, renderTask, exclusives))
- {
- return hit;
- }
-
- // For clipping, regardless of whether we have hit this actor or not.
- // This is used later to ensure all nested clipped children have hit
- // all clipping actors also for them to be counted as hit.
- bool clippingActor = actor.GetClippingMode() != ClippingMode::DISABLED;
- bool overlayedActor = overlayed || actor.IsOverlay();
-
- // If we are a clipping actor or hittable...
if(clippingActor || hitCheck.IsActorHittable(&actor))
{
Vector3 size(actor.GetCurrentSize());
}
}
}
+}
+
+/**
+ * When iterating through the children of an actor, this method updates the child-hit-data.
+ */
+void UpdateChildHitData(const HitActor& hit, const HitActor& currentHit, const bool layerIs3d, const bool parentIsRenderable, HitActor& childHit)
+{
+ bool updateChildHit = false;
+ if(currentHit.distance >= 0.0f)
+ {
+ if(layerIs3d)
+ {
+ updateChildHit = ((currentHit.depth > childHit.depth) ||
+ ((currentHit.depth == childHit.depth) && (currentHit.distance < childHit.distance)));
+ }
+ else
+ {
+ updateChildHit = currentHit.depth >= childHit.depth;
+ }
+ }
+
+ if(updateChildHit)
+ {
+ if(!parentIsRenderable || currentHit.depth > hit.depth ||
+ (layerIs3d && (currentHit.depth == hit.depth && currentHit.distance < hit.distance)))
+ {
+ childHit = currentHit;
+ }
+ }
+}
+
+/**
+ * Recursively hit test all the actors, without crossing into other layers.
+ * This algorithm performs a Depth-First-Search (DFS) on all Actors within Layer.
+ * Hit-Testing each Actor, noting the distance from the Ray-Origin (3D origin
+ * of touch vector). The closest Hit-Tested Actor is that which is returned.
+ * Exceptions to this rule are:
+ * - When comparing against renderable parents, if Actor is the same distance
+ * or closer than it's renderable parent, then it takes priority.
+ */
+HitActor HitTestWithinLayer(Actor& actor,
+ const RenderTask& renderTask,
+ const RenderTaskList::ExclusivesContainer& exclusives,
+ const Vector4& rayOrigin,
+ const Vector4& rayDir,
+ const float& nearClippingPlane,
+ const float& farClippingPlane,
+ HitTestInterface& hitCheck,
+ const bool& overlayed,
+ bool& overlayHit,
+ bool layerIs3d,
+ const RayTest& rayTest,
+ const Integration::Point& point,
+ const uint32_t eventTime)
+{
+ HitActor hit;
+
+ if(IsActorExclusiveToAnotherRenderTask(actor, renderTask, exclusives))
+ {
+ return hit;
+ }
+
+ // For clipping, regardless of whether we have hit this actor or not.
+ // This is used later to ensure all nested clipped children have hit
+ // all clipping actors also for them to be counted as hit.
+ bool clippingActor = actor.GetClippingMode() != ClippingMode::DISABLED;
+ 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);
// If current actor is clipping, and hit failed, We should not checkup child actors. Fast return
if(clippingActor && !(hit.actor))
continue;
}
- bool updateChildHit = false;
- if(currentHit.distance >= 0.0f)
- {
- if(layerIs3d)
- {
- updateChildHit = ((currentHit.depth > childHit.depth) ||
- ((currentHit.depth == childHit.depth) && (currentHit.distance < childHit.distance)));
- }
- else
- {
- updateChildHit = currentHit.depth >= childHit.depth;
- }
- }
-
- if(updateChildHit)
- {
- if(!parentIsRenderable || currentHit.depth > hit.depth ||
- (layerIs3d && (currentHit.depth == hit.depth && currentHit.distance < hit.distance)))
- {
- childHit = currentHit;
- }
- }
+ UpdateChildHitData(hit, currentHit, layerIs3d, parentIsRenderable, childHit);
}
}
}