SET(TC_SOURCES
utc-Dali-PhysicsAdaptor.cpp
utc-Dali-PhysicsActor.cpp
+ utc-Dali-IntegPhysics.cpp
)
# List of test harness files (Won't get parsed for test cases)
--- /dev/null
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdlib.h>
+#include <iostream>
+#include <typeinfo>
+
+// Need to override adaptor classes for toolkit test harness, so include
+// test harness headers before dali headers.
+#include <dali-physics/dali-physics.h>
+
+#include <dali-physics/integration-api/integ-physics-adaptor.h>
+#include <dali-physics/integration-api/physics-world.h>
+
+#include <dali-toolkit-test-suite-utils.h>
+#include <toolkit-event-thread-callback.h>
+
+#include <dali-toolkit/devel-api/controls/alignment/alignment.h>
+#include <dali-toolkit/public-api/controls/image-view/image-view.h>
+#include <dali/devel-api/adaptor-framework/window-devel.h>
+#include <dali/devel-api/events/hit-test-algorithm.h>
+
+#include <chipmunk/chipmunk.h>
+
+using namespace Dali;
+using namespace Dali::Toolkit::Physics;
+
+static const char* BALL_IMAGE = TEST_RESOURCE_DIR "/gallery-small-1.jpg";
+
+static cpBody* CreateBody(cpSpace* space)
+{
+ const float BALL_MASS = 10.0f;
+ const float BALL_RADIUS = 26.0f;
+ const float BALL_ELASTICITY = 0.5f;
+ const float BALL_FRICTION = 0.5f;
+
+ cpBody* body = cpSpaceAddBody(space, cpBodyNew(BALL_MASS, cpMomentForCircle(BALL_MASS, 0.0f, BALL_RADIUS, cpvzero)));
+
+ cpShape* shape = cpSpaceAddShape(space, cpCircleShapeNew(body, BALL_RADIUS, cpvzero));
+ cpShapeSetElasticity(shape, BALL_ELASTICITY);
+ cpShapeSetFriction(shape, BALL_FRICTION);
+
+ return body;
+}
+
+// Defines a PolyShape
+static cpBody* CreateHexBody(cpSpace* space)
+{
+ const float MASS = 10.0f;
+ const float RADIUS = 26.0f;
+ const float ELASTICITY = 0.5f;
+ const float FRICTION = 0.5f;
+
+ cpVect hexagon[6];
+ for(int i = 0; i < 6; i++)
+ {
+ cpFloat angle = -CP_PI * 2.0f * i / 6.0f;
+ hexagon[i] = cpvmult(cpv(cos(angle), sin(angle)), RADIUS - 1.0f);
+ }
+
+ cpBody* body = cpSpaceAddBody(space, cpBodyNew(MASS, cpMomentForPoly(MASS, 6, hexagon, cpvzero, 0.0f)));
+ cpShape* shape = cpSpaceAddShape(space, cpPolyShapeNew(body, 6, hexagon, cpTransformIdentity, 1.0f));
+
+ cpShapeSetElasticity(shape, ELASTICITY);
+ cpShapeSetFriction(shape, FRICTION);
+
+ return body;
+}
+
+int UtcDaliPhysics2DIntegrationGetPhysicsWorld(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline("Testing getting the physics world");
+
+ Matrix transform(true);
+ Uint16Pair size(640, 480);
+ PhysicsAdaptor adaptor = PhysicsAdaptor::New(transform, size);
+ DALI_TEST_CHECK(adaptor);
+
+ Dali::Toolkit::Physics::Integration::PhysicsWorld world = Dali::Toolkit::Physics::Integration::GetPhysicsWorld(adaptor);
+
+ DALI_TEST_CHECK(world.GetImpl() != nullptr);
+
+ END_TEST;
+}
+
+int UtcDaliPhysics2DIntegrationPhysicsWorldLockUnlock(void)
+{
+ ToolkitTestApplication application;
+
+ Matrix transform(true);
+ Uint16Pair size(640, 480);
+ PhysicsAdaptor adaptor = PhysicsAdaptor::New(transform, size);
+ Actor rootActor = adaptor.GetRootActor();
+ auto scene = application.GetScene();
+ scene.Add(rootActor);
+
+ Dali::Actor ballActor = Toolkit::ImageView::New(BALL_IMAGE);
+
+ cpBody* body{nullptr};
+ PhysicsActor physicsActor;
+ {
+ auto accessor = adaptor.GetPhysicsAccessor();
+ auto space = accessor->GetNative().Get<cpSpace*>();
+ body = CreateBody(space);
+ physicsActor = adaptor.AddActorBody(ballActor, body);
+ }
+
+ DALI_TEST_CHECK(adaptor);
+ Dali::Toolkit::Physics::Integration::PhysicsWorld world = Dali::Toolkit::Physics::Integration::GetPhysicsWorld(adaptor);
+
+ world.Lock();
+ world.Unlock();
+
+ {
+ tet_infoline("Test that creating accessor after unlocking this does not lock up!");
+ auto accessor = adaptor.GetPhysicsAccessor();
+ }
+
+ tet_result(TET_PASS);
+ END_TEST;
+}
+
+int UtcDaliPhysics2DIntegrationPhysicsWorldGetNative(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline("Testing getting the native world through Integ API");
+
+ Matrix transform(true);
+ Uint16Pair size(640, 480);
+ PhysicsAdaptor adaptor = PhysicsAdaptor::New(transform, size);
+ Actor rootActor = adaptor.GetRootActor();
+ auto scene = application.GetScene();
+ scene.Add(rootActor);
+
+ Dali::Actor ballActor = Toolkit::ImageView::New(BALL_IMAGE);
+
+ cpBody* body{nullptr};
+ PhysicsActor physicsActor;
+ {
+ auto accessor = adaptor.GetPhysicsAccessor();
+ auto space = accessor->GetNative().Get<cpSpace*>();
+ body = CreateBody(space);
+ physicsActor = adaptor.AddActorBody(ballActor, body);
+ }
+
+ DALI_TEST_CHECK(adaptor);
+ Dali::Toolkit::Physics::Integration::PhysicsWorld world = Dali::Toolkit::Physics::Integration::GetPhysicsWorld(adaptor);
+
+ world.Lock();
+ cpBody* newBody{nullptr};
+ try
+ {
+ auto worldImpl = world.GetNative();
+ cpSpace* space = worldImpl.Get<cpSpace*>();
+ DALI_TEST_CHECK(space != nullptr);
+
+ newBody = CreateHexBody(space);
+ }
+ catch(DaliException& e)
+ {
+ tet_result(TET_FAIL);
+ }
+ world.Unlock();
+
+ DALI_TEST_CHECK(newBody != nullptr);
+ END_TEST;
+}
+
+int UtcDaliPhysics2DIntegrationPhysicsWorldHitTest(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline("Testing the Hit Test works through Integ API");
+
+ const Vector2 center(TestApplication::DEFAULT_SURFACE_WIDTH * 0.5f, TestApplication::DEFAULT_SURFACE_HEIGHT * 0.5f);
+
+ Matrix transform(true);
+ Uint16Pair size(640, 480);
+ PhysicsAdaptor adaptor = PhysicsAdaptor::New(transform, size);
+ Actor rootActor = adaptor.GetRootActor();
+ auto scene = application.GetScene();
+ scene.Add(rootActor);
+
+ Dali::Actor ballActor = Toolkit::ImageView::New(BALL_IMAGE);
+
+ cpBody* body{nullptr};
+ PhysicsActor physicsActor;
+ {
+ auto accessor = adaptor.GetPhysicsAccessor();
+ auto space = accessor->GetNative().Get<cpSpace*>();
+ body = CreateBody(space);
+ physicsActor = adaptor.AddActorBody(ballActor, body);
+ }
+
+ DALI_TEST_CHECK(adaptor);
+
+ Vector3 from, to;
+ adaptor.BuildPickingRay(Vector3(center), Vector3(center), from, to);
+
+ Dali::Toolkit::Physics::Integration::PhysicsWorld world = Dali::Toolkit::Physics::Integration::GetPhysicsWorld(adaptor);
+ world.Lock();
+ try
+ {
+ auto worldImpl = world.GetNative();
+ cpSpace* space = worldImpl.Get<cpSpace*>();
+ DALI_TEST_CHECK(space != nullptr);
+
+ cpShapeFilter GRAB_FILTER = {CP_NO_GROUP, 1u << 31, 1u << 31};
+ Dali::Any nativeFilter{GRAB_FILTER};
+ Vector3 localPivot;
+ float distanceFromCamera;
+ auto body = world.HitTest(from, from, nativeFilter, localPivot, distanceFromCamera);
+
+ DALI_TEST_CHECK(!body.Empty());
+ cpBody* cbody = body.Get<cpBody*>();
+
+ DALI_TEST_CHECK(cbody != nullptr);
+ }
+ catch(DaliException& e)
+ {
+ tet_result(TET_FAIL);
+ }
+ world.Unlock();
+
+ END_TEST;
+}
set(physics_src_files "")
include(${physics_dir}/public-api/file.list)
+include(${physics_dir}/integration-api/file.list)
+# Must come last!
include(${physics_dir}/internal/file.list)
set(prefix_include_dir "${prefix}/include")
include_directories(BEFORE
${repo_root_dir}
- "${prefix_include_dir}"
"${repo_root_dir}/dali-physics/third-party/bullet3/src"
"${repo_root_dir}/dali-physics/third-party/chipmunk2d/include"
)
+include_directories(AFTER "${prefix_include_dir}")
+
MESSAGE(STATUS "2D sources: ${physics2d_src_files}")
MESSAGE(STATUS "3D sources: ${physics3d_src_files}")
install( FILES ${physics_public_api_header_files}
DESTINATION "${INCLUDE_DIR}/dali-physics/public-api"
)
+install( FILES ${physics_integration_api_header_files}
+ DESTINATION "${INCLUDE_DIR}/dali-physics/integration-api"
+ )
install( FILES ${physics_dir}/dali-physics.h
DESTINATION "${INCLUDE_DIR}/dali-physics"
--- /dev/null
+set(physics_integration_api_dir "${physics_dir}/integration-api")
+
+set(physics_src_files ${physics_src_files}
+ ${physics_integration_api_dir}/integ-physics-adaptor.cpp
+ ${physics_integration_api_dir}/physics-world.cpp
+)
+
+set(physics_integration_api_header_files
+ ${physics_integration_api_dir}/integ-physics-adaptor.h
+ ${physics_integration_api_dir}/physics-world.h
+)
--- /dev/null
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali-physics/integration-api/integ-physics-adaptor.h>
+
+#include <dali-physics/internal/physics-adaptor-impl.h>
+#include <memory>
+
+namespace Dali::Toolkit::Physics::Integration
+{
+Integration::PhysicsWorld GetPhysicsWorld(PhysicsAdaptor adaptorHandle)
+{
+ std::unique_ptr<Internal::PhysicsWorld>& worldPtr = GetImplementation(adaptorHandle).GetPhysicsWorld();
+ return PhysicsWorld{worldPtr.get()};
+}
+
+} // namespace Dali::Toolkit::Physics::Integration
--- /dev/null
+#pragma once
+
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali-physics/integration-api/physics-world.h>
+
+#include <dali-physics/public-api/physics-adaptor.h>
+
+namespace Dali::Toolkit::Physics::Integration
+{
+Integration::PhysicsWorld GetPhysicsWorld(PhysicsAdaptor adaptorHandle);
+//void QueueCallback(PhysicsAdaptor adaptorHandle, CSharpCallbackType function);
+} // namespace Dali::Toolkit::Physics::Integration
--- /dev/null
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali-physics/integration-api/physics-world.h>
+#include <dali-physics/internal/physics-world-impl.h>
+#include <dali/public-api/common/dali-common.h>
+
+namespace Dali::Toolkit::Physics::Integration
+{
+PhysicsWorld::PhysicsWorld(Dali::Toolkit::Physics::Internal::PhysicsWorld* internalWorld)
+: impl(internalWorld)
+{
+}
+
+PhysicsWorld::~PhysicsWorld() = default;
+
+Dali::Toolkit::Physics::Internal::PhysicsWorld* PhysicsWorld::GetImpl()
+{
+ return impl;
+}
+
+void PhysicsWorld::Lock()
+{
+ DALI_ASSERT_ALWAYS(impl && "Physics world proxy has null impl");
+ impl->Lock();
+}
+
+void PhysicsWorld::Unlock()
+{
+ DALI_ASSERT_ALWAYS(impl && "Physics world proxy has null impl");
+ impl->Unlock();
+}
+
+Dali::Any PhysicsWorld::GetNative()
+{
+ DALI_ASSERT_ALWAYS(impl && "Physics world proxy has null impl");
+ return impl->GetNative();
+}
+
+Dali::Any PhysicsWorld::HitTest(Dali::Vector3 rayFromWorld, Dali::Vector3 rayToWorld, Dali::Any nativeFilter, Dali::Vector3& localPivot, float& distanceFromCamera)
+
+{
+ DALI_ASSERT_ALWAYS(impl && "Physics world proxy has null impl");
+ return impl->HitTest(rayFromWorld, rayToWorld, nativeFilter, localPivot, distanceFromCamera);
+}
+
+} // namespace Dali::Toolkit::Physics::Integration
--- /dev/null
+#pragma once
+
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <dali/public-api/math/vector3.h>
+#include <dali/public-api/object/any.h>
+
+namespace Dali::Toolkit::Physics::Internal
+{
+class PhysicsWorld;
+}
+
+namespace Dali::Toolkit::Physics::Integration
+{
+// Proxy to the physics world impl
+// Does NOT own physics world.
+// Copyable. Doesn't track lock.
+class PhysicsWorld
+{
+public:
+ PhysicsWorld(Dali::Toolkit::Physics::Internal::PhysicsWorld* impl);
+ ~PhysicsWorld();
+
+ PhysicsWorld(const PhysicsWorld& rhs) = default;
+ PhysicsWorld& operator=(const PhysicsWorld& rhs) = default;
+
+ /**
+ * Lock the physics world. The caller MUST unlock it afterwards, otherwise
+ * the physics integration step will block, and DALi update thread will be locked.
+ */
+ void Lock();
+
+ /**
+ * Unlock the physics world.
+ */
+ void Unlock();
+
+ /**
+ * Get a handle to the native physics world / space
+ *
+ * This API should be wrapped with Lock/Unlock in any interop implementation
+ */
+ Dali::Any GetNative();
+
+ /**
+ * Hit test the physics world.
+ *
+ * This API should be wrapped with Lock/Unlock in any interop implementation
+ */
+ Dali::Any HitTest(Dali::Vector3 rayFromWorld, Dali::Vector3 rayToWorld, Dali::Any nativeFilter, Dali::Vector3& localPivot, float& distanceFromCamera);
+
+ /**
+ * Get the implementation pointer
+ */
+ Dali::Toolkit::Physics::Internal::PhysicsWorld* GetImpl();
+
+private:
+ Dali::Toolkit::Physics::Internal::PhysicsWorld* impl;
+};
+
+} // namespace Dali::Toolkit::Physics::Integration
BulletPhysicsWorld::~BulletPhysicsWorld()
{
- Dali::Mutex::ScopedLock lock(mMutex);
+ Lock();
if(mDynamicsWorld)
{
delete mBroadphase;
delete mDispatcher;
delete mCollisionConfiguration;
+
+ Unlock();
}
Dali::Any BulletPhysicsWorld::GetNative()
void PhysicsActor::Initialize(void)
{
- cpBodySetUserData(mBody.Get<cpBody*>(), this);
+ cpBodySetUserData2(mBody.Get<cpBody*>(), this);
// RegisterObject?
}
{
uint32_t id = static_cast<uint32_t>(actor.GetProperty<int>(Actor::Property::ID));
cpBody* cBody = body.Get<cpBody*>();
- cpBodySetUserData(cBody, this);
+ cpBodySetUserData2(cBody, this);
mPhysicsActors.insert(std::make_pair(id, PhysicsActor::New(actor, body, *this)));
actor[Actor::Property::PARENT_ORIGIN] = Dali::ParentOrigin::CENTER;
cpBody* cBody = body.Get<cpBody*>();
if(cBody)
{
- cpBodySetUserData(cBody, nullptr);
+ cpBodySetUserData2(cBody, nullptr);
}
}
cpBody* cBody = body.Get<cpBody*>();
if(cBody)
{
- return reinterpret_cast<PhysicsActor*>(cpBodyGetUserData(cBody));
+ return reinterpret_cast<PhysicsActor*>(cpBodyGetUserData2(cBody));
}
DALI_LOG_ERROR("Body not found in physics actors");
return nullptr;
ChipmunkPhysicsWorld::~ChipmunkPhysicsWorld()
{
- Dali::Mutex::ScopedLock lock(mMutex);
+ Lock();
if(mSpace)
{
cpSpaceEachShape(mSpace, (cpSpaceShapeIteratorFunc)PostShapeFree, mSpace);
cpSpaceFree(mSpace);
mSpace = nullptr;
}
+ Unlock();
}
Dali::Any ChipmunkPhysicsWorld::GetNative()
mPhysicsWorld->CreateSyncPoint();
}
+std::unique_ptr<PhysicsWorld>& PhysicsAdaptor::GetPhysicsWorld()
+{
+ return mPhysicsWorld;
+}
+
} // namespace Dali::Toolkit::Physics::Internal
*/
void OnUpdateActors(Dali::UpdateProxy* updateProxy);
+ std::unique_ptr<PhysicsWorld>& GetPhysicsWorld();
+
protected:
std::unique_ptr<PhysicsWorld> mPhysicsWorld;
std::unordered_map<uint32_t, PhysicsActorPtr> mPhysicsActors;
#include <dali/devel-api/common/stage-devel.h>
#include <dali/devel-api/update/frame-callback-interface.h>
+thread_local int gLocked{0};
+
namespace Dali::Toolkit::Physics::Internal
{
/**
Dali::DevelStage::RemoveFrameCallback(Dali::Stage::GetCurrent(), *mFrameCallback);
}
-Dali::Mutex& PhysicsWorld::GetMutex()
-{
- return mMutex;
-}
-
bool PhysicsWorld::OnUpdate(Dali::UpdateProxy& updateProxy, float elapsedSeconds)
{
- Dali::Mutex::ScopedLock lock(mMutex);
+ ScopedLock lock(*this);
// Process command queue
if(mNotifySyncPoint != Dali::UpdateProxy::INVALID_SYNC &&
return mPhysicsTimeStep;
}
-void PhysicsWorld::Queue(std::function<void(void)> function)
+/**
+ * Lock the mutex.
+ */
+void PhysicsWorld::Lock()
{
- if(!mMutex.IsLocked()) // Annoyingly, the dali mutex scoped lock doesn't prevent relocking in the same thread.
- {
- Dali::Mutex::ScopedLock lock(mMutex);
- commandQueue.push(function);
- }
- else
+ //@todo Could replace the mutex with an atomic flag, if it's not set,
+ // the queue and integration step could be skipped
+ if(!gLocked)
{
- commandQueue.push(function);
+ gLocked = true;
+ mMutex.lock();
}
}
+/**
+ * Unlock the mutex
+ */
+void PhysicsWorld::Unlock()
+{
+ mMutex.unlock();
+ gLocked = false;
+}
+
+void PhysicsWorld::Queue(std::function<void(void)> function)
+{
+ ScopedLock lock(*this);
+ commandQueue.push(function);
+}
+
void PhysicsWorld::CreateSyncPoint()
{
mNotifySyncPoint = Dali::DevelStage::NotifyFrameCallback(Dali::Stage::GetCurrent(), *mFrameCallback);
*/
#include <dali/dali.h>
-#include <dali/devel-api/threading/mutex.h>
#include <dali/devel-api/update/frame-callback-interface.h>
#include <dali/devel-api/update/update-proxy.h>
#include <dali-physics/public-api/physics-adaptor.h>
#include <functional>
+#include <mutex>
#include <queue>
namespace Dali::Toolkit::Physics::Internal
float GetTimestep();
/**
+ * Lock the mutex.
+ */
+ void Lock();
+
+ /**
+ * Unlock the mutex
+ */
+ void Unlock();
+
+ class ScopedLock
+ {
+ public:
+ ScopedLock(PhysicsWorld& world)
+ : mWorld(world)
+ {
+ mWorld.Lock();
+ }
+ ~ScopedLock()
+ {
+ mWorld.Unlock();
+ }
+ PhysicsWorld& mWorld;
+ };
+
+ /**
* Queue a function for execution in the update thread, prior to the physics integration.
* Enables syncronization of DALi properties and physics controlled properties.
*/
Physics::PhysicsAdaptor::DebugState GetDebugState();
public:
- Dali::Mutex& GetMutex(); // Only for use by adaptor in creating scoped accessor
-
bool OnUpdate(Dali::UpdateProxy& updateProxy, float elapsedSeconds);
protected:
virtual void Integrate(float timestep) = 0;
protected:
- Dali::Mutex mMutex;
+ std::mutex mMutex;
std::queue<std::function<void(void)>> commandQueue;
Dali::UpdateProxy::NotifySyncPoint mNotifySyncPoint{Dali::UpdateProxy::INVALID_SYNC};
Dali::CallbackBase* mUpdateCallback{nullptr};
struct PhysicsAdaptor::ScopedPhysicsAccessor::Impl
{
Impl(Internal::PhysicsWorld& world)
- : mLock(world.GetMutex()),
- mPhysicsWorld(world)
+ : mPhysicsWorld(world)
{
+ mPhysicsWorld.Lock();
}
Impl(Impl&) = delete;
const Impl& operator=(const Impl&) = delete;
- Dali::Mutex::ScopedLock mLock;
+ ~Impl()
+ {
+ mPhysicsWorld.Unlock();
+ }
Internal::PhysicsWorld& mPhysicsWorld;
friend Internal::PhysicsAdaptor;
};
cpTransform transform;
cpDataPointer userData;
+ cpDataPointer userData2;
// "pseudo-velocities" used for eliminating overlap.
// Erin Catto has some papers that talk about what these are.
/// Set the user data pointer assigned to the body.
CP_EXPORT void cpBodySetUserData(cpBody *body, cpDataPointer userData);
+/// Get the 2nd user data pointer assigned to the body.
+CP_EXPORT cpDataPointer cpBodyGetUserData2(const cpBody *body);
+/// Set the 2nd user data pointer assigned to the body.
+CP_EXPORT void cpBodySetUserData2(cpBody *body, cpDataPointer userData);
+
/// Set the callback used to update a body's velocity.
CP_EXPORT void cpBodySetVelocityUpdateFunc(cpBody *body, cpBodyVelocityFunc velocityFunc);
/// Set the callback used to update a body's position.
file(GLOB chipmunk_source_files "*.c")
file(GLOB chipmunk_public_header "${chipmunk_SOURCE_DIR}/include/chipmunk/*.h")
-include_directories(${chipmunk_SOURCE_DIR}/include)
+include_directories(BEFORE ${chipmunk_SOURCE_DIR}/include)
# Chipmunk2D 7.0.3
set(CHIPMUNK_VERSION_MAJOR 7)
body->w_bias = 0.0f;
body->userData = NULL;
+ body->userData2 = NULL;
// Setters must be called after full initialization so the sanity checks don't assert on garbage data.
cpBodySetMass(body, mass);
{
body->userData = userData;
}
+cpDataPointer
+cpBodyGetUserData2(const cpBody *body)
+{
+ return body->userData2;
+}
+
+void
+cpBodySetUserData2(cpBody *body, cpDataPointer userData)
+{
+ body->userData2 = userData;
+}
void
cpBodySetVelocityUpdateFunc(cpBody *body, cpBodyVelocityFunc velocityFunc)
%files -n %{dali2_physics2d}-devel
%defattr(-,root,root,-)
+%{_includedir}/dali-physics/integration-api/*
%{_includedir}/dali-physics/public-api/*
%{_includedir}/dali-physics/dali-physics.h
%{_includedir}/chipmunk/*
%files -n %{dali2_physics3d}-devel
%defattr(-,root,root,-)
+%{_includedir}/dali-physics/integration-api/*
%{_includedir}/dali-physics/public-api/*
%{_includedir}/dali-physics/dali-physics.h
%{_includedir}/bullet/*