[dali_2.3.21] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / dali-physics / internal / physics-world-impl.h
1 #ifndef DALI_TOOLKIT_PHYSICS_INTERNAL_PHYSICS_WORLD_H
2 #define DALI_TOOLKIT_PHYSICS_INTERNAL_PHYSICS_WORLD_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 implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19
20 #include <dali/dali.h>
21 #include <dali/devel-api/update/frame-callback-interface.h>
22 #include <dali/devel-api/update/update-proxy.h>
23
24 #include <dali-physics/public-api/physics-adaptor.h>
25
26 #include <functional>
27 #include <mutex>
28 #include <queue>
29
30 namespace Dali::Toolkit::Physics::Internal
31 {
32 class PhysicsWorld;
33 class FrameCallback;
34
35 /**
36  * Abstract class that handles the update frame callback, queuing and calling
37  * functions before the integration step ; calling the integration step,
38  * and owning the mutex for the update callback.
39  *
40  * Implementing classes should also hold the physics world.
41  */
42 class PhysicsWorld
43 {
44 public:
45   /**
46    * Create a new physics world.
47    */
48   static std::unique_ptr<PhysicsWorld> New(Dali::Actor rootActor, Dali::CallbackBase* updateCallback);
49
50   /**
51    * Constructor which takes the root actor and a callback from the PhysicsAdaptor
52    * @param[in] rootActor The root actor that physics actors will be added to
53    * @param[in] updateCallback A callback from the PhysicsAdaptor which updates the physics actors after the integration step
54    */
55   PhysicsWorld(Dali::Actor rootActor, Dali::CallbackBase* updateCallback);
56
57   /**
58    * Virtual destructor.
59    * Note, removes the frame callback.
60    */
61   virtual ~PhysicsWorld();
62
63   /**
64    * Initialize derived classes and creates the frame callback
65    */
66   void Initialize();
67
68   /**
69    * Initialize the derived class
70    */
71   virtual void OnInitialize() = 0;
72
73   /**
74    * Get the native physics world / space.
75    * @return A pointer to the physics world / space
76    */
77   virtual Dali::Any GetNative() = 0;
78
79   /**
80    * Set how long the integration should take.
81    * @param[in] timestep The length of time that the physics integration should take.
82    */
83   void SetTimestep(float timestep);
84
85   /**
86    * Get the current physics integration timestep
87    * @return the current physics integration timestep
88    */
89   float GetTimestep();
90
91   /**
92    * Lock the mutex.
93    */
94   void Lock();
95
96   /**
97    * Unlock the mutex
98    */
99   void Unlock();
100
101   class ScopedLock
102   {
103   public:
104     ScopedLock(PhysicsWorld& world)
105     : mWorld(world)
106     {
107       mWorld.Lock();
108     }
109     ~ScopedLock()
110     {
111       mWorld.Unlock();
112     }
113     PhysicsWorld& mWorld;
114   };
115
116   /**
117    * Queue a function for execution in the update thread, prior to the physics integration.
118    * Enables syncronization of DALi properties and physics controlled properties.
119    */
120   void Queue(std::function<void(void)> function);
121
122   /**
123    * Create a sync point for queued functions.
124    *
125    * Ensures that any queued functions are processed after this sync
126    * point is seen in the Update::FrameCallback, which will be in the
127    * same frame as any other DALi properties set during this event
128    * handler invocation.
129    *
130    * @param[in] None
131    */
132   void CreateSyncPoint();
133
134   /**
135    * Hit test the physics world and return the nearest body.
136    *
137    * @param[in] rayFromWorld The origin in physics world space
138    * @param[in] rayToWorld A point along the direction on the far side of the physics world
139    * @param[in] nativeFilter a native body / shape filter
140    * @param[out] localPivot The hit point local to the body
141    * @param[out] distanceFromCamera The distance of the pick point from the camera
142    * @return Empty value if no dynamic body found, otherwise a valid ptr to the hit body.
143    */
144   virtual Dali::Any HitTest(Dali::Vector3 rayFromWorld, Dali::Vector3 rayToWorld, Dali::Any nativeFilter, Dali::Vector3& localPivot, float& distanceFromCamera) = 0;
145
146   /**
147    * @copydoc Dali::Toolkit::Physics::PhysicsAdaptor::SetIntegrationState
148    */
149   void SetIntegrationState(Physics::PhysicsAdaptor::IntegrationState state);
150
151   /**
152    * @copydoc Dali::Toolkit::Physics::PhysicsAdaptor::GetIntegrationState
153    */
154   Physics::PhysicsAdaptor::IntegrationState GetIntegrationState();
155
156   /**
157    * @copydoc Dali::Toolkit::Physics::PhysicsAdaptor::SetDebugState
158    */
159   void SetDebugState(Physics::PhysicsAdaptor::DebugState state);
160
161   /**
162    * @copydoc Dali::Toolkit::Physics::PhysicsAdaptor::GetDebugState
163    */
164   Physics::PhysicsAdaptor::DebugState GetDebugState();
165
166 public:
167   bool OnUpdate(Dali::UpdateProxy& updateProxy, float elapsedSeconds);
168
169 protected:
170   virtual void Integrate(float timestep) = 0;
171
172 protected:
173   std::mutex                            mMutex;
174   std::queue<std::function<void(void)>> commandQueue;
175   Dali::UpdateProxy::NotifySyncPoint    mNotifySyncPoint{Dali::UpdateProxy::INVALID_SYNC};
176   Dali::CallbackBase*                   mUpdateCallback{nullptr};
177   std::unique_ptr<FrameCallback>        mFrameCallback;
178   Dali::Actor                           mRootActor;
179
180   float                                     mPhysicsTimeStep{1.0 / 180.0};
181   Physics::PhysicsAdaptor::IntegrationState mPhysicsIntegrateState{Physics::PhysicsAdaptor::IntegrationState::ON};
182   Physics::PhysicsAdaptor::DebugState       mPhysicsDebugState{Physics::PhysicsAdaptor::DebugState::OFF};
183 };
184
185 } // namespace Dali::Toolkit::Physics::Internal
186
187 #endif //DALI_TOOLKIT_PHYSICS_INTERNAL_PHYSICS_WORLD_H