DALI_TEST_CHECK(results.actor == green);
END_TEST;
+}
+
+int UtcDaliHitTestAlgorithmExclusiveMultiple(void)
+{
+ TestApplication application;
+ tet_infoline("Testing Dali::HitTestAlgorithm between On/Off render task with multiple exclusived");
+
+ 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);
+ DALI_TEST_CHECK(results.actor == green);
+
+ END_TEST;
}
\ No newline at end of file
const RenderTaskList::ExclusivesContainer& exclusives)
{
+ bool exclusiveByOtherTask = false;
if(exclusives.size())
{
for(const auto& exclusive : exclusives)
{
- if((exclusive.renderTaskPtr != &renderTask) && (exclusive.actor.GetActor() == &actor))
+ if(exclusive.actor.GetActor() == &actor)
{
- return true;
+ if(exclusive.renderTaskPtr != &renderTask)
+ {
+ exclusiveByOtherTask = true;
+ }
+ else
+ {
+ // Fast-out if render task is itself
+ return false;
+ }
}
}
}
- return false;
+ return exclusiveByOtherTask;
}
/**
bool overlayHit = false;
bool layerConsumesHit = false;
+ // Be used when we decide to consume layer.
+ // We should not consume hit if sourceLayer is above on consumable layer. Otherwise, we should consume. So just initialize it as 0.
+ // sourceLayerIndex can be a relative value to calculate the relationship with the layer.
+ // If the layer is consumed first, sourceLayerIndex is not the actual index, but it must be guaranteed to have an index smaller than the layer.
+ // If there is a sourceLayer above the consumable layer, the sourceLayerIndex is determined and the index of the consumable layer is also determined.
+ // Then we can calculate the relationship between the two layers.
+ bool IsHitTestWithinLayer = false;
+ int32_t sourceLayerIndex = 0;
+ int32_t consumedLayerIndex = -1;
+
for(int32_t i = layers.GetLayerCount() - 1; i >= 0 && !(hit.actor); --i)
{
Layer* layer(layers.GetLayer(i));
- overlayHit = false;
+ overlayHit = false;
+ IsHitTestWithinLayer = false;
+
+ if(sourceLayer == layer)
+ {
+ sourceLayerIndex = i;
+ }
// 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 == static_cast<uint32_t>(i))
{
+ IsHitTestWithinLayer = true;
// Recursively hit test the source actor & children, without crossing into other layers.
hit = HitTestWithinLayer(*sourceActor,
renderTask,
}
else if(IsWithinSourceActors(*sourceActor, *layer))
{
+ IsHitTestWithinLayer = true;
// Recursively hit test all the actors, without crossing into other layers.
hit = HitTestWithinLayer(*layer,
renderTask,
}
// If this layer is set to consume the hit, then do not check any layers behind it
- if(hitCheck.DoesLayerConsumeHit(layer))
+ if(IsHitTestWithinLayer && hitCheck.DoesLayerConsumeHit(layer))
{
- // Consume the hit if this layer is same as SourceActor's layer
- layerConsumesHit = (sourceLayer == Dali::Layer(layer));
+ consumedLayerIndex = i;
+ layerConsumesHit = true;
break;
}
}
if(layerConsumesHit)
{
- return true; // Also success if layer is consuming the hit
+ // Consumes if the hitted layer is above the SourceActor's layer.
+ bool ret = sourceLayerIndex <= consumedLayerIndex;
+ if(ret)
+ {
+ DALI_LOG_RELEASE_INFO("layer is set to consume the hit\n");
+ results.renderTask = RenderTaskPtr(&renderTask);
+ results.actor = Dali::Layer(layers.GetLayer(consumedLayerIndex));
+ }
+ return ret; // Also success if layer is consuming the hit
}
}
}