diff options
Diffstat (limited to 'modules')
153 files changed, 1373 insertions, 604 deletions
diff --git a/modules/bullet/btRayShape.cpp b/modules/bullet/btRayShape.cpp index 4164450cd2..8707096038 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::setSlipsOnSlope(bool p_slipsOnSlope) { + + slipsOnSlope = p_slipsOnSlope; +} + btVector3 btRayShape::localGetSupportingVertex(const btVector3 &vec) const { return localGetSupportingVertexWithoutMargin(vec) + (m_shapeAxis * m_collisionMargin); } diff --git a/modules/bullet/btRayShape.h b/modules/bullet/btRayShape.h index 99a9412dbe..a44c30db4b 100644 --- a/modules/bullet/btRayShape.h +++ b/modules/bullet/btRayShape.h @@ -44,6 +44,7 @@ ATTRIBUTE_ALIGNED16(class) btRayShape : public btConvexInternalShape { btScalar m_length; + bool slipsOnSlope; /// The default axis is the z btVector3 m_shapeAxis; @@ -59,6 +60,9 @@ public: void setLength(btScalar p_length); btScalar getLength() const { return m_length; } + void setSlipsOnSlope(bool p_slipOnSlope); + bool getSlipsOnSlope() const { return slipsOnSlope; } + const btTransform &getSupportPoint() const { return m_cacheSupportPoint; } const btScalar &getScaledLength() const { return m_cacheScaledLength; } diff --git a/modules/bullet/bullet_physics_server.cpp b/modules/bullet/bullet_physics_server.cpp index b646fc164d..6246a295ec 100644 --- a/modules/bullet/bullet_physics_server.cpp +++ b/modules/bullet/bullet_physics_server.cpp @@ -89,7 +89,9 @@ BulletPhysicsServer::BulletPhysicsServer() : active(true), active_spaces_count(0) {} -BulletPhysicsServer::~BulletPhysicsServer() {} +BulletPhysicsServer::~BulletPhysicsServer() { + bulletdelete(emptyShape); +} RID BulletPhysicsServer::shape_create(ShapeType p_shape) { ShapeBullet *shape = NULL; @@ -619,11 +621,11 @@ uint32_t BulletPhysicsServer::body_get_collision_mask(RID p_body) const { } void BulletPhysicsServer::body_set_user_flags(RID p_body, uint32_t p_flags) { - WARN_PRINT("This function si not currently supported by bullet and Godot"); + // This function si not currently supported } uint32_t BulletPhysicsServer::body_get_user_flags(RID p_body) const { - WARN_PRINT("This function si not currently supported by bullet and Godot"); + // This function si not currently supported return 0; } @@ -783,22 +785,27 @@ int BulletPhysicsServer::body_get_max_contacts_reported(RID p_body) const { return body->get_max_collisions_detection(); } -void BulletPhysicsServer::body_set_contacts_reported_depth_threshold(RID p_body, float p_treshold) { - WARN_PRINT("Not supported by bullet and even Godot"); +void BulletPhysicsServer::body_set_contacts_reported_depth_threshold(RID p_body, float p_threshold) { + // Not supported by bullet and even Godot } float BulletPhysicsServer::body_get_contacts_reported_depth_threshold(RID p_body) const { - WARN_PRINT("Not supported by bullet and even Godot"); + // Not supported by bullet and even Godot return 0.; } void BulletPhysicsServer::body_set_omit_force_integration(RID p_body, bool p_omit) { - WARN_PRINT("Not supported by bullet"); + RigidBodyBullet *body = rigid_body_owner.get(p_body); + ERR_FAIL_COND(!body); + + body->set_omit_forces_integration(p_omit); } bool BulletPhysicsServer::body_is_omitting_force_integration(RID p_body) const { - WARN_PRINT("Not supported by bullet"); - return false; + RigidBodyBullet *body = rigid_body_owner.get(p_body); + ERR_FAIL_COND_V(!body, false); + + return body->get_omit_forces_integration(); } void BulletPhysicsServer::body_set_force_integration_callback(RID p_body, Object *p_receiver, const StringName &p_method, const Variant &p_udata) { @@ -825,12 +832,12 @@ PhysicsDirectBodyState *BulletPhysicsServer::body_get_direct_state(RID p_body) { return BulletPhysicsDirectBodyState::get_singleton(body); } -bool BulletPhysicsServer::body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, MotionResult *r_result) { +bool BulletPhysicsServer::body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, MotionResult *r_result) { RigidBodyBullet *body = rigid_body_owner.get(p_body); ERR_FAIL_COND_V(!body, false); ERR_FAIL_COND_V(!body->get_space(), false); - return body->get_space()->test_body_motion(body, p_from, p_motion, r_result); + return body->get_space()->test_body_motion(body, p_from, p_motion, p_infinite_inertia, r_result); } RID BulletPhysicsServer::soft_body_create(bool p_init_sleeping) { @@ -979,11 +986,11 @@ PhysicsServer::JointType BulletPhysicsServer::joint_get_type(RID p_joint) const } void BulletPhysicsServer::joint_set_solver_priority(RID p_joint, int p_priority) { - //WARN_PRINTS("Joint priority not supported by bullet"); + // Joint priority not supported by bullet } int BulletPhysicsServer::joint_get_solver_priority(RID p_joint) const { - //WARN_PRINTS("Joint priority not supported by bullet"); + // Joint priority not supported by bullet return 0; } diff --git a/modules/bullet/bullet_physics_server.h b/modules/bullet/bullet_physics_server.h index 764ec2387c..e931915bba 100644 --- a/modules/bullet/bullet_physics_server.h +++ b/modules/bullet/bullet_physics_server.h @@ -239,7 +239,7 @@ public: virtual void body_set_max_contacts_reported(RID p_body, int p_contacts); virtual int body_get_max_contacts_reported(RID p_body) const; - virtual void body_set_contacts_reported_depth_threshold(RID p_body, float p_treshold); + virtual void body_set_contacts_reported_depth_threshold(RID p_body, float p_threshold); virtual float body_get_contacts_reported_depth_threshold(RID p_body) const; virtual void body_set_omit_force_integration(RID p_body, bool p_omit); @@ -253,7 +253,7 @@ public: // this function only works on physics process, errors and returns null otherwise virtual PhysicsDirectBodyState *body_get_direct_state(RID p_body); - virtual bool body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, MotionResult *r_result = NULL); + virtual bool body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, MotionResult *r_result = NULL); /* SOFT BODY API */ diff --git a/modules/bullet/doc_classes/BulletPhysicsDirectBodyState.xml b/modules/bullet/doc_classes/BulletPhysicsDirectBodyState.xml index c7909c7d72..a4dc61d0bc 100644 --- a/modules/bullet/doc_classes/BulletPhysicsDirectBodyState.xml +++ b/modules/bullet/doc_classes/BulletPhysicsDirectBodyState.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="BulletPhysicsDirectBodyState" inherits="PhysicsDirectBodyState" category="Core" version="3.0-stable"> +<class name="BulletPhysicsDirectBodyState" inherits="PhysicsDirectBodyState" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/bullet/doc_classes/BulletPhysicsServer.xml b/modules/bullet/doc_classes/BulletPhysicsServer.xml index a59abb0ebb..1486936cf4 100644 --- a/modules/bullet/doc_classes/BulletPhysicsServer.xml +++ b/modules/bullet/doc_classes/BulletPhysicsServer.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="BulletPhysicsServer" inherits="PhysicsServer" category="Core" version="3.0-stable"> +<class name="BulletPhysicsServer" inherits="PhysicsServer" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/bullet/godot_motion_state.h b/modules/bullet/godot_motion_state.h index fe5d8418b7..fa58e86589 100644 --- a/modules/bullet/godot_motion_state.h +++ b/modules/bullet/godot_motion_state.h @@ -87,7 +87,7 @@ public: public: /// Use this function to move kinematic body - /// -- or set initial transfom before body creation. + /// -- or set initial transform before body creation. void moveBody(const btTransform &newWorldTransform) { bodyKinematicWorldTransf = newWorldTransform; } diff --git a/modules/bullet/godot_ray_world_algorithm.cpp b/modules/bullet/godot_ray_world_algorithm.cpp index 4a511b39a7..53d0ab7e3c 100644 --- a/modules/bullet/godot_ray_world_algorithm.cpp +++ b/modules/bullet/godot_ray_world_algorithm.cpp @@ -100,14 +100,16 @@ void GodotRayWorldAlgorithm::processCollision(const btCollisionObjectWrapper *bo if (btResult.hasHit()) { - btVector3 ray_normal(ray_transform.getOrigin() - to.getOrigin()); - ray_normal.normalize(); btScalar depth(ray_shape->getScaledLength() * (btResult.m_closestHitFraction - 1)); if (depth >= -RAY_STABILITY_MARGIN) depth = 0; - resultOut->addContactPoint(ray_normal, btResult.m_hitPointWorld, depth); + if (ray_shape->getSlipsOnSlope()) + resultOut->addContactPoint(btResult.m_hitNormalWorld, btResult.m_hitPointWorld, depth); + else { + resultOut->addContactPoint((ray_transform.getOrigin() - to.getOrigin()).normalize(), btResult.m_hitPointWorld, depth); + } } } diff --git a/modules/bullet/godot_result_callbacks.cpp b/modules/bullet/godot_result_callbacks.cpp index 8d4ca6d6a7..72c982bb0b 100644 --- a/modules/bullet/godot_result_callbacks.cpp +++ b/modules/bullet/godot_result_callbacks.cpp @@ -98,11 +98,16 @@ bool GodotKinClosestConvexResultCallback::needsCollision(btBroadphaseProxy *prox if (gObj == m_self_object) { return false; } else { - if (m_ignore_areas && gObj->getType() == CollisionObjectBullet::TYPE_AREA) { + + // A kinematic body can't be stopped by a rigid body since the mass of kinematic body is infinite + if (m_infinite_inertia && !btObj->isStaticOrKinematicObject()) return false; - } else if (m_self_object->has_collision_exception(gObj)) { + + if (gObj->getType() == CollisionObjectBullet::TYPE_AREA) + return false; + + if (m_self_object->has_collision_exception(gObj)) return false; - } } return true; } else { @@ -252,18 +257,15 @@ btScalar GodotRestInfoContactResultCallback::addSingleResult(btManifoldPoint &cp void GodotDeepPenetrationContactResultCallback::addContactPoint(const btVector3 &normalOnBInWorld, const btVector3 &pointInWorldOnB, btScalar depth) { - if (depth < 0) { - // Has penetration - if (m_most_penetrated_distance > depth) { + // Has penetration + if (m_penetration_distance < ABS(depth)) { - bool isSwapped = m_manifoldPtr->getBody0() != m_body0Wrap->getCollisionObject(); + bool isSwapped = m_manifoldPtr->getBody0() != m_body0Wrap->getCollisionObject(); - m_most_penetrated_distance = depth; - m_pointCollisionObject = (isSwapped ? m_body0Wrap : m_body1Wrap)->getCollisionObject(); - m_other_compound_shape_index = isSwapped ? m_index1 : m_index0; - m_pointNormalWorld = isSwapped ? normalOnBInWorld * -1 : normalOnBInWorld; - m_pointWorld = isSwapped ? (pointInWorldOnB + normalOnBInWorld * depth) : pointInWorldOnB; - m_penetration_distance = depth; - } + m_penetration_distance = depth; + m_pointCollisionObject = (isSwapped ? m_body0Wrap : m_body1Wrap)->getCollisionObject(); + m_other_compound_shape_index = isSwapped ? m_index1 : m_index0; + m_pointNormalWorld = isSwapped ? normalOnBInWorld * -1 : normalOnBInWorld; + m_pointWorld = isSwapped ? (pointInWorldOnB + normalOnBInWorld * depth) : pointInWorldOnB; } } diff --git a/modules/bullet/godot_result_callbacks.h b/modules/bullet/godot_result_callbacks.h index e1b0b1b421..60493d4788 100644 --- a/modules/bullet/godot_result_callbacks.h +++ b/modules/bullet/godot_result_callbacks.h @@ -93,12 +93,12 @@ public: struct GodotKinClosestConvexResultCallback : public btCollisionWorld::ClosestConvexResultCallback { public: const RigidBodyBullet *m_self_object; - const bool m_ignore_areas; + const bool m_infinite_inertia; - GodotKinClosestConvexResultCallback(const btVector3 &convexFromWorld, const btVector3 &convexToWorld, const RigidBodyBullet *p_self_object, bool p_ignore_areas) : + GodotKinClosestConvexResultCallback(const btVector3 &convexFromWorld, const btVector3 &convexToWorld, const RigidBodyBullet *p_self_object, bool p_infinite_inertia) : btCollisionWorld::ClosestConvexResultCallback(convexFromWorld, convexToWorld), m_self_object(p_self_object), - m_ignore_areas(p_ignore_areas) {} + m_infinite_inertia(p_infinite_inertia) {} virtual bool needsCollision(btBroadphaseProxy *proxy0) const; }; @@ -187,18 +187,15 @@ struct GodotDeepPenetrationContactResultCallback : public btManifoldResult { int m_other_compound_shape_index; const btCollisionObject *m_pointCollisionObject; - btScalar m_most_penetrated_distance; - GodotDeepPenetrationContactResultCallback(const btCollisionObjectWrapper *body0Wrap, const btCollisionObjectWrapper *body1Wrap) : btManifoldResult(body0Wrap, body1Wrap), m_pointCollisionObject(NULL), m_penetration_distance(0), - m_other_compound_shape_index(0), - m_most_penetrated_distance(1e20) {} + m_other_compound_shape_index(0) {} void reset() { m_pointCollisionObject = NULL; - m_most_penetrated_distance = 1e20; + m_penetration_distance = 0; } bool hasHit() { diff --git a/modules/bullet/rigid_body_bullet.cpp b/modules/bullet/rigid_body_bullet.cpp index f96218ef46..2494063c22 100644 --- a/modules/bullet/rigid_body_bullet.cpp +++ b/modules/bullet/rigid_body_bullet.cpp @@ -114,10 +114,18 @@ Transform BulletPhysicsDirectBodyState::get_transform() const { return body->get_transform(); } +void BulletPhysicsDirectBodyState::add_central_force(const Vector3 &p_force) { + body->apply_central_force(p_force); +} + void BulletPhysicsDirectBodyState::add_force(const Vector3 &p_force, const Vector3 &p_pos) { body->apply_force(p_force, p_pos); } +void BulletPhysicsDirectBodyState::add_torque(const Vector3 &p_torque) { + body->apply_torque(p_torque); +} + void BulletPhysicsDirectBodyState::apply_impulse(const Vector3 &p_pos, const Vector3 &p_j) { body->apply_impulse(p_pos, p_j); } @@ -247,6 +255,7 @@ RigidBodyBullet::RigidBodyBullet() : linearDamp(0), angularDamp(0), can_sleep(true), + omit_forces_integration(false), force_integration_callback(NULL), isTransformChanged(false), previousActiveState(true), @@ -326,6 +335,9 @@ void RigidBodyBullet::dispatch_callbacks() { /// The check isTransformChanged is necessary in order to call integrated forces only when the first transform is sent if ((btBody->isActive() || previousActiveState != btBody->isActive()) && force_integration_callback && isTransformChanged) { + if (omit_forces_integration) + btBody->clearForces(); + BulletPhysicsDirectBodyState *bodyDirect = BulletPhysicsDirectBodyState::get_singleton(this); Variant variantBodyDirect = bodyDirect; @@ -429,6 +441,10 @@ bool RigidBodyBullet::is_active() const { return btBody->isActive(); } +void RigidBodyBullet::set_omit_forces_integration(bool p_omit) { + omit_forces_integration = p_omit; +} + void RigidBodyBullet::set_param(PhysicsServer::BodyParameter p_param, real_t p_value) { switch (p_param) { case PhysicsServer::BODY_PARAM_BOUNCE: diff --git a/modules/bullet/rigid_body_bullet.h b/modules/bullet/rigid_body_bullet.h index c4a9676bdd..b9511243c7 100644 --- a/modules/bullet/rigid_body_bullet.h +++ b/modules/bullet/rigid_body_bullet.h @@ -110,7 +110,9 @@ public: virtual void set_transform(const Transform &p_transform); virtual Transform get_transform() const; + virtual void add_central_force(const Vector3 &p_force); virtual void add_force(const Vector3 &p_force, const Vector3 &p_pos); + virtual void add_torque(const Vector3 &p_torque); virtual void apply_impulse(const Vector3 &p_pos, const Vector3 &p_j); virtual void apply_torque_impulse(const Vector3 &p_j); @@ -196,6 +198,7 @@ private: real_t linearDamp; real_t angularDamp; bool can_sleep; + bool omit_forces_integration; Vector<CollisionData> collisions; // these parameters are used to avoid vector resize @@ -252,6 +255,9 @@ public: void set_activation_state(bool p_active); bool is_active() const; + void set_omit_forces_integration(bool p_omit); + _FORCE_INLINE_ bool get_omit_forces_integration() const { return omit_forces_integration; } + void set_param(PhysicsServer::BodyParameter p_param, real_t); real_t get_param(PhysicsServer::BodyParameter p_param) const; diff --git a/modules/bullet/shape_bullet.cpp b/modules/bullet/shape_bullet.cpp index c6b9695d96..5d8d391bd9 100644 --- a/modules/bullet/shape_bullet.cpp +++ b/modules/bullet/shape_bullet.cpp @@ -135,8 +135,10 @@ btHeightfieldTerrainShape *ShapeBullet::create_shape_height_field(PoolVector<rea return bulletnew(btHeightfieldTerrainShape(p_width, p_depth, heightsPtr, ignoredHeightScale, -fieldHeight, fieldHeight, YAxis, PHY_FLOAT, flipQuadEdges)); } -btRayShape *ShapeBullet::create_shape_ray(real_t p_length) { - return bulletnew(btRayShape(p_length)); +btRayShape *ShapeBullet::create_shape_ray(real_t p_length, bool p_slips_on_slope) { + btRayShape *r(bulletnew(btRayShape(p_length))); + r->setSlipsOnSlope(p_slips_on_slope); + return r; } /* PLANE */ @@ -435,25 +437,33 @@ btCollisionShape *HeightMapShapeBullet::create_bt_shape(const btVector3 &p_impli /* Ray shape */ RayShapeBullet::RayShapeBullet() : ShapeBullet(), - length(1) {} + length(1), + slips_on_slope(false) {} void RayShapeBullet::set_data(const Variant &p_data) { - setup(p_data); + + Dictionary d = p_data; + setup(d["length"], d["slips_on_slope"]); } Variant RayShapeBullet::get_data() const { - return length; + + Dictionary d; + d["length"] = length; + d["slips_on_slope"] = slips_on_slope; + return d; } PhysicsServer::ShapeType RayShapeBullet::get_type() const { return PhysicsServer::SHAPE_RAY; } -void RayShapeBullet::setup(real_t p_length) { +void RayShapeBullet::setup(real_t p_length, bool p_slips_on_slope) { length = p_length; + slips_on_slope = p_slips_on_slope; notifyShapeChanged(); } btCollisionShape *RayShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin) { - return prepare(ShapeBullet::create_shape_ray(length * p_implicit_scale[1] + p_margin)); + return prepare(ShapeBullet::create_shape_ray(length * p_implicit_scale[1] + p_margin, slips_on_slope)); } diff --git a/modules/bullet/shape_bullet.h b/modules/bullet/shape_bullet.h index e04a3c808a..2acba90e36 100644 --- a/modules/bullet/shape_bullet.h +++ b/modules/bullet/shape_bullet.h @@ -86,7 +86,7 @@ public: static class btConvexPointCloudShape *create_shape_convex(btAlignedObjectArray<btVector3> &p_vertices, const btVector3 &p_local_scaling = btVector3(1, 1, 1)); static class btScaledBvhTriangleMeshShape *create_shape_concave(btBvhTriangleMeshShape *p_mesh_shape, const btVector3 &p_local_scaling = btVector3(1, 1, 1)); static class btHeightfieldTerrainShape *create_shape_height_field(PoolVector<real_t> &p_heights, int p_width, int p_depth, real_t p_cell_size); - static class btRayShape *create_shape_ray(real_t p_length); + static class btRayShape *create_shape_ray(real_t p_length, bool p_slips_on_slope); }; class PlaneShapeBullet : public ShapeBullet { @@ -216,6 +216,7 @@ class RayShapeBullet : public ShapeBullet { public: real_t length; + bool slips_on_slope; RayShapeBullet(); @@ -225,6 +226,6 @@ public: virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin = 0); private: - void setup(real_t p_length); + void setup(real_t p_length, bool p_slips_on_slope); }; #endif diff --git a/modules/bullet/space_bullet.cpp b/modules/bullet/space_bullet.cpp index 88d9c20eba..8c15758e0f 100644 --- a/modules/bullet/space_bullet.cpp +++ b/modules/bullet/space_bullet.cpp @@ -628,7 +628,7 @@ void SpaceBullet::destroy_world() { void SpaceBullet::check_ghost_overlaps() { - /// Algorith support variables + /// Algorithm support variables btConvexShape *other_body_shape; btConvexShape *area_shape; btGjkPairDetector::ClosestPointInput gjk_input; @@ -790,7 +790,7 @@ void SpaceBullet::update_gravity() { /// I'm leaving this here just for future tests. /// Debug motion and normal vector drawing #define debug_test_motion 0 -#define PERFORM_INITIAL_UNSTACK 0 + #define RECOVERING_MOVEMENT_SCALE 0.4 #define RECOVERING_MOVEMENT_CYCLES 4 @@ -804,8 +804,7 @@ static Ref<SpatialMaterial> red_mat; static Ref<SpatialMaterial> blue_mat; #endif -#define IGNORE_AREAS_TRUE true -bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform &p_from, const Vector3 &p_motion, PhysicsServer::MotionResult *r_result) { +bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, PhysicsServer::MotionResult *r_result) { #if debug_test_motion /// Yes I know this is not good, but I've used it as fast debugging hack. @@ -839,25 +838,14 @@ bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform &p_f } #endif - ///// Release all generated manifolds - //{ - // if(p_body->get_kinematic_utilities()){ - // for(int i= p_body->get_kinematic_utilities()->m_generatedManifold.size()-1; 0<=i; --i){ - // dispatcher->releaseManifold( p_body->get_kinematic_utilities()->m_generatedManifold[i] ); - // } - // p_body->get_kinematic_utilities()->m_generatedManifold.clear(); - // } - //} - btTransform body_safe_position; G_TO_B(p_from, body_safe_position); UNSCALE_BT_BASIS(body_safe_position); -#if PERFORM_INITIAL_UNSTACK btVector3 recover_initial_position(0, 0, 0); { /// Phase one - multi shapes depenetration using margin for (int t(RECOVERING_MOVEMENT_CYCLES); 0 < t; --t) { - if (!recover_from_penetration(p_body, body_safe_position, RECOVERING_MOVEMENT_SCALE, recover_initial_position)) { + if (!recover_from_penetration(p_body, body_safe_position, RECOVERING_MOVEMENT_SCALE, p_infinite_inertia, recover_initial_position)) { break; } } @@ -865,7 +853,6 @@ bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform &p_f // Add recover movement in order to make it safe body_safe_position.getOrigin() += recover_initial_position; } -#endif btVector3 motion; G_TO_B(p_motion, motion); @@ -900,11 +887,11 @@ bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform &p_f btTransform shape_world_to(shape_world_from); shape_world_to.getOrigin() += motion; - GodotKinClosestConvexResultCallback btResult(shape_world_from.getOrigin(), shape_world_to.getOrigin(), p_body, IGNORE_AREAS_TRUE); + GodotKinClosestConvexResultCallback btResult(shape_world_from.getOrigin(), shape_world_to.getOrigin(), p_body, p_infinite_inertia); btResult.m_collisionFilterGroup = p_body->get_collision_layer(); btResult.m_collisionFilterMask = p_body->get_collision_mask(); - dynamicsWorld->convexSweepTest(convex_shape_test, shape_world_from, shape_world_to, btResult, 0.002); + dynamicsWorld->convexSweepTest(convex_shape_test, shape_world_from, shape_world_to, btResult, dynamicsWorld->getDispatchInfo().m_allowedCcdPenetration); if (btResult.hasHit()) { /// Since for each sweep test I fix the motion of new shapes in base the recover result, @@ -926,14 +913,11 @@ bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform &p_f real_t l_penetration_distance = 1e20; for (int t(RECOVERING_MOVEMENT_CYCLES); 0 < t; --t) { - l_has_penetration = recover_from_penetration(p_body, body_safe_position, RECOVERING_MOVEMENT_SCALE, delta_recover_movement, &r_recover_result); + l_has_penetration = recover_from_penetration(p_body, body_safe_position, RECOVERING_MOVEMENT_SCALE, p_infinite_inertia, delta_recover_movement, &r_recover_result); if (r_result) { -#if PERFORM_INITIAL_UNSTACK B_TO_G(motion + delta_recover_movement + recover_initial_position, r_result->motion); -#else - B_TO_G(motion + delta_recover_movement, r_result->motion); -#endif + if (l_has_penetration) { has_penetration = true; if (l_penetration_distance <= r_recover_result.penetration_distance) { @@ -955,15 +939,6 @@ bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform &p_f r_result->collider_shape = r_recover_result.other_compound_shape_index; r_result->collision_local_shape = r_recover_result.local_shape_most_recovered; - //{ /// Add manifold point to manage collisions - // btPersistentManifold* manifold = dynamicsWorld->getDispatcher()->getNewManifold(p_body->getBtBody(), btRigid); - // btManifoldPoint manifoldPoint(result_callabck.m_pointWorld, result_callabck.m_pointWorld, result_callabck.m_pointNormalWorld, result_callabck.m_penetration_distance); - // manifoldPoint.m_index0 = r_result->collision_local_shape; - // manifoldPoint.m_index1 = r_result->collider_shape; - // manifold->addManifoldPoint(manifoldPoint); - // p_body->get_kinematic_utilities()->m_generatedManifold.push_back(manifold); - //} - #if debug_test_motion Vector3 sup_line2; B_TO_G(motion, sup_line2); @@ -1022,7 +997,7 @@ public: } }; -bool SpaceBullet::recover_from_penetration(RigidBodyBullet *p_body, const btTransform &p_body_position, btScalar p_recover_movement_scale, btVector3 &r_delta_recover_movement, RecoverResult *r_recover_result) { +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()); @@ -1053,7 +1028,7 @@ bool SpaceBullet::recover_from_penetration(RigidBodyBullet *p_body, const btTran for (int i = recover_broad_result.result_collision_objects.size() - 1; 0 <= i; --i) { btCollisionObject *otherObject = recover_broad_result.result_collision_objects[i]; - if (!p_body->get_bt_collision_object()->checkCollideWith(otherObject) || !otherObject->checkCollideWith(p_body->get_bt_collision_object())) + if (!p_body->get_bt_collision_object()->checkCollideWith(otherObject) || !otherObject->checkCollideWith(p_body->get_bt_collision_object()) || (p_infinite_inertia && !otherObject->isStaticOrKinematicObject())) continue; if (otherObject->getCollisionShape()->isCompound()) { @@ -1132,7 +1107,7 @@ bool SpaceBullet::RFP_convex_world_test(const btConvexShape *p_shapeA, const btC 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); - btCollisionAlgorithm *algorithm = dispatcher->findAlgorithm(&obA, &obB, NULL, BT_CLOSEST_POINT_ALGORITHMS); + btCollisionAlgorithm *algorithm = dispatcher->findAlgorithm(&obA, &obB, NULL, BT_CONTACT_POINT_ALGORITHMS); if (algorithm) { GodotDeepPenetrationContactResultCallback contactPointResult(&obA, &obB); //discrete collision detection query @@ -1142,7 +1117,7 @@ bool SpaceBullet::RFP_convex_world_test(const btConvexShape *p_shapeA, const btC dispatcher->freeCollisionAlgorithm(algorithm); if (contactPointResult.hasHit()) { - r_delta_recover_movement += contactPointResult.m_pointNormalWorld * (contactPointResult.m_penetration_distance * -1 * p_recover_movement_scale); + r_delta_recover_movement += contactPointResult.m_pointNormalWorld * (contactPointResult.m_penetration_distance * p_recover_movement_scale); if (r_recover_result) { if (contactPointResult.m_penetration_distance < r_recover_result->penetration_distance) { diff --git a/modules/bullet/space_bullet.h b/modules/bullet/space_bullet.h index 2b97f0b274..a6c2786878 100644 --- a/modules/bullet/space_bullet.h +++ b/modules/bullet/space_bullet.h @@ -172,7 +172,7 @@ public: void update_gravity(); - bool test_body_motion(RigidBodyBullet *p_body, const Transform &p_from, const Vector3 &p_motion, PhysicsServer::MotionResult *r_result); + bool test_body_motion(RigidBodyBullet *p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, PhysicsServer::MotionResult *r_result); private: void create_empty_world(bool p_create_soft_world); @@ -199,7 +199,7 @@ private: local_shape_most_recovered(0) {} }; - bool recover_from_penetration(RigidBodyBullet *p_body, const btTransform &p_body_position, btScalar p_recover_movement_scale, btVector3 &r_delta_recover_movement, RecoverResult *r_recover_result = NULL); + bool 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 = NULL); /// This is an API that recover a kinematic object from penetration /// This allow only Convex Convex test and it always use GJK algorithm, With this API we don't benefit of Bullet special accelerated functions bool RFP_convex_convex_test(const btConvexShape *p_shapeA, const btConvexShape *p_shapeB, btCollisionObject *p_objectB, 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); diff --git a/modules/enet/doc_classes/NetworkedMultiplayerENet.xml b/modules/enet/doc_classes/NetworkedMultiplayerENet.xml index 23ee327cc5..7bee63019b 100644 --- a/modules/enet/doc_classes/NetworkedMultiplayerENet.xml +++ b/modules/enet/doc_classes/NetworkedMultiplayerENet.xml @@ -1,12 +1,14 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="NetworkedMultiplayerENet" inherits="NetworkedMultiplayerPeer" category="Core" version="3.0-stable"> +<class name="NetworkedMultiplayerENet" inherits="NetworkedMultiplayerPeer" category="Core" version="3.1"> <brief_description> PacketPeer implementation using the ENet library. </brief_description> <description> - A connection (or a listening server) that should be passed to [method SceneTree.set_network_peer]. Socket events can be handled by connecting to [SceneTree] signals. + A PacketPeer implementation that should be passed to [method SceneTree.set_network_peer] after being initialized as either a client or server. Events can then be handled by connecting to [SceneTree] signals. </description> <tutorials> + http://docs.godotengine.org/en/3.0/tutorials/networking/high_level_multiplayer.html + http://enet.bespin.org/usergroup0.html </tutorials> <demos> </demos> @@ -15,6 +17,7 @@ <return type="void"> </return> <description> + Closes the connection. Ignored if no connection is currently established. If this is a server it tries to notify all clients before forcibly disconnecting them. If this is a client it simply closes the connection to the server. </description> </method> <method name="create_client"> @@ -29,7 +32,7 @@ <argument index="3" name="out_bandwidth" type="int" default="0"> </argument> <description> - Create client that connects to a server at address [code]ip[/code] using specified [code]port[/code]. + Create client that connects to a server at address [code]ip[/code] using specified [code]port[/code]. The given IP needs to be in IPv4 or IPv6 address format, for example: [code]192.168.1.1[/code]. The [code]port[/code] is the port the server is listening on. The [code]in_bandwidth[/code] and [code]out_bandwidth[/code] parameters can be used to limit the incoming and outgoing bandwidth to the given number of bytes per second. The default of 0 means unlimited bandwidth. Note that ENet will strategically drop packets on specific sides of a connection between peers to ensure the peer's bandwidth is not overwhelmed. The bandwidth parameters also determine the window size of a connection which limits the amount of reliable packets that may be in transit at any given time. Returns [code]OK[/code] if a client was created, [code]ERR_ALREADY_IN_USE[/code] if this NetworkedMultiplayerEnet instance already has an open connection (in which case you need to call [method close_connection] first) or [code]ERR_CANT_CREATE[/code] if the client could not be created. </description> </method> <method name="create_server"> @@ -44,7 +47,7 @@ <argument index="3" name="out_bandwidth" type="int" default="0"> </argument> <description> - Create server that listens to connections via [code]port[/code]. + Create server that listens to connections via [code]port[/code]. The port needs to be an available, unused port between 0 and 65535. Note that ports below 1024 are privileged and may require elevated permissions depending on the platform. To change the interface the server listens on, use [method set_bind_ip]. The default IP is the wildcard [code]*[/code], which listens on all available interfaces. [code]max_clients[/code] is the maximum number of clients that are allowed at once, any number up to 4096 may be used, although the achievable number of simultaneous clients may be far lower and depends on the application. For additional details on the bandwidth parameters, see [method create_client]. Returns [code]OK[/code] if a server was created, [code]ERR_ALREADY_IN_USE[/code] if this NetworkedMultiplayerEnet instance already has an open connection (in which case you need to call [method close_connection] first) or [code]ERR_CANT_CREATE[/code] if the server could not be created. </description> </method> <method name="set_bind_ip"> @@ -53,23 +56,30 @@ <argument index="0" name="ip" type="String"> </argument> <description> + The IP used when creating a server. This is set to the wildcard [code]*[/code] by default, which binds to all available interfaces. The given IP needs to be in IPv4 or IPv6 address format, for example: [code]192.168.1.1[/code]. </description> </method> </methods> <members> <member name="compression_mode" type="int" setter="set_compression_mode" getter="get_compression_mode" enum="NetworkedMultiplayerENet.CompressionMode"> + The compression method used for network packets. Default is no compression. These have different tradeoffs of compression speed versus bandwidth, you may need to test which one works best for your use case if you use compression at all. </member> </members> <constants> <constant name="COMPRESS_NONE" value="0" enum="CompressionMode"> + No compression. </constant> <constant name="COMPRESS_RANGE_CODER" value="1" enum="CompressionMode"> + ENet's buildin range encoding. </constant> <constant name="COMPRESS_FASTLZ" value="2" enum="CompressionMode"> + FastLZ compression. </constant> <constant name="COMPRESS_ZLIB" value="3" enum="CompressionMode"> + zlib compression. </constant> <constant name="COMPRESS_ZSTD" value="4" enum="CompressionMode"> + ZStandard compression. </constant> </constants> </class> diff --git a/modules/freetype/SCsub b/modules/freetype/SCsub index f69b632e76..8a7c2a773a 100644 --- a/modules/freetype/SCsub +++ b/modules/freetype/SCsub @@ -49,7 +49,6 @@ if env['builtin_freetype']: "src/pshinter/pshinter.c", "src/psnames/psnames.c", "src/raster/raster.c", - "src/sfnt/sfnt.c", "src/smooth/smooth.c", "src/truetype/truetype.c", "src/type1/type1.c", @@ -58,9 +57,18 @@ if env['builtin_freetype']: ] thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources] - # Include header for UWP to fix build issues - if "platform" in env and env["platform"] == "uwp": - env.Append(CCFLAGS=['/FI', '"modules/freetype/uwpdef.h"']) + sfnt = thirdparty_dir + 'src/sfnt/sfnt.c' + + if 'platform' in env: + if env['platform'] == 'uwp': + # Include header for UWP to fix build issues + env.Append(CCFLAGS=['/FI', '"modules/freetype/uwpdef.h"']) + elif env['platform'] == 'javascript': + # Forcibly undefine this macro so SIMD is not used in this file, + # since currently unsuported in WASM + sfnt = env.Object(sfnt, CPPFLAGS=['-U__OPTIMIZE__']) + + thirdparty_sources += [sfnt] env.Append(CPPPATH=[thirdparty_dir, thirdparty_dir + "/include"]) @@ -87,6 +95,6 @@ if env['builtin_freetype']: # Godot source files env.add_source_files(env.modules_sources, "*.cpp") -env.Append(CCFLAGS=['-DFREETYPE_ENABLED']) +env.Append(CCFLAGS=['-DFREETYPE_ENABLED', '-DFT_CONFIG_OPTION_USE_PNG']) Export('env') diff --git a/modules/gdnative/doc_classes/ARVRInterfaceGDNative.xml b/modules/gdnative/doc_classes/ARVRInterfaceGDNative.xml index bceb4f1f4c..be86ff0541 100644 --- a/modules/gdnative/doc_classes/ARVRInterfaceGDNative.xml +++ b/modules/gdnative/doc_classes/ARVRInterfaceGDNative.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="ARVRInterfaceGDNative" inherits="ARVRInterface" category="Core" version="3.0-stable"> +<class name="ARVRInterfaceGDNative" inherits="ARVRInterface" category="Core" version="3.1"> <brief_description> GDNative wrapper for an ARVR interface </brief_description> diff --git a/modules/gdnative/doc_classes/GDNative.xml b/modules/gdnative/doc_classes/GDNative.xml index 7e4d956604..ca0457623f 100644 --- a/modules/gdnative/doc_classes/GDNative.xml +++ b/modules/gdnative/doc_classes/GDNative.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="GDNative" inherits="Reference" category="Core" version="3.0-stable"> +<class name="GDNative" inherits="Reference" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/gdnative/doc_classes/GDNativeLibrary.xml b/modules/gdnative/doc_classes/GDNativeLibrary.xml index a6874c9ae8..308d8defc3 100644 --- a/modules/gdnative/doc_classes/GDNativeLibrary.xml +++ b/modules/gdnative/doc_classes/GDNativeLibrary.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="GDNativeLibrary" inherits="Resource" category="Core" version="3.0-stable"> +<class name="GDNativeLibrary" inherits="Resource" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/gdnative/doc_classes/NativeScript.xml b/modules/gdnative/doc_classes/NativeScript.xml index 6a71cd8d4d..1d3053244b 100644 --- a/modules/gdnative/doc_classes/NativeScript.xml +++ b/modules/gdnative/doc_classes/NativeScript.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="NativeScript" inherits="Script" category="Core" version="3.1-dev"> +<class name="NativeScript" inherits="Script" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/gdnative/doc_classes/PluginScript.xml b/modules/gdnative/doc_classes/PluginScript.xml index fbdd8f09e6..27c6adae3f 100644 --- a/modules/gdnative/doc_classes/PluginScript.xml +++ b/modules/gdnative/doc_classes/PluginScript.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="PluginScript" inherits="Script" category="Core" version="3.0-stable"> +<class name="PluginScript" inherits="Script" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/gdnative/include/pluginscript/godot_pluginscript.h b/modules/gdnative/include/pluginscript/godot_pluginscript.h index 671be3bbb9..d1671c014e 100644 --- a/modules/gdnative/include/pluginscript/godot_pluginscript.h +++ b/modules/gdnative/include/pluginscript/godot_pluginscript.h @@ -64,7 +64,7 @@ typedef struct { //this is used by script languages that keep a reference counter of their own //you can make make Ref<> not die when it reaches zero, so deleting the reference //depends entirely from the script. - // Note: You can set thoses function pointer to NULL if not needed. + // Note: You can set those function pointer to NULL if not needed. void (*refcount_incremented)(godot_pluginscript_instance_data *p_data); bool (*refcount_decremented)(godot_pluginscript_instance_data *p_data); // return true if it can die } godot_pluginscript_instance_desc; diff --git a/modules/gdnative/nativescript/nativescript.cpp b/modules/gdnative/nativescript/nativescript.cpp index f2e9bef467..5806ee3f3f 100644 --- a/modules/gdnative/nativescript/nativescript.cpp +++ b/modules/gdnative/nativescript/nativescript.cpp @@ -958,6 +958,7 @@ void NativeScriptLanguage::_unload_stuff(bool p_reload) { NativeScriptLanguage::NativeScriptLanguage() { NativeScriptLanguage::singleton = this; #ifndef NO_THREADS + has_objects_to_register = false; mutex = Mutex::create(); #endif } diff --git a/modules/gdscript/doc_classes/GDScript.xml b/modules/gdscript/doc_classes/GDScript.xml index 59cb00e3f6..40a435f459 100644 --- a/modules/gdscript/doc_classes/GDScript.xml +++ b/modules/gdscript/doc_classes/GDScript.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="GDScript" inherits="Script" category="Core" version="3.0-stable"> +<class name="GDScript" inherits="Script" category="Core" version="3.1"> <brief_description> A script implemented in the GDScript programming language. </brief_description> diff --git a/modules/gdscript/doc_classes/GDScriptFunctionState.xml b/modules/gdscript/doc_classes/GDScriptFunctionState.xml index 8510136f68..c205cedef5 100644 --- a/modules/gdscript/doc_classes/GDScriptFunctionState.xml +++ b/modules/gdscript/doc_classes/GDScriptFunctionState.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="GDScriptFunctionState" inherits="Reference" category="Core" version="3.0-stable"> +<class name="GDScriptFunctionState" inherits="Reference" category="Core" version="3.1"> <brief_description> State of a function call after yielding. </brief_description> diff --git a/modules/gdscript/doc_classes/GDScriptNativeClass.xml b/modules/gdscript/doc_classes/GDScriptNativeClass.xml index 48826ec1e0..90935b5c22 100644 --- a/modules/gdscript/doc_classes/GDScriptNativeClass.xml +++ b/modules/gdscript/doc_classes/GDScriptNativeClass.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="GDScriptNativeClass" inherits="Reference" category="Core" version="3.0-stable"> +<class name="GDScriptNativeClass" inherits="Reference" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp index 1649fb52f2..048948dada 100644 --- a/modules/gdscript/gdscript_compiler.cpp +++ b/modules/gdscript/gdscript_compiler.cpp @@ -181,7 +181,7 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: //wait, identifier could be a local variable or something else... careful here, must reference properly //as stack may be more interesting to work with - //This could be made much simpler by just indexing "self", but done this way (with custom self-addressing modes) increases peformance a lot. + //This could be made much simpler by just indexing "self", but done this way (with custom self-addressing modes) increases performance a lot. const GDScriptParser::IdentifierNode *in = static_cast<const GDScriptParser::IdentifierNode *>(p_expression); diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp index 505562324f..5f72dca866 100644 --- a/modules/gdscript/gdscript_editor.cpp +++ b/modules/gdscript/gdscript_editor.cpp @@ -60,7 +60,7 @@ Ref<Script> GDScriptLanguage::get_template(const String &p_class_name, const Str "# var a = 2\n" + "# var b = \"textvar\"\n\n" + "func _ready():\n" + - "%TS%# Called every time the node is added to the scene.\n" + + "%TS%# Called when the node is added to the scene for the first time.\n" + "%TS%# Initialization here\n" + "%TS%pass\n\n" + "#func _process(delta):\n" + @@ -410,13 +410,11 @@ String GDScriptLanguage::make_function(const String &p_class, const String &p_na String s = "func " + p_name + "("; if (p_args.size()) { - s += " "; for (int i = 0; i < p_args.size(); i++) { if (i > 0) s += ", "; s += p_args[i].get_slice(":", 0); } - s += " "; } s += "):\n" + _get_indentation() + "pass # replace with function body\n"; diff --git a/modules/gdscript/gdscript_function.cpp b/modules/gdscript/gdscript_function.cpp index a2f449909f..f83bec0c7f 100644 --- a/modules/gdscript/gdscript_function.cpp +++ b/modules/gdscript/gdscript_function.cpp @@ -1535,15 +1535,21 @@ Variant GDScriptFunctionState::_signal_callback(const Variant **p_args, int p_ar // then the function did yield again after resuming. if (ret.is_ref()) { GDScriptFunctionState *gdfs = Object::cast_to<GDScriptFunctionState>(ret); - if (gdfs && gdfs->function == function) + if (gdfs && gdfs->function == function) { completed = false; + gdfs->previous_state = Ref<GDScriptFunctionState>(this); + } } function = NULL; //cleaned up; state.result = Variant(); if (completed) { - emit_signal("completed", ret); + GDScriptFunctionState *state = this; + while (state != NULL) { + state->emit_signal("completed", ret); + state = *(state->previous_state); + } } return ret; @@ -1591,15 +1597,21 @@ Variant GDScriptFunctionState::resume(const Variant &p_arg) { // then the function did yield again after resuming. if (ret.is_ref()) { GDScriptFunctionState *gdfs = Object::cast_to<GDScriptFunctionState>(ret); - if (gdfs && gdfs->function == function) + if (gdfs && gdfs->function == function) { completed = false; + gdfs->previous_state = Ref<GDScriptFunctionState>(this); + } } function = NULL; //cleaned up; state.result = Variant(); if (completed) { - emit_signal("completed", ret); + GDScriptFunctionState *state = this; + while (state != NULL) { + state->emit_signal("completed", ret); + state = *(state->previous_state); + } } return ret; diff --git a/modules/gdscript/gdscript_function.h b/modules/gdscript/gdscript_function.h index 9310444c7a..dff4bdfaf2 100644 --- a/modules/gdscript/gdscript_function.h +++ b/modules/gdscript/gdscript_function.h @@ -234,6 +234,7 @@ class GDScriptFunctionState : public Reference { GDScriptFunction *function; GDScriptFunction::CallState state; Variant _signal_callback(const Variant **p_args, int p_argcount, Variant::CallError &r_error); + Ref<GDScriptFunctionState> previous_state; protected: static void _bind_methods(); diff --git a/modules/gdscript/gdscript_functions.cpp b/modules/gdscript/gdscript_functions.cpp index c067d5409f..278585cb01 100644 --- a/modules/gdscript/gdscript_functions.cpp +++ b/modules/gdscript/gdscript_functions.cpp @@ -358,13 +358,16 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_ r_ret = Math::dectime((double)*p_args[0], (double)*p_args[1], (double)*p_args[2]); } break; case MATH_RANDOMIZE: { + VALIDATE_ARG_COUNT(0); Math::randomize(); r_ret = Variant(); } break; case MATH_RAND: { + VALIDATE_ARG_COUNT(0); r_ret = Math::rand(); } break; case MATH_RANDF: { + VALIDATE_ARG_COUNT(0); r_ret = Math::randf(); } break; case MATH_RANDOM: { @@ -593,7 +596,13 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_ r_ret = String(result); } break; case TEXT_STR: { + if (p_arg_count < 1) { + r_error.error = Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; + r_error.argument = 1; + r_ret = Variant(); + return; + } String str; for (int i = 0; i < p_arg_count; i++) { @@ -1180,6 +1189,7 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_ } break; case PRINT_STACK: { + VALIDATE_ARG_COUNT(0); ScriptLanguage *script = GDScriptLanguage::get_singleton(); for (int i = 0; i < script->debug_get_stack_level_count(); i++) { diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index 1392323d56..435bc327dc 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -456,23 +456,26 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s if (!validating) { //this can be too slow for just validating code - if (for_completion && ScriptCodeCompletionCache::get_singleton()) { + if (for_completion && ScriptCodeCompletionCache::get_singleton() && FileAccess::exists(path)) { res = ScriptCodeCompletionCache::get_singleton()->get_cached_resource(path); - } else { // essential; see issue 15902 + } else if (!for_completion || FileAccess::exists(path)) { res = ResourceLoader::load(path); } - if (!res.is_valid()) { - _set_error("Can't preload resource at path: " + path); - return NULL; - } } else { if (!FileAccess::exists(path)) { _set_error("Can't preload resource at path: " + path); return NULL; + } else if (ScriptCodeCompletionCache::get_singleton()) { + res = ScriptCodeCompletionCache::get_singleton()->get_cached_resource(path); } } + if (!res.is_valid()) { + _set_error("Can't preload resource at path: " + path); + return NULL; + } + if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_CLOSE) { _set_error("Expected ')' after 'preload' path"); return NULL; @@ -576,18 +579,47 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s if (identifier == StringName()) { - _set_error("Built-in type constant expected after '.'"); + _set_error("Built-in type constant or static function expected after '.'"); return NULL; } if (!Variant::has_numeric_constant(bi_type, identifier)) { - _set_error("Static constant '" + identifier.operator String() + "' not present in built-in type " + Variant::get_type_name(bi_type) + "."); - return NULL; - } + if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_OPEN && + Variant::is_method_const(bi_type, identifier) && + Variant::get_method_return_type(bi_type, identifier) == bi_type) { + + tokenizer->advance(); + + OperatorNode *construct = alloc_node<OperatorNode>(); + construct->op = OperatorNode::OP_CALL; + + TypeNode *tn = alloc_node<TypeNode>(); + tn->vtype = bi_type; + construct->arguments.push_back(tn); + + OperatorNode *op = alloc_node<OperatorNode>(); + op->op = OperatorNode::OP_CALL; + op->arguments.push_back(construct); + + IdentifierNode *id = alloc_node<IdentifierNode>(); + id->name = identifier; + op->arguments.push_back(id); + + if (!_parse_arguments(op, op->arguments, p_static, true)) + return NULL; + + expr = op; + } else { + + _set_error("Static constant '" + identifier.operator String() + "' not present in built-in type " + Variant::get_type_name(bi_type) + "."); + return NULL; + } + } else { - ConstantNode *cn = alloc_node<ConstantNode>(); - cn->value = Variant::get_numeric_constant_value(bi_type, identifier); - expr = cn; + ConstantNode *cn = alloc_node<ConstantNode>(); + cn->value = Variant::get_numeric_constant_value(bi_type, identifier); + expr = cn; + } } else if (tokenizer->get_token(1) == GDScriptTokenizer::TK_PARENTHESIS_OPEN && tokenizer->is_token_literal()) { // We check with is_token_literal, as this allows us to use match/sync/etc. as a name @@ -1516,11 +1548,11 @@ GDScriptParser::Node *GDScriptParser::_reduce_expression(Node *p_node, bool p_to String errwhere; if (op->arguments[0]->type == Node::TYPE_TYPE) { TypeNode *tn = static_cast<TypeNode *>(op->arguments[0]); - errwhere = "'" + Variant::get_type_name(tn->vtype) + "'' constructor"; + errwhere = "'" + Variant::get_type_name(tn->vtype) + "' constructor"; } else { GDScriptFunctions::Function func = static_cast<BuiltInFunctionNode *>(op->arguments[0])->function; - errwhere = String("'") + GDScriptFunctions::get_func_name(func) + "'' intrinsic function"; + errwhere = String("'") + GDScriptFunctions::get_func_name(func) + "' intrinsic function"; } switch (ce.error) { @@ -4069,7 +4101,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { ConstantNode *cn = static_cast<ConstantNode *>(subexpr); if (cn->value.get_type() == Variant::NIL) { - _set_error("Can't accept a null constant expression for infering export type."); + _set_error("Can't accept a null constant expression for inferring export type."); return; } member._export.type = cn->value.get_type(); @@ -4205,7 +4237,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { } break; case GDScriptTokenizer::TK_PR_ENUM: { - //mutiple constant declarations.. + //multiple constant declarations.. int last_assign = -1; // Incremented by 1 right before the assingment. String enum_name; @@ -4356,8 +4388,6 @@ Error GDScriptParser::_parse(const String &p_base_path) { base_path = p_base_path; - clear(); - //assume class ClassNode *main_class = alloc_node<ClassNode>(); main_class->initializer = alloc_node<BlockNode>(); @@ -4382,17 +4412,7 @@ Error GDScriptParser::_parse(const String &p_base_path) { Error GDScriptParser::parse_bytecode(const Vector<uint8_t> &p_bytecode, const String &p_base_path, const String &p_self_path) { - for_completion = false; - validating = false; - completion_type = COMPLETION_NONE; - completion_node = NULL; - completion_class = NULL; - completion_function = NULL; - completion_block = NULL; - completion_found = false; - current_block = NULL; - current_class = NULL; - current_function = NULL; + clear(); self_path = p_self_path; GDScriptTokenizerBuffer *tb = memnew(GDScriptTokenizerBuffer); @@ -4406,16 +4426,7 @@ Error GDScriptParser::parse_bytecode(const Vector<uint8_t> &p_bytecode, const St Error GDScriptParser::parse(const String &p_code, const String &p_base_path, bool p_just_validate, const String &p_self_path, bool p_for_completion) { - completion_type = COMPLETION_NONE; - completion_node = NULL; - completion_class = NULL; - completion_function = NULL; - completion_block = NULL; - completion_found = false; - current_block = NULL; - current_class = NULL; - - current_function = NULL; + clear(); self_path = p_self_path; GDScriptTokenizerText *tt = memnew(GDScriptTokenizerText); diff --git a/modules/gridmap/doc_classes/GridMap.xml b/modules/gridmap/doc_classes/GridMap.xml index 44685220b3..bb652f3bdf 100644 --- a/modules/gridmap/doc_classes/GridMap.xml +++ b/modules/gridmap/doc_classes/GridMap.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="GridMap" inherits="Spatial" category="Core" version="3.0-stable"> +<class name="GridMap" inherits="Spatial" category="Core" version="3.1"> <brief_description> Node for 3D tile-based maps. </brief_description> diff --git a/modules/gridmap/grid_map_editor_plugin.cpp b/modules/gridmap/grid_map_editor_plugin.cpp index 7b7bc0fa2a..869492232c 100644 --- a/modules/gridmap/grid_map_editor_plugin.cpp +++ b/modules/gridmap/grid_map_editor_plugin.cpp @@ -99,6 +99,20 @@ void GridMapEditor::_menu_option(int p_option) { int idx = options->get_popup()->get_item_index(MENU_OPTION_X_AXIS + i); options->get_popup()->set_item_checked(idx, i == new_axis); } + + if (edit_axis != new_axis) { + int item1 = options->get_popup()->get_item_index(MENU_OPTION_NEXT_LEVEL); + int item2 = options->get_popup()->get_item_index(MENU_OPTION_PREV_LEVEL); + if (edit_axis == Vector3::AXIS_Y) { + options->get_popup()->set_item_text(item1, TTR("Next Plane")); + options->get_popup()->set_item_text(item2, TTR("Previous Plane")); + spin_box_label->set_text(TTR("Plane:")); + } else if (new_axis == Vector3::AXIS_Y) { + options->get_popup()->set_item_text(item1, TTR("Next Floor")); + options->get_popup()->set_item_text(item2, TTR("Previous Floor")); + spin_box_label->set_text(TTR("Floor:")); + } + } edit_axis = Vector3::Axis(new_axis); update_grid(); _update_clip(); @@ -627,12 +641,21 @@ bool GridMapEditor::forward_spatial_input_event(Camera *p_camera, const Ref<Inpu Ref<InputEventPanGesture> pan_gesture = p_event; if (pan_gesture.is_valid()) { - if (pan_gesture->get_command() || pan_gesture->get_shift()) { - const real_t delta = pan_gesture->get_delta().y; - floor->set_value(floor->get_value() + SGN(delta)); + if (pan_gesture->get_alt() && (pan_gesture->get_command() || pan_gesture->get_shift())) { + const real_t delta = pan_gesture->get_delta().y * 0.5; + accumulated_floor_delta += delta; + int step = 0; + if (ABS(accumulated_floor_delta) > 1.0) { + step = SGN(accumulated_floor_delta); + accumulated_floor_delta -= step; + } + if (step) { + floor->set_value(floor->get_value() + step); + } return true; } } + accumulated_floor_delta = 0.0; return false; } @@ -756,7 +779,7 @@ void GridMapEditor::edit(GridMap *p_gridmap) { set_process(true); - Vector3 edited_floor = p_gridmap->get_meta("_editor_floor_"); + Vector3 edited_floor = p_gridmap->has_meta("_editor_floor_") ? p_gridmap->get_meta("_editor_floor_") : Variant(); clip_mode = p_gridmap->has_meta("_editor_clip_") ? ClipMode(p_gridmap->get_meta("_editor_clip_").operator int()) : CLIP_DISABLED; for (int i = 0; i < 3; i++) { @@ -998,9 +1021,9 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) { spatial_editor_hb->set_alignment(BoxContainer::ALIGN_END); SpatialEditor::get_singleton()->add_control_to_menu_panel(spatial_editor_hb); - Label *fl = memnew(Label); - fl->set_text(TTR("Floor:")); - spatial_editor_hb->add_child(fl); + spin_box_label = memnew(Label); + spin_box_label->set_text(TTR("Floor:")); + spatial_editor_hb->add_child(spin_box_label); floor = memnew(SpinBox); floor->set_min(-32767); @@ -1233,6 +1256,7 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) { selection.active = false; updating = false; + accumulated_floor_delta = 0.0; } GridMapEditor::~GridMapEditor() { @@ -1245,9 +1269,10 @@ GridMapEditor::~GridMapEditor() { VisualServer::get_singleton()->free(grid_instance[i]); if (cursor_instance.is_valid()) VisualServer::get_singleton()->free(cursor_instance); - if (selection_level_instance[i].is_valid()) { + if (selection_level_instance[i].is_valid()) VisualServer::get_singleton()->free(selection_level_instance[i]); - } + if (selection_level_mesh[i].is_valid()) + VisualServer::get_singleton()->free(selection_level_mesh[i]); } VisualServer::get_singleton()->free(selection_mesh); diff --git a/modules/gridmap/grid_map_editor_plugin.h b/modules/gridmap/grid_map_editor_plugin.h index 3fc92bf7aa..f79d9aefa0 100644 --- a/modules/gridmap/grid_map_editor_plugin.h +++ b/modules/gridmap/grid_map_editor_plugin.h @@ -76,12 +76,14 @@ class GridMapEditor : public VBoxContainer { Panel *panel; MenuButton *options; SpinBox *floor; + double accumulated_floor_delta; ToolButton *mode_thumbnail; ToolButton *mode_list; HBoxContainer *spatial_editor_hb; ConfirmationDialog *settings_dialog; VBoxContainer *settings_vbc; SpinBox *settings_pick_distance; + Label *spin_box_label; struct SetItem { diff --git a/modules/hdr/image_loader_hdr.cpp b/modules/hdr/image_loader_hdr.cpp index 3cc362b5d6..d592c19b97 100644 --- a/modules/hdr/image_loader_hdr.cpp +++ b/modules/hdr/image_loader_hdr.cpp @@ -42,14 +42,18 @@ Error ImageLoaderHDR::load_image(Ref<Image> p_image, FileAccess *f, bool p_force ERR_FAIL_COND_V(header != "#?RADIANCE" && header != "#?RGBE", ERR_FILE_UNRECOGNIZED); while (true) { - String format = f->get_token(); + String line = f->get_line(); ERR_FAIL_COND_V(f->eof_reached(), ERR_FILE_UNRECOGNIZED); - if (format.begins_with("FORMAT=") && format != "FORMAT=32-bit_rle_rgbe") { - ERR_EXPLAIN("Only 32-bit_rle_rgbe is supported for .hdr files."); - return ERR_FILE_UNRECOGNIZED; - } - if (format == "FORMAT=32-bit_rle_rgbe") + if (line == "") // empty line indicates end of header break; + if (line.begins_with("FORMAT=")) { // leave option to implement other commands + if (line != "FORMAT=32-bit_rle_rgbe") { + ERR_EXPLAIN("Only 32-bit_rle_rgbe is supported for HDR files."); + return ERR_FILE_UNRECOGNIZED; + } + } else if (!line.begins_with("#")) { // not comment + WARN_PRINTS("Ignoring unsupported header information in HDR : " + line); + } } String token = f->get_token(); diff --git a/modules/mbedtls/SCsub b/modules/mbedtls/SCsub index b846ae38ad..38198c9105 100755 --- a/modules/mbedtls/SCsub +++ b/modules/mbedtls/SCsub @@ -85,7 +85,7 @@ if env['builtin_mbedtls']: thirdparty_dir = "#thirdparty/mbedtls/library/" thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources] env_mbed_tls.add_source_files(env.modules_sources, thirdparty_sources) - env_mbed_tls.Append(CPPPATH=["#thirdparty/mbedtls/include/"]) + env_mbed_tls.Prepend(CPPPATH=["#thirdparty/mbedtls/include/"]) # Module sources env_mbed_tls.add_source_files(env.modules_sources, "*.cpp") diff --git a/modules/mobile_vr/config.py b/modules/mobile_vr/config.py index 4e1155f0c6..aa8ef111d3 100644 --- a/modules/mobile_vr/config.py +++ b/modules/mobile_vr/config.py @@ -1,6 +1,6 @@ def can_build(platform): # should probably change this to only be true on iOS and Android - return True + return False def configure(env): pass diff --git a/modules/mobile_vr/doc_classes/MobileVRInterface.xml b/modules/mobile_vr/doc_classes/MobileVRInterface.xml index 82300e707a..359d654433 100644 --- a/modules/mobile_vr/doc_classes/MobileVRInterface.xml +++ b/modules/mobile_vr/doc_classes/MobileVRInterface.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="MobileVRInterface" inherits="ARVRInterface" category="Core" version="3.0-stable"> +<class name="MobileVRInterface" inherits="ARVRInterface" category="Core" version="3.1"> <brief_description> Generic mobile VR implementation </brief_description> diff --git a/modules/mono/SCsub b/modules/mono/SCsub index aa8626e6da..a1dfcf6377 100644 --- a/modules/mono/SCsub +++ b/modules/mono/SCsub @@ -31,11 +31,18 @@ def make_cs_files_header(src, dst): if i > 0: header.write(', ') header.write(byte_to_str(buf[buf_idx])) - inserted_files += '\tr_files.insert(\"' + file + '\", ' \ + inserted_files += '\tr_files.insert("' + file + '", ' \ 'CompressedFile(_cs_' + name + '_compressed_size, ' \ '_cs_' + name + '_uncompressed_size, ' \ '_cs_' + name + '_compressed));\n' header.write(' };\n') + version_file = os.path.join(src, 'VERSION.txt') + with open(version_file, 'r') as content_file: + try: + glue_version = int(content_file.read()) # make sure the format is valid + header.write('\n#define CS_GLUE_VERSION UINT32_C(' + str(glue_version) + ')\n') + except ValueError: + raise ValueError('Invalid C# glue version in: ' + version_file) header.write('\nstruct CompressedFile\n' '{\n' '\tint compressed_size;\n' '\tint uncompressed_size;\n' '\tconst unsigned char* data;\n' '\n\tCompressedFile(int p_comp_size, int p_uncomp_size, const unsigned char* p_data)\n' @@ -80,23 +87,23 @@ def find_msbuild_unix(filename): import sys hint_dirs = ['/opt/novell/mono/bin'] - if sys.platform == "darwin": + if sys.platform == 'darwin': hint_dirs = ['/Library/Frameworks/Mono.framework/Versions/Current/bin'] + hint_dirs for hint_dir in hint_dirs: hint_path = os.path.join(hint_dir, filename) if os.path.isfile(hint_path): return hint_path - elif os.path.isfile(hint_path + ".exe"): - return hint_path + ".exe" + elif os.path.isfile(hint_path + '.exe'): + return hint_path + '.exe' - for hint_dir in os.environ["PATH"].split(os.pathsep): + for hint_dir in os.environ['PATH'].split(os.pathsep): hint_dir = hint_dir.strip('"') hint_path = os.path.join(hint_dir, filename) if os.path.isfile(hint_path) and os.access(hint_path, os.X_OK): return hint_path - if os.path.isfile(hint_path + ".exe") and os.access(hint_path + ".exe", os.X_OK): - return hint_path + ".exe" + if os.path.isfile(hint_path + '.exe') and os.access(hint_path + '.exe', os.X_OK): + return hint_path + '.exe' return None @@ -152,7 +159,7 @@ def mono_build_solution(source, target, env): xbuild_fallback = env['xbuild_fallback'] if xbuild_fallback and os.name == 'nt': - print("Option 'xbuild_fallback' not supported on Windows") + print('Option \'xbuild_fallback\' not supported on Windows') xbuild_fallback = False if xbuild_fallback: @@ -202,10 +209,16 @@ def mono_build_solution(source, target, env): copyfile(os.path.join(src_dir, asm_file), os.path.join(dst_dir, asm_file)) +output_dir = Dir('#bin').abspath +assemblies_output_dir = Dir(env['mono_assemblies_output_dir']).abspath -mono_sln_builder = Builder(action = mono_build_solution) +mono_sln_builder = Builder(action=mono_build_solution) env_mono.Append(BUILDERS={'MonoBuildSolution': mono_sln_builder}) env_mono.MonoBuildSolution( - os.path.join(Dir('#bin').abspath, 'GodotSharpTools.dll'), + os.path.join(assemblies_output_dir, 'GodotSharpTools.dll'), 'editor/GodotSharpTools/GodotSharpTools.sln' ) + +if os.path.normpath(output_dir) != os.path.normpath(assemblies_output_dir): + rel_assemblies_output_dir = os.path.relpath(assemblies_output_dir, output_dir) + env_mono.Append(CPPDEFINES={'GD_MONO_EDITOR_ASSEMBLIES_DIR': rel_assemblies_output_dir}) diff --git a/modules/mono/config.py b/modules/mono/config.py index 7c1846dcc2..831d849ea6 100644 --- a/modules/mono/config.py +++ b/modules/mono/config.py @@ -2,8 +2,9 @@ import imp import os import sys +import subprocess -from SCons.Script import BoolVariable, Environment, Variables +from SCons.Script import BoolVariable, Dir, Environment, PathVariable, Variables monoreg = imp.load_source('mono_reg_utils', 'modules/mono/mono_reg_utils.py') @@ -29,20 +30,16 @@ def is_enabled(): return False -def copy_file_no_replace(src_dir, dst_dir, name): +def copy_file(src_dir, dst_dir, name): from shutil import copyfile src_path = os.path.join(src_dir, name) dst_path = os.path.join(dst_dir, name) - need_copy = True if not os.path.isdir(dst_dir): os.mkdir(dst_dir) - elif os.path.exists(dst_path): - need_copy = False - if need_copy: - copyfile(src_path, dst_path) + copyfile(src_path, dst_path) def configure(env): @@ -51,11 +48,13 @@ def configure(env): envvars = Variables() envvars.Add(BoolVariable('mono_static', 'Statically link mono', False)) + envvars.Add(PathVariable('mono_assemblies_output_dir', 'Path to the assemblies output directory', '#bin', PathVariable.PathIsDirCreate)) envvars.Update(env) bits = env['bits'] mono_static = env['mono_static'] + assemblies_output_dir = Dir(env['mono_assemblies_output_dir']).abspath mono_lib_names = ['mono-2.0-sgen', 'monosgen-2.0'] @@ -99,11 +98,14 @@ def configure(env): if not mono_dll_name: raise RuntimeError('Could not find mono shared library in: ' + mono_bin_path) - copy_file_no_replace(mono_bin_path, 'bin', mono_dll_name + '.dll') + copy_file(mono_bin_path, 'bin', mono_dll_name + '.dll') + + copy_file(os.path.join(mono_lib_path, 'mono', '4.5'), assemblies_output_dir, 'mscorlib.dll') else: sharedlib_ext = '.dylib' if sys.platform == 'darwin' else '.so' mono_root = '' + mono_lib_path = '' if bits == '32': if os.getenv('MONO32_PREFIX'): @@ -148,7 +150,9 @@ def configure(env): if not mono_so_name: raise RuntimeError('Could not find mono shared library in: ' + mono_lib_path) - copy_file_no_replace(mono_lib_path, 'bin', 'lib' + mono_so_name + sharedlib_ext) + copy_file(mono_lib_path, 'bin', 'lib' + mono_so_name + sharedlib_ext) + + copy_file(os.path.join(mono_lib_path, 'mono', '4.5'), assemblies_output_dir, 'mscorlib.dll') else: if mono_static: raise RuntimeError('mono-static: Not supported with pkg-config. Specify a mono prefix manually') @@ -157,6 +161,7 @@ def configure(env): mono_lib_path = '' mono_so_name = '' + mono_prefix = subprocess.check_output(["pkg-config", "mono-2", "--variable=prefix"]).decode("utf8").strip() tmpenv = Environment() tmpenv.AppendENVPath('PKG_CONFIG_PATH', os.getenv('PKG_CONFIG_PATH')) @@ -172,7 +177,8 @@ def configure(env): if not mono_so_name: raise RuntimeError('Could not find mono shared library in: ' + str(tmpenv['LIBPATH'])) - copy_file_no_replace(mono_lib_path, 'bin', 'lib' + mono_so_name + sharedlib_ext) + copy_file(mono_lib_path, 'bin', 'lib' + mono_so_name + sharedlib_ext) + copy_file(os.path.join(mono_prefix, 'lib', 'mono', '4.5'), assemblies_output_dir, 'mscorlib.dll') env.Append(LINKFLAGS='-rdynamic') diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp index fb45136575..1d0afa7f2d 100644 --- a/modules/mono/csharp_script.cpp +++ b/modules/mono/csharp_script.cpp @@ -118,6 +118,8 @@ void CSharpLanguage::init() { #ifdef TOOLS_ENABLED EditorNode::add_init_callback(&gdsharp_editor_init_callback); + + GLOBAL_DEF("mono/export/include_scripts_content", true); #endif } @@ -280,6 +282,15 @@ void CSharpLanguage::get_string_delimiters(List<String> *p_delimiters) const { p_delimiters->push_back("@\" \""); // verbatim string literal } +static String get_base_class_name(const String &p_base_class_name, const String p_class_name) { + + String base_class = p_base_class_name; + if (p_class_name == base_class) { + base_class = "Godot." + base_class; + } + return base_class; +} + Ref<Script> CSharpLanguage::get_template(const String &p_class_name, const String &p_base_class_name) const { String script_template = "using " BINDINGS_NAMESPACE ";\n" @@ -306,7 +317,8 @@ Ref<Script> CSharpLanguage::get_template(const String &p_class_name, const Strin "// }\n" "}\n"; - script_template = script_template.replace("%BASE_CLASS_NAME%", p_base_class_name) + String base_class_name = get_base_class_name(p_base_class_name, p_class_name); + script_template = script_template.replace("%BASE_CLASS_NAME%", base_class_name) .replace("%CLASS_NAME%", p_class_name); Ref<CSharpScript> script; @@ -325,12 +337,24 @@ bool CSharpLanguage::is_using_templates() { void CSharpLanguage::make_template(const String &p_class_name, const String &p_base_class_name, Ref<Script> &p_script) { String src = p_script->get_source_code(); - src = src.replace("%BASE%", p_base_class_name) + String base_class_name = get_base_class_name(p_base_class_name, p_class_name); + src = src.replace("%BASE%", base_class_name) .replace("%CLASS%", p_class_name) .replace("%TS%", _get_indentation()); p_script->set_source_code(src); } +String CSharpLanguage::validate_path(const String &p_path) const { + + String class_name = p_path.get_file().get_basename(); + List<String> keywords; + get_reserved_words(&keywords); + if (keywords.find(class_name)) { + return TTR("Class name can't be a reserved keyword"); + } + return ""; +} + Script *CSharpLanguage::create_script() const { return memnew(CSharpScript); @@ -454,7 +478,7 @@ Vector<ScriptLanguage::StackInfo> CSharpLanguage::debug_get_current_stack_info() #ifdef DEBUG_ENABLED // Printing an error here will result in endless recursion, so we must be careful - if (!gdmono->is_runtime_initialized() || !GDMono::get_singleton()->get_api_assembly() || !GDMonoUtils::mono_cache.corlib_cache_updated) + if (!gdmono->is_runtime_initialized() || !GDMono::get_singleton()->get_core_api_assembly() || !GDMonoUtils::mono_cache.corlib_cache_updated) return Vector<StackInfo>(); MonoObject *stack_trace = mono_object_new(mono_domain_get(), CACHED_CLASS(System_Diagnostics_StackTrace)->get_mono_ptr()); @@ -1550,7 +1574,6 @@ bool CSharpScript::_update_exports() { } bool CSharpScript::_update_signals() { -#ifdef TOOLS_ENABLED if (!valid) return false; @@ -1581,8 +1604,6 @@ bool CSharpScript::_update_signals() { } return changed; -#endif - return false; } bool CSharpScript::_get_signal(GDMonoClass *p_class, GDMonoClass *p_delegate, Vector<Argument> ¶ms) { @@ -2135,9 +2156,7 @@ void CSharpScript::get_script_signal_list(List<MethodInfo> *r_signals) const { } void CSharpScript::update_signals() { -#ifdef TOOLS_ENABLED _update_signals(); -#endif } Ref<Script> CSharpScript::get_base_script() const { diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h index ffb1d2e0f4..8666149111 100644 --- a/modules/mono/csharp_script.h +++ b/modules/mono/csharp_script.h @@ -90,15 +90,15 @@ class CSharpScript : public Script { Variant::Type type; }; + Map<StringName, Vector<Argument> > _signals; + bool signals_invalidated; + #ifdef TOOLS_ENABLED List<PropertyInfo> exported_members_cache; // members_cache Map<StringName, Variant> exported_members_defval_cache; // member_default_values_cache Set<PlaceHolderScriptInstance *> placeholders; bool source_changed_cache; bool exports_invalidated; - Map<StringName, Vector<Argument> > _signals; - bool signals_invalidated; - void _update_exports_values(Map<StringName, Variant> &values, List<PropertyInfo> &propnames); virtual void _placeholder_erased(PlaceHolderScriptInstance *p_placeholder); #endif @@ -294,6 +294,7 @@ public: virtual bool is_using_templates(); virtual void make_template(const String &p_class_name, const String &p_base_class_name, Ref<Script> &p_script); /* TODO */ virtual bool validate(const String &p_script, int &r_line_error, int &r_col_error, String &r_test_error, const String &p_path, List<String> *r_functions) const { return true; } + virtual String validate_path(const String &p_path) const; virtual Script *create_script() const; virtual bool has_named_classes() const; virtual bool supports_builtin_mode() const; diff --git a/modules/mono/doc_classes/@C#.xml b/modules/mono/doc_classes/@C#.xml index 0f33c76eb2..082bc30fd8 100644 --- a/modules/mono/doc_classes/@C#.xml +++ b/modules/mono/doc_classes/@C#.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="@C#" category="Core" version="3.0-stable"> +<class name="@C#" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/mono/doc_classes/CSharpScript.xml b/modules/mono/doc_classes/CSharpScript.xml index 3efe71f1b3..a1f7399653 100644 --- a/modules/mono/doc_classes/CSharpScript.xml +++ b/modules/mono/doc_classes/CSharpScript.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="CSharpScript" inherits="Script" category="Core" version="3.0-stable"> +<class name="CSharpScript" inherits="Script" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/mono/doc_classes/GodotSharp.xml b/modules/mono/doc_classes/GodotSharp.xml index 1e5edf2a2a..985c66464b 100644 --- a/modules/mono/doc_classes/GodotSharp.xml +++ b/modules/mono/doc_classes/GodotSharp.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="GodotSharp" inherits="Object" category="Core" version="3.0-stable"> +<class name="GodotSharp" inherits="Object" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp index 62c7a94755..a210b8e480 100644 --- a/modules/mono/editor/bindings_generator.cpp +++ b/modules/mono/editor/bindings_generator.cpp @@ -70,8 +70,6 @@ #define LOCAL_RET "ret" -#define CS_CLASS_NATIVECALLS "NativeCalls" -#define CS_CLASS_NATIVECALLS_EDITOR "EditorNativeCalls" #define CS_FIELD_MEMORYOWN "memoryOwn" #define CS_PARAM_METHODBIND "method" #define CS_PARAM_INSTANCE "ptr" @@ -105,6 +103,8 @@ #define C_METHOD_MANAGED_TO_DICT C_NS_MONOMARSHAL "::mono_object_to_Dictionary" #define C_METHOD_MANAGED_FROM_DICT C_NS_MONOMARSHAL "::Dictionary_to_mono_object" +#define BINDINGS_GENERATOR_VERSION UINT32_C(2) + const char *BindingsGenerator::TypeInterface::DEFAULT_VARARG_C_IN = "\t%0 %1_in = %1;\n"; bool BindingsGenerator::verbose_output = false; @@ -529,7 +529,15 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_output_dir, bo "using System.Collections.Generic;\n" "\n"); cs_icalls_content.push_back("namespace " BINDINGS_NAMESPACE "\n" OPEN_BLOCK); - cs_icalls_content.push_back(INDENT1 "internal static class " CS_CLASS_NATIVECALLS "\n" INDENT1 OPEN_BLOCK); + cs_icalls_content.push_back(INDENT1 "internal static class " BINDINGS_CLASS_NATIVECALLS "\n" INDENT1 OPEN_BLOCK); + + cs_icalls_content.push_back(INDENT2 "internal static ulong godot_api_hash = "); + cs_icalls_content.push_back(String::num_uint64(GDMono::get_singleton()->get_api_core_hash()) + ";\n"); + cs_icalls_content.push_back(INDENT2 "internal static uint bindings_version = "); + cs_icalls_content.push_back(String::num_uint64(BINDINGS_GENERATOR_VERSION) + ";\n"); + cs_icalls_content.push_back(INDENT2 "internal static uint cs_glue_version = "); + cs_icalls_content.push_back(String::num_uint64(CS_GLUE_VERSION) + ";\n"); + cs_icalls_content.push_back("\n"); #define ADD_INTERNAL_CALL(m_icall) \ if (!m_icall.editor_only) { \ @@ -551,7 +559,7 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_output_dir, bo cs_icalls_content.push_back(INDENT1 CLOSE_BLOCK CLOSE_BLOCK); - String internal_methods_file = path_join(core_dir, CS_CLASS_NATIVECALLS ".cs"); + String internal_methods_file = path_join(core_dir, BINDINGS_CLASS_NATIVECALLS ".cs"); Error err = _save_file(internal_methods_file, cs_icalls_content); if (err != OK) @@ -626,7 +634,15 @@ Error BindingsGenerator::generate_cs_editor_project(const String &p_output_dir, "using System.Collections.Generic;\n" "\n"); cs_icalls_content.push_back("namespace " BINDINGS_NAMESPACE "\n" OPEN_BLOCK); - cs_icalls_content.push_back(INDENT1 "internal static class " CS_CLASS_NATIVECALLS_EDITOR "\n" INDENT1 OPEN_BLOCK); + cs_icalls_content.push_back(INDENT1 "internal static class " BINDINGS_CLASS_NATIVECALLS_EDITOR "\n" INDENT1 OPEN_BLOCK); + + cs_icalls_content.push_back(INDENT2 "internal static ulong godot_api_hash = "); + cs_icalls_content.push_back(String::num_uint64(GDMono::get_singleton()->get_api_editor_hash()) + ";\n"); + cs_icalls_content.push_back(INDENT2 "internal static uint bindings_version = "); + cs_icalls_content.push_back(String::num_uint64(BINDINGS_GENERATOR_VERSION) + ";\n"); + cs_icalls_content.push_back(INDENT2 "internal static uint cs_glue_version = "); + cs_icalls_content.push_back(String::num_uint64(CS_GLUE_VERSION) + ";\n"); + cs_icalls_content.push_back("\n"); #define ADD_INTERNAL_CALL(m_icall) \ if (m_icall.editor_only) { \ @@ -648,7 +664,7 @@ Error BindingsGenerator::generate_cs_editor_project(const String &p_output_dir, cs_icalls_content.push_back(INDENT1 CLOSE_BLOCK CLOSE_BLOCK); - String internal_methods_file = path_join(core_dir, CS_CLASS_NATIVECALLS_EDITOR ".cs"); + String internal_methods_file = path_join(core_dir, BINDINGS_CLASS_NATIVECALLS_EDITOR ".cs"); Error err = _save_file(internal_methods_file, cs_icalls_content); if (err != OK) @@ -714,7 +730,8 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str } output.push_back(INDENT1 "public "); - output.push_back(itype.is_singleton ? "static class " : "class "); + bool is_abstract = !ClassDB::can_instance(itype.name) && ClassDB::is_class_enabled(itype.name); // can_instance returns true if there's a constructor and the class is not 'disabled' + output.push_back(itype.is_singleton ? "static class " : (is_abstract ? "abstract class " : "class ")); output.push_back(itype.proxy_name); if (itype.is_singleton) { @@ -882,7 +899,7 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str output.push_back("\";\n"); output.push_back(INDENT2 "internal static IntPtr " BINDINGS_PTR_FIELD " = "); - output.push_back(itype.api_type == ClassDB::API_EDITOR ? CS_CLASS_NATIVECALLS_EDITOR : CS_CLASS_NATIVECALLS); + output.push_back(itype.api_type == ClassDB::API_EDITOR ? BINDINGS_CLASS_NATIVECALLS_EDITOR : BINDINGS_CLASS_NATIVECALLS); output.push_back("." ICALL_PREFIX); output.push_back(itype.name); output.push_back(SINGLETON_ICALL_SUFFIX "();\n"); @@ -912,7 +929,7 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str // The engine will initialize the pointer field of the managed side before calling the constructor // This is why we only allocate a new native object from the constructor if the pointer field is not set output.push_back(")\n" OPEN_BLOCK_L2 "if (" BINDINGS_PTR_FIELD " == IntPtr.Zero)\n" INDENT4 BINDINGS_PTR_FIELD " = "); - output.push_back(itype.api_type == ClassDB::API_EDITOR ? CS_CLASS_NATIVECALLS_EDITOR : CS_CLASS_NATIVECALLS); + output.push_back(itype.api_type == ClassDB::API_EDITOR ? BINDINGS_CLASS_NATIVECALLS_EDITOR : BINDINGS_CLASS_NATIVECALLS); output.push_back("." + ctor_method); output.push_back("(this);\n" CLOSE_BLOCK_L2); } else { @@ -956,7 +973,7 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str "if (disposed) return;\n" INDENT3 "if (" BINDINGS_PTR_FIELD " != IntPtr.Zero)\n" OPEN_BLOCK_L3 "if (" CS_FIELD_MEMORYOWN ")\n" OPEN_BLOCK_L4 CS_FIELD_MEMORYOWN - " = false;\n" INDENT5 CS_CLASS_NATIVECALLS "." ICALL_OBJECT_DTOR + " = false;\n" INDENT5 BINDINGS_CLASS_NATIVECALLS "." ICALL_OBJECT_DTOR "(this, " BINDINGS_PTR_FIELD ");\n" CLOSE_BLOCK_L4 CLOSE_BLOCK_L3 INDENT3 "this." BINDINGS_PTR_FIELD " = IntPtr.Zero;\n" INDENT3 "GC.SuppressFinalize(this);\n" INDENT3 "disposed = true;\n" CLOSE_BLOCK_L2); @@ -1229,7 +1246,7 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf { if (p_itype.is_object_type && !p_imethod.is_virtual && !p_imethod.requires_object_call) { p_output.push_back(MEMBER_BEGIN "private static IntPtr "); - p_output.push_back(method_bind_field + " = " CS_CLASS_NATIVECALLS "." ICALL_GET_METHODBIND "(" BINDINGS_NATIVE_NAME_FIELD ", \""); + p_output.push_back(method_bind_field + " = " BINDINGS_CLASS_NATIVECALLS "." ICALL_GET_METHODBIND "(" BINDINGS_NATIVE_NAME_FIELD ", \""); p_output.push_back(p_imethod.name); p_output.push_back("\");\n"); } @@ -1310,7 +1327,7 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf const InternalCall *im_icall = match->value(); - String im_call = im_icall->editor_only ? CS_CLASS_NATIVECALLS_EDITOR : CS_CLASS_NATIVECALLS; + String im_call = im_icall->editor_only ? BINDINGS_CLASS_NATIVECALLS_EDITOR : BINDINGS_CLASS_NATIVECALLS; im_call += "." + im_icall->name + "(" + icall_params + ");\n"; if (p_imethod.arguments.size()) @@ -1400,25 +1417,33 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) { } output.push_back("namespace GodotSharpBindings\n" OPEN_BLOCK); + output.push_back("uint64_t get_core_api_hash() { return "); - output.push_back(itos(GDMono::get_singleton()->get_api_core_hash()) + "; }\n"); + output.push_back(String::num_uint64(GDMono::get_singleton()->get_api_core_hash()) + "; }\n"); + output.push_back("#ifdef TOOLS_ENABLED\n" "uint64_t get_editor_api_hash() { return "); - output.push_back(itos(GDMono::get_singleton()->get_api_editor_hash()) + + output.push_back(String::num_uint64(GDMono::get_singleton()->get_api_editor_hash()) + "; }\n#endif // TOOLS_ENABLED\n"); + + output.push_back("uint32_t get_bindings_version() { return "); + output.push_back(String::num_uint64(BINDINGS_GENERATOR_VERSION) + "; }\n"); + output.push_back("uint32_t get_cs_glue_version() { return "); + output.push_back(String::num_uint64(CS_GLUE_VERSION) + "; }\n"); + output.push_back("void register_generated_icalls() " OPEN_BLOCK); output.push_back("\tgodot_register_header_icalls();"); -#define ADD_INTERNAL_CALL_REGISTRATION(m_icall) \ - { \ - output.push_back("\tmono_add_internal_call("); \ - output.push_back("\"" BINDINGS_NAMESPACE "."); \ - output.push_back(m_icall.editor_only ? CS_CLASS_NATIVECALLS_EDITOR : CS_CLASS_NATIVECALLS); \ - output.push_back("::"); \ - output.push_back(m_icall.name); \ - output.push_back("\", (void*)"); \ - output.push_back(m_icall.name); \ - output.push_back(");\n"); \ +#define ADD_INTERNAL_CALL_REGISTRATION(m_icall) \ + { \ + output.push_back("\tmono_add_internal_call("); \ + output.push_back("\"" BINDINGS_NAMESPACE "."); \ + output.push_back(m_icall.editor_only ? BINDINGS_CLASS_NATIVECALLS_EDITOR : BINDINGS_CLASS_NATIVECALLS); \ + output.push_back("::"); \ + output.push_back(m_icall.name); \ + output.push_back("\", (void*)"); \ + output.push_back(m_icall.name); \ + output.push_back(");\n"); \ } bool tools_sequence = false; @@ -1486,6 +1511,14 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) { return OK; } +uint32_t BindingsGenerator::get_version() { + return BINDINGS_GENERATOR_VERSION; +} + +uint32_t BindingsGenerator::get_cs_glue_version() { + return CS_GLUE_VERSION; +} + Error BindingsGenerator::_save_file(const String &p_path, const List<String> &p_content) { FileAccessRef file = FileAccess::open(p_path, FileAccess::WRITE); @@ -1528,9 +1561,9 @@ Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInte if (p_imethod.is_vararg) { if (i < p_imethod.arguments.size() - 1) { c_in_statements += sformat(arg_type->c_in.size() ? arg_type->c_in : TypeInterface::DEFAULT_VARARG_C_IN, "Variant", c_param_name); - c_in_statements += "\t" C_LOCAL_PTRCALL_ARGS ".set(0, "; - c_in_statements += sformat("&%s_in", c_param_name); - c_in_statements += ");\n"; + c_in_statements += "\t" C_LOCAL_PTRCALL_ARGS ".set("; + c_in_statements += itos(i); + c_in_statements += sformat(", &%s_in);\n", c_param_name); } } else { if (i > 0) @@ -2231,7 +2264,8 @@ void BindingsGenerator::_populate_builtin_type_interfaces() { "this." BINDINGS_PTR_FIELD " = NativeCalls.godot_icall_NodePath_Ctor(path);\n" CLOSE_BLOCK_L2 MEMBER_BEGIN "public static implicit operator NodePath(string from)\n" OPEN_BLOCK_L2 "return new NodePath(from);\n" CLOSE_BLOCK_L2 MEMBER_BEGIN "public static implicit operator string(NodePath from)\n" OPEN_BLOCK_L2 - "return NativeCalls." ICALL_PREFIX "NodePath_operator_String(NodePath." CS_SMETHOD_GETINSTANCE "(from));\n" CLOSE_BLOCK_L2); + "return NativeCalls." ICALL_PREFIX "NodePath_operator_String(NodePath." CS_SMETHOD_GETINSTANCE "(from));\n" CLOSE_BLOCK_L2 + MEMBER_BEGIN "public override string ToString()\n" OPEN_BLOCK_L2 "return (string)this;\n" CLOSE_BLOCK_L2); builtin_types.insert(itype.cname, itype); // RID @@ -2365,7 +2399,7 @@ void BindingsGenerator::_populate_builtin_type(TypeInterface &r_itype, Variant:: imethod.name = mi.name; imethod.cname = imethod.name; - imethod.proxy_name = mi.name; + imethod.proxy_name = escape_csharp_keyword(snake_to_pascal_case(mi.name)); for (int i = 0; i < mi.arguments.size(); i++) { ArgumentInterface iarg; diff --git a/modules/mono/editor/bindings_generator.h b/modules/mono/editor/bindings_generator.h index 9b5a9cea88..f6194139af 100644 --- a/modules/mono/editor/bindings_generator.h +++ b/modules/mono/editor/bindings_generator.h @@ -536,6 +536,9 @@ public: Error generate_cs_editor_project(const String &p_output_dir, const String &p_core_dll_path, bool p_verbose_output = true); Error generate_glue(const String &p_output_dir); + static uint32_t get_version(); + static uint32_t get_cs_glue_version(); + void initialize(); _FORCE_INLINE_ static BindingsGenerator *get_singleton() { diff --git a/modules/mono/editor/godotsharp_builds.cpp b/modules/mono/editor/godotsharp_builds.cpp index 6b41b10981..ad07f043b2 100644 --- a/modules/mono/editor/godotsharp_builds.cpp +++ b/modules/mono/editor/godotsharp_builds.cpp @@ -33,7 +33,6 @@ #include "main/main.h" #include "../godotsharp_dirs.h" -#include "../mono_gd/gd_mono.h" #include "../mono_gd/gd_mono_class.h" #include "../mono_gd/gd_mono_marshal.h" #include "../utils/path_utils.h" @@ -178,13 +177,15 @@ bool GodotSharpBuilds::build_api_sln(const String &p_name, const String &p_api_s return true; } -bool GodotSharpBuilds::copy_api_assembly(const String &p_src_dir, const String &p_dst_dir, const String &p_assembly_name) { +bool GodotSharpBuilds::copy_api_assembly(const String &p_src_dir, const String &p_dst_dir, const String &p_assembly_name, APIAssembly::Type p_api_type) { String assembly_file = p_assembly_name + ".dll"; String assembly_src = p_src_dir.plus_file(assembly_file); String assembly_dst = p_dst_dir.plus_file(assembly_file); - if (!FileAccess::exists(assembly_dst) || FileAccess::get_modified_time(assembly_src) > FileAccess::get_modified_time(assembly_dst)) { + if (!FileAccess::exists(assembly_dst) || + FileAccess::get_modified_time(assembly_src) > FileAccess::get_modified_time(assembly_dst) || + GDMono::get_singleton()->metadata_is_api_assembly_invalidated(p_api_type)) { DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); String xml_file = p_assembly_name + ".xml"; @@ -200,36 +201,49 @@ bool GodotSharpBuilds::copy_api_assembly(const String &p_src_dir, const String & memdelete(da); if (err != OK) { - show_build_error_dialog("Failed to copy " API_ASSEMBLY_NAME ".dll"); + show_build_error_dialog("Failed to copy " + assembly_file); return false; } + + GDMono::get_singleton()->metadata_set_api_assembly_invalidated(p_api_type, false); } return true; } -bool GodotSharpBuilds::make_api_sln(GodotSharpBuilds::APIType p_api_type) { +String GodotSharpBuilds::_api_folder_name(APIAssembly::Type p_api_type) { + + uint64_t api_hash = p_api_type == APIAssembly::API_CORE ? + GDMono::get_singleton()->get_api_core_hash() : + GDMono::get_singleton()->get_api_editor_hash(); + return String::num_uint64(api_hash) + + "_" + String::num_uint64(BindingsGenerator::get_version()) + + "_" + String::num_uint64(BindingsGenerator::get_cs_glue_version()); +} + +bool GodotSharpBuilds::make_api_sln(APIAssembly::Type p_api_type) { - String api_name = p_api_type == API_CORE ? API_ASSEMBLY_NAME : EDITOR_API_ASSEMBLY_NAME; + String api_name = p_api_type == APIAssembly::API_CORE ? API_ASSEMBLY_NAME : EDITOR_API_ASSEMBLY_NAME; String api_build_config = "Release"; EditorProgress pr("mono_build_release_" + api_name, "Building " + api_name + " solution...", 4); pr.step("Generating " + api_name + " solution"); - uint64_t core_hash = GDMono::get_singleton()->get_api_core_hash(); - uint64_t editor_hash = GDMono::get_singleton()->get_api_editor_hash(); + String core_api_sln_dir = GodotSharpDirs::get_mono_solutions_dir() + .plus_file(_api_folder_name(APIAssembly::API_CORE)) + .plus_file(API_ASSEMBLY_NAME); + String editor_api_sln_dir = GodotSharpDirs::get_mono_solutions_dir() + .plus_file(_api_folder_name(APIAssembly::API_EDITOR)) + .plus_file(EDITOR_API_ASSEMBLY_NAME); - String core_api_sln_dir = GodotSharpDirs::get_mono_solutions_dir().plus_file(API_ASSEMBLY_NAME "_" + itos(core_hash)); - String editor_api_sln_dir = GodotSharpDirs::get_mono_solutions_dir().plus_file(EDITOR_API_ASSEMBLY_NAME "_" + itos(editor_hash)); - - String api_sln_dir = p_api_type == API_CORE ? core_api_sln_dir : editor_api_sln_dir; + String api_sln_dir = p_api_type == APIAssembly::API_CORE ? core_api_sln_dir : editor_api_sln_dir; String api_sln_file = api_sln_dir.plus_file(api_name + ".sln"); if (!DirAccess::exists(api_sln_dir) || !FileAccess::exists(api_sln_file)) { String core_api_assembly; - if (p_api_type == API_EDITOR) { + if (p_api_type == APIAssembly::API_EDITOR) { core_api_assembly = core_api_sln_dir.plus_file("bin") .plus_file(api_build_config) .plus_file(API_ASSEMBLY_NAME ".dll"); @@ -242,7 +256,7 @@ bool GodotSharpBuilds::make_api_sln(GodotSharpBuilds::APIType p_api_type) { BindingsGenerator *gen = BindingsGenerator::get_singleton(); bool gen_verbose = OS::get_singleton()->is_stdout_verbose(); - Error err = p_api_type == API_CORE ? + Error err = p_api_type == APIAssembly::API_CORE ? gen->generate_cs_core_project(api_sln_dir, gen_verbose) : gen->generate_cs_editor_project(api_sln_dir, core_api_assembly, gen_verbose); @@ -275,7 +289,7 @@ bool GodotSharpBuilds::make_api_sln(GodotSharpBuilds::APIType p_api_type) { // Copy the built assembly to the assemblies directory String api_assembly_dir = api_sln_dir.plus_file("bin").plus_file(api_build_config); - if (!GodotSharpBuilds::copy_api_assembly(api_assembly_dir, res_assemblies_dir, api_name)) + if (!GodotSharpBuilds::copy_api_assembly(api_assembly_dir, res_assemblies_dir, api_name, p_api_type)) return false; pr.step("Done"); @@ -283,22 +297,22 @@ bool GodotSharpBuilds::make_api_sln(GodotSharpBuilds::APIType p_api_type) { return true; } -bool GodotSharpBuilds::build_project_blocking() { +bool GodotSharpBuilds::build_project_blocking(const String &p_config) { if (!FileAccess::exists(GodotSharpDirs::get_project_sln_path())) return true; // No solution to build - if (!GodotSharpBuilds::make_api_sln(GodotSharpBuilds::API_CORE)) + if (!GodotSharpBuilds::make_api_sln(APIAssembly::API_CORE)) return false; - if (!GodotSharpBuilds::make_api_sln(GodotSharpBuilds::API_EDITOR)) + if (!GodotSharpBuilds::make_api_sln(APIAssembly::API_EDITOR)) return false; EditorProgress pr("mono_project_debug_build", "Building project solution...", 2); pr.step("Building project solution"); - MonoBuildInfo build_info(GodotSharpDirs::get_project_sln_path(), "Tools"); + MonoBuildInfo build_info(GodotSharpDirs::get_project_sln_path(), p_config); if (!GodotSharpBuilds::get_singleton()->build(build_info)) { GodotSharpBuilds::show_build_error_dialog("Failed to build project solution"); return false; @@ -309,6 +323,11 @@ bool GodotSharpBuilds::build_project_blocking() { return true; } +bool GodotSharpBuilds::editor_build_callback() { + + return build_project_blocking("Tools"); +} + GodotSharpBuilds *GodotSharpBuilds::singleton = NULL; void GodotSharpBuilds::build_exit_callback(const MonoBuildInfo &p_build_info, int p_exit_code) { @@ -362,7 +381,7 @@ GodotSharpBuilds::GodotSharpBuilds() { singleton = this; - EditorNode::get_singleton()->add_build_callback(&GodotSharpBuilds::build_project_blocking); + EditorNode::get_singleton()->add_build_callback(&GodotSharpBuilds::editor_build_callback); // Build tool settings EditorSettings *ed_settings = EditorSettings::get_singleton(); @@ -462,6 +481,7 @@ void GodotSharpBuilds::BuildProcess::start(bool p_blocking) { if (ex) { exited = true; + GDMonoUtils::print_unhandled_exception(ex); String message = "The build constructor threw an exception.\n" + GDMonoUtils::get_exception_name_and_message(ex); build_tab->on_build_exec_failed(message); ERR_EXPLAIN(message); @@ -482,6 +502,7 @@ void GodotSharpBuilds::BuildProcess::start(bool p_blocking) { if (ex) { exited = true; + GDMonoUtils::print_unhandled_exception(ex); String message = "The build method threw an exception.\n" + GDMonoUtils::get_exception_name_and_message(ex); build_tab->on_build_exec_failed(message); ERR_EXPLAIN(message); diff --git a/modules/mono/editor/godotsharp_builds.h b/modules/mono/editor/godotsharp_builds.h index 5d2390ecd9..27b771e324 100644 --- a/modules/mono/editor/godotsharp_builds.h +++ b/modules/mono/editor/godotsharp_builds.h @@ -31,6 +31,7 @@ #ifndef GODOTSHARP_BUILDS_H #define GODOTSHARP_BUILDS_H +#include "../mono_gd/gd_mono.h" #include "mono_bottom_panel.h" #include "mono_build_info.h" @@ -56,17 +57,14 @@ private: HashMap<MonoBuildInfo, BuildProcess, MonoBuildInfo::Hasher> builds; + static String _api_folder_name(APIAssembly::Type p_api_type); + static GodotSharpBuilds *singleton; friend class GDMono; static void _register_internal_calls(); public: - enum APIType { - API_CORE, - API_EDITOR - }; - enum BuildTool { MSBUILD_MONO, #ifdef WINDOWS_ENABLED @@ -89,11 +87,13 @@ public: bool build_async(const MonoBuildInfo &p_build_info, GodotSharpBuild_ExitCallback p_callback = NULL); static bool build_api_sln(const String &p_name, const String &p_api_sln_dir, const String &p_config); - static bool copy_api_assembly(const String &p_src_dir, const String &p_dst_dir, const String &p_assembly_name); + static bool copy_api_assembly(const String &p_src_dir, const String &p_dst_dir, const String &p_assembly_name, APIAssembly::Type p_api_type); + + static bool make_api_sln(APIAssembly::Type p_api_type); - static bool make_api_sln(APIType p_api_type); + static bool build_project_blocking(const String &p_config); - static bool build_project_blocking(); + static bool editor_build_callback(); GodotSharpBuilds(); ~GodotSharpBuilds(); diff --git a/modules/mono/editor/godotsharp_editor.cpp b/modules/mono/editor/godotsharp_editor.cpp index 0ef3adfdd0..998da8bda3 100644 --- a/modules/mono/editor/godotsharp_editor.cpp +++ b/modules/mono/editor/godotsharp_editor.cpp @@ -41,6 +41,7 @@ #include "../utils/path_utils.h" #include "bindings_generator.h" #include "csharp_project.h" +#include "godotsharp_export.h" #include "net_solution.h" #ifdef WINDOWS_ENABLED @@ -84,10 +85,10 @@ bool GodotSharpEditor::_create_project_solution() { return false; } - if (!GodotSharpBuilds::make_api_sln(GodotSharpBuilds::API_CORE)) + if (!GodotSharpBuilds::make_api_sln(APIAssembly::API_CORE)) return false; - if (!GodotSharpBuilds::make_api_sln(GodotSharpBuilds::API_EDITOR)) + if (!GodotSharpBuilds::make_api_sln(APIAssembly::API_EDITOR)) return false; pr.step(TTR("Done")); @@ -278,10 +279,11 @@ GodotSharpEditor::GodotSharpEditor(EditorNode *p_editor) { String about_text = String("C# support in Godot Engine is a brand new feature and a work in progress.\n") + "It is at the alpha stage and thus not suitable for use in production.\n\n" + - "As of Godot 3.0, C# support is not feature-complete and can crash in some situations. " + - "Bugs and usability issues will be addressed gradually over 3.0.x and 3.x releases.\n" + + "As of Godot 3.0, C# support is not feature-complete and may crash in some situations. " + + "Bugs and usability issues will be addressed gradually over 3.0.x and 3.x releases, " + + "including compatibility breaking changes as new features are implemented for a better overall C# experience.\n\n" + "The main missing feature is the ability to export games using C# assemblies - you will therefore be able to develop and run games in the editor, " + - "but not to share them as standalone binaries. This feature is of course high on the priority list and should be available in 3.0.1.\n\n" + + "but not to share them as standalone binaries yet. This feature is of course high on the priority list and should be available as soon as possible.\n\n" + "If you experience issues with this Mono build, please report them on Godot's issue tracker with details about your system, Mono version, IDE, etc.:\n\n" + " https://github.com/godotengine/godot/issues\n\n" + "Your critical feedback at this stage will play a great role in shaping the C# support in future releases, so thank you!"; @@ -315,6 +317,11 @@ GodotSharpEditor::GodotSharpEditor(EditorNode *p_editor) { EditorSettings *ed_settings = EditorSettings::get_singleton(); EDITOR_DEF("mono/editor/external_editor", EDITOR_NONE); ed_settings->add_property_hint(PropertyInfo(Variant::INT, "mono/editor/external_editor", PROPERTY_HINT_ENUM, "None,MonoDevelop,Visual Studio Code")); + + // Export plugin + Ref<GodotSharpExport> godotsharp_export; + godotsharp_export.instance(); + EditorExport::get_singleton()->add_export_plugin(godotsharp_export); } GodotSharpEditor::~GodotSharpEditor() { diff --git a/modules/mono/editor/godotsharp_editor.h b/modules/mono/editor/godotsharp_editor.h index 81c49aec30..66da814c8b 100644 --- a/modules/mono/editor/godotsharp_editor.h +++ b/modules/mono/editor/godotsharp_editor.h @@ -32,7 +32,6 @@ #define GODOTSHARP_EDITOR_H #include "godotsharp_builds.h" - #include "monodevelop_instance.h" class GodotSharpEditor : public Node { diff --git a/modules/mono/editor/godotsharp_export.cpp b/modules/mono/editor/godotsharp_export.cpp new file mode 100644 index 0000000000..cd09e6516a --- /dev/null +++ b/modules/mono/editor/godotsharp_export.cpp @@ -0,0 +1,166 @@ +/*************************************************************************/ +/* godotsharp_export.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "godotsharp_export.h" + +#include "../csharp_script.h" +#include "../godotsharp_defs.h" +#include "../godotsharp_dirs.h" +#include "godotsharp_builds.h" + +void GodotSharpExport::_export_file(const String &p_path, const String &p_type, const Set<String> &p_features) { + + if (p_type != CSharpLanguage::get_singleton()->get_type()) + return; + + ERR_FAIL_COND(p_path.get_extension() != CSharpLanguage::get_singleton()->get_extension()); + + // TODO what if the source file is not part of the game's C# project + + if (!GLOBAL_GET("mono/export/include_scripts_content")) { + // We don't want to include the source code on exported games + add_file(p_path, Vector<uint8_t>(), false); + skip(); + } +} + +void GodotSharpExport::_export_begin(const Set<String> &p_features, bool p_debug, const String &p_path, int p_flags) { + + // TODO right now there is no way to stop the export process with an error + + ERR_FAIL_COND(!GDMono::get_singleton()->is_runtime_initialized()); + ERR_FAIL_NULL(GDMono::get_singleton()->get_tools_domain()); + + String build_config = p_debug ? "Debug" : "Release"; + + ERR_FAIL_COND(!GodotSharpBuilds::build_project_blocking(build_config)); + + // Add API assemblies + + String core_api_dll_path = GodotSharpDirs::get_res_assemblies_dir().plus_file(API_ASSEMBLY_NAME ".dll"); + ERR_FAIL_COND(!_add_assembly(core_api_dll_path, core_api_dll_path)); + + String editor_api_dll_path = GodotSharpDirs::get_res_assemblies_dir().plus_file(EDITOR_API_ASSEMBLY_NAME ".dll"); + ERR_FAIL_COND(!_add_assembly(editor_api_dll_path, editor_api_dll_path)); + + // Add project assembly + + String project_dll_name = ProjectSettings::get_singleton()->get("application/config/name"); + if (project_dll_name.empty()) { + project_dll_name = "UnnamedProject"; + } + + String project_dll_src_path = GodotSharpDirs::get_res_temp_assemblies_base_dir().plus_file(build_config).plus_file(project_dll_name + ".dll"); + String project_dll_dst_path = GodotSharpDirs::get_res_assemblies_dir().plus_file(project_dll_name + ".dll"); + ERR_FAIL_COND(!_add_assembly(project_dll_src_path, project_dll_dst_path)); + + // Add dependencies + + MonoDomain *prev_domain = mono_domain_get(); + MonoDomain *export_domain = GDMonoUtils::create_domain("GodotEngine.ProjectExportDomain"); + + ERR_FAIL_COND(!export_domain); + ERR_FAIL_COND(!mono_domain_set(export_domain, false)); + + Map<String, String> dependencies; + dependencies.insert("mscorlib", GDMono::get_singleton()->get_corlib_assembly()->get_path()); + + GDMonoAssembly *scripts_assembly = GDMonoAssembly::load_from(project_dll_name, project_dll_src_path, /* refonly: */ true); + + ERR_EXPLAIN("Cannot load refonly assembly: " + project_dll_name); + ERR_FAIL_COND(!scripts_assembly); + + Error depend_error = _get_assembly_dependencies(scripts_assembly, dependencies); + + GDMono::get_singleton()->finalize_and_unload_domain(export_domain); + mono_domain_set(prev_domain, false); + + ERR_FAIL_COND(depend_error != OK); + + for (Map<String, String>::Element *E = dependencies.front(); E; E = E->next()) { + String depend_src_path = E->value(); + String depend_dst_path = GodotSharpDirs::get_res_assemblies_dir().plus_file(depend_src_path.get_file()); + ERR_FAIL_COND(!_add_assembly(depend_src_path, depend_dst_path)); + } +} + +bool GodotSharpExport::_add_assembly(const String &p_src_path, const String &p_dst_path) { + + FileAccessRef f = FileAccess::open(p_src_path, FileAccess::READ); + ERR_FAIL_COND_V(!f, false); + + Vector<uint8_t> data; + data.resize(f->get_len()); + f->get_buffer(data.ptrw(), data.size()); + + add_file(p_dst_path, data, false); + + return true; +} + +Error GodotSharpExport::_get_assembly_dependencies(GDMonoAssembly *p_assembly, Map<String, String> &r_dependencies) { + + MonoImage *image = p_assembly->get_image(); + + for (int i = 0; i < mono_image_get_table_rows(image, MONO_TABLE_ASSEMBLYREF); i++) { + MonoAssemblyName *ref_aname = aname_prealloc; + mono_assembly_get_assemblyref(image, i, ref_aname); + String ref_name = mono_assembly_name_get_name(ref_aname); + + if (ref_name == "mscorlib" || r_dependencies.find(ref_name)) + continue; + + GDMonoAssembly *ref_assembly = NULL; + if (!GDMono::get_singleton()->load_assembly(ref_name, ref_aname, &ref_assembly, /* refonly: */ true)) { + ERR_EXPLAIN("Cannot load refonly assembly: " + ref_name); + ERR_FAIL_V(ERR_CANT_RESOLVE); + } + + r_dependencies.insert(ref_name, ref_assembly->get_path()); + + Error err = _get_assembly_dependencies(ref_assembly, r_dependencies); + if (err != OK) + return err; + } + + return OK; +} + +GodotSharpExport::GodotSharpExport() { + // MonoAssemblyName is an incomplete type (internal to mono), so we can't allocate it ourselves. + // There isn't any api to allocate an empty one either, so we need to do it this way. + aname_prealloc = mono_assembly_name_new("whatever"); + mono_assembly_name_free(aname_prealloc); // "it does not frees the object itself, only the name members" (typo included) +} + +GodotSharpExport::~GodotSharpExport() { + if (aname_prealloc) + mono_free(aname_prealloc); +} diff --git a/modules/mono/editor/godotsharp_export.h b/modules/mono/editor/godotsharp_export.h new file mode 100644 index 0000000000..b38db9660c --- /dev/null +++ b/modules/mono/editor/godotsharp_export.h @@ -0,0 +1,57 @@ +/*************************************************************************/ +/* godotsharp_export.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef GODOTSHARP_EXPORT_H +#define GODOTSHARP_EXPORT_H + +#include <mono/metadata/image.h> + +#include "editor/editor_export.h" + +#include "../mono_gd/gd_mono_header.h" + +class GodotSharpExport : public EditorExportPlugin { + + MonoAssemblyName *aname_prealloc; + + bool _add_assembly(const String &p_src_path, const String &p_dst_path); + + Error _get_assembly_dependencies(GDMonoAssembly *p_assembly, Map<String, String> &r_dependencies); + +protected: + virtual void _export_file(const String &p_path, const String &p_type, const Set<String> &p_features); + virtual void _export_begin(const Set<String> &p_features, bool p_debug, const String &p_path, int p_flags); + +public: + GodotSharpExport(); + ~GodotSharpExport(); +}; + +#endif // GODOTSHARP_EXPORT_H diff --git a/modules/mono/editor/mono_bottom_panel.cpp b/modules/mono/editor/mono_bottom_panel.cpp index 20378a0162..32aec2a3b5 100644 --- a/modules/mono/editor/mono_bottom_panel.cpp +++ b/modules/mono/editor/mono_bottom_panel.cpp @@ -142,7 +142,7 @@ void MonoBottomPanel::_errors_toggled(bool p_pressed) { void MonoBottomPanel::_build_project_pressed() { - GodotSharpBuilds::get_singleton()->build_project_blocking(); + GodotSharpBuilds::get_singleton()->build_project_blocking("Tools"); MonoReloadNode::get_singleton()->restart_reload_timer(); CSharpLanguage::get_singleton()->reload_assemblies_if_needed(true); diff --git a/modules/mono/glue/cs_files/Basis.cs b/modules/mono/glue/cs_files/Basis.cs index ea92b1641b..c6cdc069ef 100644 --- a/modules/mono/glue/cs_files/Basis.cs +++ b/modules/mono/glue/cs_files/Basis.cs @@ -452,9 +452,9 @@ namespace Godot public Basis(float xx, float xy, float xz, float yx, float yy, float yz, float zx, float zy, float zz) { - this.x = new Vector3(xx, xy, xz); - this.y = new Vector3(yx, yy, yz); - this.z = new Vector3(zx, zy, zz); + this.x = new Vector3(xx, yx, zx); + this.y = new Vector3(xy, yy, zy); + this.z = new Vector3(xz, yz, zz); } public static Basis operator *(Basis left, Basis right) diff --git a/modules/mono/glue/cs_files/StringExtensions.cs b/modules/mono/glue/cs_files/StringExtensions.cs index 5c3ceff97d..cbc337ab19 100644 --- a/modules/mono/glue/cs_files/StringExtensions.cs +++ b/modules/mono/glue/cs_files/StringExtensions.cs @@ -287,7 +287,7 @@ namespace Godot if (sep == -1) return @base; - return @base + rs.substr(0, sep); + return @base + rs.Substr(0, sep); } // <summary> @@ -478,7 +478,7 @@ namespace Godot // </summary> public static bool IsValidIpAddress(this string instance) { - string[] ip = instance.split("."); + string[] ip = instance.Split("."); if (ip.Length != 4) return false; @@ -489,7 +489,7 @@ namespace Godot if (!n.IsValidInteger()) return false; - int val = n.to_int(); + int val = n.ToInt(); if (val < 0 || val > 255) return false; } @@ -571,7 +571,7 @@ namespace Godot // <summary> // Do a simple case insensitive expression match, using ? and * wildcards (see [method expr_match]). // </summary> - public static bool matchn(this string instance, string expr) + public static bool Matchn(this string instance, string expr) { return instance.ExprMatch(expr, false); } @@ -830,7 +830,7 @@ namespace Godot // <summary> // Split the string by a divisor string, return an array of the substrings. Example "One,Two,Three" will return ["One","Two","Three"] if split by ",". // </summary> - public static string[] split(this string instance, string divisor, bool allow_empty = true) + public static string[] Split(this string instance, string divisor, bool allow_empty = true) { return instance.Split(new string[] { divisor }, StringSplitOptions.RemoveEmptyEntries); } @@ -838,7 +838,7 @@ namespace Godot // <summary> // Split the string in floats by using a divisor string, return an array of the substrings. Example "1,2.5,3" will return [1,2.5,3] if split by ",". // </summary> - public static float[] split_floats(this string instance, string divisor, bool allow_empty = true) + public static float[] SplitFloats(this string instance, string divisor, bool allow_empty = true) { List<float> ret = new List<float>(); int from = 0; @@ -872,7 +872,7 @@ namespace Godot // <summary> // Return a copy of the string stripped of any non-printable character at the beginning and the end. The optional arguments are used to toggle stripping on the left and right edges respectively. // </summary> - public static string strip_edges(this string instance, bool left = true, bool right = true) + public static string StripEdges(this string instance, bool left = true, bool right = true) { if (left) { @@ -890,7 +890,7 @@ namespace Godot // <summary> // Return part of the string from the position [code]from[/code], with length [code]len[/code]. // </summary> - public static string substr(this string instance, int from, int len) + public static string Substr(this string instance, int from, int len) { return instance.Substring(from, len); } @@ -898,7 +898,7 @@ namespace Godot // <summary> // Convert the String (which is a character array) to PoolByteArray (which is an array of bytes). The conversion is speeded up in comparison to to_utf8() with the assumption that all the characters the String contains are only ASCII characters. // </summary> - public static byte[] to_ascii(this string instance) + public static byte[] ToAscii(this string instance) { return Encoding.ASCII.GetBytes(instance); } @@ -906,7 +906,7 @@ namespace Godot // <summary> // Convert a string, containing a decimal number, into a [code]float[/code]. // </summary> - public static float to_float(this string instance) + public static float ToFloat(this string instance) { return float.Parse(instance); } @@ -914,7 +914,7 @@ namespace Godot // <summary> // Convert a string, containing an integer number, into an [code]int[/code]. // </summary> - public static int to_int(this string instance) + public static int ToInt(this string instance) { return int.Parse(instance); } @@ -922,7 +922,7 @@ namespace Godot // <summary> // Return the string converted to lowercase. // </summary> - public static string to_lower(this string instance) + public static string ToLower(this string instance) { return instance.ToLower(); } @@ -930,7 +930,7 @@ namespace Godot // <summary> // Return the string converted to uppercase. // </summary> - public static string to_upper(this string instance) + public static string ToUpper(this string instance) { return instance.ToUpper(); } @@ -938,7 +938,7 @@ namespace Godot // <summary> // Convert the String (which is an array of characters) to PoolByteArray (which is an array of bytes). The conversion is a bit slower than to_ascii(), but supports all UTF-8 characters. Therefore, you should prefer this function over to_ascii(). // </summary> - public static byte[] to_utf8(this string instance) + public static byte[] ToUtf8(this string instance) { return Encoding.UTF8.GetBytes(instance); } @@ -946,7 +946,7 @@ namespace Godot // <summary> // Return a copy of the string with special characters escaped using the XML standard. // </summary> - public static string xml_escape(this string instance) + public static string XmlEscape(this string instance) { return SecurityElement.Escape(instance); } @@ -954,7 +954,7 @@ namespace Godot // <summary> // Return a copy of the string with escaped characters replaced by their meanings according to the XML standard. // </summary> - public static string xml_unescape(this string instance) + public static string XmlUnescape(this string instance) { return SecurityElement.FromString(instance).Text; } diff --git a/modules/mono/glue/cs_files/Transform.cs b/modules/mono/glue/cs_files/Transform.cs index 5214100d36..9853721f98 100644 --- a/modules/mono/glue/cs_files/Transform.cs +++ b/modules/mono/glue/cs_files/Transform.cs @@ -24,7 +24,7 @@ namespace Godot public Transform LookingAt(Vector3 target, Vector3 up) { Transform t = this; - t.set_look_at(origin, target, up); + t.SetLookAt(origin, target, up); return t; } @@ -43,7 +43,7 @@ namespace Godot return new Transform(basis.Scaled(scale), origin * scale); } - public void set_look_at(Vector3 eye, Vector3 target, Vector3 up) + public void SetLookAt(Vector3 eye, Vector3 target, Vector3 up) { // Make rotation matrix // Z vector diff --git a/modules/mono/glue/cs_files/VERSION.txt b/modules/mono/glue/cs_files/VERSION.txt new file mode 100755 index 0000000000..0cfbf08886 --- /dev/null +++ b/modules/mono/glue/cs_files/VERSION.txt @@ -0,0 +1 @@ +2 diff --git a/modules/mono/godotsharp_defs.h b/modules/mono/godotsharp_defs.h index 4c26c3e6bd..f604464e8f 100644 --- a/modules/mono/godotsharp_defs.h +++ b/modules/mono/godotsharp_defs.h @@ -39,4 +39,7 @@ #define EDITOR_API_ASSEMBLY_NAME "GodotSharpEditor" #define EDITOR_TOOLS_ASSEMBLY_NAME "GodotSharpTools" +#define BINDINGS_CLASS_NATIVECALLS "NativeCalls" +#define BINDINGS_CLASS_NATIVECALLS_EDITOR "EditorNativeCalls" + #endif // GODOTSHARP_DEFS_H diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp index f5febd415b..0646580eaa 100644 --- a/modules/mono/mono_gd/gd_mono.cpp +++ b/modules/mono/mono_gd/gd_mono.cpp @@ -42,11 +42,15 @@ #include "project_settings.h" #include "../csharp_script.h" +#include "../godotsharp_dirs.h" #include "../utils/path_utils.h" +#include "gd_mono_class.h" +#include "gd_mono_marshal.h" #include "gd_mono_utils.h" #ifdef TOOLS_ENABLED #include "../editor/godotsharp_editor.h" +#include "main/main.h" #endif void gdmono_unhandled_exception_hook(MonoObject *exc, void *user_data) { @@ -70,7 +74,31 @@ void gdmono_MonoPrintCallback(const char *string, mono_bool is_stdout) { GDMono *GDMono::singleton = NULL; +namespace { + +void setup_runtime_main_args() { + CharString execpath = OS::get_singleton()->get_executable_path().utf8(); + + List<String> cmdline_args = OS::get_singleton()->get_cmdline_args(); + + List<CharString> cmdline_args_utf8; + Vector<char *> main_args; + main_args.resize(cmdline_args.size() + 1); + + main_args[0] = execpath.ptrw(); + + int i = 1; + for (List<String>::Element *E = cmdline_args.front(); E; E = E->next()) { + CharString &stored = cmdline_args_utf8.push_back(E->get().utf8())->get(); + main_args[i] = stored.ptrw(); + i++; + } + + mono_runtime_set_main_args(main_args.size(), main_args.ptrw()); +} + #ifdef DEBUG_ENABLED + static bool _wait_for_debugger_msecs(uint32_t p_msecs) { do { @@ -92,24 +120,7 @@ static bool _wait_for_debugger_msecs(uint32_t p_msecs) { return mono_is_debugger_attached(); } -#endif - -#ifdef TOOLS_ENABLED -// temporary workaround. should be provided from Main::setup/setup2 instead -bool _is_project_manager_requested() { - - List<String> cmdline_args = OS::get_singleton()->get_cmdline_args(); - for (List<String>::Element *E = cmdline_args.front(); E; E = E->next()) { - const String &arg = E->get(); - if (arg == "-p" || arg == "--project-manager") - return true; - } - - return false; -} -#endif -#ifdef DEBUG_ENABLED void gdmono_debug_init() { mono_debug_init(MONO_DEBUG_FORMAT_MONO); @@ -121,7 +132,7 @@ void gdmono_debug_init() { #ifdef TOOLS_ENABLED if (Engine::get_singleton()->is_editor_hint() || ProjectSettings::get_singleton()->get_resource_path().empty() || - _is_project_manager_requested()) { + Main::is_project_manager()) { return; } #endif @@ -136,8 +147,11 @@ void gdmono_debug_init() { }; mono_jit_parse_options(2, (char **)options); } + #endif +} // namespace + void GDMono::initialize() { ERR_FAIL_NULL(Engine::get_singleton()); @@ -190,6 +204,8 @@ void GDMono::initialize() { GDMonoUtils::set_main_thread(GDMonoUtils::get_current_thread()); + setup_runtime_main_args(); // Required for System.Environment.GetCommandLineArgs + runtime_initialized = true; OS::get_singleton()->print("Mono: Runtime initialized\n"); @@ -222,7 +238,46 @@ void GDMono::initialize() { _register_internal_calls(); // The following assemblies are not required at initialization - _load_all_script_assemblies(); +#ifndef MONO_GLUE_DISABLED + if (_load_api_assemblies()) { + if (!core_api_assembly_out_of_sync && !editor_api_assembly_out_of_sync && GDMonoUtils::mono_cache.godot_api_cache_updated) { + // Everything is fine with the api assemblies, load the project assembly + _load_project_assembly(); + } else { +#ifdef TOOLS_ENABLED + // The assembly was successfuly loaded, but the full api could not be cached. + // This is most likely an outdated assembly loaded because of an invalid version in the metadata, + // so we invalidate the version in the metadata and unload the script domain. + + if (core_api_assembly_out_of_sync) { + ERR_PRINT("The loaded Core API assembly is out of sync"); + metadata_set_api_assembly_invalidated(APIAssembly::API_CORE, true); + } else if (!GDMonoUtils::mono_cache.godot_api_cache_updated) { + ERR_PRINT("The loaded Core API assembly is in sync, but the cache update failed"); + metadata_set_api_assembly_invalidated(APIAssembly::API_CORE, true); + } + + if (editor_api_assembly_out_of_sync) { + ERR_PRINT("The loaded Editor API assembly is out of sync"); + metadata_set_api_assembly_invalidated(APIAssembly::API_EDITOR, true); + } + + OS::get_singleton()->print("Mono: Proceeding to unload scripts domain because of invalid API assemblies\n"); + + Error err = _unload_scripts_domain(); + if (err != OK) { + WARN_PRINT("Mono: Failed to unload scripts domain"); + } +#else + ERR_PRINT("The loaded API assembly is invalid"); + CRASH_NOW(); +#endif + } + } +#else + if (OS::get_singleton()->is_stdout_verbose()) + OS::get_singleton()->print("Mono: Glue disabled, ignoring script assemblies\n"); +#endif mono_install_unhandled_exception_hook(gdmono_unhandled_exception_hook, NULL); @@ -233,7 +288,11 @@ void GDMono::initialize() { namespace GodotSharpBindings { uint64_t get_core_api_hash(); +#ifdef TOOLS_ENABLED uint64_t get_editor_api_hash(); +#endif // TOOLS_ENABLED +uint32_t get_bindings_version(); +uint32_t get_cs_glue_version(); void register_generated_icalls(); } // namespace GodotSharpBindings @@ -285,43 +344,84 @@ GDMonoAssembly **GDMono::get_loaded_assembly(const String &p_name) { return assemblies[domain_id].getptr(p_name); } -bool GDMono::_load_assembly(const String &p_name, GDMonoAssembly **r_assembly) { +bool GDMono::load_assembly(const String &p_name, GDMonoAssembly **r_assembly, bool p_refonly) { + + CRASH_COND(!r_assembly); + + MonoAssemblyName *aname = mono_assembly_name_new(p_name.utf8()); + bool result = load_assembly(p_name, aname, r_assembly, p_refonly); + mono_assembly_name_free(aname); + mono_free(aname); + + return result; +} + +bool GDMono::load_assembly(const String &p_name, MonoAssemblyName *p_aname, GDMonoAssembly **r_assembly, bool p_refonly) { CRASH_COND(!r_assembly); if (OS::get_singleton()->is_stdout_verbose()) - OS::get_singleton()->print((String() + "Mono: Loading assembly " + p_name + "...\n").utf8()); + OS::get_singleton()->print((String() + "Mono: Loading assembly " + p_name + (p_refonly ? " (refonly)" : "") + "...\n").utf8()); MonoImageOpenStatus status = MONO_IMAGE_OK; - MonoAssemblyName *aname = mono_assembly_name_new(p_name.utf8()); - MonoAssembly *assembly = mono_assembly_load_full(aname, NULL, &status, false); - mono_assembly_name_free(aname); + MonoAssembly *assembly = mono_assembly_load_full(p_aname, NULL, &status, p_refonly); if (!assembly) return false; + ERR_FAIL_COND_V(status != MONO_IMAGE_OK, false); + uint32_t domain_id = mono_domain_get_id(mono_domain_get()); GDMonoAssembly **stored_assembly = assemblies[domain_id].getptr(p_name); - ERR_FAIL_COND_V(status != MONO_IMAGE_OK, false); ERR_FAIL_COND_V(stored_assembly == NULL, false); - ERR_FAIL_COND_V((*stored_assembly)->get_assembly() != assembly, false); + *r_assembly = *stored_assembly; if (OS::get_singleton()->is_stdout_verbose()) - OS::get_singleton()->print(String("Mono: Assembly " + p_name + " loaded from path: " + (*r_assembly)->get_path() + "\n").utf8()); + OS::get_singleton()->print(String("Mono: Assembly " + p_name + (p_refonly ? " (refonly)" : "") + " loaded from path: " + (*r_assembly)->get_path() + "\n").utf8()); return true; } +APIAssembly::Version APIAssembly::Version::get_from_loaded_assembly(GDMonoAssembly *p_api_assembly, APIAssembly::Type p_api_type) { + APIAssembly::Version api_assembly_version; + + const char *nativecalls_name = p_api_type == APIAssembly::API_CORE ? + BINDINGS_CLASS_NATIVECALLS : + BINDINGS_CLASS_NATIVECALLS_EDITOR; + + GDMonoClass *nativecalls_klass = p_api_assembly->get_class(BINDINGS_NAMESPACE, nativecalls_name); + + if (nativecalls_klass) { + GDMonoField *api_hash_field = nativecalls_klass->get_field("godot_api_hash"); + if (api_hash_field) + api_assembly_version.godot_api_hash = GDMonoMarshal::unbox<uint64_t>(api_hash_field->get_value(NULL)); + + GDMonoField *binds_ver_field = nativecalls_klass->get_field("bindings_version"); + if (binds_ver_field) + api_assembly_version.bindings_version = GDMonoMarshal::unbox<uint32_t>(binds_ver_field->get_value(NULL)); + + GDMonoField *cs_glue_ver_field = nativecalls_klass->get_field("cs_glue_version"); + if (cs_glue_ver_field) + api_assembly_version.cs_glue_version = GDMonoMarshal::unbox<uint32_t>(cs_glue_ver_field->get_value(NULL)); + } + + return api_assembly_version; +} + +String APIAssembly::to_string(APIAssembly::Type p_type) { + return p_type == APIAssembly::API_CORE ? "API_CORE" : "API_EDITOR"; +} + bool GDMono::_load_corlib_assembly() { if (corlib_assembly) return true; - bool success = _load_assembly("mscorlib", &corlib_assembly); + bool success = load_assembly("mscorlib", &corlib_assembly); if (success) GDMonoUtils::update_corlib_cache(); @@ -331,13 +431,25 @@ bool GDMono::_load_corlib_assembly() { bool GDMono::_load_core_api_assembly() { - if (api_assembly) + if (core_api_assembly) return true; - bool success = _load_assembly(API_ASSEMBLY_NAME, &api_assembly); +#ifdef TOOLS_ENABLED + if (metadata_is_api_assembly_invalidated(APIAssembly::API_CORE)) + return false; +#endif - if (success) + bool success = load_assembly(API_ASSEMBLY_NAME, &core_api_assembly); + + if (success) { +#ifndef MONO_GLUE_DISABLED + APIAssembly::Version api_assembly_ver = APIAssembly::Version::get_from_loaded_assembly(core_api_assembly, APIAssembly::API_CORE); + core_api_assembly_out_of_sync = GodotSharpBindings::get_core_api_hash() != api_assembly_ver.godot_api_hash || + GodotSharpBindings::get_bindings_version() != api_assembly_ver.bindings_version || + GodotSharpBindings::get_cs_glue_version() != api_assembly_ver.cs_glue_version; +#endif GDMonoUtils::update_godot_api_cache(); + } return success; } @@ -348,7 +460,23 @@ bool GDMono::_load_editor_api_assembly() { if (editor_api_assembly) return true; - return _load_assembly(EDITOR_API_ASSEMBLY_NAME, &editor_api_assembly); +#ifdef TOOLS_ENABLED + if (metadata_is_api_assembly_invalidated(APIAssembly::API_EDITOR)) + return false; +#endif + + bool success = load_assembly(EDITOR_API_ASSEMBLY_NAME, &editor_api_assembly); + + if (success) { +#ifndef MONO_GLUE_DISABLED + APIAssembly::Version api_assembly_ver = APIAssembly::Version::get_from_loaded_assembly(editor_api_assembly, APIAssembly::API_EDITOR); + editor_api_assembly_out_of_sync = GodotSharpBindings::get_editor_api_hash() != api_assembly_ver.godot_api_hash || + GodotSharpBindings::get_bindings_version() != api_assembly_ver.bindings_version || + GodotSharpBindings::get_cs_glue_version() != api_assembly_ver.cs_glue_version; +#endif + } + + return success; } #endif @@ -360,7 +488,7 @@ bool GDMono::_load_editor_tools_assembly() { _GDMONO_SCOPE_DOMAIN_(tools_domain) - return _load_assembly(EDITOR_TOOLS_ASSEMBLY_NAME, &editor_tools_assembly); + return load_assembly(EDITOR_TOOLS_ASSEMBLY_NAME, &editor_tools_assembly); } #endif @@ -374,17 +502,20 @@ bool GDMono::_load_project_assembly() { name = "UnnamedProject"; } - bool success = _load_assembly(name, &project_assembly); + bool success = load_assembly(name, &project_assembly); - if (success) + if (success) { mono_assembly_set_main(project_assembly->get_assembly()); + } else { + if (OS::get_singleton()->is_stdout_verbose()) + OS::get_singleton()->printerr("Mono: Failed to load project assembly\n"); + } return success; } -bool GDMono::_load_all_script_assemblies() { +bool GDMono::_load_api_assemblies() { -#ifndef MONO_GLUE_DISABLED if (!_load_core_api_assembly()) { if (OS::get_singleton()->is_stdout_verbose()) OS::get_singleton()->printerr("Mono: Failed to load Core API assembly\n"); @@ -399,20 +530,72 @@ bool GDMono::_load_all_script_assemblies() { #endif } - if (!_load_project_assembly()) { - if (OS::get_singleton()->is_stdout_verbose()) - OS::get_singleton()->printerr("Mono: Failed to load project assembly\n"); - return false; + return true; +} + +#ifdef TOOLS_ENABLED +String GDMono::_get_api_assembly_metadata_path() { + + return GodotSharpDirs::get_res_metadata_dir().plus_file("api_assemblies.cfg"); +} + +void GDMono::metadata_set_api_assembly_invalidated(APIAssembly::Type p_api_type, bool p_invalidated) { + + String section = APIAssembly::to_string(p_api_type); + String path = _get_api_assembly_metadata_path(); + + Ref<ConfigFile> metadata; + metadata.instance(); + metadata->load(path); + + metadata->set_value(section, "invalidated", p_invalidated); + + String assembly_path = GodotSharpDirs::get_res_assemblies_dir() + .plus_file(p_api_type == APIAssembly::API_CORE ? + API_ASSEMBLY_NAME ".dll" : + EDITOR_API_ASSEMBLY_NAME ".dll"); + + ERR_FAIL_COND(!FileAccess::exists(assembly_path)); + + uint64_t modified_time = FileAccess::get_modified_time(assembly_path); + + metadata->set_value(section, "invalidated_asm_modified_time", String::num_uint64(modified_time)); + + String dir = path.get_base_dir(); + if (!DirAccess::exists(dir)) { + DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); + ERR_FAIL_COND(!da); + Error err = da->make_dir_recursive(ProjectSettings::get_singleton()->globalize_path(dir)); + ERR_FAIL_COND(err != OK); } - return true; -#else - if (OS::get_singleton()->is_stdout_verbose()) - OS::get_singleton()->print("Mono: Glue disbled, ignoring script assemblies\n"); + Error save_err = metadata->save(path); + ERR_FAIL_COND(save_err != OK); +} - return true; -#endif +bool GDMono::metadata_is_api_assembly_invalidated(APIAssembly::Type p_api_type) { + + String section = APIAssembly::to_string(p_api_type); + + Ref<ConfigFile> metadata; + metadata.instance(); + metadata->load(_get_api_assembly_metadata_path()); + + String assembly_path = GodotSharpDirs::get_res_assemblies_dir() + .plus_file(p_api_type == APIAssembly::API_CORE ? + API_ASSEMBLY_NAME ".dll" : + EDITOR_API_ASSEMBLY_NAME ".dll"); + + if (!FileAccess::exists(assembly_path)) + return false; + + uint64_t modified_time = FileAccess::get_modified_time(assembly_path); + + uint64_t stored_modified_time = metadata->get_value(section, "invalidated_asm_modified_time", 0); + + return metadata->get_value(section, "invalidated", false) && modified_time <= stored_modified_time; } +#endif Error GDMono::_load_scripts_domain() { @@ -455,12 +638,15 @@ Error GDMono::_unload_scripts_domain() { _domain_assemblies_cleanup(mono_domain_get_id(scripts_domain)); - api_assembly = NULL; + core_api_assembly = NULL; project_assembly = NULL; #ifdef TOOLS_ENABLED editor_api_assembly = NULL; #endif + core_api_assembly_out_of_sync = false; + editor_api_assembly_out_of_sync = false; + MonoDomain *domain = scripts_domain; scripts_domain = NULL; @@ -515,16 +701,80 @@ Error GDMono::reload_scripts_domain() { return err; } - if (!_load_all_script_assemblies()) { - if (OS::get_singleton()->is_stdout_verbose()) - OS::get_singleton()->printerr("Mono: Failed to load script assemblies\n"); +#ifndef MONO_GLUE_DISABLED + if (!_load_api_assemblies()) { return ERR_CANT_OPEN; } + if (!core_api_assembly_out_of_sync && !editor_api_assembly_out_of_sync && GDMonoUtils::mono_cache.godot_api_cache_updated) { + // Everything is fine with the api assemblies, load the project assembly + _load_project_assembly(); + } else { + // The assembly was successfuly loaded, but the full api could not be cached. + // This is most likely an outdated assembly loaded because of an invalid version in the metadata, + // so we invalidate the version in the metadata and unload the script domain. + + if (core_api_assembly_out_of_sync) { + metadata_set_api_assembly_invalidated(APIAssembly::API_CORE, true); + } else if (!GDMonoUtils::mono_cache.godot_api_cache_updated) { + ERR_PRINT("Core API assembly is in sync, but the cache update failed"); + metadata_set_api_assembly_invalidated(APIAssembly::API_CORE, true); + } + + if (editor_api_assembly_out_of_sync) { + metadata_set_api_assembly_invalidated(APIAssembly::API_EDITOR, true); + } + + Error err = _unload_scripts_domain(); + if (err != OK) { + WARN_PRINT("Mono: Failed to unload scripts domain"); + } + + return ERR_CANT_RESOLVE; + } + + if (!_load_project_assembly()) + return ERR_CANT_OPEN; +#else + if (OS::get_singleton()->is_stdout_verbose()) + OS::get_singleton()->print("Mono: Glue disabled, ignoring script assemblies\n"); +#endif + return OK; } #endif +Error GDMono::finalize_and_unload_domain(MonoDomain *p_domain) { + + CRASH_COND(p_domain == NULL); + + String domain_name = mono_domain_get_friendly_name(p_domain); + + if (OS::get_singleton()->is_stdout_verbose()) { + OS::get_singleton()->print(String("Mono: Unloading domain `" + domain_name + "`...\n").utf8()); + } + + if (mono_domain_get() != root_domain) + mono_domain_set(root_domain, true); + + mono_gc_collect(mono_gc_max_generation()); + mono_domain_finalize(p_domain, 2000); + mono_gc_collect(mono_gc_max_generation()); + + _domain_assemblies_cleanup(mono_domain_get_id(p_domain)); + + MonoObject *ex = NULL; + mono_domain_try_unload(p_domain, &ex); + + if (ex) { + ERR_PRINTS("Exception thrown when unloading domain `" + domain_name + "`:"); + mono_print_unhandled_exception(ex); + return FAILED; + } + + return OK; +} + GDMonoClass *GDMono::get_class(MonoClass *p_raw_class) { MonoImage *image = mono_class_get_image(p_raw_class); @@ -576,8 +826,11 @@ GDMono::GDMono() { tools_domain = NULL; #endif + core_api_assembly_out_of_sync = false; + editor_api_assembly_out_of_sync = false; + corlib_assembly = NULL; - api_assembly = NULL; + core_api_assembly = NULL; project_assembly = NULL; #ifdef TOOLS_ENABLED editor_api_assembly = NULL; diff --git a/modules/mono/mono_gd/gd_mono.h b/modules/mono/mono_gd/gd_mono.h index 67251778c6..5e01152870 100644 --- a/modules/mono/mono_gd/gd_mono.h +++ b/modules/mono/mono_gd/gd_mono.h @@ -31,6 +31,8 @@ #ifndef GD_MONO_H #define GD_MONO_H +#include "core/io/config_file.h" + #include "../godotsharp_defs.h" #include "gd_mono_assembly.h" #include "gd_mono_log.h" @@ -39,6 +41,43 @@ #include "../utils/mono_reg_utils.h" #endif +namespace APIAssembly { +enum Type { + API_CORE, + API_EDITOR +}; + +struct Version { + uint64_t godot_api_hash; + uint32_t bindings_version; + uint32_t cs_glue_version; + + bool operator==(const Version &p_other) const { + return godot_api_hash == p_other.godot_api_hash && + bindings_version == p_other.bindings_version && + cs_glue_version == p_other.cs_glue_version; + } + + Version() : + godot_api_hash(0), + bindings_version(0), + cs_glue_version(0) { + } + + Version(uint64_t p_godot_api_hash, + uint32_t p_bindings_version, + uint32_t p_cs_glue_version) : + godot_api_hash(p_godot_api_hash), + bindings_version(p_bindings_version), + cs_glue_version(p_cs_glue_version) { + } + + static Version get_from_loaded_assembly(GDMonoAssembly *p_api_assembly, Type p_api_type); +}; + +String to_string(Type p_type); +} // namespace APIAssembly + #define SCRIPTS_DOMAIN GDMono::get_singleton()->get_scripts_domain() #ifdef TOOLS_ENABLED #define TOOLS_DOMAIN GDMono::get_singleton()->get_tools_domain() @@ -55,8 +94,11 @@ class GDMono { MonoDomain *tools_domain; #endif + bool core_api_assembly_out_of_sync; + bool editor_api_assembly_out_of_sync; + GDMonoAssembly *corlib_assembly; - GDMonoAssembly *api_assembly; + GDMonoAssembly *core_api_assembly; GDMonoAssembly *project_assembly; #ifdef TOOLS_ENABLED GDMonoAssembly *editor_api_assembly; @@ -75,7 +117,11 @@ class GDMono { #endif bool _load_project_assembly(); - bool _load_all_script_assemblies(); + bool _load_api_assemblies(); + +#ifdef TOOLS_ENABLED + String _get_api_assembly_metadata_path(); +#endif void _register_internal_calls(); @@ -94,8 +140,6 @@ class GDMono { void _initialize_and_check_api_hashes(); #endif - bool _load_assembly(const String &p_name, GDMonoAssembly **r_assembly); - GDMonoLog *gdmono_log; #ifdef WINDOWS_ENABLED @@ -113,6 +157,11 @@ public: #endif #endif +#ifdef TOOLS_ENABLED + void metadata_set_api_assembly_invalidated(APIAssembly::Type p_api_type, bool p_invalidated); + bool metadata_is_api_assembly_invalidated(APIAssembly::Type p_api_type); +#endif + static GDMono *get_singleton() { return singleton; } // Do not use these, unless you know what you're doing @@ -128,7 +177,7 @@ public: #endif _FORCE_INLINE_ GDMonoAssembly *get_corlib_assembly() const { return corlib_assembly; } - _FORCE_INLINE_ GDMonoAssembly *get_api_assembly() const { return api_assembly; } + _FORCE_INLINE_ GDMonoAssembly *get_core_api_assembly() const { return core_api_assembly; } _FORCE_INLINE_ GDMonoAssembly *get_project_assembly() const { return project_assembly; } #ifdef TOOLS_ENABLED _FORCE_INLINE_ GDMonoAssembly *get_editor_api_assembly() const { return editor_api_assembly; } @@ -145,6 +194,10 @@ public: Error reload_scripts_domain(); #endif + bool load_assembly(const String &p_name, GDMonoAssembly **r_assembly, bool p_refonly = false); + bool load_assembly(const String &p_name, MonoAssemblyName *p_aname, GDMonoAssembly **r_assembly, bool p_refonly = false); + Error finalize_and_unload_domain(MonoDomain *p_domain); + void initialize(); GDMono(); diff --git a/modules/mono/mono_gd/gd_mono_assembly.cpp b/modules/mono/mono_gd/gd_mono_assembly.cpp index ef39b8549d..d062d56dcf 100644 --- a/modules/mono/mono_gd/gd_mono_assembly.cpp +++ b/modules/mono/mono_gd/gd_mono_assembly.cpp @@ -43,7 +43,23 @@ bool GDMonoAssembly::no_search = false; Vector<String> GDMonoAssembly::search_dirs; -MonoAssembly *GDMonoAssembly::_search_hook(MonoAssemblyName *aname, void *user_data) { +MonoAssembly *GDMonoAssembly::assembly_search_hook(MonoAssemblyName *aname, void *user_data) { + return GDMonoAssembly::_search_hook(aname, user_data, false); +} + +MonoAssembly *GDMonoAssembly::assembly_refonly_search_hook(MonoAssemblyName *aname, void *user_data) { + return GDMonoAssembly::_search_hook(aname, user_data, true); +} + +MonoAssembly *GDMonoAssembly::assembly_preload_hook(MonoAssemblyName *aname, char **assemblies_path, void *user_data) { + return GDMonoAssembly::_preload_hook(aname, assemblies_path, user_data, false); +} + +MonoAssembly *GDMonoAssembly::assembly_refonly_preload_hook(MonoAssemblyName *aname, char **assemblies_path, void *user_data) { + return GDMonoAssembly::_preload_hook(aname, assemblies_path, user_data, true); +} + +MonoAssembly *GDMonoAssembly::_search_hook(MonoAssemblyName *aname, void *user_data, bool refonly) { (void)user_data; // UNUSED @@ -60,7 +76,7 @@ MonoAssembly *GDMonoAssembly::_search_hook(MonoAssemblyName *aname, void *user_d no_search = true; // Avoid the recursion madness String path; - MonoAssembly *res = NULL; + GDMonoAssembly *res = NULL; for (int i = 0; i < search_dirs.size(); i++) { const String &search_dir = search_dirs[i]; @@ -68,44 +84,49 @@ MonoAssembly *GDMonoAssembly::_search_hook(MonoAssemblyName *aname, void *user_d if (has_extension) { path = search_dir.plus_file(name); if (FileAccess::exists(path)) { - res = _load_assembly_from(name.get_basename(), path); - break; + res = _load_assembly_from(name.get_basename(), path, refonly); + if (res != NULL) + break; } } else { path = search_dir.plus_file(name + ".dll"); if (FileAccess::exists(path)) { - res = _load_assembly_from(name, path); - break; + res = _load_assembly_from(name, path, refonly); + if (res != NULL) + break; } path = search_dir.plus_file(name + ".exe"); if (FileAccess::exists(path)) { - res = _load_assembly_from(name, path); - break; + res = _load_assembly_from(name, path, refonly); + if (res != NULL) + break; } } } no_search = false; - return res; + return res ? res->get_assembly() : NULL; } -MonoAssembly *GDMonoAssembly::_preload_hook(MonoAssemblyName *aname, char **assemblies_path, void *user_data) { +MonoAssembly *GDMonoAssembly::_preload_hook(MonoAssemblyName *aname, char **assemblies_path, void *user_data, bool refonly) { (void)user_data; // UNUSED if (search_dirs.empty()) { -#ifdef TOOLS_DOMAIN search_dirs.push_back(GodotSharpDirs::get_res_temp_assemblies_dir()); -#endif search_dirs.push_back(GodotSharpDirs::get_res_assemblies_dir()); search_dirs.push_back(OS::get_singleton()->get_resource_dir()); search_dirs.push_back(OS::get_singleton()->get_executable_path().get_base_dir()); +#ifdef GD_MONO_EDITOR_ASSEMBLIES_DIR + search_dirs.push_back(OS::get_singleton()->get_executable_path().get_base_dir().plus_file(_MKSTR(GD_MONO_EDITOR_ASSEMBLIES_DIR)).simplify_path()); +#endif const char *rootdir = mono_assembly_getrootdir(); if (rootdir) { search_dirs.push_back(String(rootdir).plus_file("mono").plus_file("4.5")); + search_dirs.push_back(String(rootdir).plus_file("mono").plus_file("4.5").plus_file("Facades")); } if (assemblies_path) { @@ -121,10 +142,11 @@ MonoAssembly *GDMonoAssembly::_preload_hook(MonoAssemblyName *aname, char **asse if (has_extension ? name == "mscorlib.dll" : name == "mscorlib") { GDMonoAssembly **stored_assembly = GDMono::get_singleton()->get_loaded_assembly(has_extension ? name.get_basename() : name); - if (stored_assembly) return (*stored_assembly)->get_assembly(); + if (stored_assembly) + return (*stored_assembly)->get_assembly(); String path; - MonoAssembly *res = NULL; + GDMonoAssembly *res = NULL; for (int i = 0; i < search_dirs.size(); i++) { const String &search_dir = search_dirs[i]; @@ -132,53 +154,57 @@ MonoAssembly *GDMonoAssembly::_preload_hook(MonoAssemblyName *aname, char **asse if (has_extension) { path = search_dir.plus_file(name); if (FileAccess::exists(path)) { - res = _load_assembly_from(name.get_basename(), path); - break; + res = _load_assembly_from(name.get_basename(), path, refonly); + if (res != NULL) + break; } } else { path = search_dir.plus_file(name + ".dll"); if (FileAccess::exists(path)) { - res = _load_assembly_from(name, path); - break; + res = _load_assembly_from(name, path, refonly); + if (res != NULL) + break; } } } - if (res) return res; + return res ? res->get_assembly() : NULL; } return NULL; } -MonoAssembly *GDMonoAssembly::_load_assembly_from(const String &p_name, const String &p_path) { +GDMonoAssembly *GDMonoAssembly::_load_assembly_from(const String &p_name, const String &p_path, bool p_refonly) { GDMonoAssembly *assembly = memnew(GDMonoAssembly(p_name, p_path)); - MonoDomain *domain = mono_domain_get(); - - Error err = assembly->load(domain); + Error err = assembly->load(p_refonly); if (err != OK) { memdelete(assembly); ERR_FAIL_V(NULL); } + MonoDomain *domain = mono_domain_get(); GDMono::get_singleton()->add_assembly(domain ? mono_domain_get_id(domain) : 0, assembly); - return assembly->get_assembly(); + return assembly; } void GDMonoAssembly::initialize() { - // TODO refonly as well? - mono_install_assembly_preload_hook(&GDMonoAssembly::_preload_hook, NULL); - mono_install_assembly_search_hook(&GDMonoAssembly::_search_hook, NULL); + mono_install_assembly_search_hook(&assembly_search_hook, NULL); + mono_install_assembly_refonly_search_hook(&assembly_refonly_search_hook, NULL); + mono_install_assembly_preload_hook(&assembly_preload_hook, NULL); + mono_install_assembly_refonly_preload_hook(&assembly_refonly_preload_hook, NULL); } -Error GDMonoAssembly::load(MonoDomain *p_domain) { +Error GDMonoAssembly::load(bool p_refonly) { ERR_FAIL_COND_V(loaded, ERR_FILE_ALREADY_IN_USE); + refonly = p_refonly; + uint64_t last_modified_time = FileAccess::get_modified_time(path); Vector<uint8_t> data = FileAccess::get_file_as_array(path); @@ -186,14 +212,15 @@ Error GDMonoAssembly::load(MonoDomain *p_domain) { String image_filename(path); - MonoImageOpenStatus status; + MonoImageOpenStatus status = MONO_IMAGE_OK; image = mono_image_open_from_data_with_name( (char *)&data[0], data.size(), - true, &status, false, + true, &status, refonly, image_filename.utf8().get_data()); - ERR_FAIL_COND_V(status != MONO_IMAGE_OK || image == NULL, ERR_FILE_CANT_OPEN); + ERR_FAIL_COND_V(status != MONO_IMAGE_OK, ERR_FILE_CANT_OPEN); + ERR_FAIL_NULL_V(image, ERR_FILE_CANT_OPEN); #ifdef DEBUG_ENABLED String pdb_path(path + ".pdb"); @@ -213,15 +240,10 @@ no_pdb: #endif - assembly = mono_assembly_load_from_full(image, image_filename.utf8().get_data(), &status, false); + assembly = mono_assembly_load_from_full(image, image_filename.utf8().get_data(), &status, refonly); ERR_FAIL_COND_V(status != MONO_IMAGE_OK || assembly == NULL, ERR_FILE_CANT_OPEN); - if (p_domain && mono_image_get_entry_point(image)) { - // TODO should this be removed? do we want to call main? what other effects does this have? - mono_jit_exec(p_domain, assembly, 0, NULL); - } - loaded = true; modified_time = last_modified_time; @@ -373,12 +395,26 @@ GDMonoClass *GDMonoAssembly::get_object_derived_class(const StringName &p_class) return match; } +GDMonoAssembly *GDMonoAssembly::load_from(const String &p_name, const String &p_path, bool p_refonly) { + + GDMonoAssembly **loaded_asm = GDMono::get_singleton()->get_loaded_assembly(p_name); + if (loaded_asm) + return *loaded_asm; + + no_search = true; + GDMonoAssembly *res = _load_assembly_from(p_name, p_path, p_refonly); + no_search = false; + + return res; +} + GDMonoAssembly::GDMonoAssembly(const String &p_name, const String &p_path) { loaded = false; gdobject_class_cache_updated = false; name = p_name; path = p_path; + refonly = false; modified_time = 0; assembly = NULL; image = NULL; diff --git a/modules/mono/mono_gd/gd_mono_assembly.h b/modules/mono/mono_gd/gd_mono_assembly.h index 8a5fa19626..5cf744a5a2 100644 --- a/modules/mono/mono_gd/gd_mono_assembly.h +++ b/modules/mono/mono_gd/gd_mono_assembly.h @@ -71,6 +71,7 @@ class GDMonoAssembly { MonoAssembly *assembly; MonoImage *image; + bool refonly; bool loaded; String name; @@ -90,19 +91,25 @@ class GDMonoAssembly { static bool no_search; static Vector<String> search_dirs; - static MonoAssembly *_search_hook(MonoAssemblyName *aname, void *user_data); - static MonoAssembly *_preload_hook(MonoAssemblyName *aname, char **assemblies_path, void *user_data); + static MonoAssembly *assembly_search_hook(MonoAssemblyName *aname, void *user_data); + static MonoAssembly *assembly_refonly_search_hook(MonoAssemblyName *aname, void *user_data); + static MonoAssembly *assembly_preload_hook(MonoAssemblyName *aname, char **assemblies_path, void *user_data); + static MonoAssembly *assembly_refonly_preload_hook(MonoAssemblyName *aname, char **assemblies_path, void *user_data); - static MonoAssembly *_load_assembly_from(const String &p_name, const String &p_path); + static MonoAssembly *_search_hook(MonoAssemblyName *aname, void *user_data, bool refonly); + static MonoAssembly *_preload_hook(MonoAssemblyName *aname, char **assemblies_path, void *user_data, bool refonly); + + static GDMonoAssembly *_load_assembly_from(const String &p_name, const String &p_path, bool p_refonly); friend class GDMono; static void initialize(); public: - Error load(MonoDomain *p_domain); + Error load(bool p_refonly); Error wrapper_for_image(MonoImage *p_image); void unload(); + _FORCE_INLINE_ bool is_refonly() const { return refonly; } _FORCE_INLINE_ bool is_loaded() const { return loaded; } _FORCE_INLINE_ MonoImage *get_image() const { return image; } _FORCE_INLINE_ MonoAssembly *get_assembly() const { return assembly; } @@ -115,6 +122,8 @@ public: GDMonoClass *get_object_derived_class(const StringName &p_class); + static GDMonoAssembly *load_from(const String &p_name, const String &p_path, bool p_refonly); + GDMonoAssembly(const String &p_name, const String &p_path = String()); ~GDMonoAssembly(); }; diff --git a/modules/mono/mono_gd/gd_mono_marshal.h b/modules/mono/mono_gd/gd_mono_marshal.h index 6572408ab5..4e28622adb 100644 --- a/modules/mono/mono_gd/gd_mono_marshal.h +++ b/modules/mono/mono_gd/gd_mono_marshal.h @@ -195,13 +195,13 @@ Dictionary mono_object_to_Dictionary(MonoObject *p_dict); // Transform #define MARSHALLED_OUT_Transform(m_in, m_out) real_t m_out[12] = { \ - m_in.basis[0].x, m_in.basis[0].y, m_in.basis[0].z, \ - m_in.basis[1].x, m_in.basis[1].y, m_in.basis[1].z, \ - m_in.basis[2].x, m_in.basis[2].y, m_in.basis[2].z, \ + m_in.basis[0].x, m_in.basis[1].x, m_in.basis[2].x, \ + m_in.basis[0].y, m_in.basis[1].y, m_in.basis[2].y, \ + m_in.basis[0].z, m_in.basis[1].z, m_in.basis[2].z, \ m_in.origin.x, m_in.origin.y, m_in.origin.z \ }; #define MARSHALLED_IN_Transform(m_in, m_out) Transform m_out( \ - Basis(m_in[0], m_in[1], m_in[2], m_in[3], m_in[4], m_in[5], m_in[6], m_in[7], m_in[8]), \ + Basis(m_in[0], m_in[3], m_in[6], m_in[1], m_in[4], m_in[7], m_in[2], m_in[5], m_in[8]), \ Vector3(m_in[9], m_in[10], m_in[11])); // AABB diff --git a/modules/mono/mono_gd/gd_mono_method.cpp b/modules/mono/mono_gd/gd_mono_method.cpp index df0985f6ac..ad52904945 100644 --- a/modules/mono/mono_gd/gd_mono_method.cpp +++ b/modules/mono/mono_gd/gd_mono_method.cpp @@ -230,10 +230,13 @@ String GDMonoMethod::get_signature_desc(bool p_namespaces) const { } void GDMonoMethod::get_parameter_names(Vector<StringName> &names) const { - const char *_names[params_count]; - mono_method_get_param_names(mono_method, _names); - for (int i = 0; i < params_count; ++i) { - names.push_back(StringName(_names[i])); + if (params_count > 0) { + const char **_names = memnew_arr(const char *, params_count); + mono_method_get_param_names(mono_method, _names); + for (int i = 0; i < params_count; ++i) { + names.push_back(StringName(_names[i])); + } + memdelete_arr(_names); } } diff --git a/modules/mono/mono_gd/gd_mono_utils.cpp b/modules/mono/mono_gd/gd_mono_utils.cpp index 42e307cf08..db136a1313 100644 --- a/modules/mono/mono_gd/gd_mono_utils.cpp +++ b/modules/mono/mono_gd/gd_mono_utils.cpp @@ -143,7 +143,7 @@ void MonoCache::cleanup() { godot_api_cache_updated = false; } -#define GODOT_API_CLASS(m_class) (GDMono::get_singleton()->get_api_assembly()->get_class(BINDINGS_NAMESPACE, #m_class)) +#define GODOT_API_CLASS(m_class) (GDMono::get_singleton()->get_core_api_assembly()->get_class(BINDINGS_NAMESPACE, #m_class)) void update_corlib_cache() { @@ -245,7 +245,7 @@ void update_godot_api_cache() { mono_runtime_object_init(task_scheduler); mono_cache.task_scheduler_handle = MonoGCHandle::create_strong(task_scheduler); - mono_cache.corlib_cache_updated = true; + mono_cache.godot_api_cache_updated = true; } void clear_cache() { @@ -305,7 +305,7 @@ GDMonoClass *type_get_proxy_class(const StringName &p_type) { if (class_name[0] == '_') class_name = class_name.substr(1, class_name.length()); - GDMonoClass *klass = GDMono::get_singleton()->get_api_assembly()->get_class(BINDINGS_NAMESPACE, class_name); + GDMonoClass *klass = GDMono::get_singleton()->get_core_api_assembly()->get_class(BINDINGS_NAMESPACE, class_name); #ifdef TOOLS_ENABLED if (!klass) { @@ -321,7 +321,7 @@ GDMonoClass *get_class_native_base(GDMonoClass *p_class) { do { const GDMonoAssembly *assembly = klass->get_assembly(); - if (assembly == GDMono::get_singleton()->get_api_assembly()) + if (assembly == GDMono::get_singleton()->get_core_api_assembly()) return klass; #ifdef TOOLS_ENABLED if (assembly == GDMono::get_singleton()->get_editor_api_assembly()) @@ -420,37 +420,56 @@ void print_unhandled_exception(MonoObject *p_exc, bool p_recursion_caution) { if (!ScriptDebugger::get_singleton()) return; - GDMonoClass *st_klass = CACHED_CLASS(System_Diagnostics_StackTrace); - MonoObject *stack_trace = mono_object_new(mono_domain_get(), st_klass->get_mono_ptr()); + ScriptLanguage::StackInfo separator; + separator.file = ""; + separator.func = "--- " + RTR("End of inner exception stack trace") + " ---"; + separator.line = 0; + + Vector<ScriptLanguage::StackInfo> si; + String exc_msg = ""; + + while (p_exc != NULL) { + GDMonoClass *st_klass = CACHED_CLASS(System_Diagnostics_StackTrace); + MonoObject *stack_trace = mono_object_new(mono_domain_get(), st_klass->get_mono_ptr()); - MonoBoolean need_file_info = true; - void *ctor_args[2] = { p_exc, &need_file_info }; + MonoBoolean need_file_info = true; + void *ctor_args[2] = { p_exc, &need_file_info }; - MonoObject *unexpected_exc = NULL; - CACHED_METHOD(System_Diagnostics_StackTrace, ctor_Exception_bool)->invoke_raw(stack_trace, ctor_args, &unexpected_exc); + MonoObject *unexpected_exc = NULL; + CACHED_METHOD(System_Diagnostics_StackTrace, ctor_Exception_bool)->invoke_raw(stack_trace, ctor_args, &unexpected_exc); - if (unexpected_exc != NULL) { - mono_print_unhandled_exception(unexpected_exc); + if (unexpected_exc != NULL) { + mono_print_unhandled_exception(unexpected_exc); - if (p_recursion_caution) { - // Called from CSharpLanguage::get_current_stack_info, - // so printing an error here could result in endless recursion - OS::get_singleton()->printerr("Mono: Method GDMonoUtils::print_unhandled_exception failed"); - return; - } else { - ERR_FAIL(); + if (p_recursion_caution) { + // Called from CSharpLanguage::get_current_stack_info, + // so printing an error here could result in endless recursion + OS::get_singleton()->printerr("Mono: Method GDMonoUtils::print_unhandled_exception failed"); + return; + } else { + ERR_FAIL(); + } } - } - Vector<ScriptLanguage::StackInfo> si; - if (stack_trace != NULL && !p_recursion_caution) - si = CSharpLanguage::get_singleton()->stack_trace_get_info(stack_trace); + Vector<ScriptLanguage::StackInfo> _si; + if (stack_trace != NULL && !p_recursion_caution) { + _si = CSharpLanguage::get_singleton()->stack_trace_get_info(stack_trace); + for (int i = _si.size() - 1; i >= 0; i--) + si.insert(0, _si[i]); + } + + exc_msg += (exc_msg.length() > 0 ? " ---> " : "") + GDMonoUtils::get_exception_name_and_message(p_exc); + + GDMonoProperty *p_prop = GDMono::get_singleton()->get_class(mono_object_get_class(p_exc))->get_property("InnerException"); + p_exc = p_prop != NULL ? p_prop->get_value(p_exc) : NULL; + if (p_exc != NULL) + si.insert(0, separator); + } String file = si.size() ? si[0].file : __FILE__; String func = si.size() ? si[0].func : FUNCTION_STR; int line = si.size() ? si[0].line : __LINE__; String error_msg = "Unhandled exception"; - String exc_msg = GDMonoUtils::get_exception_name_and_message(p_exc); ScriptDebugger::get_singleton()->send_error(func, file, line, error_msg, exc_msg, ERR_HANDLER_ERROR, si); #endif diff --git a/modules/regex/doc_classes/RegEx.xml b/modules/regex/doc_classes/RegEx.xml index 2cf80acd28..75e8903ff8 100644 --- a/modules/regex/doc_classes/RegEx.xml +++ b/modules/regex/doc_classes/RegEx.xml @@ -1,17 +1,17 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="RegEx" inherits="Reference" category="Core" version="3.0-stable"> +<class name="RegEx" inherits="Reference" category="Core" version="3.1"> <brief_description> Class for searching text for patterns using regular expressions. </brief_description> <description> - Regular Expression (or regex) is a compact programming language that can be used to recognise strings that follow a specific pattern, such as URLs, email addresses, complete sentences, etc. For instance, a regex of [code]ab[0-9][/code] would find any string that is [code]ab[/code] followed by any number from [code]0[/code] to [code]9[/code]. For a more in-depth look, you can easily find various tutorials and detailed explainations on the Internet. + Regular Expression (or regex) is a compact programming language that can be used to recognise strings that follow a specific pattern, such as URLs, email addresses, complete sentences, etc. For instance, a regex of [code]ab[0-9][/code] would find any string that is [code]ab[/code] followed by any number from [code]0[/code] to [code]9[/code]. For a more in-depth look, you can easily find various tutorials and detailed explanations on the Internet. To begin, the RegEx object needs to be compiled with the search pattern using [method compile] before it can be used. [codeblock] var regex = RegEx.new() regex.compile("\\w-(\\d+)") [/codeblock] The search pattern must be escaped first for gdscript before it is escaped for the expression. For example, [code]compile("\\d+")[/code] would be read by RegEx as [code]\d+[/code]. Similarly, [code]compile("\"(?:\\\\.|[^\"])*\"")[/code] would be read as [code]"(?:\\.|[^"])*"[/code] - Using [method search] you can find the pattern within the given text. If a pattern is found, [RegExMatch] is returned and you can retrieve details of the results using fuctions such as [method RegExMatch.get_string] and [method RegExMatch.get_start]. + Using [method search] you can find the pattern within the given text. If a pattern is found, [RegExMatch] is returned and you can retrieve details of the results using functions such as [method RegExMatch.get_string] and [method RegExMatch.get_start]. [codeblock] var regex = RegEx.new() regex.compile("\\w-(\\d+)") diff --git a/modules/regex/doc_classes/RegExMatch.xml b/modules/regex/doc_classes/RegExMatch.xml index 9eba0f738b..3d070d2786 100644 --- a/modules/regex/doc_classes/RegExMatch.xml +++ b/modules/regex/doc_classes/RegExMatch.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="RegExMatch" inherits="Reference" category="Core" version="3.0-stable"> +<class name="RegExMatch" inherits="Reference" category="Core" version="3.1"> <brief_description> Contains the results of a regex search. </brief_description> diff --git a/modules/stb_vorbis/doc_classes/AudioStreamOGGVorbis.xml b/modules/stb_vorbis/doc_classes/AudioStreamOGGVorbis.xml index 827e947a79..ac95a7197f 100644 --- a/modules/stb_vorbis/doc_classes/AudioStreamOGGVorbis.xml +++ b/modules/stb_vorbis/doc_classes/AudioStreamOGGVorbis.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="AudioStreamOGGVorbis" inherits="AudioStream" category="Core" version="3.0-stable"> +<class name="AudioStreamOGGVorbis" inherits="AudioStream" category="Core" version="3.1"> <brief_description> OGG Vorbis audio stream driver. </brief_description> diff --git a/modules/stb_vorbis/doc_classes/ResourceImporterOGGVorbis.xml b/modules/stb_vorbis/doc_classes/ResourceImporterOGGVorbis.xml index 9a095c3ddd..018f4734ec 100644 --- a/modules/stb_vorbis/doc_classes/ResourceImporterOGGVorbis.xml +++ b/modules/stb_vorbis/doc_classes/ResourceImporterOGGVorbis.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="ResourceImporterOGGVorbis" inherits="ResourceImporter" category="Core" version="3.0-stable"> +<class name="ResourceImporterOGGVorbis" inherits="ResourceImporter" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/stb_vorbis/resource_importer_ogg_vorbis.cpp b/modules/stb_vorbis/resource_importer_ogg_vorbis.cpp index 16ebfa2832..c8acdb689a 100644 --- a/modules/stb_vorbis/resource_importer_ogg_vorbis.cpp +++ b/modules/stb_vorbis/resource_importer_ogg_vorbis.cpp @@ -100,6 +100,7 @@ Error ResourceImporterOGGVorbis::import(const String &p_source_file, const Strin ogg_stream.instance(); ogg_stream->set_data(data); + ERR_FAIL_COND_V(!ogg_stream->get_data().size(), ERR_FILE_CORRUPT); ogg_stream->set_loop(loop); ogg_stream->set_loop_offset(loop_offset); diff --git a/modules/theora/doc_classes/ResourceImporterTheora.xml b/modules/theora/doc_classes/ResourceImporterTheora.xml index a280d767c3..5fc40a6eba 100644 --- a/modules/theora/doc_classes/ResourceImporterTheora.xml +++ b/modules/theora/doc_classes/ResourceImporterTheora.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="ResourceImporterTheora" inherits="ResourceImporter" category="Core" version="3.0-stable"> +<class name="ResourceImporterTheora" inherits="ResourceImporter" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/theora/doc_classes/VideoStreamTheora.xml b/modules/theora/doc_classes/VideoStreamTheora.xml index 9da3dc0d02..e7c4727332 100644 --- a/modules/theora/doc_classes/VideoStreamTheora.xml +++ b/modules/theora/doc_classes/VideoStreamTheora.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VideoStreamTheora" inherits="VideoStream" category="Core" version="3.0-stable"> +<class name="VideoStreamTheora" inherits="VideoStream" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/visual_script/doc_classes/VisualScript.xml b/modules/visual_script/doc_classes/VisualScript.xml index a6a43f31b8..dab186fb57 100644 --- a/modules/visual_script/doc_classes/VisualScript.xml +++ b/modules/visual_script/doc_classes/VisualScript.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScript" inherits="Script" category="Core" version="3.0-stable"> +<class name="VisualScript" inherits="Script" category="Core" version="3.1"> <brief_description> A script implemented in the Visual Script programming environment. </brief_description> diff --git a/modules/visual_script/doc_classes/VisualScriptBasicTypeConstant.xml b/modules/visual_script/doc_classes/VisualScriptBasicTypeConstant.xml index d63a6ad524..793291eca2 100644 --- a/modules/visual_script/doc_classes/VisualScriptBasicTypeConstant.xml +++ b/modules/visual_script/doc_classes/VisualScriptBasicTypeConstant.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptBasicTypeConstant" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptBasicTypeConstant" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> A Visual Script node representing a constant from the base types. </brief_description> diff --git a/modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml b/modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml index da4db29086..0929b227d0 100644 --- a/modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml +++ b/modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptBuiltinFunc" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptBuiltinFunc" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> A Visual Script node used to call built-in functions. </brief_description> diff --git a/modules/visual_script/doc_classes/VisualScriptClassConstant.xml b/modules/visual_script/doc_classes/VisualScriptClassConstant.xml index 189a6f6ad8..2e3a5b33c0 100644 --- a/modules/visual_script/doc_classes/VisualScriptClassConstant.xml +++ b/modules/visual_script/doc_classes/VisualScriptClassConstant.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptClassConstant" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptClassConstant" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> Gets a constant from a given class. </brief_description> diff --git a/modules/visual_script/doc_classes/VisualScriptComment.xml b/modules/visual_script/doc_classes/VisualScriptComment.xml index 5462c379ad..a4a890ea8a 100644 --- a/modules/visual_script/doc_classes/VisualScriptComment.xml +++ b/modules/visual_script/doc_classes/VisualScriptComment.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptComment" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptComment" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> A Visual Script node used to annotate the script. </brief_description> diff --git a/modules/visual_script/doc_classes/VisualScriptCondition.xml b/modules/visual_script/doc_classes/VisualScriptCondition.xml index bb70a17357..353898c93a 100644 --- a/modules/visual_script/doc_classes/VisualScriptCondition.xml +++ b/modules/visual_script/doc_classes/VisualScriptCondition.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptCondition" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptCondition" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> A Visual Script node which branches the flow. </brief_description> diff --git a/modules/visual_script/doc_classes/VisualScriptConstant.xml b/modules/visual_script/doc_classes/VisualScriptConstant.xml index e2ccb50bfd..ed633c4135 100644 --- a/modules/visual_script/doc_classes/VisualScriptConstant.xml +++ b/modules/visual_script/doc_classes/VisualScriptConstant.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptConstant" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptConstant" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> Gets a contant's value. </brief_description> diff --git a/modules/visual_script/doc_classes/VisualScriptConstructor.xml b/modules/visual_script/doc_classes/VisualScriptConstructor.xml index da6779b79d..14c44c6970 100644 --- a/modules/visual_script/doc_classes/VisualScriptConstructor.xml +++ b/modules/visual_script/doc_classes/VisualScriptConstructor.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptConstructor" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptConstructor" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> A Visual Script node which calls a base type constructor. </brief_description> diff --git a/modules/visual_script/doc_classes/VisualScriptCustomNode.xml b/modules/visual_script/doc_classes/VisualScriptCustomNode.xml index 33d2f1437a..b8e77a1b0f 100644 --- a/modules/visual_script/doc_classes/VisualScriptCustomNode.xml +++ b/modules/visual_script/doc_classes/VisualScriptCustomNode.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptCustomNode" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptCustomNode" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> A scripted Visual Script node. </brief_description> diff --git a/modules/visual_script/doc_classes/VisualScriptDeconstruct.xml b/modules/visual_script/doc_classes/VisualScriptDeconstruct.xml index 09fcba4314..d3158df357 100644 --- a/modules/visual_script/doc_classes/VisualScriptDeconstruct.xml +++ b/modules/visual_script/doc_classes/VisualScriptDeconstruct.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptDeconstruct" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptDeconstruct" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> A Visual Script node which deconstructs a base type instance into its parts. </brief_description> diff --git a/modules/visual_script/doc_classes/VisualScriptEditor.xml b/modules/visual_script/doc_classes/VisualScriptEditor.xml index 8e26758a31..fc49cfc07b 100644 --- a/modules/visual_script/doc_classes/VisualScriptEditor.xml +++ b/modules/visual_script/doc_classes/VisualScriptEditor.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptEditor" inherits="Object" category="Core" version="3.0-stable"> +<class name="VisualScriptEditor" inherits="Object" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/visual_script/doc_classes/VisualScriptEmitSignal.xml b/modules/visual_script/doc_classes/VisualScriptEmitSignal.xml index 30f96011d4..4bb05525bd 100644 --- a/modules/visual_script/doc_classes/VisualScriptEmitSignal.xml +++ b/modules/visual_script/doc_classes/VisualScriptEmitSignal.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptEmitSignal" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptEmitSignal" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> Emits a specified signal. </brief_description> diff --git a/modules/visual_script/doc_classes/VisualScriptEngineSingleton.xml b/modules/visual_script/doc_classes/VisualScriptEngineSingleton.xml index 0dc0cdf5eb..93d7ce3516 100644 --- a/modules/visual_script/doc_classes/VisualScriptEngineSingleton.xml +++ b/modules/visual_script/doc_classes/VisualScriptEngineSingleton.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptEngineSingleton" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptEngineSingleton" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> A Visual Script node returning a singleton from [@GlobalScope] </brief_description> diff --git a/modules/visual_script/doc_classes/VisualScriptExpression.xml b/modules/visual_script/doc_classes/VisualScriptExpression.xml index 91f55edb2b..343e83cb55 100644 --- a/modules/visual_script/doc_classes/VisualScriptExpression.xml +++ b/modules/visual_script/doc_classes/VisualScriptExpression.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptExpression" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptExpression" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/visual_script/doc_classes/VisualScriptFunction.xml b/modules/visual_script/doc_classes/VisualScriptFunction.xml index bd59d739ea..ec8e955cf7 100644 --- a/modules/visual_script/doc_classes/VisualScriptFunction.xml +++ b/modules/visual_script/doc_classes/VisualScriptFunction.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptFunction" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptFunction" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/visual_script/doc_classes/VisualScriptFunctionCall.xml b/modules/visual_script/doc_classes/VisualScriptFunctionCall.xml index e2b732a250..f6116cf539 100644 --- a/modules/visual_script/doc_classes/VisualScriptFunctionCall.xml +++ b/modules/visual_script/doc_classes/VisualScriptFunctionCall.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptFunctionCall" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptFunctionCall" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/visual_script/doc_classes/VisualScriptFunctionState.xml b/modules/visual_script/doc_classes/VisualScriptFunctionState.xml index 614176498a..c75dd0cdbc 100644 --- a/modules/visual_script/doc_classes/VisualScriptFunctionState.xml +++ b/modules/visual_script/doc_classes/VisualScriptFunctionState.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptFunctionState" inherits="Reference" category="Core" version="3.0-stable"> +<class name="VisualScriptFunctionState" inherits="Reference" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/visual_script/doc_classes/VisualScriptGlobalConstant.xml b/modules/visual_script/doc_classes/VisualScriptGlobalConstant.xml index a36f7809c2..9d43204f02 100644 --- a/modules/visual_script/doc_classes/VisualScriptGlobalConstant.xml +++ b/modules/visual_script/doc_classes/VisualScriptGlobalConstant.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptGlobalConstant" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptGlobalConstant" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/visual_script/doc_classes/VisualScriptIndexGet.xml b/modules/visual_script/doc_classes/VisualScriptIndexGet.xml index b2d0a194e0..73c1f47e1a 100644 --- a/modules/visual_script/doc_classes/VisualScriptIndexGet.xml +++ b/modules/visual_script/doc_classes/VisualScriptIndexGet.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptIndexGet" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptIndexGet" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/visual_script/doc_classes/VisualScriptIndexSet.xml b/modules/visual_script/doc_classes/VisualScriptIndexSet.xml index 7ad200afa4..652c29a9ac 100644 --- a/modules/visual_script/doc_classes/VisualScriptIndexSet.xml +++ b/modules/visual_script/doc_classes/VisualScriptIndexSet.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptIndexSet" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptIndexSet" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/visual_script/doc_classes/VisualScriptInputAction.xml b/modules/visual_script/doc_classes/VisualScriptInputAction.xml index 45c493887b..ab4c23012b 100644 --- a/modules/visual_script/doc_classes/VisualScriptInputAction.xml +++ b/modules/visual_script/doc_classes/VisualScriptInputAction.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptInputAction" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptInputAction" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/visual_script/doc_classes/VisualScriptIterator.xml b/modules/visual_script/doc_classes/VisualScriptIterator.xml index 28e8a66182..7090621bd7 100644 --- a/modules/visual_script/doc_classes/VisualScriptIterator.xml +++ b/modules/visual_script/doc_classes/VisualScriptIterator.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptIterator" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptIterator" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> Steps through items in a given input. </brief_description> diff --git a/modules/visual_script/doc_classes/VisualScriptLocalVar.xml b/modules/visual_script/doc_classes/VisualScriptLocalVar.xml index 66faf448cb..5c8ee6453c 100644 --- a/modules/visual_script/doc_classes/VisualScriptLocalVar.xml +++ b/modules/visual_script/doc_classes/VisualScriptLocalVar.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptLocalVar" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptLocalVar" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> Gets a local variable's value. </brief_description> diff --git a/modules/visual_script/doc_classes/VisualScriptLocalVarSet.xml b/modules/visual_script/doc_classes/VisualScriptLocalVarSet.xml index 8a816e5dd7..f2e6c48907 100644 --- a/modules/visual_script/doc_classes/VisualScriptLocalVarSet.xml +++ b/modules/visual_script/doc_classes/VisualScriptLocalVarSet.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptLocalVarSet" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptLocalVarSet" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> Changes a local variable's value. </brief_description> diff --git a/modules/visual_script/doc_classes/VisualScriptMathConstant.xml b/modules/visual_script/doc_classes/VisualScriptMathConstant.xml index 45fa471c41..df439f8794 100644 --- a/modules/visual_script/doc_classes/VisualScriptMathConstant.xml +++ b/modules/visual_script/doc_classes/VisualScriptMathConstant.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptMathConstant" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptMathConstant" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> Commonly used mathematical constants. </brief_description> diff --git a/modules/visual_script/doc_classes/VisualScriptNode.xml b/modules/visual_script/doc_classes/VisualScriptNode.xml index e9d1cd949f..941a0cd91a 100644 --- a/modules/visual_script/doc_classes/VisualScriptNode.xml +++ b/modules/visual_script/doc_classes/VisualScriptNode.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptNode" inherits="Resource" category="Core" version="3.0-stable"> +<class name="VisualScriptNode" inherits="Resource" category="Core" version="3.1"> <brief_description> A node which is part of a [VisualScript]. </brief_description> diff --git a/modules/visual_script/doc_classes/VisualScriptOperator.xml b/modules/visual_script/doc_classes/VisualScriptOperator.xml index 4538bd3c78..e60d50c977 100644 --- a/modules/visual_script/doc_classes/VisualScriptOperator.xml +++ b/modules/visual_script/doc_classes/VisualScriptOperator.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptOperator" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptOperator" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/visual_script/doc_classes/VisualScriptPreload.xml b/modules/visual_script/doc_classes/VisualScriptPreload.xml index 3dae0e4b81..5a2886ccac 100644 --- a/modules/visual_script/doc_classes/VisualScriptPreload.xml +++ b/modules/visual_script/doc_classes/VisualScriptPreload.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptPreload" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptPreload" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> Creates a new [Resource] or loads one from the filesystem. </brief_description> diff --git a/modules/visual_script/doc_classes/VisualScriptPropertyGet.xml b/modules/visual_script/doc_classes/VisualScriptPropertyGet.xml index 7555c83960..60cc8fdd4f 100644 --- a/modules/visual_script/doc_classes/VisualScriptPropertyGet.xml +++ b/modules/visual_script/doc_classes/VisualScriptPropertyGet.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptPropertyGet" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptPropertyGet" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/visual_script/doc_classes/VisualScriptPropertySet.xml b/modules/visual_script/doc_classes/VisualScriptPropertySet.xml index dc6a9efd83..8f29e9d152 100644 --- a/modules/visual_script/doc_classes/VisualScriptPropertySet.xml +++ b/modules/visual_script/doc_classes/VisualScriptPropertySet.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptPropertySet" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptPropertySet" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/visual_script/doc_classes/VisualScriptResourcePath.xml b/modules/visual_script/doc_classes/VisualScriptResourcePath.xml index 3789626ed0..f6300e03f0 100644 --- a/modules/visual_script/doc_classes/VisualScriptResourcePath.xml +++ b/modules/visual_script/doc_classes/VisualScriptResourcePath.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptResourcePath" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptResourcePath" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/visual_script/doc_classes/VisualScriptReturn.xml b/modules/visual_script/doc_classes/VisualScriptReturn.xml index 1172b7555b..6095520eff 100644 --- a/modules/visual_script/doc_classes/VisualScriptReturn.xml +++ b/modules/visual_script/doc_classes/VisualScriptReturn.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptReturn" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptReturn" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> Exits a function and returns an optional value. </brief_description> diff --git a/modules/visual_script/doc_classes/VisualScriptSceneNode.xml b/modules/visual_script/doc_classes/VisualScriptSceneNode.xml index 4c6181e040..7704eaba04 100644 --- a/modules/visual_script/doc_classes/VisualScriptSceneNode.xml +++ b/modules/visual_script/doc_classes/VisualScriptSceneNode.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptSceneNode" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptSceneNode" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> Node reference. </brief_description> diff --git a/modules/visual_script/doc_classes/VisualScriptSceneTree.xml b/modules/visual_script/doc_classes/VisualScriptSceneTree.xml index 68cc0d0b55..2c2af9262d 100644 --- a/modules/visual_script/doc_classes/VisualScriptSceneTree.xml +++ b/modules/visual_script/doc_classes/VisualScriptSceneTree.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptSceneTree" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptSceneTree" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/visual_script/doc_classes/VisualScriptSelect.xml b/modules/visual_script/doc_classes/VisualScriptSelect.xml index 017efdb07a..0731fc77e1 100644 --- a/modules/visual_script/doc_classes/VisualScriptSelect.xml +++ b/modules/visual_script/doc_classes/VisualScriptSelect.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptSelect" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptSelect" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> Chooses between two input values. </brief_description> diff --git a/modules/visual_script/doc_classes/VisualScriptSelf.xml b/modules/visual_script/doc_classes/VisualScriptSelf.xml index e9b480bbae..61a73e104c 100644 --- a/modules/visual_script/doc_classes/VisualScriptSelf.xml +++ b/modules/visual_script/doc_classes/VisualScriptSelf.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptSelf" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptSelf" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> Outputs a reference to the current instance. </brief_description> diff --git a/modules/visual_script/doc_classes/VisualScriptSequence.xml b/modules/visual_script/doc_classes/VisualScriptSequence.xml index be793ae36e..c71e068045 100644 --- a/modules/visual_script/doc_classes/VisualScriptSequence.xml +++ b/modules/visual_script/doc_classes/VisualScriptSequence.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptSequence" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptSequence" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> Executes a series of Sequence ports. </brief_description> diff --git a/modules/visual_script/doc_classes/VisualScriptSubCall.xml b/modules/visual_script/doc_classes/VisualScriptSubCall.xml index 85db63b78a..46aeebab9c 100644 --- a/modules/visual_script/doc_classes/VisualScriptSubCall.xml +++ b/modules/visual_script/doc_classes/VisualScriptSubCall.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptSubCall" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptSubCall" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/visual_script/doc_classes/VisualScriptSwitch.xml b/modules/visual_script/doc_classes/VisualScriptSwitch.xml index ec7565b31a..a00811a29b 100644 --- a/modules/visual_script/doc_classes/VisualScriptSwitch.xml +++ b/modules/visual_script/doc_classes/VisualScriptSwitch.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptSwitch" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptSwitch" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> Branches program flow based on a given input's value. </brief_description> diff --git a/modules/visual_script/doc_classes/VisualScriptTypeCast.xml b/modules/visual_script/doc_classes/VisualScriptTypeCast.xml index d414a95657..0bdc4ce89d 100644 --- a/modules/visual_script/doc_classes/VisualScriptTypeCast.xml +++ b/modules/visual_script/doc_classes/VisualScriptTypeCast.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptTypeCast" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptTypeCast" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/visual_script/doc_classes/VisualScriptVariableGet.xml b/modules/visual_script/doc_classes/VisualScriptVariableGet.xml index ccd2918ec8..06178a399d 100644 --- a/modules/visual_script/doc_classes/VisualScriptVariableGet.xml +++ b/modules/visual_script/doc_classes/VisualScriptVariableGet.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptVariableGet" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptVariableGet" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> Gets a variable's value. </brief_description> diff --git a/modules/visual_script/doc_classes/VisualScriptVariableSet.xml b/modules/visual_script/doc_classes/VisualScriptVariableSet.xml index e1fc1ba762..5969f25060 100644 --- a/modules/visual_script/doc_classes/VisualScriptVariableSet.xml +++ b/modules/visual_script/doc_classes/VisualScriptVariableSet.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptVariableSet" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptVariableSet" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> Changes a variable's value. </brief_description> diff --git a/modules/visual_script/doc_classes/VisualScriptWhile.xml b/modules/visual_script/doc_classes/VisualScriptWhile.xml index de1ff45746..b9e7f6a553 100644 --- a/modules/visual_script/doc_classes/VisualScriptWhile.xml +++ b/modules/visual_script/doc_classes/VisualScriptWhile.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptWhile" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptWhile" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> Conditional loop. </brief_description> diff --git a/modules/visual_script/doc_classes/VisualScriptYield.xml b/modules/visual_script/doc_classes/VisualScriptYield.xml index f21b53861a..c4698f746a 100644 --- a/modules/visual_script/doc_classes/VisualScriptYield.xml +++ b/modules/visual_script/doc_classes/VisualScriptYield.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptYield" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptYield" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/visual_script/doc_classes/VisualScriptYieldSignal.xml b/modules/visual_script/doc_classes/VisualScriptYieldSignal.xml index 5075fb6ded..b67e4ab1b8 100644 --- a/modules/visual_script/doc_classes/VisualScriptYieldSignal.xml +++ b/modules/visual_script/doc_classes/VisualScriptYieldSignal.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VisualScriptYieldSignal" inherits="VisualScriptNode" category="Core" version="3.0-stable"> +<class name="VisualScriptYieldSignal" inherits="VisualScriptNode" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/visual_script/visual_script.cpp b/modules/visual_script/visual_script.cpp index 5987fdf5da..ef680547ca 100644 --- a/modules/visual_script/visual_script.cpp +++ b/modules/visual_script/visual_script.cpp @@ -2182,7 +2182,7 @@ void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_o Ref<VisualScriptNode> node = F->get().node; VisualScriptNodeInstance *instance = instances[F->key()]; - // conect to default values + // connect to default values for (int i = 0; i < instance->input_port_count; i++) { if (instance->input_ports[i] == -1) { @@ -2192,7 +2192,7 @@ void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_o } } - // conect to trash + // connect to trash for (int i = 0; i < instance->output_port_count; i++) { if (instance->output_ports[i] == -1) { instance->output_ports[i] = function.trash_pos; //trash is same for all diff --git a/modules/visual_script/visual_script_nodes.cpp b/modules/visual_script/visual_script_nodes.cpp index e0b4fde237..c5654a5a20 100644 --- a/modules/visual_script/visual_script_nodes.cpp +++ b/modules/visual_script/visual_script_nodes.cpp @@ -425,7 +425,7 @@ PropertyInfo VisualScriptOperator::get_input_value_port_info(int p_idx) const { } PropertyInfo VisualScriptOperator::get_output_value_port_info(int p_idx) const { static const Variant::Type port_types[Variant::OP_MAX] = { - //comparation + //comparison Variant::BOOL, //OP_EQUAL, Variant::BOOL, //OP_NOT_EQUAL, Variant::BOOL, //OP_LESS, @@ -466,7 +466,7 @@ PropertyInfo VisualScriptOperator::get_output_value_port_info(int p_idx) const { } static const char *op_names[] = { - //comparation + //comparison "Equal", //OP_EQUAL, "NotEqual", //OP_NOT_EQUAL, "Less", //OP_LESS, @@ -506,7 +506,7 @@ String VisualScriptOperator::get_caption() const { String VisualScriptOperator::get_text() const { static const wchar_t *op_names[] = { - //comparation + //comparison L"A = B", //OP_EQUAL, L"A \u2260 B", //OP_NOT_EQUAL, L"A < B", //OP_LESS, diff --git a/modules/webm/SCsub b/modules/webm/SCsub index 2f1a28a54c..33561da098 100644 --- a/modules/webm/SCsub +++ b/modules/webm/SCsub @@ -18,6 +18,10 @@ thirdparty_libsimplewebm_sources = [thirdparty_libsimplewebm_dir + file for file env_webm.add_source_files(env.modules_sources, thirdparty_libsimplewebm_sources) env_webm.Append(CPPPATH=[thirdparty_libsimplewebm_dir, thirdparty_libsimplewebm_dir + "libwebm/"]) +# upstream uses c++11 +if (not env_webm.msvc): + env_webm.Append(CCFLAGS="-std=c++11") + # also requires libogg, libvorbis and libopus if env['builtin_libogg']: env_webm.Append(CPPPATH=["#thirdparty/libogg"]) diff --git a/modules/webm/doc_classes/ResourceImporterWebm.xml b/modules/webm/doc_classes/ResourceImporterWebm.xml index 20e0e48187..0cfab1baf0 100644 --- a/modules/webm/doc_classes/ResourceImporterWebm.xml +++ b/modules/webm/doc_classes/ResourceImporterWebm.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="ResourceImporterWebm" inherits="ResourceImporter" category="Core" version="3.0-stable"> +<class name="ResourceImporterWebm" inherits="ResourceImporter" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/webm/doc_classes/VideoStreamWebm.xml b/modules/webm/doc_classes/VideoStreamWebm.xml index 94aea5c8d2..c02a7a8016 100644 --- a/modules/webm/doc_classes/VideoStreamWebm.xml +++ b/modules/webm/doc_classes/VideoStreamWebm.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VideoStreamWebm" inherits="VideoStream" category="Core" version="3.0-stable"> +<class name="VideoStreamWebm" inherits="VideoStream" category="Core" version="3.1"> <brief_description> </brief_description> <description> diff --git a/modules/webm/libvpx/SCsub b/modules/webm/libvpx/SCsub index aa282338cb..0ebafa022d 100644 --- a/modules/webm/libvpx/SCsub +++ b/modules/webm/libvpx/SCsub @@ -254,7 +254,6 @@ env_libvpx = env.Clone() env_libvpx.Append(CPPPATH=[libvpx_dir]) cpu_bits = env["bits"] -osx_fat = (env["platform"] == 'osx' and cpu_bits == 'fat') webm_cpu_x86 = False webm_cpu_arm = False if env["platform"] == 'uwp': @@ -269,11 +268,8 @@ else: is_android_x86 = (env["platform"] == 'android' and env["android_arch"] == 'x86') if is_android_x86: cpu_bits = '32' - if osx_fat: - webm_cpu_x86 = True - else: - webm_cpu_x86 = not is_x11_or_server_arm and (cpu_bits == '32' or cpu_bits == '64') and (env["platform"] == 'windows' or env["platform"] == 'x11' or env["platform"] == 'osx' or env["platform"] == 'haiku' or is_android_x86 or is_ios_x86) - webm_cpu_arm = is_x11_or_server_arm or (not is_ios_x86 and env["platform"] == 'iphone') or (not is_android_x86 and env["platform"] == 'android') + webm_cpu_x86 = not is_x11_or_server_arm and (cpu_bits == '32' or cpu_bits == '64') and (env["platform"] == 'windows' or env["platform"] == 'x11' or env["platform"] == 'osx' or env["platform"] == 'haiku' or is_android_x86 or is_ios_x86) + webm_cpu_arm = is_x11_or_server_arm or (not is_ios_x86 and env["platform"] == 'iphone') or (not is_android_x86 and env["platform"] == 'android') if webm_cpu_x86: import subprocess @@ -303,28 +299,22 @@ if webm_cpu_x86: webm_simd_optimizations = False if webm_cpu_x86: - if osx_fat: - #'osx' platform only: run python script which will compile using 'yasm' command and then merge 32-bit and 64-bit using 'lipo' command - env_libvpx["AS"] = 'python modules/webm/libvpx/yasm_osx_fat.py' - env_libvpx["ASFLAGS"] = '-I' + libvpx_dir[1:] - env_libvpx["ASCOM"] = '$AS $ASFLAGS $TARGET $SOURCES' + if env["platform"] == 'windows' or env["platform"] == 'uwp': + env_libvpx["ASFORMAT"] = 'win' + elif env["platform"] == 'osx' or env["platform"] == "iphone": + env_libvpx["ASFORMAT"] = 'macho' else: - if env["platform"] == 'windows' or env["platform"] == 'uwp': - env_libvpx["ASFORMAT"] = 'win' - elif env["platform"] == 'osx' or env["platform"] == "iphone": - env_libvpx["ASFORMAT"] = 'macho' - else: - env_libvpx["ASFORMAT"] = 'elf' - env_libvpx["ASFORMAT"] += cpu_bits - - env_libvpx["AS"] = 'yasm' - env_libvpx["ASFLAGS"] = '-I' + libvpx_dir[1:] + ' -f $ASFORMAT -D $ASCPU' - env_libvpx["ASCOM"] = '$AS $ASFLAGS -o $TARGET $SOURCES' + env_libvpx["ASFORMAT"] = 'elf' + env_libvpx["ASFORMAT"] += cpu_bits + + env_libvpx["AS"] = 'yasm' + env_libvpx["ASFLAGS"] = '-I' + libvpx_dir[1:] + ' -f $ASFORMAT -D $ASCPU' + env_libvpx["ASCOM"] = '$AS $ASFLAGS -o $TARGET $SOURCES' - if cpu_bits == '32': - env_libvpx["ASCPU"] = 'X86_32' - elif cpu_bits == '64': - env_libvpx["ASCPU"] = 'X86_64' + if cpu_bits == '32': + env_libvpx["ASCPU"] = 'X86_32' + elif cpu_bits == '64': + env_libvpx["ASCPU"] = 'X86_64' env_libvpx.Append(CCFLAGS=['-DWEBM_X86ASM']) @@ -375,7 +365,7 @@ if webm_cpu_x86: env_libvpx.add_source_files(env.modules_sources, libvpx_sources_intrin_x86) env_libvpx.add_source_files(env.modules_sources, libvpx_sources_x86asm) - if cpu_bits == '64' or osx_fat: + if cpu_bits == '64': env_libvpx.add_source_files(env.modules_sources, libvpx_sources_x86_64asm) elif webm_cpu_arm: env_libvpx.add_source_files(env.modules_sources, libvpx_sources_arm) diff --git a/modules/webm/libvpx/yasm_osx_fat.py b/modules/webm/libvpx/yasm_osx_fat.py deleted file mode 100644 index 0065e2766c..0000000000 --- a/modules/webm/libvpx/yasm_osx_fat.py +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env python - -import sys -import os - -includes = sys.argv[1] -output_file = sys.argv[2] -input_file = sys.argv[3] - -can_remove = {} - -lipo_command = '' - -exit_code = 1 - -for arch in ['32', '64']: - if arch == '32' and input_file.endswith('x86_64.asm'): - can_remove[arch] = False - else: - command = 'yasm ' + includes + ' -f macho' + arch + ' -D X86_' + arch + ' -o ' + output_file + '.' + arch + ' ' + input_file - print(command) - if os.system(command) == 0: - lipo_command += output_file + '.' + arch + ' ' - can_remove[arch] = True - else: - can_remove[arch] = False - -if lipo_command != '': - lipo_command = 'lipo -create ' + lipo_command + '-output ' + output_file - print(lipo_command) - if os.system(lipo_command) == 0: - exit_code = 0 - -for arch in ['32', '64']: - if can_remove[arch]: - os.remove(output_file + '.' + arch) - -sys.exit(exit_code) diff --git a/modules/websocket/SCsub b/modules/websocket/SCsub index 3b0f920bbf..b36f1beacd 100644 --- a/modules/websocket/SCsub +++ b/modules/websocket/SCsub @@ -35,7 +35,6 @@ thirdparty_sources = [ "handshake.c", "header.c", "libwebsockets.c", - "minilex.c", "output.c", "pollfd.c", "service.c", @@ -54,7 +53,7 @@ thirdparty_sources = [ if env_lws["platform"] == "android": # Builtin getifaddrs thirdparty_sources += ["misc/getifaddrs.c"] -if env_lws["platform"] == "windows": # Winsock +if env_lws["platform"] == "windows" or env_lws["platform"] == "uwp": # Winsock 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 += ["plat/lws-plat-unix.c"] @@ -69,13 +68,16 @@ else: env_lws.Append(CPPPATH=[thirdparty_dir]) wrapper_includes = ["#thirdparty/lws/mbedtls_wrapper/include/" + inc for inc in ["internal", "openssl", "platform", ""]] - env_lws.Append(CPPPATH=wrapper_includes) + env_lws.Prepend(CPPPATH=wrapper_includes) if env['builtin_mbedtls']: mbedtls_includes = "#thirdparty/mbedtls/include" - env_lws.Append(CPPPATH=[mbedtls_includes]) + env_lws.Prepend(CPPPATH=[mbedtls_includes]) - if env_lws["platform"] == "windows": + if env_lws["platform"] == "windows" or env_lws["platform"] == "uwp": env_lws.Append(CPPPATH=[thirdparty_dir + helper_dir]) + if env_lws["platform"] == "uwp": + env_lws.Append(CCFLAGS=["/DLWS_MINGW_SUPPORT"]) + env_lws.add_source_files(env.modules_sources, "*.cpp") diff --git a/modules/websocket/emws_client.cpp b/modules/websocket/emws_client.cpp index 38fe520fc1..1405fa98b0 100644 --- a/modules/websocket/emws_client.cpp +++ b/modules/websocket/emws_client.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/modules/websocket/emws_client.h b/modules/websocket/emws_client.h index 8801f37007..6c2fa23b53 100644 --- a/modules/websocket/emws_client.h +++ b/modules/websocket/emws_client.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/modules/websocket/emws_peer.cpp b/modules/websocket/emws_peer.cpp index 93665e6428..d3330d683c 100644 --- a/modules/websocket/emws_peer.cpp +++ b/modules/websocket/emws_peer.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/modules/websocket/emws_peer.h b/modules/websocket/emws_peer.h index a50d1874ba..e06f725265 100644 --- a/modules/websocket/emws_peer.h +++ b/modules/websocket/emws_peer.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/modules/websocket/emws_server.cpp b/modules/websocket/emws_server.cpp index 60e9133225..c9ddae0c8c 100644 --- a/modules/websocket/emws_server.cpp +++ b/modules/websocket/emws_server.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/modules/websocket/emws_server.h b/modules/websocket/emws_server.h index 59f1d76346..aa089ea40d 100644 --- a/modules/websocket/emws_server.h +++ b/modules/websocket/emws_server.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/modules/websocket/lws_client.cpp b/modules/websocket/lws_client.cpp index 604b1886ad..bebf342f8c 100644 --- a/modules/websocket/lws_client.cpp +++ b/modules/websocket/lws_client.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/modules/websocket/lws_client.h b/modules/websocket/lws_client.h index 2e082175df..8850683cb5 100644 --- a/modules/websocket/lws_client.h +++ b/modules/websocket/lws_client.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/modules/websocket/lws_helper.h b/modules/websocket/lws_helper.h index ac0c340aa9..a850a545d3 100644 --- a/modules/websocket/lws_helper.h +++ b/modules/websocket/lws_helper.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -108,7 +108,7 @@ static bool _lws_poll(struct lws_context *context, _LWSRef *ref) { static void _lws_make_protocols(void *p_obj, lws_callback_function *p_callback, PoolVector<String> p_names, _LWSRef **r_lws_ref) { /* the input strings might go away after this call, * we need to copy them. Will clear them when - * detroying the context */ + * destroying the context */ int i; int len = p_names.size(); size_t data_size = sizeof(struct LWSPeer::PeerData); diff --git a/modules/websocket/lws_peer.cpp b/modules/websocket/lws_peer.cpp index fdaa79f9d4..ba45d7688f 100644 --- a/modules/websocket/lws_peer.cpp +++ b/modules/websocket/lws_peer.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/modules/websocket/lws_peer.h b/modules/websocket/lws_peer.h index 0a62b65d24..e96b38b168 100644 --- a/modules/websocket/lws_peer.h +++ b/modules/websocket/lws_peer.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/modules/websocket/lws_server.cpp b/modules/websocket/lws_server.cpp index 8a47ba557d..94fe4231ae 100644 --- a/modules/websocket/lws_server.cpp +++ b/modules/websocket/lws_server.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/modules/websocket/lws_server.h b/modules/websocket/lws_server.h index 5f7ac4850a..de8f59e5ae 100644 --- a/modules/websocket/lws_server.h +++ b/modules/websocket/lws_server.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/modules/websocket/register_types.cpp b/modules/websocket/register_types.cpp index 39d03ff1f0..721f3cc330 100644 --- a/modules/websocket/register_types.cpp +++ b/modules/websocket/register_types.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/modules/websocket/register_types.h b/modules/websocket/register_types.h index 010d88789b..89ce93e286 100644 --- a/modules/websocket/register_types.h +++ b/modules/websocket/register_types.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/modules/websocket/websocket_client.cpp b/modules/websocket/websocket_client.cpp index f92a386988..591d9510ce 100644 --- a/modules/websocket/websocket_client.cpp +++ b/modules/websocket/websocket_client.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/modules/websocket/websocket_client.h b/modules/websocket/websocket_client.h index 0e87825222..5c863559bc 100644 --- a/modules/websocket/websocket_client.h +++ b/modules/websocket/websocket_client.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/modules/websocket/websocket_macros.h b/modules/websocket/websocket_macros.h index b5c2159806..d27fb4d778 100644 --- a/modules/websocket/websocket_macros.h +++ b/modules/websocket/websocket_macros.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/modules/websocket/websocket_multiplayer.cpp b/modules/websocket/websocket_multiplayer.cpp index 8cd4dff38b..b948c439df 100644 --- a/modules/websocket/websocket_multiplayer.cpp +++ b/modules/websocket/websocket_multiplayer.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/modules/websocket/websocket_multiplayer.h b/modules/websocket/websocket_multiplayer.h index e8e795e97f..8edfc5296e 100644 --- a/modules/websocket/websocket_multiplayer.h +++ b/modules/websocket/websocket_multiplayer.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/modules/websocket/websocket_peer.cpp b/modules/websocket/websocket_peer.cpp index a6fbb4481b..6324047846 100644 --- a/modules/websocket/websocket_peer.cpp +++ b/modules/websocket/websocket_peer.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/modules/websocket/websocket_peer.h b/modules/websocket/websocket_peer.h index f4d8ce3e38..ad451e9cc7 100644 --- a/modules/websocket/websocket_peer.h +++ b/modules/websocket/websocket_peer.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/modules/websocket/websocket_server.cpp b/modules/websocket/websocket_server.cpp index ba77019f55..5746f61e10 100644 --- a/modules/websocket/websocket_server.cpp +++ b/modules/websocket/websocket_server.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/modules/websocket/websocket_server.h b/modules/websocket/websocket_server.h index db188811fd..360ff9e6d4 100644 --- a/modules/websocket/websocket_server.h +++ b/modules/websocket/websocket_server.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ |