diff options
Diffstat (limited to 'modules')
25 files changed, 839 insertions, 613 deletions
diff --git a/modules/bullet/btRayShape.cpp b/modules/bullet/btRayShape.cpp index b902d08eca..b60d6ba693 100644 --- a/modules/bullet/btRayShape.cpp +++ b/modules/bullet/btRayShape.cpp @@ -54,6 +54,11 @@ void btRayShape::setLength(btScalar p_length) { reload_cache(); } +void btRayShape::setMargin(btScalar margin) { + btConvexInternalShape::setMargin(margin); + reload_cache(); +} + void btRayShape::setSlipsOnSlope(bool p_slipsOnSlope) { slipsOnSlope = p_slipsOnSlope; @@ -77,10 +82,9 @@ void btRayShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVecto } void btRayShape::getAabb(const btTransform &t, btVector3 &aabbMin, btVector3 &aabbMax) const { -#define MARGIN_BROADPHASE 0.1 btVector3 localAabbMin(0, 0, 0); - btVector3 localAabbMax(m_shapeAxis * (m_cacheScaledLength + m_collisionMargin)); - btTransformAabb(localAabbMin, localAabbMax, MARGIN_BROADPHASE, t, aabbMin, aabbMax); + btVector3 localAabbMax(m_shapeAxis * m_cacheScaledLength); + btTransformAabb(localAabbMin, localAabbMax, m_collisionMargin, t, aabbMin, aabbMax); } void btRayShape::calculateLocalInertia(btScalar mass, btVector3 &inertia) const { @@ -100,5 +104,5 @@ void btRayShape::reload_cache() { m_cacheScaledLength = m_length * m_localScaling[2]; m_cacheSupportPoint.setIdentity(); - m_cacheSupportPoint.setOrigin(m_shapeAxis * (m_cacheScaledLength + m_collisionMargin)); + m_cacheSupportPoint.setOrigin(m_shapeAxis * m_cacheScaledLength); } diff --git a/modules/bullet/btRayShape.h b/modules/bullet/btRayShape.h index 7fedb74083..7f3229b3e8 100644 --- a/modules/bullet/btRayShape.h +++ b/modules/bullet/btRayShape.h @@ -60,6 +60,8 @@ public: void setLength(btScalar p_length); btScalar getLength() const { return m_length; } + virtual void setMargin(btScalar margin); + void setSlipsOnSlope(bool p_slipOnSlope); bool getSlipsOnSlope() const { return slipsOnSlope; } diff --git a/modules/bullet/collision_object_bullet.cpp b/modules/bullet/collision_object_bullet.cpp index 3a90bdc6ae..eb87901c24 100644 --- a/modules/bullet/collision_object_bullet.cpp +++ b/modules/bullet/collision_object_bullet.cpp @@ -43,7 +43,9 @@ @author AndreaCatania */ -#define enableDynamicAabbTree false +// We enable dynamic AABB tree so that we can actually perform a broadphase on bodies with compound collision shapes. +// This is crucial for the performance of kinematic bodies and for bodies with transforming shapes. +#define enableDynamicAabbTree true CollisionObjectBullet::ShapeWrapper::~ShapeWrapper() {} @@ -284,7 +286,6 @@ void RigidCollisionObjectBullet::set_shape_transform(int p_index, const Transfor ERR_FAIL_INDEX(p_index, get_shape_count()); shapes.write[p_index].set_transform(p_transform); - // Note, enableDynamicAabbTree is false because on transform change compound is destroyed reload_shapes(); } diff --git a/modules/bullet/godot_ray_world_algorithm.cpp b/modules/bullet/godot_ray_world_algorithm.cpp index 3e06239453..2ba75b9a98 100644 --- a/modules/bullet/godot_ray_world_algorithm.cpp +++ b/modules/bullet/godot_ray_world_algorithm.cpp @@ -39,6 +39,9 @@ @author AndreaCatania */ +// Epsilon to account for floating point inaccuracies +#define RAY_PENETRATION_DEPTH_EPSILON 0.01 + GodotRayWorldAlgorithm::CreateFunc::CreateFunc(const btDiscreteDynamicsWorld *world) : m_world(world) {} @@ -100,8 +103,8 @@ void GodotRayWorldAlgorithm::processCollision(const btCollisionObjectWrapper *bo btScalar depth(ray_shape->getScaledLength() * (btResult.m_closestHitFraction - 1)); - if (depth >= -ray_shape->getMargin() * 0.5) - depth = 0; + if (depth > -RAY_PENETRATION_DEPTH_EPSILON) + depth = 0.0; if (ray_shape->getSlipsOnSlope()) resultOut->addContactPoint(btResult.m_hitNormalWorld, btResult.m_hitPointWorld, depth); diff --git a/modules/bullet/space_bullet.cpp b/modules/bullet/space_bullet.cpp index 8fb8eba057..6bfd98873e 100644 --- a/modules/bullet/space_bullet.cpp +++ b/modules/bullet/space_bullet.cpp @@ -1043,23 +1043,16 @@ int SpaceBullet::test_ray_separation(RigidBodyBullet *p_body, const Transform &p btVector3 recover_motion(0, 0, 0); int rays_found = 0; + int rays_found_this_round = 0; for (int t(RECOVERING_MOVEMENT_CYCLES); 0 < t; --t) { - int last_ray_index = recover_from_penetration_ray(p_body, body_transform, RECOVERING_MOVEMENT_SCALE, p_infinite_inertia, p_result_max, recover_motion, r_results); + PhysicsServer::SeparationResult *next_results = &r_results[rays_found]; + rays_found_this_round = recover_from_penetration_ray(p_body, body_transform, RECOVERING_MOVEMENT_SCALE, p_infinite_inertia, p_result_max - rays_found, recover_motion, next_results); - rays_found = MAX(last_ray_index, rays_found); - if (!rays_found) { - break; - } else { + rays_found += rays_found_this_round; + if (rays_found_this_round == 0) { body_transform.getOrigin() += recover_motion; - } - } - - //optimize results (remove non colliding) - for (int i = 0; i < rays_found; i++) { - if (r_results[i].collision_depth >= 0) { - rays_found--; - SWAP(r_results[i], r_results[rays_found]); + break; } } @@ -1069,18 +1062,47 @@ int SpaceBullet::test_ray_separation(RigidBodyBullet *p_body, const Transform &p struct RecoverPenetrationBroadPhaseCallback : public btBroadphaseAabbCallback { private: + btDbvtVolume bounds; + const btCollisionObject *self_collision_object; uint32_t collision_layer; uint32_t collision_mask; + struct CompoundLeafCallback : btDbvt::ICollide { + private: + RecoverPenetrationBroadPhaseCallback *parent_callback; + btCollisionObject *collision_object; + + public: + CompoundLeafCallback(RecoverPenetrationBroadPhaseCallback *p_parent_callback, btCollisionObject *p_collision_object) : + parent_callback(p_parent_callback), + collision_object(p_collision_object) { + } + + void Process(const btDbvtNode *leaf) { + BroadphaseResult result; + result.collision_object = collision_object; + result.compound_child_index = leaf->dataAsInt; + parent_callback->results.push_back(result); + } + }; + public: - Vector<btCollisionObject *> result_collision_objects; + struct BroadphaseResult { + btCollisionObject *collision_object; + int compound_child_index; + }; + + Vector<BroadphaseResult> results; public: - RecoverPenetrationBroadPhaseCallback(const btCollisionObject *p_self_collision_object, uint32_t p_collision_layer, uint32_t p_collision_mask) : + RecoverPenetrationBroadPhaseCallback(const btCollisionObject *p_self_collision_object, uint32_t p_collision_layer, uint32_t p_collision_mask, btVector3 p_aabb_min, btVector3 p_aabb_max) : self_collision_object(p_self_collision_object), collision_layer(p_collision_layer), - collision_mask(p_collision_mask) {} + collision_mask(p_collision_mask) { + + bounds = btDbvtVolume::FromMM(p_aabb_min, p_aabb_max); + } virtual ~RecoverPenetrationBroadPhaseCallback() {} @@ -1089,35 +1111,98 @@ public: btCollisionObject *co = static_cast<btCollisionObject *>(proxy->m_clientObject); if (co->getInternalType() <= btCollisionObject::CO_RIGID_BODY) { if (self_collision_object != proxy->m_clientObject && GodotFilterCallback::test_collision_filters(collision_layer, collision_mask, proxy->m_collisionFilterGroup, proxy->m_collisionFilterMask)) { - result_collision_objects.push_back(co); + if (co->getCollisionShape()->isCompound()) { + const btCompoundShape *cs = static_cast<btCompoundShape *>(co->getCollisionShape()); + + if (cs->getNumChildShapes() > 1) { + const btDbvt *tree = cs->getDynamicAabbTree(); + ERR_FAIL_COND_V(tree == NULL, true); + + // Transform bounds into compound shape local space + const btTransform other_in_compound_space = co->getWorldTransform().inverse(); + const btMatrix3x3 abs_b = other_in_compound_space.getBasis().absolute(); + const btVector3 local_center = other_in_compound_space(bounds.Center()); + const btVector3 local_extent = bounds.Extents().dot3(abs_b[0], abs_b[1], abs_b[2]); + const btVector3 local_aabb_min = local_center - local_extent; + const btVector3 local_aabb_max = local_center + local_extent; + const btDbvtVolume local_bounds = btDbvtVolume::FromMM(local_aabb_min, local_aabb_max); + + // Test collision against compound child shapes using its AABB tree + CompoundLeafCallback compound_leaf_callback(this, co); + tree->collideTV(tree->m_root, local_bounds, compound_leaf_callback); + } else { + // If there's only a single child shape then there's no need to search any more, we know which child overlaps + BroadphaseResult result; + result.collision_object = co; + result.compound_child_index = 0; + results.push_back(result); + } + } else { + BroadphaseResult result; + result.collision_object = co; + result.compound_child_index = -1; + results.push_back(result); + } return true; } } return false; } - - void reset() { - result_collision_objects.clear(); - } }; bool SpaceBullet::recover_from_penetration(RigidBodyBullet *p_body, const btTransform &p_body_position, btScalar p_recover_movement_scale, bool p_infinite_inertia, btVector3 &r_delta_recover_movement, RecoverResult *r_recover_result) { - RecoverPenetrationBroadPhaseCallback recover_broad_result(p_body->get_bt_collision_object(), p_body->get_collision_layer(), p_body->get_collision_mask()); + // Calculate the cummulative AABB of all shapes of the kinematic body + btVector3 aabb_min, aabb_max; + bool shapes_found = false; + + for (int kinIndex = p_body->get_kinematic_utilities()->shapes.size() - 1; 0 <= kinIndex; --kinIndex) { + + const RigidBodyBullet::KinematicShape &kin_shape(p_body->get_kinematic_utilities()->shapes[kinIndex]); + if (!kin_shape.is_active()) { + continue; + } + + if (kin_shape.shape->getShapeType() == CUSTOM_CONVEX_SHAPE_TYPE) { + // Skip rayshape in order to implement custom separation process + continue; + } + + btTransform shape_transform = p_body_position * kin_shape.transform; + shape_transform.getOrigin() += r_delta_recover_movement; + + btVector3 shape_aabb_min, shape_aabb_max; + kin_shape.shape->getAabb(shape_transform, shape_aabb_min, shape_aabb_max); + + if (!shapes_found) { + aabb_min = shape_aabb_min; + aabb_max = shape_aabb_max; + shapes_found = true; + } else { + aabb_min.setX((aabb_min.x() < shape_aabb_min.x()) ? aabb_min.x() : shape_aabb_min.x()); + aabb_min.setY((aabb_min.y() < shape_aabb_min.y()) ? aabb_min.y() : shape_aabb_min.y()); + aabb_min.setZ((aabb_min.z() < shape_aabb_min.z()) ? aabb_min.z() : shape_aabb_min.z()); + + aabb_max.setX((aabb_max.x() > shape_aabb_max.x()) ? aabb_max.x() : shape_aabb_max.x()); + aabb_max.setY((aabb_max.y() > shape_aabb_max.y()) ? aabb_max.y() : shape_aabb_max.y()); + aabb_max.setZ((aabb_max.z() > shape_aabb_max.z()) ? aabb_max.z() : shape_aabb_max.z()); + } + } - btTransform body_shape_position; - btTransform body_shape_position_recovered; + // If there are no shapes then there is no penetration either + if (!shapes_found) { + return false; + } - // Broad phase support - btVector3 minAabb, maxAabb; + // Perform broadphase test + RecoverPenetrationBroadPhaseCallback recover_broad_result(p_body->get_bt_collision_object(), p_body->get_collision_layer(), p_body->get_collision_mask(), aabb_min, aabb_max); + dynamicsWorld->getBroadphase()->aabbTest(aabb_min, aabb_max, recover_broad_result); bool penetration = false; - // For each shape + // Perform narrowphase per shape for (int kinIndex = p_body->get_kinematic_utilities()->shapes.size() - 1; 0 <= kinIndex; --kinIndex) { - recover_broad_result.reset(); - const RigidBodyBullet::KinematicShape &kin_shape(p_body->get_kinematic_utilities()->shapes[kinIndex]); if (!kin_shape.is_active()) { continue; @@ -1128,15 +1213,11 @@ bool SpaceBullet::recover_from_penetration(RigidBodyBullet *p_body, const btTran continue; } - body_shape_position = p_body_position * kin_shape.transform; - body_shape_position_recovered = body_shape_position; - body_shape_position_recovered.getOrigin() += r_delta_recover_movement; + btTransform shape_transform = p_body_position * kin_shape.transform; + shape_transform.getOrigin() += r_delta_recover_movement; - kin_shape.shape->getAabb(body_shape_position_recovered, minAabb, maxAabb); - dynamicsWorld->getBroadphase()->aabbTest(minAabb, maxAabb, recover_broad_result); - - for (int i = recover_broad_result.result_collision_objects.size() - 1; 0 <= i; --i) { - btCollisionObject *otherObject = recover_broad_result.result_collision_objects[i]; + for (int i = recover_broad_result.results.size() - 1; 0 <= i; --i) { + btCollisionObject *otherObject = recover_broad_result.results[i].collision_object; if (p_infinite_inertia && !otherObject->isStaticOrKinematicObject()) { otherObject->activate(); // Force activation of hitten rigid, soft body continue; @@ -1144,30 +1225,28 @@ bool SpaceBullet::recover_from_penetration(RigidBodyBullet *p_body, const btTran continue; if (otherObject->getCollisionShape()->isCompound()) { + const btCompoundShape *cs = static_cast<const btCompoundShape *>(otherObject->getCollisionShape()); + int shape_idx = recover_broad_result.results[i].compound_child_index; + ERR_FAIL_COND_V(shape_idx < 0 || shape_idx >= cs->getNumChildShapes(), false); - // Each convex shape - btCompoundShape *cs = static_cast<btCompoundShape *>(otherObject->getCollisionShape()); - for (int x = cs->getNumChildShapes() - 1; 0 <= x; --x) { - - if (cs->getChildShape(x)->isConvex()) { - if (RFP_convex_convex_test(kin_shape.shape, static_cast<const btConvexShape *>(cs->getChildShape(x)), otherObject, x, body_shape_position, otherObject->getWorldTransform() * cs->getChildTransform(x), p_recover_movement_scale, r_delta_recover_movement, r_recover_result)) { + if (cs->getChildShape(shape_idx)->isConvex()) { + if (RFP_convex_convex_test(kin_shape.shape, static_cast<const btConvexShape *>(cs->getChildShape(shape_idx)), otherObject, shape_idx, shape_transform, otherObject->getWorldTransform() * cs->getChildTransform(shape_idx), p_recover_movement_scale, r_delta_recover_movement, r_recover_result)) { - penetration = true; - } - } else { - if (RFP_convex_world_test(kin_shape.shape, cs->getChildShape(x), p_body->get_bt_collision_object(), otherObject, kinIndex, x, body_shape_position, otherObject->getWorldTransform() * cs->getChildTransform(x), p_recover_movement_scale, r_delta_recover_movement, r_recover_result)) { + penetration = true; + } + } else { + if (RFP_convex_world_test(kin_shape.shape, cs->getChildShape(shape_idx), p_body->get_bt_collision_object(), otherObject, kinIndex, shape_idx, shape_transform, otherObject->getWorldTransform() * cs->getChildTransform(shape_idx), p_recover_movement_scale, r_delta_recover_movement, r_recover_result)) { - penetration = true; - } + penetration = true; } } } else if (otherObject->getCollisionShape()->isConvex()) { /// Execute GJK test against object shape - if (RFP_convex_convex_test(kin_shape.shape, static_cast<const btConvexShape *>(otherObject->getCollisionShape()), otherObject, 0, body_shape_position, otherObject->getWorldTransform(), p_recover_movement_scale, r_delta_recover_movement, r_recover_result)) { + if (RFP_convex_convex_test(kin_shape.shape, static_cast<const btConvexShape *>(otherObject->getCollisionShape()), otherObject, 0, shape_transform, otherObject->getWorldTransform(), p_recover_movement_scale, r_delta_recover_movement, r_recover_result)) { penetration = true; } } else { - if (RFP_convex_world_test(kin_shape.shape, otherObject->getCollisionShape(), p_body->get_bt_collision_object(), otherObject, kinIndex, 0, body_shape_position, otherObject->getWorldTransform(), p_recover_movement_scale, r_delta_recover_movement, r_recover_result)) { + if (RFP_convex_world_test(kin_shape.shape, otherObject->getCollisionShape(), p_body->get_bt_collision_object(), otherObject, kinIndex, 0, shape_transform, otherObject->getWorldTransform(), p_recover_movement_scale, r_delta_recover_movement, r_recover_result)) { penetration = true; } @@ -1183,7 +1262,6 @@ bool SpaceBullet::RFP_convex_convex_test(const btConvexShape *p_shapeA, const bt // Initialize GJK input btGjkPairDetector::ClosestPointInput gjk_input; gjk_input.m_transformA = p_transformA; - gjk_input.m_transformA.getOrigin() += r_delta_recover_movement; gjk_input.m_transformB = p_transformB; // Perform GJK test @@ -1214,7 +1292,6 @@ bool SpaceBullet::RFP_convex_world_test(const btConvexShape *p_shapeA, const btC /// Contact test btTransform tA(p_transformA); - tA.getOrigin() += r_delta_recover_movement; btCollisionObjectWrapper obA(NULL, p_shapeA, p_objectA, tA, -1, p_shapeId_A); btCollisionObjectWrapper obB(NULL, p_shapeB, p_objectB, p_transformB, -1, p_shapeId_B); @@ -1246,39 +1323,81 @@ bool SpaceBullet::RFP_convex_world_test(const btConvexShape *p_shapeA, const btC return false; } -void SpaceBullet::convert_to_separation_result(PhysicsServer::SeparationResult *r_result, const SpaceBullet::RecoverResult &p_recover_result, int p_shape_id, const btCollisionObject *p_other_object) const { +int SpaceBullet::add_separation_result(PhysicsServer::SeparationResult *r_result, const SpaceBullet::RecoverResult &p_recover_result, int p_shape_id, const btCollisionObject *p_other_object) const { + + // optimize results (ignore non-colliding) + if (p_recover_result.penetration_distance < 0.0) { + const btRigidBody *btRigid = static_cast<const btRigidBody *>(p_other_object); + CollisionObjectBullet *collisionObject = static_cast<CollisionObjectBullet *>(p_other_object->getUserPointer()); - const btRigidBody *btRigid = static_cast<const btRigidBody *>(p_other_object); - CollisionObjectBullet *collisionObject = static_cast<CollisionObjectBullet *>(p_other_object->getUserPointer()); + r_result->collision_depth = p_recover_result.penetration_distance; + B_TO_G(p_recover_result.pointWorld, r_result->collision_point); + B_TO_G(p_recover_result.normal, r_result->collision_normal); + B_TO_G(btRigid->getVelocityInLocalPoint(p_recover_result.pointWorld - btRigid->getWorldTransform().getOrigin()), r_result->collider_velocity); + r_result->collision_local_shape = p_shape_id; + r_result->collider_id = collisionObject->get_instance_id(); + r_result->collider = collisionObject->get_self(); + r_result->collider_shape = p_recover_result.other_compound_shape_index; - r_result->collision_depth = p_recover_result.penetration_distance; - B_TO_G(p_recover_result.pointWorld, r_result->collision_point); - B_TO_G(p_recover_result.normal, r_result->collision_normal); - B_TO_G(btRigid->getVelocityInLocalPoint(p_recover_result.pointWorld - btRigid->getWorldTransform().getOrigin()), r_result->collider_velocity); - r_result->collision_local_shape = p_shape_id; - r_result->collider_id = collisionObject->get_instance_id(); - r_result->collider = collisionObject->get_self(); - r_result->collider_shape = p_recover_result.other_compound_shape_index; + return 1; + } else { + return 0; + } } int SpaceBullet::recover_from_penetration_ray(RigidBodyBullet *p_body, const btTransform &p_body_position, btScalar p_recover_movement_scale, bool p_infinite_inertia, int p_result_max, btVector3 &r_delta_recover_movement, PhysicsServer::SeparationResult *r_results) { - RecoverPenetrationBroadPhaseCallback recover_broad_result(p_body->get_bt_collision_object(), p_body->get_collision_layer(), p_body->get_collision_mask()); + // Calculate the cummulative AABB of all shapes of the kinematic body + btVector3 aabb_min, aabb_max; + bool shapes_found = false; + + for (int kinIndex = p_body->get_kinematic_utilities()->shapes.size() - 1; 0 <= kinIndex; --kinIndex) { + + const RigidBodyBullet::KinematicShape &kin_shape(p_body->get_kinematic_utilities()->shapes[kinIndex]); + if (!kin_shape.is_active()) { + continue; + } + + if (kin_shape.shape->getShapeType() != CUSTOM_CONVEX_SHAPE_TYPE) { + continue; + } + + btTransform shape_transform = p_body_position * kin_shape.transform; + shape_transform.getOrigin() += r_delta_recover_movement; - btTransform body_shape_position; - btTransform body_shape_position_recovered; + btVector3 shape_aabb_min, shape_aabb_max; + kin_shape.shape->getAabb(shape_transform, shape_aabb_min, shape_aabb_max); - // Broad phase support - btVector3 minAabb, maxAabb; + if (!shapes_found) { + aabb_min = shape_aabb_min; + aabb_max = shape_aabb_max; + shapes_found = true; + } else { + aabb_min.setX((aabb_min.x() < shape_aabb_min.x()) ? aabb_min.x() : shape_aabb_min.x()); + aabb_min.setY((aabb_min.y() < shape_aabb_min.y()) ? aabb_min.y() : shape_aabb_min.y()); + aabb_min.setZ((aabb_min.z() < shape_aabb_min.z()) ? aabb_min.z() : shape_aabb_min.z()); - int ray_index = 0; + aabb_max.setX((aabb_max.x() > shape_aabb_max.x()) ? aabb_max.x() : shape_aabb_max.x()); + aabb_max.setY((aabb_max.y() > shape_aabb_max.y()) ? aabb_max.y() : shape_aabb_max.y()); + aabb_max.setZ((aabb_max.z() > shape_aabb_max.z()) ? aabb_max.z() : shape_aabb_max.z()); + } + } - // For each shape - for (int kinIndex = p_body->get_kinematic_utilities()->shapes.size() - 1; 0 <= kinIndex; --kinIndex) { + // If there are no shapes then there is no penetration either + if (!shapes_found) { + return 0; + } + + // Perform broadphase test + RecoverPenetrationBroadPhaseCallback recover_broad_result(p_body->get_bt_collision_object(), p_body->get_collision_layer(), p_body->get_collision_mask(), aabb_min, aabb_max); + dynamicsWorld->getBroadphase()->aabbTest(aabb_min, aabb_max, recover_broad_result); - recover_broad_result.reset(); + int ray_count = 0; + + // Perform narrowphase per shape + for (int kinIndex = p_body->get_kinematic_utilities()->shapes.size() - 1; 0 <= kinIndex; --kinIndex) { - if (ray_index >= p_result_max) { + if (ray_count >= p_result_max) { break; } @@ -1291,15 +1410,11 @@ int SpaceBullet::recover_from_penetration_ray(RigidBodyBullet *p_body, const btT continue; } - body_shape_position = p_body_position * kin_shape.transform; - body_shape_position_recovered = body_shape_position; - body_shape_position_recovered.getOrigin() += r_delta_recover_movement; + btTransform shape_transform = p_body_position * kin_shape.transform; + shape_transform.getOrigin() += r_delta_recover_movement; - kin_shape.shape->getAabb(body_shape_position_recovered, minAabb, maxAabb); - dynamicsWorld->getBroadphase()->aabbTest(minAabb, maxAabb, recover_broad_result); - - for (int i = recover_broad_result.result_collision_objects.size() - 1; 0 <= i; --i) { - btCollisionObject *otherObject = recover_broad_result.result_collision_objects[i]; + for (int i = recover_broad_result.results.size() - 1; 0 <= i; --i) { + btCollisionObject *otherObject = recover_broad_result.results[i].collision_object; if (p_infinite_inertia && !otherObject->isStaticOrKinematicObject()) { otherObject->activate(); // Force activation of hitten rigid, soft body continue; @@ -1307,29 +1422,25 @@ int SpaceBullet::recover_from_penetration_ray(RigidBodyBullet *p_body, const btT continue; if (otherObject->getCollisionShape()->isCompound()) { + const btCompoundShape *cs = static_cast<const btCompoundShape *>(otherObject->getCollisionShape()); + int shape_idx = recover_broad_result.results[i].compound_child_index; + ERR_FAIL_COND_V(shape_idx < 0 || shape_idx >= cs->getNumChildShapes(), false); - // Each convex shape - btCompoundShape *cs = static_cast<btCompoundShape *>(otherObject->getCollisionShape()); - for (int x = cs->getNumChildShapes() - 1; 0 <= x; --x) { - - RecoverResult recover_result; - if (RFP_convex_world_test(kin_shape.shape, cs->getChildShape(x), p_body->get_bt_collision_object(), otherObject, kinIndex, x, body_shape_position, otherObject->getWorldTransform() * cs->getChildTransform(x), p_recover_movement_scale, r_delta_recover_movement, &recover_result)) { + RecoverResult recover_result; + if (RFP_convex_world_test(kin_shape.shape, cs->getChildShape(shape_idx), p_body->get_bt_collision_object(), otherObject, kinIndex, shape_idx, shape_transform, otherObject->getWorldTransform() * cs->getChildTransform(shape_idx), p_recover_movement_scale, r_delta_recover_movement, &recover_result)) { - convert_to_separation_result(&r_results[ray_index], recover_result, kinIndex, otherObject); - } + ray_count = add_separation_result(&r_results[ray_count], recover_result, kinIndex, otherObject); } } else { RecoverResult recover_result; - if (RFP_convex_world_test(kin_shape.shape, otherObject->getCollisionShape(), p_body->get_bt_collision_object(), otherObject, kinIndex, 0, body_shape_position, otherObject->getWorldTransform(), p_recover_movement_scale, r_delta_recover_movement, &recover_result)) { + if (RFP_convex_world_test(kin_shape.shape, otherObject->getCollisionShape(), p_body->get_bt_collision_object(), otherObject, kinIndex, 0, shape_transform, otherObject->getWorldTransform(), p_recover_movement_scale, r_delta_recover_movement, &recover_result)) { - convert_to_separation_result(&r_results[ray_index], recover_result, kinIndex, otherObject); + ray_count = add_separation_result(&r_results[ray_count], recover_result, kinIndex, otherObject); } } } - - ++ray_index; } - return ray_index; + return ray_count; } diff --git a/modules/bullet/space_bullet.h b/modules/bullet/space_bullet.h index 7bf6a216b5..6b3d65edf6 100644 --- a/modules/bullet/space_bullet.h +++ b/modules/bullet/space_bullet.h @@ -212,7 +212,7 @@ private: /// Using this we leave Bullet to select the best algorithm, For example GJK in case we have Convex Convex, or a Bullet accelerated algorithm bool RFP_convex_world_test(const btConvexShape *p_shapeA, const btCollisionShape *p_shapeB, btCollisionObject *p_objectA, btCollisionObject *p_objectB, int p_shapeId_A, int p_shapeId_B, const btTransform &p_transformA, const btTransform &p_transformB, btScalar p_recover_movement_scale, btVector3 &r_delta_recover_movement, RecoverResult *r_recover_result = NULL); - void convert_to_separation_result(PhysicsServer::SeparationResult *r_result, const SpaceBullet::RecoverResult &p_recover_result, int p_shape_id, const btCollisionObject *p_other_object) const; + int add_separation_result(PhysicsServer::SeparationResult *r_results, const SpaceBullet::RecoverResult &p_recover_result, int p_shape_id, const btCollisionObject *p_other_object) const; int recover_from_penetration_ray(RigidBodyBullet *p_body, const btTransform &p_body_position, btScalar p_recover_movement_scale, bool p_infinite_inertia, int p_result_max, btVector3 &r_delta_recover_movement, PhysicsServer::SeparationResult *r_results); }; #endif diff --git a/modules/freetype/SCsub b/modules/freetype/SCsub index 0c8b223a9e..0ea581220e 100644 --- a/modules/freetype/SCsub +++ b/modules/freetype/SCsub @@ -61,13 +61,6 @@ if env['builtin_freetype']: # Globally too, as freetype is used in scene (see bottom) env.Append(CCFLAGS=['/FI', '"modules/freetype/uwpdef.h"']) - sfnt = thirdparty_dir + 'src/sfnt/sfnt.c' - if env['platform'] == 'javascript': - # Forcibly undefine this macro so SIMD is not used in this file, - # since currently unsupported in WASM - sfnt = env_freetype.Object(sfnt, CPPFLAGS=['-U__OPTIMIZE__']) - thirdparty_sources += [sfnt] - env_freetype.Prepend(CPPPATH=[thirdparty_dir + "/include"]) # Also needed in main env for scene/ env.Prepend(CPPPATH=[thirdparty_dir + "/include"]) @@ -80,6 +73,16 @@ if env['builtin_freetype']: if env['builtin_libpng']: env_freetype.Prepend(CPPPATH=["#thirdparty/libpng"]) + sfnt = thirdparty_dir + 'src/sfnt/sfnt.c' + # Must be done after all CPPFLAGS are being set so we can copy them. + if env['platform'] == 'javascript': + # Forcibly undefine this macro so SIMD is not used in this file, + # since currently unsupported in WASM + tmp_env = env_freetype.Clone() + tmp_env.Append(CPPFLAGS=['-U__OPTIMIZE__']) + sfnt = tmp_env.Object(sfnt) + thirdparty_sources += [sfnt] + env_thirdparty = env_freetype.Clone() env_thirdparty.disable_warnings() lib = env_thirdparty.add_library("freetype_builtin", thirdparty_sources) diff --git a/modules/gdnative/videodecoder/video_stream_gdnative.cpp b/modules/gdnative/videodecoder/video_stream_gdnative.cpp index 9bb1186269..be131c5402 100644 --- a/modules/gdnative/videodecoder/video_stream_gdnative.cpp +++ b/modules/gdnative/videodecoder/video_stream_gdnative.cpp @@ -146,23 +146,25 @@ void VideoStreamPlaybackGDNative::update(float p_delta) { ERR_FAIL_COND(interface == NULL); interface->update(data_struct, p_delta); - if (pcm_write_idx >= 0) { - // Previous remains - int mixed = mix_callback(mix_udata, pcm, samples_decoded); - if (mixed == samples_decoded) { - pcm_write_idx = -1; - } else { - samples_decoded -= mixed; - pcm_write_idx += mixed; + if (mix_callback) { + if (pcm_write_idx >= 0) { + // Previous remains + int mixed = mix_callback(mix_udata, pcm, samples_decoded); + if (mixed == samples_decoded) { + pcm_write_idx = -1; + } else { + samples_decoded -= mixed; + pcm_write_idx += mixed; + } } - } - if (pcm_write_idx < 0) { - samples_decoded = interface->get_audioframe(data_struct, pcm, AUX_BUFFER_SIZE); - pcm_write_idx = mix_callback(mix_udata, pcm, samples_decoded); - if (pcm_write_idx == samples_decoded) { - pcm_write_idx = -1; - } else { - samples_decoded -= pcm_write_idx; + if (pcm_write_idx < 0) { + samples_decoded = interface->get_audioframe(data_struct, pcm, AUX_BUFFER_SIZE); + pcm_write_idx = mix_callback(mix_udata, pcm, samples_decoded); + if (pcm_write_idx == samples_decoded) { + pcm_write_idx = -1; + } else { + samples_decoded -= pcm_write_idx; + } } } diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp index eada389c51..33e99cb82f 100644 --- a/modules/gdscript/gdscript.cpp +++ b/modules/gdscript/gdscript.cpp @@ -226,7 +226,7 @@ void GDScript::get_script_method_list(List<MethodInfo> *p_list) const { const GDScript *current = this; while (current) { - for (const Map<StringName, GDScriptFunction *>::Element *E = member_functions.front(); E; E = E->next()) { + for (const Map<StringName, GDScriptFunction *>::Element *E = current->member_functions.front(); E; E = E->next()) { GDScriptFunction *func = E->get(); MethodInfo mi; mi.name = E->key(); diff --git a/modules/gdscript/gdscript.h b/modules/gdscript/gdscript.h index 1d75d9e2fe..38009b878d 100644 --- a/modules/gdscript/gdscript.h +++ b/modules/gdscript/gdscript.h @@ -407,9 +407,10 @@ public: csi.resize(_debug_call_stack_pos); for (int i = 0; i < _debug_call_stack_pos; i++) { csi.write[_debug_call_stack_pos - i - 1].line = _call_stack[i].line ? *_call_stack[i].line : 0; - if (_call_stack[i].function) + if (_call_stack[i].function) { csi.write[_debug_call_stack_pos - i - 1].func = _call_stack[i].function->get_name(); - csi.write[_debug_call_stack_pos - i - 1].file = _call_stack[i].function->get_script()->get_path(); + csi.write[_debug_call_stack_pos - i - 1].file = _call_stack[i].function->get_script()->get_path(); + } } return csi; } diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp index 69bf114c8e..d91e32249e 100644 --- a/modules/gdscript/gdscript_editor.cpp +++ b/modules/gdscript/gdscript_editor.cpp @@ -1951,7 +1951,7 @@ static void _find_identifiers_in_base(const GDScriptCompletionContext &p_context } else { base_type.has_type = script->get_instance_base_type() != StringName(); base_type.kind = GDScriptParser::DataType::NATIVE; - base_type.script_type = script->get_instance_base_type(); + base_type.native_type = script->get_instance_base_type(); } } else { return; @@ -2178,7 +2178,6 @@ static void _find_identifiers(const GDScriptCompletionContext &p_context, bool p static void _find_call_arguments(const GDScriptCompletionContext &p_context, const GDScriptCompletionIdentifier &p_base, const StringName &p_method, int p_argidx, bool p_static, Set<String> &r_result, String &r_arghint) { Variant base = p_base.value; GDScriptParser::DataType base_type = p_base.type; - bool _static = false; const String quote_style = EDITOR_DEF("text_editor/completion/use_single_quotes", false) ? "'" : "\""; @@ -2191,12 +2190,10 @@ static void _find_call_arguments(const GDScriptCompletionContext &p_context, con return; } } - if (!_static) { - for (int i = 0; i < base_type.class_type->functions.size(); i++) { - if (base_type.class_type->functions[i]->name == p_method) { - r_arghint = _make_arguments_hint(base_type.class_type->functions[i], p_argidx); - return; - } + for (int i = 0; i < base_type.class_type->functions.size(); i++) { + if (base_type.class_type->functions[i]->name == p_method) { + r_arghint = _make_arguments_hint(base_type.class_type->functions[i], p_argidx); + return; } } diff --git a/modules/gdscript/gdscript_functions.cpp b/modules/gdscript/gdscript_functions.cpp index 7552bc6bff..5ebcddfd7c 100644 --- a/modules/gdscript/gdscript_functions.cpp +++ b/modules/gdscript/gdscript_functions.cpp @@ -72,6 +72,7 @@ const char *GDScriptFunctions::get_func_name(Function p_func) { "is_zero_approx", "ease", "decimals", + "step_decimals", "stepify", "lerp", "inverse_lerp", @@ -339,6 +340,13 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_ VALIDATE_ARG_COUNT(1); VALIDATE_ARG_NUM(0); r_ret = Math::step_decimals((double)*p_args[0]); + ERR_EXPLAIN("GDScript method 'decimals' is deprecated and has been renamed to 'step_decimals', please update your code accordingly."); + WARN_DEPRECATED + } break; + case MATH_STEP_DECIMALS: { + VALIDATE_ARG_COUNT(1); + VALIDATE_ARG_NUM(0); + r_ret = Math::step_decimals((double)*p_args[0]); } break; case MATH_STEPIFY: { VALIDATE_ARG_COUNT(2); @@ -1452,6 +1460,7 @@ bool GDScriptFunctions::is_deterministic(Function p_func) { case MATH_ISINF: case MATH_EASE: case MATH_DECIMALS: + case MATH_STEP_DECIMALS: case MATH_STEPIFY: case MATH_LERP: case MATH_INVERSE_LERP: @@ -1626,7 +1635,12 @@ MethodInfo GDScriptFunctions::get_info(Function p_func) { } break; case MATH_DECIMALS: { MethodInfo mi("decimals", PropertyInfo(Variant::REAL, "step")); - mi.return_val.type = Variant::REAL; + mi.return_val.type = Variant::INT; + return mi; + } break; + case MATH_STEP_DECIMALS: { + MethodInfo mi("step_decimals", PropertyInfo(Variant::REAL, "step")); + mi.return_val.type = Variant::INT; return mi; } break; case MATH_STEPIFY: { diff --git a/modules/gdscript/gdscript_functions.h b/modules/gdscript/gdscript_functions.h index 0dbd172acf..c594480ff8 100644 --- a/modules/gdscript/gdscript_functions.h +++ b/modules/gdscript/gdscript_functions.h @@ -63,6 +63,7 @@ public: MATH_ISZEROAPPROX, MATH_EASE, MATH_DECIMALS, + MATH_STEP_DECIMALS, MATH_STEPIFY, MATH_LERP, MATH_INVERSE_LERP, diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index 80af094c2c..903b3892d1 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -282,7 +282,6 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s switch (tokenizer->get_token()) { case GDScriptTokenizer::TK_CURSOR: { - completion_cursor = StringName(); completion_type = COMPLETION_GET_NODE; completion_class = current_class; completion_function = current_function; @@ -2870,8 +2869,6 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) { lv->assign_op = op; lv->assign = assigned; - lv->assign_op = op; - if (!_end_statement()) { _set_error("Expected end of statement (var)"); return; @@ -4785,19 +4782,30 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { return; } - if (member._export.type != Variant::NIL) { + Variant::Type initial_type = member.data_type.has_type ? member.data_type.builtin_type : member._export.type; + + if (initial_type != Variant::NIL && initial_type != Variant::OBJECT) { IdentifierNode *id = alloc_node<IdentifierNode>(); id->name = member.identifier; - ConstantNode *cn = alloc_node<ConstantNode>(); + Node *expr; - Variant::CallError ce2; - cn->value = Variant::construct(member._export.type, NULL, 0, ce2); + // Make sure arrays and dictionaries are not shared + if (initial_type == Variant::ARRAY) { + expr = alloc_node<ArrayNode>(); + } else if (initial_type == Variant::DICTIONARY) { + expr = alloc_node<DictionaryNode>(); + } else { + ConstantNode *cn = alloc_node<ConstantNode>(); + Variant::CallError ce2; + cn->value = Variant::construct(initial_type, NULL, 0, ce2); + expr = cn; + } OperatorNode *op = alloc_node<OperatorNode>(); op->op = OperatorNode::OP_INIT_ASSIGN; op->arguments.push_back(id); - op->arguments.push_back(cn); + op->arguments.push_back(expr); p_class->initializer->statements.push_back(op); @@ -6226,8 +6234,8 @@ GDScriptParser::DataType GDScriptParser::_reduce_node_type(Node *p_node) { return DataType(); } #ifdef DEBUG_ENABLED - if (var_op == Variant::OP_DIVIDE && argument_a_type.has_type && argument_a_type.kind == DataType::BUILTIN && argument_a_type.builtin_type == Variant::INT && - argument_b_type.has_type && argument_b_type.kind == DataType::BUILTIN && argument_b_type.builtin_type == Variant::INT) { + if (var_op == Variant::OP_DIVIDE && argument_a_type.kind == DataType::BUILTIN && argument_a_type.builtin_type == Variant::INT && + argument_b_type.kind == DataType::BUILTIN && argument_b_type.builtin_type == Variant::INT) { _add_warning(GDScriptWarning::INTEGER_DIVISION, op->line); } #endif // DEBUG_ENABLED @@ -6938,10 +6946,8 @@ GDScriptParser::DataType GDScriptParser::_reduce_function_call_type(const Operat #ifdef DEBUG_ENABLED if (current_function && !for_completion && !is_static && p_call->arguments[0]->type == Node::TYPE_SELF && current_function->_static) { - if (current_function && current_function->_static && p_call->arguments[0]->type == Node::TYPE_SELF) { - _set_error("Can't call non-static function from a static function.", p_call->line); - return DataType(); - } + _set_error("Can't call non-static function from a static function.", p_call->line); + return DataType(); } if (check_types && !is_static && !is_initializer && base_type.is_meta_type) { @@ -7496,30 +7502,6 @@ void GDScriptParser::_check_class_level_types(ClassNode *p_class) { v.data_type = expr_type; v.data_type.is_constant = false; } - } else if (v.data_type.has_type && v.data_type.kind == DataType::BUILTIN) { - // Create default value based on the type - IdentifierNode *id = alloc_node<IdentifierNode>(); - id->line = v.line; - id->name = v.identifier; - - ConstantNode *init = alloc_node<ConstantNode>(); - init->line = v.line; - Variant::CallError err; - init->value = Variant::construct(v.data_type.builtin_type, NULL, 0, err); - - OperatorNode *op = alloc_node<OperatorNode>(); - op->line = v.line; - op->op = OperatorNode::OP_INIT_ASSIGN; - op->arguments.push_back(id); - op->arguments.push_back(init); - - p_class->initializer->statements.push_front(op); - v.initial_assignment = op; -#ifdef DEBUG_ENABLED - NewLineNode *nl = alloc_node<NewLineNode>(); - nl->line = v.line - 1; - p_class->initializer->statements.push_front(nl); -#endif } // Check export hint diff --git a/modules/gridmap/grid_map_editor_plugin.cpp b/modules/gridmap/grid_map_editor_plugin.cpp index 17eb6f674c..657aa1f9ce 100644 --- a/modules/gridmap/grid_map_editor_plugin.cpp +++ b/modules/gridmap/grid_map_editor_plugin.cpp @@ -67,9 +67,6 @@ void GridMapEditor::_menu_option(int p_option) { floor->set_value(floor->get_value() + 1); } break; - case MENU_OPTION_CONFIGURE: { - - } break; case MENU_OPTION_LOCK_VIEW: { int index = options->get_popup()->get_item_index(MENU_OPTION_LOCK_VIEW); @@ -121,14 +118,15 @@ void GridMapEditor::_menu_option(int p_option) { case MENU_OPTION_CURSOR_ROTATE_Y: { Basis r; - if (input_action == INPUT_DUPLICATE) { + if (input_action == INPUT_PASTE) { - r.set_orthogonal_index(selection.duplicate_rot); + r.set_orthogonal_index(paste_indicator.orientation); r.rotate(Vector3(0, 1, 0), -Math_PI / 2.0); - selection.duplicate_rot = r.get_orthogonal_index(); - _update_duplicate_indicator(); + paste_indicator.orientation = r.get_orthogonal_index(); + _update_paste_indicator(); break; } + r.set_orthogonal_index(cursor_rot); r.rotate(Vector3(0, 1, 0), -Math_PI / 2.0); cursor_rot = r.get_orthogonal_index(); @@ -137,12 +135,12 @@ void GridMapEditor::_menu_option(int p_option) { case MENU_OPTION_CURSOR_ROTATE_X: { Basis r; - if (input_action == INPUT_DUPLICATE) { + if (input_action == INPUT_PASTE) { - r.set_orthogonal_index(selection.duplicate_rot); + r.set_orthogonal_index(paste_indicator.orientation); r.rotate(Vector3(1, 0, 0), -Math_PI / 2.0); - selection.duplicate_rot = r.get_orthogonal_index(); - _update_duplicate_indicator(); + paste_indicator.orientation = r.get_orthogonal_index(); + _update_paste_indicator(); break; } @@ -154,12 +152,12 @@ void GridMapEditor::_menu_option(int p_option) { case MENU_OPTION_CURSOR_ROTATE_Z: { Basis r; - if (input_action == INPUT_DUPLICATE) { + if (input_action == INPUT_PASTE) { - r.set_orthogonal_index(selection.duplicate_rot); + r.set_orthogonal_index(paste_indicator.orientation); r.rotate(Vector3(0, 0, 1), -Math_PI / 2.0); - selection.duplicate_rot = r.get_orthogonal_index(); - _update_duplicate_indicator(); + paste_indicator.orientation = r.get_orthogonal_index(); + _update_paste_indicator(); break; } @@ -171,6 +169,15 @@ void GridMapEditor::_menu_option(int p_option) { case MENU_OPTION_CURSOR_BACK_ROTATE_Y: { Basis r; + if (input_action == INPUT_PASTE) { + + r.set_orthogonal_index(paste_indicator.orientation); + r.rotate(Vector3(0, 1, 0), Math_PI / 2.0); + paste_indicator.orientation = r.get_orthogonal_index(); + _update_paste_indicator(); + break; + } + r.set_orthogonal_index(cursor_rot); r.rotate(Vector3(0, 1, 0), Math_PI / 2.0); cursor_rot = r.get_orthogonal_index(); @@ -179,6 +186,15 @@ void GridMapEditor::_menu_option(int p_option) { case MENU_OPTION_CURSOR_BACK_ROTATE_X: { Basis r; + if (input_action == INPUT_PASTE) { + + r.set_orthogonal_index(paste_indicator.orientation); + r.rotate(Vector3(1, 0, 0), Math_PI / 2.0); + paste_indicator.orientation = r.get_orthogonal_index(); + _update_paste_indicator(); + break; + } + r.set_orthogonal_index(cursor_rot); r.rotate(Vector3(1, 0, 0), Math_PI / 2.0); cursor_rot = r.get_orthogonal_index(); @@ -187,6 +203,15 @@ void GridMapEditor::_menu_option(int p_option) { case MENU_OPTION_CURSOR_BACK_ROTATE_Z: { Basis r; + if (input_action == INPUT_PASTE) { + + r.set_orthogonal_index(paste_indicator.orientation); + r.rotate(Vector3(0, 0, 1), Math_PI / 2.0); + paste_indicator.orientation = r.get_orthogonal_index(); + _update_paste_indicator(); + break; + } + r.set_orthogonal_index(cursor_rot); r.rotate(Vector3(0, 0, 1), Math_PI / 2.0); cursor_rot = r.get_orthogonal_index(); @@ -194,10 +219,10 @@ void GridMapEditor::_menu_option(int p_option) { } break; case MENU_OPTION_CURSOR_CLEAR_ROTATION: { - if (input_action == INPUT_DUPLICATE) { + if (input_action == INPUT_PASTE) { - selection.duplicate_rot = 0; - _update_duplicate_indicator(); + paste_indicator.orientation = 0; + _update_paste_indicator(); break; } @@ -205,28 +230,33 @@ void GridMapEditor::_menu_option(int p_option) { _update_cursor_transform(); } break; - case MENU_OPTION_DUPLICATE_SELECTS: { - int idx = options->get_popup()->get_item_index(MENU_OPTION_DUPLICATE_SELECTS); + case MENU_OPTION_PASTE_SELECTS: { + int idx = options->get_popup()->get_item_index(MENU_OPTION_PASTE_SELECTS); options->get_popup()->set_item_checked(idx, !options->get_popup()->is_item_checked(idx)); } break; - case MENU_OPTION_SELECTION_DUPLICATE: + + case MENU_OPTION_SELECTION_DUPLICATE: // fallthrough + case MENU_OPTION_SELECTION_CUT: { if (!(selection.active && input_action == INPUT_NONE)) - return; - if (last_mouseover == Vector3(-1, -1, -1)) //nono mouseovering anythin break; - last_mouseover = selection.begin; - VS::get_singleton()->instance_set_transform(grid_instance[edit_axis], Transform(Basis(), grid_ofs)); + _set_clipboard_data(); - input_action = INPUT_DUPLICATE; - selection.click = last_mouseover; - selection.current = last_mouseover; - selection.duplicate_rot = 0; - _update_duplicate_indicator(); - break; + if (p_option == MENU_OPTION_SELECTION_CUT) { + _delete_selection(); + } + + input_action = INPUT_PASTE; + paste_indicator.click = selection.begin; + paste_indicator.current = selection.begin; + paste_indicator.begin = selection.begin; + paste_indicator.end = selection.end; + paste_indicator.orientation = 0; + _update_paste_indicator(); + } break; case MENU_OPTION_SELECTION_CLEAR: { if (!selection.active) - return; + break; _delete_selection(); @@ -315,17 +345,28 @@ void GridMapEditor::_validate_selection() { _update_selection_transform(); } +void GridMapEditor::_set_selection(bool p_active, const Vector3 p_begin, const Vector3 p_end) { + + selection.active = p_active; + selection.begin = p_begin; + selection.end = p_end; + selection.click = p_begin; + selection.current = p_end; + + _update_selection_transform(); +} + bool GridMapEditor::do_input_action(Camera *p_camera, const Point2 &p_point, bool p_click) { if (!spatial_editor) return false; - if (selected_palette < 0 && input_action != INPUT_COPY && input_action != INPUT_SELECT && input_action != INPUT_DUPLICATE) + if (selected_palette < 0 && input_action != INPUT_PICK && input_action != INPUT_SELECT && input_action != INPUT_PASTE) return false; Ref<MeshLibrary> mesh_library = node->get_mesh_library(); if (mesh_library.is_null()) return false; - if (input_action != INPUT_COPY && input_action != INPUT_SELECT && input_action != INPUT_DUPLICATE && !mesh_library->has_item(selected_palette)) + if (input_action != INPUT_PICK && input_action != INPUT_SELECT && input_action != INPUT_PASTE && !mesh_library->has_item(selected_palette)) return false; Camera *camera = p_camera; @@ -386,13 +427,17 @@ bool GridMapEditor::do_input_action(Camera *p_camera, const Point2 &p_point, boo cursor_origin = (Vector3(cell[0], cell[1], cell[2]) + Vector3(0.5 * node->get_center_x(), 0.5 * node->get_center_y(), 0.5 * node->get_center_z())) * node->get_cell_size(); cursor_visible = true; + if (input_action == INPUT_SELECT || input_action == INPUT_PASTE) { + cursor_visible = false; + } + _update_cursor_transform(); } - if (input_action == INPUT_DUPLICATE) { + if (input_action == INPUT_PASTE) { - selection.current = Vector3(cell[0], cell[1], cell[2]); - _update_duplicate_indicator(); + paste_indicator.current = Vector3(cell[0], cell[1], cell[2]); + _update_paste_indicator(); } else if (input_action == INPUT_SELECT) { @@ -403,7 +448,7 @@ bool GridMapEditor::do_input_action(Camera *p_camera, const Point2 &p_point, boo _validate_selection(); return true; - } else if (input_action == INPUT_COPY) { + } else if (input_action == INPUT_PICK) { int item = node->get_cell_item(cell[0], cell[1], cell[2]); if (item >= 0) { @@ -456,10 +501,9 @@ void GridMapEditor::_delete_selection() { } } } + undo_redo->add_do_method(this, "_set_selection", !selection.active, selection.begin, selection.end); + undo_redo->add_undo_method(this, "_set_selection", selection.active, selection.begin, selection.end); undo_redo->commit_action(); - - selection.active = false; - _validate_selection(); } void GridMapEditor::_fill_selection() { @@ -479,97 +523,124 @@ void GridMapEditor::_fill_selection() { } } } + undo_redo->add_do_method(this, "_set_selection", !selection.active, selection.begin, selection.end); + undo_redo->add_undo_method(this, "_set_selection", selection.active, selection.begin, selection.end); undo_redo->commit_action(); +} - selection.active = false; - _validate_selection(); +void GridMapEditor::_clear_clipboard_data() { + + for (List<ClipboardItem>::Element *E = clipboard_items.front(); E; E = E->next()) { + + VisualServer::get_singleton()->free(E->get().instance); + } + + clipboard_items.clear(); } -void GridMapEditor::_update_duplicate_indicator() { +void GridMapEditor::_set_clipboard_data() { - if (!selection.active || input_action != INPUT_DUPLICATE) { + _clear_clipboard_data(); + + Ref<MeshLibrary> meshLibrary = node->get_mesh_library(); + + for (int i = selection.begin.x; i <= selection.end.x; i++) { + + for (int j = selection.begin.y; j <= selection.end.y; j++) { + + for (int k = selection.begin.z; k <= selection.end.z; k++) { + + int itm = node->get_cell_item(i, j, k); + if (itm == GridMap::INVALID_CELL_ITEM) + continue; + + Ref<Mesh> mesh = meshLibrary->get_item_mesh(itm); + + ClipboardItem item; + item.cell_item = itm; + item.grid_offset = Vector3(i, j, k) - selection.begin; + item.orientation = node->get_cell_item_orientation(i, j, k); + item.instance = VisualServer::get_singleton()->instance_create2(mesh->get_rid(), get_tree()->get_root()->get_world()->get_scenario()); + + clipboard_items.push_back(item); + } + } + } +} + +void GridMapEditor::_update_paste_indicator() { + + if (input_action != INPUT_PASTE) { Transform xf; xf.basis.set_zero(); - VisualServer::get_singleton()->instance_set_transform(duplicate_instance, xf); + VisualServer::get_singleton()->instance_set_transform(paste_instance, xf); return; } + Vector3 center = 0.5 * Vector3(node->get_center_x(), node->get_center_y(), node->get_center_z()); + Vector3 scale = (Vector3(1, 1, 1) + (paste_indicator.end - paste_indicator.begin)) * node->get_cell_size(); Transform xf; - xf.scale(Vector3(1, 1, 1) * (Vector3(1, 1, 1) + (selection.end - selection.begin)) * node->get_cell_size()); - xf.origin = (selection.begin + (selection.current - selection.click)) * node->get_cell_size(); + xf.scale(scale); + xf.origin = (paste_indicator.begin + (paste_indicator.current - paste_indicator.click) + center) * node->get_cell_size(); Basis rot; - rot.set_orthogonal_index(selection.duplicate_rot); + rot.set_orthogonal_index(paste_indicator.orientation); xf.basis = rot * xf.basis; + xf.translate((-center * node->get_cell_size()) / scale); - VisualServer::get_singleton()->instance_set_transform(duplicate_instance, node->get_global_transform() * xf); -} + VisualServer::get_singleton()->instance_set_transform(paste_instance, node->get_global_transform() * xf); -struct __Item { - Vector3 pos; - int rot; - int item; -}; -void GridMapEditor::_duplicate_paste() { + for (List<ClipboardItem>::Element *E = clipboard_items.front(); E; E = E->next()) { - if (!selection.active) - return; + ClipboardItem &item = E->get(); - int idx = options->get_popup()->get_item_index(MENU_OPTION_DUPLICATE_SELECTS); - bool reselect = options->get_popup()->is_item_checked(idx); + xf = Transform(); + xf.origin = (paste_indicator.begin + (paste_indicator.current - paste_indicator.click) + center) * node->get_cell_size(); + xf.basis = rot * xf.basis; + xf.translate(item.grid_offset * node->get_cell_size()); + + Basis item_rot; + item_rot.set_orthogonal_index(item.orientation); + xf.basis = item_rot * xf.basis; + + VisualServer::get_singleton()->instance_set_transform(item.instance, node->get_global_transform() * xf); + } +} - List<__Item> items; +void GridMapEditor::_do_paste() { + + int idx = options->get_popup()->get_item_index(MENU_OPTION_PASTE_SELECTS); + bool reselect = options->get_popup()->is_item_checked(idx); Basis rot; - rot.set_orthogonal_index(selection.duplicate_rot); + rot.set_orthogonal_index(paste_indicator.orientation); - for (int i = selection.begin.x; i <= selection.end.x; i++) { + Vector3 ofs = paste_indicator.current - paste_indicator.click; + undo_redo->create_action(TTR("GridMap Paste Selection")); - for (int j = selection.begin.y; j <= selection.end.y; j++) { + for (List<ClipboardItem>::Element *E = clipboard_items.front(); E; E = E->next()) { - for (int k = selection.begin.z; k <= selection.end.z; k++) { + ClipboardItem &item = E->get(); - int itm = node->get_cell_item(i, j, k); - if (itm == GridMap::INVALID_CELL_ITEM) - continue; - int orientation = node->get_cell_item_orientation(i, j, k); - __Item item; - Vector3 rel = Vector3(i, j, k) - selection.begin; - rel = rot.xform(rel); - - Basis orm; - orm.set_orthogonal_index(orientation); - orm = rot * orm; - - item.pos = selection.begin + rel; - item.item = itm; - item.rot = orm.get_orthogonal_index(); - items.push_back(item); - } - } - } + Vector3 pos = rot.xform(item.grid_offset) + paste_indicator.begin + ofs; - Vector3 ofs = selection.current - selection.click; - if (items.size()) { - undo_redo->create_action(TTR("GridMap Duplicate Selection")); - for (List<__Item>::Element *E = items.front(); E; E = E->next()) { - __Item &it = E->get(); - Vector3 pos = it.pos + ofs; + Basis orm; + orm.set_orthogonal_index(item.orientation); + orm = rot * orm; - undo_redo->add_do_method(node, "set_cell_item", pos.x, pos.y, pos.z, it.item, it.rot); - undo_redo->add_undo_method(node, "set_cell_item", pos.x, pos.y, pos.z, node->get_cell_item(pos.x, pos.y, pos.z), node->get_cell_item_orientation(pos.x, pos.y, pos.z)); - } - undo_redo->commit_action(); + undo_redo->add_do_method(node, "set_cell_item", pos.x, pos.y, pos.z, item.cell_item, orm.get_orthogonal_index()); + undo_redo->add_undo_method(node, "set_cell_item", pos.x, pos.y, pos.z, node->get_cell_item(pos.x, pos.y, pos.z), node->get_cell_item_orientation(pos.x, pos.y, pos.z)); } if (reselect) { - selection.begin += ofs; - selection.end += ofs; - selection.click = selection.begin; - selection.current = selection.end; - _validate_selection(); + undo_redo->add_do_method(this, "_set_selection", true, paste_indicator.begin + ofs, paste_indicator.end + ofs); + undo_redo->add_undo_method(this, "_set_selection", selection.active, selection.begin, selection.end); } + + undo_redo->commit_action(); + + _clear_clipboard_data(); } bool GridMapEditor::forward_spatial_input_event(Camera *p_camera, const Ref<InputEvent> &p_event) { @@ -596,28 +667,31 @@ bool GridMapEditor::forward_spatial_input_event(Camera *p_camera, const Ref<Inpu if (mb->get_button_index() == BUTTON_LEFT) { - if (input_action == INPUT_DUPLICATE) { - //paste - _duplicate_paste(); + if (input_action == INPUT_PASTE) { + _do_paste(); input_action = INPUT_NONE; - _update_duplicate_indicator(); + _update_paste_indicator(); } else if (mb->get_shift()) { input_action = INPUT_SELECT; + last_selection = selection; } else if (mb->get_command()) { - input_action = INPUT_COPY; + input_action = INPUT_PICK; } else { input_action = INPUT_PAINT; set_items.clear(); } } else if (mb->get_button_index() == BUTTON_RIGHT) { - if (input_action == INPUT_DUPLICATE) { + if (input_action == INPUT_PASTE) { + _clear_clipboard_data(); input_action = INPUT_NONE; - _update_duplicate_indicator(); - } else if (mb->get_shift()) { + _update_paste_indicator(); + return true; + } else if (selection.active) { + _set_selection(false); + return true; + } else { input_action = INPUT_ERASE; set_items.clear(); - } else { - return false; } } else { return false; @@ -650,13 +724,21 @@ bool GridMapEditor::forward_spatial_input_event(Camera *p_camera, const Ref<Inpu return set_items.size() > 0; } + if (mb->get_button_index() == BUTTON_LEFT && input_action == INPUT_SELECT) { + + undo_redo->create_action("GridMap Selection"); + undo_redo->add_do_method(this, "_set_selection", selection.active, selection.begin, selection.end); + undo_redo->add_undo_method(this, "_set_selection", last_selection.active, last_selection.begin, last_selection.end); + undo_redo->commit_action(); + } + if (mb->get_button_index() == BUTTON_LEFT && input_action != INPUT_NONE) { set_items.clear(); input_action = INPUT_NONE; return true; } - if (mb->get_button_index() == BUTTON_RIGHT && (input_action == INPUT_ERASE || input_action == INPUT_DUPLICATE)) { + if (mb->get_button_index() == BUTTON_RIGHT && (input_action == INPUT_ERASE || input_action == INPUT_PASTE)) { input_action = INPUT_NONE; return true; } @@ -670,6 +752,45 @@ bool GridMapEditor::forward_spatial_input_event(Camera *p_camera, const Ref<Inpu return do_input_action(p_camera, mm->get_position(), false); } + Ref<InputEventKey> k = p_event; + + if (k.is_valid()) { + if (k->is_pressed()) { + if (k->get_scancode() == KEY_ESCAPE) { + + if (input_action == INPUT_PASTE) { + _clear_clipboard_data(); + input_action = INPUT_NONE; + _update_paste_indicator(); + return true; + } else if (selection.active) { + _set_selection(false); + return true; + } else { + selected_palette = -1; + mesh_library_palette->unselect_all(); + update_palette(); + _update_cursor_instance(); + return true; + } + } + + if (k->get_shift() && selection.active && input_action != INPUT_PASTE) { + + if (k->get_scancode() == options->get_popup()->get_item_accelerator(options->get_popup()->get_item_index(MENU_OPTION_PREV_LEVEL))) { + selection.click[edit_axis]--; + _validate_selection(); + return true; + } + if (k->get_scancode() == options->get_popup()->get_item_accelerator(options->get_popup()->get_item_index(MENU_OPTION_NEXT_LEVEL))) { + selection.click[edit_axis]++; + _validate_selection(); + return true; + } + } + } + } + Ref<InputEventPanGesture> pan_gesture = p_event; if (pan_gesture.is_valid()) { @@ -818,7 +939,7 @@ void GridMapEditor::edit(GridMap *p_gridmap) { input_action = INPUT_NONE; selection.active = false; _update_selection_transform(); - _update_duplicate_indicator(); + _update_paste_indicator(); spatial_editor = Object::cast_to<SpatialEditorPlugin>(editor->get_editor_plugin_screen()); @@ -953,13 +1074,15 @@ void GridMapEditor::_notification(int p_what) { } selection_instance = VisualServer::get_singleton()->instance_create2(selection_mesh, get_tree()->get_root()->get_world()->get_scenario()); - duplicate_instance = VisualServer::get_singleton()->instance_create2(duplicate_mesh, get_tree()->get_root()->get_world()->get_scenario()); + paste_instance = VisualServer::get_singleton()->instance_create2(paste_mesh, get_tree()->get_root()->get_world()->get_scenario()); _update_selection_transform(); - _update_duplicate_indicator(); + _update_paste_indicator(); } break; case NOTIFICATION_EXIT_TREE: { + _clear_clipboard_data(); + for (int i = 0; i < 3; i++) { VS::get_singleton()->free(grid_instance[i]); @@ -970,9 +1093,9 @@ void GridMapEditor::_notification(int p_what) { } VisualServer::get_singleton()->free(selection_instance); - VisualServer::get_singleton()->free(duplicate_instance); + VisualServer::get_singleton()->free(paste_instance); selection_instance = RID(); - duplicate_instance = RID(); + paste_instance = RID(); } break; case NOTIFICATION_PROCESS: { @@ -1065,6 +1188,7 @@ void GridMapEditor::_bind_methods() { ClassDB::bind_method("_configure", &GridMapEditor::_configure); ClassDB::bind_method("_item_selected_cbk", &GridMapEditor::_item_selected_cbk); ClassDB::bind_method("_floor_changed", &GridMapEditor::_floor_changed); + ClassDB::bind_method("_set_selection", &GridMapEditor::_set_selection); ClassDB::bind_method(D_METHOD("_set_display_mode", "mode"), &GridMapEditor::_set_display_mode); } @@ -1128,15 +1252,12 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) { options->get_popup()->add_item(TTR("Cursor Back Rotate Z"), MENU_OPTION_CURSOR_BACK_ROTATE_Z, KEY_MASK_SHIFT + KEY_D); options->get_popup()->add_item(TTR("Cursor Clear Rotation"), MENU_OPTION_CURSOR_CLEAR_ROTATION, KEY_W); options->get_popup()->add_separator(); - options->get_popup()->add_check_item("Duplicate Selects", MENU_OPTION_DUPLICATE_SELECTS); - options->get_popup()->add_separator(); - options->get_popup()->add_item(TTR("Create Area"), MENU_OPTION_SELECTION_MAKE_AREA, KEY_CONTROL + KEY_C); - options->get_popup()->add_item(TTR("Create Exterior Connector"), MENU_OPTION_SELECTION_MAKE_EXTERIOR_CONNECTOR); - options->get_popup()->add_item(TTR("Erase Area"), MENU_OPTION_REMOVE_AREA); + options->get_popup()->add_check_item("Paste Selects", MENU_OPTION_PASTE_SELECTS); options->get_popup()->add_separator(); - options->get_popup()->add_item(TTR("Duplicate Selection"), MENU_OPTION_SELECTION_DUPLICATE, KEY_MASK_SHIFT + KEY_C); - options->get_popup()->add_item(TTR("Clear Selection"), MENU_OPTION_SELECTION_CLEAR, KEY_MASK_SHIFT + KEY_X); - options->get_popup()->add_item(TTR("Fill Selection"), MENU_OPTION_SELECTION_FILL, KEY_MASK_SHIFT + KEY_F); + options->get_popup()->add_item(TTR("Duplicate Selection"), MENU_OPTION_SELECTION_DUPLICATE, KEY_MASK_CTRL + KEY_C); + options->get_popup()->add_item(TTR("Cut Selection"), MENU_OPTION_SELECTION_CUT, KEY_MASK_CTRL + KEY_X); + options->get_popup()->add_item(TTR("Clear Selection"), MENU_OPTION_SELECTION_CLEAR, KEY_DELETE); + options->get_popup()->add_item(TTR("Fill Selection"), MENU_OPTION_SELECTION_FILL, KEY_MASK_CTRL + KEY_F); options->get_popup()->add_separator(); options->get_popup()->add_item(TTR("Settings"), MENU_OPTION_GRIDMAP_SETTINGS); @@ -1211,7 +1332,7 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) { last_mouseover = Vector3(-1, -1, -1); selection_mesh = VisualServer::get_singleton()->mesh_create(); - duplicate_mesh = VisualServer::get_singleton()->mesh_create(); + paste_mesh = VisualServer::get_singleton()->mesh_create(); { //selection mesh create @@ -1319,12 +1440,12 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) { VisualServer::get_singleton()->mesh_surface_set_material(selection_mesh, 1, outer_mat->get_rid()); d[VS::ARRAY_VERTEX] = triangles; - VisualServer::get_singleton()->mesh_add_surface_from_arrays(duplicate_mesh, VS::PRIMITIVE_TRIANGLES, d); - VisualServer::get_singleton()->mesh_surface_set_material(duplicate_mesh, 0, inner_mat->get_rid()); + VisualServer::get_singleton()->mesh_add_surface_from_arrays(paste_mesh, VS::PRIMITIVE_TRIANGLES, d); + VisualServer::get_singleton()->mesh_surface_set_material(paste_mesh, 0, inner_mat->get_rid()); d[VS::ARRAY_VERTEX] = lines; - VisualServer::get_singleton()->mesh_add_surface_from_arrays(duplicate_mesh, VS::PRIMITIVE_LINES, d); - VisualServer::get_singleton()->mesh_surface_set_material(duplicate_mesh, 1, outer_mat->get_rid()); + VisualServer::get_singleton()->mesh_add_surface_from_arrays(paste_mesh, VS::PRIMITIVE_LINES, d); + VisualServer::get_singleton()->mesh_surface_set_material(paste_mesh, 1, outer_mat->get_rid()); for (int i = 0; i < 3; i++) { d[VS::ARRAY_VERTEX] = square[i]; @@ -1341,6 +1462,8 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) { GridMapEditor::~GridMapEditor() { + _clear_clipboard_data(); + for (int i = 0; i < 3; i++) { if (grid[i].is_valid()) @@ -1359,9 +1482,9 @@ GridMapEditor::~GridMapEditor() { if (selection_instance.is_valid()) VisualServer::get_singleton()->free(selection_instance); - VisualServer::get_singleton()->free(duplicate_mesh); - if (duplicate_instance.is_valid()) - VisualServer::get_singleton()->free(duplicate_instance); + VisualServer::get_singleton()->free(paste_mesh); + if (paste_instance.is_valid()) + VisualServer::get_singleton()->free(paste_instance); } void GridMapEditorPlugin::_notification(int p_what) { diff --git a/modules/gridmap/grid_map_editor_plugin.h b/modules/gridmap/grid_map_editor_plugin.h index 59b8ac13da..8e1948ea7d 100644 --- a/modules/gridmap/grid_map_editor_plugin.h +++ b/modules/gridmap/grid_map_editor_plugin.h @@ -54,9 +54,9 @@ class GridMapEditor : public VBoxContainer { INPUT_NONE, INPUT_PAINT, INPUT_ERASE, - INPUT_COPY, + INPUT_PICK, INPUT_SELECT, - INPUT_DUPLICATE, + INPUT_PASTE, }; enum ClipMode { @@ -116,8 +116,17 @@ class GridMapEditor : public VBoxContainer { RID selection_instance; RID selection_level_mesh[3]; RID selection_level_instance[3]; - RID duplicate_mesh; - RID duplicate_instance; + RID paste_mesh; + RID paste_instance; + + struct ClipboardItem { + int cell_item; + Vector3 grid_offset; + int orientation; + RID instance; + }; + + List<ClipboardItem> clipboard_items; Ref<SpatialMaterial> indicator_mat; Ref<SpatialMaterial> inner_mat; @@ -132,9 +141,19 @@ class GridMapEditor : public VBoxContainer { Vector3 current; Vector3 begin; Vector3 end; - int duplicate_rot; bool active; } selection; + Selection last_selection; + + struct PasteIndicator { + + Vector3 click; + Vector3 current; + Vector3 begin; + Vector3 end; + int orientation; + }; + PasteIndicator paste_indicator; bool cursor_visible; Transform cursor_transform; @@ -148,7 +167,6 @@ class GridMapEditor : public VBoxContainer { enum Menu { - MENU_OPTION_CONFIGURE, MENU_OPTION_NEXT_LEVEL, MENU_OPTION_PREV_LEVEL, MENU_OPTION_LOCK_VIEW, @@ -165,13 +183,11 @@ class GridMapEditor : public VBoxContainer { MENU_OPTION_CURSOR_BACK_ROTATE_X, MENU_OPTION_CURSOR_BACK_ROTATE_Z, MENU_OPTION_CURSOR_CLEAR_ROTATION, - MENU_OPTION_DUPLICATE_SELECTS, - MENU_OPTION_SELECTION_MAKE_AREA, - MENU_OPTION_SELECTION_MAKE_EXTERIOR_CONNECTOR, + MENU_OPTION_PASTE_SELECTS, MENU_OPTION_SELECTION_DUPLICATE, + MENU_OPTION_SELECTION_CUT, MENU_OPTION_SELECTION_CLEAR, MENU_OPTION_SELECTION_FILL, - MENU_OPTION_REMOVE_AREA, MENU_OPTION_GRIDMAP_SETTINGS }; @@ -200,10 +216,13 @@ class GridMapEditor : public VBoxContainer { void _icon_size_changed(float p_value); - void _update_duplicate_indicator(); - void _duplicate_paste(); + void _clear_clipboard_data(); + void _set_clipboard_data(); + void _update_paste_indicator(); + void _do_paste(); void _update_selection_transform(); void _validate_selection(); + void _set_selection(bool p_active, const Vector3 p_begin = Vector3(), const Vector3 p_end = Vector3()); void _floor_changed(float p_value); diff --git a/modules/mono/glue/Managed/Files/Mathf.cs b/modules/mono/glue/Managed/Files/Mathf.cs index 947fbb6665..ff26c7fddf 100644 --- a/modules/mono/glue/Managed/Files/Mathf.cs +++ b/modules/mono/glue/Managed/Files/Mathf.cs @@ -79,14 +79,27 @@ namespace Godot return (real_t)Math.Cosh(s); } - public static int Decimals(real_t step) - { - return Decimals((decimal)step); - } - - public static int Decimals(decimal step) - { - return BitConverter.GetBytes(decimal.GetBits(step)[3])[2]; + public static int StepDecimals(real_t step) + { + double[] sd = new double[] { + 0.9999, + 0.09999, + 0.009999, + 0.0009999, + 0.00009999, + 0.000009999, + 0.0000009999, + 0.00000009999, + 0.000000009999, + }; + double abs = Mathf.Abs(step); + double decs = abs - (int)abs; // Strip away integer part + for (int i = 0; i < sd.Length; i++) { + if (decs >= sd[i]) { + return i; + } + } + return 0; } public static real_t Deg2Rad(real_t deg) diff --git a/modules/mono/glue/Managed/Files/MathfEx.cs b/modules/mono/glue/Managed/Files/MathfEx.cs index d6eb65b097..b96f01bc2e 100644 --- a/modules/mono/glue/Managed/Files/MathfEx.cs +++ b/modules/mono/glue/Managed/Files/MathfEx.cs @@ -21,6 +21,16 @@ namespace Godot public const real_t Epsilon = 1e-06f; #endif + public static int DecimalCount(real_t s) + { + return DecimalCount((decimal)s); + } + + public static int DecimalCount(decimal s) + { + return BitConverter.GetBytes(decimal.GetBits(s)[3])[2]; + } + public static int CeilToInt(real_t s) { return (int)Math.Ceiling(s); diff --git a/modules/mono/utils/string_utils.cpp b/modules/mono/utils/string_utils.cpp index 0ef66577fe..877122985d 100644 --- a/modules/mono/utils/string_utils.cpp +++ b/modules/mono/utils/string_utils.cpp @@ -33,6 +33,7 @@ #include "core/os/file_access.h" #include <stdio.h> +#include <stdlib.h> namespace { @@ -65,7 +66,7 @@ int sfind(const String &p_text, int p_from) { break; case 1: { CharType c = src[read_pos]; - found = src[read_pos] == 's' || (c >= '0' || c <= '4'); + found = src[read_pos] == 's' || (c >= '0' && c <= '4'); break; } default: @@ -209,8 +210,8 @@ String str_format(const char *p_format, ...) { #endif #endif -#if defined(MINGW_ENABLED) || defined(_MSC_VER) -#define vsnprintf vsnprintf_s +#if defined(MINGW_ENABLED) || defined(_MSC_VER) && _MSC_VER < 1900 +#define vsnprintf(m_buffer, m_count, m_format, m_argptr) vsnprintf_s(m_buffer, m_count, _TRUNCATE, m_format, m_argptr) #endif String str_format(const char *p_format, va_list p_list) { diff --git a/modules/pvr/texture_loader_pvr.cpp b/modules/pvr/texture_loader_pvr.cpp index 82f323e8cf..8f6ffcc83f 100644 --- a/modules/pvr/texture_loader_pvr.cpp +++ b/modules/pvr/texture_loader_pvr.cpp @@ -192,9 +192,9 @@ static void _compress_pvrtc4(Image *p_img) { Ref<Image> img = p_img->duplicate(); bool make_mipmaps = false; - if (img->get_width() % 8 || img->get_height() % 8) { + if (!img->is_size_po2() || img->get_width() != img->get_height()) { make_mipmaps = img->has_mipmaps(); - img->resize(img->get_width() + (8 - (img->get_width() % 8)), img->get_height() + (8 - (img->get_height() % 8))); + img->resize_to_po2(true); } img->convert(Image::FORMAT_RGBA8); if (!img->has_mipmaps() && make_mipmaps) @@ -204,7 +204,7 @@ static void _compress_pvrtc4(Image *p_img) { Ref<Image> new_img; new_img.instance(); - new_img->create(img->get_width(), img->get_height(), true, use_alpha ? Image::FORMAT_PVRTC4A : Image::FORMAT_PVRTC4); + new_img->create(img->get_width(), img->get_height(), img->has_mipmaps(), use_alpha ? Image::FORMAT_PVRTC4A : Image::FORMAT_PVRTC4); PoolVector<uint8_t> data = new_img->get_data(); { @@ -221,7 +221,6 @@ static void _compress_pvrtc4(Image *p_img) { /* red and Green colors are swapped. */ new (dp) Javelin::ColorRgba<unsigned char>(r[ofs + 4 * j + 2], r[ofs + 4 * j + 1], r[ofs + 4 * j], r[ofs + 4 * j + 3]); } - new_img->get_mipmap_offset_size_and_dimensions(i, ofs, size, w, h); Javelin::PvrTcEncoder::EncodeRgba4Bpp(&wr[ofs], bm); } diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp index 28c9a11cb8..4f6828bf1c 100644 --- a/modules/visual_script/visual_script_editor.cpp +++ b/modules/visual_script/visual_script_editor.cpp @@ -1330,9 +1330,9 @@ void VisualScriptEditor::_input(const Ref<InputEvent> &p_event) { } } -void VisualScriptEditor::_generic_search() { +void VisualScriptEditor::_generic_search(String p_base_type) { port_action_pos = graph->get_viewport()->get_mouse_position() - graph->get_global_position(); - new_connect_node_select->select_from_visual_script(String(""), false); + new_connect_node_select->select_from_visual_script(p_base_type, false); } void VisualScriptEditor::_members_gui_input(const Ref<InputEvent> &p_event) { @@ -1787,7 +1787,6 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da call->set_base_path(sn->get_path_to(node)); call->set_base_type(node->get_class()); n = call; - method_select->select_from_instance(node); selecting_method_id = base_id; } @@ -3156,7 +3155,7 @@ void VisualScriptEditor::_menu_option(int p_what) { } break; case EDIT_FIND_NODE_TYPE: { - _generic_search(); + _generic_search(script->get_instance_base_type()); } break; case EDIT_COPY_NODES: case EDIT_CUT_NODES: { diff --git a/modules/visual_script/visual_script_editor.h b/modules/visual_script/visual_script_editor.h index 9387a09c78..3d3a49f672 100644 --- a/modules/visual_script/visual_script_editor.h +++ b/modules/visual_script/visual_script_editor.h @@ -212,7 +212,7 @@ class VisualScriptEditor : public ScriptEditorBase { void _input(const Ref<InputEvent> &p_event); - void _generic_search(); + void _generic_search(String p_base_type = ""); void _members_gui_input(const Ref<InputEvent> &p_event); void _on_nodes_delete(); diff --git a/modules/visual_script/visual_script_property_selector.cpp b/modules/visual_script/visual_script_property_selector.cpp index ac5f73d113..ceec79c0d5 100644 --- a/modules/visual_script/visual_script_property_selector.cpp +++ b/modules/visual_script/visual_script_property_selector.cpp @@ -87,38 +87,17 @@ void VisualScriptPropertySelector::_update_search() { TreeItem *root = search_options->create_item(); bool found = false; + StringName base = base_type; + List<StringName> base_list; + while (base) { + base_list.push_back(base); + base = ClassDB::get_parent_class_nocheck(base); + } - if (properties) { - + for (List<StringName>::Element *E = base_list.front(); E; E = E->next()) { + List<MethodInfo> methods; List<PropertyInfo> props; - - if (instance) { - instance->get_property_list(&props, true); - } else if (type != Variant::NIL) { - Variant v; - Variant::CallError ce; - v = Variant::construct(type, NULL, 0, ce); - - v.get_property_list(&props); - } else { - - Object *obj = ObjectDB::get_instance(script); - if (Object::cast_to<Script>(obj)) { - - props.push_back(PropertyInfo(Variant::NIL, "Script Variables", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_CATEGORY)); - Object::cast_to<Script>(obj)->get_script_property_list(&props); - } - - StringName base = base_type; - while (base) { - props.push_back(PropertyInfo(Variant::NIL, base, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_CATEGORY)); - ClassDB::get_property_list(base, &props, true); - base = ClassDB::get_parent_class_nocheck(base); - } - } - TreeItem *category = NULL; - Ref<Texture> type_icons[Variant::VARIANT_MAX] = { Control::get_icon("Variant", "EditorIcons"), Control::get_icon("bool", "EditorIcons"), @@ -148,85 +127,164 @@ void VisualScriptPropertySelector::_update_search() { Control::get_icon("PoolVector3Array", "EditorIcons"), Control::get_icon("PoolColorArray", "EditorIcons") }; - - if (!seq_connect && !visual_script_generic) { - get_visual_node_names("flow_control/type_cast", Set<String>(), found, root, search_box); - get_visual_node_names("functions/built_in/print", Set<String>(), found, root, search_box); - get_visual_node_names("functions/by_type/" + Variant::get_type_name(type), Set<String>(), found, root, search_box); - get_visual_node_names("operators/compare/", Set<String>(), found, root, search_box); - if (type == Variant::INT) { - get_visual_node_names("operators/bitwise/", Set<String>(), found, root, search_box); - } - if (type == Variant::BOOL) { - get_visual_node_names("operators/logic/", Set<String>(), found, root, search_box); + { + String b = String(E->get()); + category = search_options->create_item(root); + category->set_text(0, b.replace_first("*", "")); + category->set_selectable(0, false); + Ref<Texture> icon; + String rep = b.replace("*", ""); + icon = EditorNode::get_singleton()->get_class_icon(rep); + category->set_icon(0, icon); + } + if (properties || seq_connect) { + if (instance) { + instance->get_property_list(&props, true); + } else { + Object *obj = ObjectDB::get_instance(script); + if (Object::cast_to<Script>(obj)) { + Object::cast_to<Script>(obj)->get_script_property_list(&props); + } else { + ClassDB::get_property_list(E->get(), &props, true); + } } - if (type == Variant::BOOL || type == Variant::INT || type == Variant::REAL || type == Variant::VECTOR2 || type == Variant::VECTOR3) { - get_visual_node_names("operators/math/", Set<String>(), found, root, search_box); + for (List<PropertyInfo>::Element *F = props.front(); F; F = F->next()) { + if (!(F->get().usage & PROPERTY_USAGE_EDITOR) && !(F->get().usage & PROPERTY_USAGE_SCRIPT_VARIABLE)) + continue; + + if (type_filter.size() && type_filter.find(F->get().type) == -1) + continue; + + // capitalize() also converts underscore to space, we'll match again both possible styles + String get_text_raw = String(vformat(TTR("Get %s"), F->get().name)); + String get_text = get_text_raw.capitalize(); + String set_text_raw = String(vformat(TTR("Set %s"), F->get().name)); + String set_text = set_text_raw.capitalize(); + String input = search_box->get_text().capitalize(); + + if (input == String() || get_text_raw.findn(input) != -1 || get_text.findn(input) != -1) { + TreeItem *item = search_options->create_item(category ? category : root); + item->set_text(0, get_text); + item->set_metadata(0, F->get().name); + item->set_icon(0, type_icons[F->get().type]); + item->set_metadata(1, "get"); + item->set_collapsed(1); + item->set_selectable(0, true); + item->set_selectable(1, false); + item->set_selectable(2, false); + item->set_metadata(2, connecting); + } + + if (input == String() || set_text_raw.findn(input) != -1 || set_text.findn(input) != -1) { + TreeItem *item = search_options->create_item(category ? category : root); + item->set_text(0, set_text); + item->set_metadata(0, F->get().name); + item->set_icon(0, type_icons[F->get().type]); + item->set_metadata(1, "set"); + item->set_selectable(0, true); + item->set_selectable(1, false); + item->set_selectable(2, false); + item->set_metadata(2, connecting); + } } } + bool script_methods = false; + { + if (type != Variant::NIL) { + Variant v; + Variant::CallError ce; + v = Variant::construct(type, NULL, 0, ce); + v.get_method_list(&methods); + } else { - for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) { - if (E->get().usage == PROPERTY_USAGE_CATEGORY) { - if (category && category->get_children() == NULL) { - memdelete(category); //old category was unused - } - category = search_options->create_item(root); - category->set_text(0, E->get().name); - category->set_selectable(0, false); + Object *obj = ObjectDB::get_instance(script); + if (Object::cast_to<Script>(obj)) { + methods.push_back(MethodInfo("*Script Methods")); + Object::cast_to<Script>(obj)->get_script_method_list(&methods); - Ref<Texture> icon; - if (E->get().name == "Script Variables") { - icon = get_icon("Script", "EditorIcons"); } else { - icon = EditorNode::get_singleton()->get_class_icon(E->get().name); + methods.push_back(MethodInfo("*" + String(E->get()))); + ClassDB::get_method_list(E->get(), &methods, true, true); } - category->set_icon(0, icon); - continue; } + } + for (List<MethodInfo>::Element *M = methods.front(); M; M = M->next()) { + + String name = M->get().name.get_slice(":", 0); + if (!script_methods && name.begins_with("_") && !(M->get().flags & METHOD_FLAG_VIRTUAL)) + continue; - if (!(E->get().usage & PROPERTY_USAGE_EDITOR) && !(E->get().usage & PROPERTY_USAGE_SCRIPT_VARIABLE)) + if (virtuals_only && !(M->get().flags & METHOD_FLAG_VIRTUAL)) continue; - if (type_filter.size() && type_filter.find(E->get().type) == -1) + if (!virtuals_only && (M->get().flags & METHOD_FLAG_VIRTUAL)) continue; - // capitalize() also converts underscore to space, we'll match again both possible styles - String get_text_raw = String(vformat(TTR("Get %s"), E->get().name)); - String get_text = get_text_raw.capitalize(); - String set_text_raw = String(vformat(TTR("Set %s"), E->get().name)); - String set_text = set_text_raw.capitalize(); - String input = search_box->get_text().capitalize(); - - if (input == String() || get_text_raw.findn(input) != -1 || get_text.findn(input) != -1) { - TreeItem *item = search_options->create_item(category ? category : root); - item->set_text(0, get_text); - item->set_metadata(0, E->get().name); - item->set_icon(0, type_icons[E->get().type]); - item->set_metadata(1, "get"); - item->set_collapsed(1); - item->set_selectable(0, true); - item->set_selectable(1, false); - item->set_selectable(2, false); - item->set_metadata(2, connecting); + MethodInfo mi = M->get(); + String desc_arguments; + if (mi.arguments.size() > 0) { + desc_arguments = "("; + for (int i = 0; i < mi.arguments.size(); i++) { + + if (i > 0) { + desc_arguments += ", "; + } + if (mi.arguments[i].type == Variant::NIL) { + desc_arguments += "var"; + } else if (mi.arguments[i].name.find(":") != -1) { + desc_arguments += mi.arguments[i].name.get_slice(":", 1); + mi.arguments[i].name = mi.arguments[i].name.get_slice(":", 0); + } else { + desc_arguments += Variant::get_type_name(mi.arguments[i].type); + } + } + desc_arguments += ")"; } + String desc_raw = mi.name + desc_arguments; + String desc = desc_raw.capitalize().replace("( ", "("); - if (input == String() || set_text_raw.findn(input) != -1 || set_text.findn(input) != -1) { - TreeItem *item = search_options->create_item(category ? category : root); - item->set_text(0, set_text); - item->set_metadata(0, E->get().name); - item->set_icon(0, type_icons[E->get().type]); - item->set_metadata(1, "set"); - item->set_selectable(0, true); - item->set_selectable(1, false); - item->set_selectable(2, false); - item->set_metadata(2, connecting); + if (search_box->get_text() != String() && + name.findn(search_box->get_text()) == -1 && + desc.findn(search_box->get_text()) == -1 && + desc_raw.findn(search_box->get_text()) == -1) { + continue; } + + TreeItem *item = search_options->create_item(category ? category : root); + item->set_text(0, desc); + item->set_icon(0, get_icon("MemberMethod", "EditorIcons")); + item->set_metadata(0, name); + item->set_selectable(0, true); + + item->set_metadata(1, "method"); + item->set_collapsed(1); + item->set_selectable(1, false); + + item->set_selectable(2, false); + item->set_metadata(2, connecting); } if (category && category->get_children() == NULL) { memdelete(category); //old category was unused } } + if (properties) { + if (!seq_connect && !visual_script_generic) { + get_visual_node_names("flow_control/type_cast", Set<String>(), found, root, search_box); + get_visual_node_names("functions/built_in/print", Set<String>(), found, root, search_box); + get_visual_node_names("functions/by_type/" + Variant::get_type_name(type), Set<String>(), found, root, search_box); + get_visual_node_names("operators/compare/", Set<String>(), found, root, search_box); + if (type == Variant::INT) { + get_visual_node_names("operators/bitwise/", Set<String>(), found, root, search_box); + } + if (type == Variant::BOOL) { + get_visual_node_names("operators/logic/", Set<String>(), found, root, search_box); + } + if (type == Variant::BOOL || type == Variant::INT || type == Variant::REAL || type == Variant::VECTOR2 || type == Variant::VECTOR3) { + get_visual_node_names("operators/math/", Set<String>(), found, root, search_box); + } + } + } if (seq_connect && !visual_script_generic) { String text = search_box->get_text(); @@ -240,127 +298,16 @@ void VisualScriptPropertySelector::_update_search() { get_visual_node_names("functions/built_in/print", Set<String>(), found, root, search_box); } - if (visual_script_generic) { + if ((properties || seq_connect) && visual_script_generic) { get_visual_node_names("", Set<String>(), found, root, search_box); } - List<MethodInfo> methods; - - if (type != Variant::NIL) { - Variant v; - Variant::CallError ce; - v = Variant::construct(type, NULL, 0, ce); - v.get_method_list(&methods); - } else { - - Object *obj = ObjectDB::get_instance(script); - if (Object::cast_to<Script>(obj)) { - - methods.push_back(MethodInfo("*Script Methods")); - Object::cast_to<Script>(obj)->get_script_method_list(&methods); - } - - StringName base = base_type; - while (base) { - methods.push_back(MethodInfo("*" + String(base))); - ClassDB::get_method_list(base, &methods, true, true); - base = ClassDB::get_parent_class_nocheck(base); - } - } - TreeItem *category = NULL; - bool script_methods = false; - - for (List<MethodInfo>::Element *E = methods.front(); E; E = E->next()) { - if (E->get().name.begins_with("*")) { - if (category && category->get_children() == NULL) { - memdelete(category); //old category was unused - } - category = search_options->create_item(root); - category->set_text(0, E->get().name.replace_first("*", "")); - category->set_selectable(0, false); - - Ref<Texture> icon; - script_methods = false; - String rep = E->get().name.replace("*", ""); - if (E->get().name == "*Script Methods") { - icon = get_icon("Script", "EditorIcons"); - script_methods = true; - } else { - icon = EditorNode::get_singleton()->get_class_icon(rep); - } - category->set_icon(0, icon); - - continue; - } - - String name = E->get().name.get_slice(":", 0); - if (!script_methods && name.begins_with("_") && !(E->get().flags & METHOD_FLAG_VIRTUAL)) - continue; - - if (virtuals_only && !(E->get().flags & METHOD_FLAG_VIRTUAL)) - continue; - - if (!virtuals_only && (E->get().flags & METHOD_FLAG_VIRTUAL)) - continue; - - MethodInfo mi = E->get(); - String desc_arguments; - if (mi.arguments.size() > 0) { - desc_arguments = "("; - for (int i = 0; i < mi.arguments.size(); i++) { - - if (i > 0) { - desc_arguments += ", "; - } - if (mi.arguments[i].type == Variant::NIL) { - desc_arguments += "var"; - } else if (mi.arguments[i].name.find(":") != -1) { - desc_arguments += mi.arguments[i].name.get_slice(":", 1); - mi.arguments[i].name = mi.arguments[i].name.get_slice(":", 0); - } else { - desc_arguments += Variant::get_type_name(mi.arguments[i].type); - } - } - desc_arguments += ")"; - } - String desc_raw = mi.name + desc_arguments; - String desc = desc_raw.capitalize().replace("( ", "("); - - if (search_box->get_text() != String() && - name.findn(search_box->get_text()) == -1 && - desc.findn(search_box->get_text()) == -1 && - desc_raw.findn(search_box->get_text()) == -1) { - continue; - } - - TreeItem *item = search_options->create_item(category ? category : root); - item->set_text(0, desc); - item->set_icon(0, get_icon("MemberMethod", "EditorIcons")); - item->set_metadata(0, name); - item->set_selectable(0, true); - - item->set_metadata(1, "method"); - item->set_collapsed(1); - item->set_selectable(1, false); - - item->set_selectable(2, false); - item->set_metadata(2, connecting); - - if (category && category->get_children() == NULL) { - memdelete(category); //old category was unused - } - } - TreeItem *selected_item = search_options->search_item_text(search_box->get_text()); if (!found && selected_item != NULL) { selected_item->select(0); found = true; } - if (category && category->get_children() == NULL) { - memdelete(category); //old category was unused - } - get_ok()->set_disabled(root->get_children() == NULL); } @@ -488,23 +435,23 @@ void VisualScriptPropertySelector::_item_selected() { while (at_class != String()) { - Map<String, DocData::ClassDoc>::Element *E = dd->class_list.find(at_class); - if (E) { - for (int i = 0; i < E->get().methods.size(); i++) { - if (E->get().methods[i].name == name) { - text = E->get().methods[i].description; + Map<String, DocData::ClassDoc>::Element *C = dd->class_list.find(at_class); + if (C) { + for (int i = 0; i < C->get().methods.size(); i++) { + if (C->get().methods[i].name == name) { + text = C->get().methods[i].description; } } } at_class = ClassDB::get_parent_class_nocheck(at_class); } - Map<String, DocData::ClassDoc>::Element *E = dd->class_list.find(class_type); - if (E) { - for (int i = 0; i < E->get().methods.size(); i++) { + Map<String, DocData::ClassDoc>::Element *T = dd->class_list.find(class_type); + if (T) { + for (int i = 0; i < T->get().methods.size(); i++) { Vector<String> functions = name.rsplit("/", false, 1); - if (E->get().methods[i].name == functions[functions.size() - 1]) { - text = E->get().methods[i].description; + if (T->get().methods[i].name == functions[functions.size() - 1]) { + text = T->get().methods[i].description; } } } diff --git a/modules/websocket/SCsub b/modules/websocket/SCsub index 2d2de81220..d9e60eb6f1 100644 --- a/modules/websocket/SCsub +++ b/modules/websocket/SCsub @@ -9,90 +9,85 @@ env_lws = env_modules.Clone() if env['builtin_libwebsockets'] and not env["platform"] == "javascript": # already builtin for javascript thirdparty_dir = "#thirdparty/libwebsockets/" - helper_dir = "#thirdparty/libwebsockets/win32helpers/" + helper_dir = "win32helpers/" thirdparty_sources = [ - "lib/core/adopt.c", - "lib/core/alloc.c", - "lib/core/connect.c", - "lib/core/context.c", - "lib/core/dummy-callback.c", - "lib/core/libwebsockets.c", - "lib/core/output.c", - "lib/core/pollfd.c", - "lib/core/service.c", - - "lib/event-libs/poll/poll.c", - - "lib/misc/base64-decode.c", - "lib/misc/lejp.c", - "lib/misc/sha-1.c", - - "lib/roles/h1/ops-h1.c", - "lib/roles/http/header.c", - "lib/roles/http/client/client.c", - "lib/roles/http/client/client-handshake.c", - "lib/roles/http/server/fops-zip.c", - "lib/roles/http/server/lejp-conf.c", - "lib/roles/http/server/parsers.c", - "lib/roles/http/server/server.c", - "lib/roles/listen/ops-listen.c", - "lib/roles/pipe/ops-pipe.c", - "lib/roles/raw-skt/ops-raw-skt.c", - "lib/roles/raw-file/ops-raw-file.c", - - "lib/roles/ws/client-ws.c", - "lib/roles/ws/client-parser-ws.c", - "lib/roles/ws/ops-ws.c", - "lib/roles/ws/server-ws.c", - - "lib/tls/tls.c", - "lib/tls/tls-client.c", - "lib/tls/tls-server.c", - - "lib/tls/mbedtls/wrapper/library/ssl_cert.c", - "lib/tls/mbedtls/wrapper/library/ssl_pkey.c", - "lib/tls/mbedtls/wrapper/library/ssl_stack.c", - "lib/tls/mbedtls/wrapper/library/ssl_methods.c", - "lib/tls/mbedtls/wrapper/library/ssl_lib.c", - "lib/tls/mbedtls/wrapper/library/ssl_x509.c", - "lib/tls/mbedtls/wrapper/platform/ssl_port.c", - "lib/tls/mbedtls/wrapper/platform/ssl_pm.c", - "lib/tls/mbedtls/lws-genhash.c", - "lib/tls/mbedtls/mbedtls-client.c", - "lib/tls/mbedtls/lws-genrsa.c", - "lib/tls/mbedtls/ssl.c", - "lib/tls/mbedtls/mbedtls-server.c" + "core/alloc.c", + "core/context.c", + "core/libwebsockets.c", + "core/output.c", + "core/pollfd.c", + "core/service.c", + + "event-libs/poll/poll.c", + + "misc/base64-decode.c", + "misc/lejp.c", + "misc/sha-1.c", + + "roles/h1/ops-h1.c", + "roles/http/header.c", + "roles/http/client/client.c", + "roles/http/client/client-handshake.c", + "roles/http/server/fops-zip.c", + "roles/http/server/lejp-conf.c", + "roles/http/server/parsers.c", + "roles/http/server/server.c", + "roles/listen/ops-listen.c", + "roles/pipe/ops-pipe.c", + "roles/raw/ops-raw.c", + + "roles/ws/client-ws.c", + "roles/ws/client-parser-ws.c", + "roles/ws/ops-ws.c", + "roles/ws/server-ws.c", + + "tls/tls.c", + "tls/tls-client.c", + "tls/tls-server.c", + + "tls/mbedtls/wrapper/library/ssl_cert.c", + "tls/mbedtls/wrapper/library/ssl_pkey.c", + "tls/mbedtls/wrapper/library/ssl_stack.c", + "tls/mbedtls/wrapper/library/ssl_methods.c", + "tls/mbedtls/wrapper/library/ssl_lib.c", + "tls/mbedtls/wrapper/library/ssl_x509.c", + "tls/mbedtls/wrapper/platform/ssl_port.c", + "tls/mbedtls/wrapper/platform/ssl_pm.c", + "tls/mbedtls/lws-genhash.c", + "tls/mbedtls/mbedtls-client.c", + "tls/mbedtls/lws-genrsa.c", + "tls/mbedtls/ssl.c", + "tls/mbedtls/mbedtls-server.c" ] if env["platform"] == "android": # Builtin getifaddrs - thirdparty_sources += ["lib/misc/getifaddrs.c"] - - thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources] + thirdparty_sources += ["misc/getifaddrs.c"] if env["platform"] == "windows" or env["platform"] == "uwp": # Winsock - thirdparty_sources += Glob(thirdparty_dir + "lib/plat/windows/*.c") + [helper_dir + src for src in ["getopt.c", "getopt_long.c", "gettimeofday.c"]] + thirdparty_sources += ["plat/lws-plat-win.c", helper_dir + "getopt.c", helper_dir + "getopt_long.c", helper_dir + "gettimeofday.c"] else: # Unix socket - thirdparty_sources += Glob(thirdparty_dir + "lib/plat/unix/*.c") + thirdparty_sources += ["plat/lws-plat-unix.c"] + + thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources] - env_lws.Prepend(CPPPATH=[thirdparty_dir + 'include/']) + env_lws.Prepend(CPPPATH=[thirdparty_dir]) if env['builtin_mbedtls']: mbedtls_includes = "#thirdparty/mbedtls/include" env_lws.Prepend(CPPPATH=[mbedtls_includes]) - wrapper_includes = ["#thirdparty/libwebsockets/lib/tls/mbedtls/wrapper/include/" + inc for inc in ["internal", "openssl", "platform", ""]] + wrapper_includes = ["#thirdparty/libwebsockets/tls/mbedtls/wrapper/include/" + inc for inc in ["internal", "openssl", "platform", ""]] env_lws.Prepend(CPPPATH=wrapper_includes) if env["platform"] == "windows" or env["platform"] == "uwp": - env_lws.Prepend(CPPPATH=[helper_dir]) + env_lws.Prepend(CPPPATH=[thirdparty_dir + helper_dir]) if env["platform"] == "uwp": env_lws.Append(CPPFLAGS=["/DLWS_MINGW_SUPPORT"]) env_thirdparty = env_lws.Clone() env_thirdparty.disable_warnings() - env_thirdparty.Prepend(CPPPATH=[thirdparty_dir + 'lib/']) env_thirdparty.add_source_files(env.modules_sources, thirdparty_sources) env_lws.add_source_files(env.modules_sources, "*.cpp") diff --git a/modules/websocket/lws_client.cpp b/modules/websocket/lws_client.cpp index d09558ab22..08df76293b 100644 --- a/modules/websocket/lws_client.cpp +++ b/modules/websocket/lws_client.cpp @@ -32,11 +32,10 @@ #include "lws_client.h" #include "core/io/ip.h" -#include "core/io/stream_peer_ssl.h" #include "core/project_settings.h" #if defined(LWS_OPENSSL_SUPPORT) -// Not openssl, just the mbedtls wrapper -#include "openssl/ssl.h" +#include "core/io/stream_peer_ssl.h" +#include "tls/mbedtls/wrapper/include/openssl/ssl.h" #endif Error LWSClient::connect_to_host(String p_host, String p_path, uint16_t p_port, bool p_ssl, PoolVector<String> p_protocols) { |