From 2ab44ebeec5fe2b6f4d1d74a7efb5dfe90435510 Mon Sep 17 00:00:00 2001 From: seungho baek Date: Thu, 14 Sep 2023 18:46:07 +0900 Subject: [PATCH] [Tizen] Added integration api to physics This reverts commit fab80765a2be37aa58d479bc78e8c496f09a4224. Change-Id: Id4a66d3ecb502220d9c76e2a45e10b25e71c9c23 --- automated-tests/src/dali-physics2d/CMakeLists.txt | 1 + .../src/dali-physics2d/utc-Dali-IntegPhysics.cpp | 239 +++++++++++++++++++++ build/tizen/dali-physics/CMakeLists.txt | 8 +- dali-physics/integration-api/file.list | 11 + .../integration-api/integ-physics-adaptor.cpp | 30 +++ .../integration-api/integ-physics-adaptor.h | 27 +++ dali-physics/integration-api/physics-world.cpp | 60 ++++++ dali-physics/integration-api/physics-world.h | 74 +++++++ .../bullet-impl/bullet-physics-world-impl.cpp | 4 +- .../chipmunk-impl/chipmunk-physics-actor-impl.cpp | 2 +- .../chipmunk-physics-adaptor-impl.cpp | 6 +- .../chipmunk-impl/chipmunk-physics-world-impl.cpp | 3 +- dali-physics/internal/physics-adaptor-impl.cpp | 5 + dali-physics/internal/physics-adaptor-impl.h | 2 + dali-physics/internal/physics-world-impl.cpp | 41 ++-- dali-physics/internal/physics-world-impl.h | 31 ++- .../public-api/scoped-physics-accessor.cpp | 9 +- .../chipmunk2d/include/chipmunk/chipmunk_structs.h | 1 + .../chipmunk2d/include/chipmunk/cpBody.h | 5 + .../third-party/chipmunk2d/src/CMakeLists.txt | 2 +- dali-physics/third-party/chipmunk2d/src/cpBody.c | 12 ++ packaging/dali-toolkit.spec | 2 + 22 files changed, 546 insertions(+), 29 deletions(-) create mode 100644 automated-tests/src/dali-physics2d/utc-Dali-IntegPhysics.cpp create mode 100644 dali-physics/integration-api/file.list create mode 100644 dali-physics/integration-api/integ-physics-adaptor.cpp create mode 100644 dali-physics/integration-api/integ-physics-adaptor.h create mode 100644 dali-physics/integration-api/physics-world.cpp create mode 100644 dali-physics/integration-api/physics-world.h diff --git a/automated-tests/src/dali-physics2d/CMakeLists.txt b/automated-tests/src/dali-physics2d/CMakeLists.txt index ea0f140..e796089 100644 --- a/automated-tests/src/dali-physics2d/CMakeLists.txt +++ b/automated-tests/src/dali-physics2d/CMakeLists.txt @@ -7,6 +7,7 @@ SET(RPM_NAME "core-${PKG_NAME}-tests") 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) diff --git a/automated-tests/src/dali-physics2d/utc-Dali-IntegPhysics.cpp b/automated-tests/src/dali-physics2d/utc-Dali-IntegPhysics.cpp new file mode 100644 index 0000000..c79c495 --- /dev/null +++ b/automated-tests/src/dali-physics2d/utc-Dali-IntegPhysics.cpp @@ -0,0 +1,239 @@ +/* + * 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 +#include +#include + +// Need to override adaptor classes for toolkit test harness, so include +// test harness headers before dali headers. +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include + +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(); + 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(); + 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(); + 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(); + 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(); + 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(); + + DALI_TEST_CHECK(cbody != nullptr); + } + catch(DaliException& e) + { + tet_result(TET_FAIL); + } + world.Unlock(); + + END_TEST; +} diff --git a/build/tizen/dali-physics/CMakeLists.txt b/build/tizen/dali-physics/CMakeLists.txt index 9c52173..63f4b9e 100644 --- a/build/tizen/dali-physics/CMakeLists.txt +++ b/build/tizen/dali-physics/CMakeLists.txt @@ -72,17 +72,20 @@ add_subdirectory("${physics_dir}/third-party/bullet3" bullet3) 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}") @@ -182,6 +185,9 @@ ENDIF() 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" diff --git a/dali-physics/integration-api/file.list b/dali-physics/integration-api/file.list new file mode 100644 index 0000000..bc85da7 --- /dev/null +++ b/dali-physics/integration-api/file.list @@ -0,0 +1,11 @@ +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 +) diff --git a/dali-physics/integration-api/integ-physics-adaptor.cpp b/dali-physics/integration-api/integ-physics-adaptor.cpp new file mode 100644 index 0000000..cc26338 --- /dev/null +++ b/dali-physics/integration-api/integ-physics-adaptor.cpp @@ -0,0 +1,30 @@ +/* + * 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 + +#include +#include + +namespace Dali::Toolkit::Physics::Integration +{ +Integration::PhysicsWorld GetPhysicsWorld(PhysicsAdaptor adaptorHandle) +{ + std::unique_ptr& worldPtr = GetImplementation(adaptorHandle).GetPhysicsWorld(); + return PhysicsWorld{worldPtr.get()}; +} + +} // namespace Dali::Toolkit::Physics::Integration diff --git a/dali-physics/integration-api/integ-physics-adaptor.h b/dali-physics/integration-api/integ-physics-adaptor.h new file mode 100644 index 0000000..01f2cde --- /dev/null +++ b/dali-physics/integration-api/integ-physics-adaptor.h @@ -0,0 +1,27 @@ +#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 + +#include + +namespace Dali::Toolkit::Physics::Integration +{ +Integration::PhysicsWorld GetPhysicsWorld(PhysicsAdaptor adaptorHandle); +//void QueueCallback(PhysicsAdaptor adaptorHandle, CSharpCallbackType function); +} // namespace Dali::Toolkit::Physics::Integration diff --git a/dali-physics/integration-api/physics-world.cpp b/dali-physics/integration-api/physics-world.cpp new file mode 100644 index 0000000..b17fa5c --- /dev/null +++ b/dali-physics/integration-api/physics-world.cpp @@ -0,0 +1,60 @@ +/* + * 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 +#include +#include + +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 diff --git a/dali-physics/integration-api/physics-world.h b/dali-physics/integration-api/physics-world.h new file mode 100644 index 0000000..c026bc4 --- /dev/null +++ b/dali-physics/integration-api/physics-world.h @@ -0,0 +1,74 @@ +#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 +#include + +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 diff --git a/dali-physics/internal/bullet-impl/bullet-physics-world-impl.cpp b/dali-physics/internal/bullet-impl/bullet-physics-world-impl.cpp index 920d015..accb9a4 100644 --- a/dali-physics/internal/bullet-impl/bullet-physics-world-impl.cpp +++ b/dali-physics/internal/bullet-impl/bullet-physics-world-impl.cpp @@ -54,7 +54,7 @@ void BulletPhysicsWorld::OnInitialize(/*void* dynamicsWorld*/) BulletPhysicsWorld::~BulletPhysicsWorld() { - Dali::Mutex::ScopedLock lock(mMutex); + Lock(); if(mDynamicsWorld) { @@ -90,6 +90,8 @@ BulletPhysicsWorld::~BulletPhysicsWorld() delete mBroadphase; delete mDispatcher; delete mCollisionConfiguration; + + Unlock(); } Dali::Any BulletPhysicsWorld::GetNative() diff --git a/dali-physics/internal/chipmunk-impl/chipmunk-physics-actor-impl.cpp b/dali-physics/internal/chipmunk-impl/chipmunk-physics-actor-impl.cpp index eee9cd4..3cb98f6 100644 --- a/dali-physics/internal/chipmunk-impl/chipmunk-physics-actor-impl.cpp +++ b/dali-physics/internal/chipmunk-impl/chipmunk-physics-actor-impl.cpp @@ -54,7 +54,7 @@ PhysicsActor::~PhysicsActor() = default; void PhysicsActor::Initialize(void) { - cpBodySetUserData(mBody.Get(), this); + cpBodySetUserData2(mBody.Get(), this); // RegisterObject? } diff --git a/dali-physics/internal/chipmunk-impl/chipmunk-physics-adaptor-impl.cpp b/dali-physics/internal/chipmunk-impl/chipmunk-physics-adaptor-impl.cpp index 923927a..b909890 100644 --- a/dali-physics/internal/chipmunk-impl/chipmunk-physics-adaptor-impl.cpp +++ b/dali-physics/internal/chipmunk-impl/chipmunk-physics-adaptor-impl.cpp @@ -131,7 +131,7 @@ PhysicsActorPtr ChipmunkPhysicsAdaptor::AddActorBody(Dali::Actor actor, Dali::An { uint32_t id = static_cast(actor.GetProperty(Actor::Property::ID)); cpBody* cBody = body.Get(); - 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; @@ -156,7 +156,7 @@ void ChipmunkPhysicsAdaptor::RemoveActorBody(PhysicsActor& physicsActor) cpBody* cBody = body.Get(); if(cBody) { - cpBodySetUserData(cBody, nullptr); + cpBodySetUserData2(cBody, nullptr); } } @@ -165,7 +165,7 @@ PhysicsActorPtr ChipmunkPhysicsAdaptor::GetPhysicsActor(Dali::Any body) const cpBody* cBody = body.Get(); if(cBody) { - return reinterpret_cast(cpBodyGetUserData(cBody)); + return reinterpret_cast(cpBodyGetUserData2(cBody)); } DALI_LOG_ERROR("Body not found in physics actors"); return nullptr; diff --git a/dali-physics/internal/chipmunk-impl/chipmunk-physics-world-impl.cpp b/dali-physics/internal/chipmunk-impl/chipmunk-physics-world-impl.cpp index 7423edd..353dc7f 100644 --- a/dali-physics/internal/chipmunk-impl/chipmunk-physics-world-impl.cpp +++ b/dali-physics/internal/chipmunk-impl/chipmunk-physics-world-impl.cpp @@ -90,7 +90,7 @@ void ChipmunkPhysicsWorld::OnInitialize(/*void* dynamicsWorld*/) ChipmunkPhysicsWorld::~ChipmunkPhysicsWorld() { - Dali::Mutex::ScopedLock lock(mMutex); + Lock(); if(mSpace) { cpSpaceEachShape(mSpace, (cpSpaceShapeIteratorFunc)PostShapeFree, mSpace); @@ -99,6 +99,7 @@ ChipmunkPhysicsWorld::~ChipmunkPhysicsWorld() cpSpaceFree(mSpace); mSpace = nullptr; } + Unlock(); } Dali::Any ChipmunkPhysicsWorld::GetNative() diff --git a/dali-physics/internal/physics-adaptor-impl.cpp b/dali-physics/internal/physics-adaptor-impl.cpp index 09b3408..e9bfe82 100644 --- a/dali-physics/internal/physics-adaptor-impl.cpp +++ b/dali-physics/internal/physics-adaptor-impl.cpp @@ -125,4 +125,9 @@ void PhysicsAdaptor::CreateSyncPoint() mPhysicsWorld->CreateSyncPoint(); } +std::unique_ptr& PhysicsAdaptor::GetPhysicsWorld() +{ + return mPhysicsWorld; +} + } // namespace Dali::Toolkit::Physics::Internal diff --git a/dali-physics/internal/physics-adaptor-impl.h b/dali-physics/internal/physics-adaptor-impl.h index 02e651a..fb3939b 100644 --- a/dali-physics/internal/physics-adaptor-impl.h +++ b/dali-physics/internal/physics-adaptor-impl.h @@ -179,6 +179,8 @@ public: */ void OnUpdateActors(Dali::UpdateProxy* updateProxy); + std::unique_ptr& GetPhysicsWorld(); + protected: std::unique_ptr mPhysicsWorld; std::unordered_map mPhysicsActors; diff --git a/dali-physics/internal/physics-world-impl.cpp b/dali-physics/internal/physics-world-impl.cpp index b0ca04d..41da002 100644 --- a/dali-physics/internal/physics-world-impl.cpp +++ b/dali-physics/internal/physics-world-impl.cpp @@ -24,6 +24,8 @@ #include #include +thread_local int gLocked{0}; + namespace Dali::Toolkit::Physics::Internal { /** @@ -83,14 +85,9 @@ PhysicsWorld::~PhysicsWorld() 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 && @@ -134,19 +131,35 @@ float PhysicsWorld::GetTimestep() return mPhysicsTimeStep; } -void PhysicsWorld::Queue(std::function 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 function) +{ + ScopedLock lock(*this); + commandQueue.push(function); +} + void PhysicsWorld::CreateSyncPoint() { mNotifySyncPoint = Dali::DevelStage::NotifyFrameCallback(Dali::Stage::GetCurrent(), *mFrameCallback); diff --git a/dali-physics/internal/physics-world-impl.h b/dali-physics/internal/physics-world-impl.h index b1c9460..f14f546 100644 --- a/dali-physics/internal/physics-world-impl.h +++ b/dali-physics/internal/physics-world-impl.h @@ -18,13 +18,13 @@ */ #include -#include #include #include #include #include +#include #include namespace Dali::Toolkit::Physics::Internal @@ -89,6 +89,31 @@ public: 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. */ @@ -139,15 +164,13 @@ public: 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> commandQueue; Dali::UpdateProxy::NotifySyncPoint mNotifySyncPoint{Dali::UpdateProxy::INVALID_SYNC}; Dali::CallbackBase* mUpdateCallback{nullptr}; diff --git a/dali-physics/public-api/scoped-physics-accessor.cpp b/dali-physics/public-api/scoped-physics-accessor.cpp index 1fad04c..e0804f8 100644 --- a/dali-physics/public-api/scoped-physics-accessor.cpp +++ b/dali-physics/public-api/scoped-physics-accessor.cpp @@ -24,14 +24,17 @@ namespace Dali::Toolkit::Physics 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; }; diff --git a/dali-physics/third-party/chipmunk2d/include/chipmunk/chipmunk_structs.h b/dali-physics/third-party/chipmunk2d/include/chipmunk/chipmunk_structs.h index d8b1e6f..d5efa19 100644 --- a/dali-physics/third-party/chipmunk2d/include/chipmunk/chipmunk_structs.h +++ b/dali-physics/third-party/chipmunk2d/include/chipmunk/chipmunk_structs.h @@ -61,6 +61,7 @@ struct cpBody { cpTransform transform; cpDataPointer userData; + cpDataPointer userData2; // "pseudo-velocities" used for eliminating overlap. // Erin Catto has some papers that talk about what these are. diff --git a/dali-physics/third-party/chipmunk2d/include/chipmunk/cpBody.h b/dali-physics/third-party/chipmunk2d/include/chipmunk/cpBody.h index 8e46cc3..db7a9ea 100644 --- a/dali-physics/third-party/chipmunk2d/include/chipmunk/cpBody.h +++ b/dali-physics/third-party/chipmunk2d/include/chipmunk/cpBody.h @@ -140,6 +140,11 @@ CP_EXPORT cpDataPointer cpBodyGetUserData(const cpBody *body); /// 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. diff --git a/dali-physics/third-party/chipmunk2d/src/CMakeLists.txt b/dali-physics/third-party/chipmunk2d/src/CMakeLists.txt index 55f7954..5c30d43 100644 --- a/dali-physics/third-party/chipmunk2d/src/CMakeLists.txt +++ b/dali-physics/third-party/chipmunk2d/src/CMakeLists.txt @@ -1,7 +1,7 @@ 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) diff --git a/dali-physics/third-party/chipmunk2d/src/cpBody.c b/dali-physics/third-party/chipmunk2d/src/cpBody.c index e5caaf9..3d2bb1c 100644 --- a/dali-physics/third-party/chipmunk2d/src/cpBody.c +++ b/dali-physics/third-party/chipmunk2d/src/cpBody.c @@ -56,6 +56,7 @@ cpBodyInit(cpBody *body, cpFloat mass, cpFloat moment) 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); @@ -483,6 +484,17 @@ cpBodySetUserData(cpBody *body, cpDataPointer userData) { 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) diff --git a/packaging/dali-toolkit.spec b/packaging/dali-toolkit.spec index da90ed7..8db2b8d 100644 --- a/packaging/dali-toolkit.spec +++ b/packaging/dali-toolkit.spec @@ -549,6 +549,7 @@ esac %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/* @@ -568,6 +569,7 @@ esac %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/* -- 2.7.4