summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/bullet/bullet_physics_server.cpp27
-rw-r--r--modules/bullet/doc_classes/BulletPhysicsDirectBodyState.xml2
-rw-r--r--modules/bullet/doc_classes/BulletPhysicsServer.xml2
-rw-r--r--modules/bullet/godot_result_callbacks.cpp23
-rw-r--r--modules/bullet/godot_result_callbacks.h7
-rw-r--r--modules/bullet/rigid_body_bullet.cpp8
-rw-r--r--modules/bullet/rigid_body_bullet.h4
-rw-r--r--modules/bullet/space_bullet.cpp15
-rw-r--r--modules/enet/doc_classes/NetworkedMultiplayerENet.xml18
-rw-r--r--modules/freetype/SCsub16
-rw-r--r--modules/gdnative/doc_classes/ARVRInterfaceGDNative.xml2
-rw-r--r--modules/gdnative/doc_classes/GDNative.xml2
-rw-r--r--modules/gdnative/doc_classes/GDNativeLibrary.xml2
-rw-r--r--modules/gdnative/doc_classes/NativeScript.xml2
-rw-r--r--modules/gdnative/doc_classes/PluginScript.xml2
-rw-r--r--modules/gdnative/nativescript/nativescript.cpp1
-rw-r--r--modules/gdscript/doc_classes/GDScript.xml2
-rw-r--r--modules/gdscript/doc_classes/GDScriptFunctionState.xml2
-rw-r--r--modules/gdscript/doc_classes/GDScriptNativeClass.xml2
-rw-r--r--modules/gdscript/gdscript_editor.cpp4
-rw-r--r--modules/gdscript/gdscript_function.cpp20
-rw-r--r--modules/gdscript/gdscript_function.h1
-rw-r--r--modules/gdscript/gdscript_parser.cpp11
-rw-r--r--modules/gridmap/doc_classes/GridMap.xml2
-rw-r--r--modules/gridmap/grid_map_editor_plugin.cpp27
-rw-r--r--modules/gridmap/grid_map_editor_plugin.h1
-rw-r--r--modules/hdr/image_loader_hdr.cpp16
-rwxr-xr-xmodules/mbedtls/SCsub2
-rw-r--r--modules/mobile_vr/config.py2
-rw-r--r--modules/mobile_vr/doc_classes/MobileVRInterface.xml2
-rw-r--r--modules/mono/SCsub33
-rw-r--r--modules/mono/config.py26
-rw-r--r--modules/mono/csharp_script.cpp35
-rw-r--r--modules/mono/csharp_script.h7
-rw-r--r--modules/mono/doc_classes/@C#.xml2
-rw-r--r--modules/mono/doc_classes/CSharpScript.xml2
-rw-r--r--modules/mono/doc_classes/GodotSharp.xml2
-rw-r--r--modules/mono/editor/bindings_generator.cpp87
-rw-r--r--modules/mono/editor/bindings_generator.h3
-rw-r--r--modules/mono/editor/godotsharp_builds.cpp61
-rw-r--r--modules/mono/editor/godotsharp_builds.h16
-rw-r--r--modules/mono/editor/godotsharp_editor.cpp10
-rw-r--r--modules/mono/editor/godotsharp_editor.h1
-rw-r--r--modules/mono/editor/godotsharp_export.cpp166
-rw-r--r--modules/mono/editor/godotsharp_export.h57
-rw-r--r--modules/mono/editor/mono_bottom_panel.cpp2
-rw-r--r--modules/mono/glue/cs_files/StringExtensions.cs32
-rw-r--r--modules/mono/glue/cs_files/Transform.cs4
-rwxr-xr-xmodules/mono/glue/cs_files/VERSION.txt1
-rw-r--r--modules/mono/godotsharp_defs.h3
-rw-r--r--modules/mono/mono_gd/gd_mono.cpp308
-rw-r--r--modules/mono/mono_gd/gd_mono.h63
-rw-r--r--modules/mono/mono_gd/gd_mono_assembly.cpp95
-rw-r--r--modules/mono/mono_gd/gd_mono_assembly.h17
-rw-r--r--modules/mono/mono_gd/gd_mono_marshal.h2
-rw-r--r--modules/mono/mono_gd/gd_mono_utils.cpp67
-rw-r--r--modules/regex/doc_classes/RegEx.xml2
-rw-r--r--modules/regex/doc_classes/RegExMatch.xml2
-rw-r--r--modules/stb_vorbis/doc_classes/AudioStreamOGGVorbis.xml2
-rw-r--r--modules/stb_vorbis/doc_classes/ResourceImporterOGGVorbis.xml2
-rw-r--r--modules/stb_vorbis/resource_importer_ogg_vorbis.cpp1
-rw-r--r--modules/theora/doc_classes/ResourceImporterTheora.xml2
-rw-r--r--modules/theora/doc_classes/VideoStreamTheora.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScript.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptBasicTypeConstant.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptClassConstant.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptComment.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptCondition.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptConstant.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptConstructor.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptCustomNode.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptDeconstruct.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptEditor.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptEmitSignal.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptEngineSingleton.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptExpression.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptFunction.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptFunctionCall.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptFunctionState.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptGlobalConstant.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptIndexGet.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptIndexSet.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptInputAction.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptIterator.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptLocalVar.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptLocalVarSet.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptMathConstant.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptNode.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptOperator.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptPreload.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptPropertyGet.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptPropertySet.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptResourcePath.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptReturn.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptSceneNode.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptSceneTree.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptSelect.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptSelf.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptSequence.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptSubCall.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptSwitch.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptTypeCast.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptVariableGet.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptVariableSet.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptWhile.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptYield.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptYieldSignal.xml2
-rw-r--r--modules/webm/SCsub4
-rw-r--r--modules/webm/doc_classes/ResourceImporterWebm.xml2
-rw-r--r--modules/webm/doc_classes/VideoStreamWebm.xml2
-rw-r--r--modules/websocket/SCsub5
112 files changed, 1095 insertions, 350 deletions
diff --git a/modules/bullet/bullet_physics_server.cpp b/modules/bullet/bullet_physics_server.cpp
index 61ce26e9fd..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;
}
@@ -784,21 +786,26 @@ int BulletPhysicsServer::body_get_max_contacts_reported(RID p_body) const {
}
void BulletPhysicsServer::body_set_contacts_reported_depth_threshold(RID p_body, float p_threshold) {
- WARN_PRINT("Not supported by bullet and even Godot");
+ // 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) {
@@ -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/doc_classes/BulletPhysicsDirectBodyState.xml b/modules/bullet/doc_classes/BulletPhysicsDirectBodyState.xml
index 8c8647e097..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.1-dev">
+<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 8ed84e1dec..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.1-dev">
+<class name="BulletPhysicsServer" inherits="PhysicsServer" category="Core" version="3.1">
<brief_description>
</brief_description>
<description>
diff --git a/modules/bullet/godot_result_callbacks.cpp b/modules/bullet/godot_result_callbacks.cpp
index 7c051f8f17..72c982bb0b 100644
--- a/modules/bullet/godot_result_callbacks.cpp
+++ b/modules/bullet/godot_result_callbacks.cpp
@@ -257,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) {
-
- 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;
- }
+ // Has penetration
+ if (m_penetration_distance < ABS(depth)) {
+
+ bool isSwapped = m_manifoldPtr->getBody0() != m_body0Wrap->getCollisionObject();
+
+ 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 ed6d4b7d6d..60493d4788 100644
--- a/modules/bullet/godot_result_callbacks.h
+++ b/modules/bullet/godot_result_callbacks.h
@@ -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 75b4cc054a..2494063c22 100644
--- a/modules/bullet/rigid_body_bullet.cpp
+++ b/modules/bullet/rigid_body_bullet.cpp
@@ -255,6 +255,7 @@ RigidBodyBullet::RigidBodyBullet() :
linearDamp(0),
angularDamp(0),
can_sleep(true),
+ omit_forces_integration(false),
force_integration_callback(NULL),
isTransformChanged(false),
previousActiveState(true),
@@ -334,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;
@@ -437,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 2d529f6dc7..b9511243c7 100644
--- a/modules/bullet/rigid_body_bullet.h
+++ b/modules/bullet/rigid_body_bullet.h
@@ -198,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
@@ -254,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/space_bullet.cpp b/modules/bullet/space_bullet.cpp
index e20a79f667..8c15758e0f 100644
--- a/modules/bullet/space_bullet.cpp
+++ b/modules/bullet/space_bullet.cpp
@@ -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
@@ -842,7 +842,6 @@ bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform &p_f
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) {
@@ -854,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);
@@ -893,7 +891,7 @@ bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform &p_f
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,
@@ -918,11 +916,8 @@ bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform &p_f
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) {
@@ -1112,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
@@ -1122,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/enet/doc_classes/NetworkedMultiplayerENet.xml b/modules/enet/doc_classes/NetworkedMultiplayerENet.xml
index 55a7a1ac77..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.1-dev">
+<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 a34a650a4d..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"])
diff --git a/modules/gdnative/doc_classes/ARVRInterfaceGDNative.xml b/modules/gdnative/doc_classes/ARVRInterfaceGDNative.xml
index 998460eee1..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.1-dev">
+<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 4e87cbf450..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.1-dev">
+<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 ca1bae0598..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.1-dev">
+<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 3783d9d0a4..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.1-dev">
+<class name="PluginScript" inherits="Script" category="Core" version="3.1">
<brief_description>
</brief_description>
<description>
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 0dc69c3688..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.1-dev">
+<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 254d968e1b..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.1-dev">
+<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 1abcc4762f..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.1-dev">
+<class name="GDScriptNativeClass" inherits="Reference" category="Core" version="3.1">
<brief_description>
</brief_description>
<description>
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_parser.cpp b/modules/gdscript/gdscript_parser.cpp
index ac7fd94141..435bc327dc 100644
--- a/modules/gdscript/gdscript_parser.cpp
+++ b/modules/gdscript/gdscript_parser.cpp
@@ -461,18 +461,21 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s
} 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;
diff --git a/modules/gridmap/doc_classes/GridMap.xml b/modules/gridmap/doc_classes/GridMap.xml
index 36d4d7cb59..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.1-dev">
+<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 34d51b51e2..869492232c 100644
--- a/modules/gridmap/grid_map_editor_plugin.cpp
+++ b/modules/gridmap/grid_map_editor_plugin.cpp
@@ -101,8 +101,8 @@ void GridMapEditor::_menu_option(int p_option) {
}
if (edit_axis != new_axis) {
- int item1 = options->get_popup()->get_item_id(MENU_OPTION_NEXT_LEVEL);
- int item2 = options->get_popup()->get_item_id(MENU_OPTION_PREV_LEVEL);
+ 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"));
@@ -641,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;
}
@@ -770,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++) {
@@ -1247,6 +1256,7 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) {
selection.active = false;
updating = false;
+ accumulated_floor_delta = 0.0;
}
GridMapEditor::~GridMapEditor() {
@@ -1259,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 9651770528..f79d9aefa0 100644
--- a/modules/gridmap/grid_map_editor_plugin.h
+++ b/modules/gridmap/grid_map_editor_plugin.h
@@ -76,6 +76,7 @@ class GridMapEditor : public VBoxContainer {
Panel *panel;
MenuButton *options;
SpinBox *floor;
+ double accumulated_floor_delta;
ToolButton *mode_thumbnail;
ToolButton *mode_list;
HBoxContainer *spatial_editor_hb;
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 d3f2548320..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.1-dev">
+<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..5591ed25bf 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"]).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> &params) {
@@ -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 0c2bb948ea..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.1-dev">
+<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 9bd57f1d4d..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.1-dev">
+<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 51f07523e7..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.1-dev">
+<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 952e033565..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)
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 975cf0f030..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"));
@@ -316,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/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 39474f8cbc..1ebef04561 100644
--- a/modules/mono/mono_gd/gd_mono.cpp
+++ b/modules/mono/mono_gd/gd_mono.cpp
@@ -42,7 +42,10 @@
#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
@@ -208,7 +211,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);
@@ -219,7 +261,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
@@ -271,43 +317,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();
@@ -317,13 +404,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;
}
@@ -334,7 +433,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
@@ -346,7 +461,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
@@ -360,17 +475,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");
@@ -385,20 +503,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() {
@@ -441,12 +611,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;
@@ -501,16 +674,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);
@@ -562,8 +799,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..2ce1b0a9df 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,19 +84,19 @@ 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);
+ res = _load_assembly_from(name.get_basename(), path, refonly);
break;
}
} else {
path = search_dir.plus_file(name + ".dll");
if (FileAccess::exists(path)) {
- res = _load_assembly_from(name, path);
+ res = _load_assembly_from(name, path, refonly);
break;
}
path = search_dir.plus_file(name + ".exe");
if (FileAccess::exists(path)) {
- res = _load_assembly_from(name, path);
+ res = _load_assembly_from(name, path, refonly);
break;
}
}
@@ -88,20 +104,21 @@ MonoAssembly *GDMonoAssembly::_search_hook(MonoAssemblyName *aname, void *user_d
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) {
@@ -121,10 +138,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 +150,61 @@ 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);
+ res = _load_assembly_from(name.get_basename(), path, refonly);
break;
}
} else {
path = search_dir.plus_file(name + ".dll");
if (FileAccess::exists(path)) {
- res = _load_assembly_from(name, path);
+ res = _load_assembly_from(name, path, refonly);
+ break;
+ }
+
+ path = search_dir.plus_file(name + ".exe");
+ if (FileAccess::exists(path)) {
+ res = _load_assembly_from(name, path, refonly);
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);
@@ -190,7 +216,7 @@ Error GDMonoAssembly::load(MonoDomain *p_domain) {
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);
@@ -213,15 +239,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 +394,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 8fd437223f..4e28622adb 100644
--- a/modules/mono/mono_gd/gd_mono_marshal.h
+++ b/modules/mono/mono_gd/gd_mono_marshal.h
@@ -201,7 +201,7 @@ Dictionary mono_object_to_Dictionary(MonoObject *p_dict);
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_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 26f0501df3..75e8903ff8 100644
--- a/modules/regex/doc_classes/RegEx.xml
+++ b/modules/regex/doc_classes/RegEx.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="RegEx" inherits="Reference" category="Core" version="3.1-dev">
+<class name="RegEx" inherits="Reference" category="Core" version="3.1">
<brief_description>
Class for searching text for patterns using regular expressions.
</brief_description>
diff --git a/modules/regex/doc_classes/RegExMatch.xml b/modules/regex/doc_classes/RegExMatch.xml
index 550411d3e0..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.1-dev">
+<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 8d311ae1b8..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.1-dev">
+<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 5872dd35ff..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.1-dev">
+<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 6d2de4a9ad..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.1-dev">
+<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 550844128d..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.1-dev">
+<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 975b294f30..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.1-dev">
+<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 b529589b98..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.1-dev">
+<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 9c2ec3b849..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.1-dev">
+<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 dc946cfcbd..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.1-dev">
+<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 5c20f27ec2..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.1-dev">
+<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 a3313a43d9..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.1-dev">
+<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 274adb5423..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.1-dev">
+<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 2efe8d9bd6..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.1-dev">
+<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 2165c403d4..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.1-dev">
+<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 f076c70715..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.1-dev">
+<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 1c4542336f..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.1-dev">
+<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 7eea609db4..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.1-dev">
+<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 26196f278e..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.1-dev">
+<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 0b93c3092c..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.1-dev">
+<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 18daa42797..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.1-dev">
+<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 dc025cfb27..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.1-dev">
+<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 05e9a6cb81..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.1-dev">
+<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 d0db8cbab3..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.1-dev">
+<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 983d8882a7..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.1-dev">
+<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 bc876900f3..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.1-dev">
+<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 4316bf146d..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.1-dev">
+<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 d815476e2c..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.1-dev">
+<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 038fd8c9cd..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.1-dev">
+<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 fa65a89c4a..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.1-dev">
+<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 243ab03b49..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.1-dev">
+<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 c2c5464047..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.1-dev">
+<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 68a57191de..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.1-dev">
+<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 19abc27053..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.1-dev">
+<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 88aac85f59..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.1-dev">
+<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 ac962a071d..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.1-dev">
+<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 a3144582cb..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.1-dev">
+<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 ca50f811c3..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.1-dev">
+<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 3d4bdcfd0a..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.1-dev">
+<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 c77b674b64..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.1-dev">
+<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 f1aad841ca..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.1-dev">
+<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 c2847fcada..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.1-dev">
+<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 0180f34c72..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.1-dev">
+<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 d34d0b7127..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.1-dev">
+<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 ea9e6438cf..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.1-dev">
+<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 4bdfeab35b..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.1-dev">
+<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 76c218294e..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.1-dev">
+<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 0262ad5dfb..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.1-dev">
+<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 46a6ea7a30..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.1-dev">
+<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 a1129ffbd7..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.1-dev">
+<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 ad3a016c0d..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.1-dev">
+<class name="VisualScriptYieldSignal" inherits="VisualScriptNode" category="Core" version="3.1">
<brief_description>
</brief_description>
<description>
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 7c8e1a46b1..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.1-dev">
+<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 d52e2324a1..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.1-dev">
+<class name="VideoStreamWebm" inherits="VideoStream" category="Core" version="3.1">
<brief_description>
</brief_description>
<description>
diff --git a/modules/websocket/SCsub b/modules/websocket/SCsub
index 1a36e05863..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",
@@ -69,11 +68,11 @@ 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" or env_lws["platform"] == "uwp":
env_lws.Append(CPPPATH=[thirdparty_dir + helper_dir])