diff options
Diffstat (limited to 'modules')
203 files changed, 2971 insertions, 1679 deletions
diff --git a/modules/bmp/image_loader_bmp.h b/modules/bmp/image_loader_bmp.h index 3fa7481287..e0e50859fc 100644 --- a/modules/bmp/image_loader_bmp.h +++ b/modules/bmp/image_loader_bmp.h @@ -31,7 +31,7 @@ #ifndef IMAGE_LOADER_BMP_H #define IMAGE_LOADER_BMP_H -#include "io/image_loader.h" +#include "core/io/image_loader.h" class ImageLoaderBMP : public ImageFormatLoader { protected: diff --git a/modules/bullet/SCsub b/modules/bullet/SCsub index b82eddde1c..2557e8cb1d 100644 --- a/modules/bullet/SCsub +++ b/modules/bullet/SCsub @@ -68,7 +68,7 @@ if env['builtin_bullet']: , "BulletCollision/CollisionShapes/btEmptyShape.cpp" , "BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp" , "BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp" - , "BulletCollision/CollisionShapes/btMiniSDF.cpp" + , "BulletCollision/CollisionShapes/btMiniSDF.cpp" , "BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp" , "BulletCollision/CollisionShapes/btMultiSphereShape.cpp" , "BulletCollision/CollisionShapes/btOptimizedBvh.cpp" diff --git a/modules/bullet/area_bullet.cpp b/modules/bullet/area_bullet.cpp index f1da454e2e..3200b4a214 100644 --- a/modules/bullet/area_bullet.cpp +++ b/modules/bullet/area_bullet.cpp @@ -30,6 +30,7 @@ #include "area_bullet.h" +#include "bullet_physics_server.h" #include "bullet_types_converter.h" #include "bullet_utilities.h" #include "collision_object_bullet.h" @@ -57,6 +58,7 @@ AreaBullet::AreaBullet() : spOv_priority(0) { btGhost = bulletnew(btGhostObject); + btGhost->setCollisionShape(BulletPhysicsServer::get_empty_shape()); 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. @@ -162,7 +164,10 @@ bool AreaBullet::is_monitoring() const { } void AreaBullet::main_shape_resetted() { - btGhost->setCollisionShape(get_main_shape()); + if (get_main_shape()) + btGhost->setCollisionShape(get_main_shape()); + else + btGhost->setCollisionShape(BulletPhysicsServer::get_empty_shape()); } void AreaBullet::reload_body() { diff --git a/modules/bullet/btRayShape.cpp b/modules/bullet/btRayShape.cpp index 8707096038..6cc63d79ce 100644 --- a/modules/bullet/btRayShape.cpp +++ b/modules/bullet/btRayShape.cpp @@ -30,7 +30,7 @@ #include "btRayShape.h" -#include "math/math_funcs.h" +#include "core/math/math_funcs.h" #include <LinearMath/btAabbUtil2.h> diff --git a/modules/bullet/bullet_physics_server.cpp b/modules/bullet/bullet_physics_server.cpp index dbd27a3564..53a38967c3 100644 --- a/modules/bullet/bullet_physics_server.cpp +++ b/modules/bullet/bullet_physics_server.cpp @@ -31,8 +31,8 @@ #include "bullet_physics_server.h" #include "bullet_utilities.h" -#include "class_db.h" #include "cone_twist_joint_bullet.h" +#include "core/class_db.h" #include "core/error_macros.h" #include "core/ustring.h" #include "generic_6dof_joint_bullet.h" diff --git a/modules/bullet/bullet_physics_server.h b/modules/bullet/bullet_physics_server.h index e9c568d605..4c52cace67 100644 --- a/modules/bullet/bullet_physics_server.h +++ b/modules/bullet/bullet_physics_server.h @@ -32,8 +32,8 @@ #define BULLET_PHYSICS_SERVER_H #include "area_bullet.h" +#include "core/rid.h" #include "joint_bullet.h" -#include "rid.h" #include "rigid_body_bullet.h" #include "servers/physics_server.h" #include "shape_bullet.h" @@ -61,7 +61,7 @@ class BulletPhysicsServer : public PhysicsServer { mutable RID_Owner<JointBullet> joint_owner; private: - /// This is used when a collision shape is not active, so the bullet compound shapes index are always sync with godot index + /// This is used as replacement of collision shape inside a compound or main shape static btEmptyShape *emptyShape; public: diff --git a/modules/bullet/collision_object_bullet.h b/modules/bullet/collision_object_bullet.h index d14fdd3301..ea06cecb17 100644 --- a/modules/bullet/collision_object_bullet.h +++ b/modules/bullet/collision_object_bullet.h @@ -31,11 +31,11 @@ #ifndef COLLISION_OBJECT_BULLET_H #define COLLISION_OBJECT_BULLET_H +#include "core/math/transform.h" +#include "core/math/vector3.h" +#include "core/object.h" #include "core/vset.h" -#include "object.h" #include "shape_owner_bullet.h" -#include "transform.h" -#include "vector3.h" #include <LinearMath/btTransform.h> diff --git a/modules/bullet/godot_collision_dispatcher.h b/modules/bullet/godot_collision_dispatcher.h index 2e5a6c2732..1faaa68626 100644 --- a/modules/bullet/godot_collision_dispatcher.h +++ b/modules/bullet/godot_collision_dispatcher.h @@ -31,7 +31,7 @@ #ifndef GODOT_COLLISION_DISPATCHER_H #define GODOT_COLLISION_DISPATCHER_H -#include "int_types.h" +#include "core/int_types.h" #include <btBulletDynamicsCommon.h> diff --git a/modules/bullet/godot_result_callbacks.h b/modules/bullet/godot_result_callbacks.h index 61247e2a7a..8e70b72841 100644 --- a/modules/bullet/godot_result_callbacks.h +++ b/modules/bullet/godot_result_callbacks.h @@ -74,7 +74,10 @@ public: virtual bool needsCollision(btBroadphaseProxy *proxy0) const; virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult &rayResult, bool normalInWorldSpace) { - m_shapeId = rayResult.m_localShapeInfo->m_triangleIndex; // "m_triangleIndex" Is a odd name but contains the compound shape ID + if (rayResult.m_localShapeInfo) + m_shapeId = rayResult.m_localShapeInfo->m_triangleIndex; // "m_triangleIndex" Is a odd name but contains the compound shape ID + else + m_shapeId = 0; return btCollisionWorld::ClosestRayResultCallback::addSingleResult(rayResult, normalInWorldSpace); } }; diff --git a/modules/bullet/register_types.cpp b/modules/bullet/register_types.cpp index a76b0438b4..31e5f6784e 100644 --- a/modules/bullet/register_types.cpp +++ b/modules/bullet/register_types.cpp @@ -31,8 +31,8 @@ #include "register_types.h" #include "bullet_physics_server.h" -#include "class_db.h" -#include "project_settings.h" +#include "core/class_db.h" +#include "core/project_settings.h" /** @author AndreaCatania diff --git a/modules/bullet/rigid_body_bullet.cpp b/modules/bullet/rigid_body_bullet.cpp index 2974d6b3e4..f81cfe84fb 100644 --- a/modules/bullet/rigid_body_bullet.cpp +++ b/modules/bullet/rigid_body_bullet.cpp @@ -279,7 +279,7 @@ RigidBodyBullet::RigidBodyBullet() : // Initial properties const btVector3 localInertia(0, 0, 0); - btRigidBody::btRigidBodyConstructionInfo cInfo(mass, godotMotionState, NULL, localInertia); + btRigidBody::btRigidBodyConstructionInfo cInfo(mass, godotMotionState, BulletPhysicsServer::get_empty_shape(), localInertia); btBody = bulletnew(btRigidBody(cInfo)); setupBulletCollisionObject(btBody); @@ -315,7 +315,11 @@ void RigidBodyBullet::destroy_kinematic_utilities() { } void RigidBodyBullet::main_shape_resetted() { - btBody->setCollisionShape(get_main_shape()); + if (get_main_shape()) + btBody->setCollisionShape(get_main_shape()); + else + btBody->setCollisionShape(BulletPhysicsServer::get_empty_shape()); + set_continuous_collision_detection(is_continuous_collision_detection_enabled()); // Reset } void RigidBodyBullet::reload_body() { @@ -716,15 +720,19 @@ void RigidBodyBullet::set_continuous_collision_detection(bool p_enable) { if (p_enable) { // This threshold enable CCD if the object moves more than // 1 meter in one simulation frame - btBody->setCcdMotionThreshold(1); + btBody->setCcdMotionThreshold(0.1); /// Calculate using the rule writte below the CCD swept sphere radius /// CCD works on an embedded sphere of radius, make sure this radius /// is embedded inside the convex objects, preferably smaller: /// for an object of dimensions 1 meter, try 0.2 - btVector3 center; btScalar radius; - btBody->getCollisionShape()->getBoundingSphere(center, radius); + if (btBody->getCollisionShape()) { + btVector3 center; + btBody->getCollisionShape()->getBoundingSphere(center, radius); + } else { + radius = 0; + } btBody->setCcdSweptSphereRadius(radius * 0.2); } else { btBody->setCcdMotionThreshold(0.); @@ -733,7 +741,7 @@ void RigidBodyBullet::set_continuous_collision_detection(bool p_enable) { } bool RigidBodyBullet::is_continuous_collision_detection_enabled() const { - return 0. != btBody->getCcdMotionThreshold(); + return 0. < btBody->getCcdMotionThreshold(); } void RigidBodyBullet::set_linear_velocity(const Vector3 &p_velocity) { @@ -841,7 +849,7 @@ void RigidBodyBullet::on_exit_area(AreaBullet *p_area) { bool wasTheAreaFound = false; for (int i = 0; i < areaWhereIamCount; ++i) { if (p_area == areasWhereIam[i]) { - // The area was fount, just shift down all elements + // The area was found, just shift down all elements for (int j = i; j < areaWhereIamCount; ++j) { areasWhereIam.write[j] = areasWhereIam[j + 1]; } diff --git a/modules/bullet/shape_bullet.h b/modules/bullet/shape_bullet.h index 638e044e6a..9a1c8f5bfa 100644 --- a/modules/bullet/shape_bullet.h +++ b/modules/bullet/shape_bullet.h @@ -31,8 +31,8 @@ #ifndef SHAPE_BULLET_H #define SHAPE_BULLET_H +#include "core/math/geometry.h" #include "core/variant.h" -#include "geometry.h" #include "rid_bullet.h" #include "servers/physics_server.h" diff --git a/modules/bullet/space_bullet.cpp b/modules/bullet/space_bullet.cpp index 6d00b3d1d8..5b220e1039 100644 --- a/modules/bullet/space_bullet.cpp +++ b/modules/bullet/space_bullet.cpp @@ -34,13 +34,13 @@ #include "bullet_types_converter.h" #include "bullet_utilities.h" #include "constraint_bullet.h" +#include "core/project_settings.h" +#include "core/ustring.h" #include "godot_collision_configuration.h" #include "godot_collision_dispatcher.h" -#include "project_settings.h" #include "rigid_body_bullet.h" #include "servers/physics_server.h" #include "soft_body_bullet.h" -#include "ustring.h" #include <BulletCollision/CollisionDispatch/btCollisionObject.h> #include <BulletCollision/CollisionDispatch/btGhostObject.h> diff --git a/modules/csg/csg.cpp b/modules/csg/csg.cpp index 87c2caec0d..567485c2c7 100644 --- a/modules/csg/csg.cpp +++ b/modules/csg/csg.cpp @@ -29,10 +29,10 @@ /*************************************************************************/ #include "csg.h" -#include "face3.h" -#include "geometry.h" -#include "os/os.h" -#include "sort.h" +#include "core/math/face3.h" +#include "core/math/geometry.h" +#include "core/os/os.h" +#include "core/sort.h" #include "thirdparty/misc/triangulator.h" void CSGBrush::clear() { @@ -292,12 +292,12 @@ void CSGBrushOperation::BuildPoly::_clip_segment(const CSGBrush *p_brush, int p_ for (int j = 0; j < 2; j++) { if (edges[i].points[0] == segment_idx[0] || edges[i].points[1] == segment_idx[1] || edges[i].points[0] == segment_idx[1] || edges[i].points[1] == segment_idx[0]) { - edge_valid = false; //segment has this point, cant check against this + edge_valid = false; //segment has this point, can't check against this break; } } - if (!edge_valid) //already hit a point in this edge, so dont test it + if (!edge_valid) //already hit a point in this edge, so don't test it continue; //see if either points are within the edge isntead of crossing it @@ -573,7 +573,7 @@ void CSGBrushOperation::_collision_callback(const CSGBrush *A, int p_face_a, Map } } - //if we are still here, it means they most likely intersect, so create BuildPolys if they dont existy + //if we are still here, it means they most likely intersect, so create BuildPolys if they don't exist BuildPoly *poly_a = NULL; @@ -896,7 +896,7 @@ void CSGBrushOperation::_merge_poly(MeshMerge &mesh, int p_face_idx, const Build Vector2 to = p_poly.points[to_idx].point; with_outline_vertex = l; - //try agaisnt outline (other points) first + //try against outline (other points) first valid = true; @@ -915,7 +915,7 @@ void CSGBrushOperation::_merge_poly(MeshMerge &mesh, int p_face_idx, const Build if (!valid) continue; - //try agaisnt all holes including self + //try against all holes including self for (int m = 0; m < polys[i].holes.size(); m++) { diff --git a/modules/csg/csg.h b/modules/csg/csg.h index 2e07c23e28..5d6432eca8 100644 --- a/modules/csg/csg.h +++ b/modules/csg/csg.h @@ -31,15 +31,15 @@ #ifndef CSG_H #define CSG_H -#include "aabb.h" -#include "dvector.h" -#include "map.h" -#include "oa_hash_map.h" -#include "plane.h" -#include "rect2.h" +#include "core/dvector.h" +#include "core/map.h" +#include "core/math/aabb.h" +#include "core/math/plane.h" +#include "core/math/rect2.h" +#include "core/math/transform.h" +#include "core/math/vector3.h" +#include "core/oa_hash_map.h" #include "scene/resources/material.h" -#include "transform.h" -#include "vector3.h" struct CSGBrush { diff --git a/modules/cvtt/image_compress_cvtt.cpp b/modules/cvtt/image_compress_cvtt.cpp index af92861352..17af6bff09 100644 --- a/modules/cvtt/image_compress_cvtt.cpp +++ b/modules/cvtt/image_compress_cvtt.cpp @@ -30,9 +30,9 @@ #include "image_compress_cvtt.h" -#include "os/os.h" -#include "os/thread.h" -#include "print_string.h" +#include "core/os/os.h" +#include "core/os/thread.h" +#include "core/print_string.h" #include <ConvectionKernels.h> diff --git a/modules/cvtt/image_compress_cvtt.h b/modules/cvtt/image_compress_cvtt.h index 0e18b247e5..fe912ad3bb 100644 --- a/modules/cvtt/image_compress_cvtt.h +++ b/modules/cvtt/image_compress_cvtt.h @@ -31,7 +31,7 @@ #ifndef IMAGE_COMPRESS_CVTT_H #define IMAGE_COMPRESS_CVTT_H -#include "image.h" +#include "core/image.h" void image_compress_cvtt(Image *p_image, float p_lossy_quality, Image::CompressSource p_source); void image_decompress_cvtt(Image *p_image); diff --git a/modules/dds/texture_loader_dds.cpp b/modules/dds/texture_loader_dds.cpp index 3cb24d0407..ff15aaa735 100644 --- a/modules/dds/texture_loader_dds.cpp +++ b/modules/dds/texture_loader_dds.cpp @@ -29,7 +29,7 @@ /*************************************************************************/ #include "texture_loader_dds.h" -#include "os/file_access.h" +#include "core/os/file_access.h" enum { DDS_MAGIC = 0x20534444, diff --git a/modules/dds/texture_loader_dds.h b/modules/dds/texture_loader_dds.h index 14d99ff506..4e2593c744 100644 --- a/modules/dds/texture_loader_dds.h +++ b/modules/dds/texture_loader_dds.h @@ -31,7 +31,7 @@ #ifndef TEXTURE_LOADER_DDS_H #define TEXTURE_LOADER_DDS_H -#include "io/resource_loader.h" +#include "core/io/resource_loader.h" #include "scene/resources/texture.h" class ResourceFormatDDS : public ResourceFormatLoader { diff --git a/modules/enet/doc_classes/NetworkedMultiplayerENet.xml b/modules/enet/doc_classes/NetworkedMultiplayerENet.xml index fab4b05da9..76c551e8d7 100644 --- a/modules/enet/doc_classes/NetworkedMultiplayerENet.xml +++ b/modules/enet/doc_classes/NetworkedMultiplayerENet.xml @@ -36,7 +36,7 @@ <argument index="4" name="client_port" type="int" default="0"> </argument> <description> - Create client that connects to a server at [code]address[/code] using specified [code]port[/code]. The given address needs to be either a fully qualified domain nome (e.g. [code]www.example.com[/code]) or an IP address in IPv4 or IPv6 format (e.g. [code]192.168.1.1[/code]). The [code]port[/code] is the port the server is listening on. The [code]in_bandwidth[/code] and [code]out_bandwidth[/code] parameters can be used to limit the incoming and outgoing bandwidth to the given number of bytes per second. The default of 0 means unlimited bandwidth. Note that ENet will strategically drop packets on specific sides of a connection between peers to ensure the peer's bandwidth is not overwhelmed. The bandwidth parameters also determine the window size of a connection which limits the amount of reliable packets that may be in transit at any given time. Returns [code]OK[/code] if a client was created, [code]ERR_ALREADY_IN_USE[/code] if this NetworkedMultiplayerEnet instance already has an open connection (in which case you need to call [method close_connection] first) or [code]ERR_CANT_CREATE[/code] if the client could not be created. If [code]client_port[/code] is specified, the client will also listen to the given port, this is useful in some NAT traveral technique. + Create client that connects to a server at [code]address[/code] using specified [code]port[/code]. The given address needs to be either a fully qualified domain nome (e.g. [code]www.example.com[/code]) or an IP address in IPv4 or IPv6 format (e.g. [code]192.168.1.1[/code]). The [code]port[/code] is the port the server is listening on. The [code]in_bandwidth[/code] and [code]out_bandwidth[/code] parameters can be used to limit the incoming and outgoing bandwidth to the given number of bytes per second. The default of 0 means unlimited bandwidth. Note that ENet will strategically drop packets on specific sides of a connection between peers to ensure the peer's bandwidth is not overwhelmed. The bandwidth parameters also determine the window size of a connection which limits the amount of reliable packets that may be in transit at any given time. Returns [code]OK[/code] if a client was created, [code]ERR_ALREADY_IN_USE[/code] if this NetworkedMultiplayerEnet instance already has an open connection (in which case you need to call [method close_connection] first) or [code]ERR_CANT_CREATE[/code] if the client could not be created. If [code]client_port[/code] is specified, the client will also listen to the given port, this is useful in some NAT traversal technique. </description> </method> <method name="create_server"> diff --git a/modules/enet/networked_multiplayer_enet.cpp b/modules/enet/networked_multiplayer_enet.cpp index 25b7f2472d..0a1061f92e 100644 --- a/modules/enet/networked_multiplayer_enet.cpp +++ b/modules/enet/networked_multiplayer_enet.cpp @@ -29,9 +29,9 @@ /*************************************************************************/ #include "networked_multiplayer_enet.h" -#include "io/ip.h" -#include "io/marshalls.h" -#include "os/os.h" +#include "core/io/ip.h" +#include "core/io/marshalls.h" +#include "core/os/os.h" void NetworkedMultiplayerENet::set_transfer_mode(TransferMode p_mode) { @@ -100,8 +100,8 @@ Error NetworkedMultiplayerENet::create_server(int p_port, int p_max_clients, int host = enet_host_create(&address /* the address to bind the server host to */, p_max_clients /* allow up to 32 clients and/or outgoing connections */, channel_count /* allow up to channel_count to be used */, - p_in_bandwidth /* limit incoming bandwith if > 0 */, - p_out_bandwidth /* limit outgoing bandwith if > 0 */); + p_in_bandwidth /* limit incoming bandwidth if > 0 */, + p_out_bandwidth /* limit outgoing bandwidth if > 0 */); ERR_FAIL_COND_V(!host, ERR_CANT_CREATE); @@ -144,14 +144,14 @@ Error NetworkedMultiplayerENet::create_client(const String &p_address, int p_por host = enet_host_create(&c_client /* create a client host */, 1 /* only allow 1 outgoing connection */, channel_count /* allow up to channel_count to be used */, - p_in_bandwidth /* limit incoming bandwith if > 0 */, - p_out_bandwidth /* limit outgoing bandwith if > 0 */); + p_in_bandwidth /* limit incoming bandwidth if > 0 */, + p_out_bandwidth /* limit outgoing bandwidth if > 0 */); } else { host = enet_host_create(NULL /* create a client host */, 1 /* only allow 1 outgoing connection */, channel_count /* allow up to channel_count to be used */, - p_in_bandwidth /* limit incoming bandwith if > 0 */, - p_out_bandwidth /* limit outgoing bandwith if > 0 */); + p_in_bandwidth /* limit incoming bandwidth if > 0 */, + p_out_bandwidth /* limit outgoing bandwidth if > 0 */); } ERR_FAIL_COND_V(!host, ERR_CANT_CREATE); diff --git a/modules/enet/networked_multiplayer_enet.h b/modules/enet/networked_multiplayer_enet.h index 705807d429..a2b35f2395 100644 --- a/modules/enet/networked_multiplayer_enet.h +++ b/modules/enet/networked_multiplayer_enet.h @@ -31,8 +31,8 @@ #ifndef NETWORKED_MULTIPLAYER_ENET_H #define NETWORKED_MULTIPLAYER_ENET_H -#include "io/compression.h" -#include "io/networked_multiplayer_peer.h" +#include "core/io/compression.h" +#include "core/io/networked_multiplayer_peer.h" #include <enet/enet.h> diff --git a/modules/enet/register_types.cpp b/modules/enet/register_types.cpp index cabaeb692a..cde70e8d5c 100644 --- a/modules/enet/register_types.cpp +++ b/modules/enet/register_types.cpp @@ -29,7 +29,7 @@ /*************************************************************************/ #include "register_types.h" -#include "error_macros.h" +#include "core/error_macros.h" #include "networked_multiplayer_enet.h" static bool enet_ok = false; diff --git a/modules/etc/image_etc.cpp b/modules/etc/image_etc.cpp index f5c817c816..a534aec11b 100644 --- a/modules/etc/image_etc.cpp +++ b/modules/etc/image_etc.cpp @@ -31,10 +31,10 @@ #include "image_etc.h" #include "Etc.h" #include "EtcFilter.h" -#include "image.h" -#include "os/copymem.h" -#include "os/os.h" -#include "print_string.h" +#include "core/image.h" +#include "core/os/copymem.h" +#include "core/os/os.h" +#include "core/print_string.h" static Image::Format _get_etc2_mode(Image::DetectChannels format) { switch (format) { diff --git a/modules/etc/texture_loader_pkm.cpp b/modules/etc/texture_loader_pkm.cpp index ac89259c9b..3041dde876 100644 --- a/modules/etc/texture_loader_pkm.cpp +++ b/modules/etc/texture_loader_pkm.cpp @@ -30,7 +30,7 @@ #include "texture_loader_pkm.h" -#include "os/file_access.h" +#include "core/os/file_access.h" #include <string.h> struct ETC1Header { diff --git a/modules/etc/texture_loader_pkm.h b/modules/etc/texture_loader_pkm.h index 3c6d9180bd..b5a95767c7 100644 --- a/modules/etc/texture_loader_pkm.h +++ b/modules/etc/texture_loader_pkm.h @@ -31,7 +31,7 @@ #ifndef TEXTURE_LOADER_PKM_H #define TEXTURE_LOADER_PKM_H -#include "io/resource_loader.h" +#include "core/io/resource_loader.h" #include "scene/resources/texture.h" class ResourceFormatPKM : public ResourceFormatLoader { diff --git a/modules/freetype/SCsub b/modules/freetype/SCsub index 301f218361..c86e78ccee 100644 --- a/modules/freetype/SCsub +++ b/modules/freetype/SCsub @@ -62,7 +62,7 @@ if env['builtin_freetype']: env.Append(CCFLAGS=['/FI', '"modules/freetype/uwpdef.h"']) elif env['platform'] == 'javascript': # Forcibly undefine this macro so SIMD is not used in this file, - # since currently unsuported in WASM + # since currently unsupported in WASM sfnt = env.Object(sfnt, CPPFLAGS=['-U__OPTIMIZE__']) thirdparty_sources += [sfnt] diff --git a/modules/gdnative/gdnative.cpp b/modules/gdnative/gdnative.cpp index 0acd6c27d8..ecde73ae1c 100644 --- a/modules/gdnative/gdnative.cpp +++ b/modules/gdnative/gdnative.cpp @@ -30,11 +30,11 @@ #include "gdnative.h" -#include "global_constants.h" -#include "io/file_access_encrypted.h" -#include "os/file_access.h" -#include "os/os.h" -#include "project_settings.h" +#include "core/global_constants.h" +#include "core/io/file_access_encrypted.h" +#include "core/os/file_access.h" +#include "core/os/os.h" +#include "core/project_settings.h" #include "scene/main/scene_tree.h" @@ -390,7 +390,7 @@ bool GDNative::terminate() { if (library->should_load_once()) { Vector<Ref<GDNative> > *gdnatives = &(*GDNativeLibrary::loaded_libraries)[library->get_current_library_path()]; if (gdnatives->size() > 1) { - // there are other GDNative's still using this library, so we actually don't terminte + // there are other GDNative's still using this library, so we actually don't terminate gdnatives->erase(Ref<GDNative>(this)); initialized = false; return true; diff --git a/modules/gdnative/gdnative.h b/modules/gdnative/gdnative.h index 148f85723e..c5364a72ac 100644 --- a/modules/gdnative/gdnative.h +++ b/modules/gdnative/gdnative.h @@ -31,15 +31,15 @@ #ifndef GDNATIVE_H #define GDNATIVE_H -#include "io/resource_loader.h" -#include "io/resource_saver.h" -#include "os/thread_safe.h" -#include "resource.h" +#include "core/io/resource_loader.h" +#include "core/io/resource_saver.h" +#include "core/os/thread_safe.h" +#include "core/resource.h" #include "gdnative/gdnative.h" #include "gdnative_api_struct.gen.h" -#include "io/config_file.h" +#include "core/io/config_file.h" class GDNativeLibraryResourceLoader; class GDNative; diff --git a/modules/gdnative/gdnative/gdnative.cpp b/modules/gdnative/gdnative/gdnative.cpp index 73fca655a8..8f10f116e6 100644 --- a/modules/gdnative/gdnative/gdnative.cpp +++ b/modules/gdnative/gdnative/gdnative.cpp @@ -30,12 +30,12 @@ #include "gdnative/gdnative.h" -#include "class_db.h" -#include "engine.h" -#include "error_macros.h" -#include "global_constants.h" -#include "os/os.h" -#include "variant.h" +#include "core/class_db.h" +#include "core/engine.h" +#include "core/error_macros.h" +#include "core/global_constants.h" +#include "core/os/os.h" +#include "core/variant.h" #include "modules/gdnative/gdnative.h" diff --git a/modules/gdnative/gdnative/pool_arrays.cpp b/modules/gdnative/gdnative/pool_arrays.cpp index 2b6b7a823a..d55d81b5b6 100644 --- a/modules/gdnative/gdnative/pool_arrays.cpp +++ b/modules/gdnative/gdnative/pool_arrays.cpp @@ -30,9 +30,9 @@ #include "gdnative/pool_arrays.h" -#include "array.h" +#include "core/array.h" +#include "core/dvector.h" #include "core/variant.h" -#include "dvector.h" #include "core/color.h" #include "core/math/vector2.h" diff --git a/modules/gdnative/nativescript/api_generator.cpp b/modules/gdnative/nativescript/api_generator.cpp index 70ca8d68b8..0983c12619 100644 --- a/modules/gdnative/nativescript/api_generator.cpp +++ b/modules/gdnative/nativescript/api_generator.cpp @@ -35,8 +35,8 @@ #include "core/class_db.h" #include "core/engine.h" #include "core/global_constants.h" +#include "core/os/file_access.h" #include "core/pair.h" -#include "os/file_access.h" // helper stuff diff --git a/modules/gdnative/nativescript/godot_nativescript.cpp b/modules/gdnative/nativescript/godot_nativescript.cpp index 72606c8340..c39efe126f 100644 --- a/modules/gdnative/nativescript/godot_nativescript.cpp +++ b/modules/gdnative/nativescript/godot_nativescript.cpp @@ -30,12 +30,12 @@ #include "nativescript/godot_nativescript.h" -#include "class_db.h" -#include "error_macros.h" +#include "core/class_db.h" +#include "core/error_macros.h" +#include "core/global_constants.h" +#include "core/project_settings.h" +#include "core/variant.h" #include "gdnative/gdnative.h" -#include "global_constants.h" -#include "project_settings.h" -#include "variant.h" #include "nativescript.h" diff --git a/modules/gdnative/nativescript/nativescript.cpp b/modules/gdnative/nativescript/nativescript.cpp index 3f88fabebd..ea968fb0b1 100644 --- a/modules/gdnative/nativescript/nativescript.cpp +++ b/modules/gdnative/nativescript/nativescript.cpp @@ -33,10 +33,10 @@ #include "gdnative/gdnative.h" #include "core/global_constants.h" +#include "core/io/file_access_encrypted.h" +#include "core/os/file_access.h" +#include "core/os/os.h" #include "core/project_settings.h" -#include "io/file_access_encrypted.h" -#include "os/file_access.h" -#include "os/os.h" #include "scene/main/scene_tree.h" #include "scene/resources/scene_format_text.h" @@ -44,7 +44,7 @@ #include <stdlib.h> #ifndef NO_THREADS -#include "os/thread.h" +#include "core/os/thread.h" #endif #if defined(TOOLS_ENABLED) && defined(DEBUG_METHODS_ENABLED) diff --git a/modules/gdnative/nativescript/nativescript.h b/modules/gdnative/nativescript/nativescript.h index ebfe36fd94..a96fe5c5e3 100644 --- a/modules/gdnative/nativescript/nativescript.h +++ b/modules/gdnative/nativescript/nativescript.h @@ -31,21 +31,21 @@ #ifndef NATIVE_SCRIPT_H #define NATIVE_SCRIPT_H +#include "core/io/resource_loader.h" +#include "core/io/resource_saver.h" +#include "core/oa_hash_map.h" +#include "core/ordered_hash_map.h" +#include "core/os/thread_safe.h" #include "core/resource.h" #include "core/script_language.h" #include "core/self_list.h" -#include "io/resource_loader.h" -#include "io/resource_saver.h" -#include "oa_hash_map.h" -#include "ordered_hash_map.h" -#include "os/thread_safe.h" #include "scene/main/node.h" #include "modules/gdnative/gdnative.h" #include <nativescript/godot_nativescript.h> #ifndef NO_THREADS -#include "os/mutex.h" +#include "core/os/mutex.h" #endif struct NativeScriptDesc { diff --git a/modules/gdnative/nativescript/register_types.cpp b/modules/gdnative/nativescript/register_types.cpp index 9a0e764391..4433c0a638 100644 --- a/modules/gdnative/nativescript/register_types.cpp +++ b/modules/gdnative/nativescript/register_types.cpp @@ -30,8 +30,8 @@ #include "register_types.h" -#include "io/resource_loader.h" -#include "io/resource_saver.h" +#include "core/io/resource_loader.h" +#include "core/io/resource_saver.h" #include "nativescript.h" diff --git a/modules/gdnative/pluginscript/pluginscript_loader.cpp b/modules/gdnative/pluginscript/pluginscript_loader.cpp index acba297fa0..52d5b2b595 100644 --- a/modules/gdnative/pluginscript/pluginscript_loader.cpp +++ b/modules/gdnative/pluginscript/pluginscript_loader.cpp @@ -29,7 +29,7 @@ /*************************************************************************/ // Godot imports -#include "os/file_access.h" +#include "core/os/file_access.h" // Pythonscript imports #include "pluginscript_language.h" #include "pluginscript_loader.h" diff --git a/modules/gdnative/pluginscript/pluginscript_loader.h b/modules/gdnative/pluginscript/pluginscript_loader.h index 9276ea3ef9..5c17bb932e 100644 --- a/modules/gdnative/pluginscript/pluginscript_loader.h +++ b/modules/gdnative/pluginscript/pluginscript_loader.h @@ -32,9 +32,9 @@ #define PYTHONSCRIPT_PY_LOADER_H // Godot imports +#include "core/io/resource_loader.h" +#include "core/io/resource_saver.h" #include "core/script_language.h" -#include "io/resource_loader.h" -#include "io/resource_saver.h" class PluginScriptLanguage; diff --git a/modules/gdnative/pluginscript/register_types.cpp b/modules/gdnative/pluginscript/register_types.cpp index 924abf29df..e677bc9867 100644 --- a/modules/gdnative/pluginscript/register_types.cpp +++ b/modules/gdnative/pluginscript/register_types.cpp @@ -30,11 +30,11 @@ #include "register_types.h" +#include "core/io/resource_loader.h" +#include "core/io/resource_saver.h" +#include "core/os/dir_access.h" +#include "core/os/os.h" #include "core/project_settings.h" -#include "io/resource_loader.h" -#include "io/resource_saver.h" -#include "os/dir_access.h" -#include "os/os.h" #include "scene/main/scene_tree.h" #include "pluginscript_language.h" diff --git a/modules/gdnative/register_types.cpp b/modules/gdnative/register_types.cpp index ae1a218392..48c0fc8aef 100644 --- a/modules/gdnative/register_types.cpp +++ b/modules/gdnative/register_types.cpp @@ -33,8 +33,8 @@ #include "gdnative.h" -#include "io/resource_loader.h" -#include "io/resource_saver.h" +#include "core/io/resource_loader.h" +#include "core/io/resource_saver.h" #include "arvr/register_types.h" #include "nativescript/register_types.h" diff --git a/modules/gdscript/editor/gdscript_highlighter.cpp b/modules/gdscript/editor/gdscript_highlighter.cpp index f2a1a5b50c..a1163b5d8d 100644 --- a/modules/gdscript/editor/gdscript_highlighter.cpp +++ b/modules/gdscript/editor/gdscript_highlighter.cpp @@ -121,8 +121,8 @@ Map<int, TextEdit::HighlighterInfo> GDScriptSyntaxHighlighter::_get_line_syntax_ is_hex_notation = false; } - // check for dot or underscore or 'x' for hex notation in floating point number - if ((str[j] == '.' || str[j] == 'x' || str[j] == '_') && !in_word && prev_is_number && !is_number) { + // check for dot or underscore or 'x' for hex notation in floating point number or 'e' for scientific notation + if ((str[j] == '.' || str[j] == 'x' || str[j] == '_' || str[j] == 'e') && !in_word && prev_is_number && !is_number) { is_number = true; is_symbol = false; is_char = false; diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp index 33d9c011f2..4d5d8cedde 100644 --- a/modules/gdscript/gdscript.cpp +++ b/modules/gdscript/gdscript.cpp @@ -30,13 +30,13 @@ #include "gdscript.h" -#include "engine.h" +#include "core/engine.h" +#include "core/global_constants.h" +#include "core/io/file_access_encrypted.h" +#include "core/os/file_access.h" +#include "core/os/os.h" +#include "core/project_settings.h" #include "gdscript_compiler.h" -#include "global_constants.h" -#include "io/file_access_encrypted.h" -#include "os/file_access.h" -#include "os/os.h" -#include "project_settings.h" /////////////////////////// @@ -1973,14 +1973,14 @@ String GDScriptWarning::get_message() const { } break; case UNSAFE_CAST: { CHECK_SYMBOLS(1); - return "The value is cast to '" + symbols[0] + "' but has an unkown type."; + return "The value is cast to '" + symbols[0] + "' but has an unknown type."; } break; case UNSAFE_CALL_ARGUMENT: { CHECK_SYMBOLS(4); return "The argument '" + symbols[0] + "' of the function '" + symbols[1] + "' requires a the subtype '" + symbols[2] + "' but the supertype '" + symbols[3] + "' was provided"; } break; } - ERR_EXPLAIN("Invalid GDScript waring code: " + get_name_from_code(code)); + ERR_EXPLAIN("Invalid GDScript warning code: " + get_name_from_code(code)); ERR_FAIL_V(String()); #undef CHECK_SYMBOLS @@ -2031,7 +2031,7 @@ GDScriptWarning::Code GDScriptWarning::get_code_from_name(const String &p_name) } } - ERR_EXPLAIN("Invalid GDScript waring name: " + p_name); + ERR_EXPLAIN("Invalid GDScript warning name: " + p_name); ERR_FAIL_V(WARNING_MAX); } @@ -2112,23 +2112,14 @@ RES ResourceFormatLoaderGDScript::load(const String &p_path, const String &p_ori script->set_script_path(p_original_path); // script needs this. script->set_path(p_original_path); Error err = script->load_byte_code(p_path); - - if (err != OK) { - memdelete(script); - ERR_FAIL_COND_V(err != OK, RES()); - } + ERR_FAIL_COND_V(err != OK, RES()); } else { Error err = script->load_source_code(p_path); - - if (err != OK) { - memdelete(script); - ERR_FAIL_COND_V(err != OK, RES()); - } + ERR_FAIL_COND_V(err != OK, RES()); script->set_script_path(p_original_path); // script needs this. script->set_path(p_original_path); - //script->set_name(p_path.get_file()); script->reload(); } diff --git a/modules/gdscript/gdscript.h b/modules/gdscript/gdscript.h index d400230f43..739d18569f 100644 --- a/modules/gdscript/gdscript.h +++ b/modules/gdscript/gdscript.h @@ -31,10 +31,10 @@ #ifndef GDSCRIPT_H #define GDSCRIPT_H +#include "core/io/resource_loader.h" +#include "core/io/resource_saver.h" +#include "core/script_language.h" #include "gdscript_function.h" -#include "io/resource_loader.h" -#include "io/resource_saver.h" -#include "script_language.h" class GDScriptNativeClass : public Reference { @@ -286,7 +286,7 @@ struct GDScriptWarning { FUNCTION_USED_AS_PROPERTY, // Property not found, but there's a function with the same name INTEGER_DIVISION, // Integer divide by integer, decimal part is discarded UNSAFE_PROPERTY_ACCESS, // Property not found in the detected type (but can be in subtypes) - UNSAFE_METHOD_ACCESS, // Fucntion not found in the detected type (but can be in subtypes) + UNSAFE_METHOD_ACCESS, // Function not found in the detected type (but can be in subtypes) UNSAFE_CAST, // Cast used in an unknown type UNSAFE_CALL_ARGUMENT, // Function call argument is of a supertype of the require argument WARNING_MAX, diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp index 006fbece53..741b837b05 100644 --- a/modules/gdscript/gdscript_compiler.cpp +++ b/modules/gdscript/gdscript_compiler.cpp @@ -518,7 +518,7 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: } } - codegen.opcodes.push_back(src_addr); // source adddress + codegen.opcodes.push_back(src_addr); // source address int dst_addr = (p_stack_level) | (GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS); codegen.opcodes.push_back(dst_addr); // append the stack level as destination address of the opcode codegen.alloc_stack(p_stack_level); diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp index d3068fb6d0..affb73a048 100644 --- a/modules/gdscript/gdscript_editor.cpp +++ b/modules/gdscript/gdscript_editor.cpp @@ -31,16 +31,16 @@ #include "gdscript.h" #include "core/engine.h" +#include "core/global_constants.h" +#include "core/os/file_access.h" #include "editor/editor_settings.h" #include "gdscript_compiler.h" -#include "global_constants.h" -#include "os/file_access.h" #ifdef TOOLS_ENABLED +#include "core/engine.h" #include "core/reference.h" #include "editor/editor_file_system.h" #include "editor/editor_settings.h" -#include "engine.h" #endif void GDScriptLanguage::get_comment_delimiters(List<String> *p_delimiters) const { @@ -3304,7 +3304,7 @@ Error GDScriptLanguage::lookup_code(const String &p_code, const String &p_symbol } } else { /* - // Because get_integer_constant_enum and get_integer_constant dont work on @GlobalScope + // Because get_integer_constant_enum and get_integer_constant don't work on @GlobalScope // We cannot determine the exact nature of the identifier here // Otherwise these codes would work StringName enumName = ClassDB::get_integer_constant_enum("@GlobalScope", p_symbol, true); diff --git a/modules/gdscript/gdscript_function.cpp b/modules/gdscript/gdscript_function.cpp index d615b58b24..abd08d13ff 100644 --- a/modules/gdscript/gdscript_function.cpp +++ b/modules/gdscript/gdscript_function.cpp @@ -30,9 +30,9 @@ #include "gdscript_function.h" +#include "core/os/os.h" #include "gdscript.h" #include "gdscript_functions.h" -#include "os/os.h" Variant *GDScriptFunction::_get_variant(int p_address, GDScriptInstance *p_instance, GDScript *p_script, Variant &self, Variant *p_stack, String &r_error) const { diff --git a/modules/gdscript/gdscript_function.h b/modules/gdscript/gdscript_function.h index 633cca35d3..bfb6d673f1 100644 --- a/modules/gdscript/gdscript_function.h +++ b/modules/gdscript/gdscript_function.h @@ -31,13 +31,13 @@ #ifndef GDSCRIPT_FUNCTION_H #define GDSCRIPT_FUNCTION_H -#include "os/thread.h" -#include "pair.h" -#include "reference.h" -#include "script_language.h" -#include "self_list.h" -#include "string_db.h" -#include "variant.h" +#include "core/os/thread.h" +#include "core/pair.h" +#include "core/reference.h" +#include "core/script_language.h" +#include "core/self_list.h" +#include "core/string_db.h" +#include "core/variant.h" class GDScriptInstance; class GDScript; diff --git a/modules/gdscript/gdscript_functions.cpp b/modules/gdscript/gdscript_functions.cpp index 03e7740887..c469defb01 100644 --- a/modules/gdscript/gdscript_functions.cpp +++ b/modules/gdscript/gdscript_functions.cpp @@ -30,15 +30,15 @@ #include "gdscript_functions.h" -#include "class_db.h" -#include "func_ref.h" +#include "core/class_db.h" +#include "core/func_ref.h" +#include "core/io/json.h" +#include "core/io/marshalls.h" +#include "core/math/math_funcs.h" +#include "core/os/os.h" +#include "core/reference.h" +#include "core/variant_parser.h" #include "gdscript.h" -#include "io/json.h" -#include "io/marshalls.h" -#include "math_funcs.h" -#include "os/os.h" -#include "reference.h" -#include "variant_parser.h" const char *GDScriptFunctions::get_func_name(Function p_func) { diff --git a/modules/gdscript/gdscript_functions.h b/modules/gdscript/gdscript_functions.h index a29f06e839..e920dd4ece 100644 --- a/modules/gdscript/gdscript_functions.h +++ b/modules/gdscript/gdscript_functions.h @@ -31,7 +31,7 @@ #ifndef GDSCRIPT_FUNCTIONS_H #define GDSCRIPT_FUNCTIONS_H -#include "variant.h" +#include "core/variant.h" class GDScriptFunctions { public: diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index 7502f09d8a..7243690f94 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -32,14 +32,13 @@ #include "core/core_string_names.h" #include "core/engine.h" +#include "core/io/resource_loader.h" +#include "core/os/file_access.h" +#include "core/print_string.h" #include "core/project_settings.h" #include "core/reference.h" +#include "core/script_language.h" #include "gdscript.h" -#include "io/resource_loader.h" -#include "os/file_access.h" -#include "print_string.h" -#include "project_settings.h" -#include "script_language.h" template <class T> T *GDScriptParser::alloc_node() { @@ -2479,7 +2478,7 @@ void GDScriptParser::_generate_pattern(PatternNode *p_pattern, Node *p_node_to_m Node *condition = NULL; - // chech for has, then for pattern + // check for has, then for pattern IdentifierNode *has = alloc_node<IdentifierNode>(); has->name = "has"; @@ -4536,14 +4535,14 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { member.rpc_mode = rpc_mode; if (current_class->constant_expressions.has(member.identifier)) { - _set_error("A constant named '" + String(member.identifier) + "' alread exists in this class (at line: " + + _set_error("A constant named '" + String(member.identifier) + "' already exists in this class (at line: " + itos(current_class->constant_expressions[member.identifier].expression->line) + ")."); return; } for (int i = 0; i < current_class->variables.size(); i++) { if (current_class->variables[i].identifier == member.identifier) { - _set_error("Variable '" + String(member.identifier) + "' alread exists in this class (at line: " + + _set_error("Variable '" + String(member.identifier) + "' already exists in this class (at line: " + itos(current_class->variables[i].line) + ")."); return; } @@ -4750,14 +4749,14 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { int line = tokenizer->get_token_line(); if (current_class->constant_expressions.has(const_id)) { - _set_error("Constant '" + String(const_id) + "' alread exists in this class (at line: " + + _set_error("Constant '" + String(const_id) + "' already exists in this class (at line: " + itos(current_class->constant_expressions[const_id].expression->line) + ")."); return; } for (int i = 0; i < current_class->variables.size(); i++) { if (current_class->variables[i].identifier == const_id) { - _set_error("A variable named '" + String(const_id) + "' alread exists in this class (at line: " + + _set_error("A variable named '" + String(const_id) + "' already exists in this class (at line: " + itos(current_class->variables[i].line) + ")."); return; } @@ -4811,7 +4810,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { case GDScriptTokenizer::TK_PR_ENUM: { //multiple constant declarations.. - int last_assign = -1; // Incremented by 1 right before the assingment. + int last_assign = -1; // Incremented by 1 right before the assignment. String enum_name; Dictionary enum_dict; @@ -7243,7 +7242,7 @@ void GDScriptParser::_check_class_level_types(ClassNode *p_class) { return; } - // Replace assigment with implict conversion + // Replace assignment with implict conversion BuiltInFunctionNode *convert = alloc_node<BuiltInFunctionNode>(); convert->line = v.line; convert->function = GDScriptFunctions::TYPE_CONVERT; @@ -7621,7 +7620,7 @@ void GDScriptParser::_check_block_types(BlockNode *p_block) { lv->line); return; } - // Replace assigment with implict conversion + // Replace assignment with implict conversion BuiltInFunctionNode *convert = alloc_node<BuiltInFunctionNode>(); convert->line = lv->line; convert->function = GDScriptFunctions::TYPE_CONVERT; @@ -7749,7 +7748,7 @@ void GDScriptParser::_check_block_types(BlockNode *p_block) { op->line); return; } - // Replace assigment with implict conversion + // Replace assignment with implict conversion BuiltInFunctionNode *convert = alloc_node<BuiltInFunctionNode>(); convert->line = op->line; convert->function = GDScriptFunctions::TYPE_CONVERT; diff --git a/modules/gdscript/gdscript_parser.h b/modules/gdscript/gdscript_parser.h index 3c51e3f372..cd68072499 100644 --- a/modules/gdscript/gdscript_parser.h +++ b/modules/gdscript/gdscript_parser.h @@ -31,11 +31,11 @@ #ifndef GDSCRIPT_PARSER_H #define GDSCRIPT_PARSER_H +#include "core/map.h" +#include "core/object.h" +#include "core/script_language.h" #include "gdscript_functions.h" #include "gdscript_tokenizer.h" -#include "map.h" -#include "object.h" -#include "script_language.h" struct GDScriptDataType; struct GDScriptWarning; diff --git a/modules/gdscript/gdscript_tokenizer.cpp b/modules/gdscript/gdscript_tokenizer.cpp index 6e7842f190..941f5dbecc 100644 --- a/modules/gdscript/gdscript_tokenizer.cpp +++ b/modules/gdscript/gdscript_tokenizer.cpp @@ -30,10 +30,10 @@ #include "gdscript_tokenizer.h" +#include "core/io/marshalls.h" +#include "core/map.h" +#include "core/print_string.h" #include "gdscript_functions.h" -#include "io/marshalls.h" -#include "map.h" -#include "print_string.h" const char *GDScriptTokenizer::token_names[TK_MAX] = { "Empty", diff --git a/modules/gdscript/gdscript_tokenizer.h b/modules/gdscript/gdscript_tokenizer.h index 11a291cb2e..01b1ac5bf2 100644 --- a/modules/gdscript/gdscript_tokenizer.h +++ b/modules/gdscript/gdscript_tokenizer.h @@ -32,11 +32,11 @@ #define GDSCRIPT_TOKENIZER_H #include "core/pair.h" +#include "core/string_db.h" +#include "core/ustring.h" +#include "core/variant.h" +#include "core/vmap.h" #include "gdscript_functions.h" -#include "string_db.h" -#include "ustring.h" -#include "variant.h" -#include "vmap.h" class GDScriptTokenizer { public: diff --git a/modules/gdscript/register_types.cpp b/modules/gdscript/register_types.cpp index 422223370b..26dcbdcf89 100644 --- a/modules/gdscript/register_types.cpp +++ b/modules/gdscript/register_types.cpp @@ -30,12 +30,12 @@ #include "register_types.h" +#include "core/io/file_access_encrypted.h" +#include "core/io/resource_loader.h" +#include "core/os/file_access.h" #include "editor/gdscript_highlighter.h" #include "gdscript.h" #include "gdscript_tokenizer.h" -#include "io/file_access_encrypted.h" -#include "io/resource_loader.h" -#include "os/file_access.h" GDScriptLanguage *script_language_gd = NULL; ResourceFormatLoaderGDScript *resource_loader_gd = NULL; diff --git a/modules/gridmap/doc_classes/GridMap.xml b/modules/gridmap/doc_classes/GridMap.xml index 09e8e39796..f13479940d 100644 --- a/modules/gridmap/doc_classes/GridMap.xml +++ b/modules/gridmap/doc_classes/GridMap.xml @@ -65,7 +65,7 @@ <argument index="2" name="z" type="int"> </argument> <description> - The orientation of the cell at the grid-based X, Y and Z coordinates. -1 is retuned if the cell is empty. + The orientation of the cell at the grid-based X, Y and Z coordinates. -1 is returned if the cell is empty. </description> </method> <method name="get_collision_layer_bit" qualifiers="const"> diff --git a/modules/gridmap/grid_map.cpp b/modules/gridmap/grid_map.cpp index 919607c3f6..a480c4183e 100644 --- a/modules/gridmap/grid_map.cpp +++ b/modules/gridmap/grid_map.cpp @@ -29,13 +29,13 @@ /*************************************************************************/ #include "grid_map.h" -#include "message_queue.h" +#include "core/message_queue.h" #include "scene/3d/light.h" #include "scene/resources/surface_tool.h" #include "servers/visual_server.h" -#include "io/marshalls.h" -#include "os/os.h" +#include "core/io/marshalls.h" +#include "core/os/os.h" #include "scene/resources/mesh_library.h" #include "scene/scene_string_names.h" diff --git a/modules/gridmap/grid_map_editor_plugin.cpp b/modules/gridmap/grid_map_editor_plugin.cpp index 90e28129cc..e6eaabd9ce 100644 --- a/modules/gridmap/grid_map_editor_plugin.cpp +++ b/modules/gridmap/grid_map_editor_plugin.cpp @@ -29,14 +29,14 @@ /*************************************************************************/ #include "grid_map_editor_plugin.h" +#include "core/os/input.h" #include "editor/editor_scale.h" #include "editor/editor_settings.h" #include "editor/plugins/spatial_editor_plugin.h" -#include "os/input.h" #include "scene/3d/camera.h" -#include "geometry.h" -#include "os/keyboard.h" +#include "core/math/geometry.h" +#include "core/os/keyboard.h" void GridMapEditor::_node_removed(Node *p_node) { diff --git a/modules/gridmap/register_types.cpp b/modules/gridmap/register_types.cpp index a3ceea10af..030286d651 100644 --- a/modules/gridmap/register_types.cpp +++ b/modules/gridmap/register_types.cpp @@ -30,7 +30,7 @@ #include "register_types.h" #ifndef _3D_DISABLED -#include "class_db.h" +#include "core/class_db.h" #include "grid_map.h" #include "grid_map_editor_plugin.h" #endif diff --git a/modules/hdr/image_loader_hdr.cpp b/modules/hdr/image_loader_hdr.cpp index d592c19b97..fc6779ce86 100644 --- a/modules/hdr/image_loader_hdr.cpp +++ b/modules/hdr/image_loader_hdr.cpp @@ -30,8 +30,8 @@ #include "image_loader_hdr.h" -#include "os/os.h" -#include "print_string.h" +#include "core/os/os.h" +#include "core/print_string.h" #include "thirdparty/tinyexr/tinyexr.h" diff --git a/modules/hdr/image_loader_hdr.h b/modules/hdr/image_loader_hdr.h index 3cce483745..7175b38cc8 100644 --- a/modules/hdr/image_loader_hdr.h +++ b/modules/hdr/image_loader_hdr.h @@ -31,7 +31,7 @@ #ifndef IMAGE_LOADER_HDR_H #define IMAGE_LOADER_HDR_H -#include "io/image_loader.h" +#include "core/io/image_loader.h" /** @author Juan Linietsky <reduzio@gmail.com> diff --git a/modules/jpg/image_loader_jpegd.cpp b/modules/jpg/image_loader_jpegd.cpp index 437c0d57fa..a49137ae73 100644 --- a/modules/jpg/image_loader_jpegd.cpp +++ b/modules/jpg/image_loader_jpegd.cpp @@ -30,8 +30,8 @@ #include "image_loader_jpegd.h" -#include "os/os.h" -#include "print_string.h" +#include "core/os/os.h" +#include "core/print_string.h" #include <jpgd.h> #include <string.h> diff --git a/modules/jpg/image_loader_jpegd.h b/modules/jpg/image_loader_jpegd.h index 3e3ac5217f..b5f0637c9b 100644 --- a/modules/jpg/image_loader_jpegd.h +++ b/modules/jpg/image_loader_jpegd.h @@ -31,7 +31,7 @@ #ifndef IMAGE_LOADER_JPG_H #define IMAGE_LOADER_JPG_H -#include "io/image_loader.h" +#include "core/io/image_loader.h" /** @author Juan Linietsky <reduzio@gmail.com> diff --git a/modules/mbedtls/stream_peer_mbed_tls.cpp b/modules/mbedtls/stream_peer_mbed_tls.cpp index 884c26ddfe..3398957775 100755 --- a/modules/mbedtls/stream_peer_mbed_tls.cpp +++ b/modules/mbedtls/stream_peer_mbed_tls.cpp @@ -29,8 +29,8 @@ /*************************************************************************/ #include "stream_peer_mbed_tls.h" +#include "core/os/file_access.h" #include "mbedtls/platform_util.h" -#include "os/file_access.h" static void my_debug(void *ctx, int level, const char *file, int line, diff --git a/modules/mbedtls/stream_peer_mbed_tls.h b/modules/mbedtls/stream_peer_mbed_tls.h index 7f4e5a4513..0cf893eacf 100755 --- a/modules/mbedtls/stream_peer_mbed_tls.h +++ b/modules/mbedtls/stream_peer_mbed_tls.h @@ -31,7 +31,7 @@ #ifndef STREAM_PEER_OPEN_SSL_H #define STREAM_PEER_OPEN_SSL_H -#include "io/stream_peer_ssl.h" +#include "core/io/stream_peer_ssl.h" #include "mbedtls/config.h" #include "mbedtls/ctr_drbg.h" diff --git a/modules/mono/SCsub b/modules/mono/SCsub index f3cf4c9c5d..b3a2d26e4a 100644 --- a/modules/mono/SCsub +++ b/modules/mono/SCsub @@ -7,21 +7,24 @@ env_mono = env_modules.Clone() # TODO move functions to their own modules -def make_cs_files_header(src, dst): +def make_cs_files_header(src, dst, version_dst): from compat import byte_to_str with open(dst, 'w') as header: - header.write('/* This is an automatically generated file; DO NOT EDIT! OK THX */\n') - header.write('#ifndef _CS_FILES_DATA_H\n') - header.write('#define _CS_FILES_DATA_H\n\n') - header.write('#include "map.h"\n') - header.write('#include "ustring.h"\n') + header.write('/* THIS FILE IS GENERATED DO NOT EDIT */\n') + header.write('#ifndef CS_COMPRESSED_H\n') + header.write('#define CS_COMPRESSED_H\n\n') + header.write('#ifdef TOOLS_ENABLED\n\n') + header.write('#include "core/map.h"\n') + header.write('#include "core/ustring.h"\n') inserted_files = '' import os latest_mtime = 0 + cs_file_count = 0 for root, _, files in os.walk(src): files = [f for f in files if f.endswith('.cs')] for file in files: + cs_file_count += 1 filepath = os.path.join(root, file) filepath_src_rel = os.path.relpath(filepath, src) mtime = os.path.getmtime(filepath) @@ -31,8 +34,10 @@ def make_cs_files_header(src, dst): decomp_size = len(buf) import zlib buf = zlib.compress(buf) - name = os.path.splitext(os.path.normpath(filepath_src_rel))[0].strip(os.sep).replace(os.sep, '_').replace('.', '_dotto_') - header.write('\nstatic const int _cs_' + name + '_compressed_size = ' + str(len(buf)) + ';\n') + name = str(cs_file_count) + header.write('\n') + header.write('// ' + filepath_src_rel + '\n') + header.write('static const int _cs_' + name + '_compressed_size = ' + str(len(buf)) + ';\n') header.write('static const int _cs_' + name + '_uncompressed_size = ' + str(decomp_size) + ';\n') header.write('static const unsigned char _cs_' + name + '_compressed[] = { ') for i, buf_idx in enumerate(range(len(buf))): @@ -44,8 +49,6 @@ def make_cs_files_header(src, dst): '_cs_' + name + '_uncompressed_size, ' \ '_cs_' + name + '_compressed));\n' header.write(' };\n') - glue_version = int(latest_mtime) # The latest modified time will do for now - header.write('\n#define CS_GLUE_VERSION UINT32_C(' + str(glue_version) + ')\n') header.write('\nstruct CompressedFile\n' '{\n' '\tint compressed_size;\n' '\tint uncompressed_size;\n' '\tconst unsigned char* data;\n' '\n\tCompressedFile(int p_comp_size, int p_uncomp_size, const unsigned char* p_data)\n' @@ -53,17 +56,28 @@ def make_cs_files_header(src, dst): '\t\tdata = p_data;\n' '\t}\n' '\n\tCompressedFile() {}\n' '};\n' '\nvoid get_compressed_files(Map<String, CompressedFile>& r_files)\n' '{\n' + inserted_files + '}\n' ) - header.write('#endif // _CS_FILES_DATA_H') + header.write('\n#endif // TOOLS_ENABLED\n') + header.write('\n#endif // CS_COMPRESSED_H\n') + + glue_version = int(latest_mtime) # The latest modified time will do for now + + with open(version_dst, 'w') as version_header: + version_header.write('/* THIS FILE IS GENERATED DO NOT EDIT */\n') + version_header.write('#ifndef CS_GLUE_VERSION_H\n') + version_header.write('#define CS_GLUE_VERSION_H\n\n') + version_header.write('#define CS_GLUE_VERSION UINT32_C(' + str(glue_version) + ')\n') + version_header.write('\n#endif // CS_GLUE_VERSION_H\n') env_mono.add_source_files(env.modules_sources, '*.cpp') +env_mono.add_source_files(env.modules_sources, 'glue/*.cpp') env_mono.add_source_files(env.modules_sources, 'mono_gd/*.cpp') env_mono.add_source_files(env.modules_sources, 'utils/*.cpp') if env['tools']: env_mono.add_source_files(env.modules_sources, 'editor/*.cpp') - # NOTE: It is safe to generate this file here, since this is still execute serially - make_cs_files_header('glue/cs_files', 'glue/cs_compressed.gen.h') + # NOTE: It is safe to generate this file here, since this is still executed serially + make_cs_files_header('glue/Managed/Files', 'glue/cs_compressed.gen.h', 'glue/cs_glue_version.gen.h') vars = Variables() vars.Add(BoolVariable('mono_glue', 'Build with the mono glue sources', True)) @@ -72,9 +86,7 @@ vars.Update(env_mono) # Glue sources if env_mono['mono_glue']: - env_mono.add_source_files(env.modules_sources, 'glue/*.cpp') -else: - env_mono.Append(CPPDEFINES=['MONO_GLUE_DISABLED']) + env_mono.Append(CPPDEFINES=['MONO_GLUE_ENABLED']) if ARGUMENTS.get('yolo_copy', False): env_mono.Append(CPPDEFINES=['YOLO_COPY']) diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp index d2a861dbe8..b9209fce92 100644 --- a/modules/mono/csharp_script.cpp +++ b/modules/mono/csharp_script.cpp @@ -32,10 +32,10 @@ #include <mono/metadata/threads.h> -#include "os/file_access.h" -#include "os/os.h" -#include "os/thread.h" -#include "project_settings.h" +#include "core/os/file_access.h" +#include "core/os/os.h" +#include "core/os/thread.h" +#include "core/project_settings.h" #ifdef TOOLS_ENABLED #include "editor/bindings_generator.h" @@ -107,7 +107,7 @@ void CSharpLanguage::init() { gdmono = memnew(GDMono); gdmono->initialize(); -#ifdef MONO_GLUE_DISABLED +#ifndef MONO_GLUE_ENABLED WARN_PRINT("This binary is built with `mono_glue=no` and cannot be used for scripting"); #endif @@ -138,7 +138,7 @@ void CSharpLanguage::finish() { #endif // Release gchandle bindings before finalizing mono runtime - gchandle_bindings.clear(); + script_bindings.clear(); if (gdmono) { memdelete(gdmono); @@ -551,22 +551,22 @@ Vector<ScriptLanguage::StackInfo> CSharpLanguage::stack_trace_get_info(MonoObjec void CSharpLanguage::frame() { - const Ref<MonoGCHandle> &task_scheduler_handle = GDMonoUtils::mono_cache.task_scheduler_handle; + if (gdmono && gdmono->is_runtime_initialized() && gdmono->get_core_api_assembly() != NULL) { + const Ref<MonoGCHandle> &task_scheduler_handle = GDMonoUtils::mono_cache.task_scheduler_handle; - if (task_scheduler_handle.is_valid()) { - MonoObject *task_scheduler = task_scheduler_handle->get_target(); + if (task_scheduler_handle.is_valid()) { + MonoObject *task_scheduler = task_scheduler_handle->get_target(); - if (task_scheduler) { - GDMonoUtils::GodotTaskScheduler_Activate thunk = CACHED_METHOD_THUNK(GodotTaskScheduler, Activate); + if (task_scheduler) { + GDMonoUtils::GodotTaskScheduler_Activate thunk = CACHED_METHOD_THUNK(GodotTaskScheduler, Activate); - ERR_FAIL_NULL(thunk); + MonoException *exc = NULL; + thunk(task_scheduler, (MonoObject **)&exc); - MonoException *exc = NULL; - thunk(task_scheduler, (MonoObject **)&exc); - - if (exc) { - GDMonoUtils::debug_unhandled_exception(exc); - _UNREACHABLE_(); + if (exc) { + GDMonoUtils::debug_unhandled_exception(exc); + _UNREACHABLE_(); + } } } } @@ -892,6 +892,48 @@ void CSharpLanguage::set_language_index(int p_idx) { lang_idx = p_idx; } +void CSharpLanguage::release_script_gchandle(Ref<MonoGCHandle> &p_gchandle) { + + if (!p_gchandle->is_released()) { // Do not locking unnecessarily +#ifndef NO_THREADS + get_singleton()->script_gchandle_release_lock->lock(); +#endif + + p_gchandle->release(); + +#ifndef NO_THREADS + get_singleton()->script_gchandle_release_lock->unlock(); +#endif + } +} + +void CSharpLanguage::release_script_gchandle(MonoObject *p_pinned_expected_obj, Ref<MonoGCHandle> &p_gchandle) { + + uint32_t pinned_gchandle = MonoGCHandle::new_strong_handle_pinned(p_pinned_expected_obj); // we might lock after this, so pin it + + if (!p_gchandle->is_released()) { // Do not locking unnecessarily +#ifndef NO_THREADS + get_singleton()->script_gchandle_release_lock->lock(); +#endif + + MonoObject *target = p_gchandle->get_target(); + + // We release the gchandle if it points to the MonoObject* we expect (otherwise it was + // already released and could have been replaced) or if we can't get its target MonoObject* + // (which doesn't necessarily mean it was released, and we want it released in order to + // avoid locking other threads unnecessarily). + if (target == p_pinned_expected_obj || target == NULL) { + p_gchandle->release(); + } + +#ifndef NO_THREADS + get_singleton()->script_gchandle_release_lock->unlock(); +#endif + } + + MonoGCHandle::free_handle(pinned_gchandle); +} + CSharpLanguage::CSharpLanguage() { ERR_FAIL_COND(singleton); @@ -904,9 +946,11 @@ CSharpLanguage::CSharpLanguage() { #ifdef NO_THREADS lock = NULL; gchandle_bind_lock = NULL; + script_gchandle_release_lock = NULL; #else lock = Mutex::create(); script_bind_lock = Mutex::create(); + script_gchandle_release_lock = Mutex::create(); #endif lang_idx = -1; @@ -926,6 +970,11 @@ CSharpLanguage::~CSharpLanguage() { script_bind_lock = NULL; } + if (script_gchandle_release_lock) { + memdelete(script_gchandle_release_lock); + script_gchandle_release_lock = NULL; + } + singleton = NULL; } @@ -954,30 +1003,34 @@ void *CSharpLanguage::alloc_instance_binding_data(Object *p_object) { ERR_FAIL_NULL_V(mono_object, NULL); - // Tie managed to unmanaged - Reference *ref = Object::cast_to<Reference>(p_object); + CSharpScriptBinding script_binding; - if (ref) { - // Unsafe refcount increment. The managed instance also counts as a reference. - // This way if the unmanaged world has no references to our owner - // but the managed instance is alive, the refcount will be 1 instead of 0. - // See: _GodotSharp::_dispose_object(Object *p_object) - - ref->reference(); - } - - Ref<MonoGCHandle> gchandle = MonoGCHandle::create_strong(mono_object); + script_binding.type_name = type_name; + script_binding.wrapper_class = type_class; // cache + script_binding.gchandle = MonoGCHandle::create_strong(mono_object); #ifndef NO_THREADS script_bind_lock->lock(); #endif - void *data = (void *)gchandle_bindings.insert(p_object, gchandle); + void *data = (void *)script_bindings.insert(p_object, script_binding); #ifndef NO_THREADS script_bind_lock->unlock(); #endif + // Tie managed to unmanaged + Reference *ref = Object::cast_to<Reference>(p_object); + + if (ref) { + // Unsafe refcount increment. The managed instance also counts as a reference. + // This way if the unmanaged world has no references to our owner + // but the managed instance is alive, the refcount will be 1 instead of 0. + // See: godot_icall_Reference_Dtor(MonoObject *p_obj, Object *p_ptr) + + ref->reference(); + } + return data; } @@ -985,7 +1038,7 @@ void CSharpLanguage::free_instance_binding_data(void *p_data) { if (GDMono::get_singleton() == NULL) { #ifdef DEBUG_ENABLED - CRASH_COND(!gchandle_bindings.empty()); + CRASH_COND(!script_bindings.empty()); #endif // Mono runtime finalized, all the gchandle bindings were already released return; @@ -998,15 +1051,15 @@ void CSharpLanguage::free_instance_binding_data(void *p_data) { script_bind_lock->lock(); #endif - Map<Object *, Ref<MonoGCHandle> >::Element *data = (Map<Object *, Ref<MonoGCHandle> >::Element *)p_data; + Map<Object *, CSharpScriptBinding>::Element *data = (Map<Object *, CSharpScriptBinding>::Element *)p_data; // Set the native instance field to IntPtr.Zero, if not yet garbage collected - MonoObject *mono_object = data->value()->get_target(); + MonoObject *mono_object = data->value().gchandle->get_target(); if (mono_object) { CACHED_FIELD(GodotObject, ptr)->set_value_raw(mono_object, NULL); } - gchandle_bindings.erase(data); + script_bindings.erase(data); #ifndef NO_THREADS script_bind_lock->unlock(); @@ -1024,7 +1077,7 @@ void CSharpLanguage::refcount_incremented_instance_binding(Object *p_object) { void *data = p_object->get_script_instance_binding(get_language_index()); if (!data) return; - Ref<MonoGCHandle> &gchandle = ((Map<Object *, Ref<MonoGCHandle> >::Element *)data)->get(); + Ref<MonoGCHandle> &gchandle = ((Map<Object *, CSharpScriptBinding>::Element *)data)->get().gchandle; if (ref_owner->reference_get_count() > 1 && gchandle->is_weak()) { // The managed side also holds a reference, hence 1 instead of 0 // The reference count was increased after the managed side was the only one referencing our owner. @@ -1036,7 +1089,7 @@ void CSharpLanguage::refcount_incremented_instance_binding(Object *p_object) { return; // Called after the managed side was collected, so nothing to do here // Release the current weak handle and replace it with a strong handle. - uint32_t strong_gchandle = MonoGCHandle::make_strong_handle(target); + uint32_t strong_gchandle = MonoGCHandle::new_strong_handle(target); gchandle->release(); gchandle->set_handle(strong_gchandle, MonoGCHandle::STRONG_HANDLE); } @@ -1055,7 +1108,7 @@ bool CSharpLanguage::refcount_decremented_instance_binding(Object *p_object) { void *data = p_object->get_script_instance_binding(get_language_index()); if (!data) return refcount == 0; - Ref<MonoGCHandle> &gchandle = ((Map<Object *, Ref<MonoGCHandle> >::Element *)data)->get(); + Ref<MonoGCHandle> &gchandle = ((Map<Object *, CSharpScriptBinding>::Element *)data)->get().gchandle; if (refcount == 1 && !gchandle->is_weak()) { // The managed side also holds a reference, hence 1 instead of 0 // If owner owner is no longer referenced by the unmanaged side, @@ -1066,7 +1119,7 @@ bool CSharpLanguage::refcount_decremented_instance_binding(Object *p_object) { return refcount == 0; // Called after the managed side was collected, so nothing to do here // Release the current strong handle and replace it with a weak handle. - uint32_t weak_gchandle = MonoGCHandle::make_weak_handle(target); + uint32_t weak_gchandle = MonoGCHandle::new_weak_handle(target); gchandle->release(); gchandle->set_handle(weak_gchandle, MonoGCHandle::WEAK_HANDLE); @@ -1096,9 +1149,8 @@ CSharpInstance *CSharpInstance::create_for_managed_type(Object *p_owner, CSharpS } MonoObject *CSharpInstance::get_mono_object() const { -#ifdef DEBUG_ENABLED - CRASH_COND(gchandle.is_null()); -#endif + + ERR_FAIL_COND_V(gchandle.is_null(), NULL); return gchandle->get_target(); } @@ -1326,10 +1378,12 @@ void CSharpInstance::call_multilevel_reversed(const StringName &p_method, const call_multilevel(p_method, p_args, p_argcount); } -void CSharpInstance::_reference_owner_unsafe() { +bool CSharpInstance::_reference_owner_unsafe() { #ifdef DEBUG_ENABLED CRASH_COND(!base_ref); + CRASH_COND(owner == NULL); + CRASH_COND(unsafe_referenced); // already referenced #endif // Unsafe refcount increment. The managed instance also counts as a reference. @@ -1338,36 +1392,107 @@ void CSharpInstance::_reference_owner_unsafe() { // See: _unreference_owner_unsafe() // May not me referenced yet, so we must use init_ref() instead of reference() - Object::cast_to<Reference>(owner)->init_ref(); + bool success = Object::cast_to<Reference>(owner)->init_ref(); + unsafe_referenced = success; + return success; } -void CSharpInstance::_unreference_owner_unsafe() { +bool CSharpInstance::_unreference_owner_unsafe() { #ifdef DEBUG_ENABLED CRASH_COND(!base_ref); + CRASH_COND(owner == NULL); #endif + if (!unsafe_referenced) + return false; // Already unreferenced + // Called from CSharpInstance::mono_object_disposed() or ~CSharpInstance() // Unsafe refcount decrement. The managed instance also counts as a reference. // See: _reference_owner_unsafe() - if (Object::cast_to<Reference>(owner)->unreference()) { + bool die = static_cast<Reference *>(owner)->unreference(); + + if (die) { memdelete(owner); owner = NULL; } + + return die; } -void CSharpInstance::mono_object_disposed() { +MonoObject *CSharpInstance::_internal_new_managed() { +#ifdef DEBUG_ENABLED + CRASH_COND(!gchandle.is_valid()); +#endif + + CSharpLanguage::get_singleton()->release_script_gchandle(gchandle); + + ERR_FAIL_NULL_V(owner, NULL); + ERR_FAIL_COND_V(script.is_null(), NULL); if (base_ref) - _unreference_owner_unsafe(); + _reference_owner_unsafe(); + + MonoObject *mono_object = mono_object_new(SCRIPTS_DOMAIN, script->script_class->get_mono_ptr()); + + if (!mono_object) { + script = Ref<CSharpScript>(); + owner->set_script_instance(NULL); + ERR_EXPLAIN("Failed to allocate memory for the object"); + ERR_FAIL_V(NULL); + } + + CACHED_FIELD(GodotObject, ptr)->set_value_raw(mono_object, owner); + + // Construct + GDMonoMethod *ctor = script->script_class->get_method(CACHED_STRING_NAME(dotctor), 0); + ctor->invoke_raw(mono_object, NULL); + + // Tie managed to unmanaged + gchandle = MonoGCHandle::create_strong(mono_object); + + return mono_object; +} + +void CSharpInstance::mono_object_disposed(MonoObject *p_obj) { + +#ifdef DEBUG_ENABLED + CRASH_COND(base_ref == true); + CRASH_COND(gchandle.is_null()); +#endif + CSharpLanguage::get_singleton()->release_script_gchandle(p_obj, gchandle); +} + +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(gchandle.is_null()); +#endif + if (_unreference_owner_unsafe()) { + r_owner_deleted = true; + } else { + r_owner_deleted = false; + CSharpLanguage::get_singleton()->release_script_gchandle(p_obj, gchandle); + if (p_is_finalizer) { + // If the native instance is still alive, then it was + // referenced from another thread before the finalizer could + // unreference it and delete it, so we want to keep it. + // GC.ReRegisterForFinalize(this) is not safe because the objects + // referenced by this could have already been collected. + // Instead we will create a new managed instance here. + _internal_new_managed(); + } + } } void CSharpInstance::refcount_incremented() { #ifdef DEBUG_ENABLED CRASH_COND(!base_ref); + CRASH_COND(owner == NULL); #endif Reference *ref_owner = Object::cast_to<Reference>(owner); @@ -1378,7 +1503,7 @@ void CSharpInstance::refcount_incremented() { // so the owner must hold the managed side alive again to avoid it from being GCed. // Release the current weak handle and replace it with a strong handle. - uint32_t strong_gchandle = MonoGCHandle::make_strong_handle(gchandle->get_target()); + uint32_t strong_gchandle = MonoGCHandle::new_strong_handle(gchandle->get_target()); gchandle->release(); gchandle->set_handle(strong_gchandle, MonoGCHandle::STRONG_HANDLE); } @@ -1388,6 +1513,7 @@ bool CSharpInstance::refcount_decremented() { #ifdef DEBUG_ENABLED CRASH_COND(!base_ref); + CRASH_COND(owner == NULL); #endif Reference *ref_owner = Object::cast_to<Reference>(owner); @@ -1399,7 +1525,7 @@ bool CSharpInstance::refcount_decremented() { // the managed instance takes responsibility of deleting the owner when GCed. // Release the current strong handle and replace it with a weak handle. - uint32_t weak_gchandle = MonoGCHandle::make_weak_handle(gchandle->get_target()); + uint32_t weak_gchandle = MonoGCHandle::new_weak_handle(gchandle->get_target()); gchandle->release(); gchandle->set_handle(weak_gchandle, MonoGCHandle::WEAK_HANDLE); @@ -1470,25 +1596,64 @@ MultiplayerAPI::RPCMode CSharpInstance::get_rset_mode(const StringName &p_variab void CSharpInstance::notification(int p_notification) { - MonoObject *mono_object = get_mono_object(); - if (p_notification == Object::NOTIFICATION_PREDELETE) { - if (mono_object != NULL) { // otherwise it was collected, and the finalizer already called NOTIFICATION_PREDELETE - call_notification_no_check(mono_object, p_notification); - // Set the native instance field to IntPtr.Zero - CACHED_FIELD(GodotObject, ptr)->set_value_raw(mono_object, NULL); + // When NOTIFICATION_PREDELETE is sent, we also take the chance to call Dispose(). + // It's safe to call Dispose() multiple times and NOTIFICATION_PREDELETE is guaranteed + // to be sent at least once, which happens right before the call to the destructor. + + if (base_ref) { + // It's not safe to proceed if the owner derives Reference and the refcount reached 0. + // At this point, Dispose() was already called (manually or from the finalizer) so + // that's not a problem. The refcount wouldn't have reached 0 otherwise, since the + // managed side references it and Dispose() needs to be called to release it. + // However, this means C# Reference scripts can't receive NOTIFICATION_PREDELETE, but + // this is likely the case with GDScript as well: https://github.com/godotengine/godot/issues/6784 + return; + } + + _call_notification(p_notification); + + MonoObject *mono_object = get_mono_object(); + ERR_FAIL_NULL(mono_object); + + GDMonoUtils::GodotObject_Dispose thunk = CACHED_METHOD_THUNK(GodotObject, Dispose); + + MonoException *exc = NULL; + thunk(mono_object, (MonoObject **)&exc); + + if (exc) { + GDMonoUtils::set_pending_exception(exc); } + return; } - call_notification_no_check(mono_object, p_notification); + _call_notification(p_notification); } -void CSharpInstance::call_notification_no_check(MonoObject *p_mono_object, int p_notification) { - Variant value = p_notification; - const Variant *args[1] = { &value }; +void CSharpInstance::_call_notification(int p_notification) { - _call_multilevel(p_mono_object, CACHED_STRING_NAME(_notification), args, 1); + MonoObject *mono_object = get_mono_object(); + ERR_FAIL_NULL(mono_object); + + // Custom version of _call_multilevel, optimized for _notification + + uint32_t arg = p_notification; + void *args[1] = { &arg }; + StringName method_name = CACHED_STRING_NAME(_notification); + + GDMonoClass *top = script->script_class; + + while (top && top != script->native) { + GDMonoMethod *method = top->get_method(method_name, 1); + + if (method) { + method->invoke_raw(mono_object, args); + return; + } + + top = top->get_parent_class(); + } } Ref<Script> CSharpInstance::get_script() const { @@ -1501,11 +1666,11 @@ ScriptLanguage *CSharpInstance::get_language() { return CSharpLanguage::get_singleton(); } -CSharpInstance::CSharpInstance() { - - owner = NULL; - base_ref = false; - ref_dying = false; +CSharpInstance::CSharpInstance() : + owner(NULL), + base_ref(false), + ref_dying(false), + unsafe_referenced(false) { } CSharpInstance::~CSharpInstance() { @@ -1514,10 +1679,7 @@ CSharpInstance::~CSharpInstance() { gchandle->release(); // Make sure it's released } - if (base_ref && !ref_dying) { // it may be called from the owner's destructor -#ifdef DEBUG_ENABLED - CRASH_COND(!owner); // dunno, just in case -#endif + if (base_ref && !ref_dying && owner) { // it may be called from the owner's destructor _unreference_owner_unsafe(); } @@ -1586,26 +1748,27 @@ bool CSharpScript::_update_exports() { exported_members_cache.clear(); exported_members_defval_cache.clear(); - // We are creating a temporary new instance of the class here to get the default value - // TODO Workaround. Should be replaced with IL opcodes analysis + // Here we create a temporary managed instance of the class to get the initial values MonoObject *tmp_object = mono_object_new(SCRIPTS_DOMAIN, script_class->get_mono_ptr()); - if (tmp_object) { - CACHED_FIELD(GodotObject, ptr)->set_value_raw(tmp_object, tmp_object); // FIXME WTF is this workaround + if (!tmp_object) { + ERR_PRINT("Failed to create temporary MonoObject"); + return false; + } - GDMonoMethod *ctor = script_class->get_method(CACHED_STRING_NAME(dotctor), 0); - MonoException *exc = NULL; - ctor->invoke(tmp_object, NULL, &exc); + uint32_t tmp_pinned_gchandle = MonoGCHandle::new_strong_handle_pinned(tmp_object); // pin it (not sure if needed) - if (exc) { - ERR_PRINT("Exception thrown from constructor of temporary MonoObject:"); - GDMonoUtils::debug_print_unhandled_exception(exc); - tmp_object = NULL; - ERR_FAIL_V(false); - } - } else { - ERR_PRINT("Failed to create temporary MonoObject"); + GDMonoMethod *ctor = script_class->get_method(CACHED_STRING_NAME(dotctor), 0); + MonoException *ctor_exc = NULL; + ctor->invoke(tmp_object, NULL, &ctor_exc); + + if (ctor_exc) { + MonoGCHandle::free_handle(tmp_pinned_gchandle); + tmp_object = NULL; + + ERR_PRINT("Exception thrown from constructor of temporary MonoObject:"); + GDMonoUtils::debug_print_unhandled_exception(ctor_exc); return false; } @@ -1666,6 +1829,21 @@ bool CSharpScript::_update_exports() { top = top->get_parent_class(); } + + // Dispose the temporary managed instance + + GDMonoUtils::GodotObject_Dispose thunk = CACHED_METHOD_THUNK(GodotObject, Dispose); + + MonoException *exc = NULL; + thunk(tmp_object, (MonoObject **)&exc); + + if (exc) { + ERR_PRINT("Exception thrown from method Dispose() of temporary MonoObject:"); + GDMonoUtils::debug_print_unhandled_exception(exc); + } + + MonoGCHandle::free_handle(tmp_pinned_gchandle); + tmp_object = NULL; } if (placeholders.size()) { @@ -1750,6 +1928,10 @@ bool CSharpScript::_get_signal(GDMonoClass *p_class, GDMonoClass *p_delegate, Ve } #ifdef TOOLS_ENABLED +/** + * Returns false if there was an error, otherwise true. + * If there was an error, r_prop_info and r_exported are not assigned any value. + */ bool CSharpScript::_get_member_export(GDMonoClass *p_class, GDMonoClassMember *p_member, PropertyInfo &r_prop_info, bool &r_exported) { StringName name = p_member->get_name(); @@ -1775,49 +1957,100 @@ bool CSharpScript::_get_member_export(GDMonoClass *p_class, GDMonoClassMember *p Variant::Type variant_type = GDMonoMarshal::managed_to_variant_type(type); - if (p_member->has_attribute(CACHED_CLASS(ExportAttribute))) { - if (p_member->get_member_type() == GDMonoClassMember::MEMBER_TYPE_PROPERTY) { - GDMonoProperty *property = static_cast<GDMonoProperty *>(p_member); - if (!property->has_getter() || !property->has_setter()) { - ERR_PRINTS("Cannot export property because it does not provide a getter or a setter: " + p_class->get_full_name() + "." + name.operator String()); - return false; - } + if (!p_member->has_attribute(CACHED_CLASS(ExportAttribute))) { + r_prop_info = PropertyInfo(variant_type, name.operator String(), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_SCRIPT_VARIABLE); + r_exported = false; + return true; + } + + if (p_member->get_member_type() == GDMonoClassMember::MEMBER_TYPE_PROPERTY) { + GDMonoProperty *property = static_cast<GDMonoProperty *>(p_member); + if (!property->has_getter() || !property->has_setter()) { + ERR_PRINTS("Cannot export property because it does not provide a getter or a setter: " + p_class->get_full_name() + "." + name.operator String()); + return false; } + } - MonoObject *attr = p_member->get_attribute(CACHED_CLASS(ExportAttribute)); + MonoObject *attr = p_member->get_attribute(CACHED_CLASS(ExportAttribute)); - PropertyHint hint = PROPERTY_HINT_NONE; - String hint_string; + PropertyHint hint = PROPERTY_HINT_NONE; + String hint_string; - if (variant_type == Variant::NIL) { - ERR_PRINTS("Unknown type of exported member: " + p_class->get_full_name() + "." + name.operator String()); - return false; - } else if (variant_type == Variant::INT && type.type_encoding == MONO_TYPE_VALUETYPE && mono_class_is_enum(type.type_class->get_mono_ptr())) { - variant_type = Variant::INT; - hint = PROPERTY_HINT_ENUM; + if (variant_type == Variant::NIL) { + ERR_PRINTS("Unknown type of exported member: " + p_class->get_full_name() + "." + name.operator String()); + return false; + } else if (variant_type == Variant::INT && type.type_encoding == MONO_TYPE_VALUETYPE && mono_class_is_enum(type.type_class->get_mono_ptr())) { + variant_type = Variant::INT; + hint = PROPERTY_HINT_ENUM; + + Vector<MonoClassField *> fields = type.type_class->get_enum_fields(); + + MonoType *enum_basetype = mono_class_enum_basetype(type.type_class->get_mono_ptr()); - Vector<MonoClassField *> fields = type.type_class->get_enum_fields(); + String name_only_hint_string; - for (int i = 0; i < fields.size(); i++) { - if (i > 0) - hint_string += ","; - hint_string += mono_field_get_name(fields[i]); + // True: enum Foo { Bar, Baz, Quux } + // True: enum Foo { Bar = 0, Baz = 1, Quux = 2 } + // False: enum Foo { Bar = 0, Baz = 7, Quux = 5 } + bool uses_default_values = true; + + for (int i = 0; i < fields.size(); i++) { + MonoClassField *field = fields[i]; + + if (i > 0) { + hint_string += ","; + name_only_hint_string += ","; } - } else if (variant_type == Variant::OBJECT && CACHED_CLASS(GodotReference)->is_assignable_from(type.type_class)) { - hint = PROPERTY_HINT_RESOURCE_TYPE; - hint_string = NATIVE_GDMONOCLASS_NAME(type.type_class); - } else { - hint = PropertyHint(CACHED_FIELD(ExportAttribute, hint)->get_int_value(attr)); - hint_string = CACHED_FIELD(ExportAttribute, hintString)->get_string_value(attr); + + String enum_field_name = mono_field_get_name(field); + hint_string += enum_field_name; + name_only_hint_string += enum_field_name; + + // TODO: + // Instead of using mono_field_get_value_object, we can do this without boxing. Check the + // internal mono functions: ves_icall_System_Enum_GetEnumValuesAndNames and the get_enum_field. + + MonoObject *val_obj = mono_field_get_value_object(mono_domain_get(), field, NULL); + + if (val_obj == NULL) { + ERR_PRINTS("Failed to get '" + enum_field_name + "' constant enum value of exported member: " + + p_class->get_full_name() + "." + name.operator String()); + return false; + } + + bool r_error; + uint64_t val = GDMonoUtils::unbox_enum_value(val_obj, enum_basetype, r_error); + if (r_error) { + ERR_PRINTS("Failed to unbox '" + enum_field_name + "' constant enum value of exported member: " + + p_class->get_full_name() + "." + name.operator String()); + return false; + } + + if (val != i) { + uses_default_values = false; + } + + hint_string += ":"; + hint_string += String::num_uint64(val); } - r_prop_info = PropertyInfo(variant_type, name.operator String(), hint, hint_string, PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SCRIPT_VARIABLE); - r_exported = true; + if (uses_default_values) { + // If we use the format NAME:VAL, that's what the editor displays. + // That's annoying if the user is not using custom values for the enum constants. + // This may not be needed in the future if the editor is changed to not display values. + hint_string = name_only_hint_string; + } + } else if (variant_type == Variant::OBJECT && CACHED_CLASS(GodotReference)->is_assignable_from(type.type_class)) { + hint = PROPERTY_HINT_RESOURCE_TYPE; + hint_string = NATIVE_GDMONOCLASS_NAME(type.type_class); } else { - r_prop_info = PropertyInfo(variant_type, name.operator String(), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_SCRIPT_VARIABLE); - r_exported = false; + hint = PropertyHint(CACHED_FIELD(ExportAttribute, hint)->get_int_value(attr)); + hint_string = CACHED_FIELD(ExportAttribute, hintString)->get_string_value(attr); } + r_prop_info = PropertyInfo(variant_type, name.operator String(), hint, hint_string, PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SCRIPT_VARIABLE); + r_exported = true; + return true; } #endif @@ -2012,6 +2245,8 @@ CSharpInstance *CSharpScript::_create_instance(const Variant **p_args, int p_arg ERR_FAIL_V(NULL); } + uint32_t pinned_gchandle = MonoGCHandle::new_strong_handle_pinned(mono_object); // we might lock after this, so pin it + #ifndef NO_THREADS CSharpLanguage::singleton->lock->lock(); #endif @@ -2033,6 +2268,8 @@ CSharpInstance *CSharpScript::_create_instance(const Variant **p_args, int p_arg /* STEP 3, PARTY */ + MonoGCHandle::free_handle(pinned_gchandle); + //@TODO make thread safe return instance; } diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h index 1a5d0c8a69..8b0a095890 100644 --- a/modules/mono/csharp_script.h +++ b/modules/mono/csharp_script.h @@ -31,10 +31,10 @@ #ifndef CSHARP_SCRIPT_H #define CSHARP_SCRIPT_H -#include "io/resource_loader.h" -#include "io/resource_saver.h" -#include "script_language.h" -#include "self_list.h" +#include "core/io/resource_loader.h" +#include "core/io/resource_saver.h" +#include "core/script_language.h" +#include "core/self_list.h" #include "mono_gc_handle.h" #include "mono_gd/gd_mono.h" @@ -48,6 +48,8 @@ class CSharpLanguage; #ifdef NO_SAFE_CAST template <typename TScriptInstance, typename TScriptLanguage> TScriptInstance *cast_script_instance(ScriptInstance *p_inst) { + if (!p_inst) + return NULL; return p_inst->get_language() == TScriptLanguage::get_singleton() ? static_cast<TScriptInstance *>(p_inst) : NULL; } #else @@ -177,14 +179,19 @@ class CSharpInstance : public ScriptInstance { friend class CSharpScript; friend class CSharpLanguage; + Object *owner; - Ref<CSharpScript> script; - Ref<MonoGCHandle> gchandle; bool base_ref; bool ref_dying; + bool unsafe_referenced; + + Ref<CSharpScript> script; + Ref<MonoGCHandle> gchandle; - void _reference_owner_unsafe(); - void _unreference_owner_unsafe(); + bool _reference_owner_unsafe(); + bool _unreference_owner_unsafe(); + + MonoObject *_internal_new_managed(); // Do not use unless you know what you are doing friend void GDMonoInternals::tie_managed_to_unmanaged(MonoObject *, Object *); @@ -208,7 +215,8 @@ public: virtual void call_multilevel(const StringName &p_method, const Variant **p_args, int p_argcount); virtual void call_multilevel_reversed(const StringName &p_method, const Variant **p_args, int p_argcount); - void mono_object_disposed(); + void mono_object_disposed(MonoObject *p_obj); + void mono_object_disposed_baseref(MonoObject *p_obj, bool p_is_finalizer, bool &r_owner_deleted); virtual void refcount_incremented(); virtual bool refcount_decremented(); @@ -217,7 +225,7 @@ public: virtual MultiplayerAPI::RPCMode get_rset_mode(const StringName &p_variable) const; virtual void notification(int p_notification); - void call_notification_no_check(MonoObject *p_mono_object, int p_notification); + void _call_notification(int p_notification); virtual Ref<Script> get_script() const; @@ -227,6 +235,12 @@ public: ~CSharpInstance(); }; +struct CSharpScriptBinding { + StringName type_name; + GDMonoClass *wrapper_class; + Ref<MonoGCHandle> gchandle; +}; + class CSharpLanguage : public ScriptLanguage { friend class CSharpScript; @@ -241,10 +255,11 @@ class CSharpLanguage : public ScriptLanguage { Mutex *lock; Mutex *script_bind_lock; + Mutex *script_gchandle_release_lock; Map<Ref<CSharpScript>, Map<ObjectID, List<Pair<StringName, Variant> > > > to_reload; - Map<Object *, Ref<MonoGCHandle> > gchandle_bindings; + Map<Object *, CSharpScriptBinding> script_bindings; struct StringNameCache { @@ -270,6 +285,9 @@ public: _FORCE_INLINE_ static CSharpLanguage *get_singleton() { return singleton; } + static void release_script_gchandle(Ref<MonoGCHandle> &p_gchandle); + static void release_script_gchandle(MonoObject *p_pinned_expected_obj, Ref<MonoGCHandle> &p_gchandle); + bool debug_break(const String &p_error, bool p_allow_continue = true); bool debug_break_parse(const String &p_file, int p_line, const String &p_error); diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp index cc954348f4..308c54ecb3 100644 --- a/modules/mono/editor/bindings_generator.cpp +++ b/modules/mono/editor/bindings_generator.cpp @@ -32,15 +32,16 @@ #ifdef DEBUG_METHODS_ENABLED -#include "engine.h" -#include "global_constants.h" -#include "io/compression.h" -#include "os/dir_access.h" -#include "os/file_access.h" -#include "os/os.h" -#include "ucaps.h" +#include "core/engine.h" +#include "core/global_constants.h" +#include "core/io/compression.h" +#include "core/os/dir_access.h" +#include "core/os/file_access.h" +#include "core/os/os.h" +#include "core/ucaps.h" #include "../glue/cs_compressed.gen.h" +#include "../glue/cs_glue_version.gen.h" #include "../godotsharp_defs.h" #include "../mono_gd/gd_mono_marshal.h" #include "../utils/path_utils.h" @@ -48,7 +49,7 @@ #include "csharp_project.h" #include "net_solution.h" -#define CS_INDENT " " +#define CS_INDENT " " // 4 whitespaces #define INDENT1 CS_INDENT #define INDENT2 INDENT1 INDENT1 @@ -68,23 +69,18 @@ #define CLOSE_BLOCK_L3 INDENT3 CLOSE_BLOCK #define CLOSE_BLOCK_L4 INDENT4 CLOSE_BLOCK -#define LOCAL_RET "ret" - #define CS_FIELD_MEMORYOWN "memoryOwn" #define CS_PARAM_METHODBIND "method" #define CS_PARAM_INSTANCE "ptr" #define CS_SMETHOD_GETINSTANCE "GetPtr" -#define CS_FIELD_SINGLETON "instance" -#define CS_PROP_SINGLETON "Instance" -#define CS_CLASS_SIGNALAWAITER "SignalAwaiter" #define CS_METHOD_CALL "Call" #define GLUE_HEADER_FILE "glue_header.h" #define ICALL_PREFIX "godot_icall_" #define SINGLETON_ICALL_SUFFIX "_get_singleton" -#define ICALL_GET_METHODBIND ICALL_PREFIX "ClassDB_get_method" -#define ICALL_CONNECT_SIGNAL_AWAITER ICALL_PREFIX "Object_connect_signal_awaiter" -#define ICALL_OBJECT_DTOR ICALL_PREFIX "Object_Dtor" +#define ICALL_GET_METHODBIND ICALL_PREFIX "Object_ClassDB_get_method" + +#define C_LOCAL_RET "ret" #define C_LOCAL_PTRCALL_ARGS "call_args" #define C_MACRO_OBJECT_CONSTRUCT "GODOTSHARP_INSTANCE_OBJECT" @@ -101,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(2) +#define BINDINGS_GENERATOR_VERSION UINT32_C(3) const char *BindingsGenerator::TypeInterface::DEFAULT_VARARG_C_IN = "\t%0 %1_in = %1;\n"; @@ -196,48 +192,6 @@ String BindingsGenerator::_determine_enum_prefix(const EnumInterface &p_ienum) { return front->get().name.substr(0, candidate_len); } -void BindingsGenerator::_generate_header_icalls() { - - core_custom_icalls.clear(); - - core_custom_icalls.push_back(InternalCall(ICALL_GET_METHODBIND, "IntPtr", "string type, string method")); - core_custom_icalls.push_back(InternalCall(ICALL_OBJECT_DTOR, "void", "object obj, IntPtr ptr")); - - core_custom_icalls.push_back(InternalCall(ICALL_CONNECT_SIGNAL_AWAITER, "Error", - "IntPtr source, string signal, IntPtr target, " CS_CLASS_SIGNALAWAITER " awaiter")); - - core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "NodePath_Ctor", "IntPtr", "string path")); - core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "NodePath_Dtor", "void", "IntPtr ptr")); - core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "NodePath_operator_String", "string", "IntPtr ptr")); - - core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "RID_Ctor", "IntPtr", "IntPtr from")); - core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "RID_Dtor", "void", "IntPtr ptr")); - - core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "String_md5_buffer", "byte[]", "string str")); - core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "String_md5_text", "string", "string str")); - core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "String_rfind", "int", "string str, string what, int from")); - core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "String_rfindn", "int", "string str, string what, int from")); - core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "String_sha256_buffer", "byte[]", "string str")); - core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "String_sha256_text", "string", "string str")); - - core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "Godot_bytes2var", "object", "byte[] bytes")); - core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "Godot_convert", "object", "object what, int type")); - core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "Godot_hash", "int", "object var")); - core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "Godot_instance_from_id", "Object", "int instance_id")); - core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "Godot_print", "void", "object[] what")); - core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "Godot_printerr", "void", "object[] what")); - core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "Godot_printraw", "void", "object[] what")); - core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "Godot_prints", "void", "object[] what")); - core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "Godot_printt", "void", "object[] what")); - core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "Godot_seed", "void", "int seed")); - core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "Godot_str", "string", "object[] what")); - core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "Godot_str2var", "object", "string str")); - core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "Godot_type_exists", "bool", "string type")); - core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "Godot_var2bytes", "byte[]", "object what")); - core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "Godot_var2str", "string", "object var")); - core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "Godot_weakref", "WeakRef", "IntPtr obj")); -} - void BindingsGenerator::_generate_method_icalls(const TypeInterface &p_itype) { for (const List<MethodInterface>::Element *E = p_itype.methods.front(); E; E = E->next()) { @@ -248,13 +202,8 @@ void BindingsGenerator::_generate_method_icalls(const TypeInterface &p_itype) { const TypeInterface *return_type = _get_type_or_placeholder(imethod.return_type); - String im_sig; - String im_unique_sig; - - if (p_itype.is_object_type) { - im_sig += "IntPtr " CS_PARAM_METHODBIND ", "; - im_unique_sig += imethod.return_type.cname.operator String() + ",IntPtr,IntPtr"; - } + String im_sig = "IntPtr " CS_PARAM_METHODBIND ", "; + String im_unique_sig = imethod.return_type.cname.operator String() + ",IntPtr,IntPtr"; im_sig += "IntPtr " CS_PARAM_INSTANCE; @@ -268,37 +217,28 @@ void BindingsGenerator::_generate_method_icalls(const TypeInterface &p_itype) { im_sig += " arg"; im_sig += itos(i + 1); - if (p_itype.is_object_type) { - im_unique_sig += ","; - im_unique_sig += get_unique_sig(*arg_type); - } + im_unique_sig += ","; + im_unique_sig += get_unique_sig(*arg_type); i++; } + // godot_icall_{argc}_{icallcount} String icall_method = ICALL_PREFIX; - - if (p_itype.is_object_type) { - icall_method += itos(imethod.arguments.size()) + "_" + itos(method_icalls.size()); // godot_icall_{argc}_{icallcount} - } else { - icall_method += p_itype.name + "_" + imethod.name; // godot_icall_{Type}_{method} - } + icall_method += itos(imethod.arguments.size()); + icall_method += "_"; + icall_method += itos(method_icalls.size()); InternalCall im_icall = InternalCall(p_itype.api_type, icall_method, return_type->im_type_out, im_sig, im_unique_sig); - if (p_itype.is_object_type) { - List<InternalCall>::Element *match = method_icalls.find(im_icall); + List<InternalCall>::Element *match = method_icalls.find(im_icall); - if (match) { - if (p_itype.api_type != ClassDB::API_EDITOR) - match->get().editor_only = false; - method_icalls_map.insert(&E->get(), &match->get()); - } else { - List<InternalCall>::Element *added = method_icalls.push_back(im_icall); - method_icalls_map.insert(&E->get(), &added->get()); - } + if (match) { + if (p_itype.api_type != ClassDB::API_EDITOR) + match->get().editor_only = false; + method_icalls_map.insert(&E->get(), &match->get()); } else { - List<InternalCall>::Element *added = builtin_method_icalls.push_back(im_icall); + List<InternalCall>::Element *added = method_icalls.push_back(im_icall); method_icalls_map.insert(&E->get(), &added->get()); } } @@ -483,20 +423,6 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_output_dir, bo compile_items.push_back(output_file); } -#define GENERATE_BUILTIN_TYPE(m_name) \ - { \ - String output_file = path_join(core_dir, #m_name ".cs"); \ - Error err = _generate_cs_type(builtin_types[#m_name], output_file); \ - if (err != OK) \ - return err; \ - compile_items.push_back(output_file); \ - } - - GENERATE_BUILTIN_TYPE(NodePath); - GENERATE_BUILTIN_TYPE(RID); - -#undef GENERATE_BUILTIN_TYPE - // Generate sources from compressed files Map<String, CompressedFile> compressed_files; @@ -537,29 +463,26 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_output_dir, bo cs_icalls_content.push_back("namespace " BINDINGS_NAMESPACE "\n" OPEN_BLOCK); cs_icalls_content.push_back(INDENT1 "internal static class " BINDINGS_CLASS_NATIVECALLS "\n" INDENT1 OPEN_BLOCK); - cs_icalls_content.push_back(INDENT2 "internal static ulong godot_api_hash = "); + cs_icalls_content.push_back(MEMBER_BEGIN "internal static ulong godot_api_hash = "); cs_icalls_content.push_back(String::num_uint64(GDMono::get_singleton()->get_api_core_hash()) + ";\n"); - cs_icalls_content.push_back(INDENT2 "internal static uint bindings_version = "); + cs_icalls_content.push_back(MEMBER_BEGIN "internal static uint bindings_version = "); cs_icalls_content.push_back(String::num_uint64(BINDINGS_GENERATOR_VERSION) + ";\n"); - cs_icalls_content.push_back(INDENT2 "internal static uint cs_glue_version = "); + cs_icalls_content.push_back(MEMBER_BEGIN "internal static uint cs_glue_version = "); cs_icalls_content.push_back(String::num_uint64(CS_GLUE_VERSION) + ";\n"); - cs_icalls_content.push_back("\n"); -#define ADD_INTERNAL_CALL(m_icall) \ - if (!m_icall.editor_only) { \ - cs_icalls_content.push_back(INDENT2 "[MethodImpl(MethodImplOptions.InternalCall)]\n"); \ - cs_icalls_content.push_back(INDENT2 "internal extern static "); \ - cs_icalls_content.push_back(m_icall.im_type_out + " "); \ - cs_icalls_content.push_back(m_icall.name + "("); \ - cs_icalls_content.push_back(m_icall.im_sig + ");\n"); \ +#define ADD_INTERNAL_CALL(m_icall) \ + if (!m_icall.editor_only) { \ + cs_icalls_content.push_back(MEMBER_BEGIN "[MethodImpl(MethodImplOptions.InternalCall)]\n"); \ + cs_icalls_content.push_back(INDENT2 "internal extern static "); \ + cs_icalls_content.push_back(m_icall.im_type_out + " "); \ + cs_icalls_content.push_back(m_icall.name + "("); \ + cs_icalls_content.push_back(m_icall.im_sig + ");\n"); \ } for (const List<InternalCall>::Element *E = core_custom_icalls.front(); E; E = E->next()) ADD_INTERNAL_CALL(E->get()); for (const List<InternalCall>::Element *E = method_icalls.front(); E; E = E->next()) ADD_INTERNAL_CALL(E->get()); - for (const List<InternalCall>::Element *E = builtin_method_icalls.front(); E; E = E->next()) - ADD_INTERNAL_CALL(E->get()); #undef ADD_INTERNAL_CALL @@ -658,8 +581,6 @@ Error BindingsGenerator::generate_cs_editor_project(const String &p_output_dir, cs_icalls_content.push_back(m_icall.im_sig + ");\n"); \ } - // No need to add builtin_method_icalls. Builtin types are core only - for (const List<InternalCall>::Element *E = editor_custom_icalls.front(); E; E = E->next()) ADD_INTERNAL_CALL(E->get()); for (const List<InternalCall>::Element *E = method_icalls.front(); E; E = E->next()) @@ -693,18 +614,34 @@ Error BindingsGenerator::generate_cs_editor_project(const String &p_output_dir, return OK; } -// TODO: there are constants that hide inherited members. must explicitly use `new` to avoid warnings -// e.g.: warning CS0108: 'SpriteBase3D.FLAG_MAX' hides inherited member 'GeometryInstance.FLAG_MAX'. Use the new keyword if hiding was intended. +// FIXME: There are some members that hide other inherited members. +// - In the case of both members being the same kind, the new one must be declared +// explicitly as `new` to avoid the warning (and we must print a message about it). +// - In the case of both members being of a different kind, then the new one must +// be renamed to avoid the name collision (and we must print a warning about it). +// - Csc warning e.g.: +// ObjectType/LineEdit.cs(140,38): warning CS0108: 'LineEdit.FocusMode' hides inherited member 'Control.FocusMode'. Use the new keyword if hiding was intended. Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const String &p_output_file) { + CRASH_COND(!itype.is_object_type); + bool is_derived_type = itype.base_name != StringName(); + if (!is_derived_type) { + // Some Godot.Object assertions + CRASH_COND(itype.cname != name_cache.type_Object); + CRASH_COND(!itype.is_instantiable); + CRASH_COND(itype.api_type != ClassDB::API_CORE); + CRASH_COND(itype.is_reference); + CRASH_COND(itype.is_singleton); + } + List<InternalCall> &custom_icalls = itype.api_type == ClassDB::API_EDITOR ? editor_custom_icalls : core_custom_icalls; if (verbose_output) OS::get_singleton()->print(String("Generating " + itype.proxy_name + ".cs...\n").utf8()); - String ctor_method(ICALL_PREFIX + itype.proxy_name + "_Ctor"); + String ctor_method(ICALL_PREFIX + itype.proxy_name + "_Ctor"); // Used only for derived types List<String> output; @@ -733,28 +670,24 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str } output.push_back(INDENT1 "public "); - if (itype.is_object_type) { - if (itype.is_singleton) { - output.push_back("static partial class "); - } else { - output.push_back(itype.is_instantiable ? "partial class " : "abstract partial class "); - } + if (itype.is_singleton) { + output.push_back("static partial class "); } else { - output.push_back("partial class "); + output.push_back(itype.is_instantiable ? "partial class " : "abstract partial class "); } output.push_back(itype.proxy_name); if (itype.is_singleton) { output.push_back("\n"); - } else if (!is_derived_type || !itype.is_object_type /* assuming only object types inherit */) { - output.push_back(" : IDisposable\n"); - } else if (obj_types.has(itype.base_name)) { - output.push_back(" : "); - output.push_back(obj_types[itype.base_name].proxy_name); - output.push_back("\n"); - } else { - ERR_PRINTS("Base type '" + itype.base_name.operator String() + "' does not exist, for class " + itype.name); - return ERR_INVALID_DATA; + } else if (is_derived_type) { + if (obj_types.has(itype.base_name)) { + output.push_back(" : "); + output.push_back(obj_types[itype.base_name].proxy_name); + output.push_back("\n"); + } else { + ERR_PRINTS("Base type '" + itype.base_name.operator String() + "' does not exist, for class " + itype.name); + return ERR_INVALID_DATA; + } } output.push_back(INDENT1 "{"); @@ -851,9 +784,6 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str output.push_back(INDENT2 CLOSE_BLOCK); } - if (itype.enums.size()) - output.push_back("\n"); - // Add properties for (const List<PropertyInterface>::Element *E = itype.properties.front(); E; E = E->next()) { @@ -865,43 +795,9 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str ERR_FAIL_V(prop_err); } } - - if (class_doc->properties.size()) - output.push_back("\n"); } - if (!itype.is_object_type) { - output.push_back(MEMBER_BEGIN "private const string " BINDINGS_NATIVE_NAME_FIELD " = \"" + itype.name + "\";\n"); - output.push_back(MEMBER_BEGIN "private bool disposed = false;\n"); - output.push_back(MEMBER_BEGIN "internal IntPtr " BINDINGS_PTR_FIELD ";\n"); - - output.push_back(MEMBER_BEGIN "internal static IntPtr " CS_SMETHOD_GETINSTANCE "("); - output.push_back(itype.proxy_name); - output.push_back(" instance)\n" OPEN_BLOCK_L2 "return instance == null ? IntPtr.Zero : instance." BINDINGS_PTR_FIELD ";\n" CLOSE_BLOCK_L2); - - // Add Destructor - output.push_back(MEMBER_BEGIN "~"); - output.push_back(itype.proxy_name); - output.push_back("()\n" OPEN_BLOCK_L2 "Dispose(false);\n" CLOSE_BLOCK_L2); - - // Add the Dispose from IDisposable - output.push_back(MEMBER_BEGIN "public void Dispose()\n" OPEN_BLOCK_L2 "Dispose(true);\n" INDENT3 "GC.SuppressFinalize(this);\n" CLOSE_BLOCK_L2); - - // Add the virtual Dispose - output.push_back(MEMBER_BEGIN "protected virtual void Dispose(bool disposing)\n" OPEN_BLOCK_L2 - "if (disposed) return;\n" INDENT3 - "if (" BINDINGS_PTR_FIELD " != IntPtr.Zero)\n" OPEN_BLOCK_L3 "NativeCalls.godot_icall_"); - output.push_back(itype.proxy_name); - output.push_back("_Dtor(" BINDINGS_PTR_FIELD ");\n" INDENT5 BINDINGS_PTR_FIELD " = IntPtr.Zero;\n" CLOSE_BLOCK_L3 INDENT3 - "GC.SuppressFinalize(this);\n" INDENT3 "disposed = true;\n" CLOSE_BLOCK_L2); - - output.push_back(MEMBER_BEGIN "internal "); - output.push_back(itype.proxy_name); - output.push_back("(IntPtr " BINDINGS_PTR_FIELD ")\n" OPEN_BLOCK_L2 "this." BINDINGS_PTR_FIELD " = " BINDINGS_PTR_FIELD ";\n" CLOSE_BLOCK_L2); - - output.push_back(MEMBER_BEGIN "public IntPtr NativeInstance\n" OPEN_BLOCK_L2 - "get { return " BINDINGS_PTR_FIELD "; }\n" CLOSE_BLOCK_L2); - } else if (itype.is_singleton) { + if (itype.is_singleton) { // Add the type name and the singleton pointer as static fields output.push_back(MEMBER_BEGIN "private const string " BINDINGS_NATIVE_NAME_FIELD " = \""); @@ -913,21 +809,13 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str output.push_back("." ICALL_PREFIX); output.push_back(itype.name); output.push_back(SINGLETON_ICALL_SUFFIX "();\n"); - } else { + } else if (is_derived_type) { // Add member fields output.push_back(MEMBER_BEGIN "private const string " BINDINGS_NATIVE_NAME_FIELD " = \""); output.push_back(itype.name); output.push_back("\";\n"); - // Only the base class stores the pointer to the native object - // This pointer is expected to be and must be of type Object* - if (!is_derived_type) { - output.push_back(MEMBER_BEGIN "private bool disposed = false;\n"); - output.push_back(INDENT2 "internal IntPtr " BINDINGS_PTR_FIELD ";\n"); - output.push_back(INDENT2 "internal bool " CS_FIELD_MEMORYOWN ";\n"); - } - // Add default constructor if (itype.is_instantiable) { output.push_back(MEMBER_BEGIN "public "); @@ -952,67 +840,9 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str // Add.. em.. trick constructor. Sort of. output.push_back(MEMBER_BEGIN "internal "); output.push_back(itype.proxy_name); - if (is_derived_type) { - output.push_back("(bool " CS_FIELD_MEMORYOWN ") : base(" CS_FIELD_MEMORYOWN ") {}\n"); - } else { - output.push_back("(bool " CS_FIELD_MEMORYOWN ")\n" OPEN_BLOCK_L2 - "this." CS_FIELD_MEMORYOWN " = " CS_FIELD_MEMORYOWN ";\n" CLOSE_BLOCK_L2); - } - - // Add methods - - if (!is_derived_type) { - output.push_back(MEMBER_BEGIN "public IntPtr NativeInstance\n" OPEN_BLOCK_L2 - "get { return " BINDINGS_PTR_FIELD "; }\n" CLOSE_BLOCK_L2); - - output.push_back(MEMBER_BEGIN "internal static IntPtr " CS_SMETHOD_GETINSTANCE "(Object instance)\n" OPEN_BLOCK_L2 - "return instance == null ? IntPtr.Zero : instance." BINDINGS_PTR_FIELD ";\n" CLOSE_BLOCK_L2); - } - - if (!is_derived_type) { - // Add destructor - output.push_back(MEMBER_BEGIN "~"); - output.push_back(itype.proxy_name); - output.push_back("()\n" OPEN_BLOCK_L2 "Dispose(false);\n" CLOSE_BLOCK_L2); - - // Add the Dispose from IDisposable - output.push_back(MEMBER_BEGIN "public void Dispose()\n" OPEN_BLOCK_L2 "Dispose(true);\n" INDENT3 "GC.SuppressFinalize(this);\n" CLOSE_BLOCK_L2); - - // Add the virtual Dispose - output.push_back(MEMBER_BEGIN "protected virtual void Dispose(bool disposing)\n" OPEN_BLOCK_L2 - "if (disposed) return;\n" INDENT3 - "if (" BINDINGS_PTR_FIELD " != IntPtr.Zero)\n" OPEN_BLOCK_L3 - "if (" CS_FIELD_MEMORYOWN ")\n" OPEN_BLOCK_L4 CS_FIELD_MEMORYOWN - " = false;\n" INDENT5 BINDINGS_CLASS_NATIVECALLS "." ICALL_OBJECT_DTOR - "(this, " BINDINGS_PTR_FIELD ");\n" CLOSE_BLOCK_L4 CLOSE_BLOCK_L3 INDENT3 - "this." BINDINGS_PTR_FIELD " = IntPtr.Zero;\n" INDENT3 - "GC.SuppressFinalize(this);\n" INDENT3 "disposed = true;\n" CLOSE_BLOCK_L2); - - Map<StringName, TypeInterface>::Element *array_itype = builtin_types.find(name_cache.type_Array); - - if (!array_itype) { - ERR_PRINT("BUG: Array type interface not found!"); - return ERR_BUG; - } - - OrderedHashMap<StringName, TypeInterface>::Element object_itype = obj_types.find("Object"); - - if (!object_itype) { - ERR_PRINT("BUG: Object type interface not found!"); - return ERR_BUG; - } - - output.push_back(MEMBER_BEGIN "public " CS_CLASS_SIGNALAWAITER " ToSignal("); - output.push_back(object_itype.get().cs_type); - output.push_back(" source, string signal)\n" OPEN_BLOCK_L2 - "return new " CS_CLASS_SIGNALAWAITER "(source, signal, this);\n" CLOSE_BLOCK_L2); - } + output.push_back("(bool " CS_FIELD_MEMORYOWN ") : base(" CS_FIELD_MEMORYOWN ") {}\n"); } - Map<StringName, String>::Element *extra_member = extra_members.find(itype.cname); - if (extra_member) - output.push_back(extra_member->get()); - int method_bind_count = 0; for (const List<MethodInterface>::Element *E = itype.methods.front(); E; E = E->next()) { const MethodInterface &imethod = E->get(); @@ -1030,7 +860,7 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str custom_icalls.push_back(singleton_icall); } - if (itype.is_instantiable) { + if (is_derived_type && itype.is_instantiable) { InternalCall ctor_icall = InternalCall(itype.api_type, ctor_method, "IntPtr", itype.proxy_name + " obj"); if (!find_icall_by_name(ctor_icall.name, custom_icalls)) @@ -1178,9 +1008,7 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf String arguments_sig; String cs_in_statements; - String icall_params; - if (p_itype.is_object_type) - icall_params += method_bind_field + ", "; + String icall_params = method_bind_field + ", "; icall_params += sformat(p_itype.cs_in, "this"); List<String> default_args_doc; @@ -1257,9 +1085,9 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf // Generate method { - if (p_itype.is_object_type && !p_imethod.is_virtual && !p_imethod.requires_object_call) { + if (!p_imethod.is_virtual && !p_imethod.requires_object_call) { p_output.push_back(MEMBER_BEGIN "private static IntPtr "); - p_output.push_back(method_bind_field + " = " BINDINGS_CLASS_NATIVECALLS "." ICALL_GET_METHODBIND "(" BINDINGS_NATIVE_NAME_FIELD ", \""); + 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"); } @@ -1372,19 +1200,31 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) { List<String> output; - output.push_back("#include \"" GLUE_HEADER_FILE "\"\n" - "\n"); + output.push_back("/* THIS FILE IS GENERATED DO NOT EDIT */\n"); + output.push_back("#include \"" GLUE_HEADER_FILE "\"\n"); + output.push_back("\n#ifdef MONO_GLUE_ENABLED\n"); generated_icall_funcs.clear(); for (OrderedHashMap<StringName, TypeInterface>::Element type_elem = obj_types.front(); type_elem; type_elem = type_elem.next()) { const TypeInterface &itype = type_elem.get(); + bool is_derived_type = itype.base_name != StringName(); + + if (!is_derived_type) { + // Some Object assertions + CRASH_COND(itype.cname != name_cache.type_Object); + CRASH_COND(!itype.is_instantiable); + CRASH_COND(itype.api_type != ClassDB::API_CORE); + CRASH_COND(itype.is_reference); + CRASH_COND(itype.is_singleton); + } + List<InternalCall> &custom_icalls = itype.api_type == ClassDB::API_EDITOR ? editor_custom_icalls : core_custom_icalls; OS::get_singleton()->print(String("Generating " + itype.name + "...\n").utf8()); - String ctor_method(ICALL_PREFIX + itype.proxy_name + "_Ctor"); + String ctor_method(ICALL_PREFIX + itype.proxy_name + "_Ctor"); // Used only for derived types for (const List<MethodInterface>::Element *E = itype.methods.front(); E; E = E->next()) { const MethodInterface &imethod = E->get(); @@ -1409,7 +1249,7 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) { output.push_back("\");\n" CLOSE_BLOCK "\n"); } - if (itype.is_instantiable) { + if (is_derived_type && itype.is_instantiable) { InternalCall ctor_icall = InternalCall(itype.api_type, ctor_method, "IntPtr", itype.proxy_name + " obj"); if (!find_icall_by_name(ctor_icall.name, custom_icalls)) @@ -1426,7 +1266,7 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) { } } - output.push_back("namespace GodotSharpBindings\n" OPEN_BLOCK); + 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"); @@ -1438,11 +1278,9 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) { output.push_back("uint32_t get_bindings_version() { return "); output.push_back(String::num_uint64(BINDINGS_GENERATOR_VERSION) + "; }\n"); - output.push_back("uint32_t get_cs_glue_version() { return "); - output.push_back(String::num_uint64(CS_GLUE_VERSION) + "; }\n"); - output.push_back("void register_generated_icalls() " OPEN_BLOCK); - output.push_back("\tgodot_register_header_icalls();"); + output.push_back("\nvoid register_generated_icalls() " OPEN_BLOCK); + output.push_back("\tgodot_register_glue_header_icalls();\n"); #define ADD_INTERNAL_CALL_REGISTRATION(m_icall) \ { \ @@ -1505,12 +1343,11 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) { output.push_back("#endif\n"); } - for (const List<InternalCall>::Element *E = builtin_method_icalls.front(); E; E = E->next()) - ADD_INTERNAL_CALL_REGISTRATION(E->get()); - #undef ADD_INTERNAL_CALL_REGISTRATION - output.push_back(CLOSE_BLOCK "}\n"); + output.push_back(CLOSE_BLOCK "\n} // namespace GodotSharpBindings\n"); + + output.push_back("\n#endif // MONO_GLUE_ENABLED\n"); Error save_err = _save_file(path_join(p_output_dir, "mono_glue.gen.cpp"), output); if (save_err != OK) @@ -1525,10 +1362,6 @@ uint32_t BindingsGenerator::get_version() { return BINDINGS_GENERATOR_VERSION; } -uint32_t BindingsGenerator::get_cs_glue_version() { - return CS_GLUE_VERSION; -} - Error BindingsGenerator::_save_file(const String &p_path, const List<String> &p_content) { FileAccessRef file = FileAccess::open(p_path, FileAccess::WRITE); @@ -1591,9 +1424,6 @@ Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInte i++; } - if (!p_itype.is_object_type) - return OK; // no auto-generated icall functions for builtin types - const Map<const MethodInterface *, const InternalCall *>::Element *match = method_icalls_map.find(&p_imethod); ERR_FAIL_NULL_V(match, ERR_BUG); @@ -1628,7 +1458,7 @@ Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInte } p_output.push_back("\t" + ptrcall_return_type); - p_output.push_back(" " LOCAL_RET); + p_output.push_back(" " C_LOCAL_RET); p_output.push_back(initialization + ";\n"); p_output.push_back("\tERR_FAIL_NULL_V(" CS_PARAM_INSTANCE); p_output.push_back(fail_ret); @@ -1678,7 +1508,7 @@ Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInte p_output.push_back("\tVariant::CallError vcall_error;\n\t"); if (!ret_void) - p_output.push_back(LOCAL_RET " = "); + p_output.push_back(C_LOCAL_RET " = "); p_output.push_back(CS_PARAM_METHODBIND "->call(" CS_PARAM_INSTANCE ", "); p_output.push_back(p_imethod.arguments.size() ? "(const Variant**)" C_LOCAL_PTRCALL_ARGS ".ptr()" : "NULL"); @@ -1686,14 +1516,14 @@ Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInte } else { p_output.push_back("\t" CS_PARAM_METHODBIND "->ptrcall(" CS_PARAM_INSTANCE ", "); p_output.push_back(p_imethod.arguments.size() ? C_LOCAL_PTRCALL_ARGS ", " : "NULL, "); - p_output.push_back(!ret_void ? "&" LOCAL_RET ");\n" : "NULL);\n"); + p_output.push_back(!ret_void ? "&" C_LOCAL_RET ");\n" : "NULL);\n"); } if (!ret_void) { if (return_type->c_out.empty()) - p_output.push_back("\treturn " LOCAL_RET ";\n"); + p_output.push_back("\treturn " C_LOCAL_RET ";\n"); else - p_output.push_back(sformat(return_type->c_out, return_type->c_type_out, LOCAL_RET, return_type->name)); + p_output.push_back(sformat(return_type->c_out, return_type->c_type_out, C_LOCAL_RET, return_type->name)); } p_output.push_back(CLOSE_BLOCK "\n"); @@ -1752,9 +1582,6 @@ const BindingsGenerator::TypeInterface *BindingsGenerator::_get_type_or_placehol return &placeholder_types.insert(placeholder.cname, placeholder)->get(); } -static void _create_constant_interface_from(const StringName &p_constant, const DocData::ClassDoc &p_classdoc) { -} - void BindingsGenerator::_populate_object_type_interfaces() { obj_types.clear(); @@ -1889,9 +1716,6 @@ void BindingsGenerator::_populate_object_type_interfaces() { if (virtual_method_list.find(method_info)) { // A virtual method without the virtual flag. This is a special case. - // This type of method can only be found in Object derived types. - ERR_FAIL_COND(!itype.is_object_type); - // There is no method bind, so let's fallback to Godot's object.Call(string, params) imethod.requires_object_call = true; @@ -2273,13 +2097,6 @@ void BindingsGenerator::_populate_builtin_type_interfaces() { itype.cs_out = "return new %1(%0);"; itype.im_type_in = "IntPtr"; itype.im_type_out = "IntPtr"; - _populate_builtin_type(itype, Variant::NODE_PATH); - extra_members.insert(itype.cname, MEMBER_BEGIN "public NodePath() : this(string.Empty) {}\n" MEMBER_BEGIN "public NodePath(string path)\n" OPEN_BLOCK_L2 - "this." BINDINGS_PTR_FIELD " = NativeCalls.godot_icall_NodePath_Ctor(path);\n" CLOSE_BLOCK_L2 - MEMBER_BEGIN "public static implicit operator NodePath(string from)\n" OPEN_BLOCK_L2 "return new NodePath(from);\n" CLOSE_BLOCK_L2 - MEMBER_BEGIN "public static implicit operator string(NodePath from)\n" OPEN_BLOCK_L2 - "return NativeCalls." ICALL_PREFIX "NodePath_operator_String(NodePath." CS_SMETHOD_GETINSTANCE "(from));\n" CLOSE_BLOCK_L2 - MEMBER_BEGIN "public override string ToString()\n" OPEN_BLOCK_L2 "return (string)this;\n" CLOSE_BLOCK_L2); builtin_types.insert(itype.cname, itype); // RID @@ -2296,9 +2113,6 @@ void BindingsGenerator::_populate_builtin_type_interfaces() { itype.cs_out = "return new %1(%0);"; itype.im_type_in = "IntPtr"; itype.im_type_out = "IntPtr"; - _populate_builtin_type(itype, Variant::_RID); - extra_members.insert(itype.cname, MEMBER_BEGIN "internal RID()\n" OPEN_BLOCK_L2 - "this." BINDINGS_PTR_FIELD " = IntPtr.Zero;\n" CLOSE_BLOCK_L2); builtin_types.insert(itype.cname, itype); // Variant @@ -2413,60 +2227,6 @@ void BindingsGenerator::_populate_builtin_type_interfaces() { builtin_types.insert(itype.cname, itype); } -void BindingsGenerator::_populate_builtin_type(TypeInterface &r_itype, Variant::Type vtype) { - - Variant::CallError cerror; - Variant v = Variant::construct(vtype, NULL, 0, cerror); - - List<MethodInfo> method_list; - v.get_method_list(&method_list); - method_list.sort(); - - for (List<MethodInfo>::Element *E = method_list.front(); E; E = E->next()) { - MethodInfo &mi = E->get(); - MethodInterface imethod; - - imethod.name = mi.name; - imethod.cname = imethod.name; - imethod.proxy_name = escape_csharp_keyword(snake_to_pascal_case(mi.name)); - - for (int i = 0; i < mi.arguments.size(); i++) { - ArgumentInterface iarg; - PropertyInfo pi = mi.arguments[i]; - - iarg.name = pi.name; - - if (pi.type == Variant::NIL) - iarg.type.cname = name_cache.type_Variant; - else - iarg.type.cname = Variant::get_type_name(pi.type); - - if ((mi.default_arguments.size() - mi.arguments.size() + i) >= 0) - _default_argument_from_variant(Variant::construct(pi.type, NULL, 0, cerror), iarg); - - imethod.add_argument(iarg); - } - - if (mi.return_val.type == Variant::NIL) { - if (mi.return_val.name != "") - imethod.return_type.cname = name_cache.type_Variant; - } else { - imethod.return_type.cname = Variant::get_type_name(mi.return_val.type); - } - - if (r_itype.class_doc) { - for (int i = 0; i < r_itype.class_doc->methods.size(); i++) { - if (r_itype.class_doc->methods[i].name == imethod.name) { - imethod.method_doc = &r_itype.class_doc->methods[i]; - break; - } - } - } - - r_itype.methods.push_back(imethod); - } -} - void BindingsGenerator::_populate_global_constants() { int global_constants_count = GlobalConstants::get_global_constant_count(); @@ -2564,15 +2324,13 @@ void BindingsGenerator::initialize() { _populate_global_constants(); - // Populate internal calls (after populating type interfaces and global constants) + // Generate internal calls (after populating type interfaces and global constants) - _generate_header_icalls(); + core_custom_icalls.clear(); + editor_custom_icalls.clear(); for (OrderedHashMap<StringName, TypeInterface>::Element E = obj_types.front(); E; E = E.next()) _generate_method_icalls(E.get()); - - _generate_method_icalls(builtin_types["NodePath"]); - _generate_method_icalls(builtin_types["RID"]); } void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args) { diff --git a/modules/mono/editor/bindings_generator.h b/modules/mono/editor/bindings_generator.h index 735e7ce7cc..ad89255ba5 100644 --- a/modules/mono/editor/bindings_generator.h +++ b/modules/mono/editor/bindings_generator.h @@ -31,13 +31,13 @@ #ifndef BINDINGS_GENERATOR_H #define BINDINGS_GENERATOR_H -#include "class_db.h" +#include "core/class_db.h" #include "editor/doc/doc_data.h" #include "editor/editor_help.h" #ifdef DEBUG_METHODS_ENABLED -#include "ustring.h" +#include "core/ustring.h" class BindingsGenerator { @@ -456,10 +456,7 @@ class BindingsGenerator { List<EnumInterface> global_enums; List<ConstantInterface> global_constants; - Map<StringName, String> extra_members; - List<InternalCall> method_icalls; - List<InternalCall> builtin_method_icalls; Map<const MethodInterface *, const InternalCall *> method_icalls_map; List<const InternalCall *> generated_icall_funcs; @@ -518,14 +515,12 @@ class BindingsGenerator { String _determine_enum_prefix(const EnumInterface &p_ienum); - void _generate_header_icalls(); void _generate_method_icalls(const TypeInterface &p_itype); const TypeInterface *_get_type_or_null(const TypeReference &p_typeref); const TypeInterface *_get_type_or_placeholder(const TypeReference &p_typeref); void _default_argument_from_variant(const Variant &p_val, ArgumentInterface &r_iarg); - void _populate_builtin_type(TypeInterface &r_itype, Variant::Type vtype); void _populate_object_type_interfaces(); void _populate_builtin_type_interfaces(); @@ -557,7 +552,6 @@ public: Error generate_glue(const String &p_output_dir); static uint32_t get_version(); - static uint32_t get_cs_glue_version(); void initialize(); diff --git a/modules/mono/editor/csharp_project.cpp b/modules/mono/editor/csharp_project.cpp index bc95607743..4764cbe941 100644 --- a/modules/mono/editor/csharp_project.cpp +++ b/modules/mono/editor/csharp_project.cpp @@ -30,8 +30,8 @@ #include "csharp_project.h" -#include "os/os.h" -#include "project_settings.h" +#include "core/os/os.h" +#include "core/project_settings.h" #include "../mono_gd/gd_mono_class.h" #include "../mono_gd/gd_mono_marshal.h" diff --git a/modules/mono/editor/csharp_project.h b/modules/mono/editor/csharp_project.h index 381dd17e02..d852139de0 100644 --- a/modules/mono/editor/csharp_project.h +++ b/modules/mono/editor/csharp_project.h @@ -31,7 +31,7 @@ #ifndef CSHARP_PROJECT_H #define CSHARP_PROJECT_H -#include "ustring.h" +#include "core/ustring.h" namespace CSharpProject { diff --git a/modules/mono/editor/godotsharp_builds.cpp b/modules/mono/editor/godotsharp_builds.cpp index 2faab1718d..b01f8e66c3 100644 --- a/modules/mono/editor/godotsharp_builds.cpp +++ b/modules/mono/editor/godotsharp_builds.cpp @@ -30,8 +30,10 @@ #include "godotsharp_builds.h" +#include "core/vector.h" #include "main/main.h" +#include "../glue/cs_glue_version.gen.h" #include "../godotsharp_dirs.h" #include "../mono_gd/gd_mono_class.h" #include "../mono_gd/gd_mono_marshal.h" @@ -50,6 +52,16 @@ void godot_icall_BuildInstance_ExitCallback(MonoString *p_solution, MonoString * GodotSharpBuilds::get_singleton()->build_exit_callback(MonoBuildInfo(solution, config), p_exit_code); } +static Vector<const char *> _get_msbuild_hint_dirs() { + Vector<const char *> ret; +#ifdef OSX_ENABLED + ret.push_back("/Library/Frameworks/Mono.framework/Versions/Current/bin/"); + ret.push_back("/usr/local/var/homebrew/linked/mono/bin/"); +#endif + ret.push_back("/opt/novell/mono/bin/"); + return ret; +} + #ifdef UNIX_ENABLED String _find_build_engine_on_unix(const String &p_name) { String ret = path_which(p_name); @@ -61,15 +73,9 @@ String _find_build_engine_on_unix(const String &p_name) { if (ret_fallback.length()) return ret_fallback; - const char *locations[] = { -#ifdef OSX_ENABLED - "/Library/Frameworks/Mono.framework/Versions/Current/bin/", - "/usr/local/var/homebrew/linked/mono/bin/", -#endif - "/opt/novell/mono/bin/" - }; + static Vector<const char *> locations = _get_msbuild_hint_dirs(); - for (int i = 0; i < sizeof(locations) / sizeof(const char *); i++) { + for (int i = 0; i < locations.size(); i++) { String hint_path = locations[i] + p_name; if (FileAccess::exists(hint_path)) { @@ -263,7 +269,7 @@ String GodotSharpBuilds::_api_folder_name(APIAssembly::Type p_api_type) { GDMono::get_singleton()->get_api_editor_hash(); return String::num_uint64(api_hash) + "_" + String::num_uint64(BindingsGenerator::get_version()) + - "_" + String::num_uint64(BindingsGenerator::get_cs_glue_version()); + "_" + String::num_uint64(CS_GLUE_VERSION); } bool GodotSharpBuilds::make_api_sln(APIAssembly::Type p_api_type) { diff --git a/modules/mono/editor/mono_bottom_panel.cpp b/modules/mono/editor/mono_bottom_panel.cpp index 9317550d28..ecc3e4c59e 100644 --- a/modules/mono/editor/mono_bottom_panel.cpp +++ b/modules/mono/editor/mono_bottom_panel.cpp @@ -53,9 +53,9 @@ void MonoBottomPanel::_update_build_tabs_list() { build_tabs_list->add_item(item_name, tab->get_icon_texture()); - String item_tooltip = String("Solution: ") + tab->build_info.solution; - item_tooltip += String("\nConfiguration: ") + tab->build_info.configuration; - item_tooltip += String("\nStatus: "); + String item_tooltip = "Solution: " + tab->build_info.solution; + item_tooltip += "\nConfiguration: " + tab->build_info.configuration; + item_tooltip += "\nStatus: "; if (tab->build_exited) { item_tooltip += tab->build_result == MonoBuildTab::RESULT_SUCCESS ? "Succeeded" : "Errored"; diff --git a/modules/mono/editor/monodevelop_instance.h b/modules/mono/editor/monodevelop_instance.h index 552c10a61d..73cf0f54cc 100644 --- a/modules/mono/editor/monodevelop_instance.h +++ b/modules/mono/editor/monodevelop_instance.h @@ -31,7 +31,7 @@ #ifndef MONODEVELOP_INSTANCE_H #define MONODEVELOP_INSTANCE_H -#include "reference.h" +#include "core/reference.h" #include "../mono_gc_handle.h" #include "../mono_gd/gd_mono_method.h" diff --git a/modules/mono/editor/net_solution.cpp b/modules/mono/editor/net_solution.cpp index dab96e44e9..8bbd376c9a 100644 --- a/modules/mono/editor/net_solution.cpp +++ b/modules/mono/editor/net_solution.cpp @@ -30,8 +30,8 @@ #include "net_solution.h" -#include "os/dir_access.h" -#include "os/file_access.h" +#include "core/os/dir_access.h" +#include "core/os/file_access.h" #include "../utils/path_utils.h" #include "../utils/string_utils.h" diff --git a/modules/mono/editor/net_solution.h b/modules/mono/editor/net_solution.h index 293e86917a..bdff24af0b 100644 --- a/modules/mono/editor/net_solution.h +++ b/modules/mono/editor/net_solution.h @@ -31,8 +31,8 @@ #ifndef NET_SOLUTION_H #define NET_SOLUTION_H -#include "map.h" -#include "ustring.h" +#include "core/map.h" +#include "core/ustring.h" struct NETSolution { String name; diff --git a/modules/mono/glue/cs_files/AABB.cs b/modules/mono/glue/Managed/Files/AABB.cs index 0df2e615f1..66490b5e25 100644 --- a/modules/mono/glue/cs_files/AABB.cs +++ b/modules/mono/glue/Managed/Files/AABB.cs @@ -51,24 +51,24 @@ namespace Godot src_max.z > dst_max.z; } - public AABB Expand(Vector3 to_point) + public AABB Expand(Vector3 point) { Vector3 begin = _position; Vector3 end = _position + _size; - if (to_point.x < begin.x) - begin.x = to_point.x; - if (to_point.y < begin.y) - begin.y = to_point.y; - if (to_point.z < begin.z) - begin.z = to_point.z; + if (point.x < begin.x) + begin.x = point.x; + if (point.y < begin.y) + begin.y = point.y; + if (point.z < begin.z) + begin.z = point.z; - if (to_point.x > end.x) - end.x = to_point.x; - if (to_point.y > end.y) - end.y = to_point.y; - if (to_point.z > end.z) - end.z = to_point.z; + if (point.x > end.x) + end.x = point.x; + if (point.y > end.y) + end.y = point.y; + if (point.z > end.z) + end.z = point.z; return new AABB(begin, end - begin); } @@ -347,29 +347,29 @@ namespace Godot for (int i = 0; i < 3; i++) { - real_t seg_from = from[i]; - real_t seg_to = to[i]; - real_t box_begin = _position[i]; - real_t box_end = box_begin + _size[i]; + real_t segFrom = from[i]; + real_t segTo = to[i]; + real_t boxBegin = _position[i]; + real_t boxEnd = boxBegin + _size[i]; real_t cmin, cmax; - if (seg_from < seg_to) + if (segFrom < segTo) { - if (seg_from > box_end || seg_to < box_begin) + if (segFrom > boxEnd || segTo < boxBegin) return false; - real_t length = seg_to - seg_from; - cmin = seg_from < box_begin ? (box_begin - seg_from) / length : 0f; - cmax = seg_to > box_end ? (box_end - seg_from) / length : 1f; + real_t length = segTo - segFrom; + cmin = segFrom < boxBegin ? (boxBegin - segFrom) / length : 0f; + cmax = segTo > boxEnd ? (boxEnd - segFrom) / length : 1f; } else { - if (seg_to > box_end || seg_from < box_begin) + if (segTo > boxEnd || segFrom < boxBegin) return false; - real_t length = seg_to - seg_from; - cmin = seg_from > box_end ? (box_end - seg_from) / length : 0f; - cmax = seg_to < box_begin ? (box_begin - seg_from) / length : 1f; + real_t length = segTo - segFrom; + cmin = segFrom > boxEnd ? (boxEnd - segFrom) / length : 0f; + cmax = segTo < boxBegin ? (boxBegin - segFrom) / length : 1f; } if (cmin > min) @@ -388,21 +388,21 @@ namespace Godot public AABB Merge(AABB with) { - Vector3 beg_1 = _position; - Vector3 beg_2 = with._position; - var end_1 = new Vector3(_size.x, _size.y, _size.z) + beg_1; - var end_2 = new Vector3(with._size.x, with._size.y, with._size.z) + beg_2; + Vector3 beg1 = _position; + Vector3 beg2 = with._position; + var end1 = new Vector3(_size.x, _size.y, _size.z) + beg1; + var end2 = new Vector3(with._size.x, with._size.y, with._size.z) + beg2; var min = new Vector3( - beg_1.x < beg_2.x ? beg_1.x : beg_2.x, - beg_1.y < beg_2.y ? beg_1.y : beg_2.y, - beg_1.z < beg_2.z ? beg_1.z : beg_2.z + beg1.x < beg2.x ? beg1.x : beg2.x, + beg1.y < beg2.y ? beg1.y : beg2.y, + beg1.z < beg2.z ? beg1.z : beg2.z ); var max = new Vector3( - end_1.x > end_2.x ? end_1.x : end_2.x, - end_1.y > end_2.y ? end_1.y : end_2.y, - end_1.z > end_2.z ? end_1.z : end_2.z + end1.x > end2.x ? end1.x : end2.x, + end1.y > end2.y ? end1.y : end2.y, + end1.z > end2.z ? end1.z : end2.z ); return new AABB(min, max - min); diff --git a/modules/mono/glue/cs_files/Array.cs b/modules/mono/glue/Managed/Files/Array.cs index 2f0185b1e3..c80cb7cc83 100644 --- a/modules/mono/glue/cs_files/Array.cs +++ b/modules/mono/glue/Managed/Files/Array.cs @@ -30,45 +30,6 @@ namespace Godot.Collections public class Array : IList<object>, ICollection<object>, IEnumerable<object>, IDisposable { - [MethodImpl(MethodImplOptions.InternalCall)] - internal extern static IntPtr godot_icall_Array_Ctor(); - - [MethodImpl(MethodImplOptions.InternalCall)] - internal extern static void godot_icall_Array_Dtor(IntPtr ptr); - - [MethodImpl(MethodImplOptions.InternalCall)] - internal extern static object godot_icall_Array_At(IntPtr ptr, int index); - - [MethodImpl(MethodImplOptions.InternalCall)] - internal extern static void godot_icall_Array_SetAt(IntPtr ptr, int index, object value); - - [MethodImpl(MethodImplOptions.InternalCall)] - internal extern static int godot_icall_Array_Count(IntPtr ptr); - - [MethodImpl(MethodImplOptions.InternalCall)] - internal extern static void godot_icall_Array_Add(IntPtr ptr, object item); - - [MethodImpl(MethodImplOptions.InternalCall)] - internal extern static void godot_icall_Array_Clear(IntPtr ptr); - - [MethodImpl(MethodImplOptions.InternalCall)] - internal extern static bool godot_icall_Array_Contains(IntPtr ptr, object item); - - [MethodImpl(MethodImplOptions.InternalCall)] - internal extern static void godot_icall_Array_CopyTo(IntPtr ptr, object[] array, int arrayIndex); - - [MethodImpl(MethodImplOptions.InternalCall)] - internal extern static int godot_icall_Array_IndexOf(IntPtr ptr, object item); - - [MethodImpl(MethodImplOptions.InternalCall)] - internal extern static void godot_icall_Array_Insert(IntPtr ptr, int index, object item); - - [MethodImpl(MethodImplOptions.InternalCall)] - internal extern static bool godot_icall_Array_Remove(IntPtr ptr, object item); - - [MethodImpl(MethodImplOptions.InternalCall)] - internal extern static void godot_icall_Array_RemoveAt(IntPtr ptr, int index); - ArraySafeHandle safeHandle; bool disposed = false; @@ -94,11 +55,6 @@ namespace Godot.Collections public void Dispose() { - Dispose(true); - } - - protected virtual void Dispose(bool disposing) - { if (disposed) return; @@ -200,6 +156,45 @@ namespace Godot.Collections { return GetEnumerator(); } + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static IntPtr godot_icall_Array_Ctor(); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static void godot_icall_Array_Dtor(IntPtr ptr); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static object godot_icall_Array_At(IntPtr ptr, int index); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static void godot_icall_Array_SetAt(IntPtr ptr, int index, object value); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static int godot_icall_Array_Count(IntPtr ptr); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static void godot_icall_Array_Add(IntPtr ptr, object item); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static void godot_icall_Array_Clear(IntPtr ptr); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static bool godot_icall_Array_Contains(IntPtr ptr, object item); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static void godot_icall_Array_CopyTo(IntPtr ptr, object[] array, int arrayIndex); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static int godot_icall_Array_IndexOf(IntPtr ptr, object item); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static void godot_icall_Array_Insert(IntPtr ptr, int index, object item); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static bool godot_icall_Array_Remove(IntPtr ptr, object item); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static void godot_icall_Array_RemoveAt(IntPtr ptr, int index); } public class Array<T> : IList<T>, ICollection<T>, IEnumerable<T> diff --git a/modules/mono/glue/cs_files/Attributes/ExportAttribute.cs b/modules/mono/glue/Managed/Files/Attributes/ExportAttribute.cs index 6adf044886..6adf044886 100644 --- a/modules/mono/glue/cs_files/Attributes/ExportAttribute.cs +++ b/modules/mono/glue/Managed/Files/Attributes/ExportAttribute.cs diff --git a/modules/mono/glue/cs_files/Attributes/GodotMethodAttribute.cs b/modules/mono/glue/Managed/Files/Attributes/GodotMethodAttribute.cs index 55848769d5..55848769d5 100644 --- a/modules/mono/glue/cs_files/Attributes/GodotMethodAttribute.cs +++ b/modules/mono/glue/Managed/Files/Attributes/GodotMethodAttribute.cs diff --git a/modules/mono/glue/cs_files/Attributes/RPCAttributes.cs b/modules/mono/glue/Managed/Files/Attributes/RPCAttributes.cs index 6bf9560bfa..6bf9560bfa 100644 --- a/modules/mono/glue/cs_files/Attributes/RPCAttributes.cs +++ b/modules/mono/glue/Managed/Files/Attributes/RPCAttributes.cs diff --git a/modules/mono/glue/cs_files/Attributes/SignalAttribute.cs b/modules/mono/glue/Managed/Files/Attributes/SignalAttribute.cs index 3957387be9..3957387be9 100644 --- a/modules/mono/glue/cs_files/Attributes/SignalAttribute.cs +++ b/modules/mono/glue/Managed/Files/Attributes/SignalAttribute.cs diff --git a/modules/mono/glue/cs_files/Attributes/ToolAttribute.cs b/modules/mono/glue/Managed/Files/Attributes/ToolAttribute.cs index d0437409af..d0437409af 100644 --- a/modules/mono/glue/cs_files/Attributes/ToolAttribute.cs +++ b/modules/mono/glue/Managed/Files/Attributes/ToolAttribute.cs diff --git a/modules/mono/glue/cs_files/Basis.cs b/modules/mono/glue/Managed/Files/Basis.cs index 10286f3832..ec96a9e2fa 100644 --- a/modules/mono/glue/cs_files/Basis.cs +++ b/modules/mono/glue/Managed/Files/Basis.cs @@ -378,51 +378,51 @@ namespace Godot ); } - public Quat Quat() { - real_t trace = _x[0] + _y[1] + _z[2]; - - if (trace > 0.0f) { - real_t s = Mathf.Sqrt(trace + 1.0f) * 2f; - real_t inv_s = 1f / s; - return new Quat( - (_z[1] - _y[2]) * inv_s, - (_x[2] - _z[0]) * inv_s, - (_y[0] - _x[1]) * inv_s, - s * 0.25f - ); - } - - if (_x[0] > _y[1] && _x[0] > _z[2]) { - real_t s = Mathf.Sqrt(_x[0] - _y[1] - _z[2] + 1.0f) * 2f; - real_t inv_s = 1f / s; - return new Quat( - s * 0.25f, - (_x[1] + _y[0]) * inv_s, - (_x[2] + _z[0]) * inv_s, - (_z[1] - _y[2]) * inv_s - ); - } - - if (_y[1] > _z[2]) { - real_t s = Mathf.Sqrt(-_x[0] + _y[1] - _z[2] + 1.0f) * 2f; - real_t inv_s = 1f / s; - return new Quat( - (_x[1] + _y[0]) * inv_s, - s * 0.25f, - (_y[2] + _z[1]) * inv_s, - (_x[2] - _z[0]) * inv_s - ); - } else { - real_t s = Mathf.Sqrt(-_x[0] - _y[1] + _z[2] + 1.0f) * 2f; - real_t inv_s = 1f / s; - return new Quat( - (_x[2] + _z[0]) * inv_s, - (_y[2] + _z[1]) * inv_s, - s * 0.25f, - (_y[0] - _x[1]) * inv_s - ); - } - } + public Quat Quat() { + real_t trace = _x[0] + _y[1] + _z[2]; + + if (trace > 0.0f) { + real_t s = Mathf.Sqrt(trace + 1.0f) * 2f; + real_t inv_s = 1f / s; + return new Quat( + (_z[1] - _y[2]) * inv_s, + (_x[2] - _z[0]) * inv_s, + (_y[0] - _x[1]) * inv_s, + s * 0.25f + ); + } + + if (_x[0] > _y[1] && _x[0] > _z[2]) { + real_t s = Mathf.Sqrt(_x[0] - _y[1] - _z[2] + 1.0f) * 2f; + real_t inv_s = 1f / s; + return new Quat( + s * 0.25f, + (_x[1] + _y[0]) * inv_s, + (_x[2] + _z[0]) * inv_s, + (_z[1] - _y[2]) * inv_s + ); + } + + if (_y[1] > _z[2]) { + real_t s = Mathf.Sqrt(-_x[0] + _y[1] - _z[2] + 1.0f) * 2f; + real_t inv_s = 1f / s; + return new Quat( + (_x[1] + _y[0]) * inv_s, + s * 0.25f, + (_y[2] + _z[1]) * inv_s, + (_x[2] - _z[0]) * inv_s + ); + } else { + real_t s = Mathf.Sqrt(-_x[0] - _y[1] + _z[2] + 1.0f) * 2f; + real_t inv_s = 1f / s; + return new Quat( + (_x[2] + _z[0]) * inv_s, + (_y[2] + _z[1]) * inv_s, + s * 0.25f, + (_y[0] - _x[1]) * inv_s + ); + } + } public Basis(Quat quat) { diff --git a/modules/mono/glue/cs_files/Color.cs b/modules/mono/glue/Managed/Files/Color.cs index 49e04b333a..88cb8524b8 100644 --- a/modules/mono/glue/cs_files/Color.cs +++ b/modules/mono/glue/Managed/Files/Color.cs @@ -370,12 +370,12 @@ namespace Godot { var txt = string.Empty; - txt += _to_hex(r); - txt += _to_hex(g); - txt += _to_hex(b); + txt += ToHex32(r); + txt += ToHex32(g); + txt += ToHex32(b); if (include_alpha) - txt = _to_hex(a) + txt; + txt = ToHex32(a) + txt; return txt; } @@ -411,7 +411,7 @@ namespace Godot r = (rgba & 0xFFFF) / 65535.0f; } - private static int _parse_col(string str, int ofs) + private static int ParseCol8(string str, int ofs) { int ig = 0; @@ -448,7 +448,7 @@ namespace Godot return ig; } - private String _to_hex(float val) + private String ToHex32(float val) { int v = Mathf.RoundToInt(Mathf.Clamp(val * 255, 0, 255)); @@ -490,17 +490,17 @@ namespace Godot if (alpha) { - if (_parse_col(color, 0) < 0) + if (ParseCol8(color, 0) < 0) return false; } int from = alpha ? 2 : 0; - if (_parse_col(color, from + 0) < 0) + if (ParseCol8(color, from + 0) < 0) return false; - if (_parse_col(color, from + 2) < 0) + if (ParseCol8(color, from + 2) < 0) return false; - if (_parse_col(color, from + 4) < 0) + if (ParseCol8(color, from + 4) < 0) return false; return true; @@ -542,7 +542,7 @@ namespace Godot if (alpha) { - a = _parse_col(rgba, 0) / 255f; + a = ParseCol8(rgba, 0) / 255f; if (a < 0) throw new ArgumentOutOfRangeException("Invalid color code. Alpha part is not valid hexadecimal: " + rgba); @@ -554,17 +554,17 @@ namespace Godot int from = alpha ? 2 : 0; - r = _parse_col(rgba, from + 0) / 255f; + r = ParseCol8(rgba, from + 0) / 255f; if (r < 0) throw new ArgumentOutOfRangeException("Invalid color code. Red part is not valid hexadecimal: " + rgba); - g = _parse_col(rgba, from + 2) / 255f; + g = ParseCol8(rgba, from + 2) / 255f; if (g < 0) throw new ArgumentOutOfRangeException("Invalid color code. Green part is not valid hexadecimal: " + rgba); - b = _parse_col(rgba, from + 4) / 255f; + b = ParseCol8(rgba, from + 4) / 255f; if (b < 0) throw new ArgumentOutOfRangeException("Invalid color code. Blue part is not valid hexadecimal: " + rgba); diff --git a/modules/mono/glue/cs_files/DebuggingUtils.cs b/modules/mono/glue/Managed/Files/DebuggingUtils.cs index b27816084e..b27816084e 100644 --- a/modules/mono/glue/cs_files/DebuggingUtils.cs +++ b/modules/mono/glue/Managed/Files/DebuggingUtils.cs diff --git a/modules/mono/glue/cs_files/Dictionary.cs b/modules/mono/glue/Managed/Files/Dictionary.cs index 64cb9f935d..523e48c31a 100644 --- a/modules/mono/glue/cs_files/Dictionary.cs +++ b/modules/mono/glue/Managed/Files/Dictionary.cs @@ -34,48 +34,6 @@ namespace Godot.Collections IEnumerable<KeyValuePair<object, object>>, IDisposable { - [MethodImpl(MethodImplOptions.InternalCall)] - internal extern static IntPtr godot_icall_Dictionary_Ctor(); - - [MethodImpl(MethodImplOptions.InternalCall)] - internal extern static void godot_icall_Dictionary_Dtor(IntPtr ptr); - - [MethodImpl(MethodImplOptions.InternalCall)] - internal extern static object godot_icall_Dictionary_GetValue(IntPtr ptr, object key); - - [MethodImpl(MethodImplOptions.InternalCall)] - internal extern static void godot_icall_Dictionary_SetValue(IntPtr ptr, object key, object value); - - [MethodImpl(MethodImplOptions.InternalCall)] - internal extern static IntPtr godot_icall_Dictionary_Keys(IntPtr ptr); - - [MethodImpl(MethodImplOptions.InternalCall)] - internal extern static IntPtr godot_icall_Dictionary_Values(IntPtr ptr); - - [MethodImpl(MethodImplOptions.InternalCall)] - internal extern static int godot_icall_Dictionary_Count(IntPtr ptr); - - [MethodImpl(MethodImplOptions.InternalCall)] - internal extern static void godot_icall_Dictionary_Add(IntPtr ptr, object key, object value); - - [MethodImpl(MethodImplOptions.InternalCall)] - internal extern static void godot_icall_Dictionary_Clear(IntPtr ptr); - - [MethodImpl(MethodImplOptions.InternalCall)] - internal extern static bool godot_icall_Dictionary_Contains(IntPtr ptr, object key, object value); - - [MethodImpl(MethodImplOptions.InternalCall)] - internal extern static bool godot_icall_Dictionary_ContainsKey(IntPtr ptr, object key); - - [MethodImpl(MethodImplOptions.InternalCall)] - internal extern static bool godot_icall_Dictionary_RemoveKey(IntPtr ptr, object key); - - [MethodImpl(MethodImplOptions.InternalCall)] - internal extern static bool godot_icall_Dictionary_Remove(IntPtr ptr, object key, object value); - - [MethodImpl(MethodImplOptions.InternalCall)] - internal extern static bool godot_icall_Dictionary_TryGetValue(IntPtr ptr, object key, out object value); - DictionarySafeHandle safeHandle; bool disposed = false; @@ -101,11 +59,6 @@ namespace Godot.Collections public void Dispose() { - Dispose(true); - } - - protected virtual void Dispose(bool disposing) - { if (disposed) return; @@ -240,8 +193,49 @@ namespace Godot.Collections { return GetEnumerator(); } - } + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static IntPtr godot_icall_Dictionary_Ctor(); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static void godot_icall_Dictionary_Dtor(IntPtr ptr); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static object godot_icall_Dictionary_GetValue(IntPtr ptr, object key); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static void godot_icall_Dictionary_SetValue(IntPtr ptr, object key, object value); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static IntPtr godot_icall_Dictionary_Keys(IntPtr ptr); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static IntPtr godot_icall_Dictionary_Values(IntPtr ptr); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static int godot_icall_Dictionary_Count(IntPtr ptr); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static void godot_icall_Dictionary_Add(IntPtr ptr, object key, object value); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static void godot_icall_Dictionary_Clear(IntPtr ptr); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static bool godot_icall_Dictionary_Contains(IntPtr ptr, object key, object value); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static bool godot_icall_Dictionary_ContainsKey(IntPtr ptr, object key); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static bool godot_icall_Dictionary_RemoveKey(IntPtr ptr, object key); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static bool godot_icall_Dictionary_Remove(IntPtr ptr, object key, object value); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static bool godot_icall_Dictionary_TryGetValue(IntPtr ptr, object key, out object value); + } public class Dictionary<TKey, TValue> : IDictionary<TKey, TValue>, diff --git a/modules/mono/glue/cs_files/Extensions/NodeExtensions.cs b/modules/mono/glue/Managed/Files/Extensions/NodeExtensions.cs index 71534d7782..71534d7782 100644 --- a/modules/mono/glue/cs_files/Extensions/NodeExtensions.cs +++ b/modules/mono/glue/Managed/Files/Extensions/NodeExtensions.cs diff --git a/modules/mono/glue/cs_files/Extensions/ObjectExtensions.cs b/modules/mono/glue/Managed/Files/Extensions/ObjectExtensions.cs index 5c9e6609f4..9ef0959750 100644 --- a/modules/mono/glue/cs_files/Extensions/ObjectExtensions.cs +++ b/modules/mono/glue/Managed/Files/Extensions/ObjectExtensions.cs @@ -1,4 +1,5 @@ using System; +using System.Runtime.CompilerServices; namespace Godot { @@ -11,7 +12,10 @@ namespace Godot public static WeakRef WeakRef(Object obj) { - return NativeCalls.godot_icall_Godot_weakref(Object.GetPtr(obj)); + return godot_icall_Object_weakref(Object.GetPtr(obj)); } + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static WeakRef godot_icall_Object_weakref(IntPtr obj); } } diff --git a/modules/mono/glue/cs_files/Extensions/ResourceLoaderExtensions.cs b/modules/mono/glue/Managed/Files/Extensions/ResourceLoaderExtensions.cs index ceecc589e6..ceecc589e6 100644 --- a/modules/mono/glue/cs_files/Extensions/ResourceLoaderExtensions.cs +++ b/modules/mono/glue/Managed/Files/Extensions/ResourceLoaderExtensions.cs diff --git a/modules/mono/glue/cs_files/GD.cs b/modules/mono/glue/Managed/Files/GD.cs index 0a5d703f27..264be23588 100644 --- a/modules/mono/glue/cs_files/GD.cs +++ b/modules/mono/glue/Managed/Files/GD.cs @@ -1,11 +1,12 @@ using System; +using System.Runtime.CompilerServices; #if REAL_T_IS_DOUBLE using real_t = System.Double; #else using real_t = System.Single; #endif -// TODO: Add comments describing what this class does. It is not obvious. +// TODO: Add comments describing what this class does. It is not obvious. namespace Godot { @@ -13,12 +14,12 @@ namespace Godot { public static object Bytes2Var(byte[] bytes) { - return NativeCalls.godot_icall_Godot_bytes2var(bytes); + return godot_icall_GD_bytes2var(bytes); } public static object Convert(object what, int type) { - return NativeCalls.godot_icall_Godot_convert(what, type); + return godot_icall_GD_convert(what, type); } public static real_t Db2Linear(real_t db) @@ -46,12 +47,12 @@ namespace Godot public static int Hash(object var) { - return NativeCalls.godot_icall_Godot_hash(var); + return godot_icall_GD_hash(var); } public static Object InstanceFromId(int instanceId) { - return NativeCalls.godot_icall_Godot_instance_from_id(instanceId); + return godot_icall_GD_instance_from_id(instanceId); } public static real_t Linear2Db(real_t linear) @@ -71,7 +72,7 @@ namespace Godot public static void Print(params object[] what) { - NativeCalls.godot_icall_Godot_print(what); + godot_icall_GD_print(what); } public static void PrintStack() @@ -81,22 +82,22 @@ namespace Godot public static void PrintErr(params object[] what) { - NativeCalls.godot_icall_Godot_printerr(what); + godot_icall_GD_printerr(what); } public static void PrintRaw(params object[] what) { - NativeCalls.godot_icall_Godot_printraw(what); + godot_icall_GD_printraw(what); } public static void PrintS(params object[] what) { - NativeCalls.godot_icall_Godot_prints(what); + godot_icall_GD_prints(what); } public static void PrintT(params object[] what) { - NativeCalls.godot_icall_Godot_printt(what); + godot_icall_GD_printt(what); } public static int[] Range(int length) @@ -165,32 +166,77 @@ namespace Godot public static void Seed(int seed) { - NativeCalls.godot_icall_Godot_seed(seed); + godot_icall_GD_seed(seed); } public static string Str(params object[] what) { - return NativeCalls.godot_icall_Godot_str(what); + return godot_icall_GD_str(what); } public static object Str2Var(string str) { - return NativeCalls.godot_icall_Godot_str2var(str); + return godot_icall_GD_str2var(str); } public static bool TypeExists(string type) { - return NativeCalls.godot_icall_Godot_type_exists(type); + return godot_icall_GD_type_exists(type); } public static byte[] Var2Bytes(object var) { - return NativeCalls.godot_icall_Godot_var2bytes(var); + return godot_icall_GD_var2bytes(var); } public static string Var2Str(object var) { - return NativeCalls.godot_icall_Godot_var2str(var); + return godot_icall_GD_var2str(var); } + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static object godot_icall_GD_bytes2var(byte[] bytes); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static object godot_icall_GD_convert(object what, int type); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static int godot_icall_GD_hash(object var); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static Object godot_icall_GD_instance_from_id(int instance_id); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static void godot_icall_GD_print(object[] what); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static void godot_icall_GD_printerr(object[] what); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static void godot_icall_GD_printraw(object[] what); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static void godot_icall_GD_prints(object[] what); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static void godot_icall_GD_printt(object[] what); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static void godot_icall_GD_seed(int seed); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static string godot_icall_GD_str(object[] what); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static object godot_icall_GD_str2var(string str); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static bool godot_icall_GD_type_exists(string type); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static byte[] godot_icall_GD_var2bytes(object what); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static string godot_icall_GD_var2str(object var); } } diff --git a/modules/mono/glue/Managed/Files/GodotSynchronizationContext.cs b/modules/mono/glue/Managed/Files/GodotSynchronizationContext.cs new file mode 100644 index 0000000000..e727781d63 --- /dev/null +++ b/modules/mono/glue/Managed/Files/GodotSynchronizationContext.cs @@ -0,0 +1,25 @@ +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Threading; + +namespace Godot +{ + public class GodotSynchronizationContext : SynchronizationContext + { + private readonly BlockingCollection<KeyValuePair<SendOrPostCallback, object>> queue = new BlockingCollection<KeyValuePair<SendOrPostCallback, object>>(); + + public override void Post(SendOrPostCallback d, object state) + { + queue.Add(new KeyValuePair<SendOrPostCallback, object>(d, state)); + } + + public void ExecutePendingContinuations() + { + KeyValuePair<SendOrPostCallback, object> workItem; + while (queue.TryTake(out workItem)) + { + workItem.Key(workItem.Value); + } + } + } +} diff --git a/modules/mono/glue/Managed/Files/GodotTaskScheduler.cs b/modules/mono/glue/Managed/Files/GodotTaskScheduler.cs new file mode 100644 index 0000000000..9a40fef5a9 --- /dev/null +++ b/modules/mono/glue/Managed/Files/GodotTaskScheduler.cs @@ -0,0 +1,94 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace Godot +{ + public class GodotTaskScheduler : TaskScheduler + { + private GodotSynchronizationContext Context { get; set; } + private readonly LinkedList<Task> _tasks = new LinkedList<Task>(); + + public GodotTaskScheduler() + { + Context = new GodotSynchronizationContext(); + SynchronizationContext.SetSynchronizationContext(Context); + } + + protected sealed override void QueueTask(Task task) + { + lock (_tasks) + { + _tasks.AddLast(task); + } + } + + protected sealed override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued) + { + if (SynchronizationContext.Current != Context) + { + return false; + } + + if (taskWasPreviouslyQueued) + { + TryDequeue(task); + } + + return TryExecuteTask(task); + } + + protected sealed override bool TryDequeue(Task task) + { + lock (_tasks) + { + return _tasks.Remove(task); + } + } + + protected sealed override IEnumerable<Task> GetScheduledTasks() + { + lock (_tasks) + { + return _tasks.ToArray(); + } + } + + public void Activate() + { + ExecuteQueuedTasks(); + Context.ExecutePendingContinuations(); + } + + private void ExecuteQueuedTasks() + { + while (true) + { + Task task; + + lock (_tasks) + { + if (_tasks.Any()) + { + task = _tasks.First.Value; + _tasks.RemoveFirst(); + } + else + { + break; + } + } + + if (task != null) + { + if (!TryExecuteTask(task)) + { + throw new InvalidOperationException(); + } + } + } + } + } +} diff --git a/modules/mono/glue/cs_files/Interfaces/IAwaitable.cs b/modules/mono/glue/Managed/Files/Interfaces/IAwaitable.cs index 0397957d00..0397957d00 100644 --- a/modules/mono/glue/cs_files/Interfaces/IAwaitable.cs +++ b/modules/mono/glue/Managed/Files/Interfaces/IAwaitable.cs diff --git a/modules/mono/glue/cs_files/Interfaces/IAwaiter.cs b/modules/mono/glue/Managed/Files/Interfaces/IAwaiter.cs index d3be9d781c..d3be9d781c 100644 --- a/modules/mono/glue/cs_files/Interfaces/IAwaiter.cs +++ b/modules/mono/glue/Managed/Files/Interfaces/IAwaiter.cs diff --git a/modules/mono/glue/cs_files/MarshalUtils.cs b/modules/mono/glue/Managed/Files/MarshalUtils.cs index f7699a15bf..f7699a15bf 100644 --- a/modules/mono/glue/cs_files/MarshalUtils.cs +++ b/modules/mono/glue/Managed/Files/MarshalUtils.cs diff --git a/modules/mono/glue/cs_files/Mathf.cs b/modules/mono/glue/Managed/Files/Mathf.cs index a89dfe5f27..a89dfe5f27 100644 --- a/modules/mono/glue/cs_files/Mathf.cs +++ b/modules/mono/glue/Managed/Files/Mathf.cs diff --git a/modules/mono/glue/cs_files/MathfEx.cs b/modules/mono/glue/Managed/Files/MathfEx.cs index 739b7fb568..739b7fb568 100644 --- a/modules/mono/glue/cs_files/MathfEx.cs +++ b/modules/mono/glue/Managed/Files/MathfEx.cs diff --git a/modules/mono/glue/Managed/Files/NodePath.cs b/modules/mono/glue/Managed/Files/NodePath.cs new file mode 100644 index 0000000000..2c89bec87f --- /dev/null +++ b/modules/mono/glue/Managed/Files/NodePath.cs @@ -0,0 +1,147 @@ +using System; +using System.Runtime.CompilerServices; + +namespace Godot +{ + public partial class NodePath : IDisposable + { + private bool disposed = false; + + internal IntPtr ptr; + + internal static IntPtr GetPtr(NodePath instance) + { + return instance == null ? IntPtr.Zero : instance.ptr; + } + + ~NodePath() + { + Dispose(false); + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + if (disposed) + return; + + if (ptr != IntPtr.Zero) + { + godot_icall_NodePath_Dtor(ptr); + ptr = IntPtr.Zero; + } + + disposed = true; + } + + internal NodePath(IntPtr ptr) + { + this.ptr = ptr; + } + + public IntPtr NativeInstance + { + get { return ptr; } + } + + public NodePath() : this(string.Empty) {} + + public NodePath(string path) + { + this.ptr = godot_icall_NodePath_Ctor(path); + } + + public static implicit operator NodePath(string from) + { + return new NodePath(from); + } + + public static implicit operator string(NodePath from) + { + return godot_icall_NodePath_operator_String(NodePath.GetPtr(from)); + } + + public override string ToString() + { + return (string)this; + } + + public NodePath GetAsPropertyPath() + { + return new NodePath(godot_icall_NodePath_get_as_property_path(NodePath.GetPtr(this))); + } + + public string GetConcatenatedSubnames() + { + return godot_icall_NodePath_get_concatenated_subnames(NodePath.GetPtr(this)); + } + + public string GetName(int idx) + { + return godot_icall_NodePath_get_name(NodePath.GetPtr(this), idx); + } + + public int GetNameCount() + { + return godot_icall_NodePath_get_name_count(NodePath.GetPtr(this)); + } + + public string GetSubname(int idx) + { + return godot_icall_NodePath_get_subname(NodePath.GetPtr(this), idx); + } + + public int GetSubnameCount() + { + return godot_icall_NodePath_get_subname_count(NodePath.GetPtr(this)); + } + + public bool IsAbsolute() + { + return godot_icall_NodePath_is_absolute(NodePath.GetPtr(this)); + } + + public bool IsEmpty() + { + return godot_icall_NodePath_is_empty(NodePath.GetPtr(this)); + } + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static IntPtr godot_icall_NodePath_Ctor(string path); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static void godot_icall_NodePath_Dtor(IntPtr ptr); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static string godot_icall_NodePath_operator_String(IntPtr ptr); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static IntPtr godot_icall_NodePath_get_as_property_path(IntPtr ptr); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static string godot_icall_NodePath_get_concatenated_subnames(IntPtr ptr); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static string godot_icall_NodePath_get_name(IntPtr ptr, int arg1); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static int godot_icall_NodePath_get_name_count(IntPtr ptr); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static string godot_icall_NodePath_get_subname(IntPtr ptr, int arg1); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static int godot_icall_NodePath_get_subname_count(IntPtr ptr); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static bool godot_icall_NodePath_is_absolute(IntPtr ptr); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static bool godot_icall_NodePath_is_empty(IntPtr ptr); + } +} diff --git a/modules/mono/glue/Managed/Files/Object.base.cs b/modules/mono/glue/Managed/Files/Object.base.cs new file mode 100644 index 0000000000..30490a715f --- /dev/null +++ b/modules/mono/glue/Managed/Files/Object.base.cs @@ -0,0 +1,88 @@ +using System; +using System.Runtime.CompilerServices; + +namespace Godot +{ + public partial class Object : IDisposable + { + private bool disposed = false; + + private const string nativeName = "Object"; + + internal IntPtr ptr; + internal bool memoryOwn; + + public Object() : this(false) + { + if (ptr == IntPtr.Zero) + ptr = godot_icall_Object_Ctor(this); + } + + internal Object(bool memoryOwn) + { + this.memoryOwn = memoryOwn; + } + + public IntPtr NativeInstance + { + get { return ptr; } + } + + internal static IntPtr GetPtr(Object instance) + { + return instance == null ? IntPtr.Zero : instance.ptr; + } + + ~Object() + { + Dispose(false); + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + if (disposed) + return; + + if (ptr != IntPtr.Zero) + { + if (memoryOwn) + { + memoryOwn = false; + godot_icall_Reference_Disposed(this, ptr, !disposing); + } + else + { + godot_icall_Object_Disposed(this, ptr); + } + + this.ptr = IntPtr.Zero; + } + + disposed = true; + } + + public SignalAwaiter ToSignal(Object source, string signal) + { + return new SignalAwaiter(source, signal, this); + } + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static IntPtr godot_icall_Object_Ctor(Object obj); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static void godot_icall_Object_Disposed(Object obj, IntPtr ptr); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static void godot_icall_Reference_Disposed(Object obj, IntPtr ptr, bool isFinalizer); + + // Used by the generated API + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static IntPtr godot_icall_Object_ClassDB_get_method(string type, string method); + } +} diff --git a/modules/mono/glue/cs_files/Plane.cs b/modules/mono/glue/Managed/Files/Plane.cs index 9611dce11e..9611dce11e 100644 --- a/modules/mono/glue/cs_files/Plane.cs +++ b/modules/mono/glue/Managed/Files/Plane.cs diff --git a/modules/mono/glue/cs_files/Quat.cs b/modules/mono/glue/Managed/Files/Quat.cs index eaa027eb69..eaa027eb69 100644 --- a/modules/mono/glue/cs_files/Quat.cs +++ b/modules/mono/glue/Managed/Files/Quat.cs diff --git a/modules/mono/glue/Managed/Files/RID.cs b/modules/mono/glue/Managed/Files/RID.cs new file mode 100644 index 0000000000..b862b8cac0 --- /dev/null +++ b/modules/mono/glue/Managed/Files/RID.cs @@ -0,0 +1,76 @@ +using System; +using System.Runtime.CompilerServices; + +namespace Godot +{ + public partial class RID : IDisposable + { + private bool disposed = false; + + internal IntPtr ptr; + + internal static IntPtr GetPtr(RID instance) + { + return instance == null ? IntPtr.Zero : instance.ptr; + } + + ~RID() + { + Dispose(false); + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + if (disposed) + return; + + if (ptr != IntPtr.Zero) + { + godot_icall_RID_Dtor(ptr); + ptr = IntPtr.Zero; + } + + disposed = true; + } + + internal RID(IntPtr ptr) + { + this.ptr = ptr; + } + + public IntPtr NativeInstance + { + get { return ptr; } + } + + internal RID() + { + this.ptr = IntPtr.Zero; + } + + public RID(Object from) + { + this.ptr = godot_icall_RID_Ctor(Object.GetPtr(from)); + } + + public int GetId() + { + return godot_icall_RID_get_id(RID.GetPtr(this)); + } + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static IntPtr godot_icall_RID_Ctor(IntPtr from); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static void godot_icall_RID_Dtor(IntPtr ptr); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static int godot_icall_RID_get_id(IntPtr ptr); + } +} diff --git a/modules/mono/glue/cs_files/Rect2.cs b/modules/mono/glue/Managed/Files/Rect2.cs index cb25c267bc..cb25c267bc 100644 --- a/modules/mono/glue/cs_files/Rect2.cs +++ b/modules/mono/glue/Managed/Files/Rect2.cs diff --git a/modules/mono/glue/cs_files/SignalAwaiter.cs b/modules/mono/glue/Managed/Files/SignalAwaiter.cs index c06f6b05c9..9483b6ffb4 100644 --- a/modules/mono/glue/cs_files/SignalAwaiter.cs +++ b/modules/mono/glue/Managed/Files/SignalAwaiter.cs @@ -1,4 +1,5 @@ using System; +using System.Runtime.CompilerServices; namespace Godot { @@ -10,12 +11,12 @@ namespace Godot public SignalAwaiter(Object source, string signal, Object target) { - NativeCalls.godot_icall_Object_connect_signal_awaiter( - Object.GetPtr(source), - signal, Object.GetPtr(target), this - ); + godot_icall_SignalAwaiter_connect(Object.GetPtr(source), signal, Object.GetPtr(target), this); } + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static Error godot_icall_SignalAwaiter_connect(IntPtr source, string signal, IntPtr target, SignalAwaiter awaiter); + public bool IsCompleted { get diff --git a/modules/mono/glue/cs_files/StringExtensions.cs b/modules/mono/glue/Managed/Files/StringExtensions.cs index b58f8bc6a8..21c9be98c1 100644 --- a/modules/mono/glue/cs_files/StringExtensions.cs +++ b/modules/mono/glue/Managed/Files/StringExtensions.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Globalization; +using System.Runtime.CompilerServices; using System.Security; using System.Text; using System.Text.RegularExpressions; @@ -26,7 +27,7 @@ namespace Godot return slices; } - private static string GetSlicec(this string instance, char splitter, int slice) + private static string GetSliceCharacter(this string instance, char splitter, int slice) { if (!instance.Empty() && slice >= 0) { @@ -36,12 +37,18 @@ namespace Godot while (true) { - if (instance[i] == 0 || instance[i] == splitter) + bool end = instance.Length <= i; + + if (end || instance[i] == splitter) { if (slice == count) { return instance.Substring(prev, i - prev); } + else if (end) + { + return string.Empty; + } count++; prev = i + 1; @@ -57,7 +64,7 @@ namespace Godot // <summary> // If the string is a path to a file, return the path to the file without the extension. // </summary> - public static string Basename(this string instance) + public static string BaseName(this string instance) { int index = instance.LastIndexOf('.'); @@ -144,7 +151,7 @@ namespace Godot for (int i = 0; i < aux.GetSliceCount(" "); i++) { - string slice = aux.GetSlicec(' ', i); + string slice = aux.GetSliceCharacter(' ', i); if (slice.Length > 0) { slice = char.ToUpper(slice[0]) + slice.Substring(1); @@ -162,30 +169,59 @@ namespace Godot // </summary> public static int CasecmpTo(this string instance, string to) { + return instance.CompareTo(to, true); + } + + // <summary> + // Perform a comparison to another string, return -1 if less, 0 if equal and +1 if greater. + // </summary> + public static int CompareTo(this string instance, string to, bool caseSensitive = true) + { if (instance.Empty()) return to.Empty() ? 0 : -1; if (to.Empty()) return 1; - int instance_idx = 0; - int to_idx = 0; - - while (true) + int instanceIndex = 0; + int toIndex = 0; + + if (caseSensitive) // Outside while loop to avoid checking multiple times, despite some code duplication. { - if (to[to_idx] == 0 && instance[instance_idx] == 0) - return 0; // We're equal - if (instance[instance_idx] == 0) - return -1; // If this is empty, and the other one is not, then we're less... I think? - if (to[to_idx] == 0) - return 1; // Otherwise the other one is smaller... - if (instance[instance_idx] < to[to_idx]) // More than - return -1; - if (instance[instance_idx] > to[to_idx]) // Less than - return 1; - - instance_idx++; - to_idx++; + while (true) + { + if (to[toIndex] == 0 && instance[instanceIndex] == 0) + return 0; // We're equal + if (instance[instanceIndex] == 0) + return -1; // If this is empty, and the other one is not, then we're less... I think? + if (to[toIndex] == 0) + return 1; // Otherwise the other one is smaller... + if (instance[instanceIndex] < to[toIndex]) // More than + return -1; + if (instance[instanceIndex] > to[toIndex]) // Less than + return 1; + + instanceIndex++; + toIndex++; + } + } else + { + while (true) + { + if (to[toIndex] == 0 && instance[instanceIndex] == 0) + return 0; // We're equal + if (instance[instanceIndex] == 0) + return -1; // If this is empty, and the other one is not, then we're less... I think? + if (to[toIndex] == 0) + return 1; // Otherwise the other one is smaller.. + if (char.ToUpper(instance[instanceIndex]) < char.ToUpper(to[toIndex])) // More than + return -1; + if (char.ToUpper(instance[instanceIndex]) > char.ToUpper(to[toIndex])) // Less than + return 1; + + instanceIndex++; + toIndex++; + } } } @@ -361,7 +397,7 @@ namespace Godot // <summary> // Check whether this string is a subsequence of the given string. // </summary> - public static bool IsSubsequenceOf(this string instance, string text, bool case_insensitive) + public static bool IsSubsequenceOf(this string instance, string text, bool caseSensitive = true) { int len = instance.Length; @@ -371,50 +407,42 @@ namespace Godot if (len > text.Length) return false; - int src = 0; - int tgt = 0; + int source = 0; + int target = 0; - while (instance[src] != 0 && text[tgt] != 0) + while (instance[source] != 0 && text[target] != 0) { bool match; - if (case_insensitive) + if (!caseSensitive) { - char srcc = char.ToLower(instance[src]); - char tgtc = char.ToLower(text[tgt]); - match = srcc == tgtc; + char sourcec = char.ToLower(instance[source]); + char targetc = char.ToLower(text[target]); + match = sourcec == targetc; } else { - match = instance[src] == text[tgt]; + match = instance[source] == text[target]; } if (match) { - src++; - if (instance[src] == 0) + source++; + if (instance[source] == 0) return true; } - tgt++; + target++; } return false; } // <summary> - // Check whether this string is a subsequence of the given string, considering case. - // </summary> - public static bool IsSubsequenceOf(this string instance, string text) - { - return instance.IsSubsequenceOf(text, false); - } - - // <summary> - // Check whether this string is a subsequence of the given string, without considering case. + // Check whether this string is a subsequence of the given string, ignoring case differences. // </summary> public static bool IsSubsequenceOfI(this string instance, string text) { - return instance.IsSubsequenceOf(text, true); + return instance.IsSubsequenceOf(text, false); } // <summary> @@ -452,12 +480,12 @@ namespace Godot return false; // Don't start with number plz } - bool valid_char = instance[i] >= '0' && + bool validChar = instance[i] >= '0' && instance[i] <= '9' || instance[i] >= 'a' && instance[i] <= 'z' || instance[i] >= 'A' && instance[i] <= 'Z' || instance[i] == '_'; - if (!valid_char) + if (!validChar) return false; } @@ -476,8 +504,9 @@ namespace Godot // <summary> // Check whether the string contains a valid IP address. // </summary> - public static bool IsValidIpAddress(this string instance) + public static bool IsValidIPAddress(this string instance) { + // TODO: Support IPv6 addresses string[] ip = instance.Split("."); if (ip.Length != 4) @@ -500,7 +529,7 @@ namespace Godot // <summary> // Return a copy of the string with special characters escaped using the JSON standard. // </summary> - public static string JsonEscape(this string instance) + public static string JSONEscape(this string instance) { var sb = new StringBuilder(string.Copy(instance)); @@ -563,15 +592,15 @@ namespace Godot // <summary> // Do a simple case sensitive expression match, using ? and * wildcards (see [method expr_match]). // </summary> - public static bool Match(this string instance, string expr) + public static bool Match(this string instance, string expr, bool caseSensitive = true) { - return instance.ExprMatch(expr, true); + return instance.ExprMatch(expr, caseSensitive); } // <summary> // Do a simple case insensitive expression match, using ? and * wildcards (see [method expr_match]). // </summary> - public static bool Matchn(this string instance, string expr) + public static bool MatchN(this string instance, string expr) { return instance.ExprMatch(expr, false); } @@ -579,49 +608,31 @@ namespace Godot // <summary> // Return the MD5 hash of the string as an array of bytes. // </summary> - public static byte[] Md5Buffer(this string instance) + public static byte[] MD5Buffer(this string instance) { - return NativeCalls.godot_icall_String_md5_buffer(instance); + return godot_icall_String_md5_buffer(instance); } + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static byte[] godot_icall_String_md5_buffer(string str); + // <summary> // Return the MD5 hash of the string as a string. // </summary> - public static string Md5Text(this string instance) + public static string MD5Text(this string instance) { - return NativeCalls.godot_icall_String_md5_text(instance); + return godot_icall_String_md5_text(instance); } + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static string godot_icall_String_md5_text(string str); + // <summary> // Perform a case-insensitive comparison to another string, return -1 if less, 0 if equal and +1 if greater. // </summary> public static int NocasecmpTo(this string instance, string to) { - if (instance.Empty()) - return to.Empty() ? 0 : -1; - - if (to.Empty()) - return 1; - - int instance_idx = 0; - int to_idx = 0; - - while (true) - { - if (to[to_idx] == 0 && instance[instance_idx] == 0) - return 0; // We're equal - if (instance[instance_idx] == 0) - return -1; // If this is empty, and the other one is not, then we're less... I think? - if (to[to_idx] == 0) - return 1; // Otherwise the other one is smaller.. - if (char.ToUpper(instance[instance_idx]) < char.ToUpper(to[to_idx])) // More than - return -1; - if (char.ToUpper(instance[instance_idx]) > char.ToUpper(to[to_idx])) // Less than - return 1; - - instance_idx++; - to_idx++; - } + return instance.CompareTo(to, false); } // <summary> @@ -738,7 +749,7 @@ namespace Godot // <summary> // Replace occurrences of a substring for different ones inside the string, but search case-insensitive. // </summary> - public static string Replacen(this string instance, string what, string forwhat) + public static string ReplaceN(this string instance, string what, string forwhat) { return Regex.Replace(instance, what, forwhat, RegexOptions.IgnoreCase); } @@ -746,19 +757,25 @@ namespace Godot // <summary> // Perform a search for a substring, but start from the end of the string instead of the beginning. // </summary> - public static int Rfind(this string instance, string what, int from = -1) + public static int RFind(this string instance, string what, int from = -1) { - return NativeCalls.godot_icall_String_rfind(instance, what, from); + return godot_icall_String_rfind(instance, what, from); } + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static int godot_icall_String_rfind(string str, string what, int from); + // <summary> // Perform a search for a substring, but start from the end of the string instead of the beginning. Also search case-insensitive. // </summary> - public static int Rfindn(this string instance, string what, int from = -1) + public static int RFindN(this string instance, string what, int from = -1) { - return NativeCalls.godot_icall_String_rfindn(instance, what, from); + return godot_icall_String_rfindn(instance, what, from); } + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static int godot_icall_String_rfindn(string str, string what, int from); + // <summary> // Return the right side of the string from a given position. // </summary> @@ -773,19 +790,25 @@ namespace Godot return instance.Substring(pos, instance.Length - pos); } - public static byte[] Sha256Buffer(this string instance) + public static byte[] SHA256Buffer(this string instance) { - return NativeCalls.godot_icall_String_sha256_buffer(instance); + return godot_icall_String_sha256_buffer(instance); } + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static byte[] godot_icall_String_sha256_buffer(string str); + // <summary> // Return the SHA-256 hash of the string as a string. // </summary> - public static string Sha256Text(this string instance) + public static string SHA256Text(this string instance) { - return NativeCalls.godot_icall_String_sha256_text(instance); + return godot_icall_String_sha256_text(instance); } + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static string godot_icall_String_sha256_text(string str); + // <summary> // Return the similarity index of the text compared to this string. 1 means totally similar and 0 means totally dissimilar. // </summary> @@ -802,20 +825,20 @@ namespace Godot return 0.0f; } - string[] srcBigrams = instance.Bigrams(); - string[] tgtBigrams = text.Bigrams(); + string[] sourceBigrams = instance.Bigrams(); + string[] targetBigrams = text.Bigrams(); - int src_size = srcBigrams.Length; - int tgt_size = tgtBigrams.Length; + int sourceSize = sourceBigrams.Length; + int targetSize = targetBigrams.Length; - float sum = src_size + tgt_size; + float sum = sourceSize + targetSize; float inter = 0; - for (int i = 0; i < src_size; i++) + for (int i = 0; i < sourceSize; i++) { - for (int j = 0; j < tgt_size; j++) + for (int j = 0; j < targetSize; j++) { - if (srcBigrams[i] == tgtBigrams[j]) + if (sourceBigrams[i] == targetBigrams[j]) { inter++; break; @@ -829,7 +852,7 @@ namespace Godot // <summary> // Split the string by a divisor string, return an array of the substrings. Example "One,Two,Three" will return ["One","Two","Three"] if split by ",". // </summary> - public static string[] Split(this string instance, string divisor, bool allow_empty = true) + public static string[] Split(this string instance, string divisor, bool allowEmpty = true) { return instance.Split(new[] { divisor }, StringSplitOptions.RemoveEmptyEntries); } @@ -837,7 +860,7 @@ namespace Godot // <summary> // Split the string in floats by using a divisor string, return an array of the substrings. Example "1,2.5,3" will return [1,2.5,3] if split by ",". // </summary> - public static float[] SplitFloats(this string instance, string divisor, bool allow_empty = true) + public static float[] SplitFloats(this string instance, string divisor, bool allowEmpty = true) { var ret = new List<float>(); int from = 0; @@ -848,7 +871,7 @@ namespace Godot int end = instance.Find(divisor, from); if (end < 0) end = len; - if (allow_empty || end > from) + if (allowEmpty || end > from) ret.Add(float.Parse(instance.Substring(from))); if (end == len) break; @@ -859,7 +882,7 @@ namespace Godot return ret.ToArray(); } - private static readonly char[] non_printable = { + private static readonly char[] _nonPrintable = { (char)00, (char)01, (char)02, (char)03, (char)04, (char)05, (char)06, (char)07, (char)08, (char)09, (char)10, (char)11, (char)12, (char)13, (char)14, (char)15, (char)16, (char)17, @@ -876,11 +899,11 @@ namespace Godot if (left) { if (right) - return instance.Trim(non_printable); - return instance.TrimStart(non_printable); + return instance.Trim(_nonPrintable); + return instance.TrimStart(_nonPrintable); } - return instance.TrimEnd(non_printable); + return instance.TrimEnd(_nonPrintable); } // <summary> @@ -934,7 +957,7 @@ namespace Godot // <summary> // Convert the String (which is an array of characters) to PoolByteArray (which is an array of bytes). The conversion is a bit slower than to_ascii(), but supports all UTF-8 characters. Therefore, you should prefer this function over to_ascii(). // </summary> - public static byte[] ToUtf8(this string instance) + public static byte[] ToUTF8(this string instance) { return Encoding.UTF8.GetBytes(instance); } @@ -942,7 +965,7 @@ namespace Godot // <summary> // Return a copy of the string with special characters escaped using the XML standard. // </summary> - public static string XmlEscape(this string instance) + public static string XMLEscape(this string instance) { return SecurityElement.Escape(instance); } @@ -950,7 +973,7 @@ namespace Godot // <summary> // Return a copy of the string with escaped characters replaced by their meanings according to the XML standard. // </summary> - public static string XmlUnescape(this string instance) + public static string XMLUnescape(this string instance) { return SecurityElement.FromString(instance).Text; } diff --git a/modules/mono/glue/cs_files/Transform.cs b/modules/mono/glue/Managed/Files/Transform.cs index e432d5b52c..e432d5b52c 100644 --- a/modules/mono/glue/cs_files/Transform.cs +++ b/modules/mono/glue/Managed/Files/Transform.cs diff --git a/modules/mono/glue/cs_files/Transform2D.cs b/modules/mono/glue/Managed/Files/Transform2D.cs index 8d30833066..8d30833066 100644 --- a/modules/mono/glue/cs_files/Transform2D.cs +++ b/modules/mono/glue/Managed/Files/Transform2D.cs diff --git a/modules/mono/glue/cs_files/Vector2.cs b/modules/mono/glue/Managed/Files/Vector2.cs index 080b8802ba..080b8802ba 100644 --- a/modules/mono/glue/cs_files/Vector2.cs +++ b/modules/mono/glue/Managed/Files/Vector2.cs diff --git a/modules/mono/glue/cs_files/Vector3.cs b/modules/mono/glue/Managed/Files/Vector3.cs index 6fffe5e4d6..6fffe5e4d6 100644 --- a/modules/mono/glue/cs_files/Vector3.cs +++ b/modules/mono/glue/Managed/Files/Vector3.cs diff --git a/modules/mono/glue/Managed/IgnoredFiles/Enums.cs b/modules/mono/glue/Managed/IgnoredFiles/Enums.cs new file mode 100644 index 0000000000..05f1abcf93 --- /dev/null +++ b/modules/mono/glue/Managed/IgnoredFiles/Enums.cs @@ -0,0 +1,21 @@ + +namespace Godot +{ + public enum Margin + { + Left = 0, + Top = 1, + Right = 2, + Bottom = 3 + } + + public enum Error + { + Ok = 0 + } + + public enum PropertyHint + { + None = 0 + } +} diff --git a/modules/mono/glue/Managed/IgnoredFiles/FuncRef.cs b/modules/mono/glue/Managed/IgnoredFiles/FuncRef.cs new file mode 100644 index 0000000000..83504fe49f --- /dev/null +++ b/modules/mono/glue/Managed/IgnoredFiles/FuncRef.cs @@ -0,0 +1,17 @@ +using System; + +namespace Godot +{ + public partial class FuncRef + { + public void SetInstance(Object instance) + { + throw new NotImplementedException(); + } + + public void SetFunction(string name) + { + throw new NotImplementedException(); + } + } +} diff --git a/modules/mono/glue/Managed/IgnoredFiles/Node.cs b/modules/mono/glue/Managed/IgnoredFiles/Node.cs new file mode 100644 index 0000000000..99ba0f827a --- /dev/null +++ b/modules/mono/glue/Managed/IgnoredFiles/Node.cs @@ -0,0 +1,28 @@ + +using System; + +namespace Godot +{ + public partial class Node + { + public Node GetChild(int idx) + { + throw new NotImplementedException(); + } + + public Node GetNode(NodePath path) + { + throw new NotImplementedException(); + } + + public Node GetOwner() + { + throw new NotImplementedException(); + } + + public Node GetParent() + { + throw new NotImplementedException(); + } + } +} diff --git a/modules/mono/glue/Managed/IgnoredFiles/Resource.cs b/modules/mono/glue/Managed/IgnoredFiles/Resource.cs new file mode 100644 index 0000000000..cc0a5555b1 --- /dev/null +++ b/modules/mono/glue/Managed/IgnoredFiles/Resource.cs @@ -0,0 +1,7 @@ +namespace Godot +{ + public partial class Resource + { + + } +} diff --git a/modules/mono/glue/Managed/IgnoredFiles/ResourceLoader.cs b/modules/mono/glue/Managed/IgnoredFiles/ResourceLoader.cs new file mode 100644 index 0000000000..6461d35146 --- /dev/null +++ b/modules/mono/glue/Managed/IgnoredFiles/ResourceLoader.cs @@ -0,0 +1,12 @@ +using System; + +namespace Godot +{ + public partial class ResourceLoader + { + public static Resource Load(string path, string typeHint = "", bool pNoCache = false) + { + throw new NotImplementedException(); + } + } +} diff --git a/modules/mono/glue/Managed/IgnoredFiles/WeakRef.cs b/modules/mono/glue/Managed/IgnoredFiles/WeakRef.cs new file mode 100644 index 0000000000..1498b7836b --- /dev/null +++ b/modules/mono/glue/Managed/IgnoredFiles/WeakRef.cs @@ -0,0 +1,7 @@ +namespace Godot +{ + public partial class WeakRef + { + + } +} diff --git a/modules/mono/glue/Managed/Managed.csproj b/modules/mono/glue/Managed/Managed.csproj new file mode 100644 index 0000000000..1f82dde5e7 --- /dev/null +++ b/modules/mono/glue/Managed/Managed.csproj @@ -0,0 +1,40 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">x86</Platform> + <ProjectGuid>{DAA3DEF8-5112-407C-A5E5-6C608CF5F955}</ProjectGuid> + <OutputType>Library</OutputType> + <RootNamespace>Managed</RootNamespace> + <AssemblyName>Managed</AssemblyName> + <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\Debug</OutputPath> + <DefineConstants>DEBUG;</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <ExternalConsole>true</ExternalConsole> + <PlatformTarget>x86</PlatformTarget> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' "> + <Optimize>true</Optimize> + <OutputPath>bin\Release</OutputPath> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <ExternalConsole>true</ExternalConsole> + <PlatformTarget>x86</PlatformTarget> + </PropertyGroup> + <ItemGroup> + <Reference Include="System" /> + </ItemGroup> + <ItemGroup> + <Compile Include="Files\**\*.cs" /> + <Compile Include="IgnoredFiles\**\*.cs" /> + <Compile Include="Properties\AssemblyInfo.cs" /> + </ItemGroup> + <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> +</Project> diff --git a/modules/mono/glue/Managed/Managed.sln b/modules/mono/glue/Managed/Managed.sln new file mode 100644 index 0000000000..61ddde0fb7 --- /dev/null +++ b/modules/mono/glue/Managed/Managed.sln @@ -0,0 +1,17 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Managed", "Managed.csproj", "{DAA3DEF8-5112-407C-A5E5-6C608CF5F955}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x86 = Debug|x86 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {DAA3DEF8-5112-407C-A5E5-6C608CF5F955}.Debug|x86.ActiveCfg = Debug|x86 + {DAA3DEF8-5112-407C-A5E5-6C608CF5F955}.Debug|x86.Build.0 = Debug|x86 + {DAA3DEF8-5112-407C-A5E5-6C608CF5F955}.Release|x86.ActiveCfg = Release|x86 + {DAA3DEF8-5112-407C-A5E5-6C608CF5F955}.Release|x86.Build.0 = Release|x86 + EndGlobalSection +EndGlobal diff --git a/modules/mono/glue/Managed/Properties/AssemblyInfo.cs b/modules/mono/glue/Managed/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..7ed68acad7 --- /dev/null +++ b/modules/mono/glue/Managed/Properties/AssemblyInfo.cs @@ -0,0 +1,26 @@ +using System.Reflection; +using System.Runtime.CompilerServices; + +// Information about this assembly is defined by the following attributes. +// Change them to the values specific to your project. + +[assembly: AssemblyTitle("Managed")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". +// The form "{Major}.{Minor}.*" will automatically update the build and revision, +// and "{Major}.{Minor}.{Build}.*" will update just the revision. + +[assembly: AssemblyVersion("1.0.*")] + +// The following attributes are used to specify the signing key for the assembly, +// if desired. See the Mono documentation for more information about signing. + +//[assembly: AssemblyDelaySign(false)] +//[assembly: AssemblyKeyFile("")] diff --git a/modules/mono/glue/Managed/README.md b/modules/mono/glue/Managed/README.md new file mode 100644 index 0000000000..65e63cae37 --- /dev/null +++ b/modules/mono/glue/Managed/README.md @@ -0,0 +1,5 @@ +The directory `Files` contains C# files from the core assembly project that are not part of the generated API. Any file with the `.cs` extension in this directory will be added to the core assembly project. + +A dummy solution and project is provided to get tooling help while editing these files, like code completion and name refactoring. + +The directory `IgnoredFiles` contains C# files that are needed to build the dummy project but must not be added to the core assembly project. They contain placeholders for the declarations that are part of the generated API. diff --git a/modules/mono/glue/base_object_glue.cpp b/modules/mono/glue/base_object_glue.cpp new file mode 100644 index 0000000000..d718c3cc61 --- /dev/null +++ b/modules/mono/glue/base_object_glue.cpp @@ -0,0 +1,154 @@ +/*************************************************************************/ +/* base_object_glue.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "base_object_glue.h" + +#ifdef MONO_GLUE_ENABLED + +#include "core/reference.h" +#include "core/string_db.h" + +#include "../csharp_script.h" +#include "../mono_gd/gd_mono_internals.h" +#include "../mono_gd/gd_mono_utils.h" +#include "../signal_awaiter_utils.h" + +Object *godot_icall_Object_Ctor(MonoObject *p_obj) { + Object *instance = memnew(Object); + GDMonoInternals::tie_managed_to_unmanaged(p_obj, instance); + return instance; +} + +void godot_icall_Object_Disposed(MonoObject *p_obj, Object *p_ptr) { +#ifdef DEBUG_ENABLED + CRASH_COND(p_ptr == NULL); +#endif + + if (p_ptr->get_script_instance()) { + CSharpInstance *cs_instance = CAST_CSHARP_INSTANCE(p_ptr->get_script_instance()); + if (cs_instance) { + cs_instance->mono_object_disposed(p_obj); + p_ptr->set_script_instance(NULL); + return; + } + } + + void *data = p_ptr->get_script_instance_binding(CSharpLanguage::get_singleton()->get_language_index()); + + if (data) { + Ref<MonoGCHandle> &gchandle = ((Map<Object *, CSharpScriptBinding>::Element *)data)->get().gchandle; + if (gchandle.is_valid()) { + CSharpLanguage::release_script_gchandle(p_obj, gchandle); + } + } +} + +void godot_icall_Reference_Disposed(MonoObject *p_obj, Object *p_ptr, bool p_is_finalizer) { +#ifdef DEBUG_ENABLED + CRASH_COND(p_ptr == NULL); + // This is only called with Reference derived classes + CRASH_COND(!Object::cast_to<Reference>(p_ptr)); +#endif + + Reference *ref = static_cast<Reference *>(p_ptr); + + if (ref->get_script_instance()) { + CSharpInstance *cs_instance = CAST_CSHARP_INSTANCE(ref->get_script_instance()); + if (cs_instance) { + bool r_owner_deleted; + cs_instance->mono_object_disposed_baseref(p_obj, p_is_finalizer, r_owner_deleted); + if (!r_owner_deleted && !p_is_finalizer) { + // If the native instance is still alive and Dispose() was called + // (instead of the finalizer), then we remove the script instance. + ref->set_script_instance(NULL); + } + return; + } + } + + // Unsafe refcount decrement. The managed instance also counts as a reference. + // See: CSharpLanguage::alloc_instance_binding_data(Object *p_object) + if (ref->unreference()) { + memdelete(ref); + } else { + void *data = ref->get_script_instance_binding(CSharpLanguage::get_singleton()->get_language_index()); + + if (data) { + Ref<MonoGCHandle> &gchandle = ((Map<Object *, CSharpScriptBinding>::Element *)data)->get().gchandle; + if (gchandle.is_valid()) { + CSharpLanguage::release_script_gchandle(p_obj, gchandle); + } + } + } +} + +MethodBind *godot_icall_Object_ClassDB_get_method(MonoString *p_type, MonoString *p_method) { + StringName type(GDMonoMarshal::mono_string_to_godot(p_type)); + StringName method(GDMonoMarshal::mono_string_to_godot(p_method)); + return ClassDB::get_method(type, method); +} + +MonoObject *godot_icall_Object_weakref(Object *p_obj) { + if (!p_obj) + return NULL; + + Ref<WeakRef> wref; + Reference *ref = Object::cast_to<Reference>(p_obj); + + if (ref) { + REF r = ref; + if (!r.is_valid()) + return NULL; + + wref.instance(); + wref->set_ref(r); + } else { + wref.instance(); + wref->set_obj(p_obj); + } + + return GDMonoUtils::create_managed_for_godot_object(CACHED_CLASS(WeakRef), Reference::get_class_static(), Object::cast_to<Object>(wref.ptr())); +} + +Error godot_icall_SignalAwaiter_connect(Object *p_source, MonoString *p_signal, Object *p_target, MonoObject *p_awaiter) { + String signal = GDMonoMarshal::mono_string_to_godot(p_signal); + return SignalAwaiterUtils::connect_signal_awaiter(p_source, signal, p_target, p_awaiter); +} + +void godot_register_object_icalls() { + mono_add_internal_call("Godot.Object::godot_icall_Object_Ctor", (void *)godot_icall_Object_Ctor); + mono_add_internal_call("Godot.Object::godot_icall_Object_Disposed", (void *)godot_icall_Object_Disposed); + mono_add_internal_call("Godot.Object::godot_icall_Reference_Disposed", (void *)godot_icall_Reference_Disposed); + mono_add_internal_call("Godot.Object::godot_icall_Object_ClassDB_get_method", (void *)godot_icall_Object_ClassDB_get_method); + mono_add_internal_call("Godot.Object::godot_icall_Object_weakref", (void *)godot_icall_Object_weakref); + mono_add_internal_call("Godot.SignalAwaiter::godot_icall_SignalAwaiter_connect", (void *)godot_icall_SignalAwaiter_connect); +} + +#endif // MONO_GLUE_ENABLED diff --git a/modules/mono/glue/base_object_glue.h b/modules/mono/glue/base_object_glue.h new file mode 100644 index 0000000000..2d4d66ebb8 --- /dev/null +++ b/modules/mono/glue/base_object_glue.h @@ -0,0 +1,59 @@ +/*************************************************************************/ +/* base_object_glue.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef BASE_OBJECT_GLUE_H +#define BASE_OBJECT_GLUE_H + +#ifdef MONO_GLUE_ENABLED + +#include "core/class_db.h" +#include "core/object.h" + +#include "../mono_gd/gd_mono_marshal.h" + +Object *godot_icall_Object_Ctor(MonoObject *p_obj); + +void godot_icall_Object_Disposed(MonoObject *p_obj, Object *p_ptr); + +void godot_icall_Reference_Disposed(MonoObject *p_obj, Object *p_ptr, bool p_is_finalizer); + +MethodBind *godot_icall_Object_ClassDB_get_method(MonoString *p_type, MonoString *p_method); + +MonoObject *godot_icall_Object_weakref(Object *p_obj); + +Error godot_icall_SignalAwaiter_connect(Object *p_source, MonoString *p_signal, Object *p_target, MonoObject *p_awaiter); + +// Register internal calls + +void godot_register_object_icalls(); + +#endif // MONO_GLUE_ENABLED + +#endif // BASE_OBJECT_GLUE_H diff --git a/modules/mono/glue/collections_glue.cpp b/modules/mono/glue/collections_glue.cpp index bb218b49b7..d9dba1c60d 100644 --- a/modules/mono/glue/collections_glue.cpp +++ b/modules/mono/glue/collections_glue.cpp @@ -30,9 +30,12 @@ #include "collections_glue.h" +#ifdef MONO_GLUE_ENABLED + #include <mono/metadata/exception.h> #include "../mono_gd/gd_mono_class.h" +#include "../mono_gd/gd_mono_utils.h" Array *godot_icall_Array_Ctor() { return memnew(Array); @@ -238,3 +241,5 @@ void godot_register_collections_icalls() { mono_add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Remove", (void *)godot_icall_Dictionary_Remove); mono_add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_TryGetValue", (void *)godot_icall_Dictionary_TryGetValue); } + +#endif // MONO_GLUE_ENABLED diff --git a/modules/mono/glue/collections_glue.h b/modules/mono/glue/collections_glue.h index eb5ecfb725..fa8e4c28aa 100644 --- a/modules/mono/glue/collections_glue.h +++ b/modules/mono/glue/collections_glue.h @@ -31,6 +31,8 @@ #ifndef COLLECTIONS_GLUE_H #define COLLECTIONS_GLUE_H +#ifdef MONO_GLUE_ENABLED + #include "core/array.h" #include "../mono_gd/gd_mono_marshal.h" @@ -97,4 +99,6 @@ bool godot_icall_Dictionary_TryGetValue(Dictionary *ptr, MonoObject *key, MonoOb void godot_register_collections_icalls(); +#endif // MONO_GLUE_ENABLED + #endif // COLLECTIONS_GLUE_H diff --git a/modules/mono/glue/cs_files/GodotSynchronizationContext.cs b/modules/mono/glue/cs_files/GodotSynchronizationContext.cs deleted file mode 100644 index da3c7bac83..0000000000 --- a/modules/mono/glue/cs_files/GodotSynchronizationContext.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Threading; - -namespace Godot -{ - public class GodotSynchronizationContext : SynchronizationContext - { - private readonly BlockingCollection<KeyValuePair<SendOrPostCallback, object>> queue = new BlockingCollection<KeyValuePair<SendOrPostCallback, object>>(); - - public override void Post(SendOrPostCallback d, object state) - { - queue.Add(new KeyValuePair<SendOrPostCallback, object>(d, state)); - } - - public void ExecutePendingContinuations() - { - KeyValuePair<SendOrPostCallback, object> workItem; - while (queue.TryTake(out workItem)) - { - workItem.Key(workItem.Value); - } - } - } -} diff --git a/modules/mono/glue/cs_files/GodotTaskScheduler.cs b/modules/mono/glue/cs_files/GodotTaskScheduler.cs deleted file mode 100644 index 3d23ec10f1..0000000000 --- a/modules/mono/glue/cs_files/GodotTaskScheduler.cs +++ /dev/null @@ -1,94 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; - -namespace Godot -{ - public class GodotTaskScheduler : TaskScheduler - { - private GodotSynchronizationContext Context { get; set; } - private readonly LinkedList<Task> _tasks = new LinkedList<Task>(); - - public GodotTaskScheduler() - { - Context = new GodotSynchronizationContext(); - SynchronizationContext.SetSynchronizationContext(Context); - } - - protected sealed override void QueueTask(Task task) - { - lock (_tasks) - { - _tasks.AddLast(task); - } - } - - protected sealed override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued) - { - if (SynchronizationContext.Current != Context) - { - return false; - } - - if (taskWasPreviouslyQueued) - { - TryDequeue(task); - } - - return TryExecuteTask(task); - } - - protected sealed override bool TryDequeue(Task task) - { - lock (_tasks) - { - return _tasks.Remove(task); - } - } - - protected sealed override IEnumerable<Task> GetScheduledTasks() - { - lock (_tasks) - { - return _tasks.ToArray(); - } - } - - public void Activate() - { - ExecuteQueuedTasks(); - Context.ExecutePendingContinuations(); - } - - private void ExecuteQueuedTasks() - { - while (true) - { - Task task; - - lock (_tasks) - { - if (_tasks.Any()) - { - task = _tasks.First.Value; - _tasks.RemoveFirst(); - } - else - { - break; - } - } - - if (task != null) - { - if (!TryExecuteTask(task)) - { - throw new InvalidOperationException(); - } - } - } - } - } -} diff --git a/modules/mono/glue/gd_glue.cpp b/modules/mono/glue/gd_glue.cpp new file mode 100644 index 0000000000..051f42b966 --- /dev/null +++ b/modules/mono/glue/gd_glue.cpp @@ -0,0 +1,202 @@ +/*************************************************************************/ +/* gd_glue.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "gd_glue.h" + +#ifdef MONO_GLUE_ENABLED + +#include "core/array.h" +#include "core/io/marshalls.h" +#include "core/os/os.h" +#include "core/ustring.h" +#include "core/variant.h" +#include "core/variant_parser.h" + +#include "../mono_gd/gd_mono_utils.h" + +MonoObject *godot_icall_GD_bytes2var(MonoArray *p_bytes) { + Variant ret; + PoolByteArray varr = GDMonoMarshal::mono_array_to_PoolByteArray(p_bytes); + PoolByteArray::Read r = varr.read(); + Error err = decode_variant(ret, r.ptr(), varr.size(), NULL); + if (err != OK) { + ret = RTR("Not enough bytes for decoding bytes, or invalid format."); + } + return GDMonoMarshal::variant_to_mono_object(ret); +} + +MonoObject *godot_icall_GD_convert(MonoObject *p_what, int p_type) { + Variant what = GDMonoMarshal::mono_object_to_variant(p_what); + const Variant *args[1] = { &what }; + Variant::CallError ce; + Variant ret = Variant::construct(Variant::Type(p_type), args, 1, ce); + ERR_FAIL_COND_V(ce.error != Variant::CallError::CALL_OK, NULL); + return GDMonoMarshal::variant_to_mono_object(ret); +} + +int godot_icall_GD_hash(MonoObject *p_var) { + return GDMonoMarshal::mono_object_to_variant(p_var).hash(); +} + +MonoObject *godot_icall_GD_instance_from_id(int p_instance_id) { + return GDMonoUtils::unmanaged_get_managed(ObjectDB::get_instance(p_instance_id)); +} + +void godot_icall_GD_print(MonoArray *p_what) { + Array what = GDMonoMarshal::mono_array_to_Array(p_what); + String str; + for (int i = 0; i < what.size(); i++) + str += what[i].operator String(); + print_line(str); +} + +void godot_icall_GD_printerr(MonoArray *p_what) { + Array what = GDMonoMarshal::mono_array_to_Array(p_what); + String str; + for (int i = 0; i < what.size(); i++) + str += what[i].operator String(); + OS::get_singleton()->printerr("%s\n", str.utf8().get_data()); +} + +void godot_icall_GD_printraw(MonoArray *p_what) { + Array what = GDMonoMarshal::mono_array_to_Array(p_what); + String str; + for (int i = 0; i < what.size(); i++) + str += what[i].operator String(); + OS::get_singleton()->print("%s", str.utf8().get_data()); +} + +void godot_icall_GD_prints(MonoArray *p_what) { + Array what = GDMonoMarshal::mono_array_to_Array(p_what); + String str; + for (int i = 0; i < what.size(); i++) { + if (i) + str += " "; + str += what[i].operator String(); + } + print_line(str); +} + +void godot_icall_GD_printt(MonoArray *p_what) { + Array what = GDMonoMarshal::mono_array_to_Array(p_what); + String str; + for (int i = 0; i < what.size(); i++) { + if (i) + str += "\t"; + str += what[i].operator String(); + } + print_line(str); +} + +void godot_icall_GD_seed(int p_seed) { + Math::seed(p_seed); +} + +MonoString *godot_icall_GD_str(MonoArray *p_what) { + String str; + Array what = GDMonoMarshal::mono_array_to_Array(p_what); + + for (int i = 0; i < what.size(); i++) { + String os = what[i].operator String(); + + if (i == 0) + str = os; + else + str += os; + } + + return GDMonoMarshal::mono_string_from_godot(str); +} + +MonoObject *godot_icall_GD_str2var(MonoString *p_str) { + Variant ret; + + VariantParser::StreamString ss; + ss.s = GDMonoMarshal::mono_string_to_godot(p_str); + + String errs; + int line; + Error err = VariantParser::parse(&ss, ret, errs, line); + if (err != OK) { + String err_str = "Parse error at line " + itos(line) + ": " + errs; + ERR_PRINTS(err_str); + ret = err_str; + } + + return GDMonoMarshal::variant_to_mono_object(ret); +} + +bool godot_icall_GD_type_exists(MonoString *p_type) { + return ClassDB::class_exists(GDMonoMarshal::mono_string_to_godot(p_type)); +} + +MonoArray *godot_icall_GD_var2bytes(MonoObject *p_var) { + Variant var = GDMonoMarshal::mono_object_to_variant(p_var); + + PoolByteArray barr; + int len; + Error err = encode_variant(var, NULL, len); + ERR_EXPLAIN("Unexpected error encoding variable to bytes, likely unserializable type found (Object or RID)."); + ERR_FAIL_COND_V(err != OK, NULL); + + barr.resize(len); + { + PoolByteArray::Write w = barr.write(); + encode_variant(var, w.ptr(), len); + } + + return GDMonoMarshal::PoolByteArray_to_mono_array(barr); +} + +MonoString *godot_icall_GD_var2str(MonoObject *p_var) { + String vars; + VariantWriter::write_to_string(GDMonoMarshal::mono_object_to_variant(p_var), vars); + return GDMonoMarshal::mono_string_from_godot(vars); +} + +void godot_register_gd_icalls() { + mono_add_internal_call("Godot.GD::godot_icall_GD_bytes2var", (void *)godot_icall_GD_bytes2var); + mono_add_internal_call("Godot.GD::godot_icall_GD_convert", (void *)godot_icall_GD_convert); + mono_add_internal_call("Godot.GD::godot_icall_GD_hash", (void *)godot_icall_GD_hash); + mono_add_internal_call("Godot.GD::godot_icall_GD_instance_from_id", (void *)godot_icall_GD_instance_from_id); + mono_add_internal_call("Godot.GD::godot_icall_GD_print", (void *)godot_icall_GD_print); + mono_add_internal_call("Godot.GD::godot_icall_GD_printerr", (void *)godot_icall_GD_printerr); + mono_add_internal_call("Godot.GD::godot_icall_GD_printraw", (void *)godot_icall_GD_printraw); + mono_add_internal_call("Godot.GD::godot_icall_GD_prints", (void *)godot_icall_GD_prints); + mono_add_internal_call("Godot.GD::godot_icall_GD_printt", (void *)godot_icall_GD_printt); + mono_add_internal_call("Godot.GD::godot_icall_GD_seed", (void *)godot_icall_GD_seed); + mono_add_internal_call("Godot.GD::godot_icall_GD_str", (void *)godot_icall_GD_str); + mono_add_internal_call("Godot.GD::godot_icall_GD_str2var", (void *)godot_icall_GD_str2var); + mono_add_internal_call("Godot.GD::godot_icall_GD_type_exists", (void *)godot_icall_GD_type_exists); + mono_add_internal_call("Godot.GD::godot_icall_GD_var2bytes", (void *)godot_icall_GD_var2bytes); + mono_add_internal_call("Godot.GD::godot_icall_GD_var2str", (void *)godot_icall_GD_var2str); +} + +#endif // MONO_GLUE_ENABLED diff --git a/modules/mono/glue/gd_glue.h b/modules/mono/glue/gd_glue.h new file mode 100644 index 0000000000..6f846f221d --- /dev/null +++ b/modules/mono/glue/gd_glue.h @@ -0,0 +1,74 @@ +/*************************************************************************/ +/* gd_glue.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef GD_GLUE_H +#define GD_GLUE_H + +#ifdef MONO_GLUE_ENABLED + +#include "../mono_gd/gd_mono_marshal.h" + +MonoObject *godot_icall_GD_bytes2var(MonoArray *p_bytes); + +MonoObject *godot_icall_GD_convert(MonoObject *p_what, int p_type); + +int godot_icall_GD_hash(MonoObject *p_var); + +MonoObject *godot_icall_GD_instance_from_id(int p_instance_id); + +void godot_icall_GD_print(MonoArray *p_what); + +void godot_icall_GD_printerr(MonoArray *p_what); + +void godot_icall_GD_printraw(MonoArray *p_what); + +void godot_icall_GD_prints(MonoArray *p_what); + +void godot_icall_GD_printt(MonoArray *p_what); + +void godot_icall_GD_seed(int p_seed); + +MonoString *godot_icall_GD_str(MonoArray *p_what); + +MonoObject *godot_icall_GD_str2var(MonoString *p_str); + +bool godot_icall_GD_type_exists(MonoString *p_type); + +MonoArray *godot_icall_GD_var2bytes(MonoObject *p_var); + +MonoString *godot_icall_GD_var2str(MonoObject *p_var); + +// Register internal calls + +void godot_register_gd_icalls(); + +#endif // MONO_GLUE_ENABLED + +#endif // GD_GLUE_H diff --git a/modules/mono/glue/glue_header.h b/modules/mono/glue/glue_header.h index 6a6f3062b4..69c5c6dcdb 100644 --- a/modules/mono/glue/glue_header.h +++ b/modules/mono/glue/glue_header.h @@ -28,27 +28,44 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "builtin_types_glue.h" +#ifdef MONO_GLUE_ENABLED + +#include "base_object_glue.h" #include "collections_glue.h" +#include "gd_glue.h" +#include "nodepath_glue.h" +#include "rid_glue.h" +#include "string_glue.h" + +/** + * Registers internal calls that were not generated. This function is called + * from the generated GodotSharpBindings::register_generated_icalls() function. + */ +void godot_register_glue_header_icalls() { + godot_register_collections_icalls(); + godot_register_gd_icalls(); + godot_register_nodepath_icalls(); + godot_register_object_icalls(); + godot_register_rid_icalls(); + godot_register_string_icalls(); +} + +// Used by the generated glue + +#include "core/array.h" +#include "core/class_db.h" +#include "core/dictionary.h" +#include "core/engine.h" +#include "core/method_bind.h" +#include "core/node_path.h" +#include "core/object.h" +#include "core/reference.h" +#include "core/typedefs.h" +#include "core/ustring.h" -#include "../csharp_script.h" #include "../mono_gd/gd_mono_class.h" #include "../mono_gd/gd_mono_internals.h" -#include "../mono_gd/gd_mono_marshal.h" -#include "../signal_awaiter_utils.h" - -#include "bind/core_bind.h" -#include "class_db.h" -#include "engine.h" -#include "io/marshalls.h" -#include "object.h" -#include "os/os.h" -#include "reference.h" -#include "variant_parser.h" - -#ifdef TOOLS_ENABLED -#include "editor/editor_node.h" -#endif +#include "../mono_gd/gd_mono_utils.h" #define GODOTSHARP_INSTANCE_OBJECT(m_instance, m_type) \ static ClassDB::ClassInfo *ci = NULL; \ @@ -57,257 +74,4 @@ } \ Object *m_instance = ci->creation_func(); -void godot_icall_Object_Dtor(MonoObject *obj, Object *ptr) { -#ifdef DEBUG_ENABLED - CRASH_COND(ptr == NULL); -#endif - _GodotSharp::get_singleton()->queue_dispose(obj, ptr); -} - -// -- ClassDB -- - -MethodBind *godot_icall_ClassDB_get_method(MonoString *p_type, MonoString *p_method) { - StringName type(GDMonoMarshal::mono_string_to_godot(p_type)); - StringName method(GDMonoMarshal::mono_string_to_godot(p_method)); - return ClassDB::get_method(type, method); -} - -// -- SignalAwaiter -- - -Error godot_icall_Object_connect_signal_awaiter(Object *p_source, MonoString *p_signal, Object *p_target, MonoObject *p_awaiter) { - String signal = GDMonoMarshal::mono_string_to_godot(p_signal); - return SignalAwaiterUtils::connect_signal_awaiter(p_source, signal, p_target, p_awaiter); -} - -// -- NodePath -- - -NodePath *godot_icall_NodePath_Ctor(MonoString *p_path) { - return memnew(NodePath(GDMonoMarshal::mono_string_to_godot(p_path))); -} - -void godot_icall_NodePath_Dtor(NodePath *p_ptr) { - ERR_FAIL_NULL(p_ptr); - _GodotSharp::get_singleton()->queue_dispose(p_ptr); -} - -MonoString *godot_icall_NodePath_operator_String(NodePath *p_np) { - return GDMonoMarshal::mono_string_from_godot(p_np->operator String()); -} - -// -- RID -- - -RID *godot_icall_RID_Ctor(Object *p_from) { - Resource *res_from = Object::cast_to<Resource>(p_from); - - if (res_from) - return memnew(RID(res_from->get_rid())); - - return memnew(RID); -} - -void godot_icall_RID_Dtor(RID *p_ptr) { - ERR_FAIL_NULL(p_ptr); - _GodotSharp::get_singleton()->queue_dispose(p_ptr); -} - -// -- String -- - -MonoArray *godot_icall_String_md5_buffer(MonoString *p_str) { - Vector<uint8_t> ret = GDMonoMarshal::mono_string_to_godot(p_str).md5_buffer(); - // TODO Check possible Array/Vector<uint8_t> problem? - return GDMonoMarshal::Array_to_mono_array(Variant(ret)); -} - -MonoString *godot_icall_String_md5_text(MonoString *p_str) { - String ret = GDMonoMarshal::mono_string_to_godot(p_str).md5_text(); - return GDMonoMarshal::mono_string_from_godot(ret); -} - -int godot_icall_String_rfind(MonoString *p_str, MonoString *p_what, int p_from) { - String what = GDMonoMarshal::mono_string_to_godot(p_what); - return GDMonoMarshal::mono_string_to_godot(p_str).rfind(what, p_from); -} - -int godot_icall_String_rfindn(MonoString *p_str, MonoString *p_what, int p_from) { - String what = GDMonoMarshal::mono_string_to_godot(p_what); - return GDMonoMarshal::mono_string_to_godot(p_str).rfindn(what, p_from); -} - -MonoArray *godot_icall_String_sha256_buffer(MonoString *p_str) { - Vector<uint8_t> ret = GDMonoMarshal::mono_string_to_godot(p_str).sha256_buffer(); - return GDMonoMarshal::Array_to_mono_array(Variant(ret)); -} - -MonoString *godot_icall_String_sha256_text(MonoString *p_str) { - String ret = GDMonoMarshal::mono_string_to_godot(p_str).sha256_text(); - return GDMonoMarshal::mono_string_from_godot(ret); -} - -// -- Global Scope -- - -MonoObject *godot_icall_Godot_bytes2var(MonoArray *p_bytes) { - Variant ret; - PoolByteArray varr = GDMonoMarshal::mono_array_to_PoolByteArray(p_bytes); - PoolByteArray::Read r = varr.read(); - Error err = decode_variant(ret, r.ptr(), varr.size(), NULL); - if (err != OK) { - ret = RTR("Not enough bytes for decoding bytes, or invalid format."); - } - return GDMonoMarshal::variant_to_mono_object(ret); -} - -MonoObject *godot_icall_Godot_convert(MonoObject *p_what, int p_type) { - Variant what = GDMonoMarshal::mono_object_to_variant(p_what); - const Variant *args[1] = { &what }; - Variant::CallError ce; - Variant ret = Variant::construct(Variant::Type(p_type), args, 1, ce); - ERR_FAIL_COND_V(ce.error != Variant::CallError::CALL_OK, NULL); - return GDMonoMarshal::variant_to_mono_object(ret); -} - -int godot_icall_Godot_hash(MonoObject *p_var) { - return GDMonoMarshal::mono_object_to_variant(p_var).hash(); -} - -MonoObject *godot_icall_Godot_instance_from_id(int p_instance_id) { - return GDMonoUtils::unmanaged_get_managed(ObjectDB::get_instance(p_instance_id)); -} - -void godot_icall_Godot_print(MonoArray *p_what) { - Array what = GDMonoMarshal::mono_array_to_Array(p_what); - String str; - for (int i = 0; i < what.size(); i++) - str += what[i].operator String(); - print_line(str); -} - -void godot_icall_Godot_printerr(MonoArray *p_what) { - Array what = GDMonoMarshal::mono_array_to_Array(p_what); - String str; - for (int i = 0; i < what.size(); i++) - str += what[i].operator String(); - OS::get_singleton()->printerr("%s\n", str.utf8().get_data()); -} - -void godot_icall_Godot_printraw(MonoArray *p_what) { - Array what = GDMonoMarshal::mono_array_to_Array(p_what); - String str; - for (int i = 0; i < what.size(); i++) - str += what[i].operator String(); - OS::get_singleton()->print("%s", str.utf8().get_data()); -} - -void godot_icall_Godot_prints(MonoArray *p_what) { - Array what = GDMonoMarshal::mono_array_to_Array(p_what); - String str; - for (int i = 0; i < what.size(); i++) { - if (i) - str += " "; - str += what[i].operator String(); - } - print_line(str); -} - -void godot_icall_Godot_printt(MonoArray *p_what) { - Array what = GDMonoMarshal::mono_array_to_Array(p_what); - String str; - for (int i = 0; i < what.size(); i++) { - if (i) - str += "\t"; - str += what[i].operator String(); - } - print_line(str); -} - -void godot_icall_Godot_seed(int p_seed) { - Math::seed(p_seed); -} - -MonoString *godot_icall_Godot_str(MonoArray *p_what) { - String str; - Array what = GDMonoMarshal::mono_array_to_Array(p_what); - - for (int i = 0; i < what.size(); i++) { - String os = what[i].operator String(); - - if (i == 0) - str = os; - else - str += os; - } - - return GDMonoMarshal::mono_string_from_godot(str); -} - -MonoObject *godot_icall_Godot_str2var(MonoString *p_str) { - Variant ret; - - VariantParser::StreamString ss; - ss.s = GDMonoMarshal::mono_string_to_godot(p_str); - - String errs; - int line; - Error err = VariantParser::parse(&ss, ret, errs, line); - if (err != OK) { - String err_str = "Parse error at line " + itos(line) + ": " + errs; - ERR_PRINTS(err_str); - ret = err_str; - } - - return GDMonoMarshal::variant_to_mono_object(ret); -} - -bool godot_icall_Godot_type_exists(MonoString *p_type) { - return ClassDB::class_exists(GDMonoMarshal::mono_string_to_godot(p_type)); -} - -MonoArray *godot_icall_Godot_var2bytes(MonoObject *p_var) { - Variant var = GDMonoMarshal::mono_object_to_variant(p_var); - - PoolByteArray barr; - int len; - Error err = encode_variant(var, NULL, len); - ERR_EXPLAIN("Unexpected error encoding variable to bytes, likely unserializable type found (Object or RID)."); - ERR_FAIL_COND_V(err != OK, NULL); - - barr.resize(len); - { - PoolByteArray::Write w = barr.write(); - encode_variant(var, w.ptr(), len); - } - - return GDMonoMarshal::PoolByteArray_to_mono_array(barr); -} - -MonoString *godot_icall_Godot_var2str(MonoObject *p_var) { - String vars; - VariantWriter::write_to_string(GDMonoMarshal::mono_object_to_variant(p_var), vars); - return GDMonoMarshal::mono_string_from_godot(vars); -} - -MonoObject *godot_icall_Godot_weakref(Object *p_obj) { - if (!p_obj) - return NULL; - - Ref<WeakRef> wref; - Reference *ref = Object::cast_to<Reference>(p_obj); - - if (ref) { - REF r = ref; - if (!r.is_valid()) - return NULL; - - wref.instance(); - wref->set_ref(r); - } else { - wref.instance(); - wref->set_obj(p_obj); - } - - return GDMonoUtils::create_managed_for_godot_object(CACHED_CLASS(WeakRef), Reference::get_class_static(), Object::cast_to<Object>(wref.ptr())); -} - -void godot_register_header_icalls() { - godot_register_builtin_type_icalls(); - godot_register_collections_icalls(); -} +#endif // MONO_GLUE_ENABLED diff --git a/modules/mono/glue/builtin_types_glue.h b/modules/mono/glue/nodepath_glue.cpp index ef9f152682..4b7648a4f9 100644 --- a/modules/mono/glue/builtin_types_glue.h +++ b/modules/mono/glue/nodepath_glue.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* builtin_types_glue.h */ +/* nodepath_glue.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,15 +28,24 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef BUILTIN_TYPES_GLUE_H -#define BUILTIN_TYPES_GLUE_H +#include "nodepath_glue.h" -#include "core/node_path.h" -#include "core/rid.h" +#ifdef MONO_GLUE_ENABLED -#include <mono/metadata/object.h> +#include "core/ustring.h" -#include "../mono_gd/gd_mono_marshal.h" +NodePath *godot_icall_NodePath_Ctor(MonoString *p_path) { + return memnew(NodePath(GDMonoMarshal::mono_string_to_godot(p_path))); +} + +void godot_icall_NodePath_Dtor(NodePath *p_ptr) { + ERR_FAIL_NULL(p_ptr); + _GodotSharp::get_singleton()->queue_dispose(p_ptr); +} + +MonoString *godot_icall_NodePath_operator_String(NodePath *p_np) { + return GDMonoMarshal::mono_string_from_godot(p_np->operator String()); +} MonoBoolean godot_icall_NodePath_is_absolute(NodePath *p_ptr) { return (MonoBoolean)p_ptr->is_absolute(); @@ -70,20 +79,18 @@ MonoBoolean godot_icall_NodePath_is_empty(NodePath *p_ptr) { return (MonoBoolean)p_ptr->is_empty(); } -uint32_t godot_icall_RID_get_id(RID *p_ptr) { - return p_ptr->get_id(); -} - -void godot_register_builtin_type_icalls() { - mono_add_internal_call("Godot.NativeCalls::godot_icall_NodePath_get_as_property_path", (void *)godot_icall_NodePath_get_as_property_path); - mono_add_internal_call("Godot.NativeCalls::godot_icall_NodePath_get_concatenated_subnames", (void *)godot_icall_NodePath_get_concatenated_subnames); - mono_add_internal_call("Godot.NativeCalls::godot_icall_NodePath_get_name", (void *)godot_icall_NodePath_get_name); - mono_add_internal_call("Godot.NativeCalls::godot_icall_NodePath_get_name_count", (void *)godot_icall_NodePath_get_name_count); - mono_add_internal_call("Godot.NativeCalls::godot_icall_NodePath_get_subname", (void *)godot_icall_NodePath_get_subname); - mono_add_internal_call("Godot.NativeCalls::godot_icall_NodePath_get_subname_count", (void *)godot_icall_NodePath_get_subname_count); - mono_add_internal_call("Godot.NativeCalls::godot_icall_NodePath_is_absolute", (void *)godot_icall_NodePath_is_absolute); - mono_add_internal_call("Godot.NativeCalls::godot_icall_NodePath_is_empty", (void *)godot_icall_NodePath_is_empty); - mono_add_internal_call("Godot.NativeCalls::godot_icall_RID_get_id", (void *)godot_icall_RID_get_id); +void godot_register_nodepath_icalls() { + mono_add_internal_call("Godot.NodePath::godot_icall_NodePath_Ctor", (void *)godot_icall_NodePath_Ctor); + mono_add_internal_call("Godot.NodePath::godot_icall_NodePath_Dtor", (void *)godot_icall_NodePath_Dtor); + mono_add_internal_call("Godot.NodePath::godot_icall_NodePath_operator_String", (void *)godot_icall_NodePath_operator_String); + mono_add_internal_call("Godot.NodePath::godot_icall_NodePath_get_as_property_path", (void *)godot_icall_NodePath_get_as_property_path); + mono_add_internal_call("Godot.NodePath::godot_icall_NodePath_get_concatenated_subnames", (void *)godot_icall_NodePath_get_concatenated_subnames); + mono_add_internal_call("Godot.NodePath::godot_icall_NodePath_get_name", (void *)godot_icall_NodePath_get_name); + mono_add_internal_call("Godot.NodePath::godot_icall_NodePath_get_name_count", (void *)godot_icall_NodePath_get_name_count); + mono_add_internal_call("Godot.NodePath::godot_icall_NodePath_get_subname", (void *)godot_icall_NodePath_get_subname); + mono_add_internal_call("Godot.NodePath::godot_icall_NodePath_get_subname_count", (void *)godot_icall_NodePath_get_subname_count); + mono_add_internal_call("Godot.NodePath::godot_icall_NodePath_is_absolute", (void *)godot_icall_NodePath_is_absolute); + mono_add_internal_call("Godot.NodePath::godot_icall_NodePath_is_empty", (void *)godot_icall_NodePath_is_empty); } -#endif // BUILTIN_TYPES_GLUE_H +#endif // MONO_GLUE_ENABLED diff --git a/modules/mono/glue/nodepath_glue.h b/modules/mono/glue/nodepath_glue.h new file mode 100644 index 0000000000..92579399a6 --- /dev/null +++ b/modules/mono/glue/nodepath_glue.h @@ -0,0 +1,68 @@ +/*************************************************************************/ +/* nodepath_glue.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef NODEPATH_GLUE_H +#define NODEPATH_GLUE_H + +#ifdef MONO_GLUE_ENABLED + +#include "core/node_path.h" + +#include "../mono_gd/gd_mono_marshal.h" + +NodePath *godot_icall_NodePath_Ctor(MonoString *p_path); + +void godot_icall_NodePath_Dtor(NodePath *p_ptr); + +MonoString *godot_icall_NodePath_operator_String(NodePath *p_np); + +MonoBoolean godot_icall_NodePath_is_absolute(NodePath *p_ptr); + +uint32_t godot_icall_NodePath_get_name_count(NodePath *p_ptr); + +MonoString *godot_icall_NodePath_get_name(NodePath *p_ptr, uint32_t p_idx); + +uint32_t godot_icall_NodePath_get_subname_count(NodePath *p_ptr); + +MonoString *godot_icall_NodePath_get_subname(NodePath *p_ptr, uint32_t p_idx); + +MonoString *godot_icall_NodePath_get_concatenated_subnames(NodePath *p_ptr); + +NodePath *godot_icall_NodePath_get_as_property_path(NodePath *p_ptr); + +MonoBoolean godot_icall_NodePath_is_empty(NodePath *p_ptr); + +// Register internal calls + +void godot_register_nodepath_icalls(); + +#endif // MONO_GLUE_ENABLED + +#endif // NODEPATH_GLUE_H diff --git a/modules/mono/glue/rid_glue.cpp b/modules/mono/glue/rid_glue.cpp new file mode 100644 index 0000000000..5d66b8aa6f --- /dev/null +++ b/modules/mono/glue/rid_glue.cpp @@ -0,0 +1,61 @@ +/*************************************************************************/ +/* rid_glue.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "rid_glue.h" + +#ifdef MONO_GLUE_ENABLED + +#include "core/resource.h" + +RID *godot_icall_RID_Ctor(Object *p_from) { + Resource *res_from = Object::cast_to<Resource>(p_from); + + if (res_from) + return memnew(RID(res_from->get_rid())); + + return memnew(RID); +} + +void godot_icall_RID_Dtor(RID *p_ptr) { + ERR_FAIL_NULL(p_ptr); + _GodotSharp::get_singleton()->queue_dispose(p_ptr); +} + +uint32_t godot_icall_RID_get_id(RID *p_ptr) { + return p_ptr->get_id(); +} + +void godot_register_rid_icalls() { + mono_add_internal_call("Godot.RID::godot_icall_RID_Ctor", (void *)godot_icall_RID_Ctor); + mono_add_internal_call("Godot.RID::godot_icall_RID_Dtor", (void *)godot_icall_RID_Dtor); + mono_add_internal_call("Godot.RID::godot_icall_RID_get_id", (void *)godot_icall_RID_get_id); +} + +#endif // MONO_GLUE_ENABLED diff --git a/modules/mono/glue/rid_glue.h b/modules/mono/glue/rid_glue.h new file mode 100644 index 0000000000..c725a9b5de --- /dev/null +++ b/modules/mono/glue/rid_glue.h @@ -0,0 +1,53 @@ +/*************************************************************************/ +/* rid_glue.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef RID_GLUE_H +#define RID_GLUE_H + +#ifdef MONO_GLUE_ENABLED + +#include "core/object.h" +#include "core/rid.h" + +#include "../mono_gd/gd_mono_marshal.h" + +RID *godot_icall_RID_Ctor(Object *p_from); + +void godot_icall_RID_Dtor(RID *p_ptr); + +uint32_t godot_icall_RID_get_id(RID *p_ptr); + +// Register internal calls + +void godot_register_rid_icalls(); + +#endif // MONO_GLUE_ENABLED + +#endif // RID_GLUE_H diff --git a/modules/mono/glue/string_glue.cpp b/modules/mono/glue/string_glue.cpp new file mode 100644 index 0000000000..e1a2f1affd --- /dev/null +++ b/modules/mono/glue/string_glue.cpp @@ -0,0 +1,79 @@ +/*************************************************************************/ +/* string_glue.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "string_glue.h" + +#ifdef MONO_GLUE_ENABLED + +#include "core/ustring.h" +#include "core/variant.h" +#include "core/vector.h" + +MonoArray *godot_icall_String_md5_buffer(MonoString *p_str) { + Vector<uint8_t> ret = GDMonoMarshal::mono_string_to_godot(p_str).md5_buffer(); + // TODO Check possible Array/Vector<uint8_t> problem? + return GDMonoMarshal::Array_to_mono_array(Variant(ret)); +} + +MonoString *godot_icall_String_md5_text(MonoString *p_str) { + String ret = GDMonoMarshal::mono_string_to_godot(p_str).md5_text(); + return GDMonoMarshal::mono_string_from_godot(ret); +} + +int godot_icall_String_rfind(MonoString *p_str, MonoString *p_what, int p_from) { + String what = GDMonoMarshal::mono_string_to_godot(p_what); + return GDMonoMarshal::mono_string_to_godot(p_str).rfind(what, p_from); +} + +int godot_icall_String_rfindn(MonoString *p_str, MonoString *p_what, int p_from) { + String what = GDMonoMarshal::mono_string_to_godot(p_what); + return GDMonoMarshal::mono_string_to_godot(p_str).rfindn(what, p_from); +} + +MonoArray *godot_icall_String_sha256_buffer(MonoString *p_str) { + Vector<uint8_t> ret = GDMonoMarshal::mono_string_to_godot(p_str).sha256_buffer(); + return GDMonoMarshal::Array_to_mono_array(Variant(ret)); +} + +MonoString *godot_icall_String_sha256_text(MonoString *p_str) { + String ret = GDMonoMarshal::mono_string_to_godot(p_str).sha256_text(); + return GDMonoMarshal::mono_string_from_godot(ret); +} + +void godot_register_string_icalls() { + mono_add_internal_call("Godot.String::godot_icall_String_md5_buffer", (void *)godot_icall_String_md5_buffer); + mono_add_internal_call("Godot.String::godot_icall_String_md5_text", (void *)godot_icall_String_md5_text); + mono_add_internal_call("Godot.String::godot_icall_String_rfind", (void *)godot_icall_String_rfind); + mono_add_internal_call("Godot.String::godot_icall_String_rfindn", (void *)godot_icall_String_rfindn); + mono_add_internal_call("Godot.String::godot_icall_String_sha256_buffer", (void *)godot_icall_String_sha256_buffer); + mono_add_internal_call("Godot.String::godot_icall_String_sha256_text", (void *)godot_icall_String_sha256_text); +} + +#endif // MONO_GLUE_ENABLED diff --git a/modules/mono/glue/string_glue.h b/modules/mono/glue/string_glue.h new file mode 100644 index 0000000000..8b1553e28b --- /dev/null +++ b/modules/mono/glue/string_glue.h @@ -0,0 +1,56 @@ +/*************************************************************************/ +/* string_glue.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef STRING_GLUE_H +#define STRING_GLUE_H + +#ifdef MONO_GLUE_ENABLED + +#include "../mono_gd/gd_mono_marshal.h" + +MonoArray *godot_icall_String_md5_buffer(MonoString *p_str); + +MonoString *godot_icall_String_md5_text(MonoString *p_str); + +int godot_icall_String_rfind(MonoString *p_str, MonoString *p_what, int p_from); + +int godot_icall_String_rfindn(MonoString *p_str, MonoString *p_what, int p_from); + +MonoArray *godot_icall_String_sha256_buffer(MonoString *p_str); + +MonoString *godot_icall_String_sha256_text(MonoString *p_str); + +// Register internal calls + +void godot_register_string_icalls(); + +#endif // MONO_GLUE_ENABLED + +#endif // STRING_GLUE_H diff --git a/modules/mono/godotsharp_dirs.cpp b/modules/mono/godotsharp_dirs.cpp index 92c5cdc5c1..2570e68f13 100644 --- a/modules/mono/godotsharp_dirs.cpp +++ b/modules/mono/godotsharp_dirs.cpp @@ -30,13 +30,13 @@ #include "godotsharp_dirs.h" -#include "os/os.h" +#include "core/os/os.h" #ifdef TOOLS_ENABLED +#include "core/os/dir_access.h" +#include "core/project_settings.h" +#include "core/version.h" #include "editor/editor_settings.h" -#include "os/dir_access.h" -#include "project_settings.h" -#include "version.h" #endif namespace GodotSharpDirs { diff --git a/modules/mono/godotsharp_dirs.h b/modules/mono/godotsharp_dirs.h index e87b5a4150..3466cb271d 100644 --- a/modules/mono/godotsharp_dirs.h +++ b/modules/mono/godotsharp_dirs.h @@ -31,7 +31,7 @@ #ifndef GODOTSHARP_DIRS_H #define GODOTSHARP_DIRS_H -#include "ustring.h" +#include "core/ustring.h" namespace GodotSharpDirs { diff --git a/modules/mono/mono_gc_handle.cpp b/modules/mono/mono_gc_handle.cpp index 9f0e933a8c..f695bddfeb 100644 --- a/modules/mono/mono_gc_handle.cpp +++ b/modules/mono/mono_gc_handle.cpp @@ -32,24 +32,34 @@ #include "mono_gd/gd_mono.h" -uint32_t MonoGCHandle::make_strong_handle(MonoObject *p_object) { +uint32_t MonoGCHandle::new_strong_handle(MonoObject *p_object) { return mono_gchandle_new(p_object, /* pinned: */ false); } -uint32_t MonoGCHandle::make_weak_handle(MonoObject *p_object) { +uint32_t MonoGCHandle::new_strong_handle_pinned(MonoObject *p_object) { + + return mono_gchandle_new(p_object, /* pinned: */ true); +} + +uint32_t MonoGCHandle::new_weak_handle(MonoObject *p_object) { return mono_gchandle_new_weakref(p_object, /* track_resurrection: */ false); } +void MonoGCHandle::free_handle(uint32_t p_gchandle) { + + mono_gchandle_free(p_gchandle); +} + Ref<MonoGCHandle> MonoGCHandle::create_strong(MonoObject *p_object) { - return memnew(MonoGCHandle(make_strong_handle(p_object), STRONG_HANDLE)); + return memnew(MonoGCHandle(new_strong_handle(p_object), STRONG_HANDLE)); } Ref<MonoGCHandle> MonoGCHandle::create_weak(MonoObject *p_object) { - return memnew(MonoGCHandle(make_weak_handle(p_object), WEAK_HANDLE)); + return memnew(MonoGCHandle(new_weak_handle(p_object), WEAK_HANDLE)); } void MonoGCHandle::release() { @@ -59,7 +69,7 @@ void MonoGCHandle::release() { #endif if (!released && GDMono::get_singleton()->is_runtime_initialized()) { - mono_gchandle_free(handle); + free_handle(handle); released = true; } } diff --git a/modules/mono/mono_gc_handle.h b/modules/mono/mono_gc_handle.h index 7eeaba30e0..e5aa04e2b8 100644 --- a/modules/mono/mono_gc_handle.h +++ b/modules/mono/mono_gc_handle.h @@ -33,7 +33,7 @@ #include <mono/jit/jit.h> -#include "reference.h" +#include "core/reference.h" class MonoGCHandle : public Reference { @@ -49,12 +49,15 @@ public: WEAK_HANDLE }; - static uint32_t make_strong_handle(MonoObject *p_object); - static uint32_t make_weak_handle(MonoObject *p_object); + static uint32_t new_strong_handle(MonoObject *p_object); + static uint32_t new_strong_handle_pinned(MonoObject *p_object); + static uint32_t new_weak_handle(MonoObject *p_object); + static void free_handle(uint32_t p_gchandle); static Ref<MonoGCHandle> create_strong(MonoObject *p_object); static Ref<MonoGCHandle> create_weak(MonoObject *p_object); + _FORCE_INLINE_ bool is_released() { return released; } _FORCE_INLINE_ bool is_weak() { return weak; } _FORCE_INLINE_ MonoObject *get_target() const { return released ? NULL : mono_gchandle_get_target(handle); } diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp index fadac941e9..03418a02ea 100644 --- a/modules/mono/mono_gd/gd_mono.cpp +++ b/modules/mono/mono_gd/gd_mono.cpp @@ -35,13 +35,14 @@ #include <mono/metadata/mono-debug.h> #include <mono/metadata/mono-gc.h> -#include "os/dir_access.h" -#include "os/file_access.h" -#include "os/os.h" -#include "os/thread.h" -#include "project_settings.h" +#include "core/os/dir_access.h" +#include "core/os/file_access.h" +#include "core/os/os.h" +#include "core/os/thread.h" +#include "core/project_settings.h" #include "../csharp_script.h" +#include "../glue/cs_glue_version.gen.h" #include "../godotsharp_dirs.h" #include "../utils/path_utils.h" #include "gd_mono_class.h" @@ -177,6 +178,30 @@ void GDMono::initialize() { 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; + } + } + } + } #else mono_set_dirs(NULL, NULL); #endif @@ -232,14 +257,14 @@ void GDMono::initialize() { _register_internal_calls(); // The following assemblies are not required at initialization -#ifndef MONO_GLUE_DISABLED +#ifdef MONO_GLUE_ENABLED if (_load_api_assemblies()) { if (!core_api_assembly_out_of_sync && !editor_api_assembly_out_of_sync && GDMonoUtils::mono_cache.godot_api_cache_updated) { // Everything is fine with the api assemblies, load the project assembly _load_project_assembly(); } else { #ifdef TOOLS_ENABLED - // The assembly was successfuly loaded, but the full api could not be cached. + // 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 metadata, // so we invalidate the version in the metadata and unload the script domain. @@ -275,7 +300,7 @@ void GDMono::initialize() { print_verbose("Mono: INITIALIZED"); } -#ifndef MONO_GLUE_DISABLED +#ifdef MONO_GLUE_ENABLED namespace GodotSharpBindings { uint64_t get_core_api_hash(); @@ -283,14 +308,13 @@ uint64_t get_core_api_hash(); uint64_t get_editor_api_hash(); #endif // TOOLS_ENABLED uint32_t get_bindings_version(); -uint32_t get_cs_glue_version(); void register_generated_icalls(); } // namespace GodotSharpBindings #endif void GDMono::_register_internal_calls() { -#ifndef MONO_GLUE_DISABLED +#ifdef MONO_GLUE_ENABLED GodotSharpBindings::register_generated_icalls(); #endif @@ -304,7 +328,7 @@ void GDMono::_initialize_and_check_api_hashes() { api_core_hash = ClassDB::get_api_hash(ClassDB::API_CORE); -#ifndef MONO_GLUE_DISABLED +#ifdef MONO_GLUE_ENABLED if (api_core_hash != GodotSharpBindings::get_core_api_hash()) { ERR_PRINT("Mono: Core API hash mismatch!"); } @@ -313,7 +337,7 @@ void GDMono::_initialize_and_check_api_hashes() { #ifdef TOOLS_ENABLED api_editor_hash = ClassDB::get_api_hash(ClassDB::API_EDITOR); -#ifndef MONO_GLUE_DISABLED +#ifdef MONO_GLUE_ENABLED if (api_editor_hash != GodotSharpBindings::get_editor_api_hash()) { ERR_PRINT("Mono: Editor API hash mismatch!"); } @@ -431,11 +455,11 @@ bool GDMono::_load_core_api_assembly() { bool success = load_assembly(API_ASSEMBLY_NAME, &core_api_assembly); if (success) { -#ifndef MONO_GLUE_DISABLED +#ifdef MONO_GLUE_ENABLED APIAssembly::Version api_assembly_ver = APIAssembly::Version::get_from_loaded_assembly(core_api_assembly, APIAssembly::API_CORE); core_api_assembly_out_of_sync = GodotSharpBindings::get_core_api_hash() != api_assembly_ver.godot_api_hash || GodotSharpBindings::get_bindings_version() != api_assembly_ver.bindings_version || - GodotSharpBindings::get_cs_glue_version() != api_assembly_ver.cs_glue_version; + CS_GLUE_VERSION != api_assembly_ver.cs_glue_version; #endif GDMonoUtils::update_godot_api_cache(); } @@ -457,11 +481,11 @@ bool GDMono::_load_editor_api_assembly() { bool success = load_assembly(EDITOR_API_ASSEMBLY_NAME, &editor_api_assembly); if (success) { -#ifndef MONO_GLUE_DISABLED +#ifdef MONO_GLUE_ENABLED APIAssembly::Version api_assembly_ver = APIAssembly::Version::get_from_loaded_assembly(editor_api_assembly, APIAssembly::API_EDITOR); editor_api_assembly_out_of_sync = GodotSharpBindings::get_editor_api_hash() != api_assembly_ver.godot_api_hash || GodotSharpBindings::get_bindings_version() != api_assembly_ver.bindings_version || - GodotSharpBindings::get_cs_glue_version() != api_assembly_ver.cs_glue_version; + CS_GLUE_VERSION != api_assembly_ver.cs_glue_version; #endif } @@ -615,9 +639,7 @@ Error GDMono::_unload_scripts_domain() { mono_gc_collect(mono_gc_max_generation()); - finalizing_scripts_domain = true; mono_domain_finalize(scripts_domain, 2000); - finalizing_scripts_domain = false; mono_gc_collect(mono_gc_max_generation()); @@ -684,7 +706,7 @@ Error GDMono::reload_scripts_domain() { return err; } -#ifndef MONO_GLUE_DISABLED +#ifdef MONO_GLUE_ENABLED if (!_load_api_assemblies()) { return ERR_CANT_OPEN; } @@ -693,18 +715,20 @@ Error GDMono::reload_scripts_domain() { // Everything is fine with the api assemblies, load the project assembly _load_project_assembly(); } else { - // The assembly was successfuly loaded, but the full api could not be cached. + // 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 metadata, // so we invalidate the version in the metadata and unload the script domain. if (core_api_assembly_out_of_sync) { + ERR_PRINT("The loaded Core API assembly is out of sync"); metadata_set_api_assembly_invalidated(APIAssembly::API_CORE, true); } else if (!GDMonoUtils::mono_cache.godot_api_cache_updated) { - ERR_PRINT("Core API assembly is in sync, but the cache update failed"); + ERR_PRINT("The loaded Core API assembly is in sync, but the cache update failed"); metadata_set_api_assembly_invalidated(APIAssembly::API_CORE, true); } if (editor_api_assembly_out_of_sync) { + ERR_PRINT("The loaded Editor API assembly is out of sync"); metadata_set_api_assembly_invalidated(APIAssembly::API_EDITOR, true); } @@ -813,7 +837,6 @@ GDMono::GDMono() { gdmono_log = memnew(GDMonoLog); runtime_initialized = false; - finalizing_scripts_domain = false; root_domain = NULL; scripts_domain = NULL; @@ -842,7 +865,7 @@ GDMono::GDMono() { GDMono::~GDMono() { - if (runtime_initialized) { + if (is_runtime_initialized()) { if (scripts_domain) { @@ -867,8 +890,9 @@ GDMono::~GDMono() { print_verbose("Mono: Runtime cleanup..."); - runtime_initialized = false; mono_jit_cleanup(root_domain); + + runtime_initialized = false; } if (gdmono_log) @@ -879,33 +903,12 @@ GDMono::~GDMono() { _GodotSharp *_GodotSharp::singleton = NULL; -void _GodotSharp::_dispose_object(Object *p_object) { - - if (p_object->get_script_instance()) { - CSharpInstance *cs_instance = CAST_CSHARP_INSTANCE(p_object->get_script_instance()); - if (cs_instance) { - cs_instance->mono_object_disposed(); - return; - } - } - - // Unsafe refcount decrement. The managed instance also counts as a reference. - // See: CSharpLanguage::alloc_instance_binding_data(Object *p_object) - if (Object::cast_to<Reference>(p_object)->unreference()) { - memdelete(p_object); - } -} - void _GodotSharp::_dispose_callback() { #ifndef NO_THREADS queue_mutex->lock(); #endif - for (List<Object *>::Element *E = obj_delete_queue.front(); E; E = E->next()) { - _dispose_object(E->get()); - } - for (List<NodePath *>::Element *E = np_delete_queue.front(); E; E = E->next()) { memdelete(E->get()); } @@ -914,7 +917,6 @@ void _GodotSharp::_dispose_callback() { memdelete(E->get()); } - obj_delete_queue.clear(); np_delete_queue.clear(); rid_delete_queue.clear(); queue_empty = true; @@ -934,52 +936,69 @@ void _GodotSharp::detach_thread() { GDMonoUtils::detach_current_thread(); } -bool _GodotSharp::is_finalizing_domain() { +int32_t _GodotSharp::get_domain_id() { - return GDMono::get_singleton()->is_finalizing_scripts_domain(); + MonoDomain *domain = mono_domain_get(); + CRASH_COND(!domain); // User must check if runtime is initialized before calling this method + return mono_domain_get_id(domain); } -bool _GodotSharp::is_domain_loaded() { +int32_t _GodotSharp::get_scripts_domain_id() { - return GDMono::get_singleton()->get_scripts_domain() != NULL; + MonoDomain *domain = SCRIPTS_DOMAIN; + CRASH_COND(!domain); // User must check if scripts domain is loaded before calling this method + return mono_domain_get_id(domain); } -#define ENQUEUE_FOR_DISPOSAL(m_queue, m_inst) \ - m_queue.push_back(m_inst); \ - if (queue_empty) { \ - queue_empty = false; \ - if (!is_finalizing_domain()) { /* call_deferred may not be safe here */ \ - call_deferred("_dispose_callback"); \ - } \ - } +bool _GodotSharp::is_scripts_domain_loaded() { -void _GodotSharp::queue_dispose(MonoObject *p_mono_object, Object *p_object) { + return GDMono::get_singleton()->is_runtime_initialized() && SCRIPTS_DOMAIN != NULL; +} - if (GDMonoUtils::is_main_thread() && !GDMono::get_singleton()->is_finalizing_scripts_domain()) { - _dispose_object(p_object); - } else { -#ifndef NO_THREADS - queue_mutex->lock(); -#endif +bool _GodotSharp::_is_domain_finalizing_for_unload(int32_t p_domain_id) { - // This is our last chance to invoke notification predelete (this is being called from the finalizer) - // We must use the MonoObject* passed by the finalizer, because the weak GC handle target returns NULL at this point - CSharpInstance *si = CAST_CSHARP_INSTANCE(p_object->get_script_instance()); - if (si) { - si->call_notification_no_check(p_mono_object, Object::NOTIFICATION_PREDELETE); - } + return is_domain_finalizing_for_unload(p_domain_id); +} - ENQUEUE_FOR_DISPOSAL(obj_delete_queue, p_object); +bool _GodotSharp::is_domain_finalizing_for_unload() { -#ifndef NO_THREADS - queue_mutex->unlock(); -#endif - } + return is_domain_finalizing_for_unload(mono_domain_get()); +} + +bool _GodotSharp::is_domain_finalizing_for_unload(int32_t p_domain_id) { + + return is_domain_finalizing_for_unload(mono_domain_get_by_id(p_domain_id)); +} + +bool _GodotSharp::is_domain_finalizing_for_unload(MonoDomain *p_domain) { + + if (!p_domain) + return true; + return mono_domain_is_unloading(p_domain); +} + +bool _GodotSharp::is_runtime_shutting_down() { + + return mono_runtime_is_shutting_down(); } +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() && !GDMono::get_singleton()->is_finalizing_scripts_domain()) { + if (GDMonoUtils::is_main_thread() && !is_domain_finalizing_for_unload(SCRIPTS_DOMAIN)) { memdelete(p_node_path); } else { #ifndef NO_THREADS @@ -996,7 +1015,7 @@ void _GodotSharp::queue_dispose(NodePath *p_node_path) { void _GodotSharp::queue_dispose(RID *p_rid) { - if (GDMonoUtils::is_main_thread() && !GDMono::get_singleton()->is_finalizing_scripts_domain()) { + if (GDMonoUtils::is_main_thread() && !is_domain_finalizing_for_unload(SCRIPTS_DOMAIN)) { memdelete(p_rid); } else { #ifndef NO_THREADS @@ -1016,8 +1035,13 @@ void _GodotSharp::_bind_methods() { ClassDB::bind_method(D_METHOD("attach_thread"), &_GodotSharp::attach_thread); ClassDB::bind_method(D_METHOD("detach_thread"), &_GodotSharp::detach_thread); - ClassDB::bind_method(D_METHOD("is_finalizing_domain"), &_GodotSharp::is_finalizing_domain); - ClassDB::bind_method(D_METHOD("is_domain_loaded"), &_GodotSharp::is_domain_loaded); + ClassDB::bind_method(D_METHOD("get_domain_id"), &_GodotSharp::get_domain_id); + ClassDB::bind_method(D_METHOD("get_scripts_domain_id"), &_GodotSharp::get_scripts_domain_id); + ClassDB::bind_method(D_METHOD("is_scripts_domain_loaded"), &_GodotSharp::is_scripts_domain_loaded); + ClassDB::bind_method(D_METHOD("is_domain_finalizing_for_unload", "domain_id"), &_GodotSharp::_is_domain_finalizing_for_unload); + + 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); } diff --git a/modules/mono/mono_gd/gd_mono.h b/modules/mono/mono_gd/gd_mono.h index e0ec6ced5e..0c5503d28e 100644 --- a/modules/mono/mono_gd/gd_mono.h +++ b/modules/mono/mono_gd/gd_mono.h @@ -170,8 +170,7 @@ public: void add_assembly(uint32_t p_domain_id, GDMonoAssembly *p_assembly); GDMonoAssembly **get_loaded_assembly(const String &p_name); - _FORCE_INLINE_ bool is_runtime_initialized() const { return runtime_initialized; } - _FORCE_INLINE_ bool is_finalizing_scripts_domain() const { return finalizing_scripts_domain; } + _FORCE_INLINE_ bool is_runtime_initialized() const { return runtime_initialized && !mono_runtime_is_shutting_down() /* stays true after shutdown finished */; } _FORCE_INLINE_ MonoDomain *get_scripts_domain() { return scripts_domain; } #ifdef TOOLS_ENABLED @@ -236,11 +235,10 @@ class _GodotSharp : public Object { friend class GDMono; - void _dispose_object(Object *p_object); - void _dispose_callback(); - List<Object *> obj_delete_queue; + bool _is_domain_finalizing_for_unload(int32_t p_domain_id); + List<NodePath *> np_delete_queue; List<RID *> rid_delete_queue; @@ -260,10 +258,18 @@ public: void attach_thread(); void detach_thread(); - bool is_finalizing_domain(); - bool is_domain_loaded(); + int32_t get_domain_id(); + int32_t get_scripts_domain_id(); + + bool is_scripts_domain_loaded(); + + bool is_domain_finalizing_for_unload(); + bool is_domain_finalizing_for_unload(int32_t p_domain_id); + bool is_domain_finalizing_for_unload(MonoDomain *p_domain); + + bool is_runtime_shutting_down(); + bool is_runtime_initialized(); - void queue_dispose(MonoObject *p_mono_object, Object *p_object); void queue_dispose(NodePath *p_node_path); void queue_dispose(RID *p_rid); diff --git a/modules/mono/mono_gd/gd_mono_assembly.h b/modules/mono/mono_gd/gd_mono_assembly.h index 2c6d367fc6..0ba11ac412 100644 --- a/modules/mono/mono_gd/gd_mono_assembly.h +++ b/modules/mono/mono_gd/gd_mono_assembly.h @@ -34,10 +34,10 @@ #include <mono/jit/jit.h> #include <mono/metadata/assembly.h> +#include "core/hash_map.h" +#include "core/map.h" +#include "core/ustring.h" #include "gd_mono_utils.h" -#include "hash_map.h" -#include "map.h" -#include "ustring.h" class GDMonoAssembly { diff --git a/modules/mono/mono_gd/gd_mono_class.h b/modules/mono/mono_gd/gd_mono_class.h index f4e386549a..477305d503 100644 --- a/modules/mono/mono_gd/gd_mono_class.h +++ b/modules/mono/mono_gd/gd_mono_class.h @@ -33,8 +33,8 @@ #include <mono/metadata/debug-helpers.h> -#include "map.h" -#include "ustring.h" +#include "core/map.h" +#include "core/ustring.h" #include "gd_mono_field.h" #include "gd_mono_header.h" diff --git a/modules/mono/mono_gd/gd_mono_header.h b/modules/mono/mono_gd/gd_mono_header.h index 72a5439044..2fe05006f1 100644 --- a/modules/mono/mono_gd/gd_mono_header.h +++ b/modules/mono/mono_gd/gd_mono_header.h @@ -31,7 +31,7 @@ #ifndef GD_MONO_HEADER_H #define GD_MONO_HEADER_H -#include "int_types.h" +#include "core/int_types.h" class GDMonoAssembly; class GDMonoClass; diff --git a/modules/mono/mono_gd/gd_mono_log.cpp b/modules/mono/mono_gd/gd_mono_log.cpp index 5224d309de..b7bb2cb2d6 100644 --- a/modules/mono/mono_gd/gd_mono_log.cpp +++ b/modules/mono/mono_gd/gd_mono_log.cpp @@ -33,8 +33,8 @@ #include <mono/utils/mono-logger.h> #include <stdlib.h> // abort -#include "os/dir_access.h" -#include "os/os.h" +#include "core/os/dir_access.h" +#include "core/os/os.h" #include "../godotsharp_dirs.h" diff --git a/modules/mono/mono_gd/gd_mono_log.h b/modules/mono/mono_gd/gd_mono_log.h index a7e374858c..3b4ff07b7b 100644 --- a/modules/mono/mono_gd/gd_mono_log.h +++ b/modules/mono/mono_gd/gd_mono_log.h @@ -31,7 +31,7 @@ #ifndef GD_MONO_LOG_H #define GD_MONO_LOG_H -#include "os/file_access.h" +#include "core/os/file_access.h" class GDMonoLog { diff --git a/modules/mono/mono_gd/gd_mono_marshal.h b/modules/mono/mono_gd/gd_mono_marshal.h index 464f584a0a..1ad0a4a6ea 100644 --- a/modules/mono/mono_gd/gd_mono_marshal.h +++ b/modules/mono/mono_gd/gd_mono_marshal.h @@ -31,9 +31,9 @@ #ifndef GDMONOMARSHAL_H #define GDMONOMARSHAL_H +#include "core/variant.h" #include "gd_mono.h" #include "gd_mono_utils.h" -#include "variant.h" namespace GDMonoMarshal { diff --git a/modules/mono/mono_gd/gd_mono_utils.cpp b/modules/mono/mono_gd/gd_mono_utils.cpp index c1f56bc3d2..8fbaca0992 100644 --- a/modules/mono/mono_gd/gd_mono_utils.cpp +++ b/modules/mono/mono_gd/gd_mono_utils.cpp @@ -32,10 +32,10 @@ #include <mono/metadata/exception.h> -#include "os/dir_access.h" -#include "os/os.h" -#include "project_settings.h" -#include "reference.h" +#include "core/os/dir_access.h" +#include "core/os/os.h" +#include "core/project_settings.h" +#include "core/reference.h" #include "../csharp_script.h" #include "../utils/macros.h" @@ -138,6 +138,7 @@ void MonoCache::clear_members() { field_Image_ptr = NULL; field_RID_ptr = NULL; + methodthunk_GodotObject_Dispose = NULL; methodthunk_Array_GetPtr = NULL; methodthunk_Dictionary_GetPtr = NULL; methodthunk_MarshalUtils_IsArrayGenericType = NULL; @@ -235,6 +236,7 @@ void update_godot_api_cache() { CACHE_FIELD_AND_CHECK(NodePath, ptr, CACHED_CLASS(NodePath)->get_field(BINDINGS_PTR_FIELD)); CACHE_FIELD_AND_CHECK(RID, ptr, CACHED_CLASS(RID)->get_field(BINDINGS_PTR_FIELD)); + CACHE_METHOD_THUNK_AND_CHECK(GodotObject, Dispose, (GodotObject_Dispose)CACHED_CLASS(GodotObject)->get_method_thunk("Dispose", 0)); CACHE_METHOD_THUNK_AND_CHECK(Array, GetPtr, (Array_GetPtr)GODOT_API_NS_CLAS(BINDINGS_NAMESPACE_COLLECTIONS, Array)->get_method_thunk("GetPtr", 0)); CACHE_METHOD_THUNK_AND_CHECK(Dictionary, GetPtr, (Dictionary_GetPtr)GODOT_API_NS_CLAS(BINDINGS_NAMESPACE_COLLECTIONS, Dictionary)->get_method_thunk("GetPtr", 0)); CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, IsArrayGenericType, (IsArrayGenericType)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("IsArrayGenericType", 1)); @@ -247,7 +249,7 @@ void update_godot_api_cache() { CACHE_METHOD_THUNK_AND_CHECK(DebuggingUtils, GetStackFrameInfo, (DebugUtils_StackFrameInfo)GODOT_API_CLASS(DebuggingUtils)->get_method_thunk("GetStackFrameInfo", 4)); #endif - // TODO Move to CSharpLanguage::init() + // TODO Move to CSharpLanguage::init() and do handle disposal MonoObject *task_scheduler = mono_object_new(SCRIPTS_DOMAIN, GODOT_API_CLASS(GodotTaskScheduler)->get_mono_ptr()); GDMonoUtils::runtime_object_init(task_scheduler); mono_cache.task_scheduler_handle = MonoGCHandle::create_strong(task_scheduler); @@ -270,11 +272,48 @@ MonoObject *unmanaged_get_managed(Object *unmanaged) { } } - // Only called if the owner does not have a CSharpInstance + // If the owner does not have a CSharpInstance... + void *data = unmanaged->get_script_instance_binding(CSharpLanguage::get_singleton()->get_language_index()); if (data) { - return ((Map<Object *, Ref<MonoGCHandle> >::Element *)data)->value()->get_target(); + CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)data)->value(); + + Ref<MonoGCHandle> &gchandle = script_binding.gchandle; + ERR_FAIL_COND_V(gchandle.is_null(), NULL); + + MonoObject *target = gchandle->get_target(); + + if (target) + return target; + + CSharpLanguage::get_singleton()->release_script_gchandle(gchandle); + + // Create a new one + +#ifdef DEBUG_ENABLED + CRASH_COND(script_binding.type_name == StringName()); + CRASH_COND(script_binding.wrapper_class == NULL); +#endif + + MonoObject *mono_object = GDMonoUtils::create_managed_for_godot_object(script_binding.wrapper_class, script_binding.type_name, unmanaged); + ERR_FAIL_NULL_V(mono_object, NULL); + + gchandle->set_handle(MonoGCHandle::new_strong_handle(mono_object), MonoGCHandle::STRONG_HANDLE); + + // Tie managed to unmanaged + Reference *ref = Object::cast_to<Reference>(unmanaged); + + if (ref) { + // Unsafe refcount increment. The managed instance also counts as a reference. + // This way if the unmanaged world has no references to our owner + // but the managed instance is alive, the refcount will be 1 instead of 0. + // See: godot_icall_Reference_Dtor(MonoObject *p_obj, Object *p_ptr) + + ref->reference(); + } + + return mono_object; } } @@ -304,6 +343,7 @@ MonoThread *get_current_thread() { void runtime_object_init(MonoObject *p_this_obj) { GD_MONO_BEGIN_RUNTIME_INVOKE; + // FIXME: Do not use mono_runtime_object_init, it aborts if an exception is thrown mono_runtime_object_init(p_this_obj); GD_MONO_END_RUNTIME_INVOKE; } @@ -623,4 +663,33 @@ MonoObject *property_get_value(MonoProperty *p_prop, void *p_obj, void **p_param return ret; } +uint64_t unbox_enum_value(MonoObject *p_boxed, MonoType *p_enum_basetype, bool &r_error) { + r_error = false; + switch (mono_type_get_type(p_enum_basetype)) { + case MONO_TYPE_BOOLEAN: + return (bool)GDMonoMarshal::unbox<MonoBoolean>(p_boxed) ? 1 : 0; + case MONO_TYPE_CHAR: + return GDMonoMarshal::unbox<uint16_t>(p_boxed); + case MONO_TYPE_U1: + return GDMonoMarshal::unbox<uint8_t>(p_boxed); + case MONO_TYPE_U2: + return GDMonoMarshal::unbox<uint16_t>(p_boxed); + case MONO_TYPE_U4: + return GDMonoMarshal::unbox<uint32_t>(p_boxed); + case MONO_TYPE_U8: + return GDMonoMarshal::unbox<uint64_t>(p_boxed); + case MONO_TYPE_I1: + return GDMonoMarshal::unbox<int8_t>(p_boxed); + case MONO_TYPE_I2: + return GDMonoMarshal::unbox<int16_t>(p_boxed); + case MONO_TYPE_I4: + return GDMonoMarshal::unbox<int32_t>(p_boxed); + case MONO_TYPE_I8: + return GDMonoMarshal::unbox<int64_t>(p_boxed); + default: + r_error = true; + return 0; + } +} + } // namespace GDMonoUtils diff --git a/modules/mono/mono_gd/gd_mono_utils.h b/modules/mono/mono_gd/gd_mono_utils.h index bf8860c85a..96ff3e8116 100644 --- a/modules/mono/mono_gd/gd_mono_utils.h +++ b/modules/mono/mono_gd/gd_mono_utils.h @@ -38,8 +38,8 @@ #include "../utils/thread_local.h" #include "gd_mono_header.h" -#include "object.h" -#include "reference.h" +#include "core/object.h" +#include "core/reference.h" #define UNLIKELY_UNHANDLED_EXCEPTION(m_exc) \ if (unlikely(m_exc != NULL)) { \ @@ -49,6 +49,7 @@ namespace GDMonoUtils { +typedef void (*GodotObject_Dispose)(MonoObject *, MonoObject **); typedef Array *(*Array_GetPtr)(MonoObject *, MonoObject **); typedef Dictionary *(*Dictionary_GetPtr)(MonoObject *, MonoObject **); typedef MonoObject *(*SignalAwaiter_SignalCallback)(MonoObject *, MonoArray *, MonoObject **); @@ -141,6 +142,7 @@ struct MonoCache { GDMonoField *field_Image_ptr; GDMonoField *field_RID_ptr; + GodotObject_Dispose methodthunk_GodotObject_Dispose; Array_GetPtr methodthunk_Array_GetPtr; Dictionary_GetPtr methodthunk_Dictionary_GetPtr; IsArrayGenericType methodthunk_MarshalUtils_IsArrayGenericType; @@ -238,6 +240,8 @@ MonoString *object_to_string(MonoObject *p_obj, MonoException **p_exc); void property_set_value(MonoProperty *p_prop, void *p_obj, void **p_params, MonoException **p_exc); MonoObject *property_get_value(MonoProperty *p_prop, void *p_obj, void **p_params, MonoException **p_exc); +uint64_t unbox_enum_value(MonoObject *p_boxed, MonoType *p_enum_basetype, bool &r_error); + } // namespace GDMonoUtils #define NATIVE_GDMONOCLASS_NAME(m_class) (GDMonoMarshal::mono_string_to_godot((MonoString *)m_class->get_field(BINDINGS_NATIVE_NAME_FIELD)->get_value(NULL))) diff --git a/modules/mono/register_types.cpp b/modules/mono/register_types.cpp index 4410996546..f6cb143e8e 100644 --- a/modules/mono/register_types.cpp +++ b/modules/mono/register_types.cpp @@ -30,7 +30,7 @@ #include "register_types.h" -#include "engine.h" +#include "core/engine.h" #include "csharp_script.h" diff --git a/modules/mono/signal_awaiter_utils.cpp b/modules/mono/signal_awaiter_utils.cpp index add1e506ea..b4c78df538 100644 --- a/modules/mono/signal_awaiter_utils.cpp +++ b/modules/mono/signal_awaiter_utils.cpp @@ -119,7 +119,7 @@ void SignalAwaiterHandle::_bind_methods() { } SignalAwaiterHandle::SignalAwaiterHandle(MonoObject *p_managed) : - MonoGCHandle(MonoGCHandle::make_strong_handle(p_managed), STRONG_HANDLE) { + MonoGCHandle(MonoGCHandle::new_strong_handle(p_managed), STRONG_HANDLE) { #ifdef DEBUG_ENABLED conn_target_id = 0; diff --git a/modules/mono/signal_awaiter_utils.h b/modules/mono/signal_awaiter_utils.h index 1920432709..4ec860537b 100644 --- a/modules/mono/signal_awaiter_utils.h +++ b/modules/mono/signal_awaiter_utils.h @@ -31,8 +31,8 @@ #ifndef SIGNAL_AWAITER_UTILS_H #define SIGNAL_AWAITER_UTILS_H +#include "core/reference.h" #include "mono_gc_handle.h" -#include "reference.h" namespace SignalAwaiterUtils { diff --git a/modules/mono/utils/mono_reg_utils.cpp b/modules/mono/utils/mono_reg_utils.cpp index 7b23cd7579..8116df5f51 100644 --- a/modules/mono/utils/mono_reg_utils.cpp +++ b/modules/mono/utils/mono_reg_utils.cpp @@ -32,7 +32,7 @@ #ifdef WINDOWS_ENABLED -#include "os/os.h" +#include "core/os/os.h" // Here, after os/os.h #include <windows.h> diff --git a/modules/mono/utils/mono_reg_utils.h b/modules/mono/utils/mono_reg_utils.h index edf31f5a07..26f7e2d3c2 100644 --- a/modules/mono/utils/mono_reg_utils.h +++ b/modules/mono/utils/mono_reg_utils.h @@ -33,7 +33,7 @@ #ifdef WINDOWS_ENABLED -#include "ustring.h" +#include "core/ustring.h" struct MonoRegInfo { diff --git a/modules/mono/utils/path_utils.cpp b/modules/mono/utils/path_utils.cpp index 4b77aeb54e..ea942a9a8e 100644 --- a/modules/mono/utils/path_utils.cpp +++ b/modules/mono/utils/path_utils.cpp @@ -30,10 +30,10 @@ #include "path_utils.h" -#include "os/dir_access.h" -#include "os/file_access.h" -#include "os/os.h" -#include "project_settings.h" +#include "core/os/dir_access.h" +#include "core/os/file_access.h" +#include "core/os/os.h" +#include "core/project_settings.h" #ifdef WINDOWS_ENABLED #define ENV_PATH_SEP ";" diff --git a/modules/mono/utils/path_utils.h b/modules/mono/utils/path_utils.h index 184cacfac7..3c7b36c0d4 100644 --- a/modules/mono/utils/path_utils.h +++ b/modules/mono/utils/path_utils.h @@ -31,7 +31,7 @@ #ifndef PATH_UTILS_H #define PATH_UTILS_H -#include "ustring.h" +#include "core/ustring.h" _FORCE_INLINE_ String path_join(const String &e1, const String &e2) { return e1.plus_file(e2); diff --git a/modules/mono/utils/string_utils.h b/modules/mono/utils/string_utils.h index 5dddaee6e8..f2df2340ae 100644 --- a/modules/mono/utils/string_utils.h +++ b/modules/mono/utils/string_utils.h @@ -31,8 +31,8 @@ #ifndef STRING_FORMAT_H #define STRING_FORMAT_H -#include "ustring.h" -#include "variant.h" +#include "core/ustring.h" +#include "core/variant.h" String sformat(const String &p_text, const Variant &p1 = Variant(), const Variant &p2 = Variant(), const Variant &p3 = Variant(), const Variant &p4 = Variant(), const Variant &p5 = Variant()); diff --git a/modules/opus/audio_stream_opus.cpp b/modules/opus/audio_stream_opus.cpp index 8323ff33ac..3920b3cd6e 100644 --- a/modules/opus/audio_stream_opus.cpp +++ b/modules/opus/audio_stream_opus.cpp @@ -142,7 +142,7 @@ Error AudioStreamPlaybackOpus::_load_stream() { } break; case OP_EBADLINK: // - Failed to find old data after seeking. case OP_EBADTIMESTAMP: // - Timestamp failed the validity checks. - case OP_EBADHEADER: { // - Invalid or mising Opus bitstream header. + case OP_EBADHEADER: { // - Invalid or missing Opus bitstream header. memdelete(f); f = NULL; ERR_FAIL_V(ERR_FILE_CORRUPT); @@ -208,7 +208,7 @@ Error AudioStreamPlaybackOpus::set_file(const String &p_file) { } break; case OP_EBADLINK: // - Failed to find old data after seeking. case OP_EBADTIMESTAMP: // - Timestamp failed the validity checks. - case OP_EBADHEADER: { // - Invalid or mising Opus bitstream header. + case OP_EBADHEADER: { // - Invalid or missing Opus bitstream header. memdelete(f); f = NULL; ERR_FAIL_V(ERR_FILE_CORRUPT); diff --git a/modules/opus/audio_stream_opus.h b/modules/opus/audio_stream_opus.h index 3ffdaf2c18..c004adeb77 100644 --- a/modules/opus/audio_stream_opus.h +++ b/modules/opus/audio_stream_opus.h @@ -31,8 +31,8 @@ #ifndef AUDIO_STREAM_OPUS_H #define AUDIO_STREAM_OPUS_H -#include "io/resource_loader.h" -#include "os/file_access.h" +#include "core/io/resource_loader.h" +#include "core/os/file_access.h" #include "scene/resources/audio_stream.h" #include <opus/opusfile.h> diff --git a/modules/pvr/texture_loader_pvr.cpp b/modules/pvr/texture_loader_pvr.cpp index 6ec44023c1..e6718eb4a2 100644 --- a/modules/pvr/texture_loader_pvr.cpp +++ b/modules/pvr/texture_loader_pvr.cpp @@ -31,7 +31,7 @@ #include "texture_loader_pvr.h" #include "PvrTcEncoder.h" #include "RgbaBitmap.h" -#include "os/file_access.h" +#include "core/os/file_access.h" #include <string.h> static void _pvrtc_decompress(Image *p_img); diff --git a/modules/pvr/texture_loader_pvr.h b/modules/pvr/texture_loader_pvr.h index 9369178336..c859a4cdda 100644 --- a/modules/pvr/texture_loader_pvr.h +++ b/modules/pvr/texture_loader_pvr.h @@ -31,7 +31,7 @@ #ifndef TEXTURE_LOADER_PVR_H #define TEXTURE_LOADER_PVR_H -#include "io/resource_loader.h" +#include "core/io/resource_loader.h" #include "scene/resources/texture.h" class ResourceFormatPVR : public ResourceFormatLoader { diff --git a/modules/recast/navigation_mesh_editor_plugin.cpp b/modules/recast/navigation_mesh_editor_plugin.cpp index 8556b7aa0a..98351fbaee 100644 --- a/modules/recast/navigation_mesh_editor_plugin.cpp +++ b/modules/recast/navigation_mesh_editor_plugin.cpp @@ -30,8 +30,8 @@ #include "navigation_mesh_editor_plugin.h" -#include "io/marshalls.h" -#include "io/resource_saver.h" +#include "core/io/marshalls.h" +#include "core/io/resource_saver.h" #include "scene/3d/mesh_instance.h" #include "scene/gui/box_container.h" diff --git a/modules/recast/navigation_mesh_generator.h b/modules/recast/navigation_mesh_generator.h index 3588539ef1..2f2f57d721 100644 --- a/modules/recast/navigation_mesh_generator.h +++ b/modules/recast/navigation_mesh_generator.h @@ -31,9 +31,9 @@ #ifndef NAVIGATION_MESH_GENERATOR_H #define NAVIGATION_MESH_GENERATOR_H +#include "core/os/thread.h" #include "editor/editor_node.h" #include "editor/editor_settings.h" -#include "os/thread.h" #include "scene/3d/mesh_instance.h" #include "scene/3d/navigation_mesh.h" #include "scene/resources/shape.h" diff --git a/modules/regex/register_types.cpp b/modules/regex/register_types.cpp index 14eba69ee0..73e2c5022d 100644 --- a/modules/regex/register_types.cpp +++ b/modules/regex/register_types.cpp @@ -29,7 +29,7 @@ /*************************************************************************/ #include "register_types.h" -#include "class_db.h" +#include "core/class_db.h" #include "regex.h" void register_regex_types() { diff --git a/modules/squish/image_compress_squish.cpp b/modules/squish/image_compress_squish.cpp index bb8a4bdbea..26cb76011c 100644 --- a/modules/squish/image_compress_squish.cpp +++ b/modules/squish/image_compress_squish.cpp @@ -30,7 +30,7 @@ #include "image_compress_squish.h" -#include "print_string.h" +#include "core/print_string.h" #include <squish.h> diff --git a/modules/squish/image_compress_squish.h b/modules/squish/image_compress_squish.h index 6da947beea..dfebdc955f 100644 --- a/modules/squish/image_compress_squish.h +++ b/modules/squish/image_compress_squish.h @@ -31,7 +31,7 @@ #ifndef IMAGE_COMPRESS_SQUISH_H #define IMAGE_COMPRESS_SQUISH_H -#include "image.h" +#include "core/image.h" void image_compress_squish(Image *p_image, float p_lossy_quality, Image::CompressSource p_source); void image_decompress_squish(Image *p_image); diff --git a/modules/stb_vorbis/audio_stream_ogg_vorbis.cpp b/modules/stb_vorbis/audio_stream_ogg_vorbis.cpp index 0e533d3978..57b6b5343e 100644 --- a/modules/stb_vorbis/audio_stream_ogg_vorbis.cpp +++ b/modules/stb_vorbis/audio_stream_ogg_vorbis.cpp @@ -30,7 +30,7 @@ #include "audio_stream_ogg_vorbis.h" -#include "os/file_access.h" +#include "core/os/file_access.h" #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" diff --git a/modules/stb_vorbis/audio_stream_ogg_vorbis.h b/modules/stb_vorbis/audio_stream_ogg_vorbis.h index d7bc7cc0d7..71a957a6af 100644 --- a/modules/stb_vorbis/audio_stream_ogg_vorbis.h +++ b/modules/stb_vorbis/audio_stream_ogg_vorbis.h @@ -31,7 +31,7 @@ #ifndef AUDIO_STREAM_STB_VORBIS_H #define AUDIO_STREAM_STB_VORBIS_H -#include "io/resource_loader.h" +#include "core/io/resource_loader.h" #include "servers/audio/audio_stream.h" #define STB_VORBIS_HEADER_ONLY diff --git a/modules/stb_vorbis/resource_importer_ogg_vorbis.cpp b/modules/stb_vorbis/resource_importer_ogg_vorbis.cpp index c8acdb689a..74f2e68206 100644 --- a/modules/stb_vorbis/resource_importer_ogg_vorbis.cpp +++ b/modules/stb_vorbis/resource_importer_ogg_vorbis.cpp @@ -30,8 +30,8 @@ #include "resource_importer_ogg_vorbis.h" -#include "io/resource_saver.h" -#include "os/file_access.h" +#include "core/io/resource_saver.h" +#include "core/os/file_access.h" #include "scene/resources/texture.h" String ResourceImporterOGGVorbis::get_importer_name() const { diff --git a/modules/stb_vorbis/resource_importer_ogg_vorbis.h b/modules/stb_vorbis/resource_importer_ogg_vorbis.h index a1847545aa..82a03cd207 100644 --- a/modules/stb_vorbis/resource_importer_ogg_vorbis.h +++ b/modules/stb_vorbis/resource_importer_ogg_vorbis.h @@ -32,7 +32,7 @@ #define RESOURCEIMPORTEROGGVORBIS_H #include "audio_stream_ogg_vorbis.h" -#include "io/resource_import.h" +#include "core/io/resource_import.h" class ResourceImporterOGGVorbis : public ResourceImporter { GDCLASS(ResourceImporterOGGVorbis, ResourceImporter) diff --git a/modules/svg/image_loader_svg.cpp b/modules/svg/image_loader_svg.cpp index 8ccd229f3d..ccb7d93885 100644 --- a/modules/svg/image_loader_svg.cpp +++ b/modules/svg/image_loader_svg.cpp @@ -30,10 +30,9 @@ #include "image_loader_svg.h" -#include "os/os.h" -#include "print_string.h" - -#include <ustring.h> +#include "core/os/os.h" +#include "core/print_string.h" +#include "core/ustring.h" void SVGRasterizer::rasterize(NSVGimage *p_image, float p_tx, float p_ty, float p_scale, unsigned char *p_dst, int p_w, int p_h, int p_stride) { nsvgRasterize(rasterizer, p_image, p_tx, p_ty, p_scale, p_dst, p_w, p_h, p_stride); diff --git a/modules/svg/image_loader_svg.h b/modules/svg/image_loader_svg.h index 63854da2f6..ff361ad800 100644 --- a/modules/svg/image_loader_svg.h +++ b/modules/svg/image_loader_svg.h @@ -31,8 +31,8 @@ #ifndef IMAGE_LOADER_SVG_H #define IMAGE_LOADER_SVG_H -#include "io/image_loader.h" -#include "ustring.h" +#include "core/io/image_loader.h" +#include "core/ustring.h" #include <nanosvg.h> #include <nanosvgrast.h> diff --git a/modules/tga/image_loader_tga.cpp b/modules/tga/image_loader_tga.cpp index d4fa88afa7..9bc24017fc 100644 --- a/modules/tga/image_loader_tga.cpp +++ b/modules/tga/image_loader_tga.cpp @@ -30,8 +30,8 @@ #include "image_loader_tga.h" -#include "os/os.h" -#include "print_string.h" +#include "core/os/os.h" +#include "core/print_string.h" Error ImageLoaderTGA::decode_tga_rle(const uint8_t *p_compressed_buffer, size_t p_pixel_size, uint8_t *p_uncompressed_buffer, size_t p_output_size) { Error error; diff --git a/modules/tga/image_loader_tga.h b/modules/tga/image_loader_tga.h index c4b10b7f49..0fe83a54a1 100644 --- a/modules/tga/image_loader_tga.h +++ b/modules/tga/image_loader_tga.h @@ -31,7 +31,7 @@ #ifndef IMAGE_LOADER_TGA_H #define IMAGE_LOADER_TGA_H -#include "io/image_loader.h" +#include "core/io/image_loader.h" /** @author SaracenOne diff --git a/modules/thekla_unwrap/register_types.cpp b/modules/thekla_unwrap/register_types.cpp index c74cbd9d18..8e733d1ad2 100644 --- a/modules/thekla_unwrap/register_types.cpp +++ b/modules/thekla_unwrap/register_types.cpp @@ -29,7 +29,7 @@ /*************************************************************************/ #include "register_types.h" -#include "error_macros.h" +#include "core/error_macros.h" #include "thirdparty/thekla_atlas/thekla/thekla_atlas.h" #include <stdio.h> diff --git a/modules/theora/video_stream_theora.cpp b/modules/theora/video_stream_theora.cpp index 68087ac01f..44052d473f 100644 --- a/modules/theora/video_stream_theora.cpp +++ b/modules/theora/video_stream_theora.cpp @@ -30,8 +30,8 @@ #include "video_stream_theora.h" -#include "os/os.h" -#include "project_settings.h" +#include "core/os/os.h" +#include "core/project_settings.h" #include "thirdparty/misc/yuv2rgb.h" diff --git a/modules/theora/video_stream_theora.h b/modules/theora/video_stream_theora.h index 1aba3f56da..4be723f85b 100644 --- a/modules/theora/video_stream_theora.h +++ b/modules/theora/video_stream_theora.h @@ -31,11 +31,11 @@ #ifndef VIDEO_STREAM_THEORA_H #define VIDEO_STREAM_THEORA_H -#include "io/resource_loader.h" -#include "os/file_access.h" -#include "os/semaphore.h" -#include "os/thread.h" -#include "ring_buffer.h" +#include "core/io/resource_loader.h" +#include "core/os/file_access.h" +#include "core/os/semaphore.h" +#include "core/os/thread.h" +#include "core/ring_buffer.h" #include "scene/resources/video_stream.h" #include "servers/audio_server.h" diff --git a/modules/tinyexr/image_loader_tinyexr.cpp b/modules/tinyexr/image_loader_tinyexr.cpp index b19bcfefcb..63f0781028 100644 --- a/modules/tinyexr/image_loader_tinyexr.cpp +++ b/modules/tinyexr/image_loader_tinyexr.cpp @@ -30,8 +30,8 @@ #include "image_loader_tinyexr.h" -#include "os/os.h" -#include "print_string.h" +#include "core/os/os.h" +#include "core/print_string.h" #include "thirdparty/tinyexr/tinyexr.h" diff --git a/modules/tinyexr/image_loader_tinyexr.h b/modules/tinyexr/image_loader_tinyexr.h index 6706e0972a..a6ef9000e5 100644 --- a/modules/tinyexr/image_loader_tinyexr.h +++ b/modules/tinyexr/image_loader_tinyexr.h @@ -31,7 +31,7 @@ #ifndef IMAGE_LOADER_TINYEXR_H #define IMAGE_LOADER_TINYEXR_H -#include "io/image_loader.h" +#include "core/io/image_loader.h" /** @author Juan Linietsky <reduzio@gmail.com> diff --git a/modules/upnp/doc_classes/UPNP.xml b/modules/upnp/doc_classes/UPNP.xml index 30be9c836b..b98327c60d 100644 --- a/modules/upnp/doc_classes/UPNP.xml +++ b/modules/upnp/doc_classes/UPNP.xml @@ -69,7 +69,7 @@ </argument> <description> Discovers local [UPNPDevice]s. Clears the list of previously discovered devices. - Filters for IGD (InternetGatewayDevice) type devices by default, as those manage port forwarding. [code]timeout[/code] is the time to wait for responses in miliseconds. [code]ttl[/code] is the time-to-live; only touch this if you know what you're doing. + Filters for IGD (InternetGatewayDevice) type devices by default, as those manage port forwarding. [code]timeout[/code] is the time to wait for responses in milliseconds. [code]ttl[/code] is the time-to-live; only touch this if you know what you're doing. See [enum UPNPResult] for possible return values. </description> </method> diff --git a/modules/upnp/register_types.cpp b/modules/upnp/register_types.cpp index c79155c4d2..13088c94dd 100644 --- a/modules/upnp/register_types.cpp +++ b/modules/upnp/register_types.cpp @@ -29,7 +29,9 @@ /*************************************************************************/ #include "register_types.h" -#include "error_macros.h" + +#include "core/error_macros.h" + #include "upnp.h" #include "upnpdevice.h" diff --git a/modules/upnp/upnp.cpp b/modules/upnp/upnp.cpp index 32fdfe22f8..69e054f5c5 100644 --- a/modules/upnp/upnp.cpp +++ b/modules/upnp/upnp.cpp @@ -29,8 +29,10 @@ /*************************************************************************/ #include "upnp.h" -#include "miniupnpc/miniwget.h" -#include "upnpcommands.h" + +#include <miniupnpc/miniwget.h> +#include <miniupnpc/upnpcommands.h> + #include <stdlib.h> bool UPNP::is_common_device(const String &dev) const { diff --git a/modules/upnp/upnp.h b/modules/upnp/upnp.h index fb0c0f30a0..8f0a972c22 100644 --- a/modules/upnp/upnp.h +++ b/modules/upnp/upnp.h @@ -31,9 +31,11 @@ #ifndef GODOT_UPNP_H #define GODOT_UPNP_H -#include "miniupnpc/miniupnpc.h" +#include "core/reference.h" + #include "upnpdevice.h" -#include <reference.h> + +#include <miniupnpc/miniupnpc.h> class UPNP : public Reference { diff --git a/modules/upnp/upnpdevice.cpp b/modules/upnp/upnpdevice.cpp index a5959cf649..8f935fbd82 100644 --- a/modules/upnp/upnpdevice.cpp +++ b/modules/upnp/upnpdevice.cpp @@ -29,8 +29,10 @@ /*************************************************************************/ #include "upnpdevice.h" + #include "upnp.h" -#include "upnpcommands.h" + +#include <miniupnpc/upnpcommands.h> String UPNPDevice::query_external_address() const { ERR_FAIL_COND_V(!is_valid_gateway(), ""); diff --git a/modules/upnp/upnpdevice.h b/modules/upnp/upnpdevice.h index 25c9fe1ba3..e4c5eb691d 100644 --- a/modules/upnp/upnpdevice.h +++ b/modules/upnp/upnpdevice.h @@ -31,7 +31,7 @@ #ifndef GODOT_UPNPDEVICE_H #define GODOT_UPNPDEVICE_H -#include <reference.h> +#include "core/reference.h" class UPNPDevice : public Reference { diff --git a/modules/visual_script/register_types.cpp b/modules/visual_script/register_types.cpp index 11401c0460..6e081817f1 100644 --- a/modules/visual_script/register_types.cpp +++ b/modules/visual_script/register_types.cpp @@ -31,7 +31,7 @@ #include "register_types.h" #include "core/engine.h" -#include "io/resource_loader.h" +#include "core/io/resource_loader.h" #include "visual_script.h" #include "visual_script_builtin_funcs.h" #include "visual_script_editor.h" diff --git a/modules/visual_script/visual_script.cpp b/modules/visual_script/visual_script.cpp index bbdec7195f..ff97c21fd9 100644 --- a/modules/visual_script/visual_script.cpp +++ b/modules/visual_script/visual_script.cpp @@ -30,8 +30,8 @@ #include "visual_script.h" -#include "os/os.h" -#include "project_settings.h" +#include "core/os/os.h" +#include "core/project_settings.h" #include "scene/main/node.h" #include "visual_script_nodes.h" diff --git a/modules/visual_script/visual_script.h b/modules/visual_script/visual_script.h index 13a8b909b0..ea99ce4970 100644 --- a/modules/visual_script/visual_script.h +++ b/modules/visual_script/visual_script.h @@ -31,8 +31,8 @@ #ifndef VISUAL_SCRIPT_H #define VISUAL_SCRIPT_H -#include "os/thread.h" -#include "script_language.h" +#include "core/os/thread.h" +#include "core/script_language.h" class VisualScriptInstance; class VisualScriptNodeInstance; diff --git a/modules/visual_script/visual_script_builtin_funcs.cpp b/modules/visual_script/visual_script_builtin_funcs.cpp index 8e98b08b22..e7a4e0c31f 100644 --- a/modules/visual_script/visual_script_builtin_funcs.cpp +++ b/modules/visual_script/visual_script_builtin_funcs.cpp @@ -30,13 +30,13 @@ #include "visual_script_builtin_funcs.h" -#include "class_db.h" -#include "func_ref.h" -#include "io/marshalls.h" -#include "math_funcs.h" -#include "os/os.h" -#include "reference.h" -#include "variant_parser.h" +#include "core/class_db.h" +#include "core/func_ref.h" +#include "core/io/marshalls.h" +#include "core/math/math_funcs.h" +#include "core/os/os.h" +#include "core/reference.h" +#include "core/variant_parser.h" const char *VisualScriptBuiltinFunc::func_name[VisualScriptBuiltinFunc::FUNC_MAX] = { "sin", diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp index 4471fbd0c4..1027c74f34 100644 --- a/modules/visual_script/visual_script_editor.cpp +++ b/modules/visual_script/visual_script_editor.cpp @@ -30,13 +30,13 @@ #include "visual_script_editor.h" +#include "core/object.h" +#include "core/os/input.h" +#include "core/os/keyboard.h" #include "core/script_language.h" +#include "core/variant.h" #include "editor/editor_node.h" #include "editor/editor_resource_preview.h" -#include "object.h" -#include "os/input.h" -#include "os/keyboard.h" -#include "variant.h" #include "visual_script_expression.h" #include "visual_script_flow_control.h" #include "visual_script_func_nodes.h" @@ -321,7 +321,7 @@ protected: p_list->push_back(PropertyInfo(Variant::INT, "type", PROPERTY_HINT_ENUM, argt)); p_list->push_back(PropertyInfo(script->get_variable_info(var).type, "value", script->get_variable_info(var).hint, script->get_variable_info(var).hint_string, PROPERTY_USAGE_DEFAULT)); // Update this when PropertyHint changes - p_list->push_back(PropertyInfo(Variant::INT, "hint", PROPERTY_HINT_ENUM, "None,Range,ExpRange,Enum,ExpEasing,Length,SpriteFrame,KeyAccel,Flags,Layers2dRender,Layers2dPhysics,Layer3dRender,Layer3dPhysics,File,Dir,GlobalFile,GlobalDir,ResourceType,MultilineText,ColorNoAlpha,ImageCompressLossy,ImageCompressLossLess,ObjectId,String,NodePathToEditedNode,MethodOfVariantType,MethodOfBaseType,MethodOfInstance,MethodOfScript,PropertyOfVariantType,PropertyOfBaseType,PropertyOfInstance,PropertyOfScript,ObjectTooBig")); + p_list->push_back(PropertyInfo(Variant::INT, "hint", PROPERTY_HINT_ENUM, "None,Range,ExpRange,Enum,ExpEasing,Length,SpriteFrame,KeyAccel,Flags,Layers2dRender,Layers2dPhysics,Layer3dRender,Layer3dPhysics,File,Dir,GlobalFile,GlobalDir,ResourceType,MultilineText,PlaceholderText,ColorNoAlpha,ImageCompressLossy,ImageCompressLossLess,ObjectId,String,NodePathToEditedNode,MethodOfVariantType,MethodOfBaseType,MethodOfInstance,MethodOfScript,PropertyOfVariantType,PropertyOfBaseType,PropertyOfInstance,PropertyOfScript,ObjectTooBig,NodePathValidTypes")); p_list->push_back(PropertyInfo(Variant::STRING, "hint_string")); p_list->push_back(PropertyInfo(Variant::BOOL, "export")); } @@ -2343,7 +2343,7 @@ void VisualScriptEditor::_graph_connected(const String &p_from, int p_from_slot, int from_port; if (!_get_out_slot(from_node, p_from_slot, from_port, from_seq)) - return; //can't connect this, it' s invalid + return; //can't connect this, it's invalid Ref<VisualScriptNode> to_node = script->get_node(edited_func, p_to.to_int()); ERR_FAIL_COND(!to_node.is_valid()); @@ -2352,7 +2352,7 @@ void VisualScriptEditor::_graph_connected(const String &p_from, int p_from_slot, int to_port; if (!_get_in_slot(to_node, p_to_slot, to_port, to_seq)) - return; //can't connect this, it' s invalid + return; //can't connect this, it's invalid ERR_FAIL_COND(from_seq != to_seq); @@ -2363,7 +2363,7 @@ void VisualScriptEditor::_graph_connected(const String &p_from, int p_from_slot, undo_redo->add_undo_method(script.ptr(), "sequence_disconnect", edited_func, p_from.to_int(), from_port, p_to.to_int()); } else { - // disconect current, and connect the new one + // disconnect current, and connect the new one if (script->is_input_value_port_connected(edited_func, p_to.to_int(), to_port)) { int conn_from; int conn_port; @@ -2396,7 +2396,7 @@ void VisualScriptEditor::_graph_disconnected(const String &p_from, int p_from_sl int from_port; if (!_get_out_slot(from_node, p_from_slot, from_port, from_seq)) - return; //can't connect this, it' s invalid + return; //can't connect this, it's invalid Ref<VisualScriptNode> to_node = script->get_node(edited_func, p_to.to_int()); ERR_FAIL_COND(!to_node.is_valid()); @@ -2405,7 +2405,7 @@ void VisualScriptEditor::_graph_disconnected(const String &p_from, int p_from_sl int to_port; if (!_get_in_slot(to_node, p_to_slot, to_port, to_seq)) - return; //can't connect this, it' s invalid + return; //can't connect this, it's invalid ERR_FAIL_COND(from_seq != to_seq); @@ -3615,8 +3615,7 @@ VisualScriptEditor::VisualScriptEditor() { edit_signal_dialog->set_title(TTR("Edit Signal Arguments:")); signal_editor = memnew(VisualScriptEditorSignalEdit); - edit_signal_edit = memnew(PropertyEditor); - edit_signal_edit->hide_top_label(); + edit_signal_edit = memnew(EditorInspector); edit_signal_dialog->add_child(edit_signal_edit); edit_signal_edit->edit(signal_editor); @@ -3627,8 +3626,7 @@ VisualScriptEditor::VisualScriptEditor() { edit_variable_dialog->set_title(TTR("Edit Variable:")); variable_editor = memnew(VisualScriptEditorVariableEdit); - edit_variable_edit = memnew(PropertyEditor); - edit_variable_edit->hide_top_label(); + edit_variable_edit = memnew(EditorInspector); edit_variable_dialog->add_child(edit_variable_edit); edit_variable_edit->edit(variable_editor); diff --git a/modules/visual_script/visual_script_editor.h b/modules/visual_script/visual_script_editor.h index 8bfd147519..b0bf971630 100644 --- a/modules/visual_script/visual_script_editor.h +++ b/modules/visual_script/visual_script_editor.h @@ -93,7 +93,7 @@ class VisualScriptEditor : public ScriptEditorBase { VisualScriptEditorSignalEdit *signal_editor; AcceptDialog *edit_signal_dialog; - PropertyEditor *edit_signal_edit; + EditorInspector *edit_signal_edit; VisualScriptPropertySelector *method_select; VisualScriptPropertySelector *new_connect_node_select; @@ -102,7 +102,7 @@ class VisualScriptEditor : public ScriptEditorBase { VisualScriptEditorVariableEdit *variable_editor; AcceptDialog *edit_variable_dialog; - PropertyEditor *edit_variable_edit; + EditorInspector *edit_variable_edit; CustomPropertyEditor *default_value_edit; diff --git a/modules/visual_script/visual_script_flow_control.cpp b/modules/visual_script/visual_script_flow_control.cpp index 7535f37ffc..c3ab949d24 100644 --- a/modules/visual_script/visual_script_flow_control.cpp +++ b/modules/visual_script/visual_script_flow_control.cpp @@ -30,9 +30,9 @@ #include "visual_script_flow_control.h" -#include "io/resource_loader.h" -#include "os/keyboard.h" -#include "project_settings.h" +#include "core/io/resource_loader.h" +#include "core/os/keyboard.h" +#include "core/project_settings.h" ////////////////////////////////////////// ////////////////RETURN//////////////////// diff --git a/modules/visual_script/visual_script_func_nodes.cpp b/modules/visual_script/visual_script_func_nodes.cpp index f926d4e2eb..1913bfd8c7 100644 --- a/modules/visual_script/visual_script_func_nodes.cpp +++ b/modules/visual_script/visual_script_func_nodes.cpp @@ -30,9 +30,9 @@ #include "visual_script_func_nodes.h" -#include "engine.h" -#include "io/resource_loader.h" -#include "os/os.h" +#include "core/engine.h" +#include "core/io/resource_loader.h" +#include "core/os/os.h" #include "scene/main/node.h" #include "scene/main/scene_tree.h" #include "visual_script_nodes.h" diff --git a/modules/visual_script/visual_script_nodes.cpp b/modules/visual_script/visual_script_nodes.cpp index d499512d93..99f242e974 100644 --- a/modules/visual_script/visual_script_nodes.cpp +++ b/modules/visual_script/visual_script_nodes.cpp @@ -30,11 +30,11 @@ #include "visual_script_nodes.h" -#include "engine.h" -#include "global_constants.h" -#include "os/input.h" -#include "os/os.h" -#include "project_settings.h" +#include "core/engine.h" +#include "core/global_constants.h" +#include "core/os/input.h" +#include "core/os/os.h" +#include "core/project_settings.h" #include "scene/main/node.h" #include "scene/main/scene_tree.h" diff --git a/modules/visual_script/visual_script_property_selector.cpp b/modules/visual_script/visual_script_property_selector.cpp index 8d465c8872..39997d14c4 100644 --- a/modules/visual_script/visual_script_property_selector.cpp +++ b/modules/visual_script/visual_script_property_selector.cpp @@ -30,13 +30,13 @@ #include "visual_script_property_selector.h" +#include "core/os/keyboard.h" #include "editor_scale.h" #include "modules/visual_script/visual_script.h" #include "modules/visual_script/visual_script_builtin_funcs.h" #include "modules/visual_script/visual_script_flow_control.h" #include "modules/visual_script/visual_script_func_nodes.h" #include "modules/visual_script/visual_script_nodes.h" -#include "os/keyboard.h" #include "scene/main/node.h" #include "scene/main/viewport.h" diff --git a/modules/visual_script/visual_script_yield_nodes.cpp b/modules/visual_script/visual_script_yield_nodes.cpp index a96e8408c0..a21fff67fe 100644 --- a/modules/visual_script/visual_script_yield_nodes.cpp +++ b/modules/visual_script/visual_script_yield_nodes.cpp @@ -30,7 +30,7 @@ #include "visual_script_yield_nodes.h" -#include "os/os.h" +#include "core/os/os.h" #include "scene/main/node.h" #include "scene/main/scene_tree.h" #include "visual_script_nodes.h" diff --git a/modules/vorbis/audio_stream_ogg_vorbis.h b/modules/vorbis/audio_stream_ogg_vorbis.h index 01de8a3143..73c4b5f3f4 100644 --- a/modules/vorbis/audio_stream_ogg_vorbis.h +++ b/modules/vorbis/audio_stream_ogg_vorbis.h @@ -31,9 +31,9 @@ #ifndef AUDIO_STREAM_OGG_VORBIS_H #define AUDIO_STREAM_OGG_VORBIS_H -#include "io/resource_loader.h" -#include "os/file_access.h" -#include "os/thread_safe.h" +#include "core/io/resource_loader.h" +#include "core/os/file_access.h" +#include "core/os/thread_safe.h" #include "scene/resources/audio_stream.h" #include <vorbis/vorbisfile.h> diff --git a/modules/webm/video_stream_webm.cpp b/modules/webm/video_stream_webm.cpp index 1bb9a43886..d9a6ece085 100644 --- a/modules/webm/video_stream_webm.cpp +++ b/modules/webm/video_stream_webm.cpp @@ -35,9 +35,9 @@ #include "mkvparser/mkvparser.h" -#include "os/file_access.h" -#include "os/os.h" -#include "project_settings.h" +#include "core/os/file_access.h" +#include "core/os/os.h" +#include "core/project_settings.h" #include "thirdparty/misc/yuv2rgb.h" diff --git a/modules/webm/video_stream_webm.h b/modules/webm/video_stream_webm.h index dcf88092c5..3739a73114 100644 --- a/modules/webm/video_stream_webm.h +++ b/modules/webm/video_stream_webm.h @@ -31,7 +31,7 @@ #ifndef VIDEO_STREAM_WEBM_H #define VIDEO_STREAM_WEBM_H -#include "io/resource_loader.h" +#include "core/io/resource_loader.h" #include "scene/resources/video_stream.h" class WebMFrame; diff --git a/modules/webp/image_loader_webp.cpp b/modules/webp/image_loader_webp.cpp index 42b2c77777..6734ae90d9 100644 --- a/modules/webp/image_loader_webp.cpp +++ b/modules/webp/image_loader_webp.cpp @@ -30,9 +30,9 @@ #include "image_loader_webp.h" -#include "io/marshalls.h" -#include "os/os.h" -#include "print_string.h" +#include "core/io/marshalls.h" +#include "core/os/os.h" +#include "core/print_string.h" #include <stdlib.h> #include <webp/decode.h> diff --git a/modules/webp/image_loader_webp.h b/modules/webp/image_loader_webp.h index f051fed4b8..256c787a16 100644 --- a/modules/webp/image_loader_webp.h +++ b/modules/webp/image_loader_webp.h @@ -31,7 +31,7 @@ #ifndef IMAGE_LOADER_WEBP_H #define IMAGE_LOADER_WEBP_H -#include "io/image_loader.h" +#include "core/io/image_loader.h" /** @author Juan Linietsky <reduzio@gmail.com> diff --git a/modules/websocket/doc_classes/WebSocketClient.xml b/modules/websocket/doc_classes/WebSocketClient.xml index 2e11e1a44c..9241492623 100644 --- a/modules/websocket/doc_classes/WebSocketClient.xml +++ b/modules/websocket/doc_classes/WebSocketClient.xml @@ -25,7 +25,7 @@ </argument> <description> Connect to the given URL requesting one of the given [code]protocols[/code] as sub-protocol. - If [code]true[/code] is passed as [code]gd_mp_api[/code], the client will behave like a network peer for the [MultiplayerAPI]. Note: connnections to non Godot servers will not work, and [signal data_received] will not be emitted when this option is true. + If [code]true[/code] is passed as [code]gd_mp_api[/code], the client will behave like a network peer for the [MultiplayerAPI]. Note: connections to non Godot servers will not work, and [signal data_received] will not be emitted when this option is true. </description> </method> <method name="disconnect_from_host"> diff --git a/modules/websocket/register_types.cpp b/modules/websocket/register_types.cpp index 721f3cc330..538cd40454 100644 --- a/modules/websocket/register_types.cpp +++ b/modules/websocket/register_types.cpp @@ -28,7 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "register_types.h" -#include "error_macros.h" +#include "core/error_macros.h" #ifdef JAVASCRIPT_ENABLED #include "emscripten.h" #include "emws_client.h" |