2 * Copyright (c) 2023 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 #include <dali-physics/internal/physics-world-impl.h>
23 #include <dali/dali.h>
24 #include <dali/devel-api/common/stage-devel.h>
25 #include <dali/devel-api/update/frame-callback-interface.h>
27 namespace Dali::Toolkit::Physics::Internal
30 * FrameCallback implementation. Will run the OnUpdate method.
32 class FrameCallback : public Dali::FrameCallbackInterface
38 explicit FrameCallback(PhysicsWorld& physicsWorld)
39 : mPhysicsWorld(physicsWorld)
46 * @param[in] updateProxy Used to set world matrix and size
47 * @param[in] elapsedSeconds Time since last frame
48 * @return Whether we should keep rendering.
50 bool Update(Dali::UpdateProxy& updateProxy, float elapsedSeconds) override
52 return mPhysicsWorld.OnUpdate(updateProxy, elapsedSeconds);
55 private: // Member variables
56 PhysicsWorld& mPhysicsWorld;
59 PhysicsWorld::PhysicsWorld(Dali::Actor rootActor, Dali::CallbackBase* updateCallback)
60 : mUpdateCallback(updateCallback),
65 void PhysicsWorld::Initialize()
67 // Call derived class's initializer
70 // Automatically start the frame callback. This means everything should
71 // be accessed with a mutex lock, which is automatically locked when
72 // ScopedAccessor is used.
73 mFrameCallback = std::make_unique<FrameCallback>(*this);
74 Dali::DevelStage::AddFrameCallback(Dali::Stage::GetCurrent(), *mFrameCallback, mRootActor);
75 Dali::Stage::GetCurrent().KeepRendering(30); // @todo Remove!
78 PhysicsWorld::~PhysicsWorld()
80 // Derived class's destructor should clean down physics objects under mutex lock
81 // On completion, can remove the callback.
83 Dali::DevelStage::RemoveFrameCallback(Dali::Stage::GetCurrent(), *mFrameCallback);
86 Dali::Mutex& PhysicsWorld::GetMutex()
91 bool PhysicsWorld::OnUpdate(Dali::UpdateProxy& updateProxy, float elapsedSeconds)
93 Dali::Mutex::ScopedLock lock(mMutex);
95 // Process command queue
96 if(mNotifySyncPoint != Dali::UpdateProxy::INVALID_SYNC &&
97 mNotifySyncPoint == updateProxy.PopSyncPoint())
101 commandQueue.front()(); // Execute the queued methods
103 } while(!commandQueue.empty());
105 mNotifySyncPoint = Dali::UpdateProxy::INVALID_SYNC;
108 // Perform as many integration steps as needed to handle elapsed time
109 static float frameTime = 0;
110 frameTime += elapsedSeconds;
113 Integrate(mPhysicsTimeStep);
114 frameTime -= mPhysicsTimeStep;
115 } while(frameTime > 0);
117 // Update the corresponding actors to their physics spaces
120 Dali::CallbackBase::Execute(*mUpdateCallback, &updateProxy); // Don't care about actor update return
123 // @todo Check physics world to see if everything is at rest
127 void PhysicsWorld::SetTimestep(float timeStep)
129 mPhysicsTimeStep = timeStep;
132 float PhysicsWorld::GetTimestep()
134 return mPhysicsTimeStep;
137 void PhysicsWorld::Queue(std::function<void(void)> function)
139 if(!mMutex.IsLocked()) // Annoyingly, the dali mutex scoped lock doesn't prevent relocking in the same thread.
141 Dali::Mutex::ScopedLock lock(mMutex);
142 commandQueue.push(function);
146 commandQueue.push(function);
150 void PhysicsWorld::CreateSyncPoint()
152 mNotifySyncPoint = Dali::DevelStage::NotifyFrameCallback(Dali::Stage::GetCurrent(), *mFrameCallback);
155 void PhysicsWorld::SetIntegrationState(Physics::PhysicsAdaptor::IntegrationState state)
157 mPhysicsIntegrateState = state;
160 Physics::PhysicsAdaptor::IntegrationState PhysicsWorld::GetIntegrationState()
162 return mPhysicsIntegrateState;
165 void PhysicsWorld::SetDebugState(Physics::PhysicsAdaptor::DebugState state)
167 mPhysicsDebugState = state;
170 Physics::PhysicsAdaptor::DebugState PhysicsWorld::GetDebugState()
172 return mPhysicsDebugState;
175 } // namespace Dali::Toolkit::Physics::Internal