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/chipmunk-impl/chipmunk-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>
29 #define GRABBABLE_MASK_BIT (1u << 31)
30 cpShapeFilter GRAB_FILTER = {CP_NO_GROUP, GRABBABLE_MASK_BIT, GRABBABLE_MASK_BIT};
32 inline cpVect ConvertVector(Dali::Vector3 vector)
34 return cpv(vector.x, vector.y);
37 static void ShapeFreeWrap(cpSpace* space, cpShape* shape, void* unused)
39 cpSpaceRemoveShape(space, shape);
43 static void PostShapeFree(cpShape* shape, cpSpace* space)
45 cpSpaceAddPostStepCallback(space, (cpPostStepFunc)ShapeFreeWrap, shape, NULL);
48 static void ConstraintFreeWrap(cpSpace* space, cpConstraint* constraint, void* unused)
50 cpSpaceRemoveConstraint(space, constraint);
51 cpConstraintFree(constraint);
54 static void PostConstraintFree(cpConstraint* constraint, cpSpace* space)
56 cpSpaceAddPostStepCallback(space, (cpPostStepFunc)ConstraintFreeWrap, constraint, NULL);
59 static void BodyFreeWrap(cpSpace* space, cpBody* body, void* unused)
61 cpSpaceRemoveBody(space, body);
65 static void PostBodyFree(cpBody* body, cpSpace* space)
67 cpSpaceAddPostStepCallback(space, (cpPostStepFunc)BodyFreeWrap, body, NULL);
71 namespace Dali::Toolkit::Physics::Internal
73 std::unique_ptr<PhysicsWorld> ChipmunkPhysicsWorld::New(Dali::Actor rootActor, Dali::CallbackBase* updateCallback)
75 std::unique_ptr<ChipmunkPhysicsWorld> world = std::make_unique<ChipmunkPhysicsWorld>(rootActor, updateCallback);
80 ChipmunkPhysicsWorld::ChipmunkPhysicsWorld(Dali::Actor rootActor, Dali::CallbackBase* updateCallback)
81 : PhysicsWorld(rootActor, updateCallback)
85 void ChipmunkPhysicsWorld::OnInitialize(/*void* dynamicsWorld*/)
87 // @todo Should enable developer to optionally supply their own created cpSpace.
88 mSpace = cpSpaceNew();
89 cpSpaceSetIterations(mSpace, 30);
90 cpSpaceSetSleepTimeThreshold(mSpace, 0.5f);
91 cpSpaceSetGravity(mSpace, cpv(0, -200));
94 ChipmunkPhysicsWorld::~ChipmunkPhysicsWorld()
96 Dali::Mutex::ScopedLock lock(mMutex);
99 cpSpaceEachShape(mSpace, (cpSpaceShapeIteratorFunc)PostShapeFree, mSpace);
100 cpSpaceEachConstraint(mSpace, (cpSpaceConstraintIteratorFunc)PostConstraintFree, mSpace);
101 cpSpaceEachBody(mSpace, (cpSpaceBodyIteratorFunc)PostBodyFree, mSpace);
107 Dali::Any ChipmunkPhysicsWorld::GetNative()
112 void ChipmunkPhysicsWorld::Integrate(float timestep)
114 if(mPhysicsIntegrateState == Physics::PhysicsAdaptor::IntegrationState::ON)
116 cpSpaceStep(mSpace, timestep);
120 Dali::Any ChipmunkPhysicsWorld::HitTest(Dali::Vector3 rayFromWorld, Dali::Vector3 rayToWorld, Dali::Vector3& localPivot, float& distanceFromCamera)
122 cpVect spacePosition = cpv(rayFromWorld.x, rayFromWorld.y);
123 cpFloat radius = 5.0f;
124 cpPointQueryInfo info = {0};
125 cpShape* shape = cpSpacePointQueryNearest(mSpace, spacePosition, radius, GRAB_FILTER, &info);
126 cpBody* hitBody{nullptr};
128 if(shape && cpBodyGetMass(cpShapeGetBody(shape)) < INFINITY)
130 // Use the closest point on the surface if the click is outside the shape.
131 cpVect nearest = (info.distance > 0.0f ? info.point : spacePosition);
132 hitBody = cpShapeGetBody(shape);
133 cpVect local = cpBodyWorldToLocal(hitBody, nearest);
134 localPivot.x = local.x;
135 localPivot.y = local.y;
140 // Only set non-null ptr into bodyPtr, leave empty if null.
148 } // namespace Dali::Toolkit::Physics::Internal