summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/bullet/btRayShape.cpp12
-rw-r--r--modules/bullet/btRayShape.h2
-rw-r--r--modules/bullet/collision_object_bullet.cpp5
-rw-r--r--modules/bullet/godot_ray_world_algorithm.cpp7
-rw-r--r--modules/bullet/space_bullet.cpp301
-rw-r--r--modules/bullet/space_bullet.h2
-rw-r--r--modules/freetype/SCsub17
-rw-r--r--modules/gdnative/videodecoder/video_stream_gdnative.cpp34
-rw-r--r--modules/gdscript/gdscript.cpp2
-rw-r--r--modules/gdscript/gdscript.h5
-rw-r--r--modules/gdscript/gdscript_editor.cpp13
-rw-r--r--modules/gdscript/gdscript_functions.cpp16
-rw-r--r--modules/gdscript/gdscript_functions.h1
-rw-r--r--modules/gdscript/gdscript_parser.cpp58
-rw-r--r--modules/gridmap/grid_map_editor_plugin.cpp387
-rw-r--r--modules/gridmap/grid_map_editor_plugin.h43
-rw-r--r--modules/mono/glue/Managed/Files/Mathf.cs29
-rw-r--r--modules/mono/glue/Managed/Files/MathfEx.cs10
-rw-r--r--modules/mono/utils/string_utils.cpp7
-rw-r--r--modules/pvr/texture_loader_pvr.cpp7
-rw-r--r--modules/visual_script/visual_script_editor.cpp7
-rw-r--r--modules/visual_script/visual_script_editor.h2
-rw-r--r--modules/visual_script/visual_script_property_selector.cpp363
-rw-r--r--modules/websocket/SCsub117
-rw-r--r--modules/websocket/lws_client.cpp5
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) {