Apply fittingMode lazy when resource is not ready
[platform/core/uifw/dali-toolkit.git] / dali-physics / public-api / physics-adaptor.h
1 #ifndef DALI_TOOLKIT_PHYSICS_ADAPTOR_H
2 #define DALI_TOOLKIT_PHYSICS_ADAPTOR_H
3
4 /*
5  * Copyright (c) 2023 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 adaptoried.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19
20 // EXTERNAL INCLUDES
21 #include <dali/public-api/actors/actor.h>
22 #include <dali/public-api/adaptor-framework/window.h>
23 #include <dali/public-api/object/any.h>
24 #include <dali/public-api/object/base-handle.h>
25 #include <functional> ///< for std::function
26
27 // INTERNAL INCLUDES
28 #include <dali-toolkit/public-api/dali-toolkit-common.h>
29
30 namespace Dali::Toolkit::Physics
31 {
32 class PhysicsActor;
33
34 namespace Internal
35 {
36 class PhysicsAdaptor;
37 class PhysicsWorld;
38 } // namespace Internal
39
40 /**
41  * Adaptor to manage access to the physics world and pairing actors and physics
42  * bodies, plus some translation methods to/from the physics space and dali space.
43  *
44  * Also manages a debug renderer that may utilize the physics engine debug.
45  * It is up to the developer to retrieve the root actor and parent it into the scene.
46  */
47 class DALI_TOOLKIT_API PhysicsAdaptor : public BaseHandle
48 {
49 public:
50   /**
51    * @brief Enumeration to turn the integration step on or off.
52    */
53   enum class IntegrationState
54   {
55     OFF,
56     ON
57   };
58
59   /**
60    * @brief Enumeration to turn the debug rendering on or off
61    */
62   enum class DebugState
63   {
64     OFF,
65     ON
66   };
67
68   /**
69    * @brief Scoped accessor to the physics world.
70    *
71    * @SINCE_2_2.43
72    * Automatically locks the physics world with a mutex to prevent the
73    * integration step from running whilst the developer is accessing
74    * the world, e.g. to add/remove bodies or constraints, or to
75    * perform hit-test.
76    *
77    * When it goes out of scope, the mutex is unlocked, and the integration step
78    * can resume.
79    */
80   struct ScopedPhysicsAccessor
81   {
82   public:
83     /**
84      * @brief Get a pointer to the native world.
85      *
86      * @SINCE_2_2.43
87      * This uses DALi::Any wrapper to ensure that the same interface can be used
88      * for both 2d and 3d physics. It can be cast to the right type using the
89      * following construct:
90      *   auto accessor = PhysicsAdaptor.GetPhysicsAccessor();
91      *   auto bulletWorld = accessor->GetNative().Get<btDiscreteDynamiscWorld*>();
92      */
93     Dali::Any GetNative();
94
95     /**
96      * @brief Hit test the physics world and return the nearest body.
97      *
98      * @SINCE_2_2.43
99      * @param[in] rayFromWorld The origin in physics world space
100      * @param[in] rayToWorld A point along the direction on the far side of the physics world
101      * @param[out] localPivot The hit point local to the body
102      * @param[out] distanceFromCamera The distance of the pick point from the camera
103      * @return Empty value if no dynamic body found, otherwise a valid ptr to the hit body.
104      */
105     Dali::Any HitTest(Dali::Vector3 rayFromWorld, Dali::Vector3 rayToWorld, Dali::Vector3& localPivot, float& distanceFromCamera);
106
107     // Not copyable
108     ScopedPhysicsAccessor(ScopedPhysicsAccessor&) = delete;
109     const ScopedPhysicsAccessor& operator=(const ScopedPhysicsAccessor&) = delete;
110
111     /**
112      * @brief Destructor.
113      *
114      * On leaving scope, the mutex is unlocked and the physics integration step
115      * can resume.
116      */
117     ~ScopedPhysicsAccessor();
118
119   private:
120     /**
121      * @brief Private constructor.
122      *
123      * It is created by the physics adaptor.
124      */
125     ScopedPhysicsAccessor(Internal::PhysicsWorld& world);
126     friend Internal::PhysicsAdaptor;
127
128     struct Impl; ///< Opaque implementation structure
129     Impl* mImpl;
130   };
131
132   /**
133    * @brief Creates an uninitalized PhysicsAdaptor, this can be initialized with PhysicsAdaptor::New().
134    *
135    * @SINCE_2_2.43
136    * Calling member functions with an uninitialized PhysicsAdaptor handle is not allowed.
137    */
138   PhysicsAdaptor();
139
140   /**
141    * @brief Destructor
142    *
143    * This is non-virtual since derived Handle types must not contain data or virtual methods.
144    * @SINCE_2_2.43
145    */
146   ~PhysicsAdaptor();
147
148   /**
149    * @brief Copy Constructor.
150    *
151    * @SINCE_2_2.43
152    * @param[in] handle The handle to copy
153    * @note This creates a new handle, but does not create a new implementation object.
154    */
155   PhysicsAdaptor(const PhysicsAdaptor& handle);
156
157   /**
158    * @brief Move Constructor.
159    *
160    * @SINCE_2_2.43
161    * @param[in] handle A reference to the handle to move
162    */
163   PhysicsAdaptor(PhysicsAdaptor&& rhs) noexcept;
164
165   /**
166    * @brief Assignment operator.
167    *
168    * @SINCE_2_2.43
169    * @param[in] handle A reference to the handle to move
170    * @return a reference to this handle
171    */
172   PhysicsAdaptor& operator=(const PhysicsAdaptor& handle);
173
174   /**
175    * @brief Move Assignment operator.
176    *
177    * @SINCE_2_2.43
178    * @param[in] handle A reference to the handle to move
179    * @return a reference to this handle
180    */
181   PhysicsAdaptor& operator=(PhysicsAdaptor&& handle) noexcept;
182
183   /**
184    * @brief Initialize the physics system.
185    *
186    * @SINCE_2_2.43
187    * @param[in] transform The transform matrix for DALi to Physics world space
188    * @param[in] size The size of the layer the physics actors will be drawn in
189    */
190   static PhysicsAdaptor New(const Dali::Matrix& transform, Uint16Pair size);
191
192   /**
193    * @brief Downcasts a handle to PhysicsAdaptor handle.
194    *
195    * If handle points to an PhysicsAdaptor object, the downcast produces valid handle.
196    * If not, the returned handle is left uninitialized.
197    *
198    * @SINCE_2_2.43
199    * @param[in] handle to an object
200    * @return handle to a PhysicsAdaptor object or an uninitialized handle
201    */
202   static PhysicsAdaptor DownCast(BaseHandle handle);
203
204   /**
205    * @brief Set how long the integration should take.
206    *
207    * @SINCE_2_2.43
208    * @param[in] timestep The length of time that the physics integration should take.
209    */
210   void SetTimestep(float timestep);
211
212   /**
213    * @brief Get the current physics integration timestep.
214    *
215    * @SINCE_2_2.43
216    * @return the current physics integration timestep
217    */
218   float GetTimestep() const;
219
220   /**
221    * @brief Type to represent a pointer to a scoped accessor.
222    *
223    * @SINCE_2_2.43
224    */
225   using ScopedPhysicsAccessorPtr = std::unique_ptr<PhysicsAdaptor::ScopedPhysicsAccessor>;
226
227   /**
228    * @brief Returns an accessor to the physics world.
229    *
230    * @SINCE_2_2.43
231    * It automatically locks a mutex to prevent the integration step
232    * from running whilst the world is being modified.
233    *
234    * When the pointer goes out of scope, the mutex is unlocked and the physics world
235    * can run again.
236    * @return the scoped accessor
237    */
238   ScopedPhysicsAccessorPtr GetPhysicsAccessor();
239
240   /**
241    * @brief Create a layer & debug renderer.
242    *
243    * @SINCE_2_2.43
244    * The debug renderer may utilize the debug features of the native physics
245    * engine.
246    *
247    * @param[in] window The window to draw in (requires camera)
248    * @return The debug layer
249    */
250   Dali::Layer CreateDebugLayer(Dali::Window window);
251
252   /**
253    * @brief Converts a point in RootActor local coords (e.g. gesture)
254    * into physics space coords.
255    *
256    * @SINCE_2_2.43
257    * @param vector The point to convert
258    * @return The converted point
259    */
260   Dali::Vector3 TranslateToPhysicsSpace(Dali::Vector3 vector) const;
261
262   /**
263    * @brief Convert a rotation in DALi coordinate system into physics space.
264    *
265    * @SINCE_2_2.43
266    * @param[in] rotation The rotation to convert
267    * @return the converted rotation.
268    */
269   Dali::Quaternion TranslateToPhysicsSpace(Dali::Quaternion rotation) const;
270
271   /**
272    * @brief Converts a point in physics space coords into RootActor local coords.
273    *
274    * @SINCE_2_2.43
275    * @param vector The point to convert
276    * @return The converted point
277    */
278   Dali::Vector3 TranslateFromPhysicsSpace(Dali::Vector3 vector) const;
279
280   /**
281    * @brief Convert a rotation in physics coordinate system into DALi space.
282    *
283    * @SINCE_2_2.43
284    * @param[in] rotation The rotation to convert
285    * @return the converted rotation.
286    */
287   Dali::Quaternion TranslateFromPhysicsSpace(Dali::Quaternion rotation) const;
288
289   /**
290    * @brief Converts a vector (not a point) in DALi space into physics space.
291    *
292    * @SINCE_2_2.43
293    * @param vector The vector to convert
294    * @return The converted vector
295    */
296   Dali::Vector3 ConvertVectorToPhysicsSpace(Dali::Vector3 vector) const;
297
298   /**
299    * @brief Converts a vector (not a point) in physics space to DALi space.
300    *
301    * @SINCE_2_2.43
302    * @param vector The vector to convert
303    * @return The converted vector
304    */
305   Dali::Vector3 ConvertVectorFromPhysicsSpace(Dali::Vector3 vector) const;
306
307   /**
308    * @brief Set up the transform from world space to physics space.
309    *
310    * @SINCE_2_2.43
311    * @param[in] transform The transform matrix for DALi to Physics world space
312    * @param[in] size The size of the layer the physics actors will be drawn in
313    */
314   void SetTransformAndSize(const Dali::Matrix& transform, Uint16Pair size);
315
316   /**
317    * @brief Set the integration state.
318    *
319    * @SINCE_2_2.43
320    * If it's turned off, physics will be paused.
321    * @note This is ON by default
322    * @param[in] state the new integration state
323    */
324   void SetIntegrationState(IntegrationState state);
325
326   /**
327    * @brief Get the integration state.
328    *
329    * @SINCE_2_2.43
330    * @return the new integration state
331    */
332   IntegrationState GetIntegrationState() const;
333
334   /**
335    * @brief Set the debug state.
336    *
337    * @SINCE_2_2.43
338    * If debug is turned on, use the physics engine
339    * debug to show wireframes in a layer above the root actor.
340    * @note This is OFF by default
341    * @param[in] state the new debug state
342    */
343   void SetDebugState(DebugState state);
344
345   /**
346    * @brief Get the debug state.
347    *
348    * @SINCE_2_2.43
349    * @return the new debug state
350    */
351   DebugState GetDebugState() const;
352
353   /**
354    * @brief Add an actor / body pair.
355    * @pre It's expected that the client has added the body to the physics world.
356    *
357    * The adaptor does not "take ownership" of the actor or the physics body.
358    * @SINCE_2_2.43
359    * @param[in] actor The actor used for rendering the physics object
360    * @param[in] body The physics object
361    * @return a handle to the actor / body pair.
362    */
363   PhysicsActor AddActorBody(Dali::Actor actor, Dali::Any body);
364
365   /**
366    * @brief Remove the actor / body.
367    *
368    * This will unparent the actor from the root actor and disassociate it from
369    * the body.
370    *
371    * It is the responsibility of the client to remove the body from the physics world
372    * and destroy it at an appropriate time. Create a scoped accessor to ensure
373    * that the integration step isn't being run when doing so.
374    *
375    * If the root actor is holding the last reference to the actor, it will be
376    * destroyed automatically, otherwise it is the responsibility of the client to
377    * dereference the actor.
378    *
379    * @SINCE_2_2.43
380    * @param[in] physicsActor The actor / body pair to remove.
381    */
382   void RemoveActorBody(PhysicsActor physicsActor);
383
384   /**
385    * @brief Get the physics actor associated with the given body.
386    *
387    * @SINCE_2_2.43
388    * @param[in] body The physics body
389    * @return the associated physics actor
390    */
391   PhysicsActor GetPhysicsActor(Dali::Any body) const;
392
393   /**
394    * @brief Get the root actor (which holds all the actor/body pairs).
395    *
396    * @SINCE_2_2.43
397    * @return the root actor.
398    */
399   Dali::Actor GetRootActor() const;
400
401   /**
402    * @brief Convert DALi touch point into a picking ray in the physics world.
403    *
404    * These can then be used to hit test the PhysicsWorld
405    *
406    * @SINCE_2_2.43
407    * @param[in] origin The origin in DALi world space
408    * @param[in] direction The direction of the picking ray
409    * @param[out] rayFromWorld The origin in physics world space
410    * @param[out] rayToWorld A point along the direction on the far side of the physics world
411    *
412    * Example:
413    *   OnTouched(Dali::Actor actor, Dali::TouchEvent& touch)
414    *   {
415    *     ..
416    *     Vector3 origin, direction;
417    *     Dali::HitTestAlgorithm::BuildPickingRay(renderTask, touch.GetScreenPosition(0), origin, direction);
418    *     btVector3 rayFromWorld, rayToWorld;
419    *     physicsAdaptor.BuildPickingRay(origin, direction, rayFromWorld, rayToWorld);
420    *     auto scopedAccessor = physicsAdaptor.GetPhysicsAccessor();
421    *     body = scopedAccessor->Get().HitTest(rayFromWorld, rayToWorld, ..);
422    *   }
423    */
424   void BuildPickingRay(Dali::Vector3 origin, Dali::Vector3 direction, Dali::Vector3& rayFromWorld, Dali::Vector3& rayToWorld);
425
426   /**
427    * @brief Project a point from the origin (in DALi space) a distance along
428    * the direction vector (in DALi space), and return the projected
429    * point in Physics space.
430    *
431    * @SINCE_2_2.43
432    * @param[in] origin    Origin in DALi world space
433    * @param[in] direction Direction in DALi world space
434    * @param[in] distance  Distance along the direction vector
435    * @return the projected point, converted to the Physics space.
436    */
437   Dali::Vector3 ProjectPoint(Dali::Vector3 origin, Dali::Vector3 direction, float distance);
438
439   /**
440    * @brief Queue a function to be executed before the physics integration in the update thread.
441    *
442    * @SINCE_2_2.43
443    * Multiple functions can be queued up. They are executed in the update frame
444    * callback when the next sync point is seen, so CreateSyncPoint() should be called
445    * afterwards for this to be executed.
446    *
447    * @param[in] function to execute. This can be any method, and it can work fine with
448    * physics bodies etc, but it must not be used with DALI event side objects, as this
449    * will very likely cause the update thread to crash.
450    */
451   void Queue(std::function<void(void)> function);
452
453   /**
454    * @brief Create a sync point for queued functions.
455    *
456    * @SINCE_2_2.43
457    * Ensures that any previously queued functions are processed
458    * in the Update::FrameCallback during the same frame as other
459    * DALi properties set during this event handler invocation.
460    * For example,
461    *   boxActor = Actor::New();
462    *   //... Create box actor renderer ...
463    *   btRigidBodyConstructionInfo info;
464    *   //... set construction properties
465    *   boxBody = new btRigidBody(info);
466    *   auto boxPhysicsActor = physicsAdaptor.AddActorBody(boxActor, boxBody);
467    *   boxActor.SetProperty(Actor::Property::VISIBLE, true);
468    *   boxActor.SetProperty(Actor::Property::OPACITY, 0.5f);
469    *   physicsAdaptor.Queue([boxBody](){ boxBody->activate(true);});
470    *   btVector3 impulse(4, 5, 6);
471    *   btVector3 position();
472    *   physicsAdaptor.Queue([boxBody](){ boxBody->applyImpulse(impulse, position);});
473    *   physicsAdaptor.CreateSyncPoint();
474    *
475    * Ensures that the box has both render properties and physics properties applied
476    * during the same frame.
477    */
478   void CreateSyncPoint();
479
480 public: // Not intended for developer use
481   /// @cond internal
482   /**
483    * @brief This constructor is used by PhysicsAdaptor::New() methods.
484    *
485    * @SINCE_2_2.43
486    * @param[in] impl A pointer to a newly allocated Dali resource.
487    * @note Not intended for application developers
488    */
489   explicit DALI_INTERNAL PhysicsAdaptor(Internal::PhysicsAdaptor* impl);
490   /// @endcond
491 };
492
493 } // namespace Dali::Toolkit::Physics
494
495 #endif //DALI_TOOLKIT_PHYSICS_ADAPTOR_H