summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/bmp/image_loader_bmp.cpp184
-rw-r--r--modules/bmp/image_loader_bmp.h26
-rw-r--r--modules/bullet/SCsub2
-rw-r--r--modules/bullet/rigid_body_bullet.cpp2
-rw-r--r--modules/csg/csg.cpp10
-rw-r--r--modules/csg/doc_classes/CSGMesh.xml2
-rw-r--r--modules/csg/doc_classes/CSGShape.xml2
-rw-r--r--modules/enet/networked_multiplayer_enet.cpp16
-rw-r--r--modules/etc/SCsub2
-rw-r--r--modules/freetype/SCsub6
-rw-r--r--modules/gdscript/gdscript_functions.cpp23
-rw-r--r--modules/gdscript/gdscript_functions.h2
-rw-r--r--modules/mono/csharp_script.cpp17
-rw-r--r--modules/mono/csharp_script.h15
-rw-r--r--modules/mono/editor/bindings_generator.cpp332
-rw-r--r--modules/mono/editor/bindings_generator.h68
-rw-r--r--modules/mono/editor/csharp_project.cpp2
-rw-r--r--modules/mono/editor/godotsharp_builds.cpp9
-rw-r--r--modules/mono/glue/Managed/Files/Color.cs16
-rw-r--r--modules/mono/glue/Managed/Files/GD.cs5
-rw-r--r--modules/mono/glue/Managed/Files/Mathf.cs14
-rw-r--r--modules/mono/glue/Managed/Files/MathfEx.cs4
-rw-r--r--modules/mono/glue/Managed/Files/Plane.cs2
-rw-r--r--modules/mono/glue/Managed/Files/Quat.cs2
-rw-r--r--modules/mono/glue/Managed/Files/Vector2.cs26
-rw-r--r--modules/mono/glue/Managed/Files/Vector3.cs23
-rw-r--r--modules/mono/glue/gd_glue.cpp2
-rw-r--r--modules/mono/glue/gd_glue.h2
-rw-r--r--modules/mono/mono_gd/gd_mono.cpp4
-rw-r--r--modules/mono/mono_gd/gd_mono_log.cpp24
-rw-r--r--modules/mono/utils/string_utils.cpp49
-rw-r--r--modules/mono/utils/string_utils.h13
-rw-r--r--modules/opus/SCsub12
-rw-r--r--modules/svg/SCsub2
-rw-r--r--modules/tga/image_loader_tga.cpp6
-rw-r--r--modules/theora/SCsub2
-rw-r--r--modules/theora/video_stream_theora.cpp2
-rw-r--r--modules/vhacd/SCsub2
-rw-r--r--modules/webm/SCsub2
-rw-r--r--modules/webm/libvpx/SCsub4
-rw-r--r--modules/webm/video_stream_webm.cpp4
-rw-r--r--modules/websocket/SCsub2
-rw-r--r--modules/xatlas_unwrap/SCsub19
43 files changed, 659 insertions, 304 deletions
diff --git a/modules/bmp/image_loader_bmp.cpp b/modules/bmp/image_loader_bmp.cpp
index a8172c7f52..bcc992db24 100644
--- a/modules/bmp/image_loader_bmp.cpp
+++ b/modules/bmp/image_loader_bmp.cpp
@@ -33,6 +33,7 @@
Error ImageLoaderBMP::convert_to_image(Ref<Image> p_image,
const uint8_t *p_buffer,
const uint8_t *p_color_buffer,
+ const uint32_t color_table_size,
const bmp_header_s &p_header) {
Error err = OK;
@@ -46,32 +47,87 @@ Error ImageLoaderBMP::convert_to_image(Ref<Image> p_image,
size_t height = (size_t)p_header.bmp_info_header.bmp_height;
size_t bits_per_pixel = (size_t)p_header.bmp_info_header.bmp_bit_count;
- if (p_header.bmp_info_header.bmp_compression != 0) {
+ if (p_header.bmp_info_header.bmp_compression != BI_RGB) {
err = FAILED;
}
+ // Check whether we can load it
- if (!(bits_per_pixel == 24 || bits_per_pixel == 32)) {
- err = FAILED;
- }
+ if (bits_per_pixel == 1) {
+ // Requires bit unpacking...
+ ERR_FAIL_COND_V(width % 8 != 0, ERR_UNAVAILABLE);
+ ERR_FAIL_COND_V(height % 8 != 0, ERR_UNAVAILABLE);
+
+ } else if (bits_per_pixel == 4) {
+ // Requires bit unpacking...
+ ERR_FAIL_COND_V(width % 2 != 0, ERR_UNAVAILABLE);
+ ERR_FAIL_COND_V(height % 2 != 0, ERR_UNAVAILABLE);
+ } else if (bits_per_pixel == 16) {
+
+ ERR_FAIL_V(ERR_UNAVAILABLE);
+ }
if (err == OK) {
- uint32_t line_width = ((p_header.bmp_info_header.bmp_width *
- p_header.bmp_info_header.bmp_bit_count / 8) +
- 3) &
- ~3;
+ // Image data (might be indexed)
+ PoolVector<uint8_t> data;
+ int data_len = 0;
- PoolVector<uint8_t> image_data;
- err = image_data.resize(width * height * 4);
+ if (bits_per_pixel <= 8) { // indexed
+ data_len = width * height;
+ } else { // color
+ data_len = width * height * 4;
+ }
+ ERR_FAIL_COND_V(data_len == 0, ERR_BUG);
+ err = data.resize(data_len);
- PoolVector<uint8_t>::Write image_data_w = image_data.write();
- uint8_t *write_buffer = image_data_w.ptr();
+ PoolVector<uint8_t>::Write data_w = data.write();
+ uint8_t *write_buffer = data_w.ptr();
+ const uint32_t width_bytes = width * bits_per_pixel / 8;
+ const uint32_t line_width = (width_bytes + 3) & ~3;
+
+ // The actual data traversal is determined by
+ // the data width in case of 8/4/1 bit images
+ const uint32_t w = bits_per_pixel >= 24 ? width : width_bytes;
const uint8_t *line = p_buffer + (line_width * (height - 1));
+
for (unsigned int i = 0; i < height; i++) {
const uint8_t *line_ptr = line;
- for (unsigned int j = 0; j < width; j++) {
+
+ for (unsigned int j = 0; j < w; j++) {
switch (bits_per_pixel) {
+ case 1: {
+ uint8_t color_index = *line_ptr;
+
+ write_buffer[index + 0] = (color_index >> 7) & 1;
+ write_buffer[index + 1] = (color_index >> 6) & 1;
+ write_buffer[index + 2] = (color_index >> 5) & 1;
+ write_buffer[index + 3] = (color_index >> 4) & 1;
+ write_buffer[index + 4] = (color_index >> 3) & 1;
+ write_buffer[index + 5] = (color_index >> 2) & 1;
+ write_buffer[index + 6] = (color_index >> 1) & 1;
+ write_buffer[index + 7] = (color_index >> 0) & 1;
+
+ index += 8;
+ line_ptr += 1;
+ } break;
+ case 4: {
+ uint8_t color_index = *line_ptr;
+
+ write_buffer[index + 0] = (color_index >> 4) & 0x0f;
+ write_buffer[index + 1] = color_index & 0x0f;
+
+ index += 2;
+ line_ptr += 1;
+ } break;
+ case 8: {
+ uint8_t color_index = *line_ptr;
+
+ write_buffer[index] = color_index;
+
+ index += 1;
+ line_ptr += 1;
+ } break;
case 24: {
uint32_t color = *((uint32_t *)line_ptr);
@@ -79,6 +135,7 @@ Error ImageLoaderBMP::convert_to_image(Ref<Image> p_image,
write_buffer[index + 1] = (color >> 8) & 0xff;
write_buffer[index + 0] = (color >> 16) & 0xff;
write_buffer[index + 3] = 0xff;
+
index += 4;
line_ptr += 3;
} break;
@@ -89,6 +146,7 @@ Error ImageLoaderBMP::convert_to_image(Ref<Image> p_image,
write_buffer[index + 1] = (color >> 8) & 0xff;
write_buffer[index + 0] = (color >> 16) & 0xff;
write_buffer[index + 3] = color >> 24;
+
index += 4;
line_ptr += 4;
} break;
@@ -96,7 +154,51 @@ Error ImageLoaderBMP::convert_to_image(Ref<Image> p_image,
}
line -= line_width;
}
- p_image->create(width, height, 0, Image::FORMAT_RGBA8, image_data);
+
+ if (p_color_buffer == NULL || color_table_size == 0) { // regular pixels
+
+ p_image->create(width, height, 0, Image::FORMAT_RGBA8, data);
+
+ } else { // data is in indexed format, extend it
+
+ // Palette data
+ PoolVector<uint8_t> palette_data;
+ palette_data.resize(color_table_size * 4);
+
+ PoolVector<uint8_t>::Write palette_data_w = palette_data.write();
+ uint8_t *pal = palette_data_w.ptr();
+
+ const uint8_t *cb = p_color_buffer;
+
+ for (unsigned int i = 0; i < color_table_size; ++i) {
+ uint32_t color = *((uint32_t *)cb);
+
+ pal[i * 4 + 0] = (color >> 16) & 0xff;
+ pal[i * 4 + 1] = (color >> 8) & 0xff;
+ pal[i * 4 + 2] = (color)&0xff;
+ pal[i * 4 + 3] = 0xff;
+
+ cb += 4;
+ }
+ // Extend palette to image
+ PoolVector<uint8_t> extended_data;
+ extended_data.resize(data.size() * 4);
+
+ PoolVector<uint8_t>::Write ex_w = extended_data.write();
+ uint8_t *dest = ex_w.ptr();
+
+ const int num_pixels = width * height;
+
+ for (int i = 0; i < num_pixels; i++) {
+ dest[0] = pal[write_buffer[i] * 4 + 0];
+ dest[1] = pal[write_buffer[i] * 4 + 1];
+ dest[2] = pal[write_buffer[i] * 4 + 2];
+ dest[3] = pal[write_buffer[i] * 4 + 3];
+
+ dest += 4;
+ }
+ p_image->create(width, height, 0, Image::FORMAT_RGBA8, extended_data);
+ }
}
}
return err;
@@ -108,7 +210,9 @@ Error ImageLoaderBMP::load_image(Ref<Image> p_image, FileAccess *f,
bmp_header_s bmp_header;
Error err = ERR_INVALID_DATA;
- if (f->get_len() > sizeof(bmp_header)) {
+ // A valid bmp file should always at least have a
+ // file header and a minimal info header
+ if (f->get_len() > BITMAP_FILE_HEADER_SIZE + BITMAP_INFO_HEADER_MIN_SIZE) {
// File Header
bmp_header.bmp_file_header.bmp_signature = f->get_16();
if (bmp_header.bmp_file_header.bmp_signature == BITMAP_SIGNATURE) {
@@ -118,9 +222,14 @@ Error ImageLoaderBMP::load_image(Ref<Image> p_image, FileAccess *f,
// Info Header
bmp_header.bmp_info_header.bmp_header_size = f->get_32();
+ ERR_FAIL_COND_V(bmp_header.bmp_info_header.bmp_header_size < BITMAP_INFO_HEADER_MIN_SIZE, ERR_FILE_CORRUPT);
+
bmp_header.bmp_info_header.bmp_width = f->get_32();
bmp_header.bmp_info_header.bmp_height = f->get_32();
+
bmp_header.bmp_info_header.bmp_planes = f->get_16();
+ ERR_FAIL_COND_V(bmp_header.bmp_info_header.bmp_planes != 1, ERR_FILE_CORRUPT);
+
bmp_header.bmp_info_header.bmp_bit_count = f->get_16();
bmp_header.bmp_info_header.bmp_compression = f->get_32();
bmp_header.bmp_info_header.bmp_size_image = f->get_32();
@@ -129,35 +238,34 @@ Error ImageLoaderBMP::load_image(Ref<Image> p_image, FileAccess *f,
bmp_header.bmp_info_header.bmp_colors_used = f->get_32();
bmp_header.bmp_info_header.bmp_important_colors = f->get_32();
- bmp_header.bmp_info_header.bmp_red_mask = f->get_32();
- bmp_header.bmp_info_header.bmp_green_mask = f->get_32();
- bmp_header.bmp_info_header.bmp_blue_mask = f->get_32();
- bmp_header.bmp_info_header.bmp_alpha_mask = f->get_32();
- bmp_header.bmp_info_header.bmp_cs_type = f->get_32();
- for (int i = 0; i < 9; i++)
- bmp_header.bmp_info_header.bmp_endpoints[i] = f->get_32();
-
- bmp_header.bmp_info_header.bmp_gamma_red = f->get_32();
- bmp_header.bmp_info_header.bmp_gamma_green = f->get_32();
- bmp_header.bmp_info_header.bmp_gamma_blue = f->get_32();
-
- f->seek(sizeof(bmp_header.bmp_file_header) +
- bmp_header.bmp_info_header.bmp_header_size);
+ // Compressed bitmaps not supported, stop parsing
+ if (bmp_header.bmp_info_header.bmp_compression != BI_RGB) {
+ ERR_EXPLAIN("Unsupported bmp file: " + f->get_path());
+ f->close();
+ ERR_FAIL_V(ERR_UNAVAILABLE);
+ }
+ // Don't rely on sizeof(bmp_file_header) as structure padding
+ // adds 2 bytes offset leading to misaligned color table reading
+ uint32_t ct_offset = BITMAP_FILE_HEADER_SIZE +
+ bmp_header.bmp_info_header.bmp_header_size;
+ f->seek(ct_offset);
uint32_t color_table_size = 0;
- if (bmp_header.bmp_info_header.bmp_bit_count == 1)
- color_table_size = 2;
- else if (bmp_header.bmp_info_header.bmp_bit_count == 4)
- color_table_size = 16;
- else if (bmp_header.bmp_info_header.bmp_bit_count == 8)
- color_table_size = 256;
+
+ // bmp_colors_used may report 0 despite having a color table
+ // for 4 and 1 bit images, so don't rely on this information
+ if (bmp_header.bmp_info_header.bmp_bit_count <= 8) {
+ // Support 256 colors max
+ color_table_size = 1 << bmp_header.bmp_info_header.bmp_bit_count;
+ }
+ ERR_FAIL_COND_V(color_table_size == 0, ERR_BUG);
PoolVector<uint8_t> bmp_color_table;
if (color_table_size > 0) {
+ // Color table is usually 4 bytes per color -> [B][G][R][0]
err = bmp_color_table.resize(color_table_size * 4);
PoolVector<uint8_t>::Write bmp_color_table_w = bmp_color_table.write();
- f->get_buffer(bmp_color_table_w.ptr(),
- bmp_header.bmp_info_header.bmp_colors_used * 4);
+ f->get_buffer(bmp_color_table_w.ptr(), color_table_size * 4);
}
f->seek(bmp_header.bmp_file_header.bmp_file_offset);
@@ -174,7 +282,7 @@ Error ImageLoaderBMP::load_image(Ref<Image> p_image, FileAccess *f,
PoolVector<uint8_t>::Read bmp_buffer_r = bmp_buffer.read();
PoolVector<uint8_t>::Read bmp_color_table_r = bmp_color_table.read();
err = convert_to_image(p_image, bmp_buffer_r.ptr(),
- bmp_color_table_r.ptr(), bmp_header);
+ bmp_color_table_r.ptr(), color_table_size, bmp_header);
}
f->close();
}
diff --git a/modules/bmp/image_loader_bmp.h b/modules/bmp/image_loader_bmp.h
index d6899061d0..0082cf778a 100644
--- a/modules/bmp/image_loader_bmp.h
+++ b/modules/bmp/image_loader_bmp.h
@@ -37,6 +37,22 @@ class ImageLoaderBMP : public ImageFormatLoader {
protected:
static const unsigned BITMAP_SIGNATURE = 0x4d42;
+ static const unsigned BITMAP_FILE_HEADER_SIZE = 14; // bmp_file_header_s
+ static const unsigned BITMAP_INFO_HEADER_MIN_SIZE = 40; // bmp_info_header_s
+
+ enum bmp_compression_s {
+ BI_RGB = 0x00,
+ BI_RLE8 = 0x01,
+ BI_RLE4 = 0x02,
+ BI_BITFIELDS = 0x03,
+ BI_JPEG = 0x04,
+ BI_PNG = 0x05,
+ BI_ALPHABITFIELDS = 0x06,
+ BI_CMYK = 0x0b,
+ BI_CMYKRLE8 = 0x0c,
+ BI_CMYKRLE4 = 0x0d
+ };
+
struct bmp_header_s {
struct bmp_file_header_s {
uint16_t bmp_signature;
@@ -57,21 +73,13 @@ protected:
uint32_t bmp_pixels_per_meter_y;
uint32_t bmp_colors_used;
uint32_t bmp_important_colors;
- uint32_t bmp_red_mask;
- uint32_t bmp_green_mask;
- uint32_t bmp_blue_mask;
- uint32_t bmp_alpha_mask;
- uint32_t bmp_cs_type;
- uint32_t bmp_endpoints[9];
- uint32_t bmp_gamma_red;
- uint32_t bmp_gamma_green;
- uint32_t bmp_gamma_blue;
} bmp_info_header;
};
static Error convert_to_image(Ref<Image> p_image,
const uint8_t *p_buffer,
const uint8_t *p_color_buffer,
+ const uint32_t color_table_size,
const bmp_header_s &p_header);
public:
diff --git a/modules/bullet/SCsub b/modules/bullet/SCsub
index 7e714ba43f..e7c2fff54c 100644
--- a/modules/bullet/SCsub
+++ b/modules/bullet/SCsub
@@ -188,7 +188,7 @@ if env['builtin_bullet']:
env_bullet.Append(CPPPATH=[thirdparty_dir])
# if env['target'] == "debug" or env['target'] == "release_debug":
- # env_bullet.Append(CCFLAGS=['-DBT_DEBUG'])
+ # env_bullet.Append(CPPFLAGS=['-DBT_DEBUG'])
env_thirdparty = env_bullet.Clone()
env_thirdparty.disable_warnings()
diff --git a/modules/bullet/rigid_body_bullet.cpp b/modules/bullet/rigid_body_bullet.cpp
index 22f2214898..e5f70a0b34 100644
--- a/modules/bullet/rigid_body_bullet.cpp
+++ b/modules/bullet/rigid_body_bullet.cpp
@@ -597,6 +597,8 @@ void RigidBodyBullet::set_state(PhysicsServer::BodyState p_state, const Variant
if (!can_sleep) {
// Can't sleep
btBody->forceActivationState(DISABLE_DEACTIVATION);
+ } else {
+ btBody->forceActivationState(ACTIVE_TAG);
}
break;
}
diff --git a/modules/csg/csg.cpp b/modules/csg/csg.cpp
index 0eb539b182..7e1cc937cd 100644
--- a/modules/csg/csg.cpp
+++ b/modules/csg/csg.cpp
@@ -242,7 +242,7 @@ void CSGBrushOperation::BuildPoly::_clip_segment(const CSGBrush *p_brush, int p_
//check if edge and poly share a vertex, of so, assign it to segment_idx
for (int i = 0; i < points.size(); i++) {
for (int j = 0; j < 2; j++) {
- if (segment[j].distance_to(points[i].point) < CMP_EPSILON) {
+ if (Math::is_zero_approx(segment[j].distance_to(points[i].point))) {
segment_idx[j] = i;
inserted_points.push_back(i);
break;
@@ -310,7 +310,7 @@ void CSGBrushOperation::BuildPoly::_clip_segment(const CSGBrush *p_brush, int p_
Vector2 edgeseg[2] = { points[edges[i].points[0]].point, points[edges[i].points[1]].point };
Vector2 closest = Geometry::get_closest_point_to_segment_2d(segment[j], edgeseg);
- if (closest.distance_to(segment[j]) < CMP_EPSILON) {
+ if (Math::is_zero_approx(closest.distance_to(segment[j]))) {
//point rest of this edge
res = closest;
found = true;
@@ -439,7 +439,7 @@ void CSGBrushOperation::BuildPoly::clip(const CSGBrush *p_brush, int p_face, Mes
//transform A points to 2D
- if (segment[0].distance_to(segment[1]) < CMP_EPSILON)
+ if (Math::is_zero_approx(segment[0].distance_to(segment[1])))
return; //too small
_clip_segment(p_brush, p_face, segment, mesh_merge, p_for_B);
@@ -461,10 +461,10 @@ void CSGBrushOperation::_collision_callback(const CSGBrush *A, int p_face_a, Map
{
//check if either is a degenerate
- if (va[0].distance_to(va[1]) < CMP_EPSILON || va[0].distance_to(va[2]) < CMP_EPSILON || va[1].distance_to(va[2]) < CMP_EPSILON)
+ if (Math::is_zero_approx(va[0].distance_to(va[1])) || Math::is_zero_approx(va[0].distance_to(va[2])) || Math::is_zero_approx(va[1].distance_to(va[2])))
return;
- if (vb[0].distance_to(vb[1]) < CMP_EPSILON || vb[0].distance_to(vb[2]) < CMP_EPSILON || vb[1].distance_to(vb[2]) < CMP_EPSILON)
+ if (Math::is_zero_approx(vb[0].distance_to(vb[1])) || Math::is_zero_approx(vb[0].distance_to(vb[2])) || Math::is_zero_approx(vb[1].distance_to(vb[2])))
return;
}
diff --git a/modules/csg/doc_classes/CSGMesh.xml b/modules/csg/doc_classes/CSGMesh.xml
index c1f04d724a..afe0bc262d 100644
--- a/modules/csg/doc_classes/CSGMesh.xml
+++ b/modules/csg/doc_classes/CSGMesh.xml
@@ -11,6 +11,8 @@
<methods>
</methods>
<members>
+ <member name="material" type="Material" setter="set_material" getter="get_material">
+ </member>
<member name="mesh" type="Mesh" setter="set_mesh" getter="get_mesh">
The mesh resource to use as a CSG shape.
</member>
diff --git a/modules/csg/doc_classes/CSGShape.xml b/modules/csg/doc_classes/CSGShape.xml
index 2311830ae0..7fa7c78534 100644
--- a/modules/csg/doc_classes/CSGShape.xml
+++ b/modules/csg/doc_classes/CSGShape.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="CSGShape" inherits="VisualInstance" category="Core" version="3.2">
+<class name="CSGShape" inherits="GeometryInstance" category="Core" version="3.2">
<brief_description>
The CSG base class.
</brief_description>
diff --git a/modules/enet/networked_multiplayer_enet.cpp b/modules/enet/networked_multiplayer_enet.cpp
index 193f1bb48d..492b365128 100644
--- a/modules/enet/networked_multiplayer_enet.cpp
+++ b/modules/enet/networked_multiplayer_enet.cpp
@@ -346,11 +346,10 @@ void NetworkedMultiplayerENet::poll() {
uint32_t *id = (uint32_t *)event.peer->data;
- ERR_CONTINUE(event.packet->dataLength < 12)
+ ERR_CONTINUE(event.packet->dataLength < 8)
uint32_t source = decode_uint32(&event.packet->data[0]);
int target = decode_uint32(&event.packet->data[4]);
- uint32_t flags = decode_uint32(&event.packet->data[8]);
packet.from = source;
packet.channel = event.channelID;
@@ -371,7 +370,7 @@ void NetworkedMultiplayerENet::poll() {
if (uint32_t(E->key()) == source) // Do not resend to self
continue;
- ENetPacket *packet2 = enet_packet_create(packet.packet->data, packet.packet->dataLength, flags);
+ ENetPacket *packet2 = enet_packet_create(packet.packet->data, packet.packet->dataLength, packet.packet->flags);
enet_peer_send(E->get(), event.channelID, packet2);
}
@@ -385,7 +384,7 @@ void NetworkedMultiplayerENet::poll() {
if (uint32_t(E->key()) == source || E->key() == -target) // Do not resend to self, also do not send to excluded
continue;
- ENetPacket *packet2 = enet_packet_create(packet.packet->data, packet.packet->dataLength, flags);
+ ENetPacket *packet2 = enet_packet_create(packet.packet->data, packet.packet->dataLength, packet.packet->flags);
enet_peer_send(E->get(), event.channelID, packet2);
}
@@ -503,8 +502,8 @@ Error NetworkedMultiplayerENet::get_packet(const uint8_t **r_buffer, int &r_buff
current_packet = incoming_packets.front()->get();
incoming_packets.pop_front();
- *r_buffer = (const uint8_t *)(&current_packet.packet->data[12]);
- r_buffer_size = current_packet.packet->dataLength - 12;
+ *r_buffer = (const uint8_t *)(&current_packet.packet->data[8]);
+ r_buffer_size = current_packet.packet->dataLength - 8;
return OK;
}
@@ -549,11 +548,10 @@ Error NetworkedMultiplayerENet::put_packet(const uint8_t *p_buffer, int p_buffer
}
}
- ENetPacket *packet = enet_packet_create(NULL, p_buffer_size + 12, packet_flags);
+ ENetPacket *packet = enet_packet_create(NULL, p_buffer_size + 8, packet_flags);
encode_uint32(unique_id, &packet->data[0]); // Source ID
encode_uint32(target_peer, &packet->data[4]); // Dest ID
- encode_uint32(packet_flags, &packet->data[8]); // Dest ID
- copymem(&packet->data[12], p_buffer, p_buffer_size);
+ copymem(&packet->data[8], p_buffer, p_buffer_size);
if (server) {
diff --git a/modules/etc/SCsub b/modules/etc/SCsub
index 6e963ef766..eb2738053b 100644
--- a/modules/etc/SCsub
+++ b/modules/etc/SCsub
@@ -31,7 +31,7 @@ env_etc.Append(CPPPATH=[thirdparty_dir])
# upstream uses c++11
if not env.msvc:
- env_etc.Append(CCFLAGS="-std=c++11")
+ env_etc.Append(CXXFLAGS="-std=c++11")
env_thirdparty = env_etc.Clone()
env_thirdparty.disable_warnings()
diff --git a/modules/freetype/SCsub b/modules/freetype/SCsub
index c2d165f367..f2cd9f9a60 100644
--- a/modules/freetype/SCsub
+++ b/modules/freetype/SCsub
@@ -72,9 +72,9 @@ if env['builtin_freetype']:
# Also needed in main env for scene/
env.Append(CPPPATH=[thirdparty_dir + "/include"])
- env_freetype.Append(CCFLAGS=['-DFT2_BUILD_LIBRARY', '-DFT_CONFIG_OPTION_USE_PNG'])
+ env_freetype.Append(CPPFLAGS=['-DFT2_BUILD_LIBRARY', '-DFT_CONFIG_OPTION_USE_PNG'])
if (env['target'] != 'release'):
- env_freetype.Append(CCFLAGS=['-DZLIB_DEBUG'])
+ env_freetype.Append(CPPFLAGS=['-DZLIB_DEBUG'])
# Also requires libpng headers
if env['builtin_libpng']:
@@ -100,4 +100,4 @@ if env['builtin_freetype']:
# Godot source files
env_freetype.add_source_files(env.modules_sources, "*.cpp")
# Used in scene/, needs to be in main env
-env.Append(CCFLAGS=['-DFREETYPE_ENABLED'])
+env.Append(CPPFLAGS=['-DFREETYPE_ENABLED'])
diff --git a/modules/gdscript/gdscript_functions.cpp b/modules/gdscript/gdscript_functions.cpp
index 4fd136d5cc..7552bc6bff 100644
--- a/modules/gdscript/gdscript_functions.cpp
+++ b/modules/gdscript/gdscript_functions.cpp
@@ -68,6 +68,8 @@ const char *GDScriptFunctions::get_func_name(Function p_func) {
"exp",
"is_nan",
"is_inf",
+ "is_equal_approx",
+ "is_zero_approx",
"ease",
"decimals",
"stepify",
@@ -316,6 +318,17 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
VALIDATE_ARG_NUM(0);
r_ret = Math::is_inf((double)*p_args[0]);
} break;
+ case MATH_ISEQUALAPPROX: {
+ VALIDATE_ARG_COUNT(2);
+ VALIDATE_ARG_NUM(0);
+ VALIDATE_ARG_NUM(1);
+ r_ret = Math::is_equal_approx((real_t)*p_args[0], (real_t)*p_args[1]);
+ } break;
+ case MATH_ISZEROAPPROX: {
+ VALIDATE_ARG_COUNT(1);
+ VALIDATE_ARG_NUM(0);
+ r_ret = Math::is_zero_approx((real_t)*p_args[0]);
+ } break;
case MATH_EASE: {
VALIDATE_ARG_COUNT(2);
VALIDATE_ARG_NUM(0);
@@ -1596,6 +1609,16 @@ MethodInfo GDScriptFunctions::get_info(Function p_func) {
mi.return_val.type = Variant::BOOL;
return mi;
} break;
+ case MATH_ISEQUALAPPROX: {
+ MethodInfo mi("is_equal_approx", PropertyInfo(Variant::REAL, "a"), PropertyInfo(Variant::REAL, "b"));
+ mi.return_val.type = Variant::BOOL;
+ return mi;
+ } break;
+ case MATH_ISZEROAPPROX: {
+ MethodInfo mi("is_zero_approx", PropertyInfo(Variant::REAL, "s"));
+ mi.return_val.type = Variant::BOOL;
+ return mi;
+ } break;
case MATH_EASE: {
MethodInfo mi("ease", PropertyInfo(Variant::REAL, "s"), PropertyInfo(Variant::REAL, "curve"));
mi.return_val.type = Variant::REAL;
diff --git a/modules/gdscript/gdscript_functions.h b/modules/gdscript/gdscript_functions.h
index 14bf3d7560..0dbd172acf 100644
--- a/modules/gdscript/gdscript_functions.h
+++ b/modules/gdscript/gdscript_functions.h
@@ -59,6 +59,8 @@ public:
MATH_EXP,
MATH_ISNAN,
MATH_ISINF,
+ MATH_ISEQUALAPPROX,
+ MATH_ISZEROAPPROX,
MATH_EASE,
MATH_DECIMALS,
MATH_STEPIFY,
diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp
index 3c9644127c..27e579935f 100644
--- a/modules/mono/csharp_script.cpp
+++ b/modules/mono/csharp_script.cpp
@@ -131,14 +131,6 @@ void CSharpLanguage::finish() {
finalizing = true;
-#ifdef TOOLS_ENABLED
- // Must be here, to avoid StringName leaks
- if (BindingsGenerator::singleton) {
- memdelete(BindingsGenerator::singleton);
- BindingsGenerator::singleton = NULL;
- }
-#endif
-
// Make sure all script binding gchandles are released before finalizing GDMono
for (Map<Object *, CSharpScriptBinding>::Element *E = script_bindings.front(); E; E = E->next()) {
CSharpScriptBinding &script_binding = E->value();
@@ -919,7 +911,7 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
}
#endif
-void CSharpLanguage::project_assembly_loaded() {
+void CSharpLanguage::_load_scripts_metadata() {
scripts_metadata.clear();
@@ -953,6 +945,7 @@ void CSharpLanguage::project_assembly_loaded() {
}
scripts_metadata = old_dict_var.operator Dictionary();
+ scripts_metadata_invalidated = false;
print_verbose("Successfully loaded scripts metadata");
} else {
@@ -1024,11 +1017,13 @@ bool CSharpLanguage::debug_break(const String &p_error, bool p_allow_continue) {
}
}
-void CSharpLanguage::_uninitialize_script_bindings() {
+void CSharpLanguage::_on_scripts_domain_unloaded() {
for (Map<Object *, CSharpScriptBinding>::Element *E = script_bindings.front(); E; E = E->next()) {
CSharpScriptBinding &script_binding = E->value();
script_binding.inited = false;
}
+
+ scripts_metadata_invalidated = true;
}
void CSharpLanguage::set_language_index(int p_idx) {
@@ -1086,6 +1081,8 @@ CSharpLanguage::CSharpLanguage() {
#endif
lang_idx = -1;
+
+ scripts_metadata_invalidated = true;
}
CSharpLanguage::~CSharpLanguage() {
diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h
index 050527d52b..fe4eed2e24 100644
--- a/modules/mono/csharp_script.h
+++ b/modules/mono/csharp_script.h
@@ -309,14 +309,17 @@ class CSharpLanguage : public ScriptLanguage {
int lang_idx;
Dictionary scripts_metadata;
+ bool scripts_metadata_invalidated;
// For debug_break and debug_break_parse
int _debug_parse_err_line;
String _debug_parse_err_file;
String _debug_error;
+ void _load_scripts_metadata();
+
friend class GDMono;
- void _uninitialize_script_bindings();
+ void _on_scripts_domain_unloaded();
public:
StringNameCache string_names;
@@ -341,9 +344,15 @@ public:
void reload_assemblies(bool p_soft_reload);
#endif
- void project_assembly_loaded();
+ _FORCE_INLINE_ Dictionary get_scripts_metadata_or_nothing() {
+ return scripts_metadata_invalidated ? Dictionary() : scripts_metadata;
+ }
- _FORCE_INLINE_ const Dictionary &get_scripts_metadata() { return scripts_metadata; }
+ _FORCE_INLINE_ const Dictionary &get_scripts_metadata() {
+ if (scripts_metadata_invalidated)
+ _load_scripts_metadata();
+ return scripts_metadata;
+ }
virtual String get_name() const;
diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp
index 259c0ffece..a408716641 100644
--- a/modules/mono/editor/bindings_generator.cpp
+++ b/modules/mono/editor/bindings_generator.cpp
@@ -97,14 +97,10 @@
#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(8)
+#define BINDINGS_GENERATOR_VERSION UINT32_C(9)
const char *BindingsGenerator::TypeInterface::DEFAULT_VARARG_C_IN("\t%0 %1_in = %1;\n");
-bool BindingsGenerator::verbose_output = false;
-
-BindingsGenerator *BindingsGenerator::singleton = NULL;
-
static String fix_doc_description(const String &p_bbcode) {
// This seems to be the correct way to do this. It's the same EditorHelp does.
@@ -816,9 +812,7 @@ void BindingsGenerator::_generate_global_constants(StringBuilder &p_output) {
CRASH_COND(enum_class_name != "Variant"); // Hard-coded...
- if (verbose_output) {
- WARN_PRINTS("Declaring global enum `" + enum_proxy_name + "` inside static class `" + enum_class_name + "`");
- }
+ _log("Declaring global enum `%s` inside static class `%s`\n", enum_proxy_name.utf8().get_data(), enum_class_name.utf8().get_data());
p_output.append("\n" INDENT1 "public static partial class ");
p_output.append(enum_class_name);
@@ -867,9 +861,7 @@ void BindingsGenerator::_generate_global_constants(StringBuilder &p_output) {
p_output.append("\n#pragma warning restore CS1591\n");
}
-Error BindingsGenerator::generate_cs_core_project(const String &p_solution_dir, DotNetSolution &r_solution, bool p_verbose_output) {
-
- verbose_output = p_verbose_output;
+Error BindingsGenerator::generate_cs_core_project(const String &p_solution_dir, DotNetSolution &r_solution) {
String proj_dir = p_solution_dir.plus_file(CORE_API_ASSEMBLY_NAME);
@@ -1001,15 +993,12 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_solution_dir,
r_solution.add_new_project(CORE_API_ASSEMBLY_NAME, proj_info);
- if (verbose_output)
- OS::get_singleton()->print("The solution and C# project for the Core API was generated successfully\n");
+ _log("The solution and C# project for the Core API was generated successfully\n");
return OK;
}
-Error BindingsGenerator::generate_cs_editor_project(const String &p_solution_dir, DotNetSolution &r_solution, bool p_verbose_output) {
-
- verbose_output = p_verbose_output;
+Error BindingsGenerator::generate_cs_editor_project(const String &p_solution_dir, DotNetSolution &r_solution) {
String proj_dir = p_solution_dir.plus_file(EDITOR_API_ASSEMBLY_NAME);
@@ -1100,13 +1089,12 @@ Error BindingsGenerator::generate_cs_editor_project(const String &p_solution_dir
r_solution.add_new_project(EDITOR_API_ASSEMBLY_NAME, proj_info);
- if (verbose_output)
- OS::get_singleton()->print("The solution and C# project for the Editor API was generated successfully\n");
+ _log("The solution and C# project for the Editor API was generated successfully\n");
return OK;
}
-Error BindingsGenerator::generate_cs_api(const String &p_output_dir, bool p_verbose_output) {
+Error BindingsGenerator::generate_cs_api(const String &p_output_dir) {
DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
ERR_FAIL_COND_V(!da, ERR_CANT_CREATE);
@@ -1123,13 +1111,13 @@ Error BindingsGenerator::generate_cs_api(const String &p_output_dir, bool p_verb
Error proj_err;
- proj_err = generate_cs_core_project(p_output_dir, solution, p_verbose_output);
+ proj_err = generate_cs_core_project(p_output_dir, solution);
if (proj_err != OK) {
ERR_PRINT("Generation of the Core API C# project failed");
return proj_err;
}
- proj_err = generate_cs_editor_project(p_output_dir, solution, p_verbose_output);
+ proj_err = generate_cs_editor_project(p_output_dir, solution);
if (proj_err != OK) {
ERR_PRINT("Generation of the Editor API C# project failed");
return proj_err;
@@ -1168,8 +1156,7 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
List<InternalCall> &custom_icalls = itype.api_type == ClassDB::API_EDITOR ? editor_custom_icalls : core_custom_icalls;
- if (verbose_output)
- OS::get_singleton()->print("Generating %s.cs...\n", itype.proxy_name.utf8().get_data());
+ _log("Generating %s.cs...\n", itype.proxy_name.utf8().get_data());
String ctor_method(ICALL_PREFIX + itype.proxy_name + "_Ctor"); // Used only for derived types
@@ -1477,7 +1464,13 @@ Error BindingsGenerator::_generate_cs_property(const BindingsGenerator::TypeInte
p_output.append("\n" INDENT2 OPEN_BLOCK);
if (getter) {
- p_output.append(INDENT3 "get\n" OPEN_BLOCK_L3);
+ p_output.append(INDENT3 "get\n"
+
+ // TODO Remove this once we make accessor methods private/internal (they will no longer be marked as obsolete after that)
+ "#pragma warning disable CS0618 // Disable warning about obsolete method\n"
+
+ OPEN_BLOCK_L3);
+
p_output.append("return ");
p_output.append(getter->proxy_name + "(");
if (p_iprop.index != -1) {
@@ -1491,11 +1484,22 @@ Error BindingsGenerator::_generate_cs_property(const BindingsGenerator::TypeInte
p_output.append(itos(p_iprop.index));
}
}
- p_output.append(");\n" CLOSE_BLOCK_L3);
+ p_output.append(");\n"
+
+ CLOSE_BLOCK_L3
+
+ // TODO Remove this once we make accessor methods private/internal (they will no longer be marked as obsolete after that)
+ "#pragma warning restore CS0618\n");
}
if (setter) {
- p_output.append(INDENT3 "set\n" OPEN_BLOCK_L3);
+ p_output.append(INDENT3 "set\n"
+
+ // TODO Remove this once we make accessor methods private/internal (they will no longer be marked as obsolete after that)
+ "#pragma warning disable CS0618 // Disable warning about obsolete method\n"
+
+ OPEN_BLOCK_L3);
+
p_output.append(setter->proxy_name + "(");
if (p_iprop.index != -1) {
const ArgumentInterface &idx_arg = setter->arguments.front()->get();
@@ -1508,7 +1512,12 @@ Error BindingsGenerator::_generate_cs_property(const BindingsGenerator::TypeInte
p_output.append(itos(p_iprop.index) + ", ");
}
}
- p_output.append("value);\n" CLOSE_BLOCK_L3);
+ p_output.append("value);\n"
+
+ CLOSE_BLOCK_L3
+
+ // TODO Remove this once we make accessor methods private/internal (they will no longer be marked as obsolete after that)
+ "#pragma warning restore CS0618\n");
}
p_output.append(CLOSE_BLOCK_L2);
@@ -1636,6 +1645,15 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
p_output.append("\")]");
}
+ if (p_imethod.is_deprecated) {
+ if (p_imethod.deprecation_message.empty())
+ WARN_PRINTS("An empty deprecation message is discouraged. Method: " + p_imethod.proxy_name);
+
+ p_output.append(MEMBER_BEGIN "[Obsolete(\"");
+ p_output.append(p_imethod.deprecation_message);
+ p_output.append("\")]");
+ }
+
p_output.append(MEMBER_BEGIN);
p_output.append(p_imethod.is_internal ? "internal " : "public ");
@@ -1710,8 +1728,6 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
Error BindingsGenerator::generate_glue(const String &p_output_dir) {
- verbose_output = true;
-
bool dir_exists = DirAccess::exists(p_output_dir);
ERR_EXPLAIN("The output directory does not exist.");
ERR_FAIL_COND_V(!dir_exists, ERR_FILE_BAD_PATH);
@@ -2109,6 +2125,58 @@ const BindingsGenerator::TypeInterface *BindingsGenerator::_get_type_or_placehol
return &placeholder_types.insert(placeholder.cname, placeholder)->get();
}
+StringName BindingsGenerator::_get_int_type_name_from_meta(GodotTypeInfo::Metadata p_meta) {
+
+ switch (p_meta) {
+ case GodotTypeInfo::METADATA_INT_IS_INT8:
+ return "sbyte";
+ break;
+ case GodotTypeInfo::METADATA_INT_IS_INT16:
+ return "short";
+ break;
+ case GodotTypeInfo::METADATA_INT_IS_INT32:
+ return "int";
+ break;
+ case GodotTypeInfo::METADATA_INT_IS_INT64:
+ return "long";
+ break;
+ case GodotTypeInfo::METADATA_INT_IS_UINT8:
+ return "byte";
+ break;
+ case GodotTypeInfo::METADATA_INT_IS_UINT16:
+ return "ushort";
+ break;
+ case GodotTypeInfo::METADATA_INT_IS_UINT32:
+ return "uint";
+ break;
+ case GodotTypeInfo::METADATA_INT_IS_UINT64:
+ return "ulong";
+ break;
+ default:
+ // Assume INT32
+ return "int";
+ }
+}
+
+StringName BindingsGenerator::_get_float_type_name_from_meta(GodotTypeInfo::Metadata p_meta) {
+
+ switch (p_meta) {
+ case GodotTypeInfo::METADATA_REAL_IS_FLOAT:
+ return "float";
+ break;
+ case GodotTypeInfo::METADATA_REAL_IS_DOUBLE:
+ return "double";
+ break;
+ default:
+ // Assume real_t (float or double depending of REAL_T_IS_DOUBLE)
+#ifdef REAL_T_IS_DOUBLE
+ return "double";
+#else
+ return "float";
+#endif
+ }
+}
+
void BindingsGenerator::_populate_object_type_interfaces() {
obj_types.clear();
@@ -2128,15 +2196,13 @@ void BindingsGenerator::_populate_object_type_interfaces() {
}
if (!ClassDB::is_class_exposed(type_cname)) {
- if (verbose_output)
- WARN_PRINTS("Ignoring type " + type_cname.operator String() + " because it's not exposed");
+ _log("Ignoring type `%s` because it's not exposed\n", String(type_cname).utf8().get_data());
class_list.pop_front();
continue;
}
if (!ClassDB::is_class_enabled(type_cname)) {
- if (verbose_output)
- WARN_PRINTS("Ignoring type " + type_cname.operator String() + " because it's not enabled");
+ _log("Ignoring type `%s` because it's not enabled\n", String(type_cname).utf8().get_data());
class_list.pop_front();
continue;
}
@@ -2164,10 +2230,12 @@ void BindingsGenerator::_populate_object_type_interfaces() {
itype.im_type_in = "IntPtr";
itype.im_type_out = itype.proxy_name;
+ // Populate properties
+
List<PropertyInfo> property_list;
ClassDB::get_property_list(type_cname, &property_list, true);
- // Populate properties
+ Map<StringName, StringName> accessor_methods;
for (const List<PropertyInfo>::Element *E = property_list.front(); E; E = E->next()) {
const PropertyInfo &property = E->get();
@@ -2180,18 +2248,21 @@ void BindingsGenerator::_populate_object_type_interfaces() {
iprop.setter = ClassDB::get_property_setter(type_cname, iprop.cname);
iprop.getter = ClassDB::get_property_getter(type_cname, iprop.cname);
+ if (iprop.setter != StringName())
+ accessor_methods[iprop.setter] = iprop.cname;
+ if (iprop.getter != StringName())
+ accessor_methods[iprop.getter] = iprop.cname;
+
bool valid = false;
iprop.index = ClassDB::get_property_index(type_cname, iprop.cname, &valid);
ERR_FAIL_COND(!valid);
iprop.proxy_name = escape_csharp_keyword(snake_to_pascal_case(iprop.cname));
- // Prevent property and enclosing type from sharing the same name
+ // Prevent the property and its enclosing type from sharing the same name
if (iprop.proxy_name == itype.proxy_name) {
- if (verbose_output) {
- WARN_PRINTS("Name of property `" + iprop.proxy_name + "` is ambiguous with the name of its class `" +
- itype.proxy_name + "`. Renaming property to `" + iprop.proxy_name + "_`");
- }
+ _log("Name of property `%s` is ambiguous with the name of its enclosing class `%s`. Renaming property to `%s_`\n",
+ iprop.proxy_name.utf8().get_data(), itype.proxy_name.utf8().get_data(), iprop.proxy_name.utf8().get_data());
iprop.proxy_name += "_";
}
@@ -2258,14 +2329,13 @@ void BindingsGenerator::_populate_object_type_interfaces() {
// which could actually will return something different.
// Let's put this to notify us if that ever happens.
if (itype.cname != name_cache.type_Object || imethod.name != "free") {
- if (verbose_output) {
- WARN_PRINTS("Notification: New unexpected virtual non-overridable method found.\n"
- "We only expected Object.free, but found " +
- itype.name + "." + imethod.name);
- }
+ ERR_PRINTS("Notification: New unexpected virtual non-overridable method found.\n"
+ "We only expected Object.free, but found " +
+ itype.name + "." + imethod.name);
}
} else {
- ERR_PRINTS("Missing MethodBind for non-virtual method: " + itype.name + "." + imethod.name);
+ ERR_EXPLAIN("Missing MethodBind for non-virtual method: " + itype.name + "." + imethod.name);
+ ERR_FAIL();
}
} else if (return_info.type == Variant::INT && return_info.usage & PROPERTY_USAGE_CLASS_IS_ENUM) {
imethod.return_type.cname = return_info.class_name;
@@ -2279,7 +2349,13 @@ void BindingsGenerator::_populate_object_type_interfaces() {
} else if (return_info.type == Variant::NIL) {
imethod.return_type.cname = name_cache.type_void;
} else {
- imethod.return_type.cname = Variant::get_type_name(return_info.type);
+ if (return_info.type == Variant::INT) {
+ imethod.return_type.cname = _get_int_type_name_from_meta(m ? m->get_argument_meta(-1) : GodotTypeInfo::METADATA_NONE);
+ } else if (return_info.type == Variant::REAL) {
+ imethod.return_type.cname = _get_float_type_name_from_meta(m ? m->get_argument_meta(-1) : GodotTypeInfo::METADATA_NONE);
+ } else {
+ imethod.return_type.cname = Variant::get_type_name(return_info.type);
+ }
}
for (int i = 0; i < argc; i++) {
@@ -2298,7 +2374,13 @@ void BindingsGenerator::_populate_object_type_interfaces() {
} else if (arginfo.type == Variant::NIL) {
iarg.type.cname = name_cache.type_Variant;
} else {
- iarg.type.cname = Variant::get_type_name(arginfo.type);
+ if (arginfo.type == Variant::INT) {
+ iarg.type.cname = _get_int_type_name_from_meta(m ? m->get_argument_meta(i) : GodotTypeInfo::METADATA_NONE);
+ } else if (arginfo.type == Variant::REAL) {
+ iarg.type.cname = _get_float_type_name_from_meta(m ? m->get_argument_meta(i) : GodotTypeInfo::METADATA_NONE);
+ } else {
+ iarg.type.cname = Variant::get_type_name(arginfo.type);
+ }
}
iarg.name = escape_csharp_keyword(snake_to_camel_case(iarg.name));
@@ -2319,16 +2401,24 @@ void BindingsGenerator::_populate_object_type_interfaces() {
imethod.proxy_name = escape_csharp_keyword(snake_to_pascal_case(imethod.name));
- // Prevent naming the property and its enclosing type from sharing the same name
+ // Prevent the method and its enclosing type from sharing the same name
if (imethod.proxy_name == itype.proxy_name) {
- if (verbose_output) {
- WARN_PRINTS("Name of method `" + imethod.proxy_name + "` is ambiguous with the name of its class `" +
- itype.proxy_name + "`. Renaming method to `" + imethod.proxy_name + "_`");
- }
+ _log("Name of method `%s` is ambiguous with the name of its enclosing class `%s`. Renaming method to `%s_`\n",
+ imethod.proxy_name.utf8().get_data(), itype.proxy_name.utf8().get_data(), imethod.proxy_name.utf8().get_data());
imethod.proxy_name += "_";
}
+ Map<StringName, StringName>::Element *accessor = accessor_methods.find(imethod.cname);
+ if (accessor) {
+ const PropertyInterface *accessor_property = itype.find_property_by_name(accessor->value());
+
+ // We only deprecate an accessor method if it's in the same class as the property. It's easier this way, but also
+ // we don't know if an accessor method in a different class could have other purposes, so better leave those untouched.
+ imethod.is_deprecated = true;
+ imethod.deprecation_message = imethod.proxy_name + " is deprecated. Use the " + accessor_property->proxy_name + " property instead.";
+ }
+
if (itype.class_doc) {
for (int i = 0; i < itype.class_doc->methods.size(); i++) {
if (itype.class_doc->methods[i].name == imethod.name) {
@@ -2556,7 +2646,6 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
// bool
itype = TypeInterface::create_value_type(String("bool"));
-
{
// MonoBoolean <---> bool
itype.c_in = "\t%0 %1_in = (%0)%1;\n";
@@ -2570,45 +2659,73 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.im_type_out = itype.name;
builtin_types.insert(itype.cname, itype);
- // int
- // C interface is the same as that of enums. Remember to apply any
- // changes done here to TypeInterface::postsetup_enum_type as well
- itype = TypeInterface::create_value_type(String("int"));
- itype.c_arg_in = "&%s_in";
+ // Integer types
{
- // The expected types for parameters and return value in ptrcall are 'int64_t' or 'uint64_t'.
- itype.c_in = "\t%0 %1_in = (%0)%1;\n";
- itype.c_out = "\treturn (%0)%1;\n";
- itype.c_type = "int64_t";
+ // C interface for 'uint32_t' is the same as that of enums. Remember to apply
+ // any of the changes done here to 'TypeInterface::postsetup_enum_type' as well.
+#define INSERT_INT_TYPE(m_name, m_c_type_in_out, m_c_type) \
+ { \
+ itype = TypeInterface::create_value_type(String(m_name)); \
+ { \
+ itype.c_in = "\t%0 %1_in = (%0)%1;\n"; \
+ itype.c_out = "\treturn (%0)%1;\n"; \
+ itype.c_type = #m_c_type; \
+ itype.c_arg_in = "&%s_in"; \
+ } \
+ itype.c_type_in = #m_c_type_in_out; \
+ itype.c_type_out = itype.c_type_in; \
+ itype.im_type_in = itype.name; \
+ itype.im_type_out = itype.name; \
+ builtin_types.insert(itype.cname, itype); \
}
- itype.c_type_in = "int32_t";
- itype.c_type_out = itype.c_type_in;
- itype.im_type_in = itype.name;
- itype.im_type_out = itype.name;
- builtin_types.insert(itype.cname, itype);
- // real_t
- itype = TypeInterface();
- itype.name = "float"; // The name is always "float" in Variant, even with REAL_T_IS_DOUBLE.
- itype.cname = itype.name;
-#ifdef REAL_T_IS_DOUBLE
- itype.proxy_name = "double";
-#else
- itype.proxy_name = "float";
-#endif
+ // The expected type for all integers in ptrcall is 'int64_t', so that's what we use for 'c_type'
+
+ INSERT_INT_TYPE("sbyte", int8_t, int64_t);
+ INSERT_INT_TYPE("short", int16_t, int64_t);
+ INSERT_INT_TYPE("int", int32_t, int64_t);
+ INSERT_INT_TYPE("long", int64_t, int64_t);
+ INSERT_INT_TYPE("byte", uint8_t, int64_t);
+ INSERT_INT_TYPE("ushort", uint16_t, int64_t);
+ INSERT_INT_TYPE("uint", uint32_t, int64_t);
+ INSERT_INT_TYPE("ulong", uint64_t, int64_t);
+ }
+
+ // Floating point types
{
- // The expected type for parameters and return value in ptrcall is 'double'.
- itype.c_in = "\t%0 %1_in = (%0)%1;\n";
- itype.c_out = "\treturn (%0)%1;\n";
+ // float
+ itype = TypeInterface();
+ itype.name = "float";
+ itype.cname = itype.name;
+ itype.proxy_name = "float";
+ {
+ // The expected type for 'float' in ptrcall is 'double'
+ itype.c_in = "\t%0 %1_in = (%0)%1;\n";
+ itype.c_out = "\treturn (%0)%1;\n";
+ itype.c_type = "double";
+ itype.c_type_in = "float";
+ itype.c_type_out = "float";
+ itype.c_arg_in = "&%s_in";
+ }
+ itype.cs_type = itype.proxy_name;
+ itype.im_type_in = itype.proxy_name;
+ itype.im_type_out = itype.proxy_name;
+ builtin_types.insert(itype.cname, itype);
+
+ // double
+ itype = TypeInterface();
+ itype.name = "double";
+ itype.cname = itype.name;
+ itype.proxy_name = "double";
itype.c_type = "double";
- itype.c_type_in = "real_t";
- itype.c_type_out = "real_t";
- itype.c_arg_in = "&%s_in";
+ itype.c_type_in = "double";
+ itype.c_type_out = "double";
+ itype.c_arg_in = "&%s";
+ itype.cs_type = itype.proxy_name;
+ itype.im_type_in = itype.proxy_name;
+ itype.im_type_out = itype.proxy_name;
+ builtin_types.insert(itype.cname, itype);
}
- itype.cs_type = itype.proxy_name;
- itype.im_type_in = itype.proxy_name;
- itype.im_type_out = itype.proxy_name;
- builtin_types.insert(itype.cname, itype);
// String
itype = TypeInterface();
@@ -2858,7 +2975,18 @@ void BindingsGenerator::_populate_global_constants() {
}
}
-void BindingsGenerator::initialize() {
+void BindingsGenerator::_log(const char *p_format, ...) {
+
+ if (log_print_enabled) {
+ va_list list;
+
+ va_start(list, p_format);
+ OS::get_singleton()->print("%s", str_format(p_format, list).utf8().get_data());
+ va_end(list);
+ }
+}
+
+void BindingsGenerator::_initialize() {
EditorHelp::generate_doc();
@@ -2881,12 +3009,13 @@ void BindingsGenerator::initialize() {
void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args) {
const int NUM_OPTIONS = 2;
- int options_left = NUM_OPTIONS;
-
String mono_glue_option = "--generate-mono-glue";
String cs_api_option = "--generate-cs-api";
- verbose_output = true;
+ String mono_glue_path;
+ String cs_api_path;
+
+ int options_left = NUM_OPTIONS;
const List<String>::Element *elem = p_cmdline_args.front();
@@ -2895,8 +3024,7 @@ void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args)
const List<String>::Element *path_elem = elem->next();
if (path_elem) {
- if (get_singleton()->generate_glue(path_elem->get()) != OK)
- ERR_PRINTS(mono_glue_option + ": Failed to generate mono glue");
+ mono_glue_path = path_elem->get();
elem = elem->next();
} else {
ERR_PRINTS(mono_glue_option + ": No output directory specified");
@@ -2907,8 +3035,7 @@ void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args)
const List<String>::Element *path_elem = elem->next();
if (path_elem) {
- if (get_singleton()->generate_cs_api(path_elem->get()) != OK)
- ERR_PRINTS(cs_api_option + ": Failed to generate the C# API");
+ cs_api_path = path_elem->get();
elem = elem->next();
} else {
ERR_PRINTS(cs_api_option + ": No output directory specified");
@@ -2920,10 +3047,23 @@ void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args)
elem = elem->next();
}
- verbose_output = false;
+ if (mono_glue_path.length() || cs_api_path.length()) {
+ BindingsGenerator bindings_generator;
+ bindings_generator.set_log_print_enabled(true);
+
+ if (mono_glue_path.length()) {
+ if (bindings_generator.generate_glue(mono_glue_path) != OK)
+ ERR_PRINTS(mono_glue_option + ": Failed to generate mono glue");
+ }
+
+ if (cs_api_path.length()) {
+ if (bindings_generator.generate_cs_api(cs_api_path) != OK)
+ ERR_PRINTS(cs_api_option + ": Failed to generate the C# API");
+ }
- if (options_left != NUM_OPTIONS)
+ // Exit once done
::exit(0);
+ }
}
#endif
diff --git a/modules/mono/editor/bindings_generator.h b/modules/mono/editor/bindings_generator.h
index a073c09910..bdba28c267 100644
--- a/modules/mono/editor/bindings_generator.h
+++ b/modules/mono/editor/bindings_generator.h
@@ -159,17 +159,20 @@ class BindingsGenerator {
const DocData::MethodDoc *method_doc;
+ bool is_deprecated;
+ String deprecation_message;
+
void add_argument(const ArgumentInterface &argument) {
arguments.push_back(argument);
}
MethodInterface() {
- return_type.cname = BindingsGenerator::get_singleton()->name_cache.type_void;
is_vararg = false;
is_virtual = false;
requires_object_call = false;
is_internal = false;
method_doc = NULL;
+ is_deprecated = false;
}
};
@@ -400,8 +403,8 @@ class BindingsGenerator {
}
static void postsetup_enum_type(TypeInterface &r_enum_itype) {
- // C interface is the same as that of 'int'. Remember to apply any
- // changes done here to the 'int' type interface as well
+ // C interface for enums is the same as that of 'uint32_t'. Remember to apply
+ // any of the changes done here to the 'uint32_t' type interface as well.
r_enum_itype.c_arg_in = "&%s_in";
{
@@ -469,7 +472,7 @@ class BindingsGenerator {
}
};
- static bool verbose_output;
+ bool log_print_enabled;
OrderedHashMap<StringName, TypeInterface> obj_types;
@@ -490,7 +493,6 @@ class BindingsGenerator {
struct NameCache {
StringName type_void;
- StringName type_int;
StringName type_Array;
StringName type_Dictionary;
StringName type_Variant;
@@ -501,9 +503,19 @@ class BindingsGenerator {
StringName type_at_GlobalScope;
StringName enum_Error;
+ StringName type_sbyte;
+ StringName type_short;
+ StringName type_int;
+ StringName type_long;
+ StringName type_byte;
+ StringName type_ushort;
+ StringName type_uint;
+ StringName type_ulong;
+ StringName type_float;
+ StringName type_double;
+
NameCache() {
type_void = StaticCString::create("void");
- type_int = StaticCString::create("int");
type_Array = StaticCString::create("Array");
type_Dictionary = StaticCString::create("Dictionary");
type_Variant = StaticCString::create("Variant");
@@ -513,8 +525,20 @@ class BindingsGenerator {
type_String = StaticCString::create("String");
type_at_GlobalScope = StaticCString::create("@GlobalScope");
enum_Error = StaticCString::create("Error");
+
+ type_sbyte = StaticCString::create("sbyte");
+ type_short = StaticCString::create("short");
+ type_int = StaticCString::create("int");
+ type_long = StaticCString::create("long");
+ type_byte = StaticCString::create("byte");
+ type_ushort = StaticCString::create("ushort");
+ type_uint = StaticCString::create("uint");
+ type_ulong = StaticCString::create("ulong");
+ type_float = StaticCString::create("float");
+ type_double = StaticCString::create("double");
}
+ private:
NameCache(const NameCache &);
NameCache &operator=(const NameCache &);
};
@@ -560,6 +584,9 @@ class BindingsGenerator {
const TypeInterface *_get_type_or_null(const TypeReference &p_typeref);
const TypeInterface *_get_type_or_placeholder(const TypeReference &p_typeref);
+ StringName _get_int_type_name_from_meta(GodotTypeInfo::Metadata p_meta);
+ StringName _get_float_type_name_from_meta(GodotTypeInfo::Metadata p_meta);
+
void _default_argument_from_variant(const Variant &p_val, ArgumentInterface &r_iarg);
void _populate_object_type_interfaces();
@@ -578,33 +605,26 @@ class BindingsGenerator {
Error _save_file(const String &p_path, const StringBuilder &p_content);
- BindingsGenerator() {}
-
- BindingsGenerator(const BindingsGenerator &);
- BindingsGenerator &operator=(const BindingsGenerator &);
+ void _log(const char *p_format, ...) _PRINTF_FORMAT_ATTRIBUTE_2_3;
- friend class CSharpLanguage;
- static BindingsGenerator *singleton;
+ void _initialize();
public:
- Error generate_cs_core_project(const String &p_solution_dir, DotNetSolution &r_solution, bool p_verbose_output = true);
- Error generate_cs_editor_project(const String &p_solution_dir, DotNetSolution &r_solution, bool p_verbose_output = true);
- Error generate_cs_api(const String &p_output_dir, bool p_verbose_output = true);
+ Error generate_cs_core_project(const String &p_solution_dir, DotNetSolution &r_solution);
+ Error generate_cs_editor_project(const String &p_solution_dir, DotNetSolution &r_solution);
+ Error generate_cs_api(const String &p_output_dir);
Error generate_glue(const String &p_output_dir);
+ void set_log_print_enabled(bool p_enabled) { log_print_enabled = p_enabled; }
+
static uint32_t get_version();
- void initialize();
+ static void handle_cmdline_args(const List<String> &p_cmdline_args);
- _FORCE_INLINE_ static BindingsGenerator *get_singleton() {
- if (!singleton) {
- singleton = memnew(BindingsGenerator);
- singleton->initialize();
- }
- return singleton;
+ BindingsGenerator() :
+ log_print_enabled(true) {
+ _initialize();
}
-
- static void handle_cmdline_args(const List<String> &p_cmdline_args);
};
#endif
diff --git a/modules/mono/editor/csharp_project.cpp b/modules/mono/editor/csharp_project.cpp
index beeff51bc2..fe79286556 100644
--- a/modules/mono/editor/csharp_project.cpp
+++ b/modules/mono/editor/csharp_project.cpp
@@ -158,7 +158,7 @@ Error generate_scripts_metadata(const String &p_project_path, const String &p_ou
PoolStringArray project_files = GDMonoMarshal::mono_array_to_PoolStringArray(ret);
PoolStringArray::Read r = project_files.read();
- Dictionary old_dict = CSharpLanguage::get_singleton()->get_scripts_metadata();
+ Dictionary old_dict = CSharpLanguage::get_singleton()->get_scripts_metadata_or_nothing();
Dictionary new_dict;
for (int i = 0; i < project_files.size(); i++) {
diff --git a/modules/mono/editor/godotsharp_builds.cpp b/modules/mono/editor/godotsharp_builds.cpp
index 00c780d1b7..de3fd91223 100644
--- a/modules/mono/editor/godotsharp_builds.cpp
+++ b/modules/mono/editor/godotsharp_builds.cpp
@@ -323,10 +323,13 @@ bool GodotSharpBuilds::make_api_assembly(APIAssembly::Type p_api_type) {
String api_sln_file = api_sln_dir.plus_file(API_SOLUTION_NAME ".sln");
if (!DirAccess::exists(api_sln_dir) || !FileAccess::exists(api_sln_file)) {
- BindingsGenerator *gen = BindingsGenerator::get_singleton();
- bool gen_verbose = OS::get_singleton()->is_stdout_verbose();
+ BindingsGenerator bindings_generator;
- Error err = gen->generate_cs_api(api_sln_dir, gen_verbose);
+ if (!OS::get_singleton()->is_stdout_verbose()) {
+ bindings_generator.set_log_print_enabled(false);
+ }
+
+ Error err = bindings_generator.generate_cs_api(api_sln_dir);
if (err != OK) {
show_build_error_dialog("Failed to generate " API_SOLUTION_NAME " solution. Error: " + itos(err));
return false;
diff --git a/modules/mono/glue/Managed/Files/Color.cs b/modules/mono/glue/Managed/Files/Color.cs
index 88fa3323c2..84ff19fc54 100644
--- a/modules/mono/glue/Managed/Files/Color.cs
+++ b/modules/mono/glue/Managed/Files/Color.cs
@@ -168,7 +168,7 @@ namespace Godot
int max = Mathf.Max(color.r8, Mathf.Max(color.g8, color.b8));
int min = Mathf.Min(color.r8, Mathf.Min(color.g8, color.b8));
- float delta = max - min;
+ int delta = max - min;
if (delta == 0)
{
@@ -591,11 +591,11 @@ namespace Godot
public static bool operator <(Color left, Color right)
{
- if (left.r == right.r)
+ if (Mathf.IsEqualApprox(left.r, right.r))
{
- if (left.g == right.g)
+ if (Mathf.IsEqualApprox(left.g, right.g))
{
- if (left.b == right.b)
+ if (Mathf.IsEqualApprox(left.b, right.b))
return left.a < right.a;
return left.b < right.b;
}
@@ -608,11 +608,11 @@ namespace Godot
public static bool operator >(Color left, Color right)
{
- if (left.r == right.r)
+ if (Mathf.IsEqualApprox(left.r, right.r))
{
- if (left.g == right.g)
+ if (Mathf.IsEqualApprox(left.g, right.g))
{
- if (left.b == right.b)
+ if (Mathf.IsEqualApprox(left.b, right.b))
return left.a > right.a;
return left.b > right.b;
}
@@ -635,7 +635,7 @@ namespace Godot
public bool Equals(Color other)
{
- return r == other.r && g == other.g && b == other.b && a == other.a;
+ return Mathf.IsEqualApprox(r, other.r) && Mathf.IsEqualApprox(g, other.g) && Mathf.IsEqualApprox(b, other.b) && Mathf.IsEqualApprox(a, other.a);
}
public override int GetHashCode()
diff --git a/modules/mono/glue/Managed/Files/GD.cs b/modules/mono/glue/Managed/Files/GD.cs
index 5b591646ea..2068099ac6 100644
--- a/modules/mono/glue/Managed/Files/GD.cs
+++ b/modules/mono/glue/Managed/Files/GD.cs
@@ -111,7 +111,7 @@ namespace Godot
godot_icall_GD_printt(Array.ConvertAll(what, x => x.ToString()));
}
- public static double Randf()
+ public static float Randf()
{
return godot_icall_GD_randf();
}
@@ -224,7 +224,7 @@ namespace Godot
internal extern static void godot_icall_GD_printt(object[] what);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static double godot_icall_GD_randf();
+ internal extern static float godot_icall_GD_randf();
[MethodImpl(MethodImplOptions.InternalCall)]
internal extern static uint godot_icall_GD_randi();
@@ -232,6 +232,7 @@ namespace Godot
[MethodImpl(MethodImplOptions.InternalCall)]
internal extern static void godot_icall_GD_randomize();
+
[MethodImpl(MethodImplOptions.InternalCall)]
internal extern static double godot_icall_GD_rand_range(double from, double to);
diff --git a/modules/mono/glue/Managed/Files/Mathf.cs b/modules/mono/glue/Managed/Files/Mathf.cs
index a064278237..947fbb6665 100644
--- a/modules/mono/glue/Managed/Files/Mathf.cs
+++ b/modules/mono/glue/Managed/Files/Mathf.cs
@@ -143,6 +143,15 @@ namespace Godot
return (weight - from) / (to - from);
}
+ public static bool IsEqualApprox(real_t a, real_t b)
+ {
+ real_t tolerance = Epsilon * Abs(a);
+ if (tolerance < Epsilon) {
+ tolerance = Epsilon;
+ }
+ return Abs(a - b) < tolerance;
+ }
+
public static bool IsInf(real_t s)
{
return real_t.IsInfinity(s);
@@ -153,6 +162,11 @@ namespace Godot
return real_t.IsNaN(s);
}
+ public static bool IsZeroApprox(real_t s)
+ {
+ return Abs(s) < Epsilon;
+ }
+
public static real_t Lerp(real_t from, real_t to, real_t weight)
{
return from + (to - from) * weight;
diff --git a/modules/mono/glue/Managed/Files/MathfEx.cs b/modules/mono/glue/Managed/Files/MathfEx.cs
index 414762f7b1..d6eb65b097 100644
--- a/modules/mono/glue/Managed/Files/MathfEx.cs
+++ b/modules/mono/glue/Managed/Files/MathfEx.cs
@@ -36,9 +36,9 @@ namespace Godot
return (int)Math.Round(s);
}
- public static bool IsEqualApprox(real_t a, real_t b, real_t ratio = Mathf.Epsilon)
+ public static bool IsEqualApprox(real_t a, real_t b, real_t tolerance)
{
- return Abs(a - b) < ratio;
+ return Abs(a - b) < tolerance;
}
}
} \ No newline at end of file
diff --git a/modules/mono/glue/Managed/Files/Plane.cs b/modules/mono/glue/Managed/Files/Plane.cs
index f11cd490a9..e16d4315be 100644
--- a/modules/mono/glue/Managed/Files/Plane.cs
+++ b/modules/mono/glue/Managed/Files/Plane.cs
@@ -200,7 +200,7 @@ namespace Godot
public bool Equals(Plane other)
{
- return _normal == other._normal && D == other.D;
+ return _normal == other._normal && Mathf.IsEqualApprox(D, other.D);
}
public override int GetHashCode()
diff --git a/modules/mono/glue/Managed/Files/Quat.cs b/modules/mono/glue/Managed/Files/Quat.cs
index d0c15146a5..0d4349084a 100644
--- a/modules/mono/glue/Managed/Files/Quat.cs
+++ b/modules/mono/glue/Managed/Files/Quat.cs
@@ -358,7 +358,7 @@ namespace Godot
public bool Equals(Quat other)
{
- return x == other.x && y == other.y && z == other.z && w == other.w;
+ return Mathf.IsEqualApprox(x, other.x) && Mathf.IsEqualApprox(y, other.y) && Mathf.IsEqualApprox(z, other.z) && Mathf.IsEqualApprox(w, other.w);
}
public override int GetHashCode()
diff --git a/modules/mono/glue/Managed/Files/Vector2.cs b/modules/mono/glue/Managed/Files/Vector2.cs
index 908162ec45..bb1950e1a8 100644
--- a/modules/mono/glue/Managed/Files/Vector2.cs
+++ b/modules/mono/glue/Managed/Files/Vector2.cs
@@ -52,11 +52,15 @@ namespace Godot
internal void Normalize()
{
- real_t length = x * x + y * y;
+ real_t lengthsq = LengthSquared();
- if (length != 0f)
+ if (lengthsq == 0)
{
- length = Mathf.Sqrt(length);
+ x = y = 0f;
+ }
+ else
+ {
+ real_t length = Mathf.Sqrt(lengthsq);
x /= length;
y /= length;
}
@@ -184,9 +188,9 @@ namespace Godot
public Vector2 Normalized()
{
- var result = this;
- result.Normalize();
- return result;
+ var v = this;
+ v.Normalize();
+ return v;
}
public Vector2 Project(Vector2 onNormal)
@@ -343,7 +347,7 @@ namespace Godot
public static bool operator <(Vector2 left, Vector2 right)
{
- if (left.x.Equals(right.x))
+ if (Mathf.IsEqualApprox(left.x, right.x))
{
return left.y < right.y;
}
@@ -353,7 +357,7 @@ namespace Godot
public static bool operator >(Vector2 left, Vector2 right)
{
- if (left.x.Equals(right.x))
+ if (Mathf.IsEqualApprox(left.x, right.x))
{
return left.y > right.y;
}
@@ -363,7 +367,7 @@ namespace Godot
public static bool operator <=(Vector2 left, Vector2 right)
{
- if (left.x.Equals(right.x))
+ if (Mathf.IsEqualApprox(left.x, right.x))
{
return left.y <= right.y;
}
@@ -373,7 +377,7 @@ namespace Godot
public static bool operator >=(Vector2 left, Vector2 right)
{
- if (left.x.Equals(right.x))
+ if (Mathf.IsEqualApprox(left.x, right.x))
{
return left.y >= right.y;
}
@@ -393,7 +397,7 @@ namespace Godot
public bool Equals(Vector2 other)
{
- return x == other.x && y == other.y;
+ return Mathf.IsEqualApprox(x, other.x) && Mathf.IsEqualApprox(y, other.y);
}
public override int GetHashCode()
diff --git a/modules/mono/glue/Managed/Files/Vector3.cs b/modules/mono/glue/Managed/Files/Vector3.cs
index 0c96d346a9..283cb6341a 100644
--- a/modules/mono/glue/Managed/Files/Vector3.cs
+++ b/modules/mono/glue/Managed/Files/Vector3.cs
@@ -65,14 +65,15 @@ namespace Godot
internal void Normalize()
{
- real_t length = Length();
+ real_t lengthsq = LengthSquared();
- if (length == 0f)
+ if (lengthsq == 0)
{
x = y = z = 0f;
}
else
{
+ real_t length = Mathf.Sqrt(lengthsq);
x /= length;
y /= length;
z /= length;
@@ -397,9 +398,9 @@ namespace Godot
public static bool operator <(Vector3 left, Vector3 right)
{
- if (left.x == right.x)
+ if (Mathf.IsEqualApprox(left.x, right.x))
{
- if (left.y == right.y)
+ if (Mathf.IsEqualApprox(left.y, right.y))
return left.z < right.z;
return left.y < right.y;
}
@@ -409,9 +410,9 @@ namespace Godot
public static bool operator >(Vector3 left, Vector3 right)
{
- if (left.x == right.x)
+ if (Mathf.IsEqualApprox(left.x, right.x))
{
- if (left.y == right.y)
+ if (Mathf.IsEqualApprox(left.y, right.y))
return left.z > right.z;
return left.y > right.y;
}
@@ -421,9 +422,9 @@ namespace Godot
public static bool operator <=(Vector3 left, Vector3 right)
{
- if (left.x == right.x)
+ if (Mathf.IsEqualApprox(left.x, right.x))
{
- if (left.y == right.y)
+ if (Mathf.IsEqualApprox(left.y, right.y))
return left.z <= right.z;
return left.y < right.y;
}
@@ -433,9 +434,9 @@ namespace Godot
public static bool operator >=(Vector3 left, Vector3 right)
{
- if (left.x == right.x)
+ if (Mathf.IsEqualApprox(left.x, right.x))
{
- if (left.y == right.y)
+ if (Mathf.IsEqualApprox(left.y, right.y))
return left.z >= right.z;
return left.y > right.y;
}
@@ -455,7 +456,7 @@ namespace Godot
public bool Equals(Vector3 other)
{
- return x == other.x && y == other.y && z == other.z;
+ return Mathf.IsEqualApprox(x, other.x) && Mathf.IsEqualApprox(y, other.y) && Mathf.IsEqualApprox(z, other.z);
}
public override int GetHashCode()
diff --git a/modules/mono/glue/gd_glue.cpp b/modules/mono/glue/gd_glue.cpp
index d756131ac9..7c30092855 100644
--- a/modules/mono/glue/gd_glue.cpp
+++ b/modules/mono/glue/gd_glue.cpp
@@ -115,7 +115,7 @@ void godot_icall_GD_printt(MonoArray *p_what) {
print_line(str);
}
-double godot_icall_GD_randf() {
+float godot_icall_GD_randf() {
return Math::randf();
}
diff --git a/modules/mono/glue/gd_glue.h b/modules/mono/glue/gd_glue.h
index 910979aae3..d4e20e2887 100644
--- a/modules/mono/glue/gd_glue.h
+++ b/modules/mono/glue/gd_glue.h
@@ -53,7 +53,7 @@ void godot_icall_GD_prints(MonoArray *p_what);
void godot_icall_GD_printt(MonoArray *p_what);
-double godot_icall_GD_randf();
+float godot_icall_GD_randf();
uint32_t godot_icall_GD_randi();
diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp
index bfb6c13224..19e49d29f9 100644
--- a/modules/mono/mono_gd/gd_mono.cpp
+++ b/modules/mono/mono_gd/gd_mono.cpp
@@ -658,8 +658,6 @@ bool GDMono::_load_project_assembly() {
if (success) {
mono_assembly_set_main(project_assembly->get_assembly());
-
- CSharpLanguage::get_singleton()->project_assembly_loaded();
} else {
if (OS::get_singleton()->is_stdout_verbose())
print_error("Mono: Failed to load project assembly");
@@ -866,7 +864,7 @@ Error GDMono::reload_scripts_domain() {
}
}
- CSharpLanguage::get_singleton()->_uninitialize_script_bindings();
+ CSharpLanguage::get_singleton()->_on_scripts_domain_unloaded();
Error err = _load_scripts_domain();
if (err != OK) {
diff --git a/modules/mono/mono_gd/gd_mono_log.cpp b/modules/mono/mono_gd/gd_mono_log.cpp
index 3191cdbd53..a6e04e561d 100644
--- a/modules/mono/mono_gd/gd_mono_log.cpp
+++ b/modules/mono/mono_gd/gd_mono_log.cpp
@@ -37,6 +37,7 @@
#include "core/os/os.h"
#include "../godotsharp_dirs.h"
+#include "../utils/string_utils.h"
static int log_level_get_id(const char *p_log_level) {
@@ -125,27 +126,6 @@ void GDMonoLog::_delete_old_log_files(const String &p_logs_dir) {
da->list_dir_end();
}
-static String format(const char *p_fmt, ...) {
- va_list args;
-
- va_start(args, p_fmt);
- int len = vsnprintf(NULL, 0, p_fmt, args);
- va_end(args);
-
- len += 1; // for the trailing '/0'
-
- char *buffer(memnew_arr(char, len));
-
- va_start(args, p_fmt);
- vsnprintf(buffer, len, p_fmt, args);
- va_end(args);
-
- String res(buffer);
- memdelete_arr(buffer);
-
- return res;
-}
-
void GDMonoLog::initialize() {
CharString log_level = OS::get_singleton()->get_environment("GODOT_MONO_LOG_LEVEL").utf8();
@@ -172,7 +152,7 @@ void GDMonoLog::initialize() {
OS::Time time_now = OS::get_singleton()->get_time();
int pid = OS::get_singleton()->get_process_id();
- String log_file_name = format("%d-%02d-%02d %02d:%02d:%02d (%d).txt",
+ String log_file_name = str_format("%d_%02d_%02d %02d.%02d.%02d (%d).txt",
date_now.year, date_now.month, date_now.day,
time_now.hour, time_now.min, time_now.sec, pid);
diff --git a/modules/mono/utils/string_utils.cpp b/modules/mono/utils/string_utils.cpp
index c390f8b9c2..0ef66577fe 100644
--- a/modules/mono/utils/string_utils.cpp
+++ b/modules/mono/utils/string_utils.cpp
@@ -32,6 +32,8 @@
#include "core/os/file_access.h"
+#include <stdio.h>
+
namespace {
int sfind(const String &p_text, int p_from) {
@@ -184,3 +186,50 @@ Error read_all_file_utf8(const String &p_path, String &r_content) {
r_content = source;
return OK;
}
+
+// TODO: Move to variadic templates once we upgrade to C++11
+
+String str_format(const char *p_format, ...) {
+ va_list list;
+
+ va_start(list, p_format);
+ String res = str_format(p_format, list);
+ va_end(list);
+
+ return res;
+}
+// va_copy was defined in the C99, but not in C++ standards before C++11.
+// When you compile C++ without --std=c++<XX> option, compilers still define
+// va_copy, otherwise you have to use the internal version (__va_copy).
+#if !defined(va_copy)
+#if defined(__GNUC__)
+#define va_copy(d, s) __va_copy((d), (s))
+#else
+#define va_copy(d, s) ((d) = (s))
+#endif
+#endif
+
+#if defined(MINGW_ENABLED) || defined(_MSC_VER)
+#define vsnprintf vsnprintf_s
+#endif
+
+String str_format(const char *p_format, va_list p_list) {
+ va_list list;
+
+ va_copy(list, p_list);
+ int len = vsnprintf(NULL, 0, p_format, list);
+ va_end(list);
+
+ len += 1; // for the trailing '/0'
+
+ char *buffer(memnew_arr(char, len));
+
+ va_copy(list, p_list);
+ vsnprintf(buffer, len, p_format, list);
+ va_end(list);
+
+ String res(buffer);
+ memdelete_arr(buffer);
+
+ return res;
+}
diff --git a/modules/mono/utils/string_utils.h b/modules/mono/utils/string_utils.h
index 61765ccfd8..565b9bb644 100644
--- a/modules/mono/utils/string_utils.h
+++ b/modules/mono/utils/string_utils.h
@@ -34,6 +34,8 @@
#include "core/ustring.h"
#include "core/variant.h"
+#include <stdarg.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());
#ifdef TOOLS_ENABLED
@@ -44,4 +46,15 @@ String escape_csharp_keyword(const String &p_name);
Error read_all_file_utf8(const String &p_path, String &r_content);
+#if defined(__GNUC__)
+#define _PRINTF_FORMAT_ATTRIBUTE_1_0 __attribute__((format(printf, 1, 0)))
+#define _PRINTF_FORMAT_ATTRIBUTE_1_2 __attribute__((format(printf, 1, 2)))
+#else
+#define _PRINTF_FORMAT_ATTRIBUTE_1_0
+#define _PRINTF_FORMAT_ATTRIBUTE_1_2
+#endif
+
+String str_format(const char *p_format, ...) _PRINTF_FORMAT_ATTRIBUTE_1_2;
+String str_format(const char *p_format, va_list p_list) _PRINTF_FORMAT_ATTRIBUTE_1_0;
+
#endif // STRING_FORMAT_H
diff --git a/modules/opus/SCsub b/modules/opus/SCsub
index b72144c679..a1325734e2 100644
--- a/modules/opus/SCsub
+++ b/modules/opus/SCsub
@@ -139,7 +139,7 @@ if env['builtin_opus']:
opus_sources_silk = []
if env["platform"] in ["android", "iphone", "javascript"]:
- env_opus.Append(CFLAGS=["-DFIXED_POINT"])
+ env_opus.Append(CPPFLAGS=["-DFIXED_POINT"])
opus_sources_silk = [
"silk/fixed/LTP_analysis_filter_FIX.c",
"silk/fixed/LTP_scale_ctrl_FIX.c",
@@ -208,7 +208,7 @@ if env['builtin_opus']:
if env['builtin_libogg']:
env_opus.Append(CPPPATH=["#thirdparty/libogg"])
- env_opus.Append(CFLAGS=["-DHAVE_CONFIG_H"])
+ env_opus.Append(CPPFLAGS=["-DHAVE_CONFIG_H"])
thirdparty_include_paths = [
"",
@@ -222,14 +222,14 @@ if env['builtin_opus']:
if env["platform"] == "android":
if ("android_arch" in env and env["android_arch"] in ["armv6", "armv7"]):
- env_opus.Append(CFLAGS=["-DOPUS_ARM_OPT"])
+ env_opus.Append(CPPFLAGS=["-DOPUS_ARM_OPT"])
elif ("android_arch" in env and env["android_arch"] == "arm64v8"):
- env_opus.Append(CFLAGS=["-DOPUS_ARM64_OPT"])
+ env_opus.Append(CPPFLAGS=["-DOPUS_ARM64_OPT"])
elif env["platform"] == "iphone":
if ("arch" in env and env["arch"] == "arm"):
- env_opus.Append(CFLAGS=["-DOPUS_ARM_OPT"])
+ env_opus.Append(CPPFLAGS=["-DOPUS_ARM_OPT"])
elif ("arch" in env and env["arch"] == "arm64"):
- env_opus.Append(CFLAGS=["-DOPUS_ARM64_OPT"])
+ env_opus.Append(CPPFLAGS=["-DOPUS_ARM64_OPT"])
env_thirdparty = env_opus.Clone()
env_thirdparty.disable_warnings()
diff --git a/modules/svg/SCsub b/modules/svg/SCsub
index 22f0b1e3eb..66d9b3bf75 100644
--- a/modules/svg/SCsub
+++ b/modules/svg/SCsub
@@ -16,7 +16,7 @@ env_svg.Append(CPPPATH=[thirdparty_dir])
# FIXME: Needed in editor/editor_themes.cpp for now, but ideally there
# shouldn't be a dependency on modules/ and its own 3rd party deps.
env.Append(CPPPATH=[thirdparty_dir])
-env.Append(CCFLAGS=["-DSVG_ENABLED"])
+env.Append(CPPFLAGS=["-DSVG_ENABLED"])
env_thirdparty = env_svg.Clone()
env_thirdparty.disable_warnings()
diff --git a/modules/tga/image_loader_tga.cpp b/modules/tga/image_loader_tga.cpp
index 419229677b..a3c0f5ded7 100644
--- a/modules/tga/image_loader_tga.cpp
+++ b/modules/tga/image_loader_tga.cpp
@@ -148,9 +148,11 @@ Error ImageLoaderTGA::convert_to_image(Ref<Image> p_image, const uint8_t *p_buff
uint8_t a = 0xff;
if (p_header.color_map_depth == 24) {
- r = (p_palette[(index * 3) + 0]);
+ // Due to low-high byte order, the color table must be
+ // read in the same order as image data (little endian)
+ r = (p_palette[(index * 3) + 2]);
g = (p_palette[(index * 3) + 1]);
- b = (p_palette[(index * 3) + 2]);
+ b = (p_palette[(index * 3) + 0]);
} else {
return ERR_INVALID_DATA;
}
diff --git a/modules/theora/SCsub b/modules/theora/SCsub
index 98c4274a7e..f98db2359c 100644
--- a/modules/theora/SCsub
+++ b/modules/theora/SCsub
@@ -66,7 +66,7 @@ if env['builtin_libtheora']:
thirdparty_sources += thirdparty_sources_x86_vc
if (env["x86_libtheora_opt_gcc"] or env["x86_libtheora_opt_vc"]):
- env_theora.Append(CCFLAGS=["-DOC_X86_ASM"])
+ env_theora.Append(CPPFLAGS=["-DOC_X86_ASM"])
thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
diff --git a/modules/theora/video_stream_theora.cpp b/modules/theora/video_stream_theora.cpp
index 14c5ddd7f2..8db0799b47 100644
--- a/modules/theora/video_stream_theora.cpp
+++ b/modules/theora/video_stream_theora.cpp
@@ -365,7 +365,7 @@ void VideoStreamPlaybackTheora::set_file(const String &p_file) {
float VideoStreamPlaybackTheora::get_time() const {
- return time - AudioServer::get_singleton()->get_output_delay() - delay_compensation; //-((get_total())/(float)vi.rate);
+ return time - AudioServer::get_singleton()->get_output_latency() - delay_compensation; //-((get_total())/(float)vi.rate);
};
Ref<Texture> VideoStreamPlaybackTheora::get_texture() {
diff --git a/modules/vhacd/SCsub b/modules/vhacd/SCsub
index 11cd5f4743..fdd3ddc1e6 100644
--- a/modules/vhacd/SCsub
+++ b/modules/vhacd/SCsub
@@ -29,7 +29,7 @@ env_vhacd.Append(CPPFLAGS=["-DGODOT_ENET"])
# upstream uses c++11
if not env.msvc:
- env_vhacd.Append(CCFLAGS="-std=c++11")
+ env_vhacd.Append(CXXFLAGS="-std=c++11")
env_thirdparty = env_vhacd.Clone()
env_thirdparty.disable_warnings()
diff --git a/modules/webm/SCsub b/modules/webm/SCsub
index cb35b926ab..dcc9a45044 100644
--- a/modules/webm/SCsub
+++ b/modules/webm/SCsub
@@ -19,7 +19,7 @@ env_webm.Append(CPPPATH=[thirdparty_dir, thirdparty_dir + "libwebm/"])
# upstream uses c++11
if (not env_webm.msvc):
- env_webm.Append(CCFLAGS="-std=c++11")
+ env_webm.Append(CXXFLAGS="-std=c++11")
# also requires libogg, libvorbis and libopus
if env['builtin_libogg']:
diff --git a/modules/webm/libvpx/SCsub b/modules/webm/libvpx/SCsub
index 2639d20620..5bf4ea3464 100644
--- a/modules/webm/libvpx/SCsub
+++ b/modules/webm/libvpx/SCsub
@@ -323,7 +323,7 @@ if webm_cpu_x86:
elif cpu_bits == '64':
env_libvpx["ASCPU"] = 'X86_64'
- env_libvpx.Append(CCFLAGS=['-DWEBM_X86ASM'])
+ env_libvpx.Append(CPPFLAGS=['-DWEBM_X86ASM'])
webm_simd_optimizations = True
@@ -337,7 +337,7 @@ if webm_cpu_arm:
env_libvpx["ASFLAGS"] = ''
env_libvpx["ASCOM"] = '$AS $ASFLAGS -o $TARGET $SOURCES'
- env_libvpx.Append(CCFLAGS=['-DWEBM_ARMASM'])
+ env_libvpx.Append(CPPFLAGS=['-DWEBM_ARMASM'])
webm_simd_optimizations = True
diff --git a/modules/webm/video_stream_webm.cpp b/modules/webm/video_stream_webm.cpp
index 06f9e39dc7..f2497eeec1 100644
--- a/modules/webm/video_stream_webm.cpp
+++ b/modules/webm/video_stream_webm.cpp
@@ -375,7 +375,7 @@ int VideoStreamPlaybackWebm::get_mix_rate() const {
inline bool VideoStreamPlaybackWebm::has_enough_video_frames() const {
if (video_frames_pos > 0) {
- const double audio_delay = AudioServer::get_singleton()->get_output_delay();
+ const double audio_delay = AudioServer::get_singleton()->get_output_latency();
const double video_time = video_frames[video_frames_pos - 1]->time;
return video_time >= time + audio_delay + delay_compensation;
}
@@ -383,7 +383,7 @@ inline bool VideoStreamPlaybackWebm::has_enough_video_frames() const {
}
bool VideoStreamPlaybackWebm::should_process(WebMFrame &video_frame) {
- const double audio_delay = AudioServer::get_singleton()->get_output_delay();
+ const double audio_delay = AudioServer::get_singleton()->get_output_latency();
return video_frame.time >= time + audio_delay + delay_compensation;
}
diff --git a/modules/websocket/SCsub b/modules/websocket/SCsub
index 0345e533bc..12b4969cf7 100644
--- a/modules/websocket/SCsub
+++ b/modules/websocket/SCsub
@@ -88,7 +88,7 @@ if env['builtin_libwebsockets'] and not env["platform"] == "javascript": # alrea
env_lws.Append(CPPPATH=[helper_dir])
if env["platform"] == "uwp":
- env_lws.Append(CCFLAGS=["/DLWS_MINGW_SUPPORT"])
+ env_lws.Append(CPPFLAGS=["/DLWS_MINGW_SUPPORT"])
env_thirdparty = env_lws.Clone()
env_thirdparty.disable_warnings()
diff --git a/modules/xatlas_unwrap/SCsub b/modules/xatlas_unwrap/SCsub
index ad364d5aaf..7a40945f27 100644
--- a/modules/xatlas_unwrap/SCsub
+++ b/modules/xatlas_unwrap/SCsub
@@ -1,7 +1,5 @@
#!/usr/bin/env python
-import platform
-
Import('env')
Import('env_modules')
@@ -21,23 +19,6 @@ if env['builtin_xatlas']:
if (not env.msvc):
env_xatlas_unwrap.Append(CXXFLAGS="-std=c++11")
- if env["platform"] == 'x11':
- # if not specifically one of the *BSD, then use LINUX as default
- if platform.system() == "FreeBSD":
- env_xatlas_unwrap.Append(CCFLAGS=["-DNV_OS_FREEBSD", "-DPOSH_COMPILER_GCC"])
- elif platform.system() == "OpenBSD":
- env_xatlas_unwrap.Append(CCFLAGS=["-DNV_OS_OPENBSD", "-DPOSH_COMPILER_GCC"])
- else:
- env_xatlas_unwrap.Append(CCFLAGS=["-DNV_OS_LINUX", "-DPOSH_COMPILER_GCC"])
- elif env["platform"] == 'osx':
- env_xatlas_unwrap.Append(CCFLAGS=["-DNV_OS_DARWIN", "-DPOSH_COMPILER_GCC"])
- elif env["platform"] == 'windows':
- if env.msvc:
- env_xatlas_unwrap.Append(CCFLAGS=["-DNV_OS_WIN32", "-DNV_CC_MSVC", "-DPOSH_COMPILER_MSVC" ])
- else:
- env_xatlas_unwrap.Append(CCFLAGS=["-DNV_OS_MINGW", "-DNV_CC_GNUC", "-DPOSH_COMPILER_GCC", "-U__STRICT_ANSI__"])
- env.Append(LIBS=["dbghelp"])
-
env_thirdparty = env_xatlas_unwrap.Clone()
env_thirdparty.disable_warnings()
env_thirdparty.add_source_files(env.modules_sources, thirdparty_sources)