summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/bullet/area_bullet.cpp10
-rw-r--r--modules/bullet/area_bullet.h3
-rw-r--r--modules/bullet/bullet_physics_server.cpp22
-rw-r--r--modules/bullet/bullet_physics_server.h7
-rw-r--r--modules/bullet/bullet_utilities.h7
-rw-r--r--modules/bullet/collision_object_bullet.cpp163
-rw-r--r--modules/bullet/collision_object_bullet.h40
-rw-r--r--modules/bullet/godot_motion_state.h2
-rw-r--r--modules/bullet/rigid_body_bullet.cpp42
-rw-r--r--modules/bullet/rigid_body_bullet.h11
-rw-r--r--modules/bullet/shape_bullet.cpp17
-rw-r--r--modules/bullet/shape_owner_bullet.h9
-rw-r--r--modules/bullet/soft_body_bullet.cpp6
-rw-r--r--modules/bullet/soft_body_bullet.h7
-rw-r--r--modules/bullet/space_bullet.cpp29
-rw-r--r--modules/csg/csg.cpp2
-rw-r--r--modules/csg/csg_shape.cpp5
-rw-r--r--modules/enet/doc_classes/NetworkedMultiplayerENet.xml2
-rw-r--r--modules/gdnative/nativescript/nativescript.cpp3
-rw-r--r--modules/gdscript/editor/gdscript_highlighter.cpp18
-rw-r--r--modules/gdscript/gdscript.cpp1
-rw-r--r--modules/gdscript/gdscript_compiler.cpp20
-rw-r--r--modules/gdscript/gdscript_compiler.h10
-rw-r--r--modules/gdscript/gdscript_editor.cpp3
-rw-r--r--modules/gdscript/gdscript_function.cpp72
-rw-r--r--modules/gdscript/gdscript_function.h10
-rw-r--r--modules/gdscript/gdscript_parser.cpp10
-rw-r--r--modules/gdscript/gdscript_tokenizer.cpp2
-rw-r--r--modules/jpg/image_loader_jpegd.cpp22
-rw-r--r--modules/mono/SCsub26
-rw-r--r--modules/mono/config.py180
-rw-r--r--modules/mono/csharp_script.cpp6
-rw-r--r--modules/mono/doc_classes/GodotSharp.xml34
-rw-r--r--modules/mono/editor/GodotSharpTools/Editor/GodotSharpExport.cs74
-rw-r--r--modules/mono/editor/GodotSharpTools/GodotSharpTools.csproj1
-rw-r--r--modules/mono/editor/bindings_generator.cpp235
-rw-r--r--modules/mono/editor/bindings_generator.h29
-rw-r--r--modules/mono/editor/csharp_project.cpp8
-rw-r--r--modules/mono/editor/godotsharp_builds.cpp53
-rw-r--r--modules/mono/editor/godotsharp_editor.cpp34
-rw-r--r--modules/mono/editor/godotsharp_editor.h2
-rw-r--r--modules/mono/editor/godotsharp_export.cpp146
-rw-r--r--modules/mono/editor/godotsharp_export.h4
-rw-r--r--modules/mono/editor/mono_bottom_panel.cpp2
-rw-r--r--modules/mono/glue/Managed/Files/Extensions/NodeExtensions.cs24
-rw-r--r--modules/mono/glue/Managed/Files/Extensions/ResourceLoaderExtensions.cs4
-rw-r--r--modules/mono/glue/Managed/Files/GD.cs4
-rw-r--r--modules/mono/glue/nodepath_glue.cpp2
-rw-r--r--modules/mono/glue/rid_glue.cpp2
-rw-r--r--modules/mono/godotsharp_dirs.cpp89
-rw-r--r--modules/mono/godotsharp_dirs.h11
-rw-r--r--modules/mono/mono_gd/gd_mono.cpp184
-rw-r--r--modules/mono/mono_gd/gd_mono.h46
-rw-r--r--modules/mono/mono_gd/gd_mono_assembly.cpp148
-rw-r--r--modules/mono/mono_gd/gd_mono_assembly.h3
-rw-r--r--modules/mono/mono_gd/gd_mono_field.cpp316
-rw-r--r--modules/mono/mono_gd/gd_mono_header.h10
-rw-r--r--modules/mono/mono_gd/gd_mono_marshal.cpp317
-rw-r--r--modules/mono/mono_gd/gd_mono_marshal.h285
-rw-r--r--modules/mono/utils/macros.h9
-rw-r--r--modules/opensimplex/doc_classes/NoiseTexture.xml18
-rw-r--r--modules/thekla_unwrap/config.py3
-rw-r--r--modules/theora/video_stream_theora.cpp1
-rw-r--r--modules/visual_script/visual_script.cpp20
-rw-r--r--modules/visual_script/visual_script.h1
-rw-r--r--modules/visual_script/visual_script_editor.cpp10
-rw-r--r--modules/visual_script/visual_script_editor.h2
-rw-r--r--modules/visual_script/visual_script_nodes.cpp18
-rw-r--r--modules/visual_script/visual_script_property_selector.cpp62
-rw-r--r--modules/webm/video_stream_webm.cpp1
-rw-r--r--modules/websocket/emws_server.cpp3
-rw-r--r--modules/websocket/lws_client.cpp21
-rw-r--r--modules/websocket/websocket_multiplayer.cpp2
-rw-r--r--modules/xatlas_unwrap/config.py4
-rw-r--r--modules/xatlas_unwrap/register_types.cpp18
75 files changed, 1948 insertions, 1079 deletions
diff --git a/modules/bullet/area_bullet.cpp b/modules/bullet/area_bullet.cpp
index a3ba3aa0bf..a0486443c2 100644
--- a/modules/bullet/area_bullet.cpp
+++ b/modules/bullet/area_bullet.cpp
@@ -58,7 +58,7 @@ AreaBullet::AreaBullet() :
isScratched(false) {
btGhost = bulletnew(btGhostObject);
- btGhost->setCollisionShape(BulletPhysicsServer::get_empty_shape());
+ reload_shapes();
setupBulletCollisionObject(btGhost);
/// Collision objects with a callback still have collision response with dynamic rigid bodies.
/// In order to use collision objects as trigger, you have to disable the collision response.
@@ -166,11 +166,9 @@ bool AreaBullet::is_monitoring() const {
return get_godot_object_flags() & GOF_IS_MONITORING_AREA;
}
-void AreaBullet::main_shape_resetted() {
- if (get_main_shape())
- btGhost->setCollisionShape(get_main_shape());
- else
- btGhost->setCollisionShape(BulletPhysicsServer::get_empty_shape());
+void AreaBullet::main_shape_changed() {
+ CRASH_COND(!get_main_shape())
+ btGhost->setCollisionShape(get_main_shape());
}
void AreaBullet::reload_body() {
diff --git a/modules/bullet/area_bullet.h b/modules/bullet/area_bullet.h
index a6bf73906c..1c5962cfe3 100644
--- a/modules/bullet/area_bullet.h
+++ b/modules/bullet/area_bullet.h
@@ -142,7 +142,7 @@ public:
_FORCE_INLINE_ void set_spOv_priority(int p_priority) { spOv_priority = p_priority; }
_FORCE_INLINE_ int get_spOv_priority() { return spOv_priority; }
- virtual void main_shape_resetted();
+ virtual void main_shape_changed();
virtual void reload_body();
virtual void set_space(SpaceBullet *p_space);
@@ -157,6 +157,7 @@ public:
virtual void on_collision_filters_change();
virtual void on_collision_checker_start() {}
+ virtual void on_collision_checker_end() { isTransformChanged = false; }
void add_overlap(CollisionObjectBullet *p_otherObject);
void put_overlap_as_exit(int p_index);
diff --git a/modules/bullet/bullet_physics_server.cpp b/modules/bullet/bullet_physics_server.cpp
index 53a38967c3..315afe3d72 100644
--- a/modules/bullet/bullet_physics_server.cpp
+++ b/modules/bullet/bullet_physics_server.cpp
@@ -74,12 +74,6 @@
body->get_space()->add_constraint(joint, joint->is_disabled_collisions_between_bodies());
// <--------------- Joint creation asserts
-btEmptyShape *BulletPhysicsServer::emptyShape(ShapeBullet::create_shape_empty());
-
-btEmptyShape *BulletPhysicsServer::get_empty_shape() {
- return emptyShape;
-}
-
void BulletPhysicsServer::_bind_methods() {
//ClassDB::bind_method(D_METHOD("DoTest"), &BulletPhysicsServer::DoTest);
}
@@ -89,9 +83,7 @@ BulletPhysicsServer::BulletPhysicsServer() :
active(true),
active_spaces_count(0) {}
-BulletPhysicsServer::~BulletPhysicsServer() {
- bulletdelete(emptyShape);
-}
+BulletPhysicsServer::~BulletPhysicsServer() {}
RID BulletPhysicsServer::shape_create(ShapeType p_shape) {
ShapeBullet *shape = NULL;
@@ -338,7 +330,7 @@ Transform BulletPhysicsServer::area_get_shape_transform(RID p_area, int p_shape_
void BulletPhysicsServer::area_remove_shape(RID p_area, int p_shape_idx) {
AreaBullet *area = area_owner.get(p_area);
ERR_FAIL_COND(!area);
- return area->remove_shape(p_shape_idx);
+ return area->remove_shape_full(p_shape_idx);
}
void BulletPhysicsServer::area_clear_shapes(RID p_area) {
@@ -346,7 +338,7 @@ void BulletPhysicsServer::area_clear_shapes(RID p_area) {
ERR_FAIL_COND(!area);
for (int i = area->get_shape_count(); 0 < i; --i)
- area->remove_shape(0);
+ area->remove_shape_full(0);
}
void BulletPhysicsServer::area_set_shape_disabled(RID p_area, int p_shape_idx, bool p_disabled) {
@@ -567,7 +559,7 @@ void BulletPhysicsServer::body_remove_shape(RID p_body, int p_shape_idx) {
RigidBodyBullet *body = rigid_body_owner.get(p_body);
ERR_FAIL_COND(!body);
- body->remove_shape(p_shape_idx);
+ body->remove_shape_full(p_shape_idx);
}
void BulletPhysicsServer::body_clear_shapes(RID p_body) {
@@ -1486,7 +1478,7 @@ void BulletPhysicsServer::free(RID p_rid) {
// Notify the shape is configured
for (Map<ShapeOwnerBullet *, int>::Element *element = shape->get_owners().front(); element; element = element->next()) {
- static_cast<ShapeOwnerBullet *>(element->key())->remove_shape(shape);
+ static_cast<ShapeOwnerBullet *>(element->key())->remove_shape_full(shape);
}
shape_owner.free(p_rid);
@@ -1497,7 +1489,7 @@ void BulletPhysicsServer::free(RID p_rid) {
body->set_space(NULL);
- body->remove_all_shapes(true);
+ body->remove_all_shapes(true, true);
rigid_body_owner.free(p_rid);
bulletdelete(body);
@@ -1517,7 +1509,7 @@ void BulletPhysicsServer::free(RID p_rid) {
area->set_space(NULL);
- area->remove_all_shapes(true);
+ area->remove_all_shapes(true, true);
area_owner.free(p_rid);
bulletdelete(area);
diff --git a/modules/bullet/bullet_physics_server.h b/modules/bullet/bullet_physics_server.h
index 4c52cace67..6b7dcd86e6 100644
--- a/modules/bullet/bullet_physics_server.h
+++ b/modules/bullet/bullet_physics_server.h
@@ -60,13 +60,6 @@ class BulletPhysicsServer : public PhysicsServer {
mutable RID_Owner<SoftBodyBullet> soft_body_owner;
mutable RID_Owner<JointBullet> joint_owner;
-private:
- /// This is used as replacement of collision shape inside a compound or main shape
- static btEmptyShape *emptyShape;
-
-public:
- static btEmptyShape *get_empty_shape();
-
protected:
static void _bind_methods();
diff --git a/modules/bullet/bullet_utilities.h b/modules/bullet/bullet_utilities.h
index 029eb6691a..553c1d0384 100644
--- a/modules/bullet/bullet_utilities.h
+++ b/modules/bullet/bullet_utilities.h
@@ -39,7 +39,8 @@
new cl
#define bulletdelete(cl) \
- delete cl; \
- cl = NULL;
-
+ { \
+ delete cl; \
+ cl = NULL; \
+ }
#endif
diff --git a/modules/bullet/collision_object_bullet.cpp b/modules/bullet/collision_object_bullet.cpp
index 61834b8e3f..402a276f95 100644
--- a/modules/bullet/collision_object_bullet.cpp
+++ b/modules/bullet/collision_object_bullet.cpp
@@ -43,8 +43,7 @@
@author AndreaCatania
*/
-#define enableDynamicAabbTree true
-#define initialChildCapacity 1
+#define enableDynamicAabbTree false
CollisionObjectBullet::ShapeWrapper::~ShapeWrapper() {}
@@ -60,7 +59,10 @@ void CollisionObjectBullet::ShapeWrapper::set_transform(const btTransform &p_tra
void CollisionObjectBullet::ShapeWrapper::claim_bt_shape(const btVector3 &body_scale) {
if (!bt_shape) {
- bt_shape = shape->create_bt_shape(scale * body_scale);
+ if (active)
+ bt_shape = shape->create_bt_shape(scale * body_scale);
+ else
+ bt_shape = ShapeBullet::create_shape_empty();
}
}
@@ -72,7 +74,8 @@ CollisionObjectBullet::CollisionObjectBullet(Type p_type) :
bt_collision_object(NULL),
body_scale(1., 1., 1.),
force_shape_reset(false),
- space(NULL) {}
+ space(NULL),
+ isTransformChanged(false) {}
CollisionObjectBullet::~CollisionObjectBullet() {
// Remove all overlapping, notify is not required since godot take care of it
@@ -90,7 +93,7 @@ bool equal(real_t first, real_t second) {
void CollisionObjectBullet::set_body_scale(const Vector3 &p_new_scale) {
if (!equal(p_new_scale[0], body_scale[0]) || !equal(p_new_scale[1], body_scale[1]) || !equal(p_new_scale[2], body_scale[2])) {
body_scale = p_new_scale;
- on_body_scale_changed();
+ body_scale_changed();
}
}
@@ -100,7 +103,7 @@ btVector3 CollisionObjectBullet::get_bt_body_scale() const {
return s;
}
-void CollisionObjectBullet::on_body_scale_changed() {
+void CollisionObjectBullet::body_scale_changed() {
force_shape_reset = true;
}
@@ -186,49 +189,33 @@ Transform CollisionObjectBullet::get_transform() const {
void CollisionObjectBullet::set_transform__bullet(const btTransform &p_global_transform) {
bt_collision_object->setWorldTransform(p_global_transform);
+ notify_transform_changed();
}
const btTransform &CollisionObjectBullet::get_transform__bullet() const {
return bt_collision_object->getWorldTransform();
}
+void CollisionObjectBullet::notify_transform_changed() {
+ isTransformChanged = true;
+}
+
RigidCollisionObjectBullet::RigidCollisionObjectBullet(Type p_type) :
CollisionObjectBullet(p_type),
mainShape(NULL) {
}
RigidCollisionObjectBullet::~RigidCollisionObjectBullet() {
- remove_all_shapes(true);
+ remove_all_shapes(true, true);
if (mainShape && mainShape->isCompound()) {
bulletdelete(mainShape);
}
}
-/* Not used
-void RigidCollisionObjectBullet::_internal_replaceShape(btCollisionShape *p_old_shape, btCollisionShape *p_new_shape) {
- bool at_least_one_was_changed = false;
- btTransform old_transf;
- // Inverse because I need remove the shapes
- // Fetch all shapes to be sure to remove all shapes
- for (int i = compoundShape->getNumChildShapes() - 1; 0 <= i; --i) {
- if (compoundShape->getChildShape(i) == p_old_shape) {
-
- old_transf = compoundShape->getChildTransform(i);
- compoundShape->removeChildShapeByIndex(i);
- compoundShape->addChildShape(old_transf, p_new_shape);
- at_least_one_was_changed = true;
- }
- }
-
- if (at_least_one_was_changed) {
- on_shapes_changed();
- }
-}*/
-
void RigidCollisionObjectBullet::add_shape(ShapeBullet *p_shape, const Transform &p_transform) {
shapes.push_back(ShapeWrapper(p_shape, p_transform, true));
p_shape->add_owner(this);
- on_shapes_changed();
+ reload_shapes();
}
void RigidCollisionObjectBullet::set_shape(int p_index, ShapeBullet *p_shape) {
@@ -236,17 +223,31 @@ void RigidCollisionObjectBullet::set_shape(int p_index, ShapeBullet *p_shape) {
shp.shape->remove_owner(this);
p_shape->add_owner(this);
shp.shape = p_shape;
- on_shapes_changed();
+ reload_shapes();
}
-void RigidCollisionObjectBullet::set_shape_transform(int p_index, const Transform &p_transform) {
- ERR_FAIL_INDEX(p_index, get_shape_count());
+int RigidCollisionObjectBullet::get_shape_count() const {
+ return shapes.size();
+}
- shapes.write[p_index].set_transform(p_transform);
- on_shape_changed(shapes.write[p_index].shape);
+ShapeBullet *RigidCollisionObjectBullet::get_shape(int p_index) const {
+ return shapes[p_index].shape;
}
-void RigidCollisionObjectBullet::remove_shape(ShapeBullet *p_shape) {
+btCollisionShape *RigidCollisionObjectBullet::get_bt_shape(int p_index) const {
+ return shapes[p_index].bt_shape;
+}
+
+int RigidCollisionObjectBullet::find_shape(ShapeBullet *p_shape) const {
+ const int size = shapes.size();
+ for (int i = 0; i < size; ++i) {
+ if (shapes[i].shape == p_shape)
+ return i;
+ }
+ return -1;
+}
+
+void RigidCollisionObjectBullet::remove_shape_full(ShapeBullet *p_shape) {
// Remove the shape, all the times it appears
// Reverse order required for delete.
for (int i = shapes.size() - 1; 0 <= i; --i) {
@@ -255,35 +256,32 @@ void RigidCollisionObjectBullet::remove_shape(ShapeBullet *p_shape) {
shapes.remove(i);
}
}
- on_shapes_changed();
+ reload_shapes();
}
-void RigidCollisionObjectBullet::remove_shape(int p_index) {
+void RigidCollisionObjectBullet::remove_shape_full(int p_index) {
ERR_FAIL_INDEX(p_index, get_shape_count());
internal_shape_destroy(p_index);
shapes.remove(p_index);
- on_shapes_changed();
+ reload_shapes();
}
-void RigidCollisionObjectBullet::remove_all_shapes(bool p_permanentlyFromThisBody) {
+void RigidCollisionObjectBullet::remove_all_shapes(bool p_permanentlyFromThisBody, bool p_force_not_reload) {
// Reverse order required for delete.
for (int i = shapes.size() - 1; 0 <= i; --i) {
internal_shape_destroy(i, p_permanentlyFromThisBody);
}
shapes.clear();
- on_shapes_changed();
-}
-
-int RigidCollisionObjectBullet::get_shape_count() const {
- return shapes.size();
+ if (!p_force_not_reload)
+ reload_shapes();
}
-ShapeBullet *RigidCollisionObjectBullet::get_shape(int p_index) const {
- return shapes[p_index].shape;
-}
+void RigidCollisionObjectBullet::set_shape_transform(int p_index, const Transform &p_transform) {
+ ERR_FAIL_INDEX(p_index, get_shape_count());
-btCollisionShape *RigidCollisionObjectBullet::get_bt_shape(int p_index) const {
- return shapes[p_index].bt_shape;
+ shapes.write[p_index].set_transform(p_transform);
+ // Note, enableDynamicAabbTree is false because on transform change compound is destroyed
+ reload_shapes();
}
const btTransform &RigidCollisionObjectBullet::get_bt_shape_transform(int p_index) const {
@@ -296,21 +294,27 @@ Transform RigidCollisionObjectBullet::get_shape_transform(int p_index) const {
return trs;
}
-void RigidCollisionObjectBullet::on_shape_changed(const ShapeBullet *const p_shape) {
- const int size = shapes.size();
- for (int i = 0; i < size; ++i) {
- if (shapes[i].shape == p_shape) {
- bulletdelete(shapes.write[i].bt_shape);
- }
- }
- on_shapes_changed();
+void RigidCollisionObjectBullet::set_shape_disabled(int p_index, bool p_disabled) {
+ shapes.write[p_index].active = !p_disabled;
+ shape_changed(p_index);
+}
+
+bool RigidCollisionObjectBullet::is_shape_disabled(int p_index) {
+ return !shapes[p_index].active;
}
-void RigidCollisionObjectBullet::on_shapes_changed() {
+void RigidCollisionObjectBullet::shape_changed(int p_shape_index) {
+ bulletdelete(shapes.write[p_shape_index].bt_shape);
+ reload_shapes();
+}
+
+void RigidCollisionObjectBullet::reload_shapes() {
if (mainShape && mainShape->isCompound()) {
+ // Destroy compound
bulletdelete(mainShape);
}
+
mainShape = NULL;
ShapeWrapper *shpWrapper;
@@ -325,55 +329,38 @@ void RigidCollisionObjectBullet::on_shapes_changed() {
force_shape_reset = false;
}
- btVector3 body_scale(get_bt_body_scale());
-
- if (!shape_count)
- return;
+ const btVector3 body_scale(get_bt_body_scale());
// Try to optimize by not using compound
if (1 == shape_count) {
shpWrapper = &shapes.write[0];
- if (shpWrapper->active && shpWrapper->transform.getOrigin().isZero() && shpWrapper->transform.getBasis() == shpWrapper->transform.getBasis().getIdentity()) {
+ if (shpWrapper->transform.getOrigin().isZero() && shpWrapper->transform.getBasis() == shpWrapper->transform.getBasis().getIdentity()) {
shpWrapper->claim_bt_shape(body_scale);
mainShape = shpWrapper->bt_shape;
- main_shape_resetted();
+ main_shape_changed();
return;
}
}
- btCompoundShape *compoundShape = bulletnew(btCompoundShape(enableDynamicAabbTree, initialChildCapacity));
+ // Optimization not possible use a compound shape
+ btCompoundShape *compoundShape = bulletnew(btCompoundShape(enableDynamicAabbTree, shape_count));
- // Insert all shapes into compound
for (int i(0); i < shape_count; ++i) {
shpWrapper = &shapes.write[i];
- if (shpWrapper->active) {
- shpWrapper->claim_bt_shape(body_scale);
-
- btTransform scaled_shape_transform(shpWrapper->transform);
- scaled_shape_transform.getOrigin() *= body_scale;
- compoundShape->addChildShape(scaled_shape_transform, shpWrapper->bt_shape);
- } else {
- compoundShape->addChildShape(btTransform(), BulletPhysicsServer::get_empty_shape());
- }
+ shpWrapper->claim_bt_shape(body_scale);
+ btTransform scaled_shape_transform(shpWrapper->transform);
+ scaled_shape_transform.getOrigin() *= body_scale;
+ compoundShape->addChildShape(scaled_shape_transform, shpWrapper->bt_shape);
}
compoundShape->recalculateLocalAabb();
mainShape = compoundShape;
- main_shape_resetted();
-}
-
-void RigidCollisionObjectBullet::set_shape_disabled(int p_index, bool p_disabled) {
- shapes.write[p_index].active = !p_disabled;
- on_shapes_changed();
-}
-
-bool RigidCollisionObjectBullet::is_shape_disabled(int p_index) {
- return !shapes[p_index].active;
+ main_shape_changed();
}
-void RigidCollisionObjectBullet::on_body_scale_changed() {
- CollisionObjectBullet::on_body_scale_changed();
- on_shapes_changed();
+void RigidCollisionObjectBullet::body_scale_changed() {
+ CollisionObjectBullet::body_scale_changed();
+ reload_shapes();
}
void RigidCollisionObjectBullet::internal_shape_destroy(int p_index, bool p_permanentlyFromThisBody) {
diff --git a/modules/bullet/collision_object_bullet.h b/modules/bullet/collision_object_bullet.h
index ea06cecb17..4a0c805ce5 100644
--- a/modules/bullet/collision_object_bullet.h
+++ b/modules/bullet/collision_object_bullet.h
@@ -132,6 +132,7 @@ protected:
/// New area is added when overlap with new area (AreaBullet::addOverlap), then is removed when it exit (CollisionObjectBullet::onExitArea)
/// This array is used mainly to know which area hold the pointer of this object
Vector<AreaBullet *> areasOverlapped;
+ bool isTransformChanged;
public:
CollisionObjectBullet(Type p_type);
@@ -157,7 +158,7 @@ public:
void set_body_scale(const Vector3 &p_new_scale);
const Vector3 &get_body_scale() const { return body_scale; }
btVector3 get_bt_body_scale() const;
- virtual void on_body_scale_changed();
+ virtual void body_scale_changed();
void add_collision_exception(const CollisionObjectBullet *p_ignoreCollisionObject);
void remove_collision_exception(const CollisionObjectBullet *p_ignoreCollisionObject);
@@ -185,8 +186,9 @@ public:
virtual void reload_body() = 0;
virtual void set_space(SpaceBullet *p_space) = 0;
_FORCE_INLINE_ SpaceBullet *get_space() const { return space; }
- /// This is an event that is called when a collision checker starts
+
virtual void on_collision_checker_start() = 0;
+ virtual void on_collision_checker_end() = 0;
virtual void dispatch_callbacks() = 0;
@@ -197,7 +199,6 @@ public:
virtual void on_enter_area(AreaBullet *p_area) = 0;
virtual void on_exit_area(AreaBullet *p_area);
- /// GodotObjectFlags
void set_godot_object_flags(int flags);
int get_godot_object_flags() const;
@@ -205,11 +206,13 @@ public:
Transform get_transform() const;
virtual void set_transform__bullet(const btTransform &p_global_transform);
virtual const btTransform &get_transform__bullet() const;
+
+ bool is_transform_changed() const { return isTransformChanged; }
+ virtual void notify_transform_changed();
};
class RigidCollisionObjectBullet : public CollisionObjectBullet, public ShapeOwnerBullet {
protected:
- /// This could be a compound shape in case multi please collision are found
btCollisionShape *mainShape;
Vector<ShapeWrapper> shapes;
@@ -219,31 +222,34 @@ public:
_FORCE_INLINE_ const Vector<ShapeWrapper> &get_shapes_wrappers() const { return shapes; }
- /// This is used to set new shape or replace existing
- //virtual void _internal_replaceShape(btCollisionShape *p_old_shape, btCollisionShape *p_new_shape) = 0;
+ _FORCE_INLINE_ btCollisionShape *get_main_shape() const { return mainShape; }
+
void add_shape(ShapeBullet *p_shape, const Transform &p_transform = Transform());
void set_shape(int p_index, ShapeBullet *p_shape);
- void set_shape_transform(int p_index, const Transform &p_transform);
- virtual void remove_shape(ShapeBullet *p_shape);
- void remove_shape(int p_index);
- void remove_all_shapes(bool p_permanentlyFromThisBody = false);
-
- virtual void on_shape_changed(const ShapeBullet *const p_shape);
- virtual void on_shapes_changed();
-
- _FORCE_INLINE_ btCollisionShape *get_main_shape() const { return mainShape; }
int get_shape_count() const;
ShapeBullet *get_shape(int p_index) const;
btCollisionShape *get_bt_shape(int p_index) const;
+
+ int find_shape(ShapeBullet *p_shape) const;
+
+ virtual void remove_shape_full(ShapeBullet *p_shape);
+ void remove_shape_full(int p_index);
+ void remove_all_shapes(bool p_permanentlyFromThisBody = false, bool p_force_not_reload = false);
+
+ void set_shape_transform(int p_index, const Transform &p_transform);
+
const btTransform &get_bt_shape_transform(int p_index) const;
Transform get_shape_transform(int p_index) const;
void set_shape_disabled(int p_index, bool p_disabled);
bool is_shape_disabled(int p_index);
- virtual void main_shape_resetted() = 0;
- virtual void on_body_scale_changed();
+ virtual void shape_changed(int p_shape_index);
+ virtual void reload_shapes();
+
+ virtual void main_shape_changed() = 0;
+ virtual void body_scale_changed();
private:
void internal_shape_destroy(int p_index, bool p_permanentlyFromThisBody = false);
diff --git a/modules/bullet/godot_motion_state.h b/modules/bullet/godot_motion_state.h
index fa58e86589..5844ef8bf3 100644
--- a/modules/bullet/godot_motion_state.h
+++ b/modules/bullet/godot_motion_state.h
@@ -82,7 +82,7 @@ public:
virtual void setWorldTransform(const btTransform &worldTrans) {
bodyCurrentWorldTransform = worldTrans;
- owner->scratch();
+ owner->notify_transform_changed();
}
public:
diff --git a/modules/bullet/rigid_body_bullet.cpp b/modules/bullet/rigid_body_bullet.cpp
index d9a77885b3..37e7718969 100644
--- a/modules/bullet/rigid_body_bullet.cpp
+++ b/modules/bullet/rigid_body_bullet.cpp
@@ -265,13 +265,13 @@ RigidBodyBullet::RigidBodyBullet() :
angularDamp(0),
can_sleep(true),
omit_forces_integration(false),
+ can_integrate_forces(false),
maxCollisionsDetection(0),
collisionsCount(0),
maxAreasWhereIam(10),
areaWhereIamCount(0),
countGravityPointSpaces(0),
isScratchedSpaceOverrideModificator(false),
- isTransformChanged(false),
previousActiveState(true),
force_integration_callback(NULL) {
@@ -279,9 +279,10 @@ RigidBodyBullet::RigidBodyBullet() :
// Initial properties
const btVector3 localInertia(0, 0, 0);
- btRigidBody::btRigidBodyConstructionInfo cInfo(mass, godotMotionState, BulletPhysicsServer::get_empty_shape(), localInertia);
+ btRigidBody::btRigidBodyConstructionInfo cInfo(mass, godotMotionState, NULL, localInertia);
btBody = bulletnew(btRigidBody(cInfo));
+ reload_shapes();
setupBulletCollisionObject(btBody);
set_mode(PhysicsServer::BODY_MODE_RIGID);
@@ -314,11 +315,9 @@ void RigidBodyBullet::destroy_kinematic_utilities() {
}
}
-void RigidBodyBullet::main_shape_resetted() {
- if (get_main_shape())
- btBody->setCollisionShape(get_main_shape());
- else
- btBody->setCollisionShape(BulletPhysicsServer::get_empty_shape());
+void RigidBodyBullet::main_shape_changed() {
+ CRASH_COND(!get_main_shape())
+ btBody->setCollisionShape(get_main_shape());
set_continuous_collision_detection(is_continuous_collision_detection_enabled()); // Reset
}
@@ -333,7 +332,7 @@ void RigidBodyBullet::reload_body() {
void RigidBodyBullet::set_space(SpaceBullet *p_space) {
// Clear the old space if there is one
if (space) {
- isTransformChanged = false;
+ can_integrate_forces = false;
// Remove all eventual constraints
assert_no_constraints();
@@ -350,8 +349,8 @@ void RigidBodyBullet::set_space(SpaceBullet *p_space) {
}
void RigidBodyBullet::dispatch_callbacks() {
- /// The check isTransformChanged is necessary in order to call integrated forces only when the first transform is sent
- if ((btBody->isKinematicObject() || btBody->isActive() || previousActiveState != btBody->isActive()) && force_integration_callback && isTransformChanged) {
+ /// The check isFirstTransformChanged is necessary in order to call integrated forces only when the first transform is sent
+ if ((btBody->isKinematicObject() || btBody->isActive() || previousActiveState != btBody->isActive()) && force_integration_callback && can_integrate_forces) {
if (omit_forces_integration)
btBody->clearForces();
@@ -400,10 +399,6 @@ void RigidBodyBullet::set_force_integration_callback(ObjectID p_id, const String
}
}
-void RigidBodyBullet::scratch() {
- isTransformChanged = true;
-}
-
void RigidBodyBullet::scratch_space_override_modificator() {
isScratchedSpaceOverrideModificator = true;
}
@@ -418,6 +413,11 @@ void RigidBodyBullet::on_collision_checker_start() {
collisionsCount = 0;
}
+void RigidBodyBullet::on_collision_checker_end() {
+ // Always true if active and not a static or kinematic body
+ isTransformChanged = btBody->isActive() && !btBody->isStaticOrKinematicObject();
+}
+
bool RigidBodyBullet::add_collision_object(RigidBodyBullet *p_otherObject, const Vector3 &p_hitWorldLocation, const Vector3 &p_hitLocalLocation, const Vector3 &p_hitNormal, const float &p_appliedImpulse, int p_other_shape_index, int p_local_shape_index) {
if (collisionsCount >= maxCollisionsDetection) {
@@ -520,7 +520,7 @@ real_t RigidBodyBullet::get_param(PhysicsServer::BodyParameter p_param) const {
void RigidBodyBullet::set_mode(PhysicsServer::BodyMode p_mode) {
// This is necessary to block force_integration untile next move
- isTransformChanged = false;
+ can_integrate_forces = false;
destroy_kinematic_utilities();
// The mode change is relevant to its mass
switch (p_mode) {
@@ -777,8 +777,7 @@ void RigidBodyBullet::set_transform__bullet(const btTransform &p_global_transfor
// The kinematic use MotionState class
godotMotionState->moveBody(p_global_transform);
}
- btBody->setWorldTransform(p_global_transform);
- scratch();
+ CollisionObjectBullet::set_transform__bullet(p_global_transform);
}
const btTransform &RigidBodyBullet::get_transform__bullet() const {
@@ -791,8 +790,8 @@ const btTransform &RigidBodyBullet::get_transform__bullet() const {
}
}
-void RigidBodyBullet::on_shapes_changed() {
- RigidCollisionObjectBullet::on_shapes_changed();
+void RigidBodyBullet::reload_shapes() {
+ RigidCollisionObjectBullet::reload_shapes();
const btScalar invMass = btBody->getInvMass();
const btScalar mass = invMass == 0 ? 0 : 1 / invMass;
@@ -987,6 +986,11 @@ void RigidBodyBullet::reload_kinematic_shapes() {
kinematic_utilities->copyAllOwnerShapes();
}
+void RigidBodyBullet::notify_transform_changed() {
+ RigidCollisionObjectBullet::notify_transform_changed();
+ can_integrate_forces = true;
+}
+
void RigidBodyBullet::_internal_set_mass(real_t p_mass) {
btVector3 localInertia(0, 0, 0);
diff --git a/modules/bullet/rigid_body_bullet.h b/modules/bullet/rigid_body_bullet.h
index 25dac30951..26e5018c87 100644
--- a/modules/bullet/rigid_body_bullet.h
+++ b/modules/bullet/rigid_body_bullet.h
@@ -202,6 +202,7 @@ private:
real_t angularDamp;
bool can_sleep;
bool omit_forces_integration;
+ bool can_integrate_forces;
Vector<CollisionData> collisions;
// these parameters are used to avoid vector resize
@@ -216,7 +217,6 @@ private:
int countGravityPointSpaces;
bool isScratchedSpaceOverrideModificator;
- bool isTransformChanged;
bool previousActiveState; // Last check state
ForceIntegrationCallback *force_integration_callback;
@@ -231,17 +231,18 @@ public:
_FORCE_INLINE_ btRigidBody *get_bt_rigid_body() { return btBody; }
- virtual void main_shape_resetted();
+ virtual void main_shape_changed();
virtual void reload_body();
virtual void set_space(SpaceBullet *p_space);
virtual void dispatch_callbacks();
void set_force_integration_callback(ObjectID p_id, const StringName &p_method, const Variant &p_udata = Variant());
- void scratch();
void scratch_space_override_modificator();
virtual void on_collision_filters_change();
virtual void on_collision_checker_start();
+ virtual void on_collision_checker_end();
+
void set_max_collisions_detection(int p_maxCollisionsDetection) {
maxCollisionsDetection = p_maxCollisionsDetection;
collisions.resize(p_maxCollisionsDetection);
@@ -302,7 +303,7 @@ public:
virtual void set_transform__bullet(const btTransform &p_global_transform);
virtual const btTransform &get_transform__bullet() const;
- virtual void on_shapes_changed();
+ virtual void reload_shapes();
virtual void on_enter_area(AreaBullet *p_area);
virtual void on_exit_area(AreaBullet *p_area);
@@ -311,6 +312,8 @@ public:
/// Kinematic
void reload_kinematic_shapes();
+ virtual void notify_transform_changed();
+
private:
void _internal_set_mass(real_t p_mass);
};
diff --git a/modules/bullet/shape_bullet.cpp b/modules/bullet/shape_bullet.cpp
index 4a2263407c..8bb621a863 100644
--- a/modules/bullet/shape_bullet.cpp
+++ b/modules/bullet/shape_bullet.cpp
@@ -34,6 +34,7 @@
#include "bullet_physics_server.h"
#include "bullet_types_converter.h"
#include "bullet_utilities.h"
+#include "core/project_settings.h"
#include "shape_owner_bullet.h"
#include <BulletCollision/CollisionDispatch/btInternalEdgeUtility.h>
@@ -64,7 +65,8 @@ btCollisionShape *ShapeBullet::prepare(btCollisionShape *p_btShape) const {
void ShapeBullet::notifyShapeChanged() {
for (Map<ShapeOwnerBullet *, int>::Element *E = owners.front(); E; E = E->next()) {
- static_cast<ShapeOwnerBullet *>(E->key())->on_shape_changed(this);
+ ShapeOwnerBullet *owner = static_cast<ShapeOwnerBullet *>(E->key());
+ owner->shape_changed(owner->find_shape(this));
}
}
@@ -400,18 +402,22 @@ void ConcavePolygonShapeBullet::setup(PoolVector<Vector3> p_faces) {
btVector3 supVec_1;
btVector3 supVec_2;
for (int i = 0; i < src_face_count; ++i) {
- G_TO_B(facesr[i * 3], supVec_0);
+ G_TO_B(facesr[i * 3 + 0], supVec_0);
G_TO_B(facesr[i * 3 + 1], supVec_1);
G_TO_B(facesr[i * 3 + 2], supVec_2);
- shapeInterface->addTriangle(supVec_0, supVec_1, supVec_2);
+ // Inverted from standard godot otherwise btGenerateInternalEdgeInfo generates wrong edge info
+ shapeInterface->addTriangle(supVec_2, supVec_1, supVec_0);
}
const bool useQuantizedAabbCompression = true;
meshShape = bulletnew(btBvhTriangleMeshShape(shapeInterface, useQuantizedAabbCompression));
- btTriangleInfoMap *triangleInfoMap = new btTriangleInfoMap();
- btGenerateInternalEdgeInfo(meshShape, triangleInfoMap);
+
+ if (GLOBAL_DEF("physics/3d/smooth_trimesh_collision", false)) {
+ btTriangleInfoMap *triangleInfoMap = new btTriangleInfoMap();
+ btGenerateInternalEdgeInfo(meshShape, triangleInfoMap);
+ }
} else {
meshShape = NULL;
ERR_PRINT("The faces count are 0, the mesh shape cannot be created");
@@ -426,6 +432,7 @@ btCollisionShape *ConcavePolygonShapeBullet::create_bt_shape(const btVector3 &p_
cs = ShapeBullet::create_shape_empty();
cs->setLocalScaling(p_implicit_scale);
prepare(cs);
+ cs->setMargin(0);
return cs;
}
diff --git a/modules/bullet/shape_owner_bullet.h b/modules/bullet/shape_owner_bullet.h
index 29d42d12f2..72ddbc482c 100644
--- a/modules/bullet/shape_owner_bullet.h
+++ b/modules/bullet/shape_owner_bullet.h
@@ -45,11 +45,10 @@ class CollisionObjectBullet;
/// E.G. BodyShape is a child of this
class ShapeOwnerBullet {
public:
- /// This is used to set new shape or replace existing
- //virtual void _internal_replaceShape(btCollisionShape *p_old_shape, btCollisionShape *p_new_shape) = 0;
- virtual void on_shape_changed(const ShapeBullet *const p_shape) = 0;
- virtual void on_shapes_changed() = 0;
- virtual void remove_shape(class ShapeBullet *p_shape) = 0;
+ virtual int find_shape(ShapeBullet *p_shape) const = 0;
+ virtual void shape_changed(int p_shape_index) = 0;
+ virtual void reload_shapes() = 0;
+ virtual void remove_shape_full(class ShapeBullet *p_shape) = 0;
virtual ~ShapeOwnerBullet() {}
};
#endif
diff --git a/modules/bullet/soft_body_bullet.cpp b/modules/bullet/soft_body_bullet.cpp
index f373ce5db4..94f350210f 100644
--- a/modules/bullet/soft_body_bullet.cpp
+++ b/modules/bullet/soft_body_bullet.cpp
@@ -72,12 +72,6 @@ void SoftBodyBullet::set_space(SpaceBullet *p_space) {
}
}
-void SoftBodyBullet::dispatch_callbacks() {}
-
-void SoftBodyBullet::on_collision_filters_change() {}
-
-void SoftBodyBullet::on_collision_checker_start() {}
-
void SoftBodyBullet::on_enter_area(AreaBullet *p_area) {}
void SoftBodyBullet::on_exit_area(AreaBullet *p_area) {}
diff --git a/modules/bullet/soft_body_bullet.h b/modules/bullet/soft_body_bullet.h
index c775193584..d04bfca046 100644
--- a/modules/bullet/soft_body_bullet.h
+++ b/modules/bullet/soft_body_bullet.h
@@ -91,9 +91,10 @@ public:
virtual void reload_body();
virtual void set_space(SpaceBullet *p_space);
- virtual void dispatch_callbacks();
- virtual void on_collision_filters_change();
- virtual void on_collision_checker_start();
+ virtual void dispatch_callbacks() {}
+ virtual void on_collision_filters_change() {}
+ virtual void on_collision_checker_start() {}
+ virtual void on_collision_checker_end() {}
virtual void on_enter_area(AreaBullet *p_area);
virtual void on_exit_area(AreaBullet *p_area);
diff --git a/modules/bullet/space_bullet.cpp b/modules/bullet/space_bullet.cpp
index ba4c72f4c7..ab2d1781ad 100644
--- a/modules/bullet/space_bullet.cpp
+++ b/modules/bullet/space_bullet.cpp
@@ -175,7 +175,7 @@ bool BulletPhysicsDirectSpaceState::cast_motion(const RID &p_shape, const Transf
btResult.m_collisionFilterGroup = 0;
btResult.m_collisionFilterMask = p_collision_mask;
- space->dynamicsWorld->convexSweepTest(bt_convex_shape, bt_xform_from, bt_xform_to, btResult, 0.002);
+ space->dynamicsWorld->convexSweepTest(bt_convex_shape, bt_xform_from, bt_xform_to, btResult, space->dynamicsWorld->getDispatchInfo().m_allowedCcdPenetration);
r_closest_unsafe = 1.0;
r_closest_safe = 1.0;
@@ -540,17 +540,20 @@ void onBulletPreTickCallback(btDynamicsWorld *p_dynamicsWorld, btScalar timeStep
void onBulletTickCallback(btDynamicsWorld *p_dynamicsWorld, btScalar timeStep) {
- // Notify all Collision objects the collision checker is started
const btCollisionObjectArray &colObjArray = p_dynamicsWorld->getCollisionObjectArray();
+
+ // Notify all Collision objects the collision checker is started
for (int i = colObjArray.size() - 1; 0 <= i; --i) {
- CollisionObjectBullet *colObj = static_cast<CollisionObjectBullet *>(colObjArray[i]->getUserPointer());
- assert(NULL != colObj);
- colObj->on_collision_checker_start();
+ static_cast<CollisionObjectBullet *>(colObjArray[i]->getUserPointer())->on_collision_checker_start();
}
SpaceBullet *sb = static_cast<SpaceBullet *>(p_dynamicsWorld->getWorldUserInfo());
sb->check_ghost_overlaps();
sb->check_body_collision();
+
+ for (int i = colObjArray.size() - 1; 0 <= i; --i) {
+ static_cast<CollisionObjectBullet *>(colObjArray[i]->getUserPointer())->on_collision_checker_end();
+ }
}
BulletPhysicsDirectSpaceState *SpaceBullet::get_direct_state() {
@@ -571,7 +574,6 @@ void SpaceBullet::create_empty_world(bool p_create_soft_world) {
gjk_epa_pen_solver = bulletnew(btGjkEpaPenetrationDepthSolver);
gjk_simplex_solver = bulletnew(btVoronoiSimplexSolver);
- gjk_simplex_solver->setEqualVertexThreshold(0.f);
void *world_mem;
if (p_create_soft_world) {
@@ -650,7 +652,6 @@ void SpaceBullet::check_ghost_overlaps() {
btConvexShape *area_shape;
btGjkPairDetector::ClosestPointInput gjk_input;
AreaBullet *area;
- RigidCollisionObjectBullet *otherObject;
int x(-1), i(-1), y(-1), z(-1), indexOverlap(-1);
/// For each areas
@@ -677,13 +678,17 @@ void SpaceBullet::check_ghost_overlaps() {
// For each overlapping
for (i = ghostOverlaps.size() - 1; 0 <= i; --i) {
- if (ghostOverlaps[i]->getUserIndex() == CollisionObjectBullet::TYPE_AREA) {
- if (!static_cast<AreaBullet *>(ghostOverlaps[i]->getUserPointer())->is_monitorable())
- continue;
- } else if (ghostOverlaps[i]->getUserIndex() != CollisionObjectBullet::TYPE_RIGID_BODY)
+ btCollisionObject *overlapped_bt_co = ghostOverlaps[i];
+ RigidCollisionObjectBullet *otherObject = static_cast<RigidCollisionObjectBullet *>(overlapped_bt_co->getUserPointer());
+
+ if (!area->is_transform_changed() && !otherObject->is_transform_changed())
continue;
- otherObject = static_cast<RigidCollisionObjectBullet *>(ghostOverlaps[i]->getUserPointer());
+ if (overlapped_bt_co->getUserIndex() == CollisionObjectBullet::TYPE_AREA) {
+ if (!static_cast<AreaBullet *>(overlapped_bt_co->getUserPointer())->is_monitorable())
+ continue;
+ } else if (overlapped_bt_co->getUserIndex() != CollisionObjectBullet::TYPE_RIGID_BODY)
+ continue;
bool hasOverlap = false;
diff --git a/modules/csg/csg.cpp b/modules/csg/csg.cpp
index f0103bb71d..88f3c0338a 100644
--- a/modules/csg/csg.cpp
+++ b/modules/csg/csg.cpp
@@ -805,7 +805,7 @@ void CSGBrushOperation::_merge_poly(MeshMerge &mesh, int p_face_idx, const Build
//process points that were not processed
for (int i = 0; i < edge_process.size(); i++) {
- if (edge_process[i] == true)
+ if (edge_process[i])
continue; //already processed
int intersect_poly = -1;
diff --git a/modules/csg/csg_shape.cpp b/modules/csg/csg_shape.cpp
index d1ef08dc83..44044d2750 100644
--- a/modules/csg/csg_shape.cpp
+++ b/modules/csg/csg_shape.cpp
@@ -521,6 +521,11 @@ CSGBrush *CSGMesh::_build_brush() {
Array arrays = mesh->surface_get_arrays(i);
+ if (arrays.size() == 0) {
+ _make_dirty();
+ ERR_FAIL_COND_V(arrays.size() == 0, NULL);
+ }
+
PoolVector<Vector3> avertices = arrays[Mesh::ARRAY_VERTEX];
if (avertices.size() == 0)
continue;
diff --git a/modules/enet/doc_classes/NetworkedMultiplayerENet.xml b/modules/enet/doc_classes/NetworkedMultiplayerENet.xml
index 76c551e8d7..6d990f6f6f 100644
--- a/modules/enet/doc_classes/NetworkedMultiplayerENet.xml
+++ b/modules/enet/doc_classes/NetworkedMultiplayerENet.xml
@@ -76,7 +76,7 @@
<return type="int">
</return>
<description>
- Returns the channel of the next packet that will be retrieved via [method PacketPeer.get_packet_peer]
+ Returns the channel of the next packet that will be retrieved via [method PacketPeer.get_packet]
</description>
</method>
<method name="get_peer_address" qualifiers="const">
diff --git a/modules/gdnative/nativescript/nativescript.cpp b/modules/gdnative/nativescript/nativescript.cpp
index 37e72bf9f8..3e56275396 100644
--- a/modules/gdnative/nativescript/nativescript.cpp
+++ b/modules/gdnative/nativescript/nativescript.cpp
@@ -1711,8 +1711,7 @@ void NativeReloadNode::_notification(int p_what) {
}
RES ResourceFormatLoaderNativeScript::load(const String &p_path, const String &p_original_path, Error *r_error) {
- ResourceFormatLoaderText rsflt;
- return rsflt.load(p_path, p_original_path, r_error);
+ return ResourceFormatLoaderText::singleton->load(p_path, p_original_path, r_error);
}
void ResourceFormatLoaderNativeScript::get_recognized_extensions(List<String> *p_extensions) const {
diff --git a/modules/gdscript/editor/gdscript_highlighter.cpp b/modules/gdscript/editor/gdscript_highlighter.cpp
index c199667270..e4aee842ba 100644
--- a/modules/gdscript/editor/gdscript_highlighter.cpp
+++ b/modules/gdscript/editor/gdscript_highlighter.cpp
@@ -72,6 +72,7 @@ Map<int, TextEdit::HighlighterInfo> GDScriptSyntaxHighlighter::_get_line_syntax_
bool in_word = false;
bool in_function_name = false;
bool in_variable_declaration = false;
+ bool in_function_args = false;
bool in_member_variable = false;
bool in_node_path = false;
bool is_hex_notation = false;
@@ -220,17 +221,24 @@ Map<int, TextEdit::HighlighterInfo> GDScriptSyntaxHighlighter::_get_line_syntax_
}
if (is_symbol) {
- in_function_name = false;
- in_member_variable = false;
- if (expect_type && str[j] != ' ' && str[j] != '\t' && str[j] != ':') {
+ if (in_function_name) {
+ in_function_args = true;
+ }
+
+ if (in_function_args && str[j] == ')') {
+ in_function_args = false;
+ }
+
+ if (expect_type && prev_is_char) {
expect_type = false;
}
+
if (j > 0 && str[j] == '>' && str[j - 1] == '-') {
expect_type = true;
}
- if (in_variable_declaration || previous_text == "(" || previous_text == ",") {
+ if (in_variable_declaration || in_function_args) {
int k = j;
// Skip space
while (k < str.length() && (str[k] == '\t' || str[k] == ' ')) {
@@ -244,6 +252,8 @@ Map<int, TextEdit::HighlighterInfo> GDScriptSyntaxHighlighter::_get_line_syntax_
}
in_variable_declaration = false;
+ in_function_name = false;
+ in_member_variable = false;
}
if (!in_node_path && in_region == -1 && str[j] == '$') {
diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp
index 0e52225838..ef86ccae14 100644
--- a/modules/gdscript/gdscript.cpp
+++ b/modules/gdscript/gdscript.cpp
@@ -2081,6 +2081,7 @@ GDScriptLanguage::GDScriptLanguage() {
#ifdef DEBUG_ENABLED
GLOBAL_DEF("debug/gdscript/warnings/enable", true);
GLOBAL_DEF("debug/gdscript/warnings/treat_warnings_as_errors", false);
+ GLOBAL_DEF("debug/gdscript/completion/autocomplete_setters_and_getters", false);
for (int i = 0; i < (int)GDScriptWarning::WARNING_MAX; i++) {
String warning = GDScriptWarning::get_name_from_code((GDScriptWarning::Code)i).to_lower();
GLOBAL_DEF("debug/gdscript/warnings/" + warning, !warning.begins_with("unsafe_"));
diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp
index 310c4e21f2..45319c59e7 100644
--- a/modules/gdscript/gdscript_compiler.cpp
+++ b/modules/gdscript/gdscript_compiler.cpp
@@ -1603,13 +1603,13 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Blo
return OK;
}
-Error GDScriptCompiler::_parse_function(GDScript *p_script, const GDScriptParser::ClassNode *p_class, const GDScriptParser::FunctionNode *p_func, bool p_for_ready) {
+Error GDScriptCompiler::_parse_function(Ref<GDScript> p_script, const GDScriptParser::ClassNode *p_class, const GDScriptParser::FunctionNode *p_func, bool p_for_ready) {
Vector<int> bytecode;
CodeGen codegen;
codegen.class_node = p_class;
- codegen.script = p_script;
+ codegen.script = p_script.ptr();
codegen.function_node = p_func;
codegen.stack_max = 0;
codegen.current_line = 0;
@@ -1853,7 +1853,7 @@ Error GDScriptCompiler::_parse_function(GDScript *p_script, const GDScriptParser
return OK;
}
-Error GDScriptCompiler::_parse_class_level(GDScript *p_script, GDScript *p_owner, const GDScriptParser::ClassNode *p_class, bool p_keep_state) {
+Error GDScriptCompiler::_parse_class_level(Ref<GDScript> p_script, Ref<GDScript> p_owner, const GDScriptParser::ClassNode *p_class, bool p_keep_state) {
if (p_class->owner && p_class->owner->owner) {
// Owner is not root
@@ -1887,7 +1887,7 @@ Error GDScriptCompiler::_parse_class_level(GDScript *p_script, GDScript *p_owner
p_script->initializer = NULL;
p_script->subclasses.clear();
- p_script->_owner = p_owner;
+ p_script->_owner = p_owner.ptr();
p_script->tool = p_class->tool;
p_script->name = p_class->name;
@@ -1994,7 +1994,7 @@ Error GDScriptCompiler::_parse_class_level(GDScript *p_script, GDScript *p_owner
StringName name = p_class->_signals[i].name;
- GDScript *c = p_script;
+ GDScript *c = p_script.ptr();
while (c) {
@@ -2054,7 +2054,7 @@ Error GDScriptCompiler::_parse_class_level(GDScript *p_script, GDScript *p_owner
return OK;
}
-Error GDScriptCompiler::_parse_class_blocks(GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state) {
+Error GDScriptCompiler::_parse_class_blocks(Ref<GDScript> p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state) {
//parse methods
bool has_initializer = false;
@@ -2159,7 +2159,7 @@ Error GDScriptCompiler::_parse_class_blocks(GDScript *p_script, const GDScriptPa
return OK;
}
-void GDScriptCompiler::_make_scripts(const GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state) {
+void GDScriptCompiler::_make_scripts(const Ref<GDScript> p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state) {
Map<StringName, Ref<GDScript> > old_subclasses;
@@ -2178,20 +2178,20 @@ void GDScriptCompiler::_make_scripts(const GDScript *p_script, const GDScriptPar
subclass.instance();
}
- subclass->_owner = const_cast<GDScript *>(p_script);
+ subclass->_owner = const_cast<GDScript *>(p_script.ptr());
class_map.insert(name, subclass);
_make_scripts(subclass.ptr(), p_class->subclasses[i], p_keep_state);
}
}
-Error GDScriptCompiler::compile(const GDScriptParser *p_parser, GDScript *p_script, bool p_keep_state) {
+Error GDScriptCompiler::compile(const GDScriptParser *p_parser, Ref<GDScript> p_script, bool p_keep_state) {
err_line = -1;
err_column = -1;
error = "";
parser = p_parser;
- main_script = p_script;
+ main_script = p_script.ptr();
const GDScriptParser::Node *root = parser->get_parse_tree();
ERR_FAIL_COND_V(root->type != GDScriptParser::Node::TYPE_CLASS, ERR_INVALID_DATA);
diff --git a/modules/gdscript/gdscript_compiler.h b/modules/gdscript/gdscript_compiler.h
index 55f5e2b48e..23c6450aa7 100644
--- a/modules/gdscript/gdscript_compiler.h
+++ b/modules/gdscript/gdscript_compiler.h
@@ -148,17 +148,17 @@ class GDScriptCompiler {
int _parse_assign_right_expression(CodeGen &codegen, const GDScriptParser::OperatorNode *p_expression, int p_stack_level);
int _parse_expression(CodeGen &codegen, const GDScriptParser::Node *p_expression, int p_stack_level, bool p_root = false, bool p_initializer = false);
Error _parse_block(CodeGen &codegen, const GDScriptParser::BlockNode *p_block, int p_stack_level = 0, int p_break_addr = -1, int p_continue_addr = -1);
- Error _parse_function(GDScript *p_script, const GDScriptParser::ClassNode *p_class, const GDScriptParser::FunctionNode *p_func, bool p_for_ready = false);
- Error _parse_class_level(GDScript *p_script, GDScript *p_owner, const GDScriptParser::ClassNode *p_class, bool p_keep_state);
- Error _parse_class_blocks(GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state);
- void _make_scripts(const GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state);
+ Error _parse_function(Ref<GDScript> p_script, const GDScriptParser::ClassNode *p_class, const GDScriptParser::FunctionNode *p_func, bool p_for_ready = false);
+ Error _parse_class_level(Ref<GDScript> p_script, Ref<GDScript> p_owner, const GDScriptParser::ClassNode *p_class, bool p_keep_state);
+ Error _parse_class_blocks(Ref<GDScript> p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state);
+ void _make_scripts(const Ref<GDScript> p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state);
int err_line;
int err_column;
StringName source;
String error;
public:
- Error compile(const GDScriptParser *p_parser, GDScript *p_script, bool p_keep_state = false);
+ Error compile(const GDScriptParser *p_parser, Ref<GDScript> p_script, bool p_keep_state = false);
String get_error() const;
int get_error_line() const;
diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp
index ddd9e6b01c..2ce92f340d 100644
--- a/modules/gdscript/gdscript_editor.cpp
+++ b/modules/gdscript/gdscript_editor.cpp
@@ -1999,7 +1999,8 @@ static void _find_identifiers_in_base(const GDScriptCompletionContext &p_context
if (!_static) {
List<MethodInfo> methods;
- ClassDB::get_method_list(type, &methods, false, true);
+ bool is_autocompleting_getters = GLOBAL_GET("debug/gdscript/completion/autocomplete_setters_and_getters").booleanize();
+ ClassDB::get_method_list(type, &methods, false, !is_autocompleting_getters);
for (List<MethodInfo>::Element *E = methods.front(); E; E = E->next()) {
if (E->get().name.begins_with("_")) {
continue;
diff --git a/modules/gdscript/gdscript_function.cpp b/modules/gdscript/gdscript_function.cpp
index 8088dcf17d..31115a4bd9 100644
--- a/modules/gdscript/gdscript_function.cpp
+++ b/modules/gdscript/gdscript_function.cpp
@@ -275,7 +275,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
#endif
uint32_t alloca_size = 0;
- GDScript *_class;
+ GDScript *script;
int ip = 0;
int line = _initial_line;
@@ -286,7 +286,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
line = p_state->line;
ip = p_state->ip;
alloca_size = p_state->stack.size();
- _class = p_state->_class;
+ script = p_state->script.ptr();
p_instance = p_state->instance;
defarg = p_state->defarg;
self = p_state->self;
@@ -368,9 +368,9 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
} else {
self = p_instance->owner;
}
- _class = p_instance->script.ptr();
+ script = p_instance->script.ptr();
} else {
- _class = _script;
+ script = this->_script.ptr();
}
}
@@ -395,7 +395,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
#define GET_VARIANT_PTR(m_v, m_code_ofs) \
Variant *m_v; \
- m_v = _get_variant(_code_ptr[ip + m_code_ofs], p_instance, _class, self, stack, err_text); \
+ m_v = _get_variant(_code_ptr[ip + m_code_ofs], p_instance, script, self, stack, err_text); \
if (unlikely(!m_v)) \
OPCODE_BREAK;
@@ -404,7 +404,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
#define CHECK_SPACE(m_space)
#define GET_VARIANT_PTR(m_v, m_code_ofs) \
Variant *m_v; \
- m_v = _get_variant(_code_ptr[ip + m_code_ofs], p_instance, _class, self, stack, err_text);
+ m_v = _get_variant(_code_ptr[ip + m_code_ofs], p_instance, script, self, stack, err_text);
#endif
@@ -419,8 +419,8 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
profile.call_count++;
profile.frame_call_count++;
}
-#endif
bool exit_ok = false;
+#endif
#ifdef DEBUG_ENABLED
OPCODE_WHILE(ip < _code_size) {
@@ -673,13 +673,15 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
OPCODE(OPCODE_SET_MEMBER) {
CHECK_SPACE(3);
-#ifdef DEBUG_ENABLED
int indexname = _code_ptr[ip + 1];
GD_ERR_BREAK(indexname < 0 || indexname >= _global_names_count);
const StringName *index = &_global_names_ptr[indexname];
GET_VARIANT_PTR(src, 2);
bool valid;
+#ifndef DEBUG_ENABLED
+ ClassDB::set_property(p_instance->owner, *index, *src, &valid);
+#else
bool ok = ClassDB::set_property(p_instance->owner, *index, *src, &valid);
if (!ok) {
err_text = "Internal error setting property: " + String(*index);
@@ -696,12 +698,14 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
OPCODE(OPCODE_GET_MEMBER) {
CHECK_SPACE(3);
-#ifdef DEBUG_ENABLED
int indexname = _code_ptr[ip + 1];
GD_ERR_BREAK(indexname < 0 || indexname >= _global_names_count);
const StringName *index = &_global_names_ptr[indexname];
GET_VARIANT_PTR(dst, 2);
+#ifndef DEBUG_ENABLED
+ ClassDB::get_property(p_instance->owner, *index, *dst);
+#else
bool ok = ClassDB::get_property(p_instance->owner, *index, *dst);
if (!ok) {
err_text = "Internal error getting property: " + String(*index);
@@ -779,11 +783,11 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
OPCODE(OPCODE_ASSIGN_TYPED_NATIVE) {
CHECK_SPACE(4);
- GET_VARIANT_PTR(type, 1);
GET_VARIANT_PTR(dst, 2);
GET_VARIANT_PTR(src, 3);
#ifdef DEBUG_ENABLED
+ GET_VARIANT_PTR(type, 1);
GDScriptNativeClass *nc = Object::cast_to<GDScriptNativeClass>(type->operator Object *());
GD_ERR_BREAK(!nc);
if (src->get_type() != Variant::OBJECT && src->get_type() != Variant::NIL) {
@@ -808,11 +812,11 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
OPCODE(OPCODE_ASSIGN_TYPED_SCRIPT) {
CHECK_SPACE(4);
- GET_VARIANT_PTR(type, 1);
GET_VARIANT_PTR(dst, 2);
GET_VARIANT_PTR(src, 3);
#ifdef DEBUG_ENABLED
+ GET_VARIANT_PTR(type, 1);
Script *base_type = Object::cast_to<Script>(type->operator Object *());
GD_ERR_BREAK(!base_type);
@@ -1181,7 +1185,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
GET_VARIANT_PTR(dst, argc + 3);
- const GDScript *gds = _script;
+ const GDScript *gds = _script.ptr();
const Map<StringName, GDScriptFunction *>::Element *E = NULL;
while (gds->base.ptr()) {
@@ -1252,11 +1256,10 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
gdfs->state.stack_size = _stack_size;
gdfs->state.self = self;
gdfs->state.alloca_size = alloca_size;
- gdfs->state._class = _class;
+ gdfs->state.script = _script;
gdfs->state.ip = ip + ipofs;
gdfs->state.line = line;
gdfs->state.instance_id = (p_instance && p_instance->get_owner()) ? p_instance->get_owner()->get_instance_id() : 0;
- gdfs->state.script_id = _class->get_instance_id();
//gdfs->state.result_pos=ip+ipofs-1;
gdfs->state.defarg = defarg;
gdfs->state.instance = p_instance;
@@ -1310,7 +1313,9 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
#endif
}
+#ifdef DEBUG_ENABLED
exit_ok = true;
+#endif
OPCODE_BREAK;
}
@@ -1387,7 +1392,9 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
CHECK_SPACE(2);
GET_VARIANT_PTR(r, 1);
retvalue = *r;
+#ifdef DEBUG_ENABLED
exit_ok = true;
+#endif
OPCODE_BREAK;
}
@@ -1459,9 +1466,9 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
OPCODE(OPCODE_ASSERT) {
CHECK_SPACE(2);
- GET_VARIANT_PTR(test, 1);
#ifdef DEBUG_ENABLED
+ GET_VARIANT_PTR(test, 1);
bool result = test->booleanize();
if (!result) {
@@ -1516,8 +1523,9 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
DISPATCH_OPCODE;
OPCODE(OPCODE_END) {
-
+#ifdef DEBUG_ENABLED
exit_ok = true;
+#endif
OPCODE_BREAK;
}
@@ -1540,8 +1548,8 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
String err_file;
if (p_instance)
err_file = p_instance->script->path;
- else if (_class)
- err_file = _class->path;
+ else if (script)
+ err_file = script->path;
if (err_file == "")
err_file = "<built-in>";
String err_func = name;
@@ -1756,15 +1764,20 @@ GDScriptFunction::~GDScriptFunction() {
Variant GDScriptFunctionState::_signal_callback(const Variant **p_args, int p_argcount, Variant::CallError &r_error) {
#ifdef DEBUG_ENABLED
- if (state.instance_id && !ObjectDB::get_instance(state.instance_id)) {
- ERR_EXPLAIN("Resumed after yield, but class instance is gone");
+ // Checking this first since it's faster
+ if (!state.script.is_valid()) {
+ ERR_EXPLAIN("Resumed after yield, but script is gone");
ERR_FAIL_V(Variant());
}
- if (state.script_id && !ObjectDB::get_instance(state.script_id)) {
- ERR_EXPLAIN("Resumed after yield, but script is gone");
+ if (state.instance_id && !ObjectDB::get_instance(state.instance_id)) {
+ ERR_EXPLAIN("Resumed after yield, but class instance is gone");
ERR_FAIL_V(Variant());
}
+#else
+ if (!is_valid()) {
+ return Variant();
+ }
#endif
Variant arg;
@@ -1832,12 +1845,12 @@ bool GDScriptFunctionState::is_valid(bool p_extended_check) const {
return false;
if (p_extended_check) {
+ //script gone? (checking this first since it's faster)
+ if (!state.script.is_valid())
+ return false;
//class instance gone?
if (state.instance_id && !ObjectDB::get_instance(state.instance_id))
return false;
- //script gone?
- if (state.script_id && !ObjectDB::get_instance(state.script_id))
- return false;
}
return true;
@@ -1847,13 +1860,14 @@ Variant GDScriptFunctionState::resume(const Variant &p_arg) {
ERR_FAIL_COND_V(!function, Variant());
#ifdef DEBUG_ENABLED
- if (state.instance_id && !ObjectDB::get_instance(state.instance_id)) {
- ERR_EXPLAIN("Resumed after yield, but class instance is gone");
+ // Checking this first since it's faster
+ if (!state.script.is_valid()) {
+ ERR_EXPLAIN("Resumed after yield, but script is gone");
ERR_FAIL_V(Variant());
}
- if (state.script_id && !ObjectDB::get_instance(state.script_id)) {
- ERR_EXPLAIN("Resumed after yield, but script is gone");
+ if (state.instance_id && !ObjectDB::get_instance(state.instance_id)) {
+ ERR_EXPLAIN("Resumed after yield, but class instance is gone");
ERR_FAIL_V(Variant());
}
#endif
diff --git a/modules/gdscript/gdscript_function.h b/modules/gdscript/gdscript_function.h
index bfb6d673f1..a47070de4f 100644
--- a/modules/gdscript/gdscript_function.h
+++ b/modules/gdscript/gdscript_function.h
@@ -225,7 +225,7 @@ private:
bool _static;
MultiplayerAPI::RPCMode rpc_mode;
- GDScript *_script;
+ Ref<GDScript> _script;
StringName name;
Vector<Variant> constants;
@@ -272,15 +272,13 @@ private:
public:
struct CallState {
- ObjectID instance_id; //by debug only
- ObjectID script_id;
-
+ ObjectID instance_id;
GDScriptInstance *instance;
Vector<uint8_t> stack;
int stack_size;
Variant self;
uint32_t alloca_size;
- GDScript *_class;
+ Ref<GDScript> script;
int ip;
int line;
int defarg;
@@ -299,7 +297,7 @@ public:
int get_default_argument_addr(int p_idx) const;
GDScriptDataType get_return_type() const;
GDScriptDataType get_argument_type(int p_idx) const;
- GDScript *get_script() const { return _script; }
+ GDScript *get_script() const { return const_cast<GDScript *>(_script.ptr()); }
StringName get_source() const { return source; }
void debug_get_stack_member_state(int p_line, List<Pair<StringName, int> > *r_stackvars) const;
diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp
index a79fcccaeb..97ac6f7de6 100644
--- a/modules/gdscript/gdscript_parser.cpp
+++ b/modules/gdscript/gdscript_parser.cpp
@@ -679,7 +679,7 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s
if (tokenizer->get_token() == GDScriptTokenizer::TK_BUILT_IN_TYPE) {
Variant::Type ct = tokenizer->get_token_type();
- if (p_parsing_constant == false) {
+ if (!p_parsing_constant) {
if (ct == Variant::ARRAY) {
if (tokenizer->get_token(2) == GDScriptTokenizer::TK_PARENTHESIS_CLOSE) {
ArrayNode *arr = alloc_node<ArrayNode>();
@@ -6709,9 +6709,15 @@ GDScriptParser::DataType GDScriptParser::_reduce_function_call_type(const Operat
}
}
+ bool rets = false;
return_type.has_type = true;
return_type.kind = DataType::BUILTIN;
- return_type.builtin_type = Variant::get_method_return_type(base_type.builtin_type, callee_name);
+ return_type.builtin_type = Variant::get_method_return_type(base_type.builtin_type, callee_name, &rets);
+ // If the method returns, but it might return any type, (Variant::NIL), pretend we don't know the type.
+ // At least make sure we know that it returns
+ if (rets && return_type.builtin_type == Variant::NIL) {
+ return_type.has_type = false;
+ }
break;
}
diff --git a/modules/gdscript/gdscript_tokenizer.cpp b/modules/gdscript/gdscript_tokenizer.cpp
index 77e1b7290e..c37142b3c1 100644
--- a/modules/gdscript/gdscript_tokenizer.cpp
+++ b/modules/gdscript/gdscript_tokenizer.cpp
@@ -128,8 +128,8 @@ const char *GDScriptTokenizer::token_names[TK_MAX] = {
"'.'",
"'?'",
"':'",
- "'->'",
"'$'",
+ "'->'",
"'\\n'",
"PI",
"TAU",
diff --git a/modules/jpg/image_loader_jpegd.cpp b/modules/jpg/image_loader_jpegd.cpp
index a49137ae73..24d40111cf 100644
--- a/modules/jpg/image_loader_jpegd.cpp
+++ b/modules/jpg/image_loader_jpegd.cpp
@@ -48,9 +48,9 @@ Error jpeg_load_image_from_buffer(Image *p_image, const uint8_t *p_buffer, int p
const int image_width = decoder.get_width();
const int image_height = decoder.get_height();
- int comps = decoder.get_num_components();
- if (comps == 3)
- comps = 4; //weird
+ const int comps = decoder.get_num_components();
+ if (comps != 1 && comps != 3)
+ return ERR_FILE_CORRUPT;
if (decoder.begin_decoding() != jpgd::JPGD_SUCCESS)
return ERR_FILE_CORRUPT;
@@ -73,7 +73,19 @@ Error jpeg_load_image_from_buffer(Image *p_image, const uint8_t *p_buffer, int p
}
jpgd::uint8 *pDst = pImage_data + y * dst_bpl;
- memcpy(pDst, pScan_line, dst_bpl);
+
+ if (comps == 1) {
+ memcpy(pDst, pScan_line, dst_bpl);
+ } else {
+ // For images with more than 1 channel pScan_line will always point to a buffer
+ // containing 32-bit RGBA pixels. Alpha is always 255 and we ignore it.
+ for (int x = 0; x < image_width; x++) {
+ pDst[0] = pScan_line[x * 4 + 0];
+ pDst[1] = pScan_line[x * 4 + 1];
+ pDst[2] = pScan_line[x * 4 + 2];
+ pDst += 3;
+ }
+ }
}
//all good
@@ -82,7 +94,7 @@ Error jpeg_load_image_from_buffer(Image *p_image, const uint8_t *p_buffer, int p
if (comps == 1)
fmt = Image::FORMAT_L8;
else
- fmt = Image::FORMAT_RGBA8;
+ fmt = Image::FORMAT_RGB8;
dw = PoolVector<uint8_t>::Write();
p_image->create(image_width, image_height, 0, fmt, data);
diff --git a/modules/mono/SCsub b/modules/mono/SCsub
index 1d5c145027..9a62b0fdc9 100644
--- a/modules/mono/SCsub
+++ b/modules/mono/SCsub
@@ -88,9 +88,6 @@ vars.Update(env_mono)
if env_mono['mono_glue']:
env_mono.Append(CPPDEFINES=['MONO_GLUE_ENABLED'])
-if ARGUMENTS.get('yolo_copy', False):
- env_mono.Append(CPPDEFINES=['YOLO_COPY'])
-
# Configure TLS checks
import tls_configure
@@ -244,16 +241,13 @@ 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)
-env_mono.Append(BUILDERS={'MonoBuildSolution': mono_sln_builder})
-env_mono.MonoBuildSolution(
- 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})
+if env['tools']:
+ output_dir = Dir('#bin').abspath
+ editor_tools_dir = os.path.join(output_dir, 'GodotSharp', 'Tools')
+
+ mono_sln_builder = Builder(action=mono_build_solution)
+ env_mono.Append(BUILDERS={'MonoBuildSolution': mono_sln_builder})
+ env_mono.MonoBuildSolution(
+ os.path.join(editor_tools_dir, 'GodotSharpTools.dll'),
+ 'editor/GodotSharpTools/GodotSharpTools.sln'
+ )
diff --git a/modules/mono/config.py b/modules/mono/config.py
index 01649a972e..8427103ee7 100644
--- a/modules/mono/config.py
+++ b/modules/mono/config.py
@@ -5,7 +5,7 @@ import sys
import subprocess
from distutils.version import LooseVersion
-from SCons.Script import BoolVariable, Dir, Environment, File, PathVariable, SCons, Variables
+from SCons.Script import BoolVariable, Dir, Environment, File, SCons, Variables
monoreg = imp.load_source('mono_reg_utils', 'modules/mono/mono_reg_utils.py')
@@ -55,30 +55,20 @@ def copy_file(src_dir, dst_dir, name):
copyfile(src_path, dst_path)
-def custom_path_is_dir_create(key, val, env):
- """Validator to check if Path is a directory, creating it if it does not exist.
- Similar to PathIsDirCreate, except it uses SCons.Script.Dir() and
- SCons.Script.File() in order to support the '#' top level directory token.
- """
- # Dir constructor will throw an error if the path points to a file
- fsDir = Dir(val)
- if not fsDir.exists:
- os.makedirs(fsDir.abspath)
-
-
def configure(env):
env.use_ptrcall = True
env.add_module_version_string('mono')
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', custom_path_is_dir_create))
+ envvars.Add(BoolVariable('copy_mono_root', 'Make a copy of the mono installation directory to bundle with the editor', False))
envvars.Update(env)
bits = env['bits']
+ tools_enabled = env['tools']
mono_static = env['mono_static']
- assemblies_output_dir = Dir(env['mono_assemblies_output_dir']).abspath
+ copy_mono_root = env['copy_mono_root']
mono_lib_names = ['mono-2.0-sgen', 'monosgen-2.0']
@@ -151,8 +141,6 @@ def configure(env):
raise RuntimeError('Could not find mono shared library in: ' + mono_bin_path)
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'
@@ -204,16 +192,14 @@ def configure(env):
if sys.platform == 'darwin':
env.Append(LINKFLAGS=['-Wl,-force_load,' + mono_lib_file])
- elif sys.platform == 'linux' or sys.platform == 'linux2':
- env.Append(LINKFLAGS=['-Wl,-whole-archive', mono_lib_file, '-Wl,-no-whole-archive'])
else:
- raise RuntimeError('mono-static: Not supported on this platform')
+ env.Append(LINKFLAGS=['-Wl,-whole-archive', mono_lib_file, '-Wl,-no-whole-archive'])
else:
env.Append(LIBS=[mono_lib])
if sys.platform == 'darwin':
env.Append(LIBS=['iconv', 'pthread'])
- elif sys.platform == 'linux' or sys.platform == 'linux2':
+ else:
env.Append(LIBS=['m', 'rt', 'dl', 'pthread'])
if not mono_static:
@@ -223,8 +209,6 @@ def configure(env):
raise RuntimeError('Could not find mono shared library in: ' + mono_lib_path)
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:
assert not mono_static
@@ -238,7 +222,6 @@ def configure(env):
mono_lib_path = ''
mono_so_name = ''
- mono_prefix = subprocess.check_output(['pkg-config', 'mono-2', '--variable=prefix']).decode('utf8').strip()
tmpenv = Environment()
tmpenv.AppendENVPath('PKG_CONFIG_PATH', os.getenv('PKG_CONFIG_PATH'))
@@ -255,16 +238,163 @@ def configure(env):
raise RuntimeError('Could not find mono shared library in: ' + str(tmpenv['LIBPATH']))
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')
+ if not tools_enabled:
+ if not mono_root:
+ mono_root = subprocess.check_output(['pkg-config', 'mono-2', '--variable=prefix']).decode('utf8').strip()
+
+ make_template_dir(env, mono_root)
+
+ if copy_mono_root:
+ if not mono_root:
+ mono_root = subprocess.check_output(['pkg-config', 'mono-2', '--variable=prefix']).decode('utf8').strip()
+
+ if tools_enabled:
+ copy_mono_root_files(env, mono_root)
+ else:
+ print("Ignoring option: 'copy_mono_root'. Only available for builds with 'tools' enabled.")
+
+
+def make_template_dir(env, mono_root):
+ from shutil import rmtree
+
+ platform = env['platform']
+ target = env['target']
+
+ template_dir_name = ''
+
+ if platform == 'windows':
+ template_dir_name = 'data.mono.%s.%s.%s' % (platform, env['bits'], target)
+ elif platform == 'osx':
+ template_dir_name = 'data.mono.%s.%s' % (platform, target)
+ elif platform == 'x11':
+ template_dir_name = 'data.mono.%s.%s.%s' % (platform, env['bits'], target)
+ else:
+ assert False
+
+ output_dir = Dir('#bin').abspath
+ template_dir = os.path.join(output_dir, template_dir_name)
+
+ template_mono_root_dir = os.path.join(template_dir, 'Mono')
+
+ if os.path.isdir(template_mono_root_dir):
+ rmtree(template_mono_root_dir) # Clean first
+
+ # Copy etc/mono/
+
+ template_mono_config_dir = os.path.join(template_mono_root_dir, 'etc', 'mono')
+ copy_mono_etc_dir(mono_root, template_mono_config_dir, env['platform'])
+
+ # Copy the required shared libraries
+
+ copy_mono_shared_libs(mono_root, template_mono_root_dir, env['platform'])
+
+
+def copy_mono_root_files(env, mono_root):
+ from glob import glob
+ from shutil import copy
+ from shutil import rmtree
+
+ if not mono_root:
+ raise RuntimeError('Mono installation directory not found')
+
+ output_dir = Dir('#bin').abspath
+ editor_mono_root_dir = os.path.join(output_dir, 'GodotSharp', 'Mono')
+
+ if os.path.isdir(editor_mono_root_dir):
+ rmtree(editor_mono_root_dir) # Clean first
+
+ # Copy etc/mono/
+
+ editor_mono_config_dir = os.path.join(editor_mono_root_dir, 'etc', 'mono')
+ copy_mono_etc_dir(mono_root, editor_mono_config_dir, env['platform'])
+
+ # Copy the required shared libraries
+
+ copy_mono_shared_libs(mono_root, editor_mono_root_dir, env['platform'])
+
+ # Copy framework assemblies
+
+ mono_framework_dir = os.path.join(mono_root, 'lib', 'mono', '4.5')
+ mono_framework_facades_dir = os.path.join(mono_framework_dir, 'Facades')
+
+ editor_mono_framework_dir = os.path.join(editor_mono_root_dir, 'lib', 'mono', '4.5')
+ editor_mono_framework_facades_dir = os.path.join(editor_mono_framework_dir, 'Facades')
+
+ if not os.path.isdir(editor_mono_framework_dir):
+ os.makedirs(editor_mono_framework_dir)
+ if not os.path.isdir(editor_mono_framework_facades_dir):
+ os.makedirs(editor_mono_framework_facades_dir)
+
+ for assembly in glob(os.path.join(mono_framework_dir, '*.dll')):
+ copy(assembly, editor_mono_framework_dir)
+ for assembly in glob(os.path.join(mono_framework_facades_dir, '*.dll')):
+ copy(assembly, editor_mono_framework_facades_dir)
+
+
+def copy_mono_etc_dir(mono_root, target_mono_config_dir, platform):
+ from distutils.dir_util import copy_tree
+ from glob import glob
+ from shutil import copy
+
+ if not os.path.isdir(target_mono_config_dir):
+ os.makedirs(target_mono_config_dir)
+
+ mono_etc_dir = os.path.join(mono_root, 'etc', 'mono')
+ if not os.path.isdir(mono_etc_dir):
+ mono_etc_dir = ''
+ etc_hint_dirs = []
+ if platform != 'windows':
+ etc_hint_dirs += ['/etc/mono', '/usr/local/etc/mono']
+ if 'MONO_CFG_DIR' in os.environ:
+ etc_hint_dirs += [os.path.join(os.environ['MONO_CFG_DIR'], 'mono')]
+ for etc_hint_dir in etc_hint_dirs:
+ if os.path.isdir(etc_hint_dir):
+ mono_etc_dir = etc_hint_dir
+ break
+ if not mono_etc_dir:
+ raise RuntimeError('Mono installation etc directory not found')
+
+ copy_tree(os.path.join(mono_etc_dir, '2.0'), os.path.join(target_mono_config_dir, '2.0'))
+ copy_tree(os.path.join(mono_etc_dir, '4.0'), os.path.join(target_mono_config_dir, '4.0'))
+ copy_tree(os.path.join(mono_etc_dir, '4.5'), os.path.join(target_mono_config_dir, '4.5'))
+ copy_tree(os.path.join(mono_etc_dir, 'mconfig'), os.path.join(target_mono_config_dir, 'mconfig'))
+
+ for file in glob(os.path.join(mono_etc_dir, '*')):
+ if os.path.isfile(file):
+ copy(file, target_mono_config_dir)
+
+
+def copy_mono_shared_libs(mono_root, target_mono_root_dir, platform):
+ from shutil import copy
+
+ if platform == 'windows':
+ target_mono_bin_dir = os.path.join(target_mono_root_dir, 'bin')
+
+ if not os.path.isdir(target_mono_bin_dir):
+ os.makedirs(target_mono_bin_dir)
+
+ copy(os.path.join(mono_root, 'bin', 'MonoPosixHelper.dll'), os.path.join(target_mono_bin_dir, 'MonoPosixHelper.dll'))
+ else:
+ target_mono_lib_dir = os.path.join(target_mono_root_dir, 'lib')
+
+ if not os.path.isdir(target_mono_lib_dir):
+ os.makedirs(target_mono_lib_dir)
+
+ if platform == 'osx':
+ copy(os.path.join(mono_root, 'lib', 'libMonoPosixHelper.dylib'), os.path.join(target_mono_lib_dir, 'libMonoPosixHelper.dylib'))
+ elif platform == 'x11':
+ copy(os.path.join(mono_root, 'lib', 'libmono-btls-shared.so'), os.path.join(target_mono_lib_dir, 'libmono-btls-shared.so'))
+ copy(os.path.join(mono_root, 'lib', 'libMonoPosixHelper.so'), os.path.join(target_mono_lib_dir, 'libMonoPosixHelper.so'))
+
def configure_for_mono_version(env, mono_version):
if mono_version is None:
raise RuntimeError('Mono JIT compiler version not found')
print('Found Mono JIT compiler version: ' + str(mono_version))
- if mono_version >= LooseVersion("5.12.0"):
+ if mono_version >= LooseVersion('5.12.0'):
env.Append(CPPFLAGS=['-DHAS_PENDING_EXCEPTIONS'])
diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp
index 91fd482235..5160d42367 100644
--- a/modules/mono/csharp_script.cpp
+++ b/modules/mono/csharp_script.cpp
@@ -1194,7 +1194,7 @@ bool CSharpInstance::set(const StringName &p_name, const Variant &p_value) {
MonoObject *ret = method->invoke(mono_object, args);
- if (ret && GDMonoMarshal::unbox<MonoBoolean>(ret) == true)
+ if (ret && GDMonoMarshal::unbox<MonoBoolean>(ret))
return true;
break;
@@ -1459,7 +1459,7 @@ MonoObject *CSharpInstance::_internal_new_managed() {
void CSharpInstance::mono_object_disposed(MonoObject *p_obj) {
#ifdef DEBUG_ENABLED
- CRASH_COND(base_ref == true);
+ CRASH_COND(base_ref);
CRASH_COND(gchandle.is_null());
#endif
CSharpLanguage::get_singleton()->release_script_gchandle(p_obj, gchandle);
@@ -1468,7 +1468,7 @@ void CSharpInstance::mono_object_disposed(MonoObject *p_obj) {
void CSharpInstance::mono_object_disposed_baseref(MonoObject *p_obj, bool p_is_finalizer, bool &r_owner_deleted) {
#ifdef DEBUG_ENABLED
- CRASH_COND(base_ref == false);
+ CRASH_COND(!base_ref);
CRASH_COND(gchandle.is_null());
#endif
if (_unreference_owner_unsafe()) {
diff --git a/modules/mono/doc_classes/GodotSharp.xml b/modules/mono/doc_classes/GodotSharp.xml
index 985c66464b..921c1ca825 100644
--- a/modules/mono/doc_classes/GodotSharp.xml
+++ b/modules/mono/doc_classes/GodotSharp.xml
@@ -23,18 +23,44 @@
Detaches the current thread from the mono runtime.
</description>
</method>
- <method name="is_domain_loaded">
+ <method name="get_domain_id">
+ <return type="int">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="get_scripts_domain_id">
+ <return type="int">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="is_domain_finalizing_for_unload">
+ <return type="bool">
+ </return>
+ <argument index="0" name="domain_id" type="int">
+ </argument>
+ <description>
+ Returns whether the domain is being finalized.
+ </description>
+ </method>
+ <method name="is_runtime_initialized">
+ <return type="bool">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="is_runtime_shutting_down">
<return type="bool">
</return>
<description>
- Returns whether the scripts domain is loaded.
</description>
</method>
- <method name="is_finalizing_domain">
+ <method name="is_scripts_domain_loaded">
<return type="bool">
</return>
<description>
- Returns whether the scripts domain is being finalized.
+ Returns whether the scripts domain is loaded.
</description>
</method>
</methods>
diff --git a/modules/mono/editor/GodotSharpTools/Editor/GodotSharpExport.cs b/modules/mono/editor/GodotSharpTools/Editor/GodotSharpExport.cs
new file mode 100644
index 0000000000..5fd708d539
--- /dev/null
+++ b/modules/mono/editor/GodotSharpTools/Editor/GodotSharpExport.cs
@@ -0,0 +1,74 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Runtime.CompilerServices;
+
+namespace GodotSharpTools.Editor
+{
+ public static class GodotSharpExport
+ {
+ public static void _ExportBegin(string[] features, bool debug, string path, int flags)
+ {
+ var featureSet = new HashSet<string>(features);
+
+ if (PlatformHasTemplateDir(featureSet))
+ {
+ string templateDirName = "data.mono";
+
+ if (featureSet.Contains("Windows"))
+ {
+ templateDirName += ".windows";
+ templateDirName += featureSet.Contains("64") ? ".64" : ".32";
+ }
+ else if (featureSet.Contains("X11"))
+ {
+ templateDirName += ".x11";
+ templateDirName += featureSet.Contains("64") ? ".64" : ".32";
+ }
+ else
+ {
+ throw new NotSupportedException("Target platform not supported");
+ }
+
+ templateDirName += debug ? ".debug" : ".release";
+
+ string templateDirPath = Path.Combine(GetTemplatesDir(), templateDirName);
+
+ if (!Directory.Exists(templateDirPath))
+ throw new FileNotFoundException("Data template directory not found");
+
+ string outputDir = new FileInfo(path).Directory.FullName;
+
+ string outputDataDir = Path.Combine(outputDir, GetDataDirName());
+
+ if (Directory.Exists(outputDataDir))
+ Directory.Delete(outputDataDir, recursive: true); // Clean first
+
+ Directory.CreateDirectory(outputDataDir);
+
+ foreach (string dir in Directory.GetDirectories(templateDirPath, "*", SearchOption.AllDirectories))
+ {
+ Directory.CreateDirectory(Path.Combine(outputDataDir, dir.Substring(templateDirPath.Length + 1)));
+ }
+
+ foreach (string file in Directory.GetFiles(templateDirPath, "*", SearchOption.AllDirectories))
+ {
+ File.Copy(file, Path.Combine(outputDataDir, file.Substring(templateDirPath.Length + 1)));
+ }
+ }
+ }
+
+ public static bool PlatformHasTemplateDir(HashSet<string> featureSet)
+ {
+ // OSX export templates are contained in a zip, so we place
+ // our custom template inside it and let Godot do the rest.
+ return !featureSet.Contains("OSX");
+ }
+
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ extern static string GetTemplatesDir();
+
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ extern static string GetDataDirName();
+ }
+}
diff --git a/modules/mono/editor/GodotSharpTools/GodotSharpTools.csproj b/modules/mono/editor/GodotSharpTools/GodotSharpTools.csproj
index 773e8196f7..fceb732426 100644
--- a/modules/mono/editor/GodotSharpTools/GodotSharpTools.csproj
+++ b/modules/mono/editor/GodotSharpTools/GodotSharpTools.csproj
@@ -41,6 +41,7 @@
<Compile Include="Project\ProjectUtils.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Utils\OS.cs" />
+ <Compile Include="Editor\GodotSharpExport.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
</Project> \ No newline at end of file
diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp
index 2c3435fc1c..710682d3aa 100644
--- a/modules/mono/editor/bindings_generator.cpp
+++ b/modules/mono/editor/bindings_generator.cpp
@@ -97,7 +97,7 @@
#define C_METHOD_MONOARRAY_TO(m_type) C_NS_MONOMARSHAL "::mono_array_to_" #m_type
#define C_METHOD_MONOARRAY_FROM(m_type) C_NS_MONOMARSHAL "::" #m_type "_to_mono_array"
-#define BINDINGS_GENERATOR_VERSION UINT32_C(3)
+#define BINDINGS_GENERATOR_VERSION UINT32_C(5)
const char *BindingsGenerator::TypeInterface::DEFAULT_VARARG_C_IN = "\t%0 %1_in = %1;\n";
@@ -173,23 +173,74 @@ static String snake_to_camel_case(const String &p_identifier, bool p_input_is_up
return ret;
}
-String BindingsGenerator::_determine_enum_prefix(const EnumInterface &p_ienum) {
+int BindingsGenerator::_determine_enum_prefix(const EnumInterface &p_ienum) {
CRASH_COND(p_ienum.constants.empty());
- const List<ConstantInterface>::Element *front = p_ienum.constants.front();
- int candidate_len = front->get().name.length();
+ const ConstantInterface &front_iconstant = p_ienum.constants.front()->get();
+ Vector<String> front_parts = front_iconstant.name.split("_", /* p_allow_empty: */ true);
+ int candidate_len = front_parts.size() - 1;
- for (const List<ConstantInterface>::Element *E = front->next(); E; E = E->next()) {
- int j = 0;
- for (j = 0; j < candidate_len && j < E->get().name.length(); j++) {
- if (front->get().name[j] != E->get().name[j])
- break;
+ if (candidate_len == 0)
+ return 0;
+
+ for (const List<ConstantInterface>::Element *E = p_ienum.constants.front()->next(); E; E = E->next()) {
+ const ConstantInterface &iconstant = E->get();
+
+ Vector<String> parts = iconstant.name.split("_", /* p_allow_empty: */ true);
+
+ int i;
+ for (i = 0; i < candidate_len && i < parts.size(); i++) {
+ if (front_parts[i] != parts[i]) {
+ // HARDCODED: Some Flag enums have the prefix 'FLAG_' for everything except 'FLAGS_DEFAULT' (same for 'METHOD_FLAG_' and'METHOD_FLAGS_DEFAULT').
+ bool hardcoded_exc = (i == candidate_len - 1 && ((front_parts[i] == "FLAGS" && parts[i] == "FLAG") || (front_parts[i] == "FLAG" && parts[i] == "FLAGS")));
+ if (!hardcoded_exc)
+ break;
+ }
}
- candidate_len = j;
+ candidate_len = i;
+
+ if (candidate_len == 0)
+ return 0;
}
- return front->get().name.substr(0, candidate_len);
+ return candidate_len;
+}
+
+void BindingsGenerator::_apply_prefix_to_enum_constants(BindingsGenerator::EnumInterface &p_ienum, int p_prefix_length) {
+
+ if (p_prefix_length > 0) {
+ for (List<ConstantInterface>::Element *E = p_ienum.constants.front(); E; E = E->next()) {
+ int curr_prefix_length = p_prefix_length;
+
+ ConstantInterface &curr_const = E->get();
+
+ String constant_name = curr_const.name;
+
+ Vector<String> parts = constant_name.split("_", /* p_allow_empty: */ true);
+
+ if (parts.size() <= curr_prefix_length)
+ continue;
+
+ if (parts[curr_prefix_length][0] >= '0' && parts[curr_prefix_length][0] <= '9') {
+ // The name of enum constants may begin with a numeric digit when strip from the enum prefix,
+ // so we make the prefix for this constant one word shorter in those cases.
+ for (curr_prefix_length = curr_prefix_length - 1; curr_prefix_length > 0; curr_prefix_length--) {
+ if (parts[curr_prefix_length][0] < '0' || parts[curr_prefix_length][0] > '9')
+ break;
+ }
+ }
+
+ constant_name = "";
+ for (int i = curr_prefix_length; i < parts.size(); i++) {
+ if (i > curr_prefix_length)
+ constant_name += "_";
+ constant_name += parts[i];
+ }
+
+ curr_const.proxy_name = snake_to_pascal_case(constant_name, true);
+ }
+ }
}
void BindingsGenerator::_generate_method_icalls(const TypeInterface &p_itype) {
@@ -272,7 +323,7 @@ void BindingsGenerator::_generate_global_constants(List<String> &p_output) {
}
p_output.push_back(MEMBER_BEGIN "public const int ");
- p_output.push_back(iconstant.name);
+ p_output.push_back(iconstant.proxy_name);
p_output.push_back(" = ");
p_output.push_back(itos(iconstant.value));
p_output.push_back(";");
@@ -334,25 +385,8 @@ void BindingsGenerator::_generate_global_constants(List<String> &p_output) {
p_output.push_back(INDENT2 "/// </summary>\n");
}
- String constant_name = iconstant.name;
-
- if (!ienum.prefix.empty() && constant_name.begins_with(ienum.prefix)) {
- constant_name = constant_name.substr(ienum.prefix.length(), constant_name.length());
- }
-
- if (constant_name[0] >= '0' && constant_name[0] <= '9') {
- // The name of enum constants may begin with a numeric digit when strip from the enum prefix,
- // so we make the prefix one word shorter in those cases.
- int i = 0;
- for (i = ienum.prefix.length() - 1; i >= 0; i--) {
- if (ienum.prefix[i] >= 'A' && ienum.prefix[i] <= 'Z')
- break;
- }
- constant_name = ienum.prefix.substr(i, ienum.prefix.length()) + constant_name;
- }
-
p_output.push_back(INDENT2);
- p_output.push_back(constant_name);
+ p_output.push_back(iconstant.proxy_name);
p_output.push_back(" = ");
p_output.push_back(itos(iconstant.value));
p_output.push_back(E != ienum.constants.back() ? ",\n" : "\n");
@@ -646,8 +680,11 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
List<String> output;
output.push_back("using System;\n"); // IntPtr
+ output.push_back("using System.Diagnostics;\n"); // DebuggerBrowsable
+
output.push_back("\n#pragma warning disable CS1591 // Disable warning: "
"'Missing XML comment for publicly visible type or member'\n");
+
output.push_back("\nnamespace " BINDINGS_NAMESPACE "\n" OPEN_BLOCK);
const DocData::ClassDoc *class_doc = itype.class_doc;
@@ -717,7 +754,7 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
}
output.push_back(MEMBER_BEGIN "public const int ");
- output.push_back(iconstant.name);
+ output.push_back(iconstant.proxy_name);
output.push_back(" = ");
output.push_back(itos(iconstant.value));
output.push_back(";");
@@ -757,25 +794,8 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
output.push_back(INDENT3 "/// </summary>\n");
}
- String constant_name = iconstant.name;
-
- if (!ienum.prefix.empty() && constant_name.begins_with(ienum.prefix)) {
- constant_name = constant_name.substr(ienum.prefix.length(), constant_name.length());
- }
-
- if (constant_name[0] >= '0' && constant_name[0] <= '9') {
- // The name of enum constants may begin with a numeric digit when strip from the enum prefix,
- // so we make the prefix one word shorter in those cases.
- int i = 0;
- for (i = ienum.prefix.length() - 1; i >= 0; i--) {
- if (ienum.prefix[i] >= 'A' && ienum.prefix[i] <= 'Z')
- break;
- }
- constant_name = ienum.prefix.substr(i, ienum.prefix.length()) + constant_name;
- }
-
output.push_back(INDENT3);
- output.push_back(constant_name);
+ output.push_back(iconstant.proxy_name);
output.push_back(" = ");
output.push_back(itos(iconstant.value));
output.push_back(E != ienum.constants.back() ? ",\n" : "\n");
@@ -1086,7 +1106,7 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
// Generate method
{
if (!p_imethod.is_virtual && !p_imethod.requires_object_call) {
- p_output.push_back(MEMBER_BEGIN "private static IntPtr ");
+ p_output.push_back(MEMBER_BEGIN "[DebuggerBrowsable(DebuggerBrowsableState.Never)]" MEMBER_BEGIN "private static IntPtr ");
p_output.push_back(method_bind_field + " = Object." ICALL_GET_METHODBIND "(" BINDINGS_NATIVE_NAME_FIELD ", \"");
p_output.push_back(p_imethod.name);
p_output.push_back("\");\n");
@@ -1269,12 +1289,12 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) {
output.push_back("namespace GodotSharpBindings\n" OPEN_BLOCK "\n");
output.push_back("uint64_t get_core_api_hash() { return ");
- output.push_back(String::num_uint64(GDMono::get_singleton()->get_api_core_hash()) + "; }\n");
+ output.push_back(String::num_uint64(GDMono::get_singleton()->get_api_core_hash()) + "U; }\n");
output.push_back("#ifdef TOOLS_ENABLED\n"
"uint64_t get_editor_api_hash() { return ");
- output.push_back(String::num_uint64(GDMono::get_singleton()->get_api_editor_hash()) +
- "; }\n#endif // TOOLS_ENABLED\n");
+ output.push_back(String::num_uint64(GDMono::get_singleton()->get_api_editor_hash()) + "U; }\n");
+ output.push_back("#endif // TOOLS_ENABLED\n");
output.push_back("uint32_t get_bindings_version() { return ");
output.push_back(String::num_uint64(BINDINGS_GENERATOR_VERSION) + "; }\n");
@@ -1843,11 +1863,13 @@ void BindingsGenerator::_populate_object_type_interfaces() {
EnumInterface ienum(enum_proxy_cname);
const List<StringName> &constants = enum_map.get(*k);
for (const List<StringName>::Element *E = constants.front(); E; E = E->next()) {
- int *value = class_info->constant_map.getptr(E->get());
+ const StringName &constant_cname = E->get();
+ String constant_name = constant_cname.operator String();
+ int *value = class_info->constant_map.getptr(constant_cname);
ERR_FAIL_NULL(value);
- constant_list.erase(E->get().operator String());
+ constant_list.erase(constant_name);
- ConstantInterface iconstant(snake_to_pascal_case(E->get(), true), *value);
+ ConstantInterface iconstant(constant_name, snake_to_pascal_case(constant_name, true), *value);
iconstant.const_doc = NULL;
for (int i = 0; i < itype.class_doc->constants.size(); i++) {
@@ -1862,7 +1884,9 @@ void BindingsGenerator::_populate_object_type_interfaces() {
ienum.constants.push_back(iconstant);
}
- ienum.prefix = _determine_enum_prefix(ienum);
+ int prefix_length = _determine_enum_prefix(ienum);
+
+ _apply_prefix_to_enum_constants(ienum, prefix_length);
itype.enums.push_back(ienum);
@@ -1876,10 +1900,11 @@ void BindingsGenerator::_populate_object_type_interfaces() {
}
for (const List<String>::Element *E = constant_list.front(); E; E = E->next()) {
- int *value = class_info->constant_map.getptr(E->get());
+ const String &constant_name = E->get();
+ int *value = class_info->constant_map.getptr(StringName(E->get()));
ERR_FAIL_NULL(value);
- ConstantInterface iconstant(snake_to_pascal_case(E->get(), true), *value);
+ ConstantInterface iconstant(constant_name, snake_to_pascal_case(constant_name, true), *value);
iconstant.const_doc = NULL;
for (int i = 0; i < itype.class_doc->constants.size(); i++) {
@@ -1990,18 +2015,18 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
TypeInterface itype;
-#define INSERT_STRUCT_TYPE(m_type, m_type_in) \
- { \
- itype = TypeInterface::create_value_type(String(#m_type)); \
- itype.c_in = "\tMARSHALLED_IN(" #m_type ", %1, %1_in);\n"; \
- itype.c_out = "\tMARSHALLED_OUT(" #m_type ", %1, ret_out)\n" \
- "\treturn mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(%2), ret_out);\n"; \
- itype.c_arg_in = "&%s_in"; \
- itype.c_type_in = m_type_in; \
- itype.cs_in = "ref %s"; \
- itype.cs_out = "return (%1)%0;"; \
- itype.im_type_out = "object"; \
- builtin_types.insert(itype.cname, itype); \
+#define INSERT_STRUCT_TYPE(m_type, m_type_in) \
+ { \
+ itype = TypeInterface::create_value_type(String(#m_type)); \
+ itype.c_in = "\t%0 %1_in = MARSHALLED_IN(" #m_type ", %1);\n"; \
+ itype.c_out = "\treturn MARSHALLED_OUT(" #m_type ", %1);\n"; \
+ itype.c_arg_in = "&%s_in"; \
+ itype.c_type_in = "GDMonoMarshal::M_" #m_type "*"; \
+ itype.c_type_out = "GDMonoMarshal::M_" #m_type; \
+ itype.cs_in = "ref %s"; \
+ itype.cs_out = "return (%1)%0;"; \
+ itype.im_type_out = itype.cs_type; \
+ builtin_types.insert(itype.cname, itype); \
}
INSERT_STRUCT_TYPE(Vector2, "real_t*")
@@ -2019,26 +2044,31 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
// bool
itype = TypeInterface::create_value_type(String("bool"));
- itype.c_arg_in = "&%s";
- // /* MonoBoolean <---> bool
- itype.c_in = "\t%0 %1_in = (%0)%1;\n";
- itype.c_out = "\treturn (%0)%1;\n";
- itype.c_type = "bool";
- // */
- itype.c_type_in = "MonoBoolean";
- itype.c_type_out = itype.c_type_in;
+
+ {
+ // MonoBoolean <---> bool
+ itype.c_in = "\t%0 %1_in = (%0)%1;\n";
+ itype.c_out = "\treturn (%0)%1;\n";
+ itype.c_type = "bool";
+ itype.c_type_in = "MonoBoolean";
+ itype.c_type_out = itype.c_type_in;
+ itype.c_arg_in = "&%s_in";
+ }
itype.im_type_in = itype.name;
itype.im_type_out = itype.name;
builtin_types.insert(itype.cname, itype);
// int
+ // C interface is the same as that of enums. Remember to apply any
+ // changes done here to TypeInterface::postsetup_enum_type as well
itype = TypeInterface::create_value_type(String("int"));
itype.c_arg_in = "&%s_in";
- // /* ptrcall only supports int64_t and uint64_t
- itype.c_in = "\t%0 %1_in = (%0)%1;\n";
- itype.c_out = "\treturn (%0)%1;\n";
- itype.c_type = "int64_t";
- // */
+ {
+ // The expected types for parameters and return value in ptrcall are 'int64_t' or 'uint64_t'.
+ itype.c_in = "\t%0 %1_in = (%0)%1;\n";
+ itype.c_out = "\treturn (%0)%1;\n";
+ itype.c_type = "int64_t";
+ }
itype.c_type_in = "int32_t";
itype.c_type_out = itype.c_type_in;
itype.im_type_in = itype.name;
@@ -2047,21 +2077,22 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
// real_t
itype = TypeInterface();
+ itype.name = "float"; // The name is always "float" in Variant, even with REAL_T_IS_DOUBLE.
+ itype.cname = itype.name;
#ifdef REAL_T_IS_DOUBLE
- itype.name = "double";
+ itype.proxy_name = "double";
#else
- itype.name = "float";
+ itype.proxy_name = "float";
#endif
- itype.cname = itype.name;
- itype.proxy_name = itype.name;
- itype.c_arg_in = "&%s_in";
- //* ptrcall only supports double
- itype.c_in = "\t%0 %1_in = (%0)%1;\n";
- itype.c_out = "\treturn (%0)%1;\n";
- itype.c_type = "double";
- //*/
- itype.c_type_in = "real_t";
- itype.c_type_out = "real_t";
+ {
+ // The expected type for parameters and return value in ptrcall is 'double'.
+ itype.c_in = "\t%0 %1_in = (%0)%1;\n";
+ itype.c_out = "\treturn (%0)%1;\n";
+ itype.c_type = "double";
+ itype.c_type_in = "real_t";
+ itype.c_type_out = "real_t";
+ itype.c_arg_in = "&%s_in";
+ }
itype.cs_type = itype.proxy_name;
itype.im_type_in = itype.proxy_name;
itype.im_type_out = itype.proxy_name;
@@ -2256,7 +2287,7 @@ void BindingsGenerator::_populate_global_constants() {
int constant_value = GlobalConstants::get_global_constant_value(i);
StringName enum_name = GlobalConstants::get_global_constant_enum(i);
- ConstantInterface iconstant(snake_to_pascal_case(constant_name, true), constant_value);
+ ConstantInterface iconstant(constant_name, snake_to_pascal_case(constant_name, true), constant_value);
iconstant.const_doc = const_doc;
if (enum_name != StringName()) {
@@ -2284,16 +2315,18 @@ void BindingsGenerator::_populate_global_constants() {
TypeInterface::postsetup_enum_type(enum_itype);
enum_types.insert(enum_itype.cname, enum_itype);
- ienum.prefix = _determine_enum_prefix(ienum);
+ int prefix_length = _determine_enum_prefix(ienum);
- // HARDCODED
+ // HARDCODED: The Error enum have the prefix 'ERR_' for everything except 'OK' and 'FAILED'.
if (ienum.cname == name_cache.enum_Error) {
- if (!ienum.prefix.empty()) { // Just in case it ever changes
+ if (prefix_length > 0) { // Just in case it ever changes
ERR_PRINTS("Prefix for enum 'Error' is not empty");
}
- ienum.prefix = "Err";
+ prefix_length = 1; // 'ERR_'
}
+
+ _apply_prefix_to_enum_constants(ienum, prefix_length);
}
}
diff --git a/modules/mono/editor/bindings_generator.h b/modules/mono/editor/bindings_generator.h
index ad89255ba5..38cf99c294 100644
--- a/modules/mono/editor/bindings_generator.h
+++ b/modules/mono/editor/bindings_generator.h
@@ -43,20 +43,21 @@ class BindingsGenerator {
struct ConstantInterface {
String name;
+ String proxy_name;
int value;
const DocData::ConstantDoc *const_doc;
ConstantInterface() {}
- ConstantInterface(const String &p_name, int p_value) {
+ ConstantInterface(const String &p_name, const String &p_proxy_name, int p_value) {
name = p_name;
+ proxy_name = p_proxy_name;
value = p_value;
}
};
struct EnumInterface {
StringName cname;
- String prefix;
List<ConstantInterface> constants;
_FORCE_INLINE_ bool operator==(const EnumInterface &p_ienum) const {
@@ -223,7 +224,7 @@ class BindingsGenerator {
String c_in;
/**
- * Determines the name of the variable that will be passed as argument to a ptrcall.
+ * Determines the expression that will be passed as argument to ptrcall.
* By default the value equals the name of the parameter,
* this varies for types that require special manipulation via [c_in].
* Formatting elements:
@@ -333,8 +334,6 @@ class BindingsGenerator {
itype.proxy_name = itype.name;
itype.c_type = itype.name;
- itype.c_type_in = "void*";
- itype.c_type_out = "MonoObject*";
itype.cs_type = itype.proxy_name;
itype.im_type_in = "ref " + itype.proxy_name;
itype.im_type_out = itype.proxy_name;
@@ -385,10 +384,19 @@ class BindingsGenerator {
}
static void postsetup_enum_type(TypeInterface &r_enum_itype) {
- r_enum_itype.c_arg_in = "&%s";
- r_enum_itype.c_type = "int";
- r_enum_itype.c_type_in = "int";
- r_enum_itype.c_type_out = "int";
+ // C interface is the same as that of 'int'. Remember to apply any
+ // changes done here to the 'int' type interface as well
+
+ r_enum_itype.c_arg_in = "&%s_in";
+ {
+ // The expected types for parameters and return value in ptrcall are 'int64_t' or 'uint64_t'.
+ r_enum_itype.c_in = "\t%0 %1_in = (%0)%1;\n";
+ r_enum_itype.c_out = "\treturn (%0)%1;\n";
+ r_enum_itype.c_type = "int64_t";
+ }
+ r_enum_itype.c_type_in = "int32_t";
+ r_enum_itype.c_type_out = r_enum_itype.c_type_in;
+
r_enum_itype.cs_type = r_enum_itype.proxy_name;
r_enum_itype.cs_in = "(int)%s";
r_enum_itype.cs_out = "return (%1)%0;";
@@ -513,7 +521,8 @@ class BindingsGenerator {
return p_type.name;
}
- String _determine_enum_prefix(const EnumInterface &p_ienum);
+ int _determine_enum_prefix(const EnumInterface &p_ienum);
+ void _apply_prefix_to_enum_constants(EnumInterface &p_ienum, int p_prefix_length);
void _generate_method_icalls(const TypeInterface &p_itype);
diff --git a/modules/mono/editor/csharp_project.cpp b/modules/mono/editor/csharp_project.cpp
index 4764cbe941..6f223b75a3 100644
--- a/modules/mono/editor/csharp_project.cpp
+++ b/modules/mono/editor/csharp_project.cpp
@@ -51,7 +51,7 @@ String generate_core_api_project(const String &p_dir, const Vector<String> &p_fi
MonoObject *ret = klass->get_method("GenCoreApiProject", 2)->invoke(NULL, args, &exc);
if (exc) {
- GDMonoUtils::debug_unhandled_exception(exc);
+ GDMonoUtils::debug_print_unhandled_exception(exc);
ERR_FAIL_V(String());
}
@@ -72,7 +72,7 @@ String generate_editor_api_project(const String &p_dir, const String &p_core_dll
MonoObject *ret = klass->get_method("GenEditorApiProject", 3)->invoke(NULL, args, &exc);
if (exc) {
- GDMonoUtils::debug_unhandled_exception(exc);
+ GDMonoUtils::debug_print_unhandled_exception(exc);
ERR_FAIL_V(String());
}
@@ -93,7 +93,7 @@ String generate_game_project(const String &p_dir, const String &p_name, const Ve
MonoObject *ret = klass->get_method("GenGameProject", 3)->invoke(NULL, args, &exc);
if (exc) {
- GDMonoUtils::debug_unhandled_exception(exc);
+ GDMonoUtils::debug_print_unhandled_exception(exc);
ERR_FAIL_V(String());
}
@@ -114,7 +114,7 @@ void add_item(const String &p_project_path, const String &p_item_type, const Str
klass->get_method("AddItemToProjectChecked", 3)->invoke(NULL, args, &exc);
if (exc) {
- GDMonoUtils::debug_unhandled_exception(exc);
+ GDMonoUtils::debug_print_unhandled_exception(exc);
ERR_FAIL();
}
}
diff --git a/modules/mono/editor/godotsharp_builds.cpp b/modules/mono/editor/godotsharp_builds.cpp
index d397814fa7..b504cfe712 100644
--- a/modules/mono/editor/godotsharp_builds.cpp
+++ b/modules/mono/editor/godotsharp_builds.cpp
@@ -249,6 +249,18 @@ bool GodotSharpBuilds::build_api_sln(const String &p_name, const String &p_api_s
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) {
+ // Create destination directory if needed
+ if (!DirAccess::exists(p_dst_dir)) {
+ DirAccess *da = DirAccess::create_for_path(p_dst_dir);
+ Error err = da->make_dir_recursive(p_dst_dir);
+ memdelete(da);
+
+ if (err != OK) {
+ show_build_error_dialog("Failed to create destination directory for the API assemblies. Error: " + itos(err));
+ return false;
+ }
+ }
+
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);
@@ -294,11 +306,21 @@ String GodotSharpBuilds::_api_folder_name(APIAssembly::Type p_api_type) {
bool GodotSharpBuilds::make_api_sln(APIAssembly::Type p_api_type) {
String api_name = p_api_type == APIAssembly::API_CORE ? API_ASSEMBLY_NAME : EDITOR_API_ASSEMBLY_NAME;
+
+ String editor_prebuilt_api_dir = GodotSharpDirs::get_data_editor_prebuilt_api_dir();
+ String res_assemblies_dir = GodotSharpDirs::get_res_assemblies_dir();
+
+ if (FileAccess::exists(editor_prebuilt_api_dir.plus_file(api_name + ".dll"))) {
+ EditorProgress pr("mono_copy_prebuilt_api_assembly", "Copying prebuilt " + api_name + " assembly...", 1);
+ pr.step("Copying " + api_name + " assembly", 0);
+ return GodotSharpBuilds::copy_api_assembly(editor_prebuilt_api_dir, res_assemblies_dir, api_name, p_api_type);
+ }
+
String api_build_config = "Release";
- EditorProgress pr("mono_build_release_" + api_name, "Building " + api_name + " solution...", 4);
+ EditorProgress pr("mono_build_release_" + api_name, "Building " + api_name + " solution...", 3);
- pr.step("Generating " + api_name + " solution");
+ pr.step("Generating " + api_name + " solution", 0);
String core_api_sln_dir = GodotSharpDirs::get_mono_solutions_dir()
.plus_file(_api_folder_name(APIAssembly::API_CORE))
@@ -336,34 +358,18 @@ bool GodotSharpBuilds::make_api_sln(APIAssembly::Type p_api_type) {
}
}
- pr.step("Building " + api_name + " solution");
+ pr.step("Building " + api_name + " solution", 1);
if (!GodotSharpBuilds::build_api_sln(api_name, api_sln_dir, api_build_config))
return false;
- pr.step("Copying " + api_name + " assembly");
-
- String res_assemblies_dir = GodotSharpDirs::get_res_assemblies_dir();
-
- // Create assemblies directory if needed
- if (!DirAccess::exists(res_assemblies_dir)) {
- DirAccess *da = DirAccess::create_for_path(res_assemblies_dir);
- Error err = da->make_dir_recursive(res_assemblies_dir);
- memdelete(da);
-
- if (err != OK) {
- show_build_error_dialog("Failed to create assemblies directory. Error: " + itos(err));
- return false;
- }
- }
+ pr.step("Copying " + api_name + " assembly", 2);
// 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, p_api_type))
return false;
- pr.step("Done");
-
return true;
}
@@ -378,9 +384,8 @@ bool GodotSharpBuilds::build_project_blocking(const String &p_config) {
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");
+ EditorProgress pr("mono_project_debug_build", "Building project solution...", 1);
+ pr.step("Building project solution", 0);
MonoBuildInfo build_info(GodotSharpDirs::get_project_sln_path(), p_config);
if (!GodotSharpBuilds::get_singleton()->build(build_info)) {
@@ -388,8 +393,6 @@ bool GodotSharpBuilds::build_project_blocking(const String &p_config) {
return false;
}
- pr.step("Done");
-
return true;
}
diff --git a/modules/mono/editor/godotsharp_editor.cpp b/modules/mono/editor/godotsharp_editor.cpp
index 3ee38515bf..9df4e10266 100644
--- a/modules/mono/editor/godotsharp_editor.cpp
+++ b/modules/mono/editor/godotsharp_editor.cpp
@@ -108,6 +108,33 @@ bool GodotSharpEditor::_create_project_solution() {
return true;
}
+void GodotSharpEditor::_make_api_solutions_if_needed() {
+ // I'm sick entirely of ProgressDialog
+ static bool recursion_guard = false;
+ if (!recursion_guard) {
+ recursion_guard = true;
+ _make_api_solutions_if_needed_impl();
+ recursion_guard = false;
+ }
+}
+
+void GodotSharpEditor::_make_api_solutions_if_needed_impl() {
+ // If the project has a solution and C# project make sure the API assemblies are present and up to date
+ String res_assemblies_dir = GodotSharpDirs::get_res_assemblies_dir();
+
+ if (!FileAccess::exists(res_assemblies_dir.plus_file(API_ASSEMBLY_NAME ".dll")) ||
+ GDMono::get_singleton()->metadata_is_api_assembly_invalidated(APIAssembly::API_CORE)) {
+ if (!GodotSharpBuilds::make_api_sln(APIAssembly::API_CORE))
+ return;
+ }
+
+ if (!FileAccess::exists(res_assemblies_dir.plus_file(EDITOR_API_ASSEMBLY_NAME ".dll")) ||
+ GDMono::get_singleton()->metadata_is_api_assembly_invalidated(APIAssembly::API_EDITOR)) {
+ if (!GodotSharpBuilds::make_api_sln(APIAssembly::API_EDITOR))
+ return; // Redundant? I don't think so
+ }
+}
+
void GodotSharpEditor::_remove_create_sln_menu_option() {
menu_popup->remove_item(menu_popup->get_item_index(MENU_CREATE_SLN));
@@ -169,6 +196,7 @@ void GodotSharpEditor::_notification(int p_notification) {
void GodotSharpEditor::_bind_methods() {
ClassDB::bind_method(D_METHOD("_create_project_solution"), &GodotSharpEditor::_create_project_solution);
+ ClassDB::bind_method(D_METHOD("_make_api_solutions_if_needed"), &GodotSharpEditor::_make_api_solutions_if_needed);
ClassDB::bind_method(D_METHOD("_remove_create_sln_menu_option"), &GodotSharpEditor::_remove_create_sln_menu_option);
ClassDB::bind_method(D_METHOD("_toggle_about_dialog_on_start"), &GodotSharpEditor::_toggle_about_dialog_on_start);
ClassDB::bind_method(D_METHOD("_menu_option_pressed", "id"), &GodotSharpEditor::_menu_option_pressed);
@@ -197,6 +225,7 @@ void GodotSharpEditor::register_internal_calls() {
mono_add_internal_call("GodotSharpTools.Utils.OS::GetPlatformName", (void *)godot_icall_Utils_OS_GetPlatformName);
GodotSharpBuilds::register_internal_calls();
+ GodotSharpExport::register_internal_calls();
}
void GodotSharpEditor::show_error_dialog(const String &p_message, const String &p_title) {
@@ -389,7 +418,10 @@ GodotSharpEditor::GodotSharpEditor(EditorNode *p_editor) {
String sln_path = GodotSharpDirs::get_project_sln_path();
String csproj_path = GodotSharpDirs::get_project_csproj_path();
- if (!FileAccess::exists(sln_path) || !FileAccess::exists(csproj_path)) {
+ if (FileAccess::exists(sln_path) && FileAccess::exists(csproj_path)) {
+ // We can't use EditorProgress here. It calls Main::iterarion() and the main loop is not initialized yet.
+ call_deferred("_make_api_solutions_if_needed");
+ } else {
bottom_panel_btn->hide();
menu_popup->add_item(TTR("Create C# solution"), MENU_CREATE_SLN);
}
diff --git a/modules/mono/editor/godotsharp_editor.h b/modules/mono/editor/godotsharp_editor.h
index 46b6bd5ebf..9fb0e40132 100644
--- a/modules/mono/editor/godotsharp_editor.h
+++ b/modules/mono/editor/godotsharp_editor.h
@@ -56,6 +56,8 @@ class GodotSharpEditor : public Node {
#endif
bool _create_project_solution();
+ void _make_api_solutions_if_needed();
+ void _make_api_solutions_if_needed_impl();
void _remove_create_sln_menu_option();
void _show_about_dialog();
diff --git a/modules/mono/editor/godotsharp_export.cpp b/modules/mono/editor/godotsharp_export.cpp
index cd09e6516a..933ede93dc 100644
--- a/modules/mono/editor/godotsharp_export.cpp
+++ b/modules/mono/editor/godotsharp_export.cpp
@@ -30,12 +30,37 @@
#include "godotsharp_export.h"
+#include "core/version.h"
+
#include "../csharp_script.h"
#include "../godotsharp_defs.h"
#include "../godotsharp_dirs.h"
+#include "../mono_gd/gd_mono_class.h"
+#include "../mono_gd/gd_mono_marshal.h"
#include "godotsharp_builds.h"
-void GodotSharpExport::_export_file(const String &p_path, const String &p_type, const Set<String> &p_features) {
+static MonoString *godot_icall_GodotSharpExport_GetTemplatesDir() {
+ String current_version = VERSION_FULL_CONFIG;
+ String templates_dir = EditorSettings::get_singleton()->get_templates_dir().plus_file(current_version);
+ return GDMonoMarshal::mono_string_from_godot(ProjectSettings::get_singleton()->globalize_path(templates_dir));
+}
+
+static MonoString *godot_icall_GodotSharpExport_GetDataDirName() {
+ String appname = ProjectSettings::get_singleton()->get("application/config/name");
+ String appname_safe = OS::get_singleton()->get_safe_dir_name(appname);
+ return GDMonoMarshal::mono_string_from_godot("data_" + appname_safe);
+}
+
+void GodotSharpExport::register_internal_calls() {
+ static bool registered = false;
+ ERR_FAIL_COND(registered);
+ registered = true;
+
+ mono_add_internal_call("GodotSharpTools.Editor.GodotSharpExport::GetTemplatesDir", (void *)godot_icall_GodotSharpExport_GetTemplatesDir);
+ mono_add_internal_call("GodotSharpTools.Editor.GodotSharpExport::GetDataDirName", (void *)godot_icall_GodotSharpExport_GetDataDirName);
+}
+
+void GodotSharpExport::_export_file(const String &p_path, const String &p_type, const Set<String> &) {
if (p_type != CSharpLanguage::get_singleton()->get_type())
return;
@@ -56,59 +81,78 @@ void GodotSharpExport::_export_begin(const Set<String> &p_features, bool p_debug
// 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());
+ ERR_FAIL_NULL(TOOLS_DOMAIN);
+ ERR_FAIL_NULL(GDMono::get_singleton()->get_editor_tools_assembly());
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 dependency assemblies
- // Add project assembly
+ Map<String, String> dependencies;
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");
+ String project_dll_src_dir = GodotSharpDirs::get_res_temp_assemblies_base_dir().plus_file(build_config);
+ String project_dll_src_path = project_dll_src_dir.plus_file(project_dll_name + ".dll");
+ dependencies.insert(project_dll_name, project_dll_src_path);
- ERR_FAIL_COND(!export_domain);
- ERR_FAIL_COND(!mono_domain_set(export_domain, false));
+ {
+ MonoDomain *export_domain = GDMonoUtils::create_domain("GodotEngine.ProjectExportDomain");
+ ERR_FAIL_NULL(export_domain);
+ _GDMONO_SCOPE_EXIT_DOMAIN_UNLOAD_(export_domain);
- 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);
+ _GDMONO_SCOPE_DOMAIN_(export_domain);
- ERR_EXPLAIN("Cannot load refonly assembly: " + project_dll_name);
- ERR_FAIL_COND(!scripts_assembly);
+ GDMonoAssembly *scripts_assembly = NULL;
+ bool load_success = GDMono::get_singleton()->load_assembly_from(project_dll_name,
+ project_dll_src_dir, &scripts_assembly, /* refonly: */ true);
- Error depend_error = _get_assembly_dependencies(scripts_assembly, dependencies);
+ ERR_EXPLAIN("Cannot load refonly assembly: " + project_dll_name);
+ ERR_FAIL_COND(!load_success);
- GDMono::get_singleton()->finalize_and_unload_domain(export_domain);
- mono_domain_set(prev_domain, false);
-
- ERR_FAIL_COND(depend_error != OK);
+ Vector<String> search_dirs;
+ GDMonoAssembly::fill_search_dirs(search_dirs);
+ Error depend_error = _get_assembly_dependencies(scripts_assembly, search_dirs, dependencies);
+ 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));
}
+
+ // Mono specific export template extras (data dir)
+
+ GDMonoClass *export_class = GDMono::get_singleton()->get_editor_tools_assembly()->get_class("GodotSharpTools.Editor", "GodotSharpExport");
+ ERR_FAIL_NULL(export_class);
+ GDMonoMethod *export_begin_method = export_class->get_method("_ExportBegin", 4);
+ ERR_FAIL_NULL(export_begin_method);
+
+ MonoArray *features = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(String), p_features.size());
+ int i = 0;
+ for (const Set<String>::Element *E = p_features.front(); E; E = E->next()) {
+ MonoString *boxed = GDMonoMarshal::mono_string_from_godot(E->get());
+ mono_array_set(features, MonoString *, i, boxed);
+ i++;
+ }
+
+ MonoBoolean debug = p_debug;
+ MonoString *path = GDMonoMarshal::mono_string_from_godot(p_path);
+ uint32_t flags = p_flags;
+ void *args[4] = { features, &debug, path, &flags };
+ MonoException *exc = NULL;
+ export_begin_method->invoke_raw(NULL, args, &exc);
+
+ if (exc) {
+ GDMonoUtils::debug_print_unhandled_exception(exc);
+ ERR_FAIL();
+ }
}
bool GodotSharpExport::_add_assembly(const String &p_src_path, const String &p_dst_path) {
@@ -125,7 +169,7 @@ bool GodotSharpExport::_add_assembly(const String &p_src_path, const String &p_d
return true;
}
-Error GodotSharpExport::_get_assembly_dependencies(GDMonoAssembly *p_assembly, Map<String, String> &r_dependencies) {
+Error GodotSharpExport::_get_assembly_dependencies(GDMonoAssembly *p_assembly, const Vector<String> &p_search_dirs, Map<String, String> &r_dependencies) {
MonoImage *image = p_assembly->get_image();
@@ -134,18 +178,48 @@ Error GodotSharpExport::_get_assembly_dependencies(GDMonoAssembly *p_assembly, M
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))
+ if (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);
+ String path;
+ bool has_extension = ref_name.ends_with(".dll") || ref_name.ends_with(".exe");
+
+ for (int i = 0; i < p_search_dirs.size(); i++) {
+ const String &search_dir = p_search_dirs[i];
+
+ if (has_extension) {
+ path = search_dir.plus_file(ref_name);
+ if (FileAccess::exists(path)) {
+ GDMono::get_singleton()->load_assembly_from(ref_name.get_basename(), search_dir, ref_aname, &ref_assembly, true);
+ if (ref_assembly != NULL)
+ break;
+ }
+ } else {
+ path = search_dir.plus_file(ref_name + ".dll");
+ if (FileAccess::exists(path)) {
+ GDMono::get_singleton()->load_assembly_from(ref_name, search_dir, ref_aname, &ref_assembly, true);
+ if (ref_assembly != NULL)
+ break;
+ }
+
+ path = search_dir.plus_file(ref_name + ".exe");
+ if (FileAccess::exists(path)) {
+ GDMono::get_singleton()->load_assembly_from(ref_name, search_dir, ref_aname, &ref_assembly, true);
+ if (ref_assembly != NULL)
+ break;
+ }
+ }
+ }
+
+ if (!ref_assembly) {
+ ERR_EXPLAIN("Cannot load assembly (refonly): " + 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);
+ Error err = _get_assembly_dependencies(ref_assembly, p_search_dirs, r_dependencies);
if (err != OK)
return err;
}
diff --git a/modules/mono/editor/godotsharp_export.h b/modules/mono/editor/godotsharp_export.h
index b38db9660c..f007016578 100644
--- a/modules/mono/editor/godotsharp_export.h
+++ b/modules/mono/editor/godotsharp_export.h
@@ -43,13 +43,15 @@ class GodotSharpExport : public EditorExportPlugin {
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);
+ Error _get_assembly_dependencies(GDMonoAssembly *p_assembly, const Vector<String> &p_search_dirs, 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:
+ static void register_internal_calls();
+
GodotSharpExport();
~GodotSharpExport();
};
diff --git a/modules/mono/editor/mono_bottom_panel.cpp b/modules/mono/editor/mono_bottom_panel.cpp
index 8d9b345a92..0ac59a1be8 100644
--- a/modules/mono/editor/mono_bottom_panel.cpp
+++ b/modules/mono/editor/mono_bottom_panel.cpp
@@ -63,7 +63,7 @@ void MonoBottomPanel::_update_build_tabs_list() {
item_tooltip += "Running";
}
- if (!tab->build_exited || !tab->build_result == MonoBuildTab::RESULT_SUCCESS) {
+ if (!tab->build_exited || tab->build_result == MonoBuildTab::RESULT_ERROR) {
item_tooltip += "\nErrors: " + itos(tab->error_count);
}
diff --git a/modules/mono/glue/Managed/Files/Extensions/NodeExtensions.cs b/modules/mono/glue/Managed/Files/Extensions/NodeExtensions.cs
index 71534d7782..366d89b1c2 100644
--- a/modules/mono/glue/Managed/Files/Extensions/NodeExtensions.cs
+++ b/modules/mono/glue/Managed/Files/Extensions/NodeExtensions.cs
@@ -2,42 +2,42 @@ namespace Godot
{
public partial class Node
{
- public T GetNode<T>(NodePath path) where T : Godot.Node
+ public T GetNode<T>(NodePath path) where T : class
{
- return (T)GetNode(path);
+ return (T)(object)GetNode(path);
}
- public T GetNodeOrNull<T>(NodePath path) where T : Godot.Node
+ public T GetNodeOrNull<T>(NodePath path) where T : class
{
return GetNode(path) as T;
}
- public T GetChild<T>(int idx) where T : Godot.Node
+ public T GetChild<T>(int idx) where T : class
{
- return (T)GetChild(idx);
+ return (T)(object)GetChild(idx);
}
- public T GetChildOrNull<T>(int idx) where T : Godot.Node
+ public T GetChildOrNull<T>(int idx) where T : class
{
return GetChild(idx) as T;
}
- public T GetOwner<T>() where T : Godot.Node
+ public T GetOwner<T>() where T : class
{
- return (T)GetOwner();
+ return (T)(object)GetOwner();
}
- public T GetOwnerOrNull<T>() where T : Godot.Node
+ public T GetOwnerOrNull<T>() where T : class
{
return GetOwner() as T;
}
- public T GetParent<T>() where T : Godot.Node
+ public T GetParent<T>() where T : class
{
- return (T)GetParent();
+ return (T)(object)GetParent();
}
- public T GetParentOrNull<T>() where T : Godot.Node
+ public T GetParentOrNull<T>() where T : class
{
return GetParent() as T;
}
diff --git a/modules/mono/glue/Managed/Files/Extensions/ResourceLoaderExtensions.cs b/modules/mono/glue/Managed/Files/Extensions/ResourceLoaderExtensions.cs
index ceecc589e6..684d160b57 100644
--- a/modules/mono/glue/Managed/Files/Extensions/ResourceLoaderExtensions.cs
+++ b/modules/mono/glue/Managed/Files/Extensions/ResourceLoaderExtensions.cs
@@ -2,9 +2,9 @@ namespace Godot
{
public static partial class ResourceLoader
{
- public static T Load<T>(string path) where T : Godot.Resource
+ public static T Load<T>(string path) where T : class
{
- return (T) Load(path);
+ return (T)(object)Load(path);
}
}
}
diff --git a/modules/mono/glue/Managed/Files/GD.cs b/modules/mono/glue/Managed/Files/GD.cs
index 264be23588..e4818e186c 100644
--- a/modules/mono/glue/Managed/Files/GD.cs
+++ b/modules/mono/glue/Managed/Files/GD.cs
@@ -65,9 +65,9 @@ namespace Godot
return ResourceLoader.Load(path);
}
- public static T Load<T>(string path) where T : Godot.Resource
+ public static T Load<T>(string path) where T : class
{
- return (T) ResourceLoader.Load(path);
+ return ResourceLoader.Load<T>(path);
}
public static void Print(params object[] what)
diff --git a/modules/mono/glue/nodepath_glue.cpp b/modules/mono/glue/nodepath_glue.cpp
index 4b7648a4f9..422d73104d 100644
--- a/modules/mono/glue/nodepath_glue.cpp
+++ b/modules/mono/glue/nodepath_glue.cpp
@@ -40,7 +40,7 @@ NodePath *godot_icall_NodePath_Ctor(MonoString *p_path) {
void godot_icall_NodePath_Dtor(NodePath *p_ptr) {
ERR_FAIL_NULL(p_ptr);
- _GodotSharp::get_singleton()->queue_dispose(p_ptr);
+ memdelete(p_ptr);
}
MonoString *godot_icall_NodePath_operator_String(NodePath *p_np) {
diff --git a/modules/mono/glue/rid_glue.cpp b/modules/mono/glue/rid_glue.cpp
index 5d66b8aa6f..6c002b5b9d 100644
--- a/modules/mono/glue/rid_glue.cpp
+++ b/modules/mono/glue/rid_glue.cpp
@@ -45,7 +45,7 @@ RID *godot_icall_RID_Ctor(Object *p_from) {
void godot_icall_RID_Dtor(RID *p_ptr) {
ERR_FAIL_NULL(p_ptr);
- _GodotSharp::get_singleton()->queue_dispose(p_ptr);
+ memdelete(p_ptr);
}
uint32_t godot_icall_RID_get_id(RID *p_ptr) {
diff --git a/modules/mono/godotsharp_dirs.cpp b/modules/mono/godotsharp_dirs.cpp
index 2570e68f13..d3fb2cb640 100644
--- a/modules/mono/godotsharp_dirs.cpp
+++ b/modules/mono/godotsharp_dirs.cpp
@@ -30,11 +30,11 @@
#include "godotsharp_dirs.h"
+#include "core/os/dir_access.h"
#include "core/os/os.h"
+#include "core/project_settings.h"
#ifdef TOOLS_ENABLED
-#include "core/os/dir_access.h"
-#include "core/project_settings.h"
#include "core/version.h"
#include "editor/editor_settings.h"
#endif
@@ -95,10 +95,18 @@ public:
#ifdef TOOLS_ENABLED
String mono_solutions_dir;
String build_logs_dir;
+
String sln_filepath;
String csproj_filepath;
+
+ String data_mono_bin_dir;
+ String data_editor_tools_dir;
+ String data_editor_prebuilt_api_dir;
#endif
+ String data_mono_etc_dir;
+ String data_mono_lib_dir;
+
private:
_GodotSharpDirs() {
res_data_dir = "res://.mono";
@@ -123,10 +131,60 @@ private:
name = "UnnamedProject";
}
- String base_path = String("res://") + name;
+ String base_path = ProjectSettings::get_singleton()->globalize_path("res://");
+
+ sln_filepath = base_path.plus_file(name + ".sln");
+ csproj_filepath = base_path.plus_file(name + ".csproj");
+#endif
+
+ String exe_dir = OS::get_singleton()->get_executable_path().get_base_dir();
+
+#ifdef TOOLS_ENABLED
+
+ String data_dir_root = exe_dir.plus_file("GodotSharp");
+ data_editor_tools_dir = data_dir_root.plus_file("Tools");
+ data_editor_prebuilt_api_dir = data_dir_root.plus_file("Api");
+
+ String data_mono_root_dir = data_dir_root.plus_file("Mono");
+ data_mono_bin_dir = data_mono_root_dir.plus_file("bin");
+ data_mono_etc_dir = data_mono_root_dir.plus_file("etc");
+ data_mono_lib_dir = data_mono_root_dir.plus_file("lib");
+
+#ifdef OSX_ENABLED
+ if (!DirAccess::exists(data_editor_tools_dir)) {
+ data_editor_tools_dir = exe_dir.plus_file("../Frameworks/GodotSharp/Tools");
+ }
+
+ if (!DirAccess::exists(data_editor_prebuilt_api_dir)) {
+ data_editor_prebuilt_api_dir = exe_dir.plus_file("../Frameworks/GodotSharp/Api");
+ }
+
+ if (!DirAccess::exists(data_mono_root_dir)) {
+ data_mono_bin_dir = exe_dir.plus_file("../Frameworks/GodotSharp/Mono/bin");
+ data_mono_etc_dir = exe_dir.plus_file("../Resources/GodotSharp/Mono/etc");
+ data_mono_lib_dir = exe_dir.plus_file("../Frameworks/GodotSharp/Mono/lib");
+ }
+#endif
+
+#else
+
+ String appname = OS::get_singleton()->get_safe_dir_name(ProjectSettings::get_singleton()->get("application/config/name"));
+ String data_dir_root = exe_dir.plus_file("data_" + appname);
+ if (!DirAccess::exists(data_dir_root)) {
+ data_dir_root = exe_dir.plus_file("data_Godot");
+ }
+
+ String data_mono_root_dir = data_dir_root.plus_file("Mono");
+ data_mono_etc_dir = data_mono_root_dir.plus_file("etc");
+ data_mono_lib_dir = data_mono_root_dir.plus_file("lib");
+
+#ifdef OSX_ENABLED
+ if (!DirAccess::exists(data_mono_root_dir)) {
+ data_mono_etc_dir = exe_dir.plus_file("../Resources/GodotSharp/Mono/etc");
+ data_mono_lib_dir = exe_dir.plus_file("../Frameworks/GodotSharp/Mono/lib");
+ }
+#endif
- sln_filepath = ProjectSettings::get_singleton()->globalize_path(base_path + ".sln");
- csproj_filepath = ProjectSettings::get_singleton()->globalize_path(base_path + ".csproj");
#endif
}
@@ -192,5 +250,26 @@ String get_project_sln_path() {
String get_project_csproj_path() {
return _GodotSharpDirs::get_singleton().csproj_filepath;
}
+
+String get_data_mono_bin_dir() {
+ return _GodotSharpDirs::get_singleton().data_mono_bin_dir;
+}
+
+String get_data_editor_tools_dir() {
+ return _GodotSharpDirs::get_singleton().data_editor_tools_dir;
+}
+
+String get_data_editor_prebuilt_api_dir() {
+ return _GodotSharpDirs::get_singleton().data_editor_prebuilt_api_dir;
+}
#endif
+
+String get_data_mono_etc_dir() {
+ return _GodotSharpDirs::get_singleton().data_mono_etc_dir;
+}
+
+String get_data_mono_lib_dir() {
+ return _GodotSharpDirs::get_singleton().data_mono_lib_dir;
+}
+
} // namespace GodotSharpDirs
diff --git a/modules/mono/godotsharp_dirs.h b/modules/mono/godotsharp_dirs.h
index 3466cb271d..35b564be30 100644
--- a/modules/mono/godotsharp_dirs.h
+++ b/modules/mono/godotsharp_dirs.h
@@ -49,11 +49,18 @@ String get_mono_logs_dir();
#ifdef TOOLS_ENABLED
String get_mono_solutions_dir();
String get_build_logs_dir();
-String get_custom_project_settings_dir();
-#endif
String get_project_sln_path();
String get_project_csproj_path();
+
+String get_data_mono_bin_dir();
+String get_data_editor_tools_dir();
+String get_data_editor_prebuilt_api_dir();
+#endif
+
+String get_data_mono_etc_dir();
+String get_data_mono_lib_dir();
+
} // namespace GodotSharpDirs
#endif // GODOTSHARP_DIRS_H
diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp
index 9311aa3930..4d88cca6f1 100644
--- a/modules/mono/mono_gd/gd_mono.cpp
+++ b/modules/mono/mono_gd/gd_mono.cpp
@@ -162,50 +162,62 @@ void GDMono::initialize() {
mono_trace_set_printerr_handler(gdmono_MonoPrintCallback);
#endif
+ String assembly_rootdir;
+ String config_dir;
+
+#ifdef TOOLS_ENABLED
#ifdef WINDOWS_ENABLED
mono_reg_info = MonoRegUtils::find_mono();
- CharString assembly_dir;
- CharString config_dir;
-
if (mono_reg_info.assembly_dir.length() && DirAccess::exists(mono_reg_info.assembly_dir)) {
- assembly_dir = mono_reg_info.assembly_dir.utf8();
+ assembly_rootdir = mono_reg_info.assembly_dir;
}
if (mono_reg_info.config_dir.length() && DirAccess::exists(mono_reg_info.config_dir)) {
- config_dir = mono_reg_info.config_dir.utf8();
+ config_dir = mono_reg_info.config_dir;
}
-
- mono_set_dirs(assembly_dir.length() ? assembly_dir.get_data() : NULL,
- config_dir.length() ? config_dir.get_data() : NULL);
#elif OSX_ENABLED
- mono_set_dirs(NULL, NULL);
-
- {
- const char *assembly_rootdir = mono_assembly_getrootdir();
- const char *config_dir = mono_get_config_dir();
-
- if (!assembly_rootdir || !config_dir || !DirAccess::exists(assembly_rootdir) || !DirAccess::exists(config_dir)) {
- Vector<const char *> locations;
- locations.push_back("/Library/Frameworks/Mono.framework/Versions/Current/");
- locations.push_back("/usr/local/var/homebrew/linked/mono/");
-
- for (int i = 0; i < locations.size(); i++) {
- String hint_assembly_rootdir = path_join(locations[i], "lib");
- String hint_mscorlib_path = path_join(hint_assembly_rootdir, "mono", "4.5", "mscorlib.dll");
- String hint_config_dir = path_join(locations[i], "etc");
-
- if (FileAccess::exists(hint_mscorlib_path) && DirAccess::exists(hint_config_dir)) {
- mono_set_dirs(hint_assembly_rootdir.utf8().get_data(), hint_config_dir.utf8().get_data());
- break;
- }
+ const char *c_assembly_rootdir = mono_assembly_getrootdir();
+ const char *c_config_dir = mono_get_config_dir();
+
+ if (!c_assembly_rootdir || !c_config_dir || !DirAccess::exists(c_assembly_rootdir) || !DirAccess::exists(c_config_dir)) {
+ Vector<const char *> locations;
+ locations.push_back("/Library/Frameworks/Mono.framework/Versions/Current/");
+ locations.push_back("/usr/local/var/homebrew/linked/mono/");
+
+ for (int i = 0; i < locations.size(); i++) {
+ String hint_assembly_rootdir = path_join(locations[i], "lib");
+ String hint_mscorlib_path = path_join(hint_assembly_rootdir, "mono", "4.5", "mscorlib.dll");
+ String hint_config_dir = path_join(locations[i], "etc");
+
+ if (FileAccess::exists(hint_mscorlib_path) && DirAccess::exists(hint_config_dir)) {
+ assembly_rootdir = hint_assembly_rootdir;
+ config_dir = hint_config_dir;
+ break;
}
}
}
+#endif
+#endif // TOOLS_ENABLED
+
+ String bundled_assembly_rootdir = GodotSharpDirs::get_data_mono_lib_dir();
+ String bundled_config_dir = GodotSharpDirs::get_data_mono_etc_dir();
+
+#ifdef TOOLS_ENABLED
+ if (DirAccess::exists(bundled_assembly_rootdir) && DirAccess::exists(bundled_config_dir)) {
+ assembly_rootdir = bundled_assembly_rootdir;
+ config_dir = bundled_config_dir;
+ }
#else
- mono_set_dirs(NULL, NULL);
+ // These are always the directories in export templates
+ assembly_rootdir = bundled_assembly_rootdir;
+ config_dir = bundled_config_dir;
#endif
+ // Leak if we call mono_set_dirs more than once
+ mono_set_dirs(assembly_rootdir.length() ? assembly_rootdir.utf8().get_data() : NULL,
+ config_dir.length() ? config_dir.utf8().get_data() : NULL);
+
GDMonoAssembly::initialize();
#ifdef DEBUG_ENABLED
@@ -262,8 +274,11 @@ void GDMono::initialize() {
// Everything is fine with the api assemblies, load the project assembly
_load_project_assembly();
} else {
- if ((core_api_assembly && (core_api_assembly_out_of_sync || !GDMonoUtils::mono_cache.godot_api_cache_updated)) ||
- (editor_api_assembly && editor_api_assembly_out_of_sync)) {
+ if ((core_api_assembly && (core_api_assembly_out_of_sync || !GDMonoUtils::mono_cache.godot_api_cache_updated))
+#ifdef TOOLS_ENABLED
+ || (editor_api_assembly && editor_api_assembly_out_of_sync)
+#endif
+ ) {
#ifdef TOOLS_ENABLED
// The assembly was successfully loaded, but the full api could not be cached.
// This is most likely an outdated assembly loaded because of an invalid version in the
@@ -362,24 +377,34 @@ GDMonoAssembly **GDMono::get_loaded_assembly(const String &p_name) {
bool GDMono::load_assembly(const String &p_name, GDMonoAssembly **r_assembly, bool p_refonly) {
+ return load_assembly_from(p_name, String(), r_assembly, p_refonly);
+}
+
+bool GDMono::load_assembly(const String &p_name, MonoAssemblyName *p_aname, GDMonoAssembly **r_assembly, bool p_refonly) {
+
+ return load_assembly_from(p_name, String(), p_aname, r_assembly, p_refonly);
+}
+
+bool GDMono::load_assembly_from(const String &p_name, const String &p_basedir, 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);
+ bool result = load_assembly_from(p_name, p_basedir, 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) {
+bool GDMono::load_assembly_from(const String &p_name, const String &p_basedir, MonoAssemblyName *p_aname, GDMonoAssembly **r_assembly, bool p_refonly) {
CRASH_COND(!r_assembly);
print_verbose("Mono: Loading assembly " + p_name + (p_refonly ? " (refonly)" : "") + "...");
MonoImageOpenStatus status = MONO_IMAGE_OK;
- MonoAssembly *assembly = mono_assembly_load_full(p_aname, NULL, &status, p_refonly);
+ MonoAssembly *assembly = mono_assembly_load_full(p_aname, p_basedir.length() ? p_basedir.utf8().get_data() : NULL, &status, p_refonly);
if (!assembly)
return false;
@@ -480,12 +505,10 @@ bool GDMono::_load_editor_api_assembly() {
if (editor_api_assembly)
return true;
-#ifdef TOOLS_ENABLED
if (metadata_is_api_assembly_invalidated(APIAssembly::API_EDITOR)) {
print_verbose("Mono: Skipping loading of Editor API assembly because it was invalidated");
return false;
}
-#endif
bool success = load_assembly(EDITOR_API_ASSEMBLY_NAME, &editor_api_assembly);
@@ -647,14 +670,18 @@ Error GDMono::_unload_scripts_domain() {
print_verbose("Mono: Unloading scripts domain...");
- _GodotSharp::get_singleton()->_dispose_callback();
-
if (mono_domain_get() != root_domain)
mono_domain_set(root_domain, true);
mono_gc_collect(mono_gc_max_generation());
- mono_domain_finalize(scripts_domain, 2000);
+ finalizing_scripts_domain = true;
+
+ if (!mono_domain_finalize(scripts_domain, 2000)) {
+ ERR_PRINT("Mono: Domain finalization timeout");
+ }
+
+ finalizing_scripts_domain = false;
mono_gc_collect(mono_gc_max_generation());
@@ -672,8 +699,6 @@ Error GDMono::_unload_scripts_domain() {
MonoDomain *domain = scripts_domain;
scripts_domain = NULL;
- _GodotSharp::get_singleton()->_dispose_callback();
-
MonoException *exc = NULL;
mono_domain_try_unload(domain, (MonoObject **)&exc);
@@ -772,11 +797,13 @@ Error GDMono::finalize_and_unload_domain(MonoDomain *p_domain) {
print_verbose("Mono: Unloading domain `" + domain_name + "`...");
- if (mono_domain_get() != root_domain)
+ if (mono_domain_get() == p_domain)
mono_domain_set(root_domain, true);
mono_gc_collect(mono_gc_max_generation());
- mono_domain_finalize(p_domain, 2000);
+ if (!mono_domain_finalize(p_domain, 2000)) {
+ ERR_PRINT("Mono: Domain finalization timeout");
+ }
mono_gc_collect(mono_gc_max_generation());
_domain_assemblies_cleanup(mono_domain_get_id(p_domain));
@@ -851,6 +878,7 @@ GDMono::GDMono() {
gdmono_log = memnew(GDMonoLog);
runtime_initialized = false;
+ finalizing_scripts_domain = false;
root_domain = NULL;
scripts_domain = NULL;
@@ -917,29 +945,6 @@ GDMono::~GDMono() {
_GodotSharp *_GodotSharp::singleton = NULL;
-void _GodotSharp::_dispose_callback() {
-
-#ifndef NO_THREADS
- queue_mutex->lock();
-#endif
-
- for (List<NodePath *>::Element *E = np_delete_queue.front(); E; E = E->next()) {
- memdelete(E->get());
- }
-
- for (List<RID *>::Element *E = rid_delete_queue.front(); E; E = E->next()) {
- memdelete(E->get());
- }
-
- np_delete_queue.clear();
- rid_delete_queue.clear();
- queue_empty = true;
-
-#ifndef NO_THREADS
- queue_mutex->unlock();
-#endif
-}
-
void _GodotSharp::attach_thread() {
GDMonoUtils::attach_current_thread();
@@ -988,6 +993,8 @@ bool _GodotSharp::is_domain_finalizing_for_unload(MonoDomain *p_domain) {
if (!p_domain)
return true;
+ if (p_domain == SCRIPTS_DOMAIN && GDMono::get_singleton()->is_finalizing_scripts_domain())
+ return true;
return mono_domain_is_unloading(p_domain);
}
@@ -1001,49 +1008,6 @@ bool _GodotSharp::is_runtime_initialized() {
return GDMono::get_singleton()->is_runtime_initialized();
}
-#define ENQUEUE_FOR_DISPOSAL(m_queue, m_inst) \
- m_queue.push_back(m_inst); \
- if (queue_empty) { \
- queue_empty = false; \
- if (!is_domain_finalizing_for_unload(SCRIPTS_DOMAIN)) { /* call_deferred may not be safe here */ \
- call_deferred("_dispose_callback"); \
- } \
- }
-
-void _GodotSharp::queue_dispose(NodePath *p_node_path) {
-
- if (GDMonoUtils::is_main_thread() && !is_domain_finalizing_for_unload(SCRIPTS_DOMAIN)) {
- memdelete(p_node_path);
- } else {
-#ifndef NO_THREADS
- queue_mutex->lock();
-#endif
-
- ENQUEUE_FOR_DISPOSAL(np_delete_queue, p_node_path);
-
-#ifndef NO_THREADS
- queue_mutex->unlock();
-#endif
- }
-}
-
-void _GodotSharp::queue_dispose(RID *p_rid) {
-
- if (GDMonoUtils::is_main_thread() && !is_domain_finalizing_for_unload(SCRIPTS_DOMAIN)) {
- memdelete(p_rid);
- } else {
-#ifndef NO_THREADS
- queue_mutex->lock();
-#endif
-
- ENQUEUE_FOR_DISPOSAL(rid_delete_queue, p_rid);
-
-#ifndef NO_THREADS
- queue_mutex->unlock();
-#endif
- }
-}
-
void _GodotSharp::_bind_methods() {
ClassDB::bind_method(D_METHOD("attach_thread"), &_GodotSharp::attach_thread);
@@ -1056,8 +1020,6 @@ void _GodotSharp::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_runtime_shutting_down"), &_GodotSharp::is_runtime_shutting_down);
ClassDB::bind_method(D_METHOD("is_runtime_initialized"), &_GodotSharp::is_runtime_initialized);
-
- ClassDB::bind_method(D_METHOD("_dispose_callback"), &_GodotSharp::_dispose_callback);
}
_GodotSharp::_GodotSharp() {
diff --git a/modules/mono/mono_gd/gd_mono.h b/modules/mono/mono_gd/gd_mono.h
index 0c5503d28e..745dcc34eb 100644
--- a/modules/mono/mono_gd/gd_mono.h
+++ b/modules/mono/mono_gd/gd_mono.h
@@ -142,7 +142,7 @@ class GDMono {
GDMonoLog *gdmono_log;
-#ifdef WINDOWS_ENABLED
+#if defined(WINDOWS_ENABLED) && defined(TOOLS_ENABLED)
MonoRegInfo mono_reg_info;
#endif
@@ -172,6 +172,8 @@ public:
_FORCE_INLINE_ bool is_runtime_initialized() const { return runtime_initialized && !mono_runtime_is_shutting_down() /* stays true after shutdown finished */; }
+ _FORCE_INLINE_ bool is_finalizing_scripts_domain() { return finalizing_scripts_domain; }
+
_FORCE_INLINE_ MonoDomain *get_scripts_domain() { return scripts_domain; }
#ifdef TOOLS_ENABLED
_FORCE_INLINE_ MonoDomain *get_tools_domain() { return tools_domain; }
@@ -185,7 +187,7 @@ public:
_FORCE_INLINE_ GDMonoAssembly *get_editor_tools_assembly() const { return editor_tools_assembly; }
#endif
-#ifdef WINDOWS_ENABLED
+#if defined(WINDOWS_ENABLED) && defined(TOOLS_ENABLED)
const MonoRegInfo &get_mono_reg_info() { return mono_reg_info; }
#endif
@@ -197,6 +199,9 @@ public:
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);
+ bool load_assembly_from(const String &p_name, const String &p_basedir, GDMonoAssembly **r_assembly, bool p_refonly = false);
+ bool load_assembly_from(const String &p_name, const String &p_basedir, MonoAssemblyName *p_aname, GDMonoAssembly **r_assembly, bool p_refonly = false);
+
Error finalize_and_unload_domain(MonoDomain *p_domain);
void initialize();
@@ -205,12 +210,14 @@ public:
~GDMono();
};
-class GDMonoScopeDomain {
+namespace gdmono {
+
+class ScopeDomain {
MonoDomain *prev_domain;
public:
- GDMonoScopeDomain(MonoDomain *p_domain) {
+ ScopeDomain(MonoDomain *p_domain) {
MonoDomain *prev_domain = mono_domain_get();
if (prev_domain != p_domain) {
this->prev_domain = prev_domain;
@@ -220,23 +227,41 @@ public:
}
}
- ~GDMonoScopeDomain() {
+ ~ScopeDomain() {
if (prev_domain)
mono_domain_set(prev_domain, false);
}
};
-#define _GDMONO_SCOPE_DOMAIN_(m_mono_domain) \
- GDMonoScopeDomain __gdmono__scope__domain__(m_mono_domain); \
+class ScopeExitDomainUnload {
+ MonoDomain *domain;
+
+public:
+ ScopeExitDomainUnload(MonoDomain *p_domain) :
+ domain(p_domain) {
+ }
+
+ ~ScopeExitDomainUnload() {
+ if (domain)
+ GDMono::get_singleton()->finalize_and_unload_domain(domain);
+ }
+};
+
+} // namespace gdmono
+
+#define _GDMONO_SCOPE_DOMAIN_(m_mono_domain) \
+ gdmono::ScopeDomain __gdmono__scope__domain__(m_mono_domain); \
(void)__gdmono__scope__domain__;
+#define _GDMONO_SCOPE_EXIT_DOMAIN_UNLOAD_(m_mono_domain) \
+ gdmono::ScopeExitDomainUnload __gdmono__scope__exit__domain__unload__(m_mono_domain); \
+ (void)__gdmono__scope__exit__domain__unload__;
+
class _GodotSharp : public Object {
GDCLASS(_GodotSharp, Object)
friend class GDMono;
- void _dispose_callback();
-
bool _is_domain_finalizing_for_unload(int32_t p_domain_id);
List<NodePath *> np_delete_queue;
@@ -270,9 +295,6 @@ public:
bool is_runtime_shutting_down();
bool is_runtime_initialized();
- void queue_dispose(NodePath *p_node_path);
- void queue_dispose(RID *p_rid);
-
_GodotSharp();
~_GodotSharp();
};
diff --git a/modules/mono/mono_gd/gd_mono_assembly.cpp b/modules/mono/mono_gd/gd_mono_assembly.cpp
index 27ce39b6d7..1067c11e0e 100644
--- a/modules/mono/mono_gd/gd_mono_assembly.cpp
+++ b/modules/mono/mono_gd/gd_mono_assembly.cpp
@@ -46,6 +46,29 @@ bool GDMonoAssembly::in_preload = false;
Vector<String> GDMonoAssembly::search_dirs;
+void GDMonoAssembly::fill_search_dirs(Vector<String> &r_search_dirs, const String &p_custom_config) {
+
+ const char *rootdir = mono_assembly_getrootdir();
+ if (rootdir) {
+ String framework_dir = String(rootdir).plus_file("mono").plus_file("4.5");
+ r_search_dirs.push_back(framework_dir);
+ r_search_dirs.push_back(framework_dir.plus_file("Facades"));
+ }
+
+ if (p_custom_config.length()) {
+ r_search_dirs.push_back(GodotSharpDirs::get_res_temp_assemblies_base_dir().plus_file(p_custom_config));
+ } else {
+ r_search_dirs.push_back(GodotSharpDirs::get_res_temp_assemblies_dir());
+ }
+
+ r_search_dirs.push_back(GodotSharpDirs::get_res_assemblies_dir());
+ r_search_dirs.push_back(OS::get_singleton()->get_resource_dir());
+ r_search_dirs.push_back(OS::get_singleton()->get_executable_path().get_base_dir());
+#ifdef TOOLS_ENABLED
+ r_search_dirs.push_back(GodotSharpDirs::get_data_editor_tools_dir());
+#endif
+}
+
void GDMonoAssembly::assembly_load_hook(MonoAssembly *assembly, void *user_data) {
if (no_search)
@@ -93,35 +116,7 @@ MonoAssembly *GDMonoAssembly::_search_hook(MonoAssemblyName *aname, void *user_d
no_search = true; // Avoid the recursion madness
- String path;
- GDMonoAssembly *res = NULL;
-
- for (int i = 0; i < search_dirs.size(); i++) {
- const String &search_dir = search_dirs[i];
-
- if (has_extension) {
- path = search_dir.plus_file(name);
- if (FileAccess::exists(path)) {
- res = _load_assembly_from(name.get_basename(), path, refonly);
- if (res != NULL)
- break;
- }
- } else {
- path = search_dir.plus_file(name + ".dll");
- if (FileAccess::exists(path)) {
- res = _load_assembly_from(name, path, refonly);
- if (res != NULL)
- break;
- }
-
- path = search_dir.plus_file(name + ".exe");
- if (FileAccess::exists(path)) {
- res = _load_assembly_from(name, path, refonly);
- if (res != NULL)
- break;
- }
- }
- }
+ GDMonoAssembly *res = _load_assembly_search(name, search_dirs, refonly);
no_search = false;
@@ -130,31 +125,12 @@ MonoAssembly *GDMonoAssembly::_search_hook(MonoAssemblyName *aname, void *user_d
static _THREAD_LOCAL_(MonoImage *) image_corlib_loading = NULL;
-MonoAssembly *GDMonoAssembly::_preload_hook(MonoAssemblyName *aname, char **assemblies_path, void *user_data, bool refonly) {
+MonoAssembly *GDMonoAssembly::_preload_hook(MonoAssemblyName *aname, char **, void *user_data, bool refonly) {
(void)user_data; // UNUSED
if (search_dirs.empty()) {
- search_dirs.push_back(GodotSharpDirs::get_res_temp_assemblies_dir());
- search_dirs.push_back(GodotSharpDirs::get_res_assemblies_dir());
- search_dirs.push_back(OS::get_singleton()->get_resource_dir());
- search_dirs.push_back(OS::get_singleton()->get_executable_path().get_base_dir());
-#ifdef GD_MONO_EDITOR_ASSEMBLIES_DIR
- search_dirs.push_back(OS::get_singleton()->get_executable_path().get_base_dir().plus_file(_MKSTR(GD_MONO_EDITOR_ASSEMBLIES_DIR)).simplify_path());
-#endif
-
- const char *rootdir = mono_assembly_getrootdir();
- if (rootdir) {
- search_dirs.push_back(String(rootdir).plus_file("mono").plus_file("4.5"));
- search_dirs.push_back(String(rootdir).plus_file("mono").plus_file("4.5").plus_file("Facades"));
- }
-
- if (assemblies_path) {
- while (*assemblies_path) {
- search_dirs.push_back(*assemblies_path);
- ++assemblies_path;
- }
- }
+ fill_search_dirs(search_dirs);
}
{
@@ -188,27 +164,7 @@ MonoAssembly *GDMonoAssembly::_preload_hook(MonoAssemblyName *aname, char **asse
if (stored_assembly)
return (*stored_assembly)->get_assembly();
- String path;
-
- for (int i = 0; i < search_dirs.size(); i++) {
- const String &search_dir = search_dirs[i];
-
- if (has_extension) {
- path = search_dir.plus_file(name);
- if (FileAccess::exists(path)) {
- res = _load_assembly_from(name.get_basename(), path, refonly);
- if (res != NULL)
- break;
- }
- } else {
- path = search_dir.plus_file(name + ".dll");
- if (FileAccess::exists(path)) {
- res = _load_assembly_from(name, path, refonly);
- if (res != NULL)
- break;
- }
- }
- }
+ res = _load_assembly_search("mscorlib.dll", search_dirs, refonly);
}
no_search = false;
@@ -217,6 +173,43 @@ MonoAssembly *GDMonoAssembly::_preload_hook(MonoAssemblyName *aname, char **asse
return res ? res->get_assembly() : NULL;
}
+GDMonoAssembly *GDMonoAssembly::_load_assembly_search(const String &p_name, const Vector<String> &p_search_dirs, bool p_refonly) {
+
+ GDMonoAssembly *res = NULL;
+ String path;
+
+ bool has_extension = p_name.ends_with(".dll") || p_name.ends_with(".exe");
+
+ for (int i = 0; i < p_search_dirs.size(); i++) {
+ const String &search_dir = p_search_dirs[i];
+
+ if (has_extension) {
+ path = search_dir.plus_file(p_name);
+ if (FileAccess::exists(path)) {
+ res = _load_assembly_from(p_name.get_basename(), path, p_refonly);
+ if (res != NULL)
+ return res;
+ }
+ } else {
+ path = search_dir.plus_file(p_name + ".dll");
+ if (FileAccess::exists(path)) {
+ res = _load_assembly_from(p_name, path, p_refonly);
+ if (res != NULL)
+ return res;
+ }
+
+ path = search_dir.plus_file(p_name + ".exe");
+ if (FileAccess::exists(path)) {
+ res = _load_assembly_from(p_name, path, p_refonly);
+ if (res != NULL)
+ return res;
+ }
+ }
+ }
+
+ return NULL;
+}
+
GDMonoAssembly *GDMonoAssembly::_load_assembly_from(const String &p_name, const String &p_path, bool p_refonly) {
GDMonoAssembly *assembly = memnew(GDMonoAssembly(p_name, p_path));
@@ -464,19 +457,6 @@ 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;
diff --git a/modules/mono/mono_gd/gd_mono_assembly.h b/modules/mono/mono_gd/gd_mono_assembly.h
index 0ba11ac412..4c9b1cb10d 100644
--- a/modules/mono/mono_gd/gd_mono_assembly.h
+++ b/modules/mono/mono_gd/gd_mono_assembly.h
@@ -102,6 +102,7 @@ class GDMonoAssembly {
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);
+ static GDMonoAssembly *_load_assembly_search(const String &p_name, const Vector<String> &p_search_dirs, bool p_refonly);
static void _wrap_mono_assembly(MonoAssembly *assembly);
friend class GDMono;
@@ -125,7 +126,7 @@ 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);
+ static void fill_search_dirs(Vector<String> &r_search_dirs, const String &p_custom_config = String());
GDMonoAssembly(const String &p_name, const String &p_path = String());
~GDMonoAssembly();
diff --git a/modules/mono/mono_gd/gd_mono_field.cpp b/modules/mono/mono_gd/gd_mono_field.cpp
index d3a673dc1b..fe41722af0 100644
--- a/modules/mono/mono_gd/gd_mono_field.cpp
+++ b/modules/mono/mono_gd/gd_mono_field.cpp
@@ -40,65 +40,71 @@ void GDMonoField::set_value_raw(MonoObject *p_object, void *p_ptr) {
}
void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_value) {
-#define SET_FROM_STRUCT_AND_BREAK(m_type) \
- { \
- const m_type &val = p_value.operator ::m_type(); \
- MARSHALLED_OUT(m_type, val, raw); \
- mono_field_set_value(p_object, mono_field, raw); \
- break; \
+#define SET_FROM_STRUCT(m_type) \
+ { \
+ GDMonoMarshal::M_##m_type from = MARSHALLED_OUT(m_type, p_value.operator ::m_type()); \
+ mono_field_set_value(p_object, mono_field, &from); \
}
-#define SET_FROM_PRIMITIVE(m_type) \
- { \
- m_type val = p_value.operator m_type(); \
- mono_field_set_value(p_object, mono_field, &val); \
- break; \
- }
-
-#define SET_FROM_ARRAY_AND_BREAK(m_type) \
- { \
- MonoArray *managed = GDMonoMarshal::m_type##_to_mono_array(p_value.operator m_type()); \
- mono_field_set_value(p_object, mono_field, &managed); \
- break; \
+#define SET_FROM_ARRAY(m_type) \
+ { \
+ MonoArray *managed = GDMonoMarshal::m_type##_to_mono_array(p_value.operator ::m_type()); \
+ mono_field_set_value(p_object, mono_field, &managed); \
}
switch (type.type_encoding) {
case MONO_TYPE_BOOLEAN: {
- SET_FROM_PRIMITIVE(bool);
+ MonoBoolean val = p_value.operator bool();
+ mono_field_set_value(p_object, mono_field, &val);
+ } break;
+
+ case MONO_TYPE_CHAR: {
+ int16_t val = p_value.operator unsigned short();
+ mono_field_set_value(p_object, mono_field, &val);
} break;
case MONO_TYPE_I1: {
- SET_FROM_PRIMITIVE(signed char);
+ int8_t val = p_value.operator signed char();
+ mono_field_set_value(p_object, mono_field, &val);
} break;
case MONO_TYPE_I2: {
- SET_FROM_PRIMITIVE(signed short);
+ int16_t val = p_value.operator signed short();
+ mono_field_set_value(p_object, mono_field, &val);
} break;
case MONO_TYPE_I4: {
- SET_FROM_PRIMITIVE(signed int);
+ int32_t val = p_value.operator signed int();
+ mono_field_set_value(p_object, mono_field, &val);
} break;
case MONO_TYPE_I8: {
- SET_FROM_PRIMITIVE(int64_t);
+ int64_t val = p_value.operator int64_t();
+ mono_field_set_value(p_object, mono_field, &val);
} break;
case MONO_TYPE_U1: {
- SET_FROM_PRIMITIVE(unsigned char);
+ uint8_t val = p_value.operator unsigned char();
+ mono_field_set_value(p_object, mono_field, &val);
} break;
case MONO_TYPE_U2: {
- SET_FROM_PRIMITIVE(unsigned short);
+ uint16_t val = p_value.operator unsigned short();
+ mono_field_set_value(p_object, mono_field, &val);
} break;
case MONO_TYPE_U4: {
- SET_FROM_PRIMITIVE(unsigned int);
+ uint32_t val = p_value.operator unsigned int();
+ mono_field_set_value(p_object, mono_field, &val);
} break;
case MONO_TYPE_U8: {
- SET_FROM_PRIMITIVE(uint64_t);
+ uint64_t val = p_value.operator uint64_t();
+ mono_field_set_value(p_object, mono_field, &val);
} break;
case MONO_TYPE_R4: {
- SET_FROM_PRIMITIVE(float);
+ float val = p_value.operator float();
+ mono_field_set_value(p_object, mono_field, &val);
} break;
case MONO_TYPE_R8: {
- SET_FROM_PRIMITIVE(double);
+ double val = p_value.operator double();
+ mono_field_set_value(p_object, mono_field, &val);
} break;
case MONO_TYPE_STRING: {
@@ -109,38 +115,115 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_
case MONO_TYPE_VALUETYPE: {
GDMonoClass *tclass = type.type_class;
- if (tclass == CACHED_CLASS(Vector2))
- SET_FROM_STRUCT_AND_BREAK(Vector2);
+ if (tclass == CACHED_CLASS(Vector2)) {
+ SET_FROM_STRUCT(Vector2);
+ break;
+ }
- if (tclass == CACHED_CLASS(Rect2))
- SET_FROM_STRUCT_AND_BREAK(Rect2);
+ if (tclass == CACHED_CLASS(Rect2)) {
+ SET_FROM_STRUCT(Rect2);
+ break;
+ }
- if (tclass == CACHED_CLASS(Transform2D))
- SET_FROM_STRUCT_AND_BREAK(Transform2D);
+ if (tclass == CACHED_CLASS(Transform2D)) {
+ SET_FROM_STRUCT(Transform2D);
+ break;
+ }
- if (tclass == CACHED_CLASS(Vector3))
- SET_FROM_STRUCT_AND_BREAK(Vector3);
+ if (tclass == CACHED_CLASS(Vector3)) {
+ SET_FROM_STRUCT(Vector3);
+ break;
+ }
- if (tclass == CACHED_CLASS(Basis))
- SET_FROM_STRUCT_AND_BREAK(Basis);
+ if (tclass == CACHED_CLASS(Basis)) {
+ SET_FROM_STRUCT(Basis);
+ break;
+ }
- if (tclass == CACHED_CLASS(Quat))
- SET_FROM_STRUCT_AND_BREAK(Quat);
+ if (tclass == CACHED_CLASS(Quat)) {
+ SET_FROM_STRUCT(Quat);
+ break;
+ }
- if (tclass == CACHED_CLASS(Transform))
- SET_FROM_STRUCT_AND_BREAK(Transform);
+ if (tclass == CACHED_CLASS(Transform)) {
+ SET_FROM_STRUCT(Transform);
+ break;
+ }
- if (tclass == CACHED_CLASS(AABB))
- SET_FROM_STRUCT_AND_BREAK(AABB);
+ if (tclass == CACHED_CLASS(AABB)) {
+ SET_FROM_STRUCT(AABB);
+ break;
+ }
- if (tclass == CACHED_CLASS(Color))
- SET_FROM_STRUCT_AND_BREAK(Color);
+ if (tclass == CACHED_CLASS(Color)) {
+ SET_FROM_STRUCT(Color);
+ break;
+ }
- if (tclass == CACHED_CLASS(Plane))
- SET_FROM_STRUCT_AND_BREAK(Plane);
+ if (tclass == CACHED_CLASS(Plane)) {
+ SET_FROM_STRUCT(Plane);
+ break;
+ }
- if (mono_class_is_enum(tclass->get_mono_ptr()))
- SET_FROM_PRIMITIVE(signed int);
+ if (mono_class_is_enum(tclass->get_mono_ptr())) {
+ MonoType *enum_basetype = mono_class_enum_basetype(tclass->get_mono_ptr());
+ switch (mono_type_get_type(enum_basetype)) {
+ case MONO_TYPE_BOOLEAN: {
+ MonoBoolean val = p_value.operator bool();
+ mono_field_set_value(p_object, mono_field, &val);
+ break;
+ }
+ case MONO_TYPE_CHAR: {
+ uint16_t val = p_value.operator unsigned short();
+ mono_field_set_value(p_object, mono_field, &val);
+ break;
+ }
+ case MONO_TYPE_I1: {
+ int8_t val = p_value.operator signed char();
+ mono_field_set_value(p_object, mono_field, &val);
+ break;
+ }
+ case MONO_TYPE_I2: {
+ int16_t val = p_value.operator signed short();
+ mono_field_set_value(p_object, mono_field, &val);
+ break;
+ }
+ case MONO_TYPE_I4: {
+ int32_t val = p_value.operator signed int();
+ mono_field_set_value(p_object, mono_field, &val);
+ break;
+ }
+ case MONO_TYPE_I8: {
+ int64_t val = p_value.operator int64_t();
+ mono_field_set_value(p_object, mono_field, &val);
+ break;
+ }
+ case MONO_TYPE_U1: {
+ uint8_t val = p_value.operator unsigned char();
+ mono_field_set_value(p_object, mono_field, &val);
+ break;
+ }
+ case MONO_TYPE_U2: {
+ uint16_t val = p_value.operator unsigned short();
+ mono_field_set_value(p_object, mono_field, &val);
+ break;
+ }
+ case MONO_TYPE_U4: {
+ uint32_t val = p_value.operator unsigned int();
+ mono_field_set_value(p_object, mono_field, &val);
+ break;
+ }
+ case MONO_TYPE_U8: {
+ uint64_t val = p_value.operator uint64_t();
+ mono_field_set_value(p_object, mono_field, &val);
+ break;
+ }
+ default: {
+ ERR_EXPLAIN(String() + "Attempted to convert Variant to a managed enum value of unmarshallable base type.");
+ ERR_FAIL();
+ }
+ }
+ }
ERR_EXPLAIN(String() + "Attempted to set the value of a field of unmarshallable type: " + tclass->get_name());
ERR_FAIL();
@@ -150,29 +233,45 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_
case MONO_TYPE_SZARRAY: {
MonoArrayType *array_type = mono_type_get_array_type(type.type_class->get_mono_type());
- if (array_type->eklass == CACHED_CLASS_RAW(MonoObject))
- SET_FROM_ARRAY_AND_BREAK(Array);
+ if (array_type->eklass == CACHED_CLASS_RAW(MonoObject)) {
+ SET_FROM_ARRAY(Array);
+ break;
+ }
- if (array_type->eklass == CACHED_CLASS_RAW(uint8_t))
- SET_FROM_ARRAY_AND_BREAK(PoolByteArray);
+ if (array_type->eklass == CACHED_CLASS_RAW(uint8_t)) {
+ SET_FROM_ARRAY(PoolByteArray);
+ break;
+ }
- if (array_type->eklass == CACHED_CLASS_RAW(int32_t))
- SET_FROM_ARRAY_AND_BREAK(PoolIntArray);
+ if (array_type->eklass == CACHED_CLASS_RAW(int32_t)) {
+ SET_FROM_ARRAY(PoolIntArray);
+ break;
+ }
- if (array_type->eklass == REAL_T_MONOCLASS)
- SET_FROM_ARRAY_AND_BREAK(PoolRealArray);
+ if (array_type->eklass == REAL_T_MONOCLASS) {
+ SET_FROM_ARRAY(PoolRealArray);
+ break;
+ }
- if (array_type->eklass == CACHED_CLASS_RAW(String))
- SET_FROM_ARRAY_AND_BREAK(PoolStringArray);
+ if (array_type->eklass == CACHED_CLASS_RAW(String)) {
+ SET_FROM_ARRAY(PoolStringArray);
+ break;
+ }
- if (array_type->eklass == CACHED_CLASS_RAW(Vector2))
- SET_FROM_ARRAY_AND_BREAK(PoolVector2Array);
+ if (array_type->eklass == CACHED_CLASS_RAW(Vector2)) {
+ SET_FROM_ARRAY(PoolVector2Array);
+ break;
+ }
- if (array_type->eklass == CACHED_CLASS_RAW(Vector3))
- SET_FROM_ARRAY_AND_BREAK(PoolVector3Array);
+ if (array_type->eklass == CACHED_CLASS_RAW(Vector3)) {
+ SET_FROM_ARRAY(PoolVector3Array);
+ break;
+ }
- if (array_type->eklass == CACHED_CLASS_RAW(Color))
- SET_FROM_ARRAY_AND_BREAK(PoolColorArray);
+ if (array_type->eklass == CACHED_CLASS_RAW(Color)) {
+ SET_FROM_ARRAY(PoolColorArray);
+ break;
+ }
ERR_EXPLAIN(String() + "Attempted to convert Variant to a managed array of unmarshallable element type.");
ERR_FAIL();
@@ -220,32 +319,56 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_
// Variant
switch (p_value.get_type()) {
case Variant::BOOL: {
- SET_FROM_PRIMITIVE(bool);
+ MonoBoolean val = p_value.operator bool();
+ mono_field_set_value(p_object, mono_field, &val);
} break;
case Variant::INT: {
- SET_FROM_PRIMITIVE(int);
+ int32_t val = p_value.operator signed int();
+ mono_field_set_value(p_object, mono_field, &val);
} break;
case Variant::REAL: {
#ifdef REAL_T_IS_DOUBLE
- SET_FROM_PRIMITIVE(double);
+ double val = p_value.operator double();
+ mono_field_set_value(p_object, mono_field, &val);
#else
- SET_FROM_PRIMITIVE(float);
+ float val = p_value.operator float();
+ mono_field_set_value(p_object, mono_field, &val);
#endif
} break;
case Variant::STRING: {
MonoString *mono_string = GDMonoMarshal::mono_string_from_godot(p_value);
mono_field_set_value(p_object, mono_field, mono_string);
} break;
- case Variant::VECTOR2: SET_FROM_STRUCT_AND_BREAK(Vector2);
- case Variant::RECT2: SET_FROM_STRUCT_AND_BREAK(Rect2);
- case Variant::VECTOR3: SET_FROM_STRUCT_AND_BREAK(Vector3);
- case Variant::TRANSFORM2D: SET_FROM_STRUCT_AND_BREAK(Transform2D);
- case Variant::PLANE: SET_FROM_STRUCT_AND_BREAK(Plane);
- case Variant::QUAT: SET_FROM_STRUCT_AND_BREAK(Quat);
- case Variant::AABB: SET_FROM_STRUCT_AND_BREAK(AABB);
- case Variant::BASIS: SET_FROM_STRUCT_AND_BREAK(Basis);
- case Variant::TRANSFORM: SET_FROM_STRUCT_AND_BREAK(Transform);
- case Variant::COLOR: SET_FROM_STRUCT_AND_BREAK(Color);
+ case Variant::VECTOR2: {
+ SET_FROM_STRUCT(Vector2);
+ } break;
+ case Variant::RECT2: {
+ SET_FROM_STRUCT(Rect2);
+ } break;
+ case Variant::VECTOR3: {
+ SET_FROM_STRUCT(Vector3);
+ } break;
+ case Variant::TRANSFORM2D: {
+ SET_FROM_STRUCT(Transform2D);
+ } break;
+ case Variant::PLANE: {
+ SET_FROM_STRUCT(Plane);
+ } break;
+ case Variant::QUAT: {
+ SET_FROM_STRUCT(Quat);
+ } break;
+ case Variant::AABB: {
+ SET_FROM_STRUCT(AABB);
+ } break;
+ case Variant::BASIS: {
+ SET_FROM_STRUCT(Basis);
+ } break;
+ case Variant::TRANSFORM: {
+ SET_FROM_STRUCT(Transform);
+ } break;
+ case Variant::COLOR: {
+ SET_FROM_STRUCT(Color);
+ } break;
case Variant::NODE_PATH: {
MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator NodePath());
mono_field_set_value(p_object, mono_field, managed);
@@ -267,14 +390,27 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_
MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator Array(), CACHED_CLASS(Array));
mono_field_set_value(p_object, mono_field, managed);
} break;
- case Variant::POOL_BYTE_ARRAY: SET_FROM_ARRAY_AND_BREAK(PoolByteArray);
- case Variant::POOL_INT_ARRAY: SET_FROM_ARRAY_AND_BREAK(PoolIntArray);
- case Variant::POOL_REAL_ARRAY: SET_FROM_ARRAY_AND_BREAK(PoolRealArray);
- case Variant::POOL_STRING_ARRAY: SET_FROM_ARRAY_AND_BREAK(PoolStringArray);
- case Variant::POOL_VECTOR2_ARRAY: SET_FROM_ARRAY_AND_BREAK(PoolVector2Array);
- case Variant::POOL_VECTOR3_ARRAY: SET_FROM_ARRAY_AND_BREAK(PoolVector3Array);
- case Variant::POOL_COLOR_ARRAY: SET_FROM_ARRAY_AND_BREAK(PoolColorArray);
-#undef SET_FROM_ARRAY_AND_BREAK
+ case Variant::POOL_BYTE_ARRAY: {
+ SET_FROM_ARRAY(PoolByteArray);
+ } break;
+ case Variant::POOL_INT_ARRAY: {
+ SET_FROM_ARRAY(PoolIntArray);
+ } break;
+ case Variant::POOL_REAL_ARRAY: {
+ SET_FROM_ARRAY(PoolRealArray);
+ } break;
+ case Variant::POOL_STRING_ARRAY: {
+ SET_FROM_ARRAY(PoolStringArray);
+ } break;
+ case Variant::POOL_VECTOR2_ARRAY: {
+ SET_FROM_ARRAY(PoolVector2Array);
+ } break;
+ case Variant::POOL_VECTOR3_ARRAY: {
+ SET_FROM_ARRAY(PoolVector3Array);
+ } break;
+ case Variant::POOL_COLOR_ARRAY: {
+ SET_FROM_ARRAY(PoolColorArray);
+ } break;
default: break;
}
} break;
@@ -312,8 +448,8 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_
} break;
}
+#undef SET_FROM_ARRAY_AND_BREAK
#undef SET_FROM_STRUCT_AND_BREAK
-#undef SET_FROM_PRIMITIVE
}
MonoObject *GDMonoField::get_value(MonoObject *p_object) {
diff --git a/modules/mono/mono_gd/gd_mono_header.h b/modules/mono/mono_gd/gd_mono_header.h
index 4f2efc7b92..51d0c9b356 100644
--- a/modules/mono/mono_gd/gd_mono_header.h
+++ b/modules/mono/mono_gd/gd_mono_header.h
@@ -55,14 +55,4 @@ struct ManagedType {
}
};
-typedef union {
- uint32_t _uint32;
- float _float;
-} mono_float;
-
-typedef union {
- uint64_t _uint64;
- float _double;
-} mono_double;
-
#endif // GD_MONO_HEADER_H
diff --git a/modules/mono/mono_gd/gd_mono_marshal.cpp b/modules/mono/mono_gd/gd_mono_marshal.cpp
index de91e71bab..2543f5dc47 100644
--- a/modules/mono/mono_gd/gd_mono_marshal.cpp
+++ b/modules/mono/mono_gd/gd_mono_marshal.cpp
@@ -35,20 +35,6 @@
namespace GDMonoMarshal {
-#define RETURN_BOXED_STRUCT(m_t, m_var_in) \
- { \
- const m_t &m_in = m_var_in->operator ::m_t(); \
- MARSHALLED_OUT(m_t, m_in, raw); \
- return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(m_t), raw); \
- }
-
-#define RETURN_UNBOXED_STRUCT(m_t, m_var_in) \
- { \
- float *raw = (float *)mono_object_unbox(m_var_in); \
- MARSHALLED_IN(m_t, raw, ret); \
- return ret; \
- }
-
Variant::Type managed_to_variant_type(const ManagedType &p_type) {
switch (p_type.type_encoding) {
case MONO_TYPE_BOOLEAN:
@@ -252,16 +238,21 @@ MonoObject *variant_to_mono_object(const Variant *p_var, const ManagedType &p_ty
return BOX_BOOLEAN(val);
}
+ case MONO_TYPE_CHAR: {
+ uint16_t val = p_var->operator unsigned short();
+ return BOX_UINT16(val);
+ }
+
case MONO_TYPE_I1: {
- char val = p_var->operator signed char();
+ int8_t val = p_var->operator signed char();
return BOX_INT8(val);
}
case MONO_TYPE_I2: {
- short val = p_var->operator signed short();
+ int16_t val = p_var->operator signed short();
return BOX_INT16(val);
}
case MONO_TYPE_I4: {
- int val = p_var->operator signed int();
+ int32_t val = p_var->operator signed int();
return BOX_INT32(val);
}
case MONO_TYPE_I8: {
@@ -270,15 +261,15 @@ MonoObject *variant_to_mono_object(const Variant *p_var, const ManagedType &p_ty
}
case MONO_TYPE_U1: {
- char val = p_var->operator unsigned char();
+ uint8_t val = p_var->operator unsigned char();
return BOX_UINT8(val);
}
case MONO_TYPE_U2: {
- short val = p_var->operator unsigned short();
+ uint16_t val = p_var->operator unsigned short();
return BOX_UINT16(val);
}
case MONO_TYPE_U4: {
- int val = p_var->operator unsigned int();
+ uint32_t val = p_var->operator unsigned int();
return BOX_UINT32(val);
}
case MONO_TYPE_U8: {
@@ -302,39 +293,105 @@ MonoObject *variant_to_mono_object(const Variant *p_var, const ManagedType &p_ty
case MONO_TYPE_VALUETYPE: {
GDMonoClass *tclass = p_type.type_class;
- if (tclass == CACHED_CLASS(Vector2))
- RETURN_BOXED_STRUCT(Vector2, p_var);
+ if (tclass == CACHED_CLASS(Vector2)) {
+ GDMonoMarshal::M_Vector2 from = MARSHALLED_OUT(Vector2, p_var->operator ::Vector2());
+ return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Vector2), &from);
+ }
- if (tclass == CACHED_CLASS(Rect2))
- RETURN_BOXED_STRUCT(Rect2, p_var);
+ if (tclass == CACHED_CLASS(Rect2)) {
+ GDMonoMarshal::M_Rect2 from = MARSHALLED_OUT(Rect2, p_var->operator ::Rect2());
+ return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Rect2), &from);
+ }
- if (tclass == CACHED_CLASS(Transform2D))
- RETURN_BOXED_STRUCT(Transform2D, p_var);
+ if (tclass == CACHED_CLASS(Transform2D)) {
+ GDMonoMarshal::M_Transform2D from = MARSHALLED_OUT(Transform2D, p_var->operator ::Transform2D());
+ return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Transform2D), &from);
+ }
- if (tclass == CACHED_CLASS(Vector3))
- RETURN_BOXED_STRUCT(Vector3, p_var);
+ if (tclass == CACHED_CLASS(Vector3)) {
+ GDMonoMarshal::M_Vector3 from = MARSHALLED_OUT(Vector3, p_var->operator ::Vector3());
+ return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Vector3), &from);
+ }
- if (tclass == CACHED_CLASS(Basis))
- RETURN_BOXED_STRUCT(Basis, p_var);
+ if (tclass == CACHED_CLASS(Basis)) {
+ GDMonoMarshal::M_Basis from = MARSHALLED_OUT(Basis, p_var->operator ::Basis());
+ return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Basis), &from);
+ }
- if (tclass == CACHED_CLASS(Quat))
- RETURN_BOXED_STRUCT(Quat, p_var);
+ if (tclass == CACHED_CLASS(Quat)) {
+ GDMonoMarshal::M_Quat from = MARSHALLED_OUT(Quat, p_var->operator ::Quat());
+ return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Quat), &from);
+ }
- if (tclass == CACHED_CLASS(Transform))
- RETURN_BOXED_STRUCT(Transform, p_var);
+ if (tclass == CACHED_CLASS(Transform)) {
+ GDMonoMarshal::M_Transform from = MARSHALLED_OUT(Transform, p_var->operator ::Transform());
+ return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Transform), &from);
+ }
- if (tclass == CACHED_CLASS(AABB))
- RETURN_BOXED_STRUCT(AABB, p_var);
+ if (tclass == CACHED_CLASS(AABB)) {
+ GDMonoMarshal::M_AABB from = MARSHALLED_OUT(AABB, p_var->operator ::AABB());
+ return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(AABB), &from);
+ }
- if (tclass == CACHED_CLASS(Color))
- RETURN_BOXED_STRUCT(Color, p_var);
+ if (tclass == CACHED_CLASS(Color)) {
+ GDMonoMarshal::M_Color from = MARSHALLED_OUT(Color, p_var->operator ::Color());
+ return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Color), &from);
+ }
- if (tclass == CACHED_CLASS(Plane))
- RETURN_BOXED_STRUCT(Plane, p_var);
+ if (tclass == CACHED_CLASS(Plane)) {
+ GDMonoMarshal::M_Plane from = MARSHALLED_OUT(Plane, p_var->operator ::Plane());
+ return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Plane), &from);
+ }
if (mono_class_is_enum(tclass->get_mono_ptr())) {
- int val = p_var->operator signed int();
- return BOX_ENUM(tclass->get_mono_ptr(), val);
+ MonoType *enum_basetype = mono_class_enum_basetype(tclass->get_mono_ptr());
+ MonoClass *enum_baseclass = mono_class_from_mono_type(enum_basetype);
+ switch (mono_type_get_type(enum_basetype)) {
+ case MONO_TYPE_BOOLEAN: {
+ MonoBoolean val = p_var->operator bool();
+ return BOX_ENUM(enum_baseclass, val);
+ }
+ case MONO_TYPE_CHAR: {
+ uint16_t val = p_var->operator unsigned short();
+ return BOX_ENUM(enum_baseclass, val);
+ }
+ case MONO_TYPE_I1: {
+ int8_t val = p_var->operator signed char();
+ return BOX_ENUM(enum_baseclass, val);
+ }
+ case MONO_TYPE_I2: {
+ int16_t val = p_var->operator signed short();
+ return BOX_ENUM(enum_baseclass, val);
+ }
+ case MONO_TYPE_I4: {
+ int32_t val = p_var->operator signed int();
+ return BOX_ENUM(enum_baseclass, val);
+ }
+ case MONO_TYPE_I8: {
+ int64_t val = p_var->operator int64_t();
+ return BOX_ENUM(enum_baseclass, val);
+ }
+ case MONO_TYPE_U1: {
+ uint8_t val = p_var->operator unsigned char();
+ return BOX_ENUM(enum_baseclass, val);
+ }
+ case MONO_TYPE_U2: {
+ uint16_t val = p_var->operator unsigned short();
+ return BOX_ENUM(enum_baseclass, val);
+ }
+ case MONO_TYPE_U4: {
+ uint32_t val = p_var->operator unsigned int();
+ return BOX_ENUM(enum_baseclass, val);
+ }
+ case MONO_TYPE_U8: {
+ uint64_t val = p_var->operator uint64_t();
+ return BOX_ENUM(enum_baseclass, val);
+ }
+ default: {
+ ERR_EXPLAIN(String() + "Attempted to convert Variant to a managed enum value of unmarshallable base type.");
+ ERR_FAIL_V(NULL);
+ }
+ }
}
} break;
@@ -402,7 +459,7 @@ MonoObject *variant_to_mono_object(const Variant *p_var, const ManagedType &p_ty
return BOX_BOOLEAN(val);
}
case Variant::INT: {
- int val = p_var->operator signed int();
+ int32_t val = p_var->operator signed int();
return BOX_INT32(val);
}
case Variant::REAL: {
@@ -416,33 +473,52 @@ MonoObject *variant_to_mono_object(const Variant *p_var, const ManagedType &p_ty
}
case Variant::STRING:
return (MonoObject *)mono_string_from_godot(p_var->operator String());
- case Variant::VECTOR2:
- RETURN_BOXED_STRUCT(Vector2, p_var);
- case Variant::RECT2:
- RETURN_BOXED_STRUCT(Rect2, p_var);
- case Variant::VECTOR3:
- RETURN_BOXED_STRUCT(Vector3, p_var);
- case Variant::TRANSFORM2D:
- RETURN_BOXED_STRUCT(Transform2D, p_var);
- case Variant::PLANE:
- RETURN_BOXED_STRUCT(Plane, p_var);
- case Variant::QUAT:
- RETURN_BOXED_STRUCT(Quat, p_var);
- case Variant::AABB:
- RETURN_BOXED_STRUCT(AABB, p_var);
- case Variant::BASIS:
- RETURN_BOXED_STRUCT(Basis, p_var);
- case Variant::TRANSFORM:
- RETURN_BOXED_STRUCT(Transform, p_var);
- case Variant::COLOR:
- RETURN_BOXED_STRUCT(Color, p_var);
+ case Variant::VECTOR2: {
+ GDMonoMarshal::M_Vector2 from = MARSHALLED_OUT(Vector2, p_var->operator ::Vector2());
+ return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Vector2), &from);
+ }
+ case Variant::RECT2: {
+ GDMonoMarshal::M_Rect2 from = MARSHALLED_OUT(Rect2, p_var->operator ::Rect2());
+ return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Rect2), &from);
+ }
+ case Variant::VECTOR3: {
+ GDMonoMarshal::M_Vector3 from = MARSHALLED_OUT(Vector3, p_var->operator ::Vector3());
+ return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Vector3), &from);
+ }
+ case Variant::TRANSFORM2D: {
+ GDMonoMarshal::M_Transform2D from = MARSHALLED_OUT(Transform2D, p_var->operator ::Transform2D());
+ return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Transform2D), &from);
+ }
+ case Variant::PLANE: {
+ GDMonoMarshal::M_Plane from = MARSHALLED_OUT(Plane, p_var->operator ::Plane());
+ return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Plane), &from);
+ }
+ case Variant::QUAT: {
+ GDMonoMarshal::M_Quat from = MARSHALLED_OUT(Quat, p_var->operator ::Quat());
+ return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Quat), &from);
+ }
+ case Variant::AABB: {
+ GDMonoMarshal::M_AABB from = MARSHALLED_OUT(AABB, p_var->operator ::AABB());
+ return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(AABB), &from);
+ }
+ case Variant::BASIS: {
+ GDMonoMarshal::M_Basis from = MARSHALLED_OUT(Basis, p_var->operator ::Basis());
+ return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Basis), &from);
+ }
+ case Variant::TRANSFORM: {
+ GDMonoMarshal::M_Transform from = MARSHALLED_OUT(Transform, p_var->operator ::Transform());
+ return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Transform), &from);
+ }
+ case Variant::COLOR: {
+ GDMonoMarshal::M_Color from = MARSHALLED_OUT(Color, p_var->operator ::Color());
+ return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Color), &from);
+ }
case Variant::NODE_PATH:
return GDMonoUtils::create_managed_from(p_var->operator NodePath());
case Variant::_RID:
return GDMonoUtils::create_managed_from(p_var->operator RID());
- case Variant::OBJECT: {
+ case Variant::OBJECT:
return GDMonoUtils::unmanaged_get_managed(p_var->operator Object *());
- }
case Variant::DICTIONARY:
return GDMonoUtils::create_managed_from(p_var->operator Dictionary(), CACHED_CLASS(Dictionary));
case Variant::ARRAY:
@@ -512,6 +588,9 @@ Variant mono_object_to_variant(MonoObject *p_obj) {
case MONO_TYPE_BOOLEAN:
return (bool)unbox<MonoBoolean>(p_obj);
+ case MONO_TYPE_CHAR:
+ return unbox<uint16_t>(p_obj);
+
case MONO_TYPE_I1:
return unbox<int8_t>(p_obj);
case MONO_TYPE_I2:
@@ -545,34 +624,34 @@ Variant mono_object_to_variant(MonoObject *p_obj) {
GDMonoClass *tclass = type.type_class;
if (tclass == CACHED_CLASS(Vector2))
- RETURN_UNBOXED_STRUCT(Vector2, p_obj);
+ return MARSHALLED_IN(Vector2, (GDMonoMarshal::M_Vector2 *)mono_object_unbox(p_obj));
if (tclass == CACHED_CLASS(Rect2))
- RETURN_UNBOXED_STRUCT(Rect2, p_obj);
+ return MARSHALLED_IN(Rect2, (GDMonoMarshal::M_Rect2 *)mono_object_unbox(p_obj));
if (tclass == CACHED_CLASS(Transform2D))
- RETURN_UNBOXED_STRUCT(Transform2D, p_obj);
+ return MARSHALLED_IN(Transform2D, (GDMonoMarshal::M_Transform2D *)mono_object_unbox(p_obj));
if (tclass == CACHED_CLASS(Vector3))
- RETURN_UNBOXED_STRUCT(Vector3, p_obj);
+ return MARSHALLED_IN(Vector3, (GDMonoMarshal::M_Vector3 *)mono_object_unbox(p_obj));
if (tclass == CACHED_CLASS(Basis))
- RETURN_UNBOXED_STRUCT(Basis, p_obj);
+ return MARSHALLED_IN(Basis, (GDMonoMarshal::M_Basis *)mono_object_unbox(p_obj));
if (tclass == CACHED_CLASS(Quat))
- RETURN_UNBOXED_STRUCT(Quat, p_obj);
+ return MARSHALLED_IN(Quat, (GDMonoMarshal::M_Quat *)mono_object_unbox(p_obj));
if (tclass == CACHED_CLASS(Transform))
- RETURN_UNBOXED_STRUCT(Transform, p_obj);
+ return MARSHALLED_IN(Transform, (GDMonoMarshal::M_Transform *)mono_object_unbox(p_obj));
if (tclass == CACHED_CLASS(AABB))
- RETURN_UNBOXED_STRUCT(AABB, p_obj);
+ return MARSHALLED_IN(AABB, (GDMonoMarshal::M_AABB *)mono_object_unbox(p_obj));
if (tclass == CACHED_CLASS(Color))
- RETURN_UNBOXED_STRUCT(Color, p_obj);
+ return MARSHALLED_IN(Color, (GDMonoMarshal::M_Color *)mono_object_unbox(p_obj));
if (tclass == CACHED_CLASS(Plane))
- RETURN_UNBOXED_STRUCT(Plane, p_obj);
+ return MARSHALLED_IN(Plane, (GDMonoMarshal::M_Plane *)mono_object_unbox(p_obj));
if (mono_class_is_enum(tclass->get_mono_ptr()))
return unbox<int32_t>(p_obj);
@@ -708,13 +787,13 @@ Array mono_array_to_Array(MonoArray *p_array) {
return ret;
}
-// TODO Optimize reading/writing from/to PoolArrays
-
MonoArray *PoolIntArray_to_mono_array(const PoolIntArray &p_array) {
+ PoolIntArray::Read r = p_array.read();
+
MonoArray *ret = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(int32_t), p_array.size());
for (int i = 0; i < p_array.size(); i++) {
- mono_array_set(ret, int32_t, i, p_array[i]);
+ mono_array_set(ret, int32_t, i, r[i]);
}
return ret;
@@ -726,19 +805,22 @@ PoolIntArray mono_array_to_PoolIntArray(MonoArray *p_array) {
return ret;
int length = mono_array_length(p_array);
ret.resize(length);
+ PoolIntArray::Write w = ret.write();
+
for (int i = 0; i < length; i++) {
- int32_t elem = mono_array_get(p_array, int32_t, i);
- ret.set(i, elem);
+ w[i] = mono_array_get(p_array, int32_t, i);
}
return ret;
}
MonoArray *PoolByteArray_to_mono_array(const PoolByteArray &p_array) {
+ PoolByteArray::Read r = p_array.read();
+
MonoArray *ret = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(uint8_t), p_array.size());
for (int i = 0; i < p_array.size(); i++) {
- mono_array_set(ret, uint8_t, i, p_array[i]);
+ mono_array_set(ret, uint8_t, i, r[i]);
}
return ret;
@@ -750,20 +832,22 @@ PoolByteArray mono_array_to_PoolByteArray(MonoArray *p_array) {
return ret;
int length = mono_array_length(p_array);
ret.resize(length);
+ PoolByteArray::Write w = ret.write();
for (int i = 0; i < length; i++) {
- uint8_t elem = mono_array_get(p_array, uint8_t, i);
- ret.set(i, elem);
+ w[i] = mono_array_get(p_array, uint8_t, i);
}
return ret;
}
MonoArray *PoolRealArray_to_mono_array(const PoolRealArray &p_array) {
+ PoolRealArray::Read r = p_array.read();
+
MonoArray *ret = mono_array_new(mono_domain_get(), REAL_T_MONOCLASS, p_array.size());
for (int i = 0; i < p_array.size(); i++) {
- mono_array_set(ret, real_t, i, p_array[i]);
+ mono_array_set(ret, real_t, i, r[i]);
}
return ret;
@@ -775,20 +859,22 @@ PoolRealArray mono_array_to_PoolRealArray(MonoArray *p_array) {
return ret;
int length = mono_array_length(p_array);
ret.resize(length);
+ PoolRealArray::Write w = ret.write();
for (int i = 0; i < length; i++) {
- real_t elem = mono_array_get(p_array, real_t, i);
- ret.set(i, elem);
+ w[i] = mono_array_get(p_array, real_t, i);
}
return ret;
}
MonoArray *PoolStringArray_to_mono_array(const PoolStringArray &p_array) {
+ PoolStringArray::Read r = p_array.read();
+
MonoArray *ret = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(String), p_array.size());
for (int i = 0; i < p_array.size(); i++) {
- MonoString *boxed = mono_string_from_godot(p_array[i]);
+ MonoString *boxed = mono_string_from_godot(r[i]);
mono_array_set(ret, MonoString *, i, boxed);
}
@@ -801,29 +887,24 @@ PoolStringArray mono_array_to_PoolStringArray(MonoArray *p_array) {
return ret;
int length = mono_array_length(p_array);
ret.resize(length);
+ PoolStringArray::Write w = ret.write();
for (int i = 0; i < length; i++) {
MonoString *elem = mono_array_get(p_array, MonoString *, i);
- ret.set(i, mono_string_to_godot(elem));
+ w[i] = mono_string_to_godot(elem);
}
return ret;
}
MonoArray *PoolColorArray_to_mono_array(const PoolColorArray &p_array) {
+ PoolColorArray::Read r = p_array.read();
+
MonoArray *ret = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(Color), p_array.size());
for (int i = 0; i < p_array.size(); i++) {
-#ifdef YOLOCOPY
- mono_array_set(ret, Color, i, p_array[i]);
-#else
- real_t *raw = (real_t *)mono_array_addr_with_size(ret, sizeof(real_t) * 4, i);
- const Color &elem = p_array[i];
- raw[0] = elem.r;
- raw[1] = elem.g;
- raw[2] = elem.b;
- raw[3] = elem.a;
-#endif
+ M_Color *raw = (M_Color *)mono_array_addr_with_size(ret, sizeof(M_Color), i);
+ *raw = MARSHALLED_OUT(Color, r[i]);
}
return ret;
@@ -835,28 +916,23 @@ PoolColorArray mono_array_to_PoolColorArray(MonoArray *p_array) {
return ret;
int length = mono_array_length(p_array);
ret.resize(length);
+ PoolColorArray::Write w = ret.write();
for (int i = 0; i < length; i++) {
- real_t *raw_elem = (real_t *)mono_array_addr_with_size(p_array, sizeof(real_t) * 4, i);
- MARSHALLED_IN(Color, raw_elem, elem);
- ret.set(i, elem);
+ w[i] = MARSHALLED_IN(Color, (M_Color *)mono_array_addr_with_size(p_array, sizeof(M_Color), i));
}
return ret;
}
MonoArray *PoolVector2Array_to_mono_array(const PoolVector2Array &p_array) {
+ PoolVector2Array::Read r = p_array.read();
+
MonoArray *ret = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(Vector2), p_array.size());
for (int i = 0; i < p_array.size(); i++) {
-#ifdef YOLOCOPY
- mono_array_set(ret, Vector2, i, p_array[i]);
-#else
- real_t *raw = (real_t *)mono_array_addr_with_size(ret, sizeof(real_t) * 2, i);
- const Vector2 &elem = p_array[i];
- raw[0] = elem.x;
- raw[1] = elem.y;
-#endif
+ M_Vector2 *raw = (M_Vector2 *)mono_array_addr_with_size(ret, sizeof(M_Vector2), i);
+ *raw = MARSHALLED_OUT(Vector2, r[i]);
}
return ret;
@@ -868,29 +944,23 @@ PoolVector2Array mono_array_to_PoolVector2Array(MonoArray *p_array) {
return ret;
int length = mono_array_length(p_array);
ret.resize(length);
+ PoolVector2Array::Write w = ret.write();
for (int i = 0; i < length; i++) {
- real_t *raw_elem = (real_t *)mono_array_addr_with_size(p_array, sizeof(real_t) * 2, i);
- MARSHALLED_IN(Vector2, raw_elem, elem);
- ret.set(i, elem);
+ w[i] = MARSHALLED_IN(Vector2, (M_Vector2 *)mono_array_addr_with_size(p_array, sizeof(M_Vector2), i));
}
return ret;
}
MonoArray *PoolVector3Array_to_mono_array(const PoolVector3Array &p_array) {
+ PoolVector3Array::Read r = p_array.read();
+
MonoArray *ret = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(Vector3), p_array.size());
for (int i = 0; i < p_array.size(); i++) {
-#ifdef YOLOCOPY
- mono_array_set(ret, Vector3, i, p_array[i]);
-#else
- real_t *raw = (real_t *)mono_array_addr_with_size(ret, sizeof(real_t) * 3, i);
- const Vector3 &elem = p_array[i];
- raw[0] = elem.x;
- raw[1] = elem.y;
- raw[2] = elem.z;
-#endif
+ M_Vector3 *raw = (M_Vector3 *)mono_array_addr_with_size(ret, sizeof(M_Vector3), i);
+ *raw = MARSHALLED_OUT(Vector3, r[i]);
}
return ret;
@@ -902,11 +972,10 @@ PoolVector3Array mono_array_to_PoolVector3Array(MonoArray *p_array) {
return ret;
int length = mono_array_length(p_array);
ret.resize(length);
+ PoolVector3Array::Write w = ret.write();
for (int i = 0; i < length; i++) {
- real_t *raw_elem = (real_t *)mono_array_addr_with_size(p_array, sizeof(real_t) * 3, i);
- MARSHALLED_IN(Vector3, raw_elem, elem);
- ret.set(i, elem);
+ w[i] = MARSHALLED_IN(Vector3, (M_Vector3 *)mono_array_addr_with_size(p_array, sizeof(M_Vector3), i));
}
return ret;
diff --git a/modules/mono/mono_gd/gd_mono_marshal.h b/modules/mono/mono_gd/gd_mono_marshal.h
index cc0ab5fa05..4002f2a225 100644
--- a/modules/mono/mono_gd/gd_mono_marshal.h
+++ b/modules/mono/mono_gd/gd_mono_marshal.h
@@ -147,78 +147,271 @@ PoolVector2Array mono_array_to_PoolVector2Array(MonoArray *p_array);
MonoArray *PoolVector3Array_to_mono_array(const PoolVector3Array &p_array);
PoolVector3Array mono_array_to_PoolVector3Array(MonoArray *p_array);
-#ifdef YOLO_COPY
-#define MARSHALLED_OUT(m_t, m_in, m_out) m_t *m_out = (m_t *)&m_in;
-#define MARSHALLED_IN(m_t, m_in, m_out) m_t m_out = *reinterpret_cast<m_t *>(m_in);
+// Structures
+
+namespace InteropLayout {
+
+enum {
+ MATCHES_float = (sizeof(float) == sizeof(uint32_t)),
+
+ MATCHES_double = (sizeof(double) == sizeof(uint64_t)),
+
+#ifdef REAL_T_IS_DOUBLE
+ MATCHES_real_t = (sizeof(real_t) == sizeof(uint64_t)),
#else
+ MATCHES_real_t = (sizeof(real_t) == sizeof(uint32_t)),
+#endif
-// Expects m_in to be of type float*
+ MATCHES_Vector2 = (MATCHES_real_t && (sizeof(Vector2) == (sizeof(real_t) * 2)) &&
+ offsetof(Vector2, x) == (sizeof(real_t) * 0) &&
+ offsetof(Vector2, y) == (sizeof(real_t) * 1)),
-#define MARSHALLED_OUT(m_t, m_in, m_out) MARSHALLED_OUT_##m_t(m_in, m_out)
-#define MARSHALLED_IN(m_t, m_in, m_out) MARSHALLED_IN_##m_t(m_in, m_out)
+ MATCHES_Rect2 = (MATCHES_Vector2 && (sizeof(Rect2) == (sizeof(Vector2) * 2)) &&
+ offsetof(Rect2, position) == (sizeof(Vector2) * 0) &&
+ offsetof(Rect2, size) == (sizeof(Vector2) * 1)),
-// Vector2
+ MATCHES_Transform2D = (MATCHES_Vector2 && (sizeof(Transform2D) == (sizeof(Vector2) * 3))), // No field offset required, it stores an array
-#define MARSHALLED_OUT_Vector2(m_in, m_out) real_t m_out[2] = { m_in.x, m_in.y };
-#define MARSHALLED_IN_Vector2(m_in, m_out) Vector2 m_out(m_in[0], m_in[1]);
+ MATCHES_Vector3 = (MATCHES_real_t && (sizeof(Vector3) == (sizeof(real_t) * 3)) &&
+ offsetof(Vector3, x) == (sizeof(real_t) * 0) &&
+ offsetof(Vector3, y) == (sizeof(real_t) * 1) &&
+ offsetof(Vector3, z) == (sizeof(real_t) * 2)),
-// Rect2
+ MATCHES_Basis = (MATCHES_Vector3 && (sizeof(Basis) == (sizeof(Vector3) * 3))), // No field offset required, it stores an array
-#define MARSHALLED_OUT_Rect2(m_in, m_out) real_t m_out[4] = { m_in.position.x, m_in.position.y, m_in.size.width, m_in.size.height };
-#define MARSHALLED_IN_Rect2(m_in, m_out) Rect2 m_out(m_in[0], m_in[1], m_in[2], m_in[3]);
+ MATCHES_Quat = (MATCHES_real_t && (sizeof(Quat) == (sizeof(real_t) * 4)) &&
+ offsetof(Quat, x) == (sizeof(real_t) * 0) &&
+ offsetof(Quat, y) == (sizeof(real_t) * 1) &&
+ offsetof(Quat, z) == (sizeof(real_t) * 2) &&
+ offsetof(Quat, w) == (sizeof(real_t) * 3)),
-// Transform2D
+ MATCHES_Transform = (MATCHES_Basis && MATCHES_Vector3 && (sizeof(Transform) == (sizeof(Basis) + sizeof(Vector3))) &&
+ offsetof(Transform, basis) == 0 &&
+ offsetof(Transform, origin) == sizeof(Basis)),
-#define MARSHALLED_OUT_Transform2D(m_in, m_out) real_t m_out[6] = { m_in[0].x, m_in[0].y, m_in[1].x, m_in[1].y, m_in[2].x, m_in[2].y };
-#define MARSHALLED_IN_Transform2D(m_in, m_out) Transform2D m_out(m_in[0], m_in[1], m_in[2], m_in[3], m_in[4], m_in[5]);
+ MATCHES_AABB = (MATCHES_Vector3 && (sizeof(AABB) == (sizeof(Vector3) * 2)) &&
+ offsetof(AABB, position) == (sizeof(Vector3) * 0) &&
+ offsetof(AABB, size) == (sizeof(Vector3) * 1)),
-// Vector3
+ MATCHES_Color = (MATCHES_float && (sizeof(Color) == (sizeof(float) * 4)) &&
+ offsetof(Color, r) == (sizeof(float) * 0) &&
+ offsetof(Color, g) == (sizeof(float) * 1) &&
+ offsetof(Color, b) == (sizeof(float) * 2) &&
+ offsetof(Color, a) == (sizeof(float) * 3)),
+
+ MATCHES_Plane = (MATCHES_Vector3 && MATCHES_real_t && (sizeof(Plane) == (sizeof(Vector3) + sizeof(real_t))) &&
+ offsetof(Plane, normal) == 0 &&
+ offsetof(Plane, d) == sizeof(Vector3))
+};
+
+// In the future we may force this if we want to ref return these structs
+#ifdef GD_MONO_FORCE_INTEROP_STRUCT_COPY
+// Sometimes clang-format can be an ass
+GD_STATIC_ASSERT(MATCHES_Vector2 &&MATCHES_Rect2 &&MATCHES_Transform2D &&MATCHES_Vector3 &&
+ MATCHES_Basis &&MATCHES_Quat &&MATCHES_Transform &&MATCHES_AABB &&MATCHES_Color &&MATCHES_Plane);
+#endif
-#define MARSHALLED_OUT_Vector3(m_in, m_out) real_t m_out[3] = { m_in.x, m_in.y, m_in.z };
-#define MARSHALLED_IN_Vector3(m_in, m_out) Vector3 m_out(m_in[0], m_in[1], m_in[2]);
+} // namespace InteropLayout
-// Basis
+#pragma pack(push, 1)
-#define MARSHALLED_OUT_Basis(m_in, m_out) real_t m_out[9] = { \
- m_in[0].x, m_in[0].y, m_in[0].z, \
- m_in[1].x, m_in[1].y, m_in[1].z, \
- m_in[2].x, m_in[2].y, m_in[2].z \
+struct M_Vector2 {
+ real_t x, y;
+
+ static _FORCE_INLINE_ Vector2 convert_to(const M_Vector2 &p_from) {
+ return Vector2(p_from.x, p_from.y);
+ }
+
+ static _FORCE_INLINE_ M_Vector2 convert_from(const Vector2 &p_from) {
+ M_Vector2 ret = { p_from.x, p_from.y };
+ return ret;
+ }
};
-#define MARSHALLED_IN_Basis(m_in, m_out) Basis m_out(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]);
-// Quat
+struct M_Rect2 {
+ M_Vector2 position;
+ M_Vector2 size;
-#define MARSHALLED_OUT_Quat(m_in, m_out) real_t m_out[4] = { m_in.x, m_in.y, m_in.z, m_in.w };
-#define MARSHALLED_IN_Quat(m_in, m_out) Quat m_out(m_in[0], m_in[1], m_in[2], m_in[3]);
+ static _FORCE_INLINE_ Rect2 convert_to(const M_Rect2 &p_from) {
+ return Rect2(M_Vector2::convert_to(p_from.position),
+ M_Vector2::convert_to(p_from.size));
+ }
-// Transform
+ static _FORCE_INLINE_ M_Rect2 convert_from(const Rect2 &p_from) {
+ M_Rect2 ret = { M_Vector2::convert_from(p_from.position), M_Vector2::convert_from(p_from.size) };
+ return ret;
+ }
+};
-#define MARSHALLED_OUT_Transform(m_in, m_out) real_t m_out[12] = { \
- m_in.basis[0].x, m_in.basis[0].y, m_in.basis[0].z, \
- m_in.basis[1].x, m_in.basis[1].y, m_in.basis[1].z, \
- m_in.basis[2].x, m_in.basis[2].y, m_in.basis[2].z, \
- m_in.origin.x, m_in.origin.y, m_in.origin.z \
+struct M_Transform2D {
+ M_Vector2 elements[3];
+
+ static _FORCE_INLINE_ Transform2D convert_to(const M_Transform2D &p_from) {
+ return Transform2D(p_from.elements[0].x, p_from.elements[0].y,
+ p_from.elements[1].x, p_from.elements[1].y,
+ p_from.elements[2].x, p_from.elements[2].y);
+ }
+
+ static _FORCE_INLINE_ M_Transform2D convert_from(const Transform2D &p_from) {
+ M_Transform2D ret = {
+ M_Vector2::convert_from(p_from.elements[0]),
+ M_Vector2::convert_from(p_from.elements[1]),
+ M_Vector2::convert_from(p_from.elements[2])
+ };
+ return ret;
+ }
};
-#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]), \
- Vector3(m_in[9], m_in[10], m_in[11]));
-// AABB
+struct M_Vector3 {
+ real_t x, y, z;
+
+ static _FORCE_INLINE_ Vector3 convert_to(const M_Vector3 &p_from) {
+ return Vector3(p_from.x, p_from.y, p_from.z);
+ }
-#define MARSHALLED_OUT_AABB(m_in, m_out) real_t m_out[6] = { m_in.position.x, m_in.position.y, m_in.position.z, m_in.size.x, m_in.size.y, m_in.size.z };
-#define MARSHALLED_IN_AABB(m_in, m_out) AABB m_out(Vector3(m_in[0], m_in[1], m_in[2]), Vector3(m_in[3], m_in[4], m_in[5]));
+ static _FORCE_INLINE_ M_Vector3 convert_from(const Vector3 &p_from) {
+ M_Vector3 ret = { p_from.x, p_from.y, p_from.z };
+ return ret;
+ }
+};
-// Color
+struct M_Basis {
+ M_Vector3 elements[3];
+
+ static _FORCE_INLINE_ Basis convert_to(const M_Basis &p_from) {
+ return Basis(M_Vector3::convert_to(p_from.elements[0]),
+ M_Vector3::convert_to(p_from.elements[1]),
+ M_Vector3::convert_to(p_from.elements[2]));
+ }
+
+ static _FORCE_INLINE_ M_Basis convert_from(const Basis &p_from) {
+ M_Basis ret = {
+ M_Vector3::convert_from(p_from.elements[0]),
+ M_Vector3::convert_from(p_from.elements[1]),
+ M_Vector3::convert_from(p_from.elements[2])
+ };
+ return ret;
+ }
+};
-#define MARSHALLED_OUT_Color(m_in, m_out) real_t m_out[4] = { m_in.r, m_in.g, m_in.b, m_in.a };
-#define MARSHALLED_IN_Color(m_in, m_out) Color m_out(m_in[0], m_in[1], m_in[2], m_in[3]);
+struct M_Quat {
+ real_t x, y, z, w;
-// Plane
+ static _FORCE_INLINE_ Quat convert_to(const M_Quat &p_from) {
+ return Quat(p_from.x, p_from.y, p_from.z, p_from.w);
+ }
-#define MARSHALLED_OUT_Plane(m_in, m_out) real_t m_out[4] = { m_in.normal.x, m_in.normal.y, m_in.normal.z, m_in.d };
-#define MARSHALLED_IN_Plane(m_in, m_out) Plane m_out(m_in[0], m_in[1], m_in[2], m_in[3]);
+ static _FORCE_INLINE_ M_Quat convert_from(const Quat &p_from) {
+ M_Quat ret = { p_from.x, p_from.y, p_from.z, p_from.w };
+ return ret;
+ }
+};
-#endif
+struct M_Transform {
+ M_Basis basis;
+ M_Vector3 origin;
+
+ static _FORCE_INLINE_ Transform convert_to(const M_Transform &p_from) {
+ return Transform(M_Basis::convert_to(p_from.basis), M_Vector3::convert_to(p_from.origin));
+ }
+
+ static _FORCE_INLINE_ M_Transform convert_from(const Transform &p_from) {
+ M_Transform ret = { M_Basis::convert_from(p_from.basis), M_Vector3::convert_from(p_from.origin) };
+ return ret;
+ }
+};
+
+struct M_AABB {
+ M_Vector3 position;
+ M_Vector3 size;
+
+ static _FORCE_INLINE_ AABB convert_to(const M_AABB &p_from) {
+ return AABB(M_Vector3::convert_to(p_from.position), M_Vector3::convert_to(p_from.size));
+ }
+
+ static _FORCE_INLINE_ M_AABB convert_from(const AABB &p_from) {
+ M_AABB ret = { M_Vector3::convert_from(p_from.position), M_Vector3::convert_from(p_from.size) };
+ return ret;
+ }
+};
+
+struct M_Color {
+ float r, g, b, a;
+
+ static _FORCE_INLINE_ Color convert_to(const M_Color &p_from) {
+ return Color(p_from.r, p_from.g, p_from.b, p_from.a);
+ }
+
+ static _FORCE_INLINE_ M_Color convert_from(const Color &p_from) {
+ M_Color ret = { p_from.r, p_from.g, p_from.b, p_from.a };
+ return ret;
+ }
+};
+
+struct M_Plane {
+ M_Vector3 normal;
+ real_t d;
+
+ static _FORCE_INLINE_ Plane convert_to(const M_Plane &p_from) {
+ return Plane(M_Vector3::convert_to(p_from.normal), p_from.d);
+ }
+
+ static _FORCE_INLINE_ M_Plane convert_from(const Plane &p_from) {
+ M_Plane ret = { M_Vector3::convert_from(p_from.normal), p_from.d };
+ return ret;
+ }
+};
+
+#pragma pack(pop)
+
+#define DECL_TYPE_MARSHAL_TEMPLATES(m_type) \
+ template <int> \
+ _FORCE_INLINE_ m_type marshalled_in_##m_type##_impl(const M_##m_type *p_from); \
+ \
+ template <> \
+ _FORCE_INLINE_ m_type marshalled_in_##m_type##_impl<0>(const M_##m_type *p_from) { \
+ return M_##m_type::convert_to(*p_from); \
+ } \
+ \
+ template <> \
+ _FORCE_INLINE_ m_type marshalled_in_##m_type##_impl<1>(const M_##m_type *p_from) { \
+ return *reinterpret_cast<const m_type *>(p_from); \
+ } \
+ \
+ _FORCE_INLINE_ m_type marshalled_in_##m_type(const M_##m_type *p_from) { \
+ return marshalled_in_##m_type##_impl<InteropLayout::MATCHES_##m_type>(p_from); \
+ } \
+ \
+ template <int> \
+ _FORCE_INLINE_ M_##m_type marshalled_out_##m_type##_impl(const m_type &p_from); \
+ \
+ template <> \
+ _FORCE_INLINE_ M_##m_type marshalled_out_##m_type##_impl<0>(const m_type &p_from) { \
+ return M_##m_type::convert_from(p_from); \
+ } \
+ \
+ template <> \
+ _FORCE_INLINE_ M_##m_type marshalled_out_##m_type##_impl<1>(const m_type &p_from) { \
+ return *reinterpret_cast<const M_##m_type *>(&p_from); \
+ } \
+ \
+ _FORCE_INLINE_ M_##m_type marshalled_out_##m_type(const m_type &p_from) { \
+ return marshalled_out_##m_type##_impl<InteropLayout::MATCHES_##m_type>(p_from); \
+ }
+
+DECL_TYPE_MARSHAL_TEMPLATES(Vector2)
+DECL_TYPE_MARSHAL_TEMPLATES(Rect2)
+DECL_TYPE_MARSHAL_TEMPLATES(Transform2D)
+DECL_TYPE_MARSHAL_TEMPLATES(Vector3)
+DECL_TYPE_MARSHAL_TEMPLATES(Basis)
+DECL_TYPE_MARSHAL_TEMPLATES(Quat)
+DECL_TYPE_MARSHAL_TEMPLATES(Transform)
+DECL_TYPE_MARSHAL_TEMPLATES(AABB)
+DECL_TYPE_MARSHAL_TEMPLATES(Color)
+DECL_TYPE_MARSHAL_TEMPLATES(Plane)
+
+#define MARSHALLED_IN(m_type, m_from_ptr) (GDMonoMarshal::marshalled_in_##m_type(m_from_ptr))
+#define MARSHALLED_OUT(m_type, m_from) (GDMonoMarshal::marshalled_out_##m_type(m_from))
} // namespace GDMonoMarshal
diff --git a/modules/mono/utils/macros.h b/modules/mono/utils/macros.h
index 337a86870e..40b47e8648 100644
--- a/modules/mono/utils/macros.h
+++ b/modules/mono/utils/macros.h
@@ -33,6 +33,15 @@
// noreturn
+#if __cpp_static_assert
+#define GD_STATIC_ASSERT(m_cond) static_assert((m_cond), "Condition '" #m_cond "' failed")
+#else
+#define _GD_STATIC_ASSERT_VARNAME_CONCAT_B(m_ignore, m_name) m_name
+#define _GD_STATIC_ASSERT_VARNAME_CONCAT_A(m_a, m_b) GD_STATIC_ASSERT_VARNAME_CONCAT_B(hello there, m_a##m_b)
+#define _GD_STATIC_ASSERT_VARNAME_CONCAT(m_a, m_b) GD_STATIC_ASSERT_VARNAME_CONCAT_A(m_a, m_b)
+#define GD_STATIC_ASSERT(m_cond) typedef int GD_STATIC_ASSERT_VARNAME_CONCAT(godot_static_assert_, __COUNTER__)[((m_cond) ? 1 : -1)]
+#endif
+
#undef _NO_RETURN_
#ifdef __GNUC__
diff --git a/modules/opensimplex/doc_classes/NoiseTexture.xml b/modules/opensimplex/doc_classes/NoiseTexture.xml
index 9642865c43..d88abb3180 100644
--- a/modules/opensimplex/doc_classes/NoiseTexture.xml
+++ b/modules/opensimplex/doc_classes/NoiseTexture.xml
@@ -12,24 +12,6 @@
<demos>
</demos>
<methods>
- <method name="set_height">
- <return type="void">
- </return>
- <argument index="0" name="height" type="int">
- </argument>
- <description>
- Set texture height.
- </description>
- </method>
- <method name="set_width">
- <return type="void">
- </return>
- <argument index="0" name="width" type="int">
- </argument>
- <description>
- Set texture width.
- </description>
- </method>
</methods>
<members>
<member name="as_normalmap" type="bool" setter="set_as_normalmap" getter="is_normalmap">
diff --git a/modules/thekla_unwrap/config.py b/modules/thekla_unwrap/config.py
index bd092bdc16..fad6095064 100644
--- a/modules/thekla_unwrap/config.py
+++ b/modules/thekla_unwrap/config.py
@@ -1,5 +1,6 @@
def can_build(env, platform):
- return (env['tools'] and platform not in ["android", "ios"])
+ #return (env['tools'] and platform not in ["android", "ios"])
+ return False
def configure(env):
pass
diff --git a/modules/theora/video_stream_theora.cpp b/modules/theora/video_stream_theora.cpp
index d72d74cf79..2a6bb0783b 100644
--- a/modules/theora/video_stream_theora.cpp
+++ b/modules/theora/video_stream_theora.cpp
@@ -730,7 +730,6 @@ RES ResourceFormatLoaderTheora::load(const String &p_path, const String &p_origi
if (r_error) {
*r_error = ERR_CANT_OPEN;
}
- memdelete(f);
return RES();
}
diff --git a/modules/visual_script/visual_script.cpp b/modules/visual_script/visual_script.cpp
index 12c62c2edb..186e9e63b1 100644
--- a/modules/visual_script/visual_script.cpp
+++ b/modules/visual_script/visual_script.cpp
@@ -48,20 +48,22 @@ bool VisualScriptNode::is_breakpoint() const {
void VisualScriptNode::_notification(int p_what) {
if (p_what == NOTIFICATION_POSTINITIALIZE) {
-
- int dvc = get_input_value_port_count();
- for (int i = 0; i < dvc; i++) {
- Variant::Type expected = get_input_value_port_info(i).type;
- Variant::CallError ce;
- default_input_values.push_back(Variant::construct(expected, NULL, 0, ce, false));
- }
+ _update_input_ports();
}
}
-void VisualScriptNode::ports_changed_notify() {
-
+void VisualScriptNode::_update_input_ports() {
default_input_values.resize(MAX(default_input_values.size(), get_input_value_port_count())); //let it grow as big as possible, we don't want to lose values on resize
+ int port_count = get_input_value_port_count();
+ for (int i = 0; i < port_count; i++) {
+ Variant::Type expected = get_input_value_port_info(i).type;
+ Variant::CallError ce;
+ set_default_input_value(i, Variant::construct(expected, NULL, 0, ce, false));
+ }
+}
+void VisualScriptNode::ports_changed_notify() {
+ _update_input_ports();
emit_signal("ports_changed");
}
diff --git a/modules/visual_script/visual_script.h b/modules/visual_script/visual_script.h
index ea99ce4970..bd666447a3 100644
--- a/modules/visual_script/visual_script.h
+++ b/modules/visual_script/visual_script.h
@@ -52,6 +52,7 @@ class VisualScriptNode : public Resource {
Array _get_default_input_values() const;
void validate_input_default_values();
+ void _update_input_ports();
protected:
void _notification(int p_what);
diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp
index 79f71535ad..7fdd7fe446 100644
--- a/modules/visual_script/visual_script_editor.cpp
+++ b/modules/visual_script/visual_script_editor.cpp
@@ -1940,7 +1940,7 @@ void VisualScriptEditor::_draw_color_over_button(Object *obj, Color p_color) {
button->draw_rect(Rect2(normal->get_offset(), button->get_size() - normal->get_minimum_size()), p_color);
}
-void VisualScriptEditor::_button_resource_previewed(const String &p_path, const Ref<Texture> &p_preview, Variant p_ud) {
+void VisualScriptEditor::_button_resource_previewed(const String &p_path, const Ref<Texture> &p_preview, const Ref<Texture> &p_small_preview, Variant p_ud) {
Array ud = p_ud;
ERR_FAIL_COND(ud.size() != 2);
@@ -2639,7 +2639,7 @@ void VisualScriptEditor::_selected_connect_node(const String &p_text, const Stri
}
undo_redo->create_action(TTR("Add Node"));
undo_redo->add_do_method(script.ptr(), "add_node", edited_func, new_id, vnode_new, ofs);
- if (vnode_old.is_valid() && p_connecting == true) {
+ if (vnode_old.is_valid() && p_connecting) {
connect_seq(vnode_old, vnode_new, new_id);
connect_data(vnode_old, vnode_new, new_id);
}
@@ -2806,7 +2806,7 @@ void VisualScriptEditor::_selected_connect_node(const String &p_text, const Stri
}
}
Ref<VisualScriptNode> vnode_old = script->get_node(edited_func, port_action_node);
- if (vnode_old.is_valid() && p_connecting == true) {
+ if (vnode_old.is_valid() && p_connecting) {
connect_seq(vnode_old, vnode, port_action_new_node);
connect_data(vnode_old, vnode, port_action_new_node);
}
@@ -2816,7 +2816,7 @@ void VisualScriptEditor::_selected_connect_node(const String &p_text, const Stri
void VisualScriptEditor::connect_seq(Ref<VisualScriptNode> vnode_old, Ref<VisualScriptNode> vnode_new, int new_id) {
VisualScriptOperator *vnode_operator = Object::cast_to<VisualScriptOperator>(vnode_new.ptr());
- if (vnode_operator != NULL && vnode_operator->has_input_sequence_port() == false) {
+ if (vnode_operator != NULL && !vnode_operator->has_input_sequence_port()) {
return;
}
VisualScriptConstructor *vnode_constructor = Object::cast_to<VisualScriptConstructor>(vnode_new.ptr());
@@ -2826,7 +2826,7 @@ void VisualScriptEditor::connect_seq(Ref<VisualScriptNode> vnode_old, Ref<Visual
if (vnode_old->get_output_sequence_port_count() <= 0) {
return;
}
- if (vnode_new->has_input_sequence_port() == false) {
+ if (!vnode_new->has_input_sequence_port()) {
return;
}
diff --git a/modules/visual_script/visual_script_editor.h b/modules/visual_script/visual_script_editor.h
index fb90e346a4..97c75dae94 100644
--- a/modules/visual_script/visual_script_editor.h
+++ b/modules/visual_script/visual_script_editor.h
@@ -237,7 +237,7 @@ class VisualScriptEditor : public ScriptEditorBase {
void _selected_method(const String &p_method, const String &p_type);
void _draw_color_over_button(Object *obj, Color p_color);
- void _button_resource_previewed(const String &p_path, const Ref<Texture> &p_preview, Variant p_ud);
+ void _button_resource_previewed(const String &p_path, const Ref<Texture> &p_preview, const Ref<Texture> &p_small_preview, Variant p_ud);
VisualScriptNode::TypeGuess _guess_output_type(int p_port_action_node, int p_port_action_output, Set<int> &visited_nodes);
diff --git a/modules/visual_script/visual_script_nodes.cpp b/modules/visual_script/visual_script_nodes.cpp
index 5c880f48d1..99748af8a1 100644
--- a/modules/visual_script/visual_script_nodes.cpp
+++ b/modules/visual_script/visual_script_nodes.cpp
@@ -853,7 +853,7 @@ public:
virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Variant::CallError &r_error, String &r_error_str) {
- if (instance->get_variable(variable, p_outputs[0]) == false) {
+ if (!instance->get_variable(variable, p_outputs[0])) {
r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD;
r_error_str = RTR("VariableGet not found in script: ") + "'" + String(variable) + "'";
return false;
@@ -975,7 +975,7 @@ public:
virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Variant::CallError &r_error, String &r_error_str) {
- if (instance->set_variable(variable, *p_inputs[0]) == false) {
+ if (!instance->set_variable(variable, *p_inputs[0])) {
r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD;
r_error_str = RTR("VariableSet not found in script: ") + "'" + String(variable) + "'";
@@ -3708,18 +3708,18 @@ void register_visual_script_nodes() {
for (List<MethodInfo>::Element *E = constructors.front(); E; E = E->next()) {
if (E->get().arguments.size() > 0) {
-
- String name = "functions/constructors/" + Variant::get_type_name(Variant::Type(i)) + " ( ";
+ String name = "functions/constructors/" + Variant::get_type_name(Variant::Type(i)) + "(";
for (int j = 0; j < E->get().arguments.size(); j++) {
- if (j > 0)
+ if (j > 0) {
name += ", ";
- if (E->get().arguments.size() == 1)
+ }
+ if (E->get().arguments.size() == 1) {
name += Variant::get_type_name(E->get().arguments[j].type);
- else
+ } else {
name += E->get().arguments[j].name;
+ }
}
- name += ") ";
-
+ name += ")";
VisualScriptLanguage::singleton->add_register_func(name, create_constructor_node);
Pair<Variant::Type, MethodInfo> pair;
pair.first = Variant::Type(i);
diff --git a/modules/visual_script/visual_script_property_selector.cpp b/modules/visual_script/visual_script_property_selector.cpp
index cd29df9855..e5d12cb495 100644
--- a/modules/visual_script/visual_script_property_selector.cpp
+++ b/modules/visual_script/visual_script_property_selector.cpp
@@ -149,7 +149,7 @@ void VisualScriptPropertySelector::_update_search() {
Control::get_icon("PoolColorArray", "EditorIcons")
};
- if (!seq_connect && visual_script_generic == false) {
+ if (!seq_connect && !visual_script_generic) {
get_visual_node_names("flow_control/type_cast", Set<String>(), found, root, search_box);
get_visual_node_names("functions/built_in/print", Set<String>(), found, root, search_box);
get_visual_node_names("functions/by_type/" + Variant::get_type_name(type), Set<String>(), found, root, search_box);
@@ -228,7 +228,7 @@ void VisualScriptPropertySelector::_update_search() {
}
}
- if (seq_connect == true && visual_script_generic == false) {
+ if (seq_connect && !visual_script_generic) {
String text = search_box->get_text();
create_visualscript_item(String("VisualScriptCondition"), root, text, String("Condition"));
create_visualscript_item(String("VisualScriptSwitch"), root, text, String("Switch"));
@@ -304,31 +304,36 @@ void VisualScriptPropertySelector::_update_search() {
continue;
MethodInfo mi = E->get();
- String desc = mi.name.capitalize() + " (";
+ String desc_arguments;
+ if (mi.arguments.size() > 0) {
+ desc_arguments = "(";
+ for (int i = 0; i < mi.arguments.size(); i++) {
+
+ if (i > 0) {
+ desc_arguments += ", ";
+ }
+ if (mi.arguments[i].type == Variant::NIL) {
+ desc_arguments += "var";
+ } else if (mi.arguments[i].name.find(":") != -1) {
+ desc_arguments += mi.arguments[i].name.get_slice(":", 1);
+ mi.arguments[i].name = mi.arguments[i].name.get_slice(":", 0);
+ } else {
+ desc_arguments += Variant::get_type_name(mi.arguments[i].type);
+ }
+ }
+ desc_arguments += ")";
+ }
+ String desc_raw = mi.name + desc_arguments;
+ String desc = desc_raw.capitalize().replace("( ", "(");
if (search_box->get_text() != String() &&
name.findn(search_box->get_text()) == -1 &&
- desc.findn(search_box->get_text()) == -1)
+ desc.findn(search_box->get_text()) == -1 &&
+ desc_raw.findn(search_box->get_text()) == -1) {
continue;
-
- TreeItem *item = search_options->create_item(category ? category : root);
-
- for (int i = 0; i < mi.arguments.size(); i++) {
-
- if (i > 0)
- desc += ", ";
-
- if (mi.arguments[i].type == Variant::NIL)
- desc += "var";
- else if (mi.arguments[i].name.find(":") != -1) {
- desc += mi.arguments[i].name.get_slice(":", 1);
- mi.arguments[i].name = mi.arguments[i].name.get_slice(":", 0);
- } else
- desc += Variant::get_type_name(mi.arguments[i].type);
}
- desc += ")";
-
+ TreeItem *item = search_options->create_item(category ? category : root);
item->set_text(0, desc);
item->set_icon(0, get_icon("MemberMethod", "EditorIcons"));
item->set_metadata(0, name);
@@ -392,7 +397,7 @@ void VisualScriptPropertySelector::get_visual_node_names(const String &root_filt
break;
}
}
- if (is_filter == true) {
+ if (is_filter) {
continue;
}
@@ -414,11 +419,16 @@ void VisualScriptPropertySelector::get_visual_node_names(const String &root_filt
String basic_type = Variant::get_type_name(vnode_function_call->get_basic_type());
type_name = basic_type.capitalize() + " ";
}
- VisualScriptBuiltinFunc *vnode_builtin_function_call = Object::cast_to<VisualScriptBuiltinFunc>(*VisualScriptLanguage::singleton->create_node_from_name(E->get()));
- if (vnode_builtin_function_call != NULL) {
- type_name = "Builtin ";
+
+ Vector<String> desc = path[path.size() - 1].replace("(", "( ").replace(")", " )").replace(",", ", ").split(" ");
+ for (size_t i = 0; i < desc.size(); i++) {
+ desc.write[i] = desc[i].capitalize();
+ if (desc[i].ends_with(",")) {
+ desc.write[i] = desc[i].replace(",", ", ");
+ }
}
- item->set_text(0, type_name + path[path.size() - 1].capitalize());
+
+ item->set_text(0, type_name + String("").join(desc));
item->set_icon(0, get_icon("VisualScript", "EditorIcons"));
item->set_selectable(0, true);
item->set_metadata(0, E->get());
diff --git a/modules/webm/video_stream_webm.cpp b/modules/webm/video_stream_webm.cpp
index d9a6ece085..675fc97b55 100644
--- a/modules/webm/video_stream_webm.cpp
+++ b/modules/webm/video_stream_webm.cpp
@@ -453,7 +453,6 @@ RES ResourceFormatLoaderWebm::load(const String &p_path, const String &p_origina
if (r_error) {
*r_error = ERR_CANT_OPEN;
}
- memdelete(f);
return RES();
}
diff --git a/modules/websocket/emws_server.cpp b/modules/websocket/emws_server.cpp
index ad4a758c0f..db02162699 100644
--- a/modules/websocket/emws_server.cpp
+++ b/modules/websocket/emws_server.cpp
@@ -71,6 +71,9 @@ int EMWSServer::get_peer_port(int p_peer_id) const {
void EMWSServer::disconnect_peer(int p_peer_id, int p_code, String p_reason) {
}
+void EMWSServer::poll() {
+}
+
EMWSServer::EMWSServer() {
}
diff --git a/modules/websocket/lws_client.cpp b/modules/websocket/lws_client.cpp
index cd814760e6..d71d091720 100644
--- a/modules/websocket/lws_client.cpp
+++ b/modules/websocket/lws_client.cpp
@@ -76,23 +76,11 @@ Error LWSClient::connect_to_host(String p_host, String p_path, uint16_t p_port,
ERR_FAIL_V(FAILED);
}
- char abuf[1024];
- char hbuf[1024];
- char pbuf[2048];
- String addr_str = (String)addr;
- strncpy(abuf, addr_str.ascii().get_data(), 1024);
- strncpy(hbuf, p_host.utf8().get_data(), 1024);
- strncpy(pbuf, p_path.utf8().get_data(), 2048);
-
i.context = context;
if (p_protocols.size() > 0)
i.protocol = _lws_ref->lws_names;
else
i.protocol = NULL;
- i.address = abuf;
- i.host = hbuf;
- i.path = pbuf;
- i.port = p_port;
if (p_ssl) {
i.ssl_connection = LCCSCF_USE_SSL;
@@ -102,7 +90,16 @@ Error LWSClient::connect_to_host(String p_host, String p_path, uint16_t p_port,
i.ssl_connection = 0;
}
+ // This String needs to survive till we call lws_client_connect_via_info
+ String addr_str = (String)addr;
+
+ i.address = addr_str.ascii().get_data();
+ i.host = p_host.utf8().get_data();
+ i.path = p_path.utf8().get_data();
+ i.port = p_port;
+
lws_client_connect_via_info(&i);
+
return OK;
};
diff --git a/modules/websocket/websocket_multiplayer.cpp b/modules/websocket/websocket_multiplayer.cpp
index b948c439df..873658559a 100644
--- a/modules/websocket/websocket_multiplayer.cpp
+++ b/modules/websocket/websocket_multiplayer.cpp
@@ -313,7 +313,7 @@ void WebSocketMultiplayerPeer::_process_multiplayer(Ref<WebSocketPeer> p_peer, u
} else if (to < 0) {
// All but one, for us if not excluded
- if (_peer_id != -p_peer_id)
+ if (_peer_id != -(int32_t)p_peer_id)
_store_pkt(from, to, in_buffer, data_size);
} else {
diff --git a/modules/xatlas_unwrap/config.py b/modules/xatlas_unwrap/config.py
index 962d33280f..2dda5db7e0 100644
--- a/modules/xatlas_unwrap/config.py
+++ b/modules/xatlas_unwrap/config.py
@@ -1,6 +1,6 @@
def can_build(env, platform):
- return False #xatlas is buggy
- #return (env['tools'] and platform not in ["android", "ios"])
+ #return False #xatlas is buggy
+ return (env['tools'] and platform not in ["android", "ios"])
def configure(env):
pass
diff --git a/modules/xatlas_unwrap/register_types.cpp b/modules/xatlas_unwrap/register_types.cpp
index 9df16aac70..57eea4eda6 100644
--- a/modules/xatlas_unwrap/register_types.cpp
+++ b/modules/xatlas_unwrap/register_types.cpp
@@ -75,8 +75,9 @@ bool xatlas_mesh_lightmap_unwrap_callback(float p_texel_size, const float *p_ver
xatlas::CharterOptions chart_options;
xatlas::PackerOptions pack_options;
+ pack_options.method = xatlas::PackMethod::TexelArea;
pack_options.texelArea = 1.0 / p_texel_size;
- pack_options.quality = 4;
+ pack_options.quality = 3;
xatlas::Atlas *atlas = xatlas::Create();
printf("adding mesh..\n");
@@ -93,7 +94,10 @@ bool xatlas_mesh_lightmap_unwrap_callback(float p_texel_size, const float *p_ver
float w = *r_size_hint_x;
float h = *r_size_hint_y;
- printf("final texsize: %f,%f\n", w, h);
+ if (w == 0 || h == 0) {
+ return false; //could not bake
+ }
+
const xatlas::OutputMesh *const *output_meshes = xatlas::GetOutputMeshes(atlas);
const xatlas::OutputMesh *output = output_meshes[0];
@@ -102,11 +106,17 @@ bool xatlas_mesh_lightmap_unwrap_callback(float p_texel_size, const float *p_ver
*r_uv = (float *)malloc(sizeof(float) * output->vertexCount * 2);
*r_index = (int *)malloc(sizeof(int) * output->indexCount);
+ float max_x = 0;
+ float max_y = 0;
for (int i = 0; i < output->vertexCount; i++) {
(*r_vertex)[i] = output->vertexArray[i].xref;
- (*r_uv)[i * 2 + 0] = output->vertexArray[i].uv[0];
- (*r_uv)[i * 2 + 1] = output->vertexArray[i].uv[1];
+ (*r_uv)[i * 2 + 0] = output->vertexArray[i].uv[0] / w;
+ (*r_uv)[i * 2 + 1] = output->vertexArray[i].uv[1] / h;
+ max_x = MAX(max_x, output->vertexArray[i].uv[0]);
+ max_y = MAX(max_y, output->vertexArray[i].uv[1]);
}
+
+ printf("final texsize: %f,%f - max %f,%f\n", w, h, max_x, max_y);
*r_vertex_count = output->vertexCount;
for (int i = 0; i < output->indexCount; i++) {