Merge remote-tracking branch 'origin/tizen' into devel/new_mesh
[platform/core/uifw/dali-core.git] / dali / devel-api / events / hit-test-algorithm.h
1 #ifndef  __DALI_HIT_TEST_ALGORITHM_H__
2 #define  __DALI_HIT_TEST_ALGORITHM_H__
3
4 /*
5  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  */
20
21 #include <dali/public-api/actors/actor.h>
22 #include <dali/public-api/common/stage.h>
23
24
25 namespace Dali
26 {
27
28 class RenderTask;
29
30 /**
31  * @brief This namespace is provided for application developers to do hit-test for the actors.
32  *
33  * <h3>Hit Test Algorithm:</h3>
34  *
35  * Hit testing is dependent on the camera used, which is specific to each RenderTask. For each RenderTask,
36  * hit testing starts from the top-most layer and we go through all the layers until we have a hit or there
37  * are none left. Before we perform a hit test within a layer, we check if all the layer's parents meet the
38  * conditions defined by the function ((e.g. whether it is visible)). If they are not, we skip hit testing
39  * the actors in that layer altogether. Otherwise, we walk through the actor tree within a layer to check
40  * whether the actors within the actor tree should be hit-tested.
41  *
42  * The following pseudocode gives an example of what the function can typically check, which should normally
43  * be provided by the application code:
44  *
45  *   @code
46  *   HIT-TEST-FUNCTION( ACTOR, TRAVERSE-TYPE )
47  *   {
48  *     if( TRAVERSE-TYPE == CHECK_ACTOR ) // Check whether current actor should be hit-tested
49  *     {
50  *       if( ACTOR-IS-VISIBLE &&
51  *           ACTOR-WORLD-COLOR-IS-NOT-TRANSPARENT )
52  *       {
53  *         HITTABLE = TRUE
54  *       }
55  *     }
56  *     else if( TRAVERSE-TYPE == DESCEND_ACTOR_TREE ) ///< Check whether the actor tree should be descended to hit-test its children.
57  *     {
58  *       if( ACTOR-IS-VISIBLE )
59  *       {
60  *         HITTABLE = TRUE
61  *       }
62  *     }
63  *   }
64  *   @endcode
65  *
66  * The following pseudocode explains how the algorithm performs the hit-test with the above functor:
67  *
68  *   @code
69  *   HIT-TEST-WITHIN-LAYER( ACTOR )
70  *   {
71  *     // Depth-first traversal within current layer, visiting parent first
72  *
73  *     // Check whether current actor should be hit-tested
74  *     IF ( HIT-TEST-FUNCTION( ACTOR, CHECK_ACTOR ) &&
75  *          ACTOR-HAS-NON-ZERO-SIZE )
76  *     {
77  *       // Hit-test current actor
78  *       IF ( ACTOR-HIT )
79  *       {
80  *         IF ( DISTANCE-TO-ACTOR < DISTANCE-TO-LAST-HIT-ACTOR )
81  *         {
82  *           // The current actor is the closest actor that was underneath the touch
83  *           LAST-HIT-ACTOR = CURRENT-ACTOR
84  *         }
85  *       }
86  *     }
87  *
88  *     // Keep checking children, in case we hit something closer
89  *     FOR-EACH CHILD (in order)
90  *     {
91  *       IF ( HIT-TEST-FUNCTION( ACTOR, DESCEND_ACTOR_TREE ) &&
92  *            ACTOR-IS-NOT-A-LAYER )
93  *       {
94  *         // Continue traversal for this child's sub-tree
95  *         HIT-TEST-WITHIN-LAYER ( CHILD )
96  *       }
97  *       // else we skip the sub-tree with from this child
98  *     }
99  *   }
100  *   @endcode
101  */
102 namespace HitTestAlgorithm
103 {
104
105 /**
106  * @brief How the actor tree should be traversed.
107  */
108 enum TraverseType
109 {
110   CHECK_ACTOR,            ///< Hit test the given actor.
111   DESCEND_ACTOR_TREE      ///< Check whether the actor tree should be descended to hit-test its children.
112 };
113
114 /**
115  * @brief Results structure containing the hit actor and where it was hit.
116  */
117 struct Results
118 {
119   Actor      actor;            ///< The hit actor.
120   Vector2    actorCoordinates; ///< The actor coordinates.
121 };
122
123 /**
124  * @brief Definition of a hit-test function to use in HitTest() method to check if the actor is hittable (e.g. touchable or focusable).
125  *
126  * @return true, if the actor is hittable, false otherwise.
127  */
128 typedef bool (*HitTestFunction)(Actor actor, TraverseType type);
129
130 /**
131  * @brief Given screen coordinates, this method returns the hit actor & the local coordinates relative to
132  * the top-left (0.0f, 0.0f, 0.5f) of the actor.
133  *
134  * An actor is only hittable if the actor meets all the conditions
135  * defined by the given function (see HitTestAlgorithm).
136  *
137  * Typically, if an actor has a zero size or its world color is fully transparent, it should not be
138  * hittable; and if an actor's visibility flag is unset, its children should not be hittable either.
139  *
140  * @param[in] stage The stage.
141  * @param[in] screenCoordinates The screen coordinates.
142  * @param[out] results The results of the hit-test, only modified if something is hit
143  * @param[in] func The function to use in the hit-test algorithm.
144  * @return true if something was hit
145  */
146 DALI_IMPORT_API bool HitTest( Stage stage, const Vector2& screenCoordinates, Results& results, HitTestFunction func );
147
148 /**
149  * @brief Hit test specific to a given RenderTask.
150  *
151  * @param[in] renderTask The render task for hit test
152  * @param[in] screenCoordinates The screen coordinates.
153  * @param[out] results The results of the hit-test, only modified if something is hit
154  * @param[in] func The function to use in the hit-test algorithm.
155  * @return true if something was hit
156  */
157 DALI_IMPORT_API bool HitTest( RenderTask& renderTask, const Vector2& screenCoordinates, Results& results, HitTestFunction func );
158
159 } // namespace HitTestAlgorithm
160
161 } // namespace Dali
162
163 #endif // __DALI_HIT_TEST_ALGORITHM_H__